github.com/Aodurkeen/go-ubiq@v2.3.0+incompatible/contracts/ens/ens.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library 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 // The go-ethereum library 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 the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package ens 18 19 //go:generate abigen --sol contract/ENS.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/ens.go 20 //go:generate abigen --sol contract/FIFSRegistrar.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/fifsregistrar.go 21 //go:generate abigen --sol contract/PublicResolver.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/publicresolver.go 22 23 import ( 24 "strings" 25 26 "github.com/ubiq/go-ubiq/accounts/abi/bind" 27 "github.com/ubiq/go-ubiq/common" 28 "github.com/ubiq/go-ubiq/contracts/ens/contract" 29 "github.com/ubiq/go-ubiq/core/types" 30 "github.com/ubiq/go-ubiq/crypto" 31 ) 32 33 var ( 34 MainNetAddress = common.HexToAddress("0x314159265dD8dbb310642f98f50C066173C1259b") 35 TestNetAddress = common.HexToAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010") 36 ) 37 38 // ENS is the swarm domain name registry and resolver 39 type ENS struct { 40 *contract.ENSSession 41 contractBackend bind.ContractBackend 42 } 43 44 // NewENS creates a struct exposing convenient high-level operations for interacting with 45 // the Ethereum Name Service. 46 func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) (*ENS, error) { 47 ens, err := contract.NewENS(contractAddr, contractBackend) 48 if err != nil { 49 return nil, err 50 } 51 return &ENS{ 52 &contract.ENSSession{ 53 Contract: ens, 54 TransactOpts: *transactOpts, 55 }, 56 contractBackend, 57 }, nil 58 } 59 60 // DeployENS deploys an instance of the ENS nameservice, with a 'first-in, first-served' root registrar. 61 func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *ENS, error) { 62 // Deploy the ENS registry 63 ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend) 64 if err != nil { 65 return ensAddr, nil, err 66 } 67 ens, err := NewENS(transactOpts, ensAddr, contractBackend) 68 if err != nil { 69 return ensAddr, nil, err 70 } 71 // Deploy the registrar 72 regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{}) 73 if err != nil { 74 return ensAddr, nil, err 75 } 76 // Set the registrar as owner of the ENS root 77 if _, err = ens.SetOwner([32]byte{}, regAddr); err != nil { 78 return ensAddr, nil, err 79 } 80 return ensAddr, ens, nil 81 } 82 83 func ensParentNode(name string) (common.Hash, common.Hash) { 84 parts := strings.SplitN(name, ".", 2) 85 label := crypto.Keccak256Hash([]byte(parts[0])) 86 if len(parts) == 1 { 87 return [32]byte{}, label 88 } 89 parentNode, parentLabel := ensParentNode(parts[1]) 90 return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label 91 } 92 93 func EnsNode(name string) common.Hash { 94 parentNode, parentLabel := ensParentNode(name) 95 return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) 96 } 97 98 func (ens *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) { 99 resolverAddr, err := ens.Resolver(node) 100 if err != nil { 101 return nil, err 102 } 103 resolver, err := contract.NewPublicResolver(resolverAddr, ens.contractBackend) 104 if err != nil { 105 return nil, err 106 } 107 return &contract.PublicResolverSession{ 108 Contract: resolver, 109 TransactOpts: ens.TransactOpts, 110 }, nil 111 } 112 113 func (ens *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) { 114 registrarAddr, err := ens.Owner(node) 115 if err != nil { 116 return nil, err 117 } 118 registrar, err := contract.NewFIFSRegistrar(registrarAddr, ens.contractBackend) 119 if err != nil { 120 return nil, err 121 } 122 return &contract.FIFSRegistrarSession{ 123 Contract: registrar, 124 TransactOpts: ens.TransactOpts, 125 }, nil 126 } 127 128 // Resolve is a non-transactional call that returns the content hash associated with a name. 129 func (ens *ENS) Resolve(name string) (common.Hash, error) { 130 node := EnsNode(name) 131 132 resolver, err := ens.getResolver(node) 133 if err != nil { 134 return common.Hash{}, err 135 } 136 ret, err := resolver.Content(node) 137 if err != nil { 138 return common.Hash{}, err 139 } 140 return common.BytesToHash(ret[:]), nil 141 } 142 143 // Addr is a non-transactional call that returns the address associated with a name. 144 func (ens *ENS) Addr(name string) (common.Address, error) { 145 node := EnsNode(name) 146 147 resolver, err := ens.getResolver(node) 148 if err != nil { 149 return common.Address{}, err 150 } 151 ret, err := resolver.Addr(node) 152 if err != nil { 153 return common.Address{}, err 154 } 155 return common.BytesToAddress(ret[:]), nil 156 } 157 158 // SetAddress sets the address associated with a name. Only works if the caller 159 // owns the name, and the associated resolver implements a `setAddress` function. 160 func (ens *ENS) SetAddr(name string, addr common.Address) (*types.Transaction, error) { 161 node := EnsNode(name) 162 163 resolver, err := ens.getResolver(node) 164 if err != nil { 165 return nil, err 166 } 167 opts := ens.TransactOpts 168 opts.GasLimit = 200000 169 return resolver.Contract.SetAddr(&opts, node, addr) 170 } 171 172 // Register registers a new domain name for the caller, making them the owner of the new name. 173 // Only works if the registrar for the parent domain implements the FIFS registrar protocol. 174 func (ens *ENS) Register(name string) (*types.Transaction, error) { 175 parentNode, label := ensParentNode(name) 176 registrar, err := ens.getRegistrar(parentNode) 177 if err != nil { 178 return nil, err 179 } 180 return registrar.Contract.Register(&ens.TransactOpts, label, ens.TransactOpts.From) 181 } 182 183 // SetContentHash sets the content hash associated with a name. Only works if the caller 184 // owns the name, and the associated resolver implements a `setContent` function. 185 func (ens *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) { 186 node := EnsNode(name) 187 188 resolver, err := ens.getResolver(node) 189 if err != nil { 190 return nil, err 191 } 192 opts := ens.TransactOpts 193 opts.GasLimit = 200000 194 return resolver.Contract.SetContent(&opts, node, hash) 195 }