diff options
Diffstat (limited to 'common/registrar/registrar.go')
-rw-r--r-- | common/registrar/registrar.go | 436 |
1 files changed, 0 insertions, 436 deletions
diff --git a/common/registrar/registrar.go b/common/registrar/registrar.go deleted file mode 100644 index 0606f6985..000000000 --- a/common/registrar/registrar.go +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. - -package registrar - -import ( - "encoding/binary" - "fmt" - "math/big" - "regexp" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/logger/glog" -) - -/* -Registrar implements the Ethereum name registrar services mapping -- arbitrary strings to ethereum addresses -- hashes to hashes -- hashes to arbitrary strings -(likely will provide lookup service for all three) - -The Registrar is used by -* the roundtripper transport implementation of -url schemes to resolve domain names and services that register these names -* contract info retrieval (NatSpec). - -The Registrar uses 3 contracts on the blockchain: -* GlobalRegistrar: Name (string) -> Address (Owner) -* HashReg : Key Hash (hash of domain name or contract code) -> Content Hash -* UrlHint : Content Hash -> Url Hint - -These contracts are (currently) not included in the genesis block. -Each Set<X> needs to be called once on each blockchain/network once. - -Contract addresses need to be set the first time any Registrar method is called -in a client session. -This is done for frontier by default, otherwise the caller needs to make sure -the relevant environment initialised the desired contracts -*/ -var ( - // GlobalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b" // olympic - GlobalRegistrarAddr = "0x33990122638b9132ca29c723bdf037f1a891a70c" // frontier - HashRegAddr = "0x23bf622b5a65f6060d855fca401133ded3520620" // frontier - UrlHintAddr = "0x73ed5ef6c010727dfd2671dbb70faac19ec18626" // frontier - - zero = regexp.MustCompile("^(0x)?0*$") -) - -const ( - trueHex = "0000000000000000000000000000000000000000000000000000000000000001" - falseHex = "0000000000000000000000000000000000000000000000000000000000000000" -) - -func abiSignature(s string) string { - return common.ToHex(crypto.Keccak256([]byte(s))[:4]) -} - -var ( - HashRegName = "HashReg" - UrlHintName = "UrlHint" - - registerContentHashAbi = abiSignature("register(uint256,uint256)") - registerUrlAbi = abiSignature("register(uint256,uint8,uint256)") - setOwnerAbi = abiSignature("setowner()") - reserveAbi = abiSignature("reserve(bytes32)") - resolveAbi = abiSignature("addr(bytes32)") - registerAbi = abiSignature("setAddress(bytes32,address,bool)") - addressAbiPrefix = falseHex[:24] -) - -// Registrar's backend is defined as an interface (implemented by xeth, but could be remote) -type Backend interface { - StorageAt(string, string) string - Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) - Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, string, error) -} - -// TODO Registrar should also just implement The Resolver and Registry interfaces -// Simplify for now. -type VersionedRegistrar interface { - Resolver(*big.Int) *Registrar - Registry() *Registrar -} - -type Registrar struct { - backend Backend -} - -func New(b Backend) (res *Registrar) { - res = &Registrar{b} - return -} - -func (self *Registrar) SetGlobalRegistrar(namereg string, addr common.Address) (txhash string, err error) { - if namereg != "" { - GlobalRegistrarAddr = namereg - return - } - if zero.MatchString(GlobalRegistrarAddr) { - if (addr == common.Address{}) { - err = fmt.Errorf("GlobalRegistrar address not found and sender for creation not given") - return - } else { - txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "800000", "", GlobalRegistrarCode) - if err != nil { - err = fmt.Errorf("GlobalRegistrar address not found and sender for creation failed: %v", err) - return - } - } - } - return -} - -func (self *Registrar) SetHashReg(hashreg string, addr common.Address) (txhash string, err error) { - if hashreg != "" { - HashRegAddr = hashreg - } else { - if !zero.MatchString(HashRegAddr) { - return - } - nameHex, extra := encodeName(HashRegName, 2) - hashRegAbi := resolveAbi + nameHex + extra - glog.V(logger.Detail).Infof("\ncall HashRegAddr %v with %v\n", GlobalRegistrarAddr, hashRegAbi) - var res string - res, _, err = self.backend.Call("", GlobalRegistrarAddr, "", "", "", hashRegAbi) - if len(res) >= 40 { - HashRegAddr = "0x" + res[len(res)-40:len(res)] - } - if err != nil || zero.MatchString(HashRegAddr) { - if (addr == common.Address{}) { - err = fmt.Errorf("HashReg address not found and sender for creation not given") - return - } - - txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "", "", HashRegCode) - if err != nil { - err = fmt.Errorf("HashReg address not found and sender for creation failed: %v", err) - } - glog.V(logger.Detail).Infof("created HashRegAddr @ txhash %v\n", txhash) - } else { - glog.V(logger.Detail).Infof("HashRegAddr found at @ %v\n", HashRegAddr) - return - } - } - - return -} - -func (self *Registrar) SetUrlHint(urlhint string, addr common.Address) (txhash string, err error) { - if urlhint != "" { - UrlHintAddr = urlhint - } else { - if !zero.MatchString(UrlHintAddr) { - return - } - nameHex, extra := encodeName(UrlHintName, 2) - urlHintAbi := resolveAbi + nameHex + extra - glog.V(logger.Detail).Infof("UrlHint address query data: %s to %s", urlHintAbi, GlobalRegistrarAddr) - var res string - res, _, err = self.backend.Call("", GlobalRegistrarAddr, "", "", "", urlHintAbi) - if len(res) >= 40 { - UrlHintAddr = "0x" + res[len(res)-40:len(res)] - } - if err != nil || zero.MatchString(UrlHintAddr) { - if (addr == common.Address{}) { - err = fmt.Errorf("UrlHint address not found and sender for creation not given") - return - } - txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "210000", "", UrlHintCode) - if err != nil { - err = fmt.Errorf("UrlHint address not found and sender for creation failed: %v", err) - } - glog.V(logger.Detail).Infof("created UrlHint @ txhash %v\n", txhash) - } else { - glog.V(logger.Detail).Infof("UrlHint found @ %v\n", HashRegAddr) - return - } - } - - return -} - -// ReserveName(from, name) reserves name for the sender address in the globalRegistrar -// the tx needs to be mined to take effect -func (self *Registrar) ReserveName(address common.Address, name string) (txh string, err error) { - if zero.MatchString(GlobalRegistrarAddr) { - return "", fmt.Errorf("GlobalRegistrar address is not set") - } - nameHex, extra := encodeName(name, 2) - abi := reserveAbi + nameHex + extra - glog.V(logger.Detail).Infof("Reserve data: %s", abi) - return self.backend.Transact( - address.Hex(), - GlobalRegistrarAddr, - "", "", "", "", - abi, - ) -} - -// SetAddressToName(from, name, addr) will set the Address to address for name -// in the globalRegistrar using from as the sender of the transaction -// the tx needs to be mined to take effect -func (self *Registrar) SetAddressToName(from common.Address, name string, address common.Address) (txh string, err error) { - if zero.MatchString(GlobalRegistrarAddr) { - return "", fmt.Errorf("GlobalRegistrar address is not set") - } - - nameHex, extra := encodeName(name, 6) - addrHex := encodeAddress(address) - - abi := registerAbi + nameHex + addrHex + trueHex + extra - glog.V(logger.Detail).Infof("SetAddressToName data: %s to %s ", abi, GlobalRegistrarAddr) - - return self.backend.Transact( - from.Hex(), - GlobalRegistrarAddr, - "", "", "", "", - abi, - ) -} - -// NameToAddr(from, name) queries the registrar for the address on name -func (self *Registrar) NameToAddr(from common.Address, name string) (address common.Address, err error) { - if zero.MatchString(GlobalRegistrarAddr) { - return address, fmt.Errorf("GlobalRegistrar address is not set") - } - - nameHex, extra := encodeName(name, 2) - abi := resolveAbi + nameHex + extra - glog.V(logger.Detail).Infof("NameToAddr data: %s", abi) - res, _, err := self.backend.Call( - from.Hex(), - GlobalRegistrarAddr, - "", "", "", - abi, - ) - if err != nil { - return - } - address = common.HexToAddress(res) - return -} - -// called as first step in the registration process on HashReg -func (self *Registrar) SetOwner(address common.Address) (txh string, err error) { - if zero.MatchString(HashRegAddr) { - return "", fmt.Errorf("HashReg address is not set") - } - return self.backend.Transact( - address.Hex(), - HashRegAddr, - "", "", "", "", - setOwnerAbi, - ) -} - -// registers some content hash to a key/code hash -// e.g., the contract Info combined Json Doc's ContentHash -// to CodeHash of a contract or hash of a domain -func (self *Registrar) SetHashToHash(address common.Address, codehash, dochash common.Hash) (txh string, err error) { - if zero.MatchString(HashRegAddr) { - return "", fmt.Errorf("HashReg address is not set") - } - - _, err = self.SetOwner(address) - if err != nil { - return - } - codehex := common.Bytes2Hex(codehash[:]) - dochex := common.Bytes2Hex(dochash[:]) - - data := registerContentHashAbi + codehex + dochex - glog.V(logger.Detail).Infof("SetHashToHash data: %s sent to %v\n", data, HashRegAddr) - return self.backend.Transact( - address.Hex(), - HashRegAddr, - "", "", "", "", - data, - ) -} - -// SetUrlToHash(from, hash, url) registers a url to a content hash so that the content can be fetched -// address is used as sender for the transaction and will be the owner of a new -// registry entry on first time use -// FIXME: silently doing nothing if sender is not the owner -// note that with content addressed storage, this step is no longer necessary -func (self *Registrar) SetUrlToHash(address common.Address, hash common.Hash, url string) (txh string, err error) { - if zero.MatchString(UrlHintAddr) { - return "", fmt.Errorf("UrlHint address is not set") - } - - hashHex := common.Bytes2Hex(hash[:]) - var urlHex string - urlb := []byte(url) - var cnt byte - n := len(urlb) - - for n > 0 { - if n > 32 { - n = 32 - } - urlHex = common.Bytes2Hex(urlb[:n]) - urlb = urlb[n:] - n = len(urlb) - bcnt := make([]byte, 32) - bcnt[31] = cnt - data := registerUrlAbi + - hashHex + - common.Bytes2Hex(bcnt) + - common.Bytes2Hex(common.Hex2BytesFixed(urlHex, 32)) - txh, err = self.backend.Transact( - address.Hex(), - UrlHintAddr, - "", "", "", "", - data, - ) - if err != nil { - return - } - cnt++ - } - return -} - -// HashToHash(key) resolves contenthash for key (a hash) using HashReg -// resolution is costless non-transactional -// implemented as direct retrieval from db -func (self *Registrar) HashToHash(khash common.Hash) (chash common.Hash, err error) { - if zero.MatchString(HashRegAddr) { - return common.Hash{}, fmt.Errorf("HashReg address is not set") - } - - // look up in hashReg - at := HashRegAddr[2:] - key := storageAddress(storageMapping(storageIdx2Addr(1), khash[:])) - hash := self.backend.StorageAt(at, key) - - if hash == "0x0" || len(hash) < 3 || (hash == common.Hash{}.Hex()) { - err = fmt.Errorf("HashToHash: content hash not found for '%v'", khash.Hex()) - return - } - copy(chash[:], common.Hex2BytesFixed(hash[2:], 32)) - return -} - -// HashToUrl(contenthash) resolves the url for contenthash using UrlHint -// resolution is costless non-transactional -// implemented as direct retrieval from db -// if we use content addressed storage, this step is no longer necessary -func (self *Registrar) HashToUrl(chash common.Hash) (uri string, err error) { - if zero.MatchString(UrlHintAddr) { - return "", fmt.Errorf("UrlHint address is not set") - } - // look up in URL reg - var str string = " " - var idx uint32 - for len(str) > 0 { - mapaddr := storageMapping(storageIdx2Addr(1), chash[:]) - key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(idx))) - hex := self.backend.StorageAt(UrlHintAddr[2:], key) - str = string(common.Hex2Bytes(hex[2:])) - l := 0 - for (l < len(str)) && (str[l] == 0) { - l++ - } - - str = str[l:] - uri = uri + str - idx++ - } - - if len(uri) == 0 { - err = fmt.Errorf("HashToUrl: URL hint not found for '%v'", chash.Hex()) - } - return -} - -func storageIdx2Addr(varidx uint32) []byte { - data := make([]byte, 32) - binary.BigEndian.PutUint32(data[28:32], varidx) - return data -} - -func storageMapping(addr, key []byte) []byte { - data := make([]byte, 64) - copy(data[0:32], key[0:32]) - copy(data[32:64], addr[0:32]) - sha := crypto.Keccak256(data) - return sha -} - -func storageFixedArray(addr, idx []byte) []byte { - var carry byte - for i := 31; i >= 0; i-- { - var b byte = addr[i] + idx[i] + carry - if b < addr[i] { - carry = 1 - } else { - carry = 0 - } - addr[i] = b - } - return addr -} - -func storageAddress(addr []byte) string { - return common.ToHex(addr) -} - -func encodeAddress(address common.Address) string { - return addressAbiPrefix + address.Hex()[2:] -} - -func encodeName(name string, index uint8) (string, string) { - extra := common.Bytes2Hex([]byte(name)) - if len(name) > 32 { - return fmt.Sprintf("%064x", index), extra - } - return extra + falseHex[len(extra):], "" -} |