github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/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 --pkg contract --out contract/ens.go
    20  
    21  import (
    22  	"math/big"
    23  	"strings"
    24  
    25  	"github.com/atheioschain/go-atheios/accounts/abi/bind"
    26  	"github.com/atheioschain/go-atheios/common"
    27  	"github.com/atheioschain/go-atheios/contracts/ens/contract"
    28  	"github.com/atheioschain/go-atheios/core/types"
    29  	"github.com/atheioschain/go-atheios/crypto"
    30  )
    31  
    32  // swarm domain name registry and resolver
    33  type ENS struct {
    34  	*contract.ENSSession
    35  	contractBackend bind.ContractBackend
    36  }
    37  
    38  // NewENS creates a struct exposing convenient high-level operations for interacting with
    39  // the Ethereum Name Service.
    40  func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) (*ENS, error) {
    41  	ens, err := contract.NewENS(contractAddr, contractBackend)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	return &ENS{
    47  		&contract.ENSSession{
    48  			Contract:     ens,
    49  			TransactOpts: *transactOpts,
    50  		},
    51  		contractBackend,
    52  	}, nil
    53  }
    54  
    55  // DeployENS deploys an instance of the ENS nameservice, with a 'first in first served' root registrar.
    56  func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (*ENS, error) {
    57  	// Deploy the ENS registry
    58  	ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend, transactOpts.From)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	ens, err := NewENS(transactOpts, ensAddr, contractBackend)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	// Deploy the registrar
    69  	regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{})
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	// Set the registrar as owner of the ENS root
    75  	_, err = ens.SetOwner([32]byte{}, regAddr)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	return 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  	} else {
    89  		parentNode, parentLabel := ensParentNode(parts[1])
    90  		return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label
    91  	}
    92  }
    93  
    94  func ensNode(name string) common.Hash {
    95  	parentNode, parentLabel := ensParentNode(name)
    96  	return crypto.Keccak256Hash(parentNode[:], parentLabel[:])
    97  }
    98  
    99  func (self *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) {
   100  	resolverAddr, err := self.Resolver(node)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	resolver, err := contract.NewPublicResolver(resolverAddr, self.contractBackend)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	return &contract.PublicResolverSession{
   111  		Contract:     resolver,
   112  		TransactOpts: self.TransactOpts,
   113  	}, nil
   114  }
   115  
   116  func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) {
   117  	registrarAddr, err := self.Owner(node)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	registrar, err := contract.NewFIFSRegistrar(registrarAddr, self.contractBackend)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	return &contract.FIFSRegistrarSession{
   128  		Contract:     registrar,
   129  		TransactOpts: self.TransactOpts,
   130  	}, nil
   131  }
   132  
   133  // Resolve is a non-transactional call that returns the content hash associated with a name.
   134  func (self *ENS) Resolve(name string) (common.Hash, error) {
   135  	node := ensNode(name)
   136  
   137  	resolver, err := self.getResolver(node)
   138  	if err != nil {
   139  		return common.Hash{}, err
   140  	}
   141  
   142  	ret, err := resolver.Content(node)
   143  	if err != nil {
   144  		return common.Hash{}, err
   145  	}
   146  
   147  	return common.BytesToHash(ret[:]), nil
   148  }
   149  
   150  // Register registers a new domain name for the caller, making them the owner of the new name.
   151  // Only works if the registrar for the parent domain implements the FIFS registrar protocol.
   152  func (self *ENS) Register(name string) (*types.Transaction, error) {
   153  	parentNode, label := ensParentNode(name)
   154  
   155  	registrar, err := self.getRegistrar(parentNode)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	opts := self.TransactOpts
   161  	opts.GasLimit = big.NewInt(200000)
   162  	return registrar.Contract.Register(&opts, label, self.TransactOpts.From)
   163  }
   164  
   165  // SetContentHash sets the content hash associated with a name. Only works if the caller
   166  // owns the name, and the associated resolver implements a `setContent` function.
   167  func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
   168  	node := ensNode(name)
   169  
   170  	resolver, err := self.getResolver(node)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  
   175  	opts := self.TransactOpts
   176  	opts.GasLimit = big.NewInt(200000)
   177  	return resolver.Contract.SetContent(&opts, node, hash)
   178  }