registrar.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // go-ethereum is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package registrar
  17. import (
  18. "encoding/binary"
  19. "fmt"
  20. "math/big"
  21. "regexp"
  22. "github.com/ethereum/go-ethereum/common"
  23. "github.com/ethereum/go-ethereum/crypto"
  24. "github.com/ethereum/go-ethereum/logger"
  25. "github.com/ethereum/go-ethereum/logger/glog"
  26. )
  27. /*
  28. Registrar implements the Ethereum name registrar services mapping
  29. - arbitrary strings to ethereum addresses
  30. - hashes to hashes
  31. - hashes to arbitrary strings
  32. (likely will provide lookup service for all three)
  33. The Registrar is used by
  34. * the roundtripper transport implementation of
  35. url schemes to resolve domain names and services that register these names
  36. * contract info retrieval (NatSpec).
  37. The Registrar uses 3 contracts on the blockchain:
  38. * GlobalRegistrar: Name (string) -> Address (Owner)
  39. * HashReg : Key Hash (hash of domain name or contract code) -> Content Hash
  40. * UrlHint : Content Hash -> Url Hint
  41. These contracts are (currently) not included in the genesis block.
  42. Each Set<X> needs to be called once on each blockchain/network once.
  43. Contract addresses need to be set (HashReg and UrlHint retrieved from the global
  44. registrar the first time any Registrar method is called in a client session
  45. So the caller needs to make sure the relevant environment initialised the desired
  46. contracts
  47. */
  48. var (
  49. UrlHintAddr = "0x0"
  50. HashRegAddr = "0x0"
  51. GlobalRegistrarAddr = "0x0"
  52. // GlobalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
  53. zero = regexp.MustCompile("^(0x)?0*$")
  54. )
  55. const (
  56. trueHex = "0000000000000000000000000000000000000000000000000000000000000001"
  57. falseHex = "0000000000000000000000000000000000000000000000000000000000000000"
  58. )
  59. func abiSignature(s string) string {
  60. return common.ToHex(crypto.Sha3([]byte(s))[:4])
  61. }
  62. var (
  63. HashRegName = "HashReg"
  64. UrlHintName = "UrlHint"
  65. registerContentHashAbi = abiSignature("register(uint256,uint256)")
  66. registerUrlAbi = abiSignature("register(uint256,uint8,uint256)")
  67. setOwnerAbi = abiSignature("setowner()")
  68. reserveAbi = abiSignature("reserve(bytes32)")
  69. resolveAbi = abiSignature("addr(bytes32)")
  70. registerAbi = abiSignature("setAddress(bytes32,address,bool)")
  71. addressAbiPrefix = falseHex[:24]
  72. )
  73. // Registrar's backend is defined as an interface (implemented by xeth, but could be remote)
  74. type Backend interface {
  75. StorageAt(string, string) string
  76. Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error)
  77. Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, string, error)
  78. }
  79. // TODO Registrar should also just implement The Resolver and Registry interfaces
  80. // Simplify for now.
  81. type VersionedRegistrar interface {
  82. Resolver(*big.Int) *Registrar
  83. Registry() *Registrar
  84. }
  85. type Registrar struct {
  86. backend Backend
  87. }
  88. func New(b Backend) (res *Registrar) {
  89. res = &Registrar{b}
  90. return
  91. }
  92. func (self *Registrar) SetGlobalRegistrar(namereg string, addr common.Address) (txhash string, err error) {
  93. if namereg != "" {
  94. GlobalRegistrarAddr = namereg
  95. return
  96. }
  97. if GlobalRegistrarAddr == "0x0" || GlobalRegistrarAddr == "0x" {
  98. if (addr == common.Address{}) {
  99. err = fmt.Errorf("GlobalRegistrar address not found and sender for creation not given")
  100. return
  101. } else {
  102. txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "800000", "", GlobalRegistrarCode)
  103. if err != nil {
  104. err = fmt.Errorf("GlobalRegistrar address not found and sender for creation failed: %v", err)
  105. return
  106. }
  107. }
  108. }
  109. return
  110. }
  111. func (self *Registrar) SetHashReg(hashreg string, addr common.Address) (txhash string, err error) {
  112. if hashreg != "" {
  113. HashRegAddr = hashreg
  114. } else {
  115. if !zero.MatchString(HashRegAddr) {
  116. return
  117. }
  118. nameHex, extra := encodeName(HashRegName, 2)
  119. hashRegAbi := resolveAbi + nameHex + extra
  120. glog.V(logger.Detail).Infof("\ncall HashRegAddr %v with %v\n", GlobalRegistrarAddr, hashRegAbi)
  121. var res string
  122. res, _, err = self.backend.Call("", GlobalRegistrarAddr, "", "", "", hashRegAbi)
  123. if len(res) >= 40 {
  124. HashRegAddr = "0x" + res[len(res)-40:len(res)]
  125. }
  126. if err != nil || zero.MatchString(HashRegAddr) {
  127. if (addr == common.Address{}) {
  128. err = fmt.Errorf("HashReg address not found and sender for creation not given")
  129. return
  130. }
  131. txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "", "", HashRegCode)
  132. if err != nil {
  133. err = fmt.Errorf("HashReg address not found and sender for creation failed: %v", err)
  134. }
  135. glog.V(logger.Detail).Infof("created HashRegAddr @ txhash %v\n", txhash)
  136. } else {
  137. glog.V(logger.Detail).Infof("HashRegAddr found at @ %v\n", HashRegAddr)
  138. return
  139. }
  140. }
  141. return
  142. }
  143. func (self *Registrar) SetUrlHint(urlhint string, addr common.Address) (txhash string, err error) {
  144. if urlhint != "" {
  145. UrlHintAddr = urlhint
  146. } else {
  147. if !zero.MatchString(UrlHintAddr) {
  148. return
  149. }
  150. nameHex, extra := encodeName(UrlHintName, 2)
  151. urlHintAbi := resolveAbi + nameHex + extra
  152. glog.V(logger.Detail).Infof("UrlHint address query data: %s to %s", urlHintAbi, GlobalRegistrarAddr)
  153. var res string
  154. res, _, err = self.backend.Call("", GlobalRegistrarAddr, "", "", "", urlHintAbi)
  155. if len(res) >= 40 {
  156. UrlHintAddr = "0x" + res[len(res)-40:len(res)]
  157. }
  158. if err != nil || zero.MatchString(UrlHintAddr) {
  159. if (addr == common.Address{}) {
  160. err = fmt.Errorf("UrlHint address not found and sender for creation not given")
  161. return
  162. }
  163. txhash, err = self.backend.Transact(addr.Hex(), "", "", "", "210000", "", UrlHintCode)
  164. if err != nil {
  165. err = fmt.Errorf("UrlHint address not found and sender for creation failed: %v", err)
  166. }
  167. glog.V(logger.Detail).Infof("created UrlHint @ txhash %v\n", txhash)
  168. } else {
  169. glog.V(logger.Detail).Infof("UrlHint found @ %v\n", HashRegAddr)
  170. return
  171. }
  172. }
  173. return
  174. }
  175. // ReserveName(from, name) reserves name for the sender address in the globalRegistrar
  176. // the tx needs to be mined to take effect
  177. func (self *Registrar) ReserveName(address common.Address, name string) (txh string, err error) {
  178. nameHex, extra := encodeName(name, 2)
  179. abi := reserveAbi + nameHex + extra
  180. glog.V(logger.Detail).Infof("Reserve data: %s", abi)
  181. return self.backend.Transact(
  182. address.Hex(),
  183. GlobalRegistrarAddr,
  184. "", "", "", "",
  185. abi,
  186. )
  187. }
  188. // SetAddressToName(from, name, addr) will set the Address to address for name
  189. // in the globalRegistrar using from as the sender of the transaction
  190. // the tx needs to be mined to take effect
  191. func (self *Registrar) SetAddressToName(from common.Address, name string, address common.Address) (txh string, err error) {
  192. nameHex, extra := encodeName(name, 6)
  193. addrHex := encodeAddress(address)
  194. abi := registerAbi + nameHex + addrHex + trueHex + extra
  195. glog.V(logger.Detail).Infof("SetAddressToName data: %s to %s ", abi, GlobalRegistrarAddr)
  196. return self.backend.Transact(
  197. from.Hex(),
  198. GlobalRegistrarAddr,
  199. "", "", "", "",
  200. abi,
  201. )
  202. }
  203. // NameToAddr(from, name) queries the registrar for the address on name
  204. func (self *Registrar) NameToAddr(from common.Address, name string) (address common.Address, err error) {
  205. nameHex, extra := encodeName(name, 2)
  206. abi := resolveAbi + nameHex + extra
  207. glog.V(logger.Detail).Infof("NameToAddr data: %s", abi)
  208. res, _, err := self.backend.Call(
  209. from.Hex(),
  210. GlobalRegistrarAddr,
  211. "", "", "",
  212. abi,
  213. )
  214. if err != nil {
  215. return
  216. }
  217. address = common.HexToAddress(res)
  218. return
  219. }
  220. // called as first step in the registration process on HashReg
  221. func (self *Registrar) SetOwner(address common.Address) (txh string, err error) {
  222. return self.backend.Transact(
  223. address.Hex(),
  224. HashRegAddr,
  225. "", "", "", "",
  226. setOwnerAbi,
  227. )
  228. }
  229. // registers some content hash to a key/code hash
  230. // e.g., the contract Info combined Json Doc's ContentHash
  231. // to CodeHash of a contract or hash of a domain
  232. func (self *Registrar) SetHashToHash(address common.Address, codehash, dochash common.Hash) (txh string, err error) {
  233. _, err = self.SetOwner(address)
  234. if err != nil {
  235. return
  236. }
  237. codehex := common.Bytes2Hex(codehash[:])
  238. dochex := common.Bytes2Hex(dochash[:])
  239. data := registerContentHashAbi + codehex + dochex
  240. glog.V(logger.Detail).Infof("SetHashToHash data: %s sent to %v\n", data, HashRegAddr)
  241. return self.backend.Transact(
  242. address.Hex(),
  243. HashRegAddr,
  244. "", "", "", "",
  245. data,
  246. )
  247. }
  248. // SetUrlToHash(from, hash, url) registers a url to a content hash so that the content can be fetched
  249. // address is used as sender for the transaction and will be the owner of a new
  250. // registry entry on first time use
  251. // FIXME: silently doing nothing if sender is not the owner
  252. // note that with content addressed storage, this step is no longer necessary
  253. func (self *Registrar) SetUrlToHash(address common.Address, hash common.Hash, url string) (txh string, err error) {
  254. hashHex := common.Bytes2Hex(hash[:])
  255. var urlHex string
  256. urlb := []byte(url)
  257. var cnt byte
  258. n := len(urlb)
  259. for n > 0 {
  260. if n > 32 {
  261. n = 32
  262. }
  263. urlHex = common.Bytes2Hex(urlb[:n])
  264. urlb = urlb[n:]
  265. n = len(urlb)
  266. bcnt := make([]byte, 32)
  267. bcnt[31] = cnt
  268. data := registerUrlAbi +
  269. hashHex +
  270. common.Bytes2Hex(bcnt) +
  271. common.Bytes2Hex(common.Hex2BytesFixed(urlHex, 32))
  272. txh, err = self.backend.Transact(
  273. address.Hex(),
  274. UrlHintAddr,
  275. "", "", "", "",
  276. data,
  277. )
  278. if err != nil {
  279. return
  280. }
  281. cnt++
  282. }
  283. return
  284. }
  285. // HashToHash(key) resolves contenthash for key (a hash) using HashReg
  286. // resolution is costless non-transactional
  287. // implemented as direct retrieval from db
  288. func (self *Registrar) HashToHash(khash common.Hash) (chash common.Hash, err error) {
  289. // look up in hashReg
  290. at := HashRegAddr[2:]
  291. key := storageAddress(storageMapping(storageIdx2Addr(1), khash[:]))
  292. hash := self.backend.StorageAt(at, key)
  293. if hash == "0x0" || len(hash) < 3 || (hash == common.Hash{}.Hex()) {
  294. err = fmt.Errorf("content hash not found for '%v'", khash.Hex())
  295. return
  296. }
  297. copy(chash[:], common.Hex2BytesFixed(hash[2:], 32))
  298. return
  299. }
  300. // HashToUrl(contenthash) resolves the url for contenthash using UrlHint
  301. // resolution is costless non-transactional
  302. // implemented as direct retrieval from db
  303. // if we use content addressed storage, this step is no longer necessary
  304. func (self *Registrar) HashToUrl(chash common.Hash) (uri string, err error) {
  305. // look up in URL reg
  306. var str string = " "
  307. var idx uint32
  308. for len(str) > 0 {
  309. mapaddr := storageMapping(storageIdx2Addr(1), chash[:])
  310. key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(idx)))
  311. hex := self.backend.StorageAt(UrlHintAddr[2:], key)
  312. str = string(common.Hex2Bytes(hex[2:]))
  313. l := 0
  314. for (l < len(str)) && (str[l] == 0) {
  315. l++
  316. }
  317. str = str[l:]
  318. uri = uri + str
  319. idx++
  320. }
  321. if len(uri) == 0 {
  322. err = fmt.Errorf("GetURLhint: URL hint not found for '%v'", chash.Hex())
  323. }
  324. return
  325. }
  326. func storageIdx2Addr(varidx uint32) []byte {
  327. data := make([]byte, 32)
  328. binary.BigEndian.PutUint32(data[28:32], varidx)
  329. return data
  330. }
  331. func storageMapping(addr, key []byte) []byte {
  332. data := make([]byte, 64)
  333. copy(data[0:32], key[0:32])
  334. copy(data[32:64], addr[0:32])
  335. sha := crypto.Sha3(data)
  336. return sha
  337. }
  338. func storageFixedArray(addr, idx []byte) []byte {
  339. var carry byte
  340. for i := 31; i >= 0; i-- {
  341. var b byte = addr[i] + idx[i] + carry
  342. if b < addr[i] {
  343. carry = 1
  344. } else {
  345. carry = 0
  346. }
  347. addr[i] = b
  348. }
  349. return addr
  350. }
  351. func storageAddress(addr []byte) string {
  352. return common.ToHex(addr)
  353. }
  354. func encodeAddress(address common.Address) string {
  355. return addressAbiPrefix + address.Hex()[2:]
  356. }
  357. func encodeName(name string, index uint8) (string, string) {
  358. extra := common.Bytes2Hex([]byte(name))
  359. if len(name) > 32 {
  360. return fmt.Sprintf("%064x", index), extra
  361. }
  362. return extra + falseHex[len(extra):], ""
  363. }