swarm: code cleanup, move to ethersphere/swarm (#19661)

This commit is contained in:
Rafael Matias
2019-06-04 15:35:36 +02:00
committed by Péter Szilágyi
parent 15f24ff189
commit 42b81f94ad
361 changed files with 22 additions and 87054 deletions

View File

@ -1,68 +0,0 @@
// Copyright 2016 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 chequebook
import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
const Version = "1.0"
var errNoChequebook = errors.New("no chequebook")
type API struct {
chequebookf func() *Chequebook
}
func NewAPI(ch func() *Chequebook) *API {
return &API{ch}
}
func (a *API) Balance() (string, error) {
ch := a.chequebookf()
if ch == nil {
return "", errNoChequebook
}
return ch.Balance().String(), nil
}
func (a *API) Issue(beneficiary common.Address, amount *big.Int) (cheque *Cheque, err error) {
ch := a.chequebookf()
if ch == nil {
return nil, errNoChequebook
}
return ch.Issue(beneficiary, amount)
}
func (a *API) Cash(cheque *Cheque) (txhash string, err error) {
ch := a.chequebookf()
if ch == nil {
return "", errNoChequebook
}
return ch.Cash(cheque)
}
func (a *API) Deposit(amount *big.Int) (txhash string, err error) {
ch := a.chequebookf()
if ch == nil {
return "", errNoChequebook
}
return ch.Deposit(amount)
}

View File

@ -1,642 +0,0 @@
// Copyright 2016 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 chequebook package wraps the 'chequebook' Ethereum smart contract.
//
// The functions in this package allow using chequebook for
// issuing, receiving, verifying cheques in ether; (auto)cashing cheques in ether
// as well as (auto)depositing ether to the chequebook contract.
package chequebook
//go:generate abigen --sol contract/chequebook.sol --exc contract/mortal.sol:mortal,contract/owned.sol:owned --pkg contract --out contract/chequebook.go
//go:generate go run ./gencode.go
import (
"bytes"
"context"
"crypto/ecdsa"
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"os"
"sync"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/contracts/chequebook/contract"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/swarm/services/swap/swap"
)
// TODO(zelig): watch peer solvency and notify of bouncing cheques
// TODO(zelig): enable paying with cheque by signing off
// Some functionality requires interacting with the blockchain:
// * setting current balance on peer's chequebook
// * sending the transaction to cash the cheque
// * depositing ether to the chequebook
// * watching incoming ether
var (
gasToCash = uint64(2000000) // gas cost of a cash transaction using chequebook
// gasToDeploy = uint64(3000000)
)
// Backend wraps all methods required for chequebook operation.
type Backend interface {
bind.ContractBackend
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
BalanceAt(ctx context.Context, address common.Address, blockNum *big.Int) (*big.Int, error)
}
// Cheque represents a payment promise to a single beneficiary.
type Cheque struct {
Contract common.Address // address of chequebook, needed to avoid cross-contract submission
Beneficiary common.Address
Amount *big.Int // cumulative amount of all funds sent
Sig []byte // signature Sign(Keccak256(contract, beneficiary, amount), prvKey)
}
func (ch *Cheque) String() string {
return fmt.Sprintf("contract: %s, beneficiary: %s, amount: %v, signature: %x", ch.Contract.Hex(), ch.Beneficiary.Hex(), ch.Amount, ch.Sig)
}
type Params struct {
ContractCode, ContractAbi string
}
var ContractParams = &Params{contract.ChequebookBin, contract.ChequebookABI}
// Chequebook can create and sign cheques from a single contract to multiple beneficiaries.
// It is the outgoing payment handler for peer to peer micropayments.
type Chequebook struct {
path string // path to chequebook file
prvKey *ecdsa.PrivateKey // private key to sign cheque with
lock sync.Mutex //
backend Backend // blockchain API
quit chan bool // when closed causes autodeposit to stop
owner common.Address // owner address (derived from pubkey)
contract *contract.Chequebook // abigen binding
session *contract.ChequebookSession // abigen binding with Tx Opts
// persisted fields
balance *big.Int // not synced with blockchain
contractAddr common.Address // contract address
sent map[common.Address]*big.Int //tallies for beneficiaries
txhash string // tx hash of last deposit tx
threshold *big.Int // threshold that triggers autodeposit if not nil
buffer *big.Int // buffer to keep on top of balance for fork protection
log log.Logger // contextual logger with the contract address embedded
}
func (cb *Chequebook) String() string {
return fmt.Sprintf("contract: %s, owner: %s, balance: %v, signer: %x", cb.contractAddr.Hex(), cb.owner.Hex(), cb.balance, cb.prvKey.PublicKey)
}
// NewChequebook creates a new Chequebook.
func NewChequebook(path string, contractAddr common.Address, prvKey *ecdsa.PrivateKey, backend Backend) (*Chequebook, error) {
balance := new(big.Int)
sent := make(map[common.Address]*big.Int)
chbook, err := contract.NewChequebook(contractAddr, backend)
if err != nil {
return nil, err
}
transactOpts := bind.NewKeyedTransactor(prvKey)
session := &contract.ChequebookSession{
Contract: chbook,
TransactOpts: *transactOpts,
}
cb := &Chequebook{
prvKey: prvKey,
balance: balance,
contractAddr: contractAddr,
sent: sent,
path: path,
backend: backend,
owner: transactOpts.From,
contract: chbook,
session: session,
log: log.New("contract", contractAddr),
}
if (contractAddr != common.Address{}) {
cb.setBalanceFromBlockChain()
cb.log.Trace("New chequebook initialised", "owner", cb.owner, "balance", cb.balance)
}
return cb, nil
}
func (cb *Chequebook) setBalanceFromBlockChain() {
balance, err := cb.backend.BalanceAt(context.TODO(), cb.contractAddr, nil)
if err != nil {
log.Error("Failed to retrieve chequebook balance", "err", err)
} else {
cb.balance.Set(balance)
}
}
// LoadChequebook loads a chequebook from disk (file path).
func LoadChequebook(path string, prvKey *ecdsa.PrivateKey, backend Backend, checkBalance bool) (*Chequebook, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
cb, _ := NewChequebook(path, common.Address{}, prvKey, backend)
if err = json.Unmarshal(data, cb); err != nil {
return nil, err
}
if checkBalance {
cb.setBalanceFromBlockChain()
}
log.Trace("Loaded chequebook from disk", "path", path)
return cb, nil
}
// chequebookFile is the JSON representation of a chequebook.
type chequebookFile struct {
Balance string
Contract string
Owner string
Sent map[string]string
}
// UnmarshalJSON deserialises a chequebook.
func (cb *Chequebook) UnmarshalJSON(data []byte) error {
var file chequebookFile
err := json.Unmarshal(data, &file)
if err != nil {
return err
}
_, ok := cb.balance.SetString(file.Balance, 10)
if !ok {
return fmt.Errorf("cumulative amount sent: unable to convert string to big integer: %v", file.Balance)
}
cb.contractAddr = common.HexToAddress(file.Contract)
for addr, sent := range file.Sent {
cb.sent[common.HexToAddress(addr)], ok = new(big.Int).SetString(sent, 10)
if !ok {
return fmt.Errorf("beneficiary %v cumulative amount sent: unable to convert string to big integer: %v", addr, sent)
}
}
return nil
}
// MarshalJSON serialises a chequebook.
func (cb *Chequebook) MarshalJSON() ([]byte, error) {
var file = &chequebookFile{
Balance: cb.balance.String(),
Contract: cb.contractAddr.Hex(),
Owner: cb.owner.Hex(),
Sent: make(map[string]string),
}
for addr, sent := range cb.sent {
file.Sent[addr.Hex()] = sent.String()
}
return json.Marshal(file)
}
// Save persists the chequebook on disk, remembering balance, contract address and
// cumulative amount of funds sent for each beneficiary.
func (cb *Chequebook) Save() error {
data, err := json.MarshalIndent(cb, "", " ")
if err != nil {
return err
}
cb.log.Trace("Saving chequebook to disk", cb.path)
return ioutil.WriteFile(cb.path, data, os.ModePerm)
}
// Stop quits the autodeposit go routine to terminate
func (cb *Chequebook) Stop() {
defer cb.lock.Unlock()
cb.lock.Lock()
if cb.quit != nil {
close(cb.quit)
cb.quit = nil
}
}
// Issue creates a cheque signed by the chequebook owner's private key. The
// signer commits to a contract (one that they own), a beneficiary and amount.
func (cb *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (*Cheque, error) {
defer cb.lock.Unlock()
cb.lock.Lock()
if amount.Sign() <= 0 {
return nil, fmt.Errorf("amount must be greater than zero (%v)", amount)
}
var (
ch *Cheque
err error
)
if cb.balance.Cmp(amount) < 0 {
err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, cb.balance)
} else {
var sig []byte
sent, found := cb.sent[beneficiary]
if !found {
sent = new(big.Int)
cb.sent[beneficiary] = sent
}
sum := new(big.Int).Set(sent)
sum.Add(sum, amount)
sig, err = crypto.Sign(sigHash(cb.contractAddr, beneficiary, sum), cb.prvKey)
if err == nil {
ch = &Cheque{
Contract: cb.contractAddr,
Beneficiary: beneficiary,
Amount: sum,
Sig: sig,
}
sent.Set(sum)
cb.balance.Sub(cb.balance, amount) // subtract amount from balance
}
}
// auto deposit if threshold is set and balance is less then threshold
// note this is called even if issuing cheque fails
// so we reattempt depositing
if cb.threshold != nil {
if cb.balance.Cmp(cb.threshold) < 0 {
send := new(big.Int).Sub(cb.buffer, cb.balance)
cb.deposit(send)
}
}
return ch, err
}
// Cash is a convenience method to cash any cheque.
func (cb *Chequebook) Cash(ch *Cheque) (string, error) {
return ch.Cash(cb.session)
}
// data to sign: contract address, beneficiary, cumulative amount of funds ever sent
func sigHash(contract, beneficiary common.Address, sum *big.Int) []byte {
bigamount := sum.Bytes()
if len(bigamount) > 32 {
return nil
}
var amount32 [32]byte
copy(amount32[32-len(bigamount):32], bigamount)
input := append(contract.Bytes(), beneficiary.Bytes()...)
input = append(input, amount32[:]...)
return crypto.Keccak256(input)
}
// Balance returns the current balance of the chequebook.
func (cb *Chequebook) Balance() *big.Int {
defer cb.lock.Unlock()
cb.lock.Lock()
return new(big.Int).Set(cb.balance)
}
// Owner returns the owner account of the chequebook.
func (cb *Chequebook) Owner() common.Address {
return cb.owner
}
// Address returns the on-chain contract address of the chequebook.
func (cb *Chequebook) Address() common.Address {
return cb.contractAddr
}
// Deposit deposits money to the chequebook account.
func (cb *Chequebook) Deposit(amount *big.Int) (string, error) {
defer cb.lock.Unlock()
cb.lock.Lock()
return cb.deposit(amount)
}
// deposit deposits amount to the chequebook account.
// The caller must hold lock.
func (cb *Chequebook) deposit(amount *big.Int) (string, error) {
// since the amount is variable here, we do not use sessions
depositTransactor := bind.NewKeyedTransactor(cb.prvKey)
depositTransactor.Value = amount
chbookRaw := &contract.ChequebookRaw{Contract: cb.contract}
tx, err := chbookRaw.Transfer(depositTransactor)
if err != nil {
cb.log.Warn("Failed to fund chequebook", "amount", amount, "balance", cb.balance, "target", cb.buffer, "err", err)
return "", err
}
// assume that transaction is actually successful, we add the amount to balance right away
cb.balance.Add(cb.balance, amount)
cb.log.Trace("Deposited funds to chequebook", "amount", amount, "balance", cb.balance, "target", cb.buffer)
return tx.Hash().Hex(), nil
}
// AutoDeposit (re)sets interval time and amount which triggers sending funds to the
// chequebook. Contract backend needs to be set if threshold is not less than buffer, then
// deposit will be triggered on every new cheque issued.
func (cb *Chequebook) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
defer cb.lock.Unlock()
cb.lock.Lock()
cb.threshold = threshold
cb.buffer = buffer
cb.autoDeposit(interval)
}
// autoDeposit starts a goroutine that periodically sends funds to the chequebook
// contract caller holds the lock the go routine terminates if Chequebook.quit is closed.
func (cb *Chequebook) autoDeposit(interval time.Duration) {
if cb.quit != nil {
close(cb.quit)
cb.quit = nil
}
// if threshold >= balance autodeposit after every cheque issued
if interval == time.Duration(0) || cb.threshold != nil && cb.buffer != nil && cb.threshold.Cmp(cb.buffer) >= 0 {
return
}
ticker := time.NewTicker(interval)
cb.quit = make(chan bool)
quit := cb.quit
go func() {
for {
select {
case <-quit:
return
case <-ticker.C:
cb.lock.Lock()
if cb.balance.Cmp(cb.buffer) < 0 {
amount := new(big.Int).Sub(cb.buffer, cb.balance)
txhash, err := cb.deposit(amount)
if err == nil {
cb.txhash = txhash
}
}
cb.lock.Unlock()
}
}
}()
}
// Outbox can issue cheques from a single contract to a single beneficiary.
type Outbox struct {
chequeBook *Chequebook
beneficiary common.Address
}
// NewOutbox creates an outbox.
func NewOutbox(cb *Chequebook, beneficiary common.Address) *Outbox {
return &Outbox{cb, beneficiary}
}
// Issue creates cheque.
func (o *Outbox) Issue(amount *big.Int) (swap.Promise, error) {
return o.chequeBook.Issue(o.beneficiary, amount)
}
// AutoDeposit enables auto-deposits on the underlying chequebook.
func (o *Outbox) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
o.chequeBook.AutoDeposit(interval, threshold, buffer)
}
// Stop helps satisfy the swap.OutPayment interface.
func (o *Outbox) Stop() {}
// String implements fmt.Stringer.
func (o *Outbox) String() string {
return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", o.chequeBook.Address().Hex(), o.beneficiary.Hex(), o.chequeBook.Balance())
}
// Inbox can deposit, verify and cash cheques from a single contract to a single
// beneficiary. It is the incoming payment handler for peer to peer micropayments.
type Inbox struct {
lock sync.Mutex
contract common.Address // peer's chequebook contract
beneficiary common.Address // local peer's receiving address
sender common.Address // local peer's address to send cashing tx from
signer *ecdsa.PublicKey // peer's public key
txhash string // tx hash of last cashing tx
session *contract.ChequebookSession // abi contract backend with tx opts
quit chan bool // when closed causes autocash to stop
maxUncashed *big.Int // threshold that triggers autocashing
cashed *big.Int // cumulative amount cashed
cheque *Cheque // last cheque, nil if none yet received
log log.Logger // contextual logger with the contract address embedded
}
// NewInbox creates an Inbox. An Inboxes is not persisted, the cumulative sum is updated
// from blockchain when first cheque is received.
func NewInbox(prvKey *ecdsa.PrivateKey, contractAddr, beneficiary common.Address, signer *ecdsa.PublicKey, abigen bind.ContractBackend) (*Inbox, error) {
if signer == nil {
return nil, fmt.Errorf("signer is null")
}
chbook, err := contract.NewChequebook(contractAddr, abigen)
if err != nil {
return nil, err
}
transactOpts := bind.NewKeyedTransactor(prvKey)
transactOpts.GasLimit = gasToCash
session := &contract.ChequebookSession{
Contract: chbook,
TransactOpts: *transactOpts,
}
sender := transactOpts.From
inbox := &Inbox{
contract: contractAddr,
beneficiary: beneficiary,
sender: sender,
signer: signer,
session: session,
cashed: new(big.Int).Set(common.Big0),
log: log.New("contract", contractAddr),
}
inbox.log.Trace("New chequebook inbox initialized", "beneficiary", inbox.beneficiary, "signer", hexutil.Bytes(crypto.FromECDSAPub(signer)))
return inbox, nil
}
func (i *Inbox) String() string {
return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", i.contract.Hex(), i.beneficiary.Hex(), i.cheque.Amount)
}
// Stop quits the autocash goroutine.
func (i *Inbox) Stop() {
defer i.lock.Unlock()
i.lock.Lock()
if i.quit != nil {
close(i.quit)
i.quit = nil
}
}
// Cash attempts to cash the current cheque.
func (i *Inbox) Cash() (string, error) {
if i.cheque == nil {
return "", nil
}
txhash, err := i.cheque.Cash(i.session)
i.log.Trace("Cashing in chequebook cheque", "amount", i.cheque.Amount, "beneficiary", i.beneficiary)
i.cashed = i.cheque.Amount
return txhash, err
}
// AutoCash (re)sets maximum time and amount which triggers cashing of the last uncashed
// cheque if maxUncashed is set to 0, then autocash on receipt.
func (i *Inbox) AutoCash(cashInterval time.Duration, maxUncashed *big.Int) {
defer i.lock.Unlock()
i.lock.Lock()
i.maxUncashed = maxUncashed
i.autoCash(cashInterval)
}
// autoCash starts a loop that periodically clears the last cheque
// if the peer is trusted. Clearing period could be 24h or a week.
// The caller must hold lock.
func (i *Inbox) autoCash(cashInterval time.Duration) {
if i.quit != nil {
close(i.quit)
i.quit = nil
}
// if maxUncashed is set to 0, then autocash on receipt
if cashInterval == time.Duration(0) || i.maxUncashed != nil && i.maxUncashed.Sign() == 0 {
return
}
ticker := time.NewTicker(cashInterval)
i.quit = make(chan bool)
quit := i.quit
go func() {
for {
select {
case <-quit:
return
case <-ticker.C:
i.lock.Lock()
if i.cheque != nil && i.cheque.Amount.Cmp(i.cashed) != 0 {
txhash, err := i.Cash()
if err == nil {
i.txhash = txhash
}
}
i.lock.Unlock()
}
}
}()
}
// Receive is called to deposit the latest cheque to the incoming Inbox.
// The given promise must be a *Cheque.
func (i *Inbox) Receive(promise swap.Promise) (*big.Int, error) {
ch := promise.(*Cheque)
defer i.lock.Unlock()
i.lock.Lock()
var sum *big.Int
if i.cheque == nil {
// the sum is checked against the blockchain once a cheque is received
tally, err := i.session.Sent(i.beneficiary)
if err != nil {
return nil, fmt.Errorf("inbox: error calling backend to set amount: %v", err)
}
sum = tally
} else {
sum = i.cheque.Amount
}
amount, err := ch.Verify(i.signer, i.contract, i.beneficiary, sum)
var uncashed *big.Int
if err == nil {
i.cheque = ch
if i.maxUncashed != nil {
uncashed = new(big.Int).Sub(ch.Amount, i.cashed)
if i.maxUncashed.Cmp(uncashed) < 0 {
i.Cash()
}
}
i.log.Trace("Received cheque in chequebook inbox", "amount", amount, "uncashed", uncashed)
}
return amount, err
}
// Verify verifies cheque for signer, contract, beneficiary, amount, valid signature.
func (ch *Cheque) Verify(signerKey *ecdsa.PublicKey, contract, beneficiary common.Address, sum *big.Int) (*big.Int, error) {
log.Trace("Verifying chequebook cheque", "cheque", ch, "sum", sum)
if sum == nil {
return nil, fmt.Errorf("invalid amount")
}
if ch.Beneficiary != beneficiary {
return nil, fmt.Errorf("beneficiary mismatch: %v != %v", ch.Beneficiary.Hex(), beneficiary.Hex())
}
if ch.Contract != contract {
return nil, fmt.Errorf("contract mismatch: %v != %v", ch.Contract.Hex(), contract.Hex())
}
amount := new(big.Int).Set(ch.Amount)
if sum != nil {
amount.Sub(amount, sum)
if amount.Sign() <= 0 {
return nil, fmt.Errorf("incorrect amount: %v <= 0", amount)
}
}
pubKey, err := crypto.SigToPub(sigHash(ch.Contract, beneficiary, ch.Amount), ch.Sig)
if err != nil {
return nil, fmt.Errorf("invalid signature: %v", err)
}
if !bytes.Equal(crypto.FromECDSAPub(pubKey), crypto.FromECDSAPub(signerKey)) {
return nil, fmt.Errorf("signer mismatch: %x != %x", crypto.FromECDSAPub(pubKey), crypto.FromECDSAPub(signerKey))
}
return amount, nil
}
// v/r/s representation of signature
func sig2vrs(sig []byte) (v byte, r, s [32]byte) {
v = sig[64] + 27
copy(r[:], sig[:32])
copy(s[:], sig[32:64])
return
}
// Cash cashes the cheque by sending an Ethereum transaction.
func (ch *Cheque) Cash(session *contract.ChequebookSession) (string, error) {
v, r, s := sig2vrs(ch.Sig)
tx, err := session.Cash(ch.Beneficiary, ch.Amount, v, r, s)
if err != nil {
return "", err
}
return tx.Hash().Hex(), nil
}
// ValidateCode checks that the on-chain code at address matches the expected chequebook
// contract code. This is used to detect suicided chequebooks.
func ValidateCode(ctx context.Context, b Backend, address common.Address) (bool, error) {
code, err := b.CodeAt(ctx, address, nil)
if err != nil {
return false, err
}
return bytes.Equal(code, common.FromHex(contract.ContractDeployedCode)), nil
}

View File

@ -1,487 +0,0 @@
// Copyright 2016 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 chequebook
import (
"crypto/ecdsa"
"math/big"
"os"
"path/filepath"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts/chequebook/contract"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
var (
key0, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
key1, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
key2, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
addr0 = crypto.PubkeyToAddress(key0.PublicKey)
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
)
func newTestBackend() *backends.SimulatedBackend {
return backends.NewSimulatedBackend(core.GenesisAlloc{
addr0: {Balance: big.NewInt(1000000000)},
addr1: {Balance: big.NewInt(1000000000)},
addr2: {Balance: big.NewInt(1000000000)},
}, 10000000)
}
func deploy(prvKey *ecdsa.PrivateKey, amount *big.Int, backend *backends.SimulatedBackend) (common.Address, error) {
deployTransactor := bind.NewKeyedTransactor(prvKey)
deployTransactor.Value = amount
addr, _, _, err := contract.DeployChequebook(deployTransactor, backend)
if err != nil {
return common.Address{}, err
}
backend.Commit()
return addr, nil
}
func TestIssueAndReceive(t *testing.T) {
path := filepath.Join(os.TempDir(), "chequebook-test.json")
backend := newTestBackend()
addr0, err := deploy(key0, big.NewInt(0), backend)
if err != nil {
t.Fatalf("deploy contract: expected no error, got %v", err)
}
chbook, err := NewChequebook(path, addr0, key0, backend)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
chbook.sent[addr1] = new(big.Int).SetUint64(42)
amount := common.Big1
if _, err = chbook.Issue(addr1, amount); err == nil {
t.Fatalf("expected insufficient funds error, got none")
}
chbook.balance = new(big.Int).Set(common.Big1)
if chbook.Balance().Cmp(common.Big1) != 0 {
t.Fatalf("expected: %v, got %v", "0", chbook.Balance())
}
ch, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if chbook.Balance().Sign() != 0 {
t.Errorf("expected: %v, got %v", "0", chbook.Balance())
}
chbox, err := NewInbox(key1, addr0, addr1, &key0.PublicKey, backend)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
received, err := chbox.Receive(ch)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if received.Cmp(big.NewInt(43)) != 0 {
t.Errorf("expected: %v, got %v", "43", received)
}
}
func TestCheckbookFile(t *testing.T) {
path := filepath.Join(os.TempDir(), "chequebook-test.json")
backend := newTestBackend()
chbook, err := NewChequebook(path, addr0, key0, backend)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
chbook.sent[addr1] = new(big.Int).SetUint64(42)
chbook.balance = new(big.Int).Set(common.Big1)
chbook.Save()
chbook, err = LoadChequebook(path, key0, backend, false)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if chbook.Balance().Cmp(common.Big1) != 0 {
t.Errorf("expected: %v, got %v", "0", chbook.Balance())
}
var ch *Cheque
if ch, err = chbook.Issue(addr1, common.Big1); err != nil {
t.Fatalf("expected no error, got %v", err)
}
if ch.Amount.Cmp(new(big.Int).SetUint64(43)) != 0 {
t.Errorf("expected: %v, got %v", "0", ch.Amount)
}
err = chbook.Save()
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
}
func TestVerifyErrors(t *testing.T) {
path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
backend := newTestBackend()
contr0, err := deploy(key0, common.Big2, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
chbook0, err := NewChequebook(path0, contr0, key0, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
path1 := filepath.Join(os.TempDir(), "chequebook-test-1.json")
contr1, _ := deploy(key1, common.Big2, backend)
chbook1, err := NewChequebook(path1, contr1, key1, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
chbook0.sent[addr1] = new(big.Int).SetUint64(42)
chbook0.balance = new(big.Int).Set(common.Big2)
chbook1.balance = new(big.Int).Set(common.Big1)
amount := common.Big1
ch0, err := chbook0.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
received, err := chbox.Receive(ch0)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if received.Cmp(big.NewInt(43)) != 0 {
t.Errorf("expected: %v, got %v", "43", received)
}
ch1, err := chbook0.Issue(addr2, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
received, err = chbox.Receive(ch1)
t.Logf("correct error: %v", err)
if err == nil {
t.Fatalf("expected receiver error, got none and value %v", received)
}
ch2, err := chbook1.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
received, err = chbox.Receive(ch2)
t.Logf("correct error: %v", err)
if err == nil {
t.Fatalf("expected sender error, got none and value %v", received)
}
_, err = chbook1.Issue(addr1, new(big.Int).SetInt64(-1))
t.Logf("correct error: %v", err)
if err == nil {
t.Fatalf("expected incorrect amount error, got none")
}
received, err = chbox.Receive(ch0)
t.Logf("correct error: %v", err)
if err == nil {
t.Fatalf("expected incorrect amount error, got none and value %v", received)
}
}
func TestDeposit(t *testing.T) {
path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
backend := newTestBackend()
contr0, _ := deploy(key0, new(big.Int), backend)
chbook, err := NewChequebook(path0, contr0, key0, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
balance := new(big.Int).SetUint64(42)
chbook.Deposit(balance)
backend.Commit()
if chbook.Balance().Cmp(balance) != 0 {
t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
}
amount := common.Big1
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
exp := new(big.Int).SetUint64(41)
if chbook.Balance().Cmp(exp) != 0 {
t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
}
// autodeposit on each issue
chbook.AutoDeposit(0, balance, balance)
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
if chbook.Balance().Cmp(balance) != 0 {
t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
}
// autodeposit off
chbook.AutoDeposit(0, common.Big0, balance)
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
exp = new(big.Int).SetUint64(40)
if chbook.Balance().Cmp(exp) != 0 {
t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
}
// autodeposit every 200ms if new cheque issued
interval := 200 * time.Millisecond
chbook.AutoDeposit(interval, common.Big1, balance)
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
exp = new(big.Int).SetUint64(38)
if chbook.Balance().Cmp(exp) != 0 {
t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
}
time.Sleep(3 * interval)
backend.Commit()
if chbook.Balance().Cmp(balance) != 0 {
t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
}
exp = new(big.Int).SetUint64(40)
chbook.AutoDeposit(4*interval, exp, balance)
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
time.Sleep(3 * interval)
backend.Commit()
if chbook.Balance().Cmp(exp) != 0 {
t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
}
_, err = chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
time.Sleep(1 * interval)
backend.Commit()
if chbook.Balance().Cmp(balance) != 0 {
t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
}
chbook.AutoDeposit(1*interval, common.Big0, balance)
chbook.Stop()
_, err = chbook.Issue(addr1, common.Big1)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbook.Issue(addr1, common.Big2)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
time.Sleep(1 * interval)
backend.Commit()
exp = new(big.Int).SetUint64(39)
if chbook.Balance().Cmp(exp) != 0 {
t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
}
}
func TestCash(t *testing.T) {
path := filepath.Join(os.TempDir(), "chequebook-test.json")
backend := newTestBackend()
contr0, _ := deploy(key0, common.Big2, backend)
chbook, err := NewChequebook(path, contr0, key0, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
chbook.sent[addr1] = new(big.Int).SetUint64(42)
amount := common.Big1
chbook.balance = new(big.Int).Set(common.Big1)
ch, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
// cashing latest cheque
if _, err = chbox.Receive(ch); err != nil {
t.Fatalf("expected no error, got %v", err)
}
if _, err = ch.Cash(chbook.session); err != nil {
t.Fatal("Cash failed:", err)
}
backend.Commit()
chbook.balance = new(big.Int).Set(common.Big3)
ch0, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
ch1, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
interval := 10 * time.Millisecond
// setting autocash with interval of 10ms
chbox.AutoCash(interval, nil)
_, err = chbox.Receive(ch0)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
_, err = chbox.Receive(ch1)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
// after 3x interval time and 2 cheques received, exactly one cashing tx is sent
time.Sleep(4 * interval)
backend.Commit()
// after stopping autocash no more tx are sent
ch2, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
chbox.Stop()
_, err = chbox.Receive(ch2)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
time.Sleep(2 * interval)
backend.Commit()
// autocash below 1
chbook.balance = big.NewInt(2)
chbox.AutoCash(0, common.Big1)
ch3, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
ch4, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbox.Receive(ch3)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbox.Receive(ch4)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
// autochash on receipt when maxUncashed is 0
chbook.balance = new(big.Int).Set(common.Big2)
chbox.AutoCash(0, common.Big0)
ch5, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
ch6, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
_, err = chbox.Receive(ch5)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
_, err = chbox.Receive(ch6)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
backend.Commit()
}

View File

@ -1,367 +0,0 @@
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package contract
import (
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// ChequebookABI is the input ABI used to generate the binding from.
const ChequebookABI = "[{\"constant\":false,\"inputs\":[],\"name\":\"kill\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"sent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"beneficiary\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"sig_v\",\"type\":\"uint8\"},{\"name\":\"sig_r\",\"type\":\"bytes32\"},{\"name\":\"sig_s\",\"type\":\"bytes32\"}],\"name\":\"cash\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"deadbeat\",\"type\":\"address\"}],\"name\":\"Overdraft\",\"type\":\"event\"}]"
// ChequebookBin is the compiled bytecode used for deploying new contracts.
const ChequebookBin = `0x606060405260008054600160a060020a033316600160a060020a03199091161790556102ec806100306000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029`
// DeployChequebook deploys a new Ethereum contract, binding an instance of Chequebook to it.
func DeployChequebook(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Chequebook, error) {
parsed, err := abi.JSON(strings.NewReader(ChequebookABI))
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ChequebookBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
}
// Chequebook is an auto generated Go binding around an Ethereum contract.
type Chequebook struct {
ChequebookCaller // Read-only binding to the contract
ChequebookTransactor // Write-only binding to the contract
ChequebookFilterer // Log filterer for contract events
}
// ChequebookCaller is an auto generated read-only Go binding around an Ethereum contract.
type ChequebookCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ChequebookTransactor is an auto generated write-only Go binding around an Ethereum contract.
type ChequebookTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ChequebookFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type ChequebookFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ChequebookSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type ChequebookSession struct {
Contract *Chequebook // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// ChequebookCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type ChequebookCallerSession struct {
Contract *ChequebookCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// ChequebookTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type ChequebookTransactorSession struct {
Contract *ChequebookTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// ChequebookRaw is an auto generated low-level Go binding around an Ethereum contract.
type ChequebookRaw struct {
Contract *Chequebook // Generic contract binding to access the raw methods on
}
// ChequebookCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type ChequebookCallerRaw struct {
Contract *ChequebookCaller // Generic read-only contract binding to access the raw methods on
}
// ChequebookTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type ChequebookTransactorRaw struct {
Contract *ChequebookTransactor // Generic write-only contract binding to access the raw methods on
}
// NewChequebook creates a new instance of Chequebook, bound to a specific deployed contract.
func NewChequebook(address common.Address, backend bind.ContractBackend) (*Chequebook, error) {
contract, err := bindChequebook(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
}
// NewChequebookCaller creates a new read-only instance of Chequebook, bound to a specific deployed contract.
func NewChequebookCaller(address common.Address, caller bind.ContractCaller) (*ChequebookCaller, error) {
contract, err := bindChequebook(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &ChequebookCaller{contract: contract}, nil
}
// NewChequebookTransactor creates a new write-only instance of Chequebook, bound to a specific deployed contract.
func NewChequebookTransactor(address common.Address, transactor bind.ContractTransactor) (*ChequebookTransactor, error) {
contract, err := bindChequebook(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &ChequebookTransactor{contract: contract}, nil
}
// NewChequebookFilterer creates a new log filterer instance of Chequebook, bound to a specific deployed contract.
func NewChequebookFilterer(address common.Address, filterer bind.ContractFilterer) (*ChequebookFilterer, error) {
contract, err := bindChequebook(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &ChequebookFilterer{contract: contract}, nil
}
// bindChequebook binds a generic wrapper to an already deployed contract.
func bindChequebook(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(ChequebookABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Chequebook *ChequebookRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _Chequebook.Contract.ChequebookCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Chequebook *ChequebookRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Chequebook.Contract.ChequebookTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Chequebook *ChequebookRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Chequebook.Contract.ChequebookTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Chequebook *ChequebookCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _Chequebook.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Chequebook *ChequebookTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Chequebook.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Chequebook *ChequebookTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Chequebook.Contract.contract.Transact(opts, method, params...)
}
// Sent is a free data retrieval call binding the contract method 0x7bf786f8.
//
// Solidity: function sent( address) constant returns(uint256)
func (_Chequebook *ChequebookCaller) Sent(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) {
var (
ret0 = new(*big.Int)
)
out := ret0
err := _Chequebook.contract.Call(opts, out, "sent", arg0)
return *ret0, err
}
// Sent is a free data retrieval call binding the contract method 0x7bf786f8.
//
// Solidity: function sent( address) constant returns(uint256)
func (_Chequebook *ChequebookSession) Sent(arg0 common.Address) (*big.Int, error) {
return _Chequebook.Contract.Sent(&_Chequebook.CallOpts, arg0)
}
// Sent is a free data retrieval call binding the contract method 0x7bf786f8.
//
// Solidity: function sent( address) constant returns(uint256)
func (_Chequebook *ChequebookCallerSession) Sent(arg0 common.Address) (*big.Int, error) {
return _Chequebook.Contract.Sent(&_Chequebook.CallOpts, arg0)
}
// Cash is a paid mutator transaction binding the contract method 0xfbf788d6.
//
// Solidity: function cash(beneficiary address, amount uint256, sig_v uint8, sig_r bytes32, sig_s bytes32) returns()
func (_Chequebook *ChequebookTransactor) Cash(opts *bind.TransactOpts, beneficiary common.Address, amount *big.Int, sigV uint8, sigR [32]byte, sigS [32]byte) (*types.Transaction, error) {
return _Chequebook.contract.Transact(opts, "cash", beneficiary, amount, sigV, sigR, sigS)
}
// Cash is a paid mutator transaction binding the contract method 0xfbf788d6.
//
// Solidity: function cash(beneficiary address, amount uint256, sig_v uint8, sig_r bytes32, sig_s bytes32) returns()
func (_Chequebook *ChequebookSession) Cash(beneficiary common.Address, amount *big.Int, sigV uint8, sigR [32]byte, sigS [32]byte) (*types.Transaction, error) {
return _Chequebook.Contract.Cash(&_Chequebook.TransactOpts, beneficiary, amount, sigV, sigR, sigS)
}
// Cash is a paid mutator transaction binding the contract method 0xfbf788d6.
//
// Solidity: function cash(beneficiary address, amount uint256, sig_v uint8, sig_r bytes32, sig_s bytes32) returns()
func (_Chequebook *ChequebookTransactorSession) Cash(beneficiary common.Address, amount *big.Int, sigV uint8, sigR [32]byte, sigS [32]byte) (*types.Transaction, error) {
return _Chequebook.Contract.Cash(&_Chequebook.TransactOpts, beneficiary, amount, sigV, sigR, sigS)
}
// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
//
// Solidity: function kill() returns()
func (_Chequebook *ChequebookTransactor) Kill(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Chequebook.contract.Transact(opts, "kill")
}
// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
//
// Solidity: function kill() returns()
func (_Chequebook *ChequebookSession) Kill() (*types.Transaction, error) {
return _Chequebook.Contract.Kill(&_Chequebook.TransactOpts)
}
// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
//
// Solidity: function kill() returns()
func (_Chequebook *ChequebookTransactorSession) Kill() (*types.Transaction, error) {
return _Chequebook.Contract.Kill(&_Chequebook.TransactOpts)
}
// ChequebookOverdraftIterator is returned from FilterOverdraft and is used to iterate over the raw logs and unpacked data for Overdraft events raised by the Chequebook contract.
type ChequebookOverdraftIterator struct {
Event *ChequebookOverdraft // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ChequebookOverdraftIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ChequebookOverdraft)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ChequebookOverdraft)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error retruned any retrieval or parsing error occurred during filtering.
func (it *ChequebookOverdraftIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ChequebookOverdraftIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ChequebookOverdraft represents a Overdraft event raised by the Chequebook contract.
type ChequebookOverdraft struct {
Deadbeat common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterOverdraft is a free log retrieval operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
//
// Solidity: event Overdraft(deadbeat address)
func (_Chequebook *ChequebookFilterer) FilterOverdraft(opts *bind.FilterOpts) (*ChequebookOverdraftIterator, error) {
logs, sub, err := _Chequebook.contract.FilterLogs(opts, "Overdraft")
if err != nil {
return nil, err
}
return &ChequebookOverdraftIterator{contract: _Chequebook.contract, event: "Overdraft", logs: logs, sub: sub}, nil
}
// WatchOverdraft is a free log subscription operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
//
// Solidity: event Overdraft(deadbeat address)
func (_Chequebook *ChequebookFilterer) WatchOverdraft(opts *bind.WatchOpts, sink chan<- *ChequebookOverdraft) (event.Subscription, error) {
logs, sub, err := _Chequebook.contract.WatchLogs(opts, "Overdraft")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ChequebookOverdraft)
if err := _Chequebook.contract.UnpackLog(event, "Overdraft", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}

View File

@ -1,47 +0,0 @@
pragma solidity ^0.4.18;
import "./mortal.sol";
/// @title Chequebook for Ethereum micropayments
/// @author Daniel A. Nagy <daniel@ethereum.org>
contract chequebook is mortal {
// Cumulative paid amount in wei to each beneficiary
mapping (address => uint256) public sent;
/// @notice Overdraft event
event Overdraft(address deadbeat);
// Allow sending ether to the chequebook.
function() public payable { }
/// @notice Cash cheque
///
/// @param beneficiary beneficiary address
/// @param amount cumulative amount in wei
/// @param sig_v signature parameter v
/// @param sig_r signature parameter r
/// @param sig_s signature parameter s
/// The digital signature is calculated on the concatenated triplet of contract address, beneficiary address and cumulative amount
function cash(address beneficiary, uint256 amount, uint8 sig_v, bytes32 sig_r, bytes32 sig_s) public {
// Check if the cheque is old.
// Only cheques that are more recent than the last cashed one are considered.
require(amount > sent[beneficiary]);
// Check the digital signature of the cheque.
bytes32 hash = keccak256(address(this), beneficiary, amount);
require(owner == ecrecover(hash, sig_v, sig_r, sig_s));
// Attempt sending the difference between the cumulative amount on the cheque
// and the cumulative amount on the last cashed cheque to beneficiary.
uint256 diff = amount - sent[beneficiary];
if (diff <= this.balance) {
// update the cumulative amount before sending
sent[beneficiary] = amount;
beneficiary.transfer(diff);
} else {
// Upon failure, punish owner for writing a bounced cheque.
// owner.sendToDebtorsPrison();
Overdraft(owner);
// Compensate beneficiary.
selfdestruct(beneficiary);
}
}
}

View File

@ -1,5 +0,0 @@
package contract
// ContractDeployedCode is used to detect suicides. This constant needs to be
// updated when the contract code is changed.
const ContractDeployedCode = "0x6060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029"

View File

@ -1,10 +0,0 @@
pragma solidity ^0.4.0;
import "./owned.sol";
contract mortal is owned {
function kill() public {
if (msg.sender == owner)
selfdestruct(owner);
}
}

View File

@ -1,15 +0,0 @@
pragma solidity ^0.4.0;
contract owned {
address owner;
modifier onlyowner() {
if (msg.sender == owner) {
_;
}
}
function owned() public {
owner = msg.sender;
}
}

View File

@ -1,70 +0,0 @@
// Copyright 2016 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/>.
// +build none
// This program generates contract/code.go, which contains the chequebook code
// after deployment.
package main
import (
"fmt"
"io/ioutil"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/contracts/chequebook/contract"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
var (
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
testAlloc = core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(500000000000)},
}
)
func main() {
backend := backends.NewSimulatedBackend(testAlloc, uint64(100000000))
auth := bind.NewKeyedTransactor(testKey)
// Deploy the contract, get the code.
addr, _, _, err := contract.DeployChequebook(auth, backend)
if err != nil {
panic(err)
}
backend.Commit()
code, err := backend.CodeAt(nil, addr, nil)
if err != nil {
panic(err)
}
if len(code) == 0 {
panic("empty code")
}
// Write the output file.
content := fmt.Sprintf(`package contract
// ContractDeployedCode is used to detect suicides. This constant needs to be
// updated when the contract code is changed.
const ContractDeployedCode = "%#x"
`, code)
if err := ioutil.WriteFile("contract/code.go", []byte(content), 0644); err != nil {
panic(err)
}
}

View File

@ -1,30 +0,0 @@
# Swarm ENS interface
## Usage
Full documentation for the Ethereum Name Service [can be found as EIP 137](https://github.com/ethereum/EIPs/issues/137).
This package offers a simple binding that streamlines the registration of arbitrary UTF8 domain names to swarm content hashes.
## Development
The SOL file in contract subdirectory implements the ENS root registry, a simple
first-in, first-served registrar for the root namespace, and a simple resolver contract;
they're used in tests, and can be used to deploy these contracts for your own purposes.
The solidity source code can be found at [github.com/arachnid/ens/](https://github.com/arachnid/ens/).
The go bindings for ENS contracts are generated using `abigen` via the go generator:
```shell
go generate ./contracts/ens
```
## Fallback contract support
In order to better support content resolution on different service providers (such as Swarm and IPFS), [EIP-1577](https://eips.ethereum.org/EIPS/eip-1577)
was introduced and with it changes that allow applications to know _where_ content hashes are stored (i.e. if the
requested hash resides on Swarm or IPFS).
The code under `contracts/ens/contract` reflects the new Public Resolver changes and the code under `fallback_contract` allows
us to support the old contract resolution in cases where the ENS name owner did not update her Resolver contract, until the migration
period ends (date arbitrarily set to June 1st, 2019).

View File

@ -1,121 +0,0 @@
// Copyright 2016 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 ens
import (
"encoding/binary"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/common"
)
const (
cidv1 = 0x1
nsIpfs = 0xe3
nsSwarm = 0xe4
swarmTypecode = 0xfa // swarm manifest, see https://github.com/multiformats/multicodec/blob/master/table.csv
swarmHashtype = 0x1b // keccak256, see https://github.com/multiformats/multicodec/blob/master/table.csv
hashLength = 32
)
// deocodeEIP1577ContentHash decodes a chain-stored content hash from an ENS record according to EIP-1577
// a successful decode will result the different parts of the content hash in accordance to the CID spec
// Note: only CIDv1 is supported
func decodeEIP1577ContentHash(buf []byte) (storageNs, contentType, hashType, hashLength uint64, hash []byte, err error) {
if len(buf) < 10 {
return 0, 0, 0, 0, nil, errors.New("buffer too short")
}
storageNs, n := binary.Uvarint(buf)
buf = buf[n:]
vers, n := binary.Uvarint(buf)
if vers != 1 {
return 0, 0, 0, 0, nil, fmt.Errorf("expected cid v1, got: %d", vers)
}
buf = buf[n:]
contentType, n = binary.Uvarint(buf)
buf = buf[n:]
hashType, n = binary.Uvarint(buf)
buf = buf[n:]
hashLength, n = binary.Uvarint(buf)
hash = buf[n:]
if len(hash) != int(hashLength) {
return 0, 0, 0, 0, nil, errors.New("hash length mismatch")
}
return storageNs, contentType, hashType, hashLength, hash, nil
}
func extractContentHash(buf []byte) (common.Hash, error) {
storageNs, _ /*contentType*/, _ /* hashType*/, decodedHashLength, hashBytes, err := decodeEIP1577ContentHash(buf)
if err != nil {
return common.Hash{}, err
}
if storageNs != nsSwarm {
return common.Hash{}, errors.New("unknown storage system")
}
//todo: for the time being we implement loose enforcement for the EIP rules until ENS manager is updated
/*if contentType != swarmTypecode {
return common.Hash{}, errors.New("unknown content type")
}
if hashType != swarmHashtype {
return common.Hash{}, errors.New("unknown multihash type")
}*/
if decodedHashLength != hashLength {
return common.Hash{}, errors.New("odd hash length, swarm expects 32 bytes")
}
if len(hashBytes) != int(hashLength) {
return common.Hash{}, errors.New("hash length mismatch")
}
return common.BytesToHash(buf), nil
}
func EncodeSwarmHash(hash common.Hash) ([]byte, error) {
var cidBytes []byte
var headerBytes = []byte{
nsSwarm, //swarm namespace
cidv1, // CIDv1
swarmTypecode, // swarm hash
swarmHashtype, // keccak256 hash
hashLength, //hash length. 32 bytes
}
varintbuf := make([]byte, binary.MaxVarintLen64)
for _, v := range headerBytes {
n := binary.PutUvarint(varintbuf, uint64(v))
cidBytes = append(cidBytes, varintbuf[:n]...)
}
cidBytes = append(cidBytes, hash[:]...)
return cidBytes, nil
}

View File

@ -1,158 +0,0 @@
// Copyright 2016 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 ens
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"testing"
"github.com/ethereum/go-ethereum/common"
)
// Tests for the decoding of the example ENS
func TestEIPSpecCidDecode(t *testing.T) {
const (
eipSpecHash = "e3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
eipHash = "29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
dagPb = 0x70
sha2256 = 0x12
)
b, err := hex.DecodeString(eipSpecHash)
if err != nil {
t.Fatal(err)
}
hashBytes, err := hex.DecodeString(eipHash)
if err != nil {
t.Fatal(err)
}
storageNs, contentType, hashType, hashLength, decodedHashBytes, err := decodeEIP1577ContentHash(b)
if err != nil {
t.Fatal(err)
}
if storageNs != nsIpfs {
t.Fatal("wrong ns")
}
if contentType != dagPb {
t.Fatal("should be ipfs typecode")
}
if hashType != sha2256 {
t.Fatal("should be sha2-256")
}
if hashLength != 32 {
t.Fatal("should be 32")
}
if !bytes.Equal(hashBytes, decodedHashBytes) {
t.Fatal("should be equal")
}
}
func TestManualCidDecode(t *testing.T) {
// call cid encode method with hash. expect byte slice returned, compare according to spec
for _, v := range []struct {
name string
headerBytes []byte
wantErr bool
}{
{
name: "values correct, should not fail",
headerBytes: []byte{0xe4, 0x01, 0xfa, 0x1b, 0x20},
wantErr: false,
},
{
name: "cid version wrong, should fail",
headerBytes: []byte{0xe4, 0x00, 0xfa, 0x1b, 0x20},
wantErr: true,
},
{
name: "hash length wrong, should fail",
headerBytes: []byte{0xe4, 0x01, 0xfa, 0x1b, 0x1f},
wantErr: true,
},
{
name: "values correct for ipfs, should fail",
headerBytes: []byte{0xe3, 0x01, 0x70, 0x12, 0x20},
wantErr: true,
},
{
name: "loose values for swarm, todo remove, should not fail",
headerBytes: []byte{0xe4, 0x01, 0x70, 0x12, 0x20},
wantErr: false,
},
{
name: "loose values for swarm, todo remove, should not fail",
headerBytes: []byte{0xe4, 0x01, 0x99, 0x99, 0x20},
wantErr: false,
},
} {
t.Run(v.name, func(t *testing.T) {
const eipHash = "29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
var bb []byte
buf := make([]byte, binary.MaxVarintLen64)
for _, vv := range v.headerBytes {
n := binary.PutUvarint(buf, uint64(vv))
bb = append(bb, buf[:n]...)
}
h := common.HexToHash(eipHash)
bb = append(bb, h[:]...)
str := hex.EncodeToString(bb)
fmt.Println(str)
decodedHash, e := extractContentHash(bb)
switch v.wantErr {
case true:
if e == nil {
t.Fatal("the decode should fail")
}
case false:
if e != nil {
t.Fatalf("the deccode shouldnt fail: %v", e)
}
if !bytes.Equal(decodedHash[:], h[:]) {
t.Fatal("hashes not equal")
}
}
})
}
}
func TestManuelCidEncode(t *testing.T) {
// call cid encode method with hash. expect byte slice returned, compare according to spec
const eipHash = "29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f"
cidBytes, err := EncodeSwarmHash(common.HexToHash(eipHash))
if err != nil {
t.Fatal(err)
}
// logic in extractContentHash is unit tested thoroughly
// hence we just check that the returned hash is equal
h, err := extractContentHash(cidBytes)
if err != nil {
t.Fatal(err)
}
if bytes.Equal(h[:], cidBytes) {
t.Fatal("should be equal")
}
}

View File

@ -1,26 +0,0 @@
pragma solidity >=0.4.24;
interface ENS {
// Logged when the owner of a node assigns a new owner to a subnode.
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
// Logged when the owner of a node transfers ownership to a new account.
event Transfer(bytes32 indexed node, address owner);
// Logged when the resolver for a node changes.
event NewResolver(bytes32 indexed node, address resolver);
// Logged when the TTL of a node changes
event NewTTL(bytes32 indexed node, uint64 ttl);
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external;
function setResolver(bytes32 node, address resolver) external;
function setOwner(bytes32 node, address owner) external;
function setTTL(bytes32 node, uint64 ttl) external;
function owner(bytes32 node) external view returns (address);
function resolver(bytes32 node) external view returns (address);
function ttl(bytes32 node) external view returns (uint64);
}

View File

@ -1,99 +0,0 @@
pragma solidity ^0.5.0;
import "./ENS.sol";
/**
* The ENS registry contract.
*/
contract ENSRegistry is ENS {
struct Record {
address owner;
address resolver;
uint64 ttl;
}
mapping (bytes32 => Record) records;
// Permits modifications only by the owner of the specified node.
modifier only_owner(bytes32 node) {
require(records[node].owner == msg.sender);
_;
}
/**
* @dev Constructs a new ENS registrar.
*/
constructor() public {
records[0x0].owner = msg.sender;
}
/**
* @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.
* @param node The node to transfer ownership of.
* @param owner The address of the new owner.
*/
function setOwner(bytes32 node, address owner) external only_owner(node) {
emit Transfer(node, owner);
records[node].owner = owner;
}
/**
* @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.
* @param node The parent node.
* @param label The hash of the label specifying the subnode.
* @param owner The address of the new owner.
*/
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external only_owner(node) {
bytes32 subnode = keccak256(abi.encodePacked(node, label));
emit NewOwner(node, label, owner);
records[subnode].owner = owner;
}
/**
* @dev Sets the resolver address for the specified node.
* @param node The node to update.
* @param resolver The address of the resolver.
*/
function setResolver(bytes32 node, address resolver) external only_owner(node) {
emit NewResolver(node, resolver);
records[node].resolver = resolver;
}
/**
* @dev Sets the TTL for the specified node.
* @param node The node to update.
* @param ttl The TTL in seconds.
*/
function setTTL(bytes32 node, uint64 ttl) external only_owner(node) {
emit NewTTL(node, ttl);
records[node].ttl = ttl;
}
/**
* @dev Returns the address that owns the specified node.
* @param node The specified node.
* @return address of the owner.
*/
function owner(bytes32 node) external view returns (address) {
return records[node].owner;
}
/**
* @dev Returns the address of the resolver for the specified node.
* @param node The specified node.
* @return address of the resolver.
*/
function resolver(bytes32 node) external view returns (address) {
return records[node].resolver;
}
/**
* @dev Returns the TTL of a node, and any records associated with it.
* @param node The specified node.
* @return ttl of the node.
*/
function ttl(bytes32 node) external view returns (uint64) {
return records[node].ttl;
}
}

View File

@ -1,36 +0,0 @@
pragma solidity ^0.5.0;
import "./ENS.sol";
/**
* A registrar that allocates subdomains to the first person to claim them.
*/
contract FIFSRegistrar {
ENS ens;
bytes32 rootNode;
modifier only_owner(bytes32 label) {
address currentOwner = ens.owner(keccak256(abi.encodePacked(rootNode, label)));
require(currentOwner == address(0x0) || currentOwner == msg.sender);
_;
}
/**
* Constructor.
* @param ensAddr The address of the ENS registry.
* @param node The node that this registrar administers.
*/
constructor(ENS ensAddr, bytes32 node) public {
ens = ensAddr;
rootNode = node;
}
/**
* Register a name, or change the owner of an existing registration.
* @param label The hash of the label to register.
* @param owner The address of the new owner.
*/
function register(bytes32 label, address owner) public only_owner(label) {
ens.setSubnodeOwner(rootNode, label, owner);
}
}

View File

@ -1,212 +0,0 @@
pragma solidity >=0.4.25;
import "./ENS.sol";
/**
* A simple resolver anyone can use; only allows the owner of a node to set its
* address.
*/
contract PublicResolver {
bytes4 constant INTERFACE_META_ID = 0x01ffc9a7;
bytes4 constant ADDR_INTERFACE_ID = 0x3b3b57de;
bytes4 constant NAME_INTERFACE_ID = 0x691f3431;
bytes4 constant ABI_INTERFACE_ID = 0x2203ab56;
bytes4 constant PUBKEY_INTERFACE_ID = 0xc8690233;
bytes4 constant TEXT_INTERFACE_ID = 0x59d1d43c;
bytes4 constant CONTENTHASH_INTERFACE_ID = 0xbc1c58d1;
event AddrChanged(bytes32 indexed node, address a);
event NameChanged(bytes32 indexed node, string name);
event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
event TextChanged(bytes32 indexed node, string indexedKey, string key);
event ContenthashChanged(bytes32 indexed node, bytes hash);
struct PublicKey {
bytes32 x;
bytes32 y;
}
struct Record {
address addr;
string name;
PublicKey pubkey;
mapping(string=>string) text;
mapping(uint256=>bytes) abis;
bytes contenthash;
}
ENS ens;
mapping (bytes32 => Record) records;
modifier onlyOwner(bytes32 node) {
require(ens.owner(node) == msg.sender);
_;
}
/**
* Constructor.
* @param ensAddr The ENS registrar contract.
*/
constructor(ENS ensAddr) public {
ens = ensAddr;
}
/**
* Sets the address associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param addr The address to set.
*/
function setAddr(bytes32 node, address addr) external onlyOwner(node) {
records[node].addr = addr;
emit AddrChanged(node, addr);
}
/**
* Sets the contenthash associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param hash The contenthash to set
*/
function setContenthash(bytes32 node, bytes calldata hash) external onlyOwner(node) {
records[node].contenthash = hash;
emit ContenthashChanged(node, hash);
}
/**
* Sets the name associated with an ENS node, for reverse records.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param name The name to set.
*/
function setName(bytes32 node, string calldata name) external onlyOwner(node) {
records[node].name = name;
emit NameChanged(node, name);
}
/**
* Sets the ABI associated with an ENS node.
* Nodes may have one ABI of each content type. To remove an ABI, set it to
* the empty string.
* @param node The node to update.
* @param contentType The content type of the ABI
* @param data The ABI data.
*/
function setABI(bytes32 node, uint256 contentType, bytes calldata data) external onlyOwner(node) {
// Content types must be powers of 2
require(((contentType - 1) & contentType) == 0);
records[node].abis[contentType] = data;
emit ABIChanged(node, contentType);
}
/**
* Sets the SECP256k1 public key associated with an ENS node.
* @param node The ENS node to query
* @param x the X coordinate of the curve point for the public key.
* @param y the Y coordinate of the curve point for the public key.
*/
function setPubkey(bytes32 node, bytes32 x, bytes32 y) external onlyOwner(node) {
records[node].pubkey = PublicKey(x, y);
emit PubkeyChanged(node, x, y);
}
/**
* Sets the text data associated with an ENS node and key.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param key The key to set.
* @param value The text data value to set.
*/
function setText(bytes32 node, string calldata key, string calldata value) external onlyOwner(node) {
records[node].text[key] = value;
emit TextChanged(node, key, key);
}
/**
* Returns the text data associated with an ENS node and key.
* @param node The ENS node to query.
* @param key The text data key to query.
* @return The associated text data.
*/
function text(bytes32 node, string calldata key) external view returns (string memory) {
return records[node].text[key];
}
/**
* Returns the SECP256k1 public key associated with an ENS node.
* Defined in EIP 619.
* @param node The ENS node to query
* @return x, y the X and Y coordinates of the curve point for the public key.
*/
function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) {
return (records[node].pubkey.x, records[node].pubkey.y);
}
/**
* Returns the ABI associated with an ENS node.
* Defined in EIP205.
* @param node The ENS node to query
* @param contentTypes A bitwise OR of the ABI formats accepted by the caller.
* @return contentType The content type of the return value
* @return data The ABI data
*/
function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory) {
Record storage record = records[node];
for (uint256 contentType = 1; contentType <= contentTypes; contentType <<= 1) {
if ((contentType & contentTypes) != 0 && record.abis[contentType].length > 0) {
return (contentType, record.abis[contentType]);
}
}
bytes memory empty;
return (0, empty);
}
/**
* Returns the name associated with an ENS node, for reverse records.
* Defined in EIP181.
* @param node The ENS node to query.
* @return The associated name.
*/
function name(bytes32 node) external view returns (string memory) {
return records[node].name;
}
/**
* Returns the address associated with an ENS node.
* @param node The ENS node to query.
* @return The associated address.
*/
function addr(bytes32 node) external view returns (address) {
return records[node].addr;
}
/**
* Returns the contenthash associated with an ENS node.
* @param node The ENS node to query.
* @return The associated contenthash.
*/
function contenthash(bytes32 node) external view returns (bytes memory) {
return records[node].contenthash;
}
/**
* Returns true if the resolver implements the interface specified by the provided hash.
* @param interfaceID The ID of the interface to check for.
* @return True if the contract implements the requested interface.
*/
function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
return interfaceID == ADDR_INTERFACE_ID ||
interfaceID == NAME_INTERFACE_ID ||
interfaceID == ABI_INTERFACE_ID ||
interfaceID == PUBKEY_INTERFACE_ID ||
interfaceID == TEXT_INTERFACE_ID ||
interfaceID == CONTENTHASH_INTERFACE_ID ||
interfaceID == INTERFACE_META_ID;
}
}

View File

@ -1,892 +0,0 @@
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package contract
import (
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = abi.U256
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// ENSABI is the input ABI used to generate the binding from.
const ENSABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"label\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setSubnodeOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"setTTL\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ttl\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"label\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NewOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"NewResolver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"NewTTL\",\"type\":\"event\"}]"
// ENSBin is the compiled bytecode used for deploying new contracts.
const ENSBin = `0x`
// DeployENS deploys a new Ethereum contract, binding an instance of ENS to it.
func DeployENS(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ENS, error) {
parsed, err := abi.JSON(strings.NewReader(ENSABI))
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ENSBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}, ENSFilterer: ENSFilterer{contract: contract}}, nil
}
// ENS is an auto generated Go binding around an Ethereum contract.
type ENS struct {
ENSCaller // Read-only binding to the contract
ENSTransactor // Write-only binding to the contract
ENSFilterer // Log filterer for contract events
}
// ENSCaller is an auto generated read-only Go binding around an Ethereum contract.
type ENSCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ENSTransactor is an auto generated write-only Go binding around an Ethereum contract.
type ENSTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ENSFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type ENSFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ENSSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type ENSSession struct {
Contract *ENS // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// ENSCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type ENSCallerSession struct {
Contract *ENSCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// ENSTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type ENSTransactorSession struct {
Contract *ENSTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// ENSRaw is an auto generated low-level Go binding around an Ethereum contract.
type ENSRaw struct {
Contract *ENS // Generic contract binding to access the raw methods on
}
// ENSCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type ENSCallerRaw struct {
Contract *ENSCaller // Generic read-only contract binding to access the raw methods on
}
// ENSTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type ENSTransactorRaw struct {
Contract *ENSTransactor // Generic write-only contract binding to access the raw methods on
}
// NewENS creates a new instance of ENS, bound to a specific deployed contract.
func NewENS(address common.Address, backend bind.ContractBackend) (*ENS, error) {
contract, err := bindENS(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}, ENSFilterer: ENSFilterer{contract: contract}}, nil
}
// NewENSCaller creates a new read-only instance of ENS, bound to a specific deployed contract.
func NewENSCaller(address common.Address, caller bind.ContractCaller) (*ENSCaller, error) {
contract, err := bindENS(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &ENSCaller{contract: contract}, nil
}
// NewENSTransactor creates a new write-only instance of ENS, bound to a specific deployed contract.
func NewENSTransactor(address common.Address, transactor bind.ContractTransactor) (*ENSTransactor, error) {
contract, err := bindENS(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &ENSTransactor{contract: contract}, nil
}
// NewENSFilterer creates a new log filterer instance of ENS, bound to a specific deployed contract.
func NewENSFilterer(address common.Address, filterer bind.ContractFilterer) (*ENSFilterer, error) {
contract, err := bindENS(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &ENSFilterer{contract: contract}, nil
}
// bindENS binds a generic wrapper to an already deployed contract.
func bindENS(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(ENSABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_ENS *ENSRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _ENS.Contract.ENSCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_ENS *ENSRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _ENS.Contract.ENSTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_ENS *ENSRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _ENS.Contract.ENSTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_ENS *ENSCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _ENS.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_ENS *ENSTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _ENS.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_ENS *ENSTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _ENS.Contract.contract.Transact(opts, method, params...)
}
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(bytes32 node) constant returns(address)
func (_ENS *ENSCaller) Owner(opts *bind.CallOpts, node [32]byte) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _ENS.contract.Call(opts, out, "owner", node)
return *ret0, err
}
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(bytes32 node) constant returns(address)
func (_ENS *ENSSession) Owner(node [32]byte) (common.Address, error) {
return _ENS.Contract.Owner(&_ENS.CallOpts, node)
}
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(bytes32 node) constant returns(address)
func (_ENS *ENSCallerSession) Owner(node [32]byte) (common.Address, error) {
return _ENS.Contract.Owner(&_ENS.CallOpts, node)
}
// Resolver is a free data retrieval call binding the contract method 0x0178b8bf.
//
// Solidity: function resolver(bytes32 node) constant returns(address)
func (_ENS *ENSCaller) Resolver(opts *bind.CallOpts, node [32]byte) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _ENS.contract.Call(opts, out, "resolver", node)
return *ret0, err
}
// Resolver is a free data retrieval call binding the contract method 0x0178b8bf.
//
// Solidity: function resolver(bytes32 node) constant returns(address)
func (_ENS *ENSSession) Resolver(node [32]byte) (common.Address, error) {
return _ENS.Contract.Resolver(&_ENS.CallOpts, node)
}
// Resolver is a free data retrieval call binding the contract method 0x0178b8bf.
//
// Solidity: function resolver(bytes32 node) constant returns(address)
func (_ENS *ENSCallerSession) Resolver(node [32]byte) (common.Address, error) {
return _ENS.Contract.Resolver(&_ENS.CallOpts, node)
}
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(bytes32 node) constant returns(uint64)
func (_ENS *ENSCaller) Ttl(opts *bind.CallOpts, node [32]byte) (uint64, error) {
var (
ret0 = new(uint64)
)
out := ret0
err := _ENS.contract.Call(opts, out, "ttl", node)
return *ret0, err
}
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(bytes32 node) constant returns(uint64)
func (_ENS *ENSSession) Ttl(node [32]byte) (uint64, error) {
return _ENS.Contract.Ttl(&_ENS.CallOpts, node)
}
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(bytes32 node) constant returns(uint64)
func (_ENS *ENSCallerSession) Ttl(node [32]byte) (uint64, error) {
return _ENS.Contract.Ttl(&_ENS.CallOpts, node)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(bytes32 node, address owner) returns()
func (_ENS *ENSTransactor) SetOwner(opts *bind.TransactOpts, node [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENS.contract.Transact(opts, "setOwner", node, owner)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(bytes32 node, address owner) returns()
func (_ENS *ENSSession) SetOwner(node [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENS.Contract.SetOwner(&_ENS.TransactOpts, node, owner)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(bytes32 node, address owner) returns()
func (_ENS *ENSTransactorSession) SetOwner(node [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENS.Contract.SetOwner(&_ENS.TransactOpts, node, owner)
}
// SetResolver is a paid mutator transaction binding the contract method 0x1896f70a.
//
// Solidity: function setResolver(bytes32 node, address resolver) returns()
func (_ENS *ENSTransactor) SetResolver(opts *bind.TransactOpts, node [32]byte, resolver common.Address) (*types.Transaction, error) {
return _ENS.contract.Transact(opts, "setResolver", node, resolver)
}
// SetResolver is a paid mutator transaction binding the contract method 0x1896f70a.
//
// Solidity: function setResolver(bytes32 node, address resolver) returns()
func (_ENS *ENSSession) SetResolver(node [32]byte, resolver common.Address) (*types.Transaction, error) {
return _ENS.Contract.SetResolver(&_ENS.TransactOpts, node, resolver)
}
// SetResolver is a paid mutator transaction binding the contract method 0x1896f70a.
//
// Solidity: function setResolver(bytes32 node, address resolver) returns()
func (_ENS *ENSTransactorSession) SetResolver(node [32]byte, resolver common.Address) (*types.Transaction, error) {
return _ENS.Contract.SetResolver(&_ENS.TransactOpts, node, resolver)
}
// SetSubnodeOwner is a paid mutator transaction binding the contract method 0x06ab5923.
//
// Solidity: function setSubnodeOwner(bytes32 node, bytes32 label, address owner) returns()
func (_ENS *ENSTransactor) SetSubnodeOwner(opts *bind.TransactOpts, node [32]byte, label [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENS.contract.Transact(opts, "setSubnodeOwner", node, label, owner)
}
// SetSubnodeOwner is a paid mutator transaction binding the contract method 0x06ab5923.
//
// Solidity: function setSubnodeOwner(bytes32 node, bytes32 label, address owner) returns()
func (_ENS *ENSSession) SetSubnodeOwner(node [32]byte, label [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENS.Contract.SetSubnodeOwner(&_ENS.TransactOpts, node, label, owner)
}
// SetSubnodeOwner is a paid mutator transaction binding the contract method 0x06ab5923.
//
// Solidity: function setSubnodeOwner(bytes32 node, bytes32 label, address owner) returns()
func (_ENS *ENSTransactorSession) SetSubnodeOwner(node [32]byte, label [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENS.Contract.SetSubnodeOwner(&_ENS.TransactOpts, node, label, owner)
}
// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
//
// Solidity: function setTTL(bytes32 node, uint64 ttl) returns()
func (_ENS *ENSTransactor) SetTTL(opts *bind.TransactOpts, node [32]byte, ttl uint64) (*types.Transaction, error) {
return _ENS.contract.Transact(opts, "setTTL", node, ttl)
}
// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
//
// Solidity: function setTTL(bytes32 node, uint64 ttl) returns()
func (_ENS *ENSSession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, error) {
return _ENS.Contract.SetTTL(&_ENS.TransactOpts, node, ttl)
}
// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
//
// Solidity: function setTTL(bytes32 node, uint64 ttl) returns()
func (_ENS *ENSTransactorSession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, error) {
return _ENS.Contract.SetTTL(&_ENS.TransactOpts, node, ttl)
}
// ENSNewOwnerIterator is returned from FilterNewOwner and is used to iterate over the raw logs and unpacked data for NewOwner events raised by the ENS contract.
type ENSNewOwnerIterator struct {
Event *ENSNewOwner // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSNewOwnerIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSNewOwner)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSNewOwner)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSNewOwnerIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSNewOwnerIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSNewOwner represents a NewOwner event raised by the ENS contract.
type ENSNewOwner struct {
Node [32]byte
Label [32]byte
Owner common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewOwner is a free log retrieval operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
//
// Solidity: event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner)
func (_ENS *ENSFilterer) FilterNewOwner(opts *bind.FilterOpts, node [][32]byte, label [][32]byte) (*ENSNewOwnerIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
var labelRule []interface{}
for _, labelItem := range label {
labelRule = append(labelRule, labelItem)
}
logs, sub, err := _ENS.contract.FilterLogs(opts, "NewOwner", nodeRule, labelRule)
if err != nil {
return nil, err
}
return &ENSNewOwnerIterator{contract: _ENS.contract, event: "NewOwner", logs: logs, sub: sub}, nil
}
// WatchNewOwner is a free log subscription operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
//
// Solidity: event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner)
func (_ENS *ENSFilterer) WatchNewOwner(opts *bind.WatchOpts, sink chan<- *ENSNewOwner, node [][32]byte, label [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
var labelRule []interface{}
for _, labelItem := range label {
labelRule = append(labelRule, labelItem)
}
logs, sub, err := _ENS.contract.WatchLogs(opts, "NewOwner", nodeRule, labelRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSNewOwner)
if err := _ENS.contract.UnpackLog(event, "NewOwner", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ENSNewResolverIterator is returned from FilterNewResolver and is used to iterate over the raw logs and unpacked data for NewResolver events raised by the ENS contract.
type ENSNewResolverIterator struct {
Event *ENSNewResolver // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSNewResolverIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSNewResolver)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSNewResolver)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSNewResolverIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSNewResolverIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSNewResolver represents a NewResolver event raised by the ENS contract.
type ENSNewResolver struct {
Node [32]byte
Resolver common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewResolver is a free log retrieval operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
// Solidity: event NewResolver(bytes32 indexed node, address resolver)
func (_ENS *ENSFilterer) FilterNewResolver(opts *bind.FilterOpts, node [][32]byte) (*ENSNewResolverIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENS.contract.FilterLogs(opts, "NewResolver", nodeRule)
if err != nil {
return nil, err
}
return &ENSNewResolverIterator{contract: _ENS.contract, event: "NewResolver", logs: logs, sub: sub}, nil
}
// WatchNewResolver is a free log subscription operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
// Solidity: event NewResolver(bytes32 indexed node, address resolver)
func (_ENS *ENSFilterer) WatchNewResolver(opts *bind.WatchOpts, sink chan<- *ENSNewResolver, node [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENS.contract.WatchLogs(opts, "NewResolver", nodeRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSNewResolver)
if err := _ENS.contract.UnpackLog(event, "NewResolver", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ENSNewTTLIterator is returned from FilterNewTTL and is used to iterate over the raw logs and unpacked data for NewTTL events raised by the ENS contract.
type ENSNewTTLIterator struct {
Event *ENSNewTTL // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSNewTTLIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSNewTTL)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSNewTTL)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSNewTTLIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSNewTTLIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSNewTTL represents a NewTTL event raised by the ENS contract.
type ENSNewTTL struct {
Node [32]byte
Ttl uint64
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewTTL is a free log retrieval operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
//
// Solidity: event NewTTL(bytes32 indexed node, uint64 ttl)
func (_ENS *ENSFilterer) FilterNewTTL(opts *bind.FilterOpts, node [][32]byte) (*ENSNewTTLIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENS.contract.FilterLogs(opts, "NewTTL", nodeRule)
if err != nil {
return nil, err
}
return &ENSNewTTLIterator{contract: _ENS.contract, event: "NewTTL", logs: logs, sub: sub}, nil
}
// WatchNewTTL is a free log subscription operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
//
// Solidity: event NewTTL(bytes32 indexed node, uint64 ttl)
func (_ENS *ENSFilterer) WatchNewTTL(opts *bind.WatchOpts, sink chan<- *ENSNewTTL, node [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENS.contract.WatchLogs(opts, "NewTTL", nodeRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSNewTTL)
if err := _ENS.contract.UnpackLog(event, "NewTTL", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ENSTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the ENS contract.
type ENSTransferIterator struct {
Event *ENSTransfer // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSTransferIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSTransfer)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSTransfer)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSTransferIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSTransferIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSTransfer represents a Transfer event raised by the ENS contract.
type ENSTransfer struct {
Node [32]byte
Owner common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterTransfer is a free log retrieval operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
// Solidity: event Transfer(bytes32 indexed node, address owner)
func (_ENS *ENSFilterer) FilterTransfer(opts *bind.FilterOpts, node [][32]byte) (*ENSTransferIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENS.contract.FilterLogs(opts, "Transfer", nodeRule)
if err != nil {
return nil, err
}
return &ENSTransferIterator{contract: _ENS.contract, event: "Transfer", logs: logs, sub: sub}, nil
}
// WatchTransfer is a free log subscription operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
// Solidity: event Transfer(bytes32 indexed node, address owner)
func (_ENS *ENSFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ENSTransfer, node [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENS.contract.WatchLogs(opts, "Transfer", nodeRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSTransfer)
if err := _ENS.contract.UnpackLog(event, "Transfer", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}

View File

@ -1,892 +0,0 @@
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package contract
import (
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = abi.U256
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// ENSRegistryABI is the input ABI used to generate the binding from.
const ENSRegistryABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"label\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setSubnodeOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"setTTL\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ttl\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"label\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NewOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"NewResolver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"NewTTL\",\"type\":\"event\"}]"
// ENSRegistryBin is the compiled bytecode used for deploying new contracts.
const ENSRegistryBin = `0x608060405234801561001057600080fd5b5060008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a0319163317905561059d806100596000396000f3fe6080604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178b8bf811461008757806302571be3146100cd57806306ab5923146100f757806314ab90381461013857806316a25cbd146101725780631896f70a146101b95780635b0fc9c3146101f2575b600080fd5b34801561009357600080fd5b506100b1600480360360208110156100aa57600080fd5b503561022b565b60408051600160a060020a039092168252519081900360200190f35b3480156100d957600080fd5b506100b1600480360360208110156100f057600080fd5b5035610249565b34801561010357600080fd5b506101366004803603606081101561011a57600080fd5b5080359060208101359060400135600160a060020a0316610264565b005b34801561014457600080fd5b506101366004803603604081101561015b57600080fd5b508035906020013567ffffffffffffffff1661032e565b34801561017e57600080fd5b5061019c6004803603602081101561019557600080fd5b50356103f7565b6040805167ffffffffffffffff9092168252519081900360200190f35b3480156101c557600080fd5b50610136600480360360408110156101dc57600080fd5b5080359060200135600160a060020a031661042e565b3480156101fe57600080fd5b506101366004803603604081101561021557600080fd5b5080359060200135600160a060020a03166104d1565b600090815260208190526040902060010154600160a060020a031690565b600090815260208190526040902054600160a060020a031690565b6000838152602081905260409020548390600160a060020a0316331461028957600080fd5b6040805160208082018790528183018690528251808303840181526060830180855281519190920120600160a060020a0386169091529151859187917fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e829181900360800190a36000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039390931692909217909155505050565b6000828152602081905260409020548290600160a060020a0316331461035357600080fd5b6040805167ffffffffffffffff84168152905184917f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68919081900360200190a250600091825260208290526040909120600101805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60009081526020819052604090206001015474010000000000000000000000000000000000000000900467ffffffffffffffff1690565b6000828152602081905260409020548290600160a060020a0316331461045357600080fd5b60408051600160a060020a0384168152905184917f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0919081900360200190a250600091825260208290526040909120600101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b6000828152602081905260409020548290600160a060020a031633146104f657600080fd5b60408051600160a060020a0384168152905184917fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266919081900360200190a250600091825260208290526040909120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0390921691909117905556fea165627a7a723058208be97eda88107945616fbd44aa4f2f1ce188b1a930a4bc5f8e1fb7924395d1650029`
// DeployENSRegistry deploys a new Ethereum contract, binding an instance of ENSRegistry to it.
func DeployENSRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ENSRegistry, error) {
parsed, err := abi.JSON(strings.NewReader(ENSRegistryABI))
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ENSRegistryBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &ENSRegistry{ENSRegistryCaller: ENSRegistryCaller{contract: contract}, ENSRegistryTransactor: ENSRegistryTransactor{contract: contract}, ENSRegistryFilterer: ENSRegistryFilterer{contract: contract}}, nil
}
// ENSRegistry is an auto generated Go binding around an Ethereum contract.
type ENSRegistry struct {
ENSRegistryCaller // Read-only binding to the contract
ENSRegistryTransactor // Write-only binding to the contract
ENSRegistryFilterer // Log filterer for contract events
}
// ENSRegistryCaller is an auto generated read-only Go binding around an Ethereum contract.
type ENSRegistryCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ENSRegistryTransactor is an auto generated write-only Go binding around an Ethereum contract.
type ENSRegistryTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ENSRegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type ENSRegistryFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// ENSRegistrySession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type ENSRegistrySession struct {
Contract *ENSRegistry // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// ENSRegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type ENSRegistryCallerSession struct {
Contract *ENSRegistryCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// ENSRegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type ENSRegistryTransactorSession struct {
Contract *ENSRegistryTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// ENSRegistryRaw is an auto generated low-level Go binding around an Ethereum contract.
type ENSRegistryRaw struct {
Contract *ENSRegistry // Generic contract binding to access the raw methods on
}
// ENSRegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type ENSRegistryCallerRaw struct {
Contract *ENSRegistryCaller // Generic read-only contract binding to access the raw methods on
}
// ENSRegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type ENSRegistryTransactorRaw struct {
Contract *ENSRegistryTransactor // Generic write-only contract binding to access the raw methods on
}
// NewENSRegistry creates a new instance of ENSRegistry, bound to a specific deployed contract.
func NewENSRegistry(address common.Address, backend bind.ContractBackend) (*ENSRegistry, error) {
contract, err := bindENSRegistry(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &ENSRegistry{ENSRegistryCaller: ENSRegistryCaller{contract: contract}, ENSRegistryTransactor: ENSRegistryTransactor{contract: contract}, ENSRegistryFilterer: ENSRegistryFilterer{contract: contract}}, nil
}
// NewENSRegistryCaller creates a new read-only instance of ENSRegistry, bound to a specific deployed contract.
func NewENSRegistryCaller(address common.Address, caller bind.ContractCaller) (*ENSRegistryCaller, error) {
contract, err := bindENSRegistry(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &ENSRegistryCaller{contract: contract}, nil
}
// NewENSRegistryTransactor creates a new write-only instance of ENSRegistry, bound to a specific deployed contract.
func NewENSRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*ENSRegistryTransactor, error) {
contract, err := bindENSRegistry(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &ENSRegistryTransactor{contract: contract}, nil
}
// NewENSRegistryFilterer creates a new log filterer instance of ENSRegistry, bound to a specific deployed contract.
func NewENSRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*ENSRegistryFilterer, error) {
contract, err := bindENSRegistry(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &ENSRegistryFilterer{contract: contract}, nil
}
// bindENSRegistry binds a generic wrapper to an already deployed contract.
func bindENSRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(ENSRegistryABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_ENSRegistry *ENSRegistryRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _ENSRegistry.Contract.ENSRegistryCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_ENSRegistry *ENSRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _ENSRegistry.Contract.ENSRegistryTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_ENSRegistry *ENSRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _ENSRegistry.Contract.ENSRegistryTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_ENSRegistry *ENSRegistryCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _ENSRegistry.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_ENSRegistry *ENSRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _ENSRegistry.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_ENSRegistry *ENSRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _ENSRegistry.Contract.contract.Transact(opts, method, params...)
}
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(bytes32 node) constant returns(address)
func (_ENSRegistry *ENSRegistryCaller) Owner(opts *bind.CallOpts, node [32]byte) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _ENSRegistry.contract.Call(opts, out, "owner", node)
return *ret0, err
}
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(bytes32 node) constant returns(address)
func (_ENSRegistry *ENSRegistrySession) Owner(node [32]byte) (common.Address, error) {
return _ENSRegistry.Contract.Owner(&_ENSRegistry.CallOpts, node)
}
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(bytes32 node) constant returns(address)
func (_ENSRegistry *ENSRegistryCallerSession) Owner(node [32]byte) (common.Address, error) {
return _ENSRegistry.Contract.Owner(&_ENSRegistry.CallOpts, node)
}
// Resolver is a free data retrieval call binding the contract method 0x0178b8bf.
//
// Solidity: function resolver(bytes32 node) constant returns(address)
func (_ENSRegistry *ENSRegistryCaller) Resolver(opts *bind.CallOpts, node [32]byte) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _ENSRegistry.contract.Call(opts, out, "resolver", node)
return *ret0, err
}
// Resolver is a free data retrieval call binding the contract method 0x0178b8bf.
//
// Solidity: function resolver(bytes32 node) constant returns(address)
func (_ENSRegistry *ENSRegistrySession) Resolver(node [32]byte) (common.Address, error) {
return _ENSRegistry.Contract.Resolver(&_ENSRegistry.CallOpts, node)
}
// Resolver is a free data retrieval call binding the contract method 0x0178b8bf.
//
// Solidity: function resolver(bytes32 node) constant returns(address)
func (_ENSRegistry *ENSRegistryCallerSession) Resolver(node [32]byte) (common.Address, error) {
return _ENSRegistry.Contract.Resolver(&_ENSRegistry.CallOpts, node)
}
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(bytes32 node) constant returns(uint64)
func (_ENSRegistry *ENSRegistryCaller) Ttl(opts *bind.CallOpts, node [32]byte) (uint64, error) {
var (
ret0 = new(uint64)
)
out := ret0
err := _ENSRegistry.contract.Call(opts, out, "ttl", node)
return *ret0, err
}
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(bytes32 node) constant returns(uint64)
func (_ENSRegistry *ENSRegistrySession) Ttl(node [32]byte) (uint64, error) {
return _ENSRegistry.Contract.Ttl(&_ENSRegistry.CallOpts, node)
}
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(bytes32 node) constant returns(uint64)
func (_ENSRegistry *ENSRegistryCallerSession) Ttl(node [32]byte) (uint64, error) {
return _ENSRegistry.Contract.Ttl(&_ENSRegistry.CallOpts, node)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(bytes32 node, address owner) returns()
func (_ENSRegistry *ENSRegistryTransactor) SetOwner(opts *bind.TransactOpts, node [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENSRegistry.contract.Transact(opts, "setOwner", node, owner)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(bytes32 node, address owner) returns()
func (_ENSRegistry *ENSRegistrySession) SetOwner(node [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetOwner(&_ENSRegistry.TransactOpts, node, owner)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(bytes32 node, address owner) returns()
func (_ENSRegistry *ENSRegistryTransactorSession) SetOwner(node [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetOwner(&_ENSRegistry.TransactOpts, node, owner)
}
// SetResolver is a paid mutator transaction binding the contract method 0x1896f70a.
//
// Solidity: function setResolver(bytes32 node, address resolver) returns()
func (_ENSRegistry *ENSRegistryTransactor) SetResolver(opts *bind.TransactOpts, node [32]byte, resolver common.Address) (*types.Transaction, error) {
return _ENSRegistry.contract.Transact(opts, "setResolver", node, resolver)
}
// SetResolver is a paid mutator transaction binding the contract method 0x1896f70a.
//
// Solidity: function setResolver(bytes32 node, address resolver) returns()
func (_ENSRegistry *ENSRegistrySession) SetResolver(node [32]byte, resolver common.Address) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetResolver(&_ENSRegistry.TransactOpts, node, resolver)
}
// SetResolver is a paid mutator transaction binding the contract method 0x1896f70a.
//
// Solidity: function setResolver(bytes32 node, address resolver) returns()
func (_ENSRegistry *ENSRegistryTransactorSession) SetResolver(node [32]byte, resolver common.Address) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetResolver(&_ENSRegistry.TransactOpts, node, resolver)
}
// SetSubnodeOwner is a paid mutator transaction binding the contract method 0x06ab5923.
//
// Solidity: function setSubnodeOwner(bytes32 node, bytes32 label, address owner) returns()
func (_ENSRegistry *ENSRegistryTransactor) SetSubnodeOwner(opts *bind.TransactOpts, node [32]byte, label [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENSRegistry.contract.Transact(opts, "setSubnodeOwner", node, label, owner)
}
// SetSubnodeOwner is a paid mutator transaction binding the contract method 0x06ab5923.
//
// Solidity: function setSubnodeOwner(bytes32 node, bytes32 label, address owner) returns()
func (_ENSRegistry *ENSRegistrySession) SetSubnodeOwner(node [32]byte, label [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetSubnodeOwner(&_ENSRegistry.TransactOpts, node, label, owner)
}
// SetSubnodeOwner is a paid mutator transaction binding the contract method 0x06ab5923.
//
// Solidity: function setSubnodeOwner(bytes32 node, bytes32 label, address owner) returns()
func (_ENSRegistry *ENSRegistryTransactorSession) SetSubnodeOwner(node [32]byte, label [32]byte, owner common.Address) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetSubnodeOwner(&_ENSRegistry.TransactOpts, node, label, owner)
}
// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
//
// Solidity: function setTTL(bytes32 node, uint64 ttl) returns()
func (_ENSRegistry *ENSRegistryTransactor) SetTTL(opts *bind.TransactOpts, node [32]byte, ttl uint64) (*types.Transaction, error) {
return _ENSRegistry.contract.Transact(opts, "setTTL", node, ttl)
}
// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
//
// Solidity: function setTTL(bytes32 node, uint64 ttl) returns()
func (_ENSRegistry *ENSRegistrySession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetTTL(&_ENSRegistry.TransactOpts, node, ttl)
}
// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
//
// Solidity: function setTTL(bytes32 node, uint64 ttl) returns()
func (_ENSRegistry *ENSRegistryTransactorSession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, error) {
return _ENSRegistry.Contract.SetTTL(&_ENSRegistry.TransactOpts, node, ttl)
}
// ENSRegistryNewOwnerIterator is returned from FilterNewOwner and is used to iterate over the raw logs and unpacked data for NewOwner events raised by the ENSRegistry contract.
type ENSRegistryNewOwnerIterator struct {
Event *ENSRegistryNewOwner // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSRegistryNewOwnerIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSRegistryNewOwner)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSRegistryNewOwner)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSRegistryNewOwnerIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSRegistryNewOwnerIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSRegistryNewOwner represents a NewOwner event raised by the ENSRegistry contract.
type ENSRegistryNewOwner struct {
Node [32]byte
Label [32]byte
Owner common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewOwner is a free log retrieval operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
//
// Solidity: event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner)
func (_ENSRegistry *ENSRegistryFilterer) FilterNewOwner(opts *bind.FilterOpts, node [][32]byte, label [][32]byte) (*ENSRegistryNewOwnerIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
var labelRule []interface{}
for _, labelItem := range label {
labelRule = append(labelRule, labelItem)
}
logs, sub, err := _ENSRegistry.contract.FilterLogs(opts, "NewOwner", nodeRule, labelRule)
if err != nil {
return nil, err
}
return &ENSRegistryNewOwnerIterator{contract: _ENSRegistry.contract, event: "NewOwner", logs: logs, sub: sub}, nil
}
// WatchNewOwner is a free log subscription operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
//
// Solidity: event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner)
func (_ENSRegistry *ENSRegistryFilterer) WatchNewOwner(opts *bind.WatchOpts, sink chan<- *ENSRegistryNewOwner, node [][32]byte, label [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
var labelRule []interface{}
for _, labelItem := range label {
labelRule = append(labelRule, labelItem)
}
logs, sub, err := _ENSRegistry.contract.WatchLogs(opts, "NewOwner", nodeRule, labelRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSRegistryNewOwner)
if err := _ENSRegistry.contract.UnpackLog(event, "NewOwner", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ENSRegistryNewResolverIterator is returned from FilterNewResolver and is used to iterate over the raw logs and unpacked data for NewResolver events raised by the ENSRegistry contract.
type ENSRegistryNewResolverIterator struct {
Event *ENSRegistryNewResolver // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSRegistryNewResolverIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSRegistryNewResolver)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSRegistryNewResolver)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSRegistryNewResolverIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSRegistryNewResolverIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSRegistryNewResolver represents a NewResolver event raised by the ENSRegistry contract.
type ENSRegistryNewResolver struct {
Node [32]byte
Resolver common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewResolver is a free log retrieval operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
// Solidity: event NewResolver(bytes32 indexed node, address resolver)
func (_ENSRegistry *ENSRegistryFilterer) FilterNewResolver(opts *bind.FilterOpts, node [][32]byte) (*ENSRegistryNewResolverIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENSRegistry.contract.FilterLogs(opts, "NewResolver", nodeRule)
if err != nil {
return nil, err
}
return &ENSRegistryNewResolverIterator{contract: _ENSRegistry.contract, event: "NewResolver", logs: logs, sub: sub}, nil
}
// WatchNewResolver is a free log subscription operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
// Solidity: event NewResolver(bytes32 indexed node, address resolver)
func (_ENSRegistry *ENSRegistryFilterer) WatchNewResolver(opts *bind.WatchOpts, sink chan<- *ENSRegistryNewResolver, node [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENSRegistry.contract.WatchLogs(opts, "NewResolver", nodeRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSRegistryNewResolver)
if err := _ENSRegistry.contract.UnpackLog(event, "NewResolver", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ENSRegistryNewTTLIterator is returned from FilterNewTTL and is used to iterate over the raw logs and unpacked data for NewTTL events raised by the ENSRegistry contract.
type ENSRegistryNewTTLIterator struct {
Event *ENSRegistryNewTTL // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSRegistryNewTTLIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSRegistryNewTTL)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSRegistryNewTTL)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSRegistryNewTTLIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSRegistryNewTTLIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSRegistryNewTTL represents a NewTTL event raised by the ENSRegistry contract.
type ENSRegistryNewTTL struct {
Node [32]byte
Ttl uint64
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewTTL is a free log retrieval operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
//
// Solidity: event NewTTL(bytes32 indexed node, uint64 ttl)
func (_ENSRegistry *ENSRegistryFilterer) FilterNewTTL(opts *bind.FilterOpts, node [][32]byte) (*ENSRegistryNewTTLIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENSRegistry.contract.FilterLogs(opts, "NewTTL", nodeRule)
if err != nil {
return nil, err
}
return &ENSRegistryNewTTLIterator{contract: _ENSRegistry.contract, event: "NewTTL", logs: logs, sub: sub}, nil
}
// WatchNewTTL is a free log subscription operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
//
// Solidity: event NewTTL(bytes32 indexed node, uint64 ttl)
func (_ENSRegistry *ENSRegistryFilterer) WatchNewTTL(opts *bind.WatchOpts, sink chan<- *ENSRegistryNewTTL, node [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENSRegistry.contract.WatchLogs(opts, "NewTTL", nodeRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSRegistryNewTTL)
if err := _ENSRegistry.contract.UnpackLog(event, "NewTTL", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ENSRegistryTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the ENSRegistry contract.
type ENSRegistryTransferIterator struct {
Event *ENSRegistryTransfer // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *ENSRegistryTransferIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(ENSRegistryTransfer)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(ENSRegistryTransfer)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSRegistryTransferIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *ENSRegistryTransferIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// ENSRegistryTransfer represents a Transfer event raised by the ENSRegistry contract.
type ENSRegistryTransfer struct {
Node [32]byte
Owner common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterTransfer is a free log retrieval operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
// Solidity: event Transfer(bytes32 indexed node, address owner)
func (_ENSRegistry *ENSRegistryFilterer) FilterTransfer(opts *bind.FilterOpts, node [][32]byte) (*ENSRegistryTransferIterator, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENSRegistry.contract.FilterLogs(opts, "Transfer", nodeRule)
if err != nil {
return nil, err
}
return &ENSRegistryTransferIterator{contract: _ENSRegistry.contract, event: "Transfer", logs: logs, sub: sub}, nil
}
// WatchTransfer is a free log subscription operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
// Solidity: event Transfer(bytes32 indexed node, address owner)
func (_ENSRegistry *ENSRegistryFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ENSRegistryTransfer, node [][32]byte) (event.Subscription, error) {
var nodeRule []interface{}
for _, nodeItem := range node {
nodeRule = append(nodeRule, nodeItem)
}
logs, sub, err := _ENSRegistry.contract.WatchLogs(opts, "Transfer", nodeRule)
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(ENSRegistryTransfer)
if err := _ENSRegistry.contract.UnpackLog(event, "Transfer", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}

View File

@ -1,210 +0,0 @@
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package contract
import (
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = abi.U256
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// FIFSRegistrarABI is the input ABI used to generate the binding from.
const FIFSRegistrarABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"label\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"register\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"ensAddr\",\"type\":\"address\"},{\"name\":\"node\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"
// FIFSRegistrarBin is the compiled bytecode used for deploying new contracts.
const FIFSRegistrarBin = `0x608060405234801561001057600080fd5b506040516040806102cc8339810180604052604081101561003057600080fd5b50805160209091015160008054600160a060020a031916600160a060020a0390931692909217825560015561026190819061006b90396000f3fe6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663d22057a98114610045575b600080fd5b34801561005157600080fd5b5061008b6004803603604081101561006857600080fd5b508035906020013573ffffffffffffffffffffffffffffffffffffffff1661008d565b005b6000805460015460408051602080820193909352808201879052815180820383018152606082018084528151918501919091207f02571be3000000000000000000000000000000000000000000000000000000009091526064820152905186949373ffffffffffffffffffffffffffffffffffffffff16926302571be39260848082019391829003018186803b15801561012657600080fd5b505afa15801561013a573d6000803e3d6000fd5b505050506040513d602081101561015057600080fd5b5051905073ffffffffffffffffffffffffffffffffffffffff8116158061018c575073ffffffffffffffffffffffffffffffffffffffff811633145b151561019757600080fd5b60008054600154604080517f06ab592300000000000000000000000000000000000000000000000000000000815260048101929092526024820188905273ffffffffffffffffffffffffffffffffffffffff878116604484015290519216926306ab59239260648084019382900301818387803b15801561021757600080fd5b505af115801561022b573d6000803e3d6000fd5b505050505050505056fea165627a7a723058200f21424d48c6fc6f2bc79f5b36b3a0e3067a97d4ce084ab0e0f9106303a3ee520029`
// DeployFIFSRegistrar deploys a new Ethereum contract, binding an instance of FIFSRegistrar to it.
func DeployFIFSRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend, ensAddr common.Address, node [32]byte) (common.Address, *types.Transaction, *FIFSRegistrar, error) {
parsed, err := abi.JSON(strings.NewReader(FIFSRegistrarABI))
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(FIFSRegistrarBin), backend, ensAddr, node)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}, FIFSRegistrarFilterer: FIFSRegistrarFilterer{contract: contract}}, nil
}
// FIFSRegistrar is an auto generated Go binding around an Ethereum contract.
type FIFSRegistrar struct {
FIFSRegistrarCaller // Read-only binding to the contract
FIFSRegistrarTransactor // Write-only binding to the contract
FIFSRegistrarFilterer // Log filterer for contract events
}
// FIFSRegistrarCaller is an auto generated read-only Go binding around an Ethereum contract.
type FIFSRegistrarCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// FIFSRegistrarTransactor is an auto generated write-only Go binding around an Ethereum contract.
type FIFSRegistrarTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// FIFSRegistrarFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type FIFSRegistrarFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// FIFSRegistrarSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type FIFSRegistrarSession struct {
Contract *FIFSRegistrar // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// FIFSRegistrarCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type FIFSRegistrarCallerSession struct {
Contract *FIFSRegistrarCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// FIFSRegistrarTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type FIFSRegistrarTransactorSession struct {
Contract *FIFSRegistrarTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// FIFSRegistrarRaw is an auto generated low-level Go binding around an Ethereum contract.
type FIFSRegistrarRaw struct {
Contract *FIFSRegistrar // Generic contract binding to access the raw methods on
}
// FIFSRegistrarCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type FIFSRegistrarCallerRaw struct {
Contract *FIFSRegistrarCaller // Generic read-only contract binding to access the raw methods on
}
// FIFSRegistrarTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type FIFSRegistrarTransactorRaw struct {
Contract *FIFSRegistrarTransactor // Generic write-only contract binding to access the raw methods on
}
// NewFIFSRegistrar creates a new instance of FIFSRegistrar, bound to a specific deployed contract.
func NewFIFSRegistrar(address common.Address, backend bind.ContractBackend) (*FIFSRegistrar, error) {
contract, err := bindFIFSRegistrar(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}, FIFSRegistrarFilterer: FIFSRegistrarFilterer{contract: contract}}, nil
}
// NewFIFSRegistrarCaller creates a new read-only instance of FIFSRegistrar, bound to a specific deployed contract.
func NewFIFSRegistrarCaller(address common.Address, caller bind.ContractCaller) (*FIFSRegistrarCaller, error) {
contract, err := bindFIFSRegistrar(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &FIFSRegistrarCaller{contract: contract}, nil
}
// NewFIFSRegistrarTransactor creates a new write-only instance of FIFSRegistrar, bound to a specific deployed contract.
func NewFIFSRegistrarTransactor(address common.Address, transactor bind.ContractTransactor) (*FIFSRegistrarTransactor, error) {
contract, err := bindFIFSRegistrar(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &FIFSRegistrarTransactor{contract: contract}, nil
}
// NewFIFSRegistrarFilterer creates a new log filterer instance of FIFSRegistrar, bound to a specific deployed contract.
func NewFIFSRegistrarFilterer(address common.Address, filterer bind.ContractFilterer) (*FIFSRegistrarFilterer, error) {
contract, err := bindFIFSRegistrar(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &FIFSRegistrarFilterer{contract: contract}, nil
}
// bindFIFSRegistrar binds a generic wrapper to an already deployed contract.
func bindFIFSRegistrar(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(FIFSRegistrarABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_FIFSRegistrar *FIFSRegistrarRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _FIFSRegistrar.Contract.FIFSRegistrarCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_FIFSRegistrar *FIFSRegistrarRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.FIFSRegistrarTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_FIFSRegistrar *FIFSRegistrarRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.FIFSRegistrarTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_FIFSRegistrar *FIFSRegistrarCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _FIFSRegistrar.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_FIFSRegistrar *FIFSRegistrarTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_FIFSRegistrar *FIFSRegistrarTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.contract.Transact(opts, method, params...)
}
// Register is a paid mutator transaction binding the contract method 0xd22057a9.
//
// Solidity: function register(bytes32 label, address owner) returns()
func (_FIFSRegistrar *FIFSRegistrarTransactor) Register(opts *bind.TransactOpts, label [32]byte, owner common.Address) (*types.Transaction, error) {
return _FIFSRegistrar.contract.Transact(opts, "register", label, owner)
}
// Register is a paid mutator transaction binding the contract method 0xd22057a9.
//
// Solidity: function register(bytes32 label, address owner) returns()
func (_FIFSRegistrar *FIFSRegistrarSession) Register(label [32]byte, owner common.Address) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, label, owner)
}
// Register is a paid mutator transaction binding the contract method 0xd22057a9.
//
// Solidity: function register(bytes32 label, address owner) returns()
func (_FIFSRegistrar *FIFSRegistrarTransactorSession) Register(label [32]byte, owner common.Address) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, label, owner)
}

File diff suppressed because one or more lines are too long

View File

@ -1,263 +0,0 @@
// Copyright 2016 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 ens
//go:generate abigen --sol contract/ENS.sol --pkg contract --out contract/ens.go
//go:generate abigen --sol contract/ENSRegistry.sol --exc contract/ENS.sol:ENS --pkg contract --out contract/ensregistry.go
//go:generate abigen --sol contract/FIFSRegistrar.sol --exc contract/ENS.sol:ENS --pkg contract --out contract/fifsregistrar.go
//go:generate abigen --sol contract/PublicResolver.sol --exc contract/ENS.sol:ENS --pkg contract --out contract/publicresolver.go
import (
"encoding/binary"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts/ens/contract"
"github.com/ethereum/go-ethereum/contracts/ens/fallback_contract"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
var (
MainNetAddress = common.HexToAddress("0x314159265dD8dbb310642f98f50C066173C1259b")
TestNetAddress = common.HexToAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010")
contentHash_Interface_Id [4]byte
)
const contentHash_Interface_Id_Spec = 0xbc1c58d1
func init() {
binary.BigEndian.PutUint32(contentHash_Interface_Id[:], contentHash_Interface_Id_Spec)
}
// ENS is the swarm domain name registry and resolver
type ENS struct {
*contract.ENSSession
contractBackend bind.ContractBackend
}
// NewENS creates a struct exposing convenient high-level operations for interacting with
// the Ethereum Name Service.
func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) (*ENS, error) {
ens, err := contract.NewENS(contractAddr, contractBackend)
if err != nil {
return nil, err
}
return &ENS{
&contract.ENSSession{
Contract: ens,
TransactOpts: *transactOpts,
},
contractBackend,
}, nil
}
// DeployENS deploys an instance of the ENS nameservice, with a 'first-in, first-served' root registrar.
func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *ENS, error) {
// Deploy the ENS registry
ensAddr, _, _, err := contract.DeployENSRegistry(transactOpts, contractBackend)
if err != nil {
return ensAddr, nil, err
}
ens, err := NewENS(transactOpts, ensAddr, contractBackend)
if err != nil {
return ensAddr, nil, err
}
// Deploy the registrar
regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{})
if err != nil {
return ensAddr, nil, err
}
// Set the registrar as owner of the ENS root
if _, err = ens.SetOwner([32]byte{}, regAddr); err != nil {
return ensAddr, nil, err
}
return ensAddr, ens, nil
}
func ensParentNode(name string) (common.Hash, common.Hash) {
parts := strings.SplitN(name, ".", 2)
label := crypto.Keccak256Hash([]byte(parts[0]))
if len(parts) == 1 {
return [32]byte{}, label
}
parentNode, parentLabel := ensParentNode(parts[1])
return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label
}
func EnsNode(name string) common.Hash {
parentNode, parentLabel := ensParentNode(name)
return crypto.Keccak256Hash(parentNode[:], parentLabel[:])
}
func (ens *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) {
resolverAddr, err := ens.Resolver(node)
if err != nil {
return nil, err
}
resolver, err := contract.NewPublicResolver(resolverAddr, ens.contractBackend)
if err != nil {
return nil, err
}
return &contract.PublicResolverSession{
Contract: resolver,
TransactOpts: ens.TransactOpts,
}, nil
}
func (ens *ENS) getFallbackResolver(node [32]byte) (*fallback_contract.PublicResolverSession, error) {
resolverAddr, err := ens.Resolver(node)
if err != nil {
return nil, err
}
resolver, err := fallback_contract.NewPublicResolver(resolverAddr, ens.contractBackend)
if err != nil {
return nil, err
}
return &fallback_contract.PublicResolverSession{
Contract: resolver,
TransactOpts: ens.TransactOpts,
}, nil
}
func (ens *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) {
registrarAddr, err := ens.Owner(node)
if err != nil {
return nil, err
}
registrar, err := contract.NewFIFSRegistrar(registrarAddr, ens.contractBackend)
if err != nil {
return nil, err
}
return &contract.FIFSRegistrarSession{
Contract: registrar,
TransactOpts: ens.TransactOpts,
}, nil
}
// Resolve is a non-transactional call that returns the content hash associated with a name.
func (ens *ENS) Resolve(name string) (common.Hash, error) {
node := EnsNode(name)
resolver, err := ens.getResolver(node)
if err != nil {
return common.Hash{}, err
}
// IMPORTANT: The old contract is deprecated. This code should be removed latest on June 1st 2019
supported, err := resolver.SupportsInterface(contentHash_Interface_Id)
if err != nil {
return common.Hash{}, err
}
if !supported {
resolver, err := ens.getFallbackResolver(node)
if err != nil {
return common.Hash{}, err
}
ret, err := resolver.Content(node)
if err != nil {
return common.Hash{}, err
}
return common.BytesToHash(ret[:]), nil
}
// END DEPRECATED CODE
contentHash, err := resolver.Contenthash(node)
if err != nil {
return common.Hash{}, err
}
return extractContentHash(contentHash)
}
// Addr is a non-transactional call that returns the address associated with a name.
func (ens *ENS) Addr(name string) (common.Address, error) {
node := EnsNode(name)
resolver, err := ens.getResolver(node)
if err != nil {
return common.Address{}, err
}
ret, err := resolver.Addr(node)
if err != nil {
return common.Address{}, err
}
return common.BytesToAddress(ret[:]), nil
}
// SetAddress sets the address associated with a name. Only works if the caller
// owns the name, and the associated resolver implements a `setAddress` function.
func (ens *ENS) SetAddr(name string, addr common.Address) (*types.Transaction, error) {
node := EnsNode(name)
resolver, err := ens.getResolver(node)
if err != nil {
return nil, err
}
opts := ens.TransactOpts
opts.GasLimit = 200000
return resolver.Contract.SetAddr(&opts, node, addr)
}
// Register registers a new domain name for the caller, making them the owner of the new name.
// Only works if the registrar for the parent domain implements the FIFS registrar protocol.
func (ens *ENS) Register(name string) (*types.Transaction, error) {
parentNode, label := ensParentNode(name)
registrar, err := ens.getRegistrar(parentNode)
if err != nil {
return nil, err
}
return registrar.Contract.Register(&ens.TransactOpts, label, ens.TransactOpts.From)
}
// SetContentHash sets the content hash associated with a name. Only works if the caller
// owns the name, and the associated resolver implements a `setContenthash` function.
func (ens *ENS) SetContentHash(name string, hash []byte) (*types.Transaction, error) {
node := EnsNode(name)
resolver, err := ens.getResolver(node)
if err != nil {
return nil, err
}
opts := ens.TransactOpts
opts.GasLimit = 200000
// IMPORTANT: The old contract is deprecated. This code should be removed latest on June 1st 2019
supported, err := resolver.SupportsInterface(contentHash_Interface_Id)
if err != nil {
return nil, err
}
if !supported {
resolver, err := ens.getFallbackResolver(node)
if err != nil {
return nil, err
}
opts := ens.TransactOpts
opts.GasLimit = 200000
var b [32]byte
copy(b[:], hash)
return resolver.Contract.SetContent(&opts, node, b)
}
// END DEPRECATED CODE
return resolver.Contract.SetContenthash(&opts, node, hash)
}

View File

@ -1,126 +0,0 @@
// Copyright 2016 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 ens
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts/ens/contract"
"github.com/ethereum/go-ethereum/contracts/ens/fallback_contract"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
name = "my name on ENS"
hash = crypto.Keccak256Hash([]byte("my content"))
fallbackHash = crypto.Keccak256Hash([]byte("my content hash"))
addr = crypto.PubkeyToAddress(key.PublicKey)
testAddr = common.HexToAddress("0x1234123412341234123412341234123412341234")
)
func TestENS(t *testing.T) {
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000)
transactOpts := bind.NewKeyedTransactor(key)
ensAddr, ens, err := DeployENS(transactOpts, contractBackend)
if err != nil {
t.Fatalf("can't deploy root registry: %v", err)
}
contractBackend.Commit()
// Set ourself as the owner of the name.
if _, err := ens.Register(name); err != nil {
t.Fatalf("can't register: %v", err)
}
contractBackend.Commit()
// Deploy a resolver and make it responsible for the name.
resolverAddr, _, _, err := contract.DeployPublicResolver(transactOpts, contractBackend, ensAddr)
if err != nil {
t.Fatalf("can't deploy resolver: %v", err)
}
if _, err := ens.SetResolver(EnsNode(name), resolverAddr); err != nil {
t.Fatalf("can't set resolver: %v", err)
}
contractBackend.Commit()
// Set the content hash for the name.
cid, err := EncodeSwarmHash(hash)
if err != nil {
t.Fatal(err)
}
if _, err = ens.SetContentHash(name, cid); err != nil {
t.Fatalf("can't set content hash: %v", err)
}
contractBackend.Commit()
// Try to resolve the name.
resolvedHash, err := ens.Resolve(name)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if resolvedHash.Hex() != hash.Hex() {
t.Fatalf("resolve error, expected %v, got %v", hash.Hex(), resolvedHash.Hex())
}
// set the address for the name
if _, err = ens.SetAddr(name, testAddr); err != nil {
t.Fatalf("can't set address: %v", err)
}
contractBackend.Commit()
// Try to resolve the name to an address
recoveredAddr, err := ens.Addr(name)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if testAddr.Hex() != recoveredAddr.Hex() {
t.Fatalf("resolve error, expected %v, got %v", testAddr.Hex(), recoveredAddr.Hex())
}
// deploy the fallback contract and see that the fallback mechanism works
fallbackResolverAddr, _, _, err := fallback_contract.DeployPublicResolver(transactOpts, contractBackend, ensAddr)
if err != nil {
t.Fatalf("can't deploy resolver: %v", err)
}
if _, err := ens.SetResolver(EnsNode(name), fallbackResolverAddr); err != nil {
t.Fatalf("can't set resolver: %v", err)
}
contractBackend.Commit()
// Set the content hash for the name.
if _, err = ens.SetContentHash(name, fallbackHash.Bytes()); err != nil {
t.Fatalf("can't set content hash: %v", err)
}
contractBackend.Commit()
// Try to resolve the name.
fallbackResolvedHash, err := ens.Resolve(name)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if fallbackResolvedHash.Hex() != fallbackHash.Hex() {
t.Fatalf("resolve error, expected %v, got %v", hash.Hex(), resolvedHash.Hex())
}
}

View File

@ -1,212 +0,0 @@
pragma solidity ^0.4.0;
import './AbstractENS.sol';
/**
* A simple resolver anyone can use; only allows the owner of a node to set its
* address.
*/
contract PublicResolver {
bytes4 constant INTERFACE_META_ID = 0x01ffc9a7;
bytes4 constant ADDR_INTERFACE_ID = 0x3b3b57de;
bytes4 constant CONTENT_INTERFACE_ID = 0xd8389dc5;
bytes4 constant NAME_INTERFACE_ID = 0x691f3431;
bytes4 constant ABI_INTERFACE_ID = 0x2203ab56;
bytes4 constant PUBKEY_INTERFACE_ID = 0xc8690233;
bytes4 constant TEXT_INTERFACE_ID = 0x59d1d43c;
event AddrChanged(bytes32 indexed node, address a);
event ContentChanged(bytes32 indexed node, bytes32 hash);
event NameChanged(bytes32 indexed node, string name);
event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);
struct PublicKey {
bytes32 x;
bytes32 y;
}
struct Record {
address addr;
bytes32 content;
string name;
PublicKey pubkey;
mapping(string=>string) text;
mapping(uint256=>bytes) abis;
}
AbstractENS ens;
mapping(bytes32=>Record) records;
modifier only_owner(bytes32 node) {
if (ens.owner(node) != msg.sender) throw;
_;
}
/**
* Constructor.
* @param ensAddr The ENS registrar contract.
*/
function PublicResolver(AbstractENS ensAddr) {
ens = ensAddr;
}
/**
* Returns true if the resolver implements the interface specified by the provided hash.
* @param interfaceID The ID of the interface to check for.
* @return True if the contract implements the requested interface.
*/
function supportsInterface(bytes4 interfaceID) constant returns (bool) {
return interfaceID == ADDR_INTERFACE_ID ||
interfaceID == CONTENT_INTERFACE_ID ||
interfaceID == NAME_INTERFACE_ID ||
interfaceID == ABI_INTERFACE_ID ||
interfaceID == PUBKEY_INTERFACE_ID ||
interfaceID == TEXT_INTERFACE_ID ||
interfaceID == INTERFACE_META_ID;
}
/**
* Returns the address associated with an ENS node.
* @param node The ENS node to query.
* @return The associated address.
*/
function addr(bytes32 node) constant returns (address ret) {
ret = records[node].addr;
}
/**
* Sets the address associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param addr The address to set.
*/
function setAddr(bytes32 node, address addr) only_owner(node) {
records[node].addr = addr;
AddrChanged(node, addr);
}
/**
* Returns the content hash associated with an ENS node.
* Note that this resource type is not standardized, and will likely change
* in future to a resource type based on multihash.
* @param node The ENS node to query.
* @return The associated content hash.
*/
function content(bytes32 node) constant returns (bytes32 ret) {
ret = records[node].content;
}
/**
* Sets the content hash associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* Note that this resource type is not standardized, and will likely change
* in future to a resource type based on multihash.
* @param node The node to update.
* @param hash The content hash to set
*/
function setContent(bytes32 node, bytes32 hash) only_owner(node) {
records[node].content = hash;
ContentChanged(node, hash);
}
/**
* Returns the name associated with an ENS node, for reverse records.
* Defined in EIP181.
* @param node The ENS node to query.
* @return The associated name.
*/
function name(bytes32 node) constant returns (string ret) {
ret = records[node].name;
}
/**
* Sets the name associated with an ENS node, for reverse records.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param name The name to set.
*/
function setName(bytes32 node, string name) only_owner(node) {
records[node].name = name;
NameChanged(node, name);
}
/**
* Returns the ABI associated with an ENS node.
* Defined in EIP205.
* @param node The ENS node to query
* @param contentTypes A bitwise OR of the ABI formats accepted by the caller.
* @return contentType The content type of the return value
* @return data The ABI data
*/
function ABI(bytes32 node, uint256 contentTypes) constant returns (uint256 contentType, bytes data) {
var record = records[node];
for(contentType = 1; contentType <= contentTypes; contentType <<= 1) {
if ((contentType & contentTypes) != 0 && record.abis[contentType].length > 0) {
data = record.abis[contentType];
return;
}
}
contentType = 0;
}
/**
* Sets the ABI associated with an ENS node.
* Nodes may have one ABI of each content type. To remove an ABI, set it to
* the empty string.
* @param node The node to update.
* @param contentType The content type of the ABI
* @param data The ABI data.
*/
function setABI(bytes32 node, uint256 contentType, bytes data) only_owner(node) {
// Content types must be powers of 2
if (((contentType - 1) & contentType) != 0) throw;
records[node].abis[contentType] = data;
ABIChanged(node, contentType);
}
/**
* Returns the SECP256k1 public key associated with an ENS node.
* Defined in EIP 619.
* @param node The ENS node to query
* @return x, y the X and Y coordinates of the curve point for the public key.
*/
function pubkey(bytes32 node) constant returns (bytes32 x, bytes32 y) {
return (records[node].pubkey.x, records[node].pubkey.y);
}
/**
* Sets the SECP256k1 public key associated with an ENS node.
* @param node The ENS node to query
* @param x the X coordinate of the curve point for the public key.
* @param y the Y coordinate of the curve point for the public key.
*/
function setPubkey(bytes32 node, bytes32 x, bytes32 y) only_owner(node) {
records[node].pubkey = PublicKey(x, y);
PubkeyChanged(node, x, y);
}
/**
* Returns the text data associated with an ENS node and key.
* @param node The ENS node to query.
* @param key The text data key to query.
* @return The associated text data.
*/
function text(bytes32 node, string key) constant returns (string ret) {
ret = records[node].text[key];
}
/**
* Sets the text data associated with an ENS node and key.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param key The key to set.
* @param value The text data value to set.
*/
function setText(bytes32 node, string key, string value) only_owner(node) {
records[node].text[key] = value;
TextChanged(node, key, key);
}
}

File diff suppressed because one or more lines are too long