Merge branch 'master' of github.com:ethereum/go-ethereum into pss-smoke-basic

This commit is contained in:
Rafael Matias 2019-03-25 10:15:51 +01:00
commit e9c6a587ab
No known key found for this signature in database
GPG key ID: 1BC39532FB4A2DBD
67 changed files with 3879 additions and 707 deletions

View file

@ -232,4 +232,4 @@ matrix:
go: 1.12.x
git:
submodules: false # avoid cloning ethereum/tests
script: ./build/travis_keepalive.sh go test -v -timeout 20m -race ./swarm...
script: ./build/travis_keepalive.sh go test -timeout 20m -race ./swarm... ./p2p/{protocols,simulations,testing}/...

View file

@ -23,8 +23,8 @@ environment:
install:
- git submodule update --init
- rmdir C:\go /s /q
- appveyor DownloadFile https://dl.google.com/go/go1.12.windows-%GETH_ARCH%.zip
- 7z x go1.12.windows-%GETH_ARCH%.zip -y -oC:\ > NUL
- appveyor DownloadFile https://dl.google.com/go/go1.12.1.windows-%GETH_ARCH%.zip
- 7z x go1.12.1.windows-%GETH_ARCH%.zip -y -oC:\ > NUL
- go version
- gcc --version

View file

@ -137,7 +137,6 @@ var (
utils.RPCCORSDomainFlag,
utils.RPCVirtualHostsFlag,
utils.EthStatsURLFlag,
utils.MetricsEnabledFlag,
utils.FakePoWFlag,
utils.NoCompactionFlag,
utils.GpoBlocksFlag,
@ -174,6 +173,8 @@ var (
}
metricsFlags = []cli.Flag{
utils.MetricsEnabledFlag,
utils.MetricsEnabledExpensiveFlag,
utils.MetricsEnableInfluxDBFlag,
utils.MetricsInfluxDBEndpointFlag,
utils.MetricsInfluxDBDatabaseFlag,

View file

@ -226,15 +226,7 @@ var AppHelpFlagGroups = []flagGroup{
},
{
Name: "METRICS AND STATS",
Flags: []cli.Flag{
utils.MetricsEnabledFlag,
utils.MetricsEnableInfluxDBFlag,
utils.MetricsInfluxDBEndpointFlag,
utils.MetricsInfluxDBDatabaseFlag,
utils.MetricsInfluxDBUsernameFlag,
utils.MetricsInfluxDBPasswordFlag,
utils.MetricsInfluxDBTagsFlag,
},
Flags: metricsFlags,
},
{
Name: "WHISPER (EXPERIMENTAL)",

View file

@ -123,18 +123,22 @@ func buildConfig(ctx *cli.Context) (config *bzzapi.Config, err error) {
}
//finally, after the configuration build phase is finished, initialize
func initSwarmNode(config *bzzapi.Config, stack *node.Node, ctx *cli.Context) {
func initSwarmNode(config *bzzapi.Config, stack *node.Node, ctx *cli.Context, nodeconfig *node.Config) error {
//at this point, all vars should be set in the Config
//get the account for the provided swarm account
prvkey := getAccount(config.BzzAccount, ctx, stack)
//set the resolved config path (geth --datadir)
config.Path = expandPath(stack.InstanceDir())
//finally, initialize the configuration
config.Init(prvkey)
err := config.Init(prvkey, nodeconfig.NodeKey())
if err != nil {
return err
}
//configuration phase completed here
log.Debug("Starting Swarm with the following parameters:")
//after having created the config, print it to screen
log.Debug(printConfig(config))
return nil
}
//configFileOverride overrides the current config with the config file, if a config file has been provided

View file

@ -19,10 +19,13 @@ package main
import (
"context"
"encoding/hex"
"fmt"
"os"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts/ens"
"github.com/ethereum/go-ethereum/swarm/storage"
"gopkg.in/urfave/cli.v1"
)
@ -34,7 +37,33 @@ var hashCommand = cli.Command{
Usage: "print the swarm hash of a file or directory",
ArgsUsage: "<file>",
Description: "Prints the swarm hash of file or directory",
}
Subcommands: []cli.Command{
{
CustomHelpTemplate: helpTemplate,
Name: "ens",
Usage: "converts a swarm hash to an ens EIP1577 compatible CIDv1 hash",
ArgsUsage: "<ref>",
Description: "",
Subcommands: []cli.Command{
{
Action: encodeEipHash,
CustomHelpTemplate: helpTemplate,
Name: "contenthash",
Usage: "converts a swarm hash to an ens EIP1577 compatible CIDv1 hash",
ArgsUsage: "<ref>",
Description: "",
},
{
Action: ensNodeHash,
CustomHelpTemplate: helpTemplate,
Name: "node",
Usage: "converts an ens name to an ENS node hash",
ArgsUsage: "<ref>",
Description: "",
},
},
},
}}
func hash(ctx *cli.Context) {
args := ctx.Args()
@ -56,3 +85,31 @@ func hash(ctx *cli.Context) {
fmt.Printf("%v\n", addr)
}
}
func ensNodeHash(ctx *cli.Context) {
args := ctx.Args()
if len(args) < 1 {
utils.Fatalf("Usage: swarm hash ens node <ens name>")
}
ensName := args[0]
hash := ens.EnsNode(ensName)
stringHex := hex.EncodeToString(hash[:])
fmt.Println(stringHex)
}
func encodeEipHash(ctx *cli.Context) {
args := ctx.Args()
if len(args) < 1 {
utils.Fatalf("Usage: swarm hash ens <swarm hash>")
}
swarmHash := args[0]
hash := common.HexToHash(swarmHash)
ensHash, err := ens.EncodeSwarmHash(hash)
if err != nil {
utils.Fatalf("error converting swarm hash", err)
}
stringHex := hex.EncodeToString(ensHash)
fmt.Println(stringHex)
}

View file

@ -298,7 +298,10 @@ func bzzd(ctx *cli.Context) error {
//a few steps need to be done after the config phase is completed,
//due to overriding behavior
initSwarmNode(bzzconfig, stack, ctx)
err = initSwarmNode(bzzconfig, stack, ctx, &cfg)
if err != nil {
return err
}
//register BZZ as node.Service in the ethereum node
registerBzzService(bzzconfig, stack)
//start the node

View file

@ -40,6 +40,7 @@ var (
allhosts string
hosts []string
filesize int
inputSeed int
syncDelay int
httpPort int
wsPort int
@ -74,6 +75,12 @@ func main() {
Usage: "ws port",
Destination: &wsPort,
},
cli.IntFlag{
Name: "seed",
Value: 0,
Usage: "input seed in case we need deterministic upload",
Destination: &inputSeed,
},
cli.IntFlag{
Name: "filesize",
Value: 1024,

View file

@ -39,6 +39,11 @@ import (
)
func uploadAndSyncCmd(ctx *cli.Context, tuid string) error {
// use input seed if it has been set
if inputSeed != 0 {
seed = inputSeed
}
randomBytes := testutil.RandomBytes(seed, filesize*1000)
errc := make(chan error)
@ -47,37 +52,28 @@ func uploadAndSyncCmd(ctx *cli.Context, tuid string) error {
errc <- uploadAndSync(ctx, randomBytes, tuid)
}()
var err error
select {
case err := <-errc:
case err = <-errc:
if err != nil {
metrics.GetOrRegisterCounter(fmt.Sprintf("%s.fail", commandName), nil).Inc(1)
}
return err
case <-time.After(time.Duration(timeout) * time.Second):
metrics.GetOrRegisterCounter(fmt.Sprintf("%s.timeout", commandName), nil).Inc(1)
e := fmt.Errorf("timeout after %v sec", timeout)
err = fmt.Errorf("timeout after %v sec", timeout)
}
// trigger debug functionality on randomBytes
err := trackChunks(randomBytes[:])
if err != nil {
e = fmt.Errorf("%v; triggerChunkDebug failed: %v", e, err)
e := trackChunks(randomBytes[:])
if e != nil {
log.Error(e.Error())
}
return e
}
// trigger debug functionality on randomBytes even on successful runs
err := trackChunks(randomBytes[:])
if err != nil {
log.Error(err.Error())
}
return nil
return err
}
func trackChunks(testData []byte) error {
log.Warn("Test timed out, running chunk debug sequence")
addrs, err := getAllRefs(testData)
if err != nil {
return err
@ -94,14 +90,14 @@ func trackChunks(testData []byte) error {
rpcClient, err := rpc.Dial(httpHost)
if err != nil {
log.Error("Error dialing host", "err", err)
log.Error("error dialing host", "err", err, "host", httpHost)
continue
}
var hasInfo []api.HasInfo
err = rpcClient.Call(&hasInfo, "bzz_has", addrs)
if err != nil {
log.Error("Error calling host", "err", err)
log.Error("error calling rpc client", "err", err, "host", httpHost)
continue
}
@ -125,7 +121,6 @@ func trackChunks(testData []byte) error {
}
func getAllRefs(testData []byte) (storage.AddressCollection, error) {
log.Trace("Getting all references for given root hash")
datadir, err := ioutil.TempDir("", "chunk-debug")
if err != nil {
return nil, fmt.Errorf("unable to create temp dir: %v", err)

View file

@ -226,7 +226,7 @@ var (
}
// Dashboard settings
DashboardEnabledFlag = cli.BoolFlag{
Name: metrics.DashboardEnabledFlag,
Name: "dashboard",
Usage: "Enable the dashboard",
}
DashboardAddrFlag = cli.StringFlag{
@ -644,9 +644,13 @@ var (
// Metrics flags
MetricsEnabledFlag = cli.BoolFlag{
Name: metrics.MetricsEnabledFlag,
Name: "metrics",
Usage: "Enable metrics collection and reporting",
}
MetricsEnabledExpensiveFlag = cli.BoolFlag{
Name: "metrics.expensive",
Usage: "Enable expensive metrics collection and reporting",
}
MetricsEnableInfluxDBFlag = cli.BoolFlag{
Name: "metrics.influxdb",
Usage: "Enable metrics export/push to an external InfluxDB database",

View file

@ -18,3 +18,13 @@ The go bindings for ENS contracts are generated using `abigen` via the go genera
```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).

121
contracts/ens/cid.go Normal file
View file

@ -0,0 +1,121 @@
// 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 = 0xd6 // BMT, 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, // swarm bmt 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
}

158
contracts/ens/cid_test.go Normal file
View file

@ -0,0 +1,158 @@
// 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, 0xd6, 0x20},
wantErr: false,
},
{
name: "cid version wrong, should fail",
headerBytes: []byte{0xe4, 0x00, 0xfa, 0xd6, 0x20},
wantErr: true,
},
{
name: "hash length wrong, should fail",
headerBytes: []byte{0xe4, 0x01, 0xfa, 0xd6, 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,23 +0,0 @@
pragma solidity ^0.4.0;
contract AbstractENS {
function owner(bytes32 node) constant returns(address);
function resolver(bytes32 node) constant returns(address);
function ttl(bytes32 node) constant returns(uint64);
function setOwner(bytes32 node, address owner);
function setSubnodeOwner(bytes32 node, bytes32 label, address owner);
function setResolver(bytes32 node, address resolver);
function setTTL(bytes32 node, uint64 ttl);
// 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);
}

View file

@ -1,94 +1,26 @@
pragma solidity ^0.4.0;
pragma solidity >=0.4.24;
import './AbstractENS.sol';
interface ENS {
/**
* The ENS registry contract.
*/
contract ENS is AbstractENS {
struct Record {
address owner;
address resolver;
uint64 ttl;
}
// Logged when the owner of a node assigns a new owner to a subnode.
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
mapping(bytes32=>Record) records;
// Logged when the owner of a node transfers ownership to a new account.
event Transfer(bytes32 indexed node, address owner);
// Permits modifications only by the owner of the specified node.
modifier only_owner(bytes32 node) {
if (records[node].owner != msg.sender) throw;
_;
}
// Logged when the resolver for a node changes.
event NewResolver(bytes32 indexed node, address resolver);
/**
* Constructs a new ENS registrar.
*/
function ENS() {
records[0].owner = msg.sender;
}
// Logged when the TTL of a node changes
event NewTTL(bytes32 indexed node, uint64 ttl);
/**
* Returns the address that owns the specified node.
*/
function owner(bytes32 node) constant returns (address) {
return records[node].owner;
}
/**
* Returns the address of the resolver for the specified node.
*/
function resolver(bytes32 node) constant returns (address) {
return records[node].resolver;
}
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);
/**
* Returns the TTL of a node, and any records associated with it.
*/
function ttl(bytes32 node) constant returns (uint64) {
return records[node].ttl;
}
/**
* 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) only_owner(node) {
Transfer(node, owner);
records[node].owner = owner;
}
/**
* Transfers ownership of a subnode sha3(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) only_owner(node) {
var subnode = sha3(node, label);
NewOwner(node, label, owner);
records[subnode].owner = owner;
}
/**
* 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) only_owner(node) {
NewResolver(node, resolver);
records[node].resolver = resolver;
}
/**
* 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) only_owner(node) {
NewTTL(node, ttl);
records[node].ttl = ttl;
}
}

View file

@ -0,0 +1,99 @@
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,20 +1,17 @@
pragma solidity ^0.4.0;
pragma solidity ^0.5.0;
import './AbstractENS.sol';
import "./ENS.sol";
/**
* A registrar that allocates subdomains to the first person to claim them.
*/
contract FIFSRegistrar {
AbstractENS ens;
ENS ens;
bytes32 rootNode;
modifier only_owner(bytes32 subnode) {
var node = sha3(rootNode, subnode);
var currentOwner = ens.owner(node);
if (currentOwner != 0 && currentOwner != msg.sender) throw;
modifier only_owner(bytes32 label) {
address currentOwner = ens.owner(keccak256(abi.encodePacked(rootNode, label)));
require(currentOwner == address(0x0) || currentOwner == msg.sender);
_;
}
@ -23,17 +20,17 @@ contract FIFSRegistrar {
* @param ensAddr The address of the ENS registry.
* @param node The node that this registrar administers.
*/
function FIFSRegistrar(AbstractENS ensAddr, bytes32 node) {
constructor(ENS ensAddr, bytes32 node) public {
ens = ensAddr;
rootNode = node;
}
/**
* Register a name, or change the owner of an existing registration.
* @param subnode The hash of the label to register.
* @param label The hash of the label to register.
* @param owner The address of the new owner.
*/
function register(bytes32 subnode, address owner) only_owner(subnode) {
ens.setSubnodeOwner(rootNode, subnode, owner);
function register(bytes32 label, address owner) public only_owner(label) {
ens.setSubnodeOwner(rootNode, label, owner);
}
}

View file

@ -1,26 +1,27 @@
pragma solidity ^0.4.0;
pragma solidity >=0.4.25;
import './AbstractENS.sol';
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 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;
bytes4 constant CONTENTHASH_INTERFACE_ID = 0xbc1c58d1;
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);
event TextChanged(bytes32 indexed node, string indexedKey, string key);
event ContenthashChanged(bytes32 indexed node, bytes hash);
struct PublicKey {
bytes32 x;
@ -29,18 +30,19 @@ contract PublicResolver {
struct Record {
address addr;
bytes32 content;
string name;
PublicKey pubkey;
mapping(string=>string) text;
mapping(uint256=>bytes) abis;
bytes contenthash;
}
AbstractENS ens;
mapping(bytes32=>Record) records;
ENS ens;
modifier only_owner(bytes32 node) {
if (ens.owner(node) != msg.sender) throw;
mapping (bytes32 => Record) records;
modifier onlyOwner(bytes32 node) {
require(ens.owner(node) == msg.sender);
_;
}
@ -48,77 +50,30 @@ contract PublicResolver {
* Constructor.
* @param ensAddr The ENS registrar contract.
*/
function PublicResolver(AbstractENS ensAddr) {
constructor(ENS ensAddr) public {
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) {
function setAddr(bytes32 node, address addr) external onlyOwner(node) {
records[node].addr = addr;
AddrChanged(node, addr);
emit 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.
* Sets the contenthash 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
* @param hash The contenthash 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;
function setContenthash(bytes32 node, bytes calldata hash) external onlyOwner(node) {
records[node].contenthash = hash;
emit ContenthashChanged(node, hash);
}
/**
@ -127,28 +82,9 @@ contract PublicResolver {
* @param node The node to update.
* @param name The name to set.
*/
function setName(bytes32 node, string name) only_owner(node) {
function setName(bytes32 node, string calldata name) external onlyOwner(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;
emit NameChanged(node, name);
}
/**
@ -159,22 +95,12 @@ contract PublicResolver {
* @param contentType The content type of the ABI
* @param data The ABI data.
*/
function setABI(bytes32 node, uint256 contentType, bytes data) only_owner(node) {
function setABI(bytes32 node, uint256 contentType, bytes calldata data) external onlyOwner(node) {
// Content types must be powers of 2
if (((contentType - 1) & contentType) != 0) throw;
require(((contentType - 1) & contentType) == 0);
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);
emit ABIChanged(node, contentType);
}
/**
@ -183,19 +109,9 @@ contract PublicResolver {
* @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) {
function setPubkey(bytes32 node, bytes32 x, bytes32 y) external onlyOwner(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];
emit PubkeyChanged(node, x, y);
}
/**
@ -205,8 +121,92 @@ contract PublicResolver {
* @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) {
function setText(bytes32 node, string calldata key, string calldata value) external onlyOwner(node) {
records[node].text[key] = value;
TextChanged(node, key, key);
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

@ -4,6 +4,7 @@
package contract
import (
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
@ -14,11 +15,23 @@ import (
"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\"},{\"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\"}]"
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 = `0x6060604052341561000f57600080fd5b60008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a033316600160a060020a0319909116179055610503806100626000396000f3006060604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178b8bf811461008757806302571be3146100b957806306ab5923146100cf57806314ab9038146100f657806316a25cbd146101195780631896f70a1461014c5780635b0fc9c31461016e575b600080fd5b341561009257600080fd5b61009d600435610190565b604051600160a060020a03909116815260200160405180910390f35b34156100c457600080fd5b61009d6004356101ae565b34156100da57600080fd5b6100f4600435602435600160a060020a03604435166101c9565b005b341561010157600080fd5b6100f460043567ffffffffffffffff6024351661028b565b341561012457600080fd5b61012f600435610357565b60405167ffffffffffffffff909116815260200160405180910390f35b341561015757600080fd5b6100f4600435600160a060020a036024351661038e565b341561017957600080fd5b6100f4600435600160a060020a0360243516610434565b600090815260208190526040902060010154600160a060020a031690565b600090815260208190526040902054600160a060020a031690565b600083815260208190526040812054849033600160a060020a039081169116146101f257600080fd5b8484604051918252602082015260409081019051908190039020915083857fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8285604051600160a060020a03909116815260200160405180910390a3506000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555050565b600082815260208190526040902054829033600160a060020a039081169116146102b457600080fd5b827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa688360405167ffffffffffffffff909116815260200160405180910390a250600091825260208290526040909120600101805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60009081526020819052604090206001015474010000000000000000000000000000000000000000900467ffffffffffffffff1690565b600082815260208190526040902054829033600160a060020a039081169116146103b757600080fd5b827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120600101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b600082815260208190526040902054829033600160a060020a0390811691161461045d57600080fd5b827fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26683604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555600a165627a7a72305820f4c798d4c84c9912f389f64631e85e8d16c3e6644f8c2e1579936015c7d5f6660029`
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) {
@ -177,7 +190,7 @@ func (_ENS *ENSTransactorRaw) Transact(opts *bind.TransactOpts, method string, p
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(node bytes32) constant returns(address)
// 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)
@ -189,21 +202,21 @@ func (_ENS *ENSCaller) Owner(opts *bind.CallOpts, node [32]byte) (common.Address
// Owner is a free data retrieval call binding the contract method 0x02571be3.
//
// Solidity: function owner(node bytes32) constant returns(address)
// 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(node bytes32) constant returns(address)
// 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(node bytes32) constant returns(address)
// 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)
@ -215,22 +228,22 @@ func (_ENS *ENSCaller) Resolver(opts *bind.CallOpts, node [32]byte) (common.Addr
// Resolver is a free data retrieval call binding the contract method 0x0178b8bf.
//
// Solidity: function resolver(node bytes32) constant returns(address)
// 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(node bytes32) constant returns(address)
// 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.
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(node bytes32) constant returns(uint64)
func (_ENS *ENSCaller) TTL(opts *bind.CallOpts, node [32]byte) (uint64, error) {
// Solidity: function ttl(bytes32 node) constant returns(uint64)
func (_ENS *ENSCaller) Ttl(opts *bind.CallOpts, node [32]byte) (uint64, error) {
var (
ret0 = new(uint64)
)
@ -239,100 +252,100 @@ func (_ENS *ENSCaller) TTL(opts *bind.CallOpts, node [32]byte) (uint64, error) {
return *ret0, err
}
// TTL is a free data retrieval call binding the contract method 0x16a25cbd.
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(node bytes32) constant returns(uint64)
func (_ENS *ENSSession) TTL(node [32]byte) (uint64, error) {
return _ENS.Contract.TTL(&_ENS.CallOpts, node)
// 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.
// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
//
// Solidity: function ttl(node bytes32) constant returns(uint64)
func (_ENS *ENSCallerSession) TTL(node [32]byte) (uint64, error) {
return _ENS.Contract.TTL(&_ENS.CallOpts, node)
// 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(node bytes32, owner address) returns()
// 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(node bytes32, owner address) returns()
// 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(node bytes32, owner address) returns()
// 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(node bytes32, resolver address) returns()
// 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(node bytes32, resolver address) returns()
// 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(node bytes32, resolver address) returns()
// 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(node bytes32, label bytes32, owner address) returns()
// 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(node bytes32, label bytes32, owner address) returns()
// 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(node bytes32, label bytes32, owner address) returns()
// 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(node bytes32, ttl uint64) returns()
// 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(node bytes32, ttl uint64) returns()
// 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(node bytes32, ttl uint64) returns()
// 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)
}
@ -392,7 +405,7 @@ func (it *ENSNewOwnerIterator) Next() bool {
}
}
// Error retruned any retrieval or parsing error occurred during filtering.
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSNewOwnerIterator) Error() error {
return it.fail
}
@ -414,7 +427,7 @@ type ENSNewOwner struct {
// FilterNewOwner is a free log retrieval operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
//
// Solidity: event NewOwner(node indexed bytes32, label indexed bytes32, owner address)
// 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{}
@ -435,7 +448,7 @@ func (_ENS *ENSFilterer) FilterNewOwner(opts *bind.FilterOpts, node [][32]byte,
// WatchNewOwner is a free log subscription operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
//
// Solidity: event NewOwner(node indexed bytes32, label indexed bytes32, owner address)
// 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{}
@ -534,7 +547,7 @@ func (it *ENSNewResolverIterator) Next() bool {
}
}
// Error retruned any retrieval or parsing error occurred during filtering.
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSNewResolverIterator) Error() error {
return it.fail
}
@ -555,7 +568,7 @@ type ENSNewResolver struct {
// FilterNewResolver is a free log retrieval operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
// Solidity: event NewResolver(node indexed bytes32, resolver address)
// Solidity: event NewResolver(bytes32 indexed node, address resolver)
func (_ENS *ENSFilterer) FilterNewResolver(opts *bind.FilterOpts, node [][32]byte) (*ENSNewResolverIterator, error) {
var nodeRule []interface{}
@ -572,7 +585,7 @@ func (_ENS *ENSFilterer) FilterNewResolver(opts *bind.FilterOpts, node [][32]byt
// WatchNewResolver is a free log subscription operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
// Solidity: event NewResolver(node indexed bytes32, resolver address)
// 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{}
@ -667,7 +680,7 @@ func (it *ENSNewTTLIterator) Next() bool {
}
}
// Error retruned any retrieval or parsing error occurred during filtering.
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSNewTTLIterator) Error() error {
return it.fail
}
@ -682,13 +695,13 @@ func (it *ENSNewTTLIterator) Close() error {
// ENSNewTTL represents a NewTTL event raised by the ENS contract.
type ENSNewTTL struct {
Node [32]byte
TTL uint64
Ttl uint64
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewTTL is a free log retrieval operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
//
// Solidity: event NewTTL(node indexed bytes32, ttl uint64)
// Solidity: event NewTTL(bytes32 indexed node, uint64 ttl)
func (_ENS *ENSFilterer) FilterNewTTL(opts *bind.FilterOpts, node [][32]byte) (*ENSNewTTLIterator, error) {
var nodeRule []interface{}
@ -705,7 +718,7 @@ func (_ENS *ENSFilterer) FilterNewTTL(opts *bind.FilterOpts, node [][32]byte) (*
// WatchNewTTL is a free log subscription operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
//
// Solidity: event NewTTL(node indexed bytes32, ttl uint64)
// 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{}
@ -800,7 +813,7 @@ func (it *ENSTransferIterator) Next() bool {
}
}
// Error retruned any retrieval or parsing error occurred during filtering.
// Error returns any retrieval or parsing error occurred during filtering.
func (it *ENSTransferIterator) Error() error {
return it.fail
}
@ -821,7 +834,7 @@ type ENSTransfer struct {
// FilterTransfer is a free log retrieval operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
// Solidity: event Transfer(node indexed bytes32, owner address)
// Solidity: event Transfer(bytes32 indexed node, address owner)
func (_ENS *ENSFilterer) FilterTransfer(opts *bind.FilterOpts, node [][32]byte) (*ENSTransferIterator, error) {
var nodeRule []interface{}
@ -838,7 +851,7 @@ func (_ENS *ENSFilterer) FilterTransfer(opts *bind.FilterOpts, node [][32]byte)
// WatchTransfer is a free log subscription operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
// Solidity: event Transfer(node indexed bytes32, owner address)
// 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{}

View file

@ -0,0 +1,892 @@
// 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

@ -4,19 +4,34 @@
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\":\"subnode\",\"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\"}]"
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 = `0x6060604052341561000f57600080fd5b604051604080610224833981016040528080519190602001805160008054600160a060020a03909516600160a060020a03199095169490941790935550506001556101c58061005f6000396000f3006060604052600436106100275763ffffffff60e060020a600035041663d22057a9811461002c575b600080fd5b341561003757600080fd5b61004e600435600160a060020a0360243516610050565b005b816000806001548360405191825260208201526040908101905190819003902060008054919350600160a060020a03909116906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156100c857600080fd5b6102c65a03f115156100d957600080fd5b5050506040518051915050600160a060020a0381161580159061010e575033600160a060020a031681600160a060020a031614155b1561011857600080fd5b600054600154600160a060020a03909116906306ab592390878760405160e060020a63ffffffff861602815260048101939093526024830191909152600160a060020a03166044820152606401600060405180830381600087803b151561017e57600080fd5b6102c65a03f1151561018f57600080fd5b50505050505050505600a165627a7a723058206fb963cb168d5e3a51af12cd6bb23e324dbd32dd4954f43653ba27e66b68ea650029`
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) {
@ -175,21 +190,21 @@ func (_FIFSRegistrar *FIFSRegistrarTransactorRaw) Transact(opts *bind.TransactOp
// Register is a paid mutator transaction binding the contract method 0xd22057a9.
//
// Solidity: function register(subnode bytes32, owner address) returns()
func (_FIFSRegistrar *FIFSRegistrarTransactor) Register(opts *bind.TransactOpts, subnode [32]byte, owner common.Address) (*types.Transaction, error) {
return _FIFSRegistrar.contract.Transact(opts, "register", subnode, owner)
// 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(subnode bytes32, owner address) returns()
func (_FIFSRegistrar *FIFSRegistrarSession) Register(subnode [32]byte, owner common.Address) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, subnode, owner)
// 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(subnode bytes32, owner address) returns()
func (_FIFSRegistrar *FIFSRegistrarTransactorSession) Register(subnode [32]byte, owner common.Address) (*types.Transaction, error) {
return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, subnode, owner)
// 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

@ -16,16 +16,19 @@
package ens
//go:generate abigen --sol contract/ENS.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/ens.go
//go:generate abigen --sol contract/FIFSRegistrar.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/fifsregistrar.go
//go:generate abigen --sol contract/PublicResolver.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/publicresolver.go
//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"
)
@ -33,8 +36,15 @@ import (
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
@ -60,7 +70,7 @@ func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contra
// 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.DeployENS(transactOpts, contractBackend)
ensAddr, _, _, err := contract.DeployENSRegistry(transactOpts, contractBackend)
if err != nil {
return ensAddr, nil, err
}
@ -110,6 +120,21 @@ func (ens *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, err
}, 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 {
@ -133,11 +158,33 @@ func (ens *ENS) Resolve(name string) (common.Hash, error) {
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.
@ -181,15 +228,36 @@ func (ens *ENS) Register(name string) (*types.Transaction, error) {
}
// SetContentHash sets the content hash associated with a name. Only works if the caller
// owns the name, and the associated resolver implements a `setContent` function.
func (ens *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
// 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
return resolver.Contract.SetContent(&opts, node, hash)
// 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

@ -24,6 +24,7 @@ import (
"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"
)
@ -32,6 +33,7 @@ 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")
)
@ -57,24 +59,29 @@ func TestENS(t *testing.T) {
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.
if _, err = ens.SetContentHash(name, hash); err != nil {
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.
vhost, err := ens.Resolve(name)
resolvedHash, err := ens.Resolve(name)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if vhost != hash {
t.Fatalf("resolve error, expected %v, got %v", hash.Hex(), vhost.Hex())
if resolvedHash.Hex() != hash.Hex() {
t.Fatalf("resolve error, expected %v, got %v", hash.Hex(), resolvedHash.Hex())
}
// set the address for the name
@ -88,7 +95,32 @@ func TestENS(t *testing.T) {
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if vhost != hash {
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

@ -0,0 +1,212 @@
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

View file

@ -47,6 +47,16 @@ import (
)
var (
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
accountCommitTimer = metrics.NewRegisteredTimer("chain/account/commits", nil)
storageReadTimer = metrics.NewRegisteredTimer("chain/storage/reads", nil)
storageHashTimer = metrics.NewRegisteredTimer("chain/storage/hashes", nil)
storageUpdateTimer = metrics.NewRegisteredTimer("chain/storage/updates", nil)
storageCommitTimer = metrics.NewRegisteredTimer("chain/storage/commits", nil)
blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil)
blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
@ -1249,10 +1259,26 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
if err != nil {
return it.index, events, coalescedLogs, err
}
// Update the metrics subsystem with all the measurements
accountReadTimer.Update(state.AccountReads)
accountHashTimer.Update(state.AccountHashes)
accountUpdateTimer.Update(state.AccountUpdates)
accountCommitTimer.Update(state.AccountCommits)
storageReadTimer.Update(state.StorageReads)
storageHashTimer.Update(state.StorageHashes)
storageUpdateTimer.Update(state.StorageUpdates)
storageCommitTimer.Update(state.StorageCommits)
trieAccess := state.AccountReads + state.AccountHashes + state.AccountUpdates + state.AccountCommits
trieAccess += state.StorageReads + state.StorageHashes + state.StorageUpdates + state.StorageCommits
blockInsertTimer.UpdateSince(start)
blockExecutionTimer.Update(t1.Sub(t0))
blockExecutionTimer.Update(t1.Sub(t0) - trieAccess)
blockValidationTimer.Update(t2.Sub(t1))
blockWriteTimer.Update(t3.Sub(t2))
switch status {
case CanonStatTy:
log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(),
@ -1274,7 +1300,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
"root", block.Root())
events = append(events, ChainSideEvent{block})
}
blockInsertTimer.UpdateSince(start)
stats.processed++
stats.usedGas += usedGas

View file

@ -21,9 +21,11 @@ import (
"fmt"
"io"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
)
@ -177,6 +179,10 @@ func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.
if cached {
return value
}
// Track the amount of time wasted on reading the storge trie
if metrics.EnabledExpensive {
defer func(start time.Time) { self.db.StorageReads += time.Since(start) }(time.Now())
}
// Otherwise load the value from the database
enc, err := self.getTrie(db).TryGet(key[:])
if err != nil {
@ -216,6 +222,11 @@ func (self *stateObject) setState(key, value common.Hash) {
// updateTrie writes cached storage modifications into the object's storage trie.
func (self *stateObject) updateTrie(db Database) Trie {
// Track the amount of time wasted on updating the storge trie
if metrics.EnabledExpensive {
defer func(start time.Time) { self.db.StorageUpdates += time.Since(start) }(time.Now())
}
// Update all the dirty slots in the trie
tr := self.getTrie(db)
for key, value := range self.dirtyStorage {
delete(self.dirtyStorage, key)
@ -240,6 +251,11 @@ func (self *stateObject) updateTrie(db Database) Trie {
// UpdateRoot sets the trie root to the current root hash of
func (self *stateObject) updateRoot(db Database) {
self.updateTrie(db)
// Track the amount of time wasted on hashing the storge trie
if metrics.EnabledExpensive {
defer func(start time.Time) { self.db.StorageHashes += time.Since(start) }(time.Now())
}
self.data.Root = self.trie.Hash()
}
@ -250,6 +266,10 @@ func (self *stateObject) CommitTrie(db Database) error {
if self.dbErr != nil {
return self.dbErr
}
// Track the amount of time wasted on committing the storge trie
if metrics.EnabledExpensive {
defer func(start time.Time) { self.db.StorageCommits += time.Since(start) }(time.Now())
}
root, err := self.trie.Commit(nil)
if err == nil {
self.data.Root = root

View file

@ -22,11 +22,13 @@ import (
"fmt"
"math/big"
"sort"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
@ -86,6 +88,16 @@ type StateDB struct {
journal *journal
validRevisions []revision
nextRevisionId int
// Measurements gathered during execution for debugging purposes
AccountReads time.Duration
AccountHashes time.Duration
AccountUpdates time.Duration
AccountCommits time.Duration
StorageReads time.Duration
StorageHashes time.Duration
StorageUpdates time.Duration
StorageCommits time.Duration
}
// Create a new state from a given trie.
@ -386,36 +398,51 @@ func (self *StateDB) Suicide(addr common.Address) bool {
//
// updateStateObject writes the given object to the trie.
func (self *StateDB) updateStateObject(stateObject *stateObject) {
func (s *StateDB) updateStateObject(stateObject *stateObject) {
// Track the amount of time wasted on updating the account from the trie
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())
}
// Encode the account and update the account trie
addr := stateObject.Address()
data, err := rlp.EncodeToBytes(stateObject)
if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
}
self.setError(self.trie.TryUpdate(addr[:], data))
s.setError(s.trie.TryUpdate(addr[:], data))
}
// deleteStateObject removes the given object from the state trie.
func (self *StateDB) deleteStateObject(stateObject *stateObject) {
func (s *StateDB) deleteStateObject(stateObject *stateObject) {
// Track the amount of time wasted on deleting the account from the trie
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())
}
// Delete the account from the trie
stateObject.deleted = true
addr := stateObject.Address()
self.setError(self.trie.TryDelete(addr[:]))
s.setError(s.trie.TryDelete(addr[:]))
}
// Retrieve a state object given by the address. Returns nil if not found.
func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer 'live' objects.
if obj := self.stateObjects[addr]; obj != nil {
func (s *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer live objects
if obj := s.stateObjects[addr]; obj != nil {
if obj.deleted {
return nil
}
return obj
}
// Load the object from the database.
enc, err := self.trie.TryGet(addr[:])
// Track the amount of time wasted on loading the object from the database
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountReads += time.Since(start) }(time.Now())
}
// Load the object from the database
enc, err := s.trie.TryGet(addr[:])
if len(enc) == 0 {
self.setError(err)
s.setError(err)
return nil
}
var data Account
@ -423,9 +450,9 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje
log.Error("Failed to decode state object", "addr", addr, "err", err)
return nil
}
// Insert into the live set.
obj := newObject(self, addr, data)
self.setStateObject(obj)
// Insert into the live set
obj := newObject(s, addr, data)
s.setStateObject(obj)
return obj
}
@ -600,6 +627,11 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
// goes into transaction receipts.
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
s.Finalise(deleteEmptyObjects)
// Track the amount of time wasted on hashing the account trie
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now())
}
return s.trie.Hash()
}
@ -624,7 +656,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
for addr := range s.journal.dirties {
s.stateObjectsDirty[addr] = struct{}{}
}
// Commit objects to the trie.
// Commit objects to the trie, measuring the elapsed time
for addr, stateObject := range s.stateObjects {
_, isDirty := s.stateObjectsDirty[addr]
switch {
@ -647,7 +679,10 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
}
delete(s.stateObjectsDirty, addr)
}
// Write trie changes.
// Write the account trie changes, measuing the amount of wasted time
if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now())
}
root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {
var account Account
if err := rlp.DecodeBytes(leaf, &account); err != nil {

View file

@ -143,9 +143,9 @@ func CopyFile(dst, src string, mode os.FileMode) {
// so that go commands executed by build use the same version of Go as the 'host' that runs
// build code. e.g.
//
// /usr/lib/go-1.12/bin/go run build/ci.go ...
// /usr/lib/go-1.12.1/bin/go run build/ci.go ...
//
// runs using go 1.12 and invokes go 1.12 tools from the same GOROOT. This is also important
// runs using go 1.12.1 and invokes go 1.12.1 tools from the same GOROOT. This is also important
// because runtime.Version checks on the host should match the tools that are run.
func GoTool(tool string, args ...string) *exec.Cmd {
args = append([]string{tool}, args...)

View file

@ -329,6 +329,11 @@ func (pm *ProtocolManager) handle(p *peer) error {
// handleMsg is invoked whenever an inbound message is received from a remote
// peer. The remote connection is torn down upon returning any error.
func (pm *ProtocolManager) handleMsg(p *peer) error {
select {
case err := <-p.errCh:
return err
default:
}
// Read the next message from the remote peer, and ensure it's fully consumed
msg, err := p.rw.ReadMsg()
if err != nil {
@ -389,7 +394,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if reply != nil {
p.queueSend(func() {
if err := reply.send(bv); err != nil {
p.errCh <- err
select {
case p.errCh <- err:
default:
}
}
})
}

View file

@ -98,15 +98,14 @@ type peer struct {
}
func newPeer(version int, network uint64, isTrusted bool, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
id := p.ID()
return &peer{
Peer: p,
rw: rw,
version: version,
network: network,
id: fmt.Sprintf("%x", id),
id: fmt.Sprintf("%x", p.ID().Bytes()),
isTrusted: isTrusted,
errCh: make(chan error, 1),
}
}

View file

@ -280,8 +280,8 @@ func (pm *ProtocolManager) blockLoop() {
)
for _, p := range peers {
p := p
switch p.announceType {
case announceTypeSimple:
p.queueSend(func() { p.SendAnnounce(announce) })
case announceTypeSigned:
@ -290,7 +290,6 @@ func (pm *ProtocolManager) blockLoop() {
signedAnnounce.sign(pm.server.privateKey)
signed = true
}
p.queueSend(func() { p.SendAnnounce(signedAnnounce) })
}
}

View file

@ -91,6 +91,7 @@ func (r *reporter) makeClient() (err error) {
URL: r.url,
Username: r.username,
Password: r.password,
Timeout: 10 * time.Second,
})
return

View file

@ -21,20 +21,37 @@ import (
// for less cluttered pprof profiles.
var Enabled = false
// MetricsEnabledFlag is the CLI flag name to use to enable metrics collections.
const MetricsEnabledFlag = "metrics"
const DashboardEnabledFlag = "dashboard"
// EnabledExpensive is a soft-flag meant for external packages to check if costly
// metrics gathering is allowed or not. The goal is to separate standard metrics
// for health monitoring and debug metrics that might impact runtime performance.
var EnabledExpensive = false
// enablerFlags is the CLI flag names to use to enable metrics collections.
var enablerFlags = []string{"metrics", "dashboard"}
// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections.
var expensiveEnablerFlags = []string{"metrics.expensive"}
// Init enables or disables the metrics system. Since we need this to run before
// any other code gets to create meters and timers, we'll actually do an ugly hack
// and peek into the command line args for the metrics flag.
func init() {
for _, arg := range os.Args {
if flag := strings.TrimLeft(arg, "-"); flag == MetricsEnabledFlag || flag == DashboardEnabledFlag {
flag := strings.TrimLeft(arg, "-")
for _, enabler := range enablerFlags {
if !Enabled && flag == enabler {
log.Info("Enabling metrics collection")
Enabled = true
}
}
for _, enabler := range expensiveEnablerFlags {
if !EnabledExpensive && flag == enabler {
log.Info("Enabling expensive metrics collection")
EnabledExpensive = true
}
}
}
}
// CollectProcessMetrics periodically collects various metrics about the running

View file

@ -92,6 +92,10 @@ func (e *ExecAdapter) NewNode(config *NodeConfig) (Node, error) {
return nil, fmt.Errorf("error creating node directory: %s", err)
}
err := config.initDummyEnode()
if err != nil {
return nil, err
}
// generate the config
conf := &execNodeConfig{
Stack: node.DefaultConfig,
@ -407,6 +411,13 @@ func startExecNodeStack() (*node.Node, error) {
if err := json.Unmarshal([]byte(confEnv), &conf); err != nil {
return nil, fmt.Errorf("error decoding %s: %v", envNodeConfig, err)
}
// create enode record
nodeTcpConn, err := net.ResolveTCPAddr("tcp", conf.Stack.P2P.ListenAddr)
if nodeTcpConn.IP == nil {
nodeTcpConn.IP = net.IPv4(127, 0, 0, 1)
}
conf.Node.initEnode(nodeTcpConn.IP, nodeTcpConn.Port, nodeTcpConn.Port)
conf.Stack.P2P.PrivateKey = conf.Node.PrivateKey
conf.Stack.Logger = log.New("node.id", conf.Node.ID.String())

View file

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/p2p/simulations/pipes"
"github.com/ethereum/go-ethereum/rpc"
)
@ -93,23 +92,10 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
}
}
// dialer in simulations based on ENR records
// doesn't work unless we explicitly set localhost record
ip := enr.IP(net.IPv4(127, 0, 0, 1))
config.Record.Set(&ip)
tcpPort := enr.TCP(0)
config.Record.Set(&tcpPort)
err := enode.SignV4(&config.Record, config.PrivateKey)
err := config.initDummyEnode()
if err != nil {
return nil, fmt.Errorf("unable to generate ENR: %v", err)
return nil, err
}
nod, err := enode.New(enode.V4ID{}, &config.Record)
if err != nil {
return nil, fmt.Errorf("unable to create enode: %v", err)
}
log.Trace("simnode new", "record", config.Record)
config.node = nod
n, err := node.New(&node.Config{
P2P: p2p.Config{

View file

@ -27,6 +27,7 @@ import (
"github.com/docker/docker/pkg/reexec"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
@ -265,3 +266,30 @@ func RegisterServices(services Services) {
os.Exit(0)
}
}
// adds the host part to the configuration's ENR, signs it
// creates and the corresponding enode object to the configuration
func (n *NodeConfig) initEnode(ip net.IP, tcpport int, udpport int) error {
enrIp := enr.IP(ip)
n.Record.Set(&enrIp)
enrTcpPort := enr.TCP(tcpport)
n.Record.Set(&enrTcpPort)
enrUdpPort := enr.UDP(udpport)
n.Record.Set(&enrUdpPort)
err := enode.SignV4(&n.Record, n.PrivateKey)
if err != nil {
return fmt.Errorf("unable to generate ENR: %v", err)
}
nod, err := enode.New(enode.V4ID{}, &n.Record)
if err != nil {
return fmt.Errorf("unable to create enode: %v", err)
}
log.Trace("simnode new", "record", n.Record)
n.node = nod
return nil
}
func (n *NodeConfig) initDummyEnode() error {
return n.initEnode(net.IPv4(127, 0, 0, 1), 0, 0)
}

View file

@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/swarm/log"
"github.com/ethereum/go-ethereum/swarm/network"
"github.com/ethereum/go-ethereum/swarm/pss"
"github.com/ethereum/go-ethereum/swarm/services/swap"
@ -58,7 +57,7 @@ type Config struct {
Port string
PublicKey string
BzzKey string
NodeID string
Enode *enode.Node `toml:"-"`
NetworkID uint64
SwapEnabled bool
SyncEnabled bool
@ -104,33 +103,38 @@ func NewConfig() (c *Config) {
//some config params need to be initialized after the complete
//config building phase is completed (e.g. due to overriding flags)
func (c *Config) Init(prvKey *ecdsa.PrivateKey) {
func (c *Config) Init(prvKey *ecdsa.PrivateKey, nodeKey *ecdsa.PrivateKey) error {
address := crypto.PubkeyToAddress(prvKey.PublicKey)
c.Path = filepath.Join(c.Path, "bzz-"+common.Bytes2Hex(address.Bytes()))
err := os.MkdirAll(c.Path, os.ModePerm)
// create swarm dir and record key
err := c.createAndSetPath(c.Path, prvKey)
if err != nil {
log.Error(fmt.Sprintf("Error creating root swarm data directory: %v", err))
return
return fmt.Errorf("Error creating root swarm data directory: %v", err)
}
c.setKey(prvKey)
// create the new enode record
// signed with the ephemeral node key
enodeParams := &network.EnodeParams{
PrivateKey: prvKey,
EnodeKey: nodeKey,
Lightnode: c.LightNodeEnabled,
Bootnode: c.BootnodeMode,
}
c.Enode, err = network.NewEnode(enodeParams)
if err != nil {
return fmt.Errorf("Error creating enode: %v", err)
}
pubkey := crypto.FromECDSAPub(&prvKey.PublicKey)
pubkeyhex := common.ToHex(pubkey)
keyhex := hexutil.Encode(network.PrivateKeyToBzzKey(prvKey))
c.PublicKey = pubkeyhex
c.BzzKey = keyhex
c.NodeID = enode.PubkeyToIDV4(&prvKey.PublicKey).String()
// initialize components that depend on the swarm instance's private key
if c.SwapEnabled {
c.Swap.Init(c.Contract, prvKey)
}
c.privateKey = prvKey
c.LocalStoreParams.Init(c.Path)
c.LocalStoreParams.BaseKey = common.FromHex(keyhex)
c.LocalStoreParams.BaseKey = common.FromHex(c.BzzKey)
c.Pss = c.Pss.WithPrivateKey(c.privateKey)
return nil
}
func (c *Config) ShiftPrivateKey() (privKey *ecdsa.PrivateKey) {
@ -140,3 +144,25 @@ func (c *Config) ShiftPrivateKey() (privKey *ecdsa.PrivateKey) {
}
return privKey
}
func (c *Config) setKey(prvKey *ecdsa.PrivateKey) {
bzzkeybytes := network.PrivateKeyToBzzKey(prvKey)
pubkey := crypto.FromECDSAPub(&prvKey.PublicKey)
pubkeyhex := hexutil.Encode(pubkey)
keyhex := hexutil.Encode(bzzkeybytes)
c.privateKey = prvKey
c.PublicKey = pubkeyhex
c.BzzKey = keyhex
}
func (c *Config) createAndSetPath(datadirPath string, prvKey *ecdsa.PrivateKey) error {
address := crypto.PubkeyToAddress(prvKey.PublicKey)
bzzdirPath := filepath.Join(datadirPath, "bzz-"+common.Bytes2Hex(address.Bytes()))
err := os.MkdirAll(bzzdirPath, os.ModePerm)
if err != nil {
return err
}
c.Path = bzzdirPath
return nil
}

View file

@ -27,11 +27,16 @@ import (
func TestConfig(t *testing.T) {
var hexprvkey = "65138b2aa745041b372153550584587da326ab440576b2a1191dd95cee30039c"
var hexnodekey = "75138b2aa745041b372153550584587da326ab440576b2a1191dd95cee30039c"
prvkey, err := crypto.HexToECDSA(hexprvkey)
if err != nil {
t.Fatalf("failed to load private key: %v", err)
}
nodekey, err := crypto.HexToECDSA(hexnodekey)
if err != nil {
t.Fatalf("failed to load private key: %v", err)
}
one := NewConfig()
two := NewConfig()
@ -41,7 +46,10 @@ func TestConfig(t *testing.T) {
t.Fatal("Two default configs are not equal")
}
one.Init(prvkey)
err = one.Init(prvkey, nodekey)
if err != nil {
t.Fatal(err)
}
//the init function should set the following fields
if one.BzzKey == "" {

View file

@ -204,24 +204,24 @@ func (f *Fetcher) run(peers *sync.Map) {
// incoming request
case hopCount = <-f.requestC:
log.Trace("new request", "request addr", f.addr)
// 2) chunk is requested, set requested flag
// launch a request iff none been launched yet
doRequest = !requested
log.Trace("new request", "request addr", f.addr, "doRequest", doRequest)
requested = true
// peer we requested from is gone. fall back to another
// and remove the peer from the peers map
case id := <-gone:
log.Trace("peer gone", "peer id", id.String(), "request addr", f.addr)
peers.Delete(id.String())
doRequest = requested
log.Trace("peer gone", "peer id", id.String(), "request addr", f.addr, "doRequest", doRequest)
// search timeout: too much time passed since the last request,
// extend the search to a new peer if we can find one
case <-waitC:
log.Trace("search timed out: requesting", "request addr", f.addr)
doRequest = requested
log.Trace("search timed out: requesting", "request addr", f.addr, "doRequest", doRequest)
// all Fetcher context closed, can quit
case <-f.ctx.Done():
@ -288,6 +288,7 @@ func (f *Fetcher) doRequest(gone chan *enode.ID, peersToSkip *sync.Map, sources
for i = 0; i < len(sources); i++ {
req.Source = sources[i]
var err error
log.Trace("fetcher.doRequest", "request addr", f.addr, "peer", req.Source.String())
sourceID, quit, err = f.protoRequestFunc(f.ctx, req)
if err == nil {
// remove the peer from known sources

View file

@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
)
// BzzAddr implements the PeerAddr interface
@ -68,3 +69,37 @@ func PrivateKeyToBzzKey(prvKey *ecdsa.PrivateKey) []byte {
pubkeyBytes := crypto.FromECDSAPub(&prvKey.PublicKey)
return crypto.Keccak256Hash(pubkeyBytes).Bytes()
}
type EnodeParams struct {
PrivateKey *ecdsa.PrivateKey
EnodeKey *ecdsa.PrivateKey
Lightnode bool
Bootnode bool
}
func NewEnodeRecord(params *EnodeParams) (*enr.Record, error) {
if params.PrivateKey == nil {
return nil, fmt.Errorf("all param private keys must be defined")
}
bzzkeybytes := PrivateKeyToBzzKey(params.PrivateKey)
var record enr.Record
record.Set(NewENRAddrEntry(bzzkeybytes))
record.Set(ENRLightNodeEntry(params.Lightnode))
record.Set(ENRBootNodeEntry(params.Bootnode))
return &record, nil
}
func NewEnode(params *EnodeParams) (*enode.Node, error) {
record, err := NewEnodeRecord(params)
if err != nil {
return nil, err
}
err = enode.SignV4(record, params.EnodeKey)
if err != nil {
return nil, fmt.Errorf("ENR create fail: %v", err)
}
return enode.New(enode.V4ID{}, record)
}

View file

@ -28,8 +28,9 @@ package priorityqueue
import (
"context"
"errors"
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
var (
@ -69,13 +70,16 @@ READ:
case <-ctx.Done():
return
case x := <-q:
log.Trace("priority.queue f(x)", "p", p, "len(Queues[p])", len(pq.Queues[p]))
f(x)
val := x.(struct {
v interface{}
t time.Time
})
f(val.v)
metrics.GetOrRegisterResettingTimer("pq.run", nil).UpdateSince(val.t)
p = top
default:
if p > 0 {
p--
log.Trace("priority.queue p > 0", "p", p)
continue READ
}
p = top
@ -83,7 +87,6 @@ READ:
case <-ctx.Done():
return
case <-pq.wakeup:
log.Trace("priority.queue wakeup", "p", p)
}
}
}
@ -95,9 +98,15 @@ func (pq *PriorityQueue) Push(x interface{}, p int) error {
if p < 0 || p >= len(pq.Queues) {
return errBadPriority
}
log.Trace("priority.queue push", "p", p, "len(Queues[p])", len(pq.Queues[p]))
val := struct {
v interface{}
t time.Time
}{
x,
time.Now(),
}
select {
case pq.Queues[p] <- x:
case pq.Queues[p] <- val:
default:
return ErrContention
}

View file

@ -103,7 +103,7 @@ func (s *Simulation) kademlias() (ks map[enode.ID]*network.Kademlia) {
// in the snapshot are registered in the kademlia.
// It differs from WaitTillHealthy, which waits only until all the kademlias are
// healthy (it might happen even before all the connections are established).
func (s *Simulation) WaitTillSnapshotRecreated(ctx context.Context, snap simulations.Snapshot) error {
func (s *Simulation) WaitTillSnapshotRecreated(ctx context.Context, snap *simulations.Snapshot) error {
expected := getSnapshotConnections(snap.Conns)
ticker := time.NewTicker(150 * time.Millisecond)
defer ticker.Stop()

View file

@ -182,7 +182,7 @@ func TestWaitTillSnapshotRecreated(t *testing.T) {
if err != nil {
t.Fatal(err)
}
err = controlSim.WaitTillSnapshotRecreated(ctx, *snap)
err = controlSim.WaitTillSnapshotRecreated(ctx, snap)
if err != nil {
t.Fatal(err)
}

View file

@ -17,20 +17,28 @@
package simulation
import (
"bytes"
"context"
"crypto/ecdsa"
"encoding/json"
"errors"
"io/ioutil"
"math/rand"
"os"
"sync"
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/simulations"
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
"github.com/ethereum/go-ethereum/swarm/network"
)
var (
BucketKeyBzzPrivateKey BucketKey = "bzzprivkey"
)
// NodeIDs returns NodeIDs for all nodes in the network.
func (s *Simulation) NodeIDs() (ids []enode.ID) {
nodes := s.Net.GetNodes()
@ -102,22 +110,26 @@ func (s *Simulation) AddNode(opts ...AddNodeOption) (id enode.ID, err error) {
// most importantly the bzz overlay address
//
// for now we have no way of setting bootnodes or lightnodes in sims
// so we just set them as false
// so we just let them be set to false
// they should perhaps be possible to override them with AddNodeOption
bzzKey := network.PrivateKeyToBzzKey(conf.PrivateKey)
bzzAddr := network.NewENRAddrEntry(bzzKey)
bzzPrivateKey, err := BzzPrivateKeyFromConfig(conf)
if err != nil {
return enode.ID{}, err
}
var lightnode network.ENRLightNodeEntry
var bootnode network.ENRBootNodeEntry
conf.Record.Set(bzzAddr)
conf.Record.Set(&lightnode)
conf.Record.Set(&bootnode)
enodeParams := &network.EnodeParams{
PrivateKey: bzzPrivateKey,
}
record, err := network.NewEnodeRecord(enodeParams)
conf.Record = *record
// Add the bzz address to the node config
node, err := s.Net.NewNodeWithConfig(conf)
if err != nil {
return id, err
}
s.buckets[node.ID()] = new(sync.Map)
s.SetNodeItem(node.ID(), BucketKeyBzzPrivateKey, bzzPrivateKey)
return node.ID(), s.Net.Start(node.ID())
}
@ -217,30 +229,24 @@ func (s *Simulation) AddNodesAndConnectStar(count int, opts ...AddNodeOption) (i
// UploadSnapshot uploads a snapshot to the simulation
// This method tries to open the json file provided, applies the config to all nodes
// and then loads the snapshot into the Simulation network
func (s *Simulation) UploadSnapshot(snapshotFile string, opts ...AddNodeOption) error {
func (s *Simulation) UploadSnapshot(ctx context.Context, snapshotFile string, opts ...AddNodeOption) error {
f, err := os.Open(snapshotFile)
if err != nil {
return err
}
defer func() {
err := f.Close()
if err != nil {
log.Error("Error closing snapshot file", "err", err)
}
}()
defer f.Close()
jsonbyte, err := ioutil.ReadAll(f)
if err != nil {
return err
}
var snap simulations.Snapshot
err = json.Unmarshal(jsonbyte, &snap)
if err != nil {
if err := json.Unmarshal(jsonbyte, &snap); err != nil {
return err
}
//the snapshot probably has the property EnableMsgEvents not set
//just in case, set it to true!
//(we need this to wait for messages before uploading)
//set it to true (we need this to wait for messages before uploading)
for i := range snap.Nodes {
snap.Nodes[i].Node.Config.EnableMsgEvents = true
snap.Nodes[i].Node.Config.Services = s.serviceNames
@ -249,15 +255,10 @@ func (s *Simulation) UploadSnapshot(snapshotFile string, opts ...AddNodeOption)
}
}
log.Info("Waiting for p2p connections to be established...")
//now we can load the snapshot
err = s.Net.Load(&snap)
if err != nil {
if err := s.Net.Load(&snap); err != nil {
return err
}
log.Info("Snapshot loaded")
return nil
return s.WaitTillSnapshotRecreated(ctx, &snap)
}
// StartNode starts a node by NodeID.
@ -326,3 +327,15 @@ func (s *Simulation) StopRandomNodes(count int) (ids []enode.ID, err error) {
func init() {
rand.Seed(time.Now().UnixNano())
}
// derive a private key for swarm for the node key
// returns the private key used to generate the bzz key
func BzzPrivateKeyFromConfig(conf *adapters.NodeConfig) (*ecdsa.PrivateKey, error) {
// pad the seed key some arbitrary data as ecdsa.GenerateKey takes 40 bytes seed data
privKeyBuf := append(crypto.FromECDSA(conf.PrivateKey), []byte{0x62, 0x7a, 0x7a, 0x62, 0x7a, 0x7a, 0x62, 0x7a}...)
bzzPrivateKey, err := ecdsa.GenerateKey(crypto.S256(), bytes.NewReader(privKeyBuf))
if err != nil {
return nil, err
}
return bzzPrivateKey, nil
}

View file

@ -289,6 +289,7 @@ func TestUploadSnapshot(t *testing.T) {
HiveParams: hp,
}
kad := network.NewKademlia(addr.Over(), network.NewKadParams())
b.Store(BucketKeyKademlia, kad)
return network.NewBzz(config, kad, nil, nil, nil), nil, nil
},
})
@ -296,12 +297,13 @@ func TestUploadSnapshot(t *testing.T) {
nodeCount := 16
log.Debug("Uploading snapshot")
err := s.UploadSnapshot(fmt.Sprintf("../stream/testing/snapshot_%d.json", nodeCount))
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := s.UploadSnapshot(ctx, fmt.Sprintf("../stream/testing/snapshot_%d.json", nodeCount))
if err != nil {
t.Fatalf("Error uploading snapshot to simulation network: %v", err)
}
ctx := context.Background()
log.Debug("Starting simulation...")
s.Run(ctx, func(ctx context.Context, sim *Simulation) error {
log.Debug("Checking")

View file

@ -85,13 +85,16 @@ func New(services map[string]ServiceFunc) (s *Simulation) {
name, serviceFunc := name, serviceFunc
s.serviceNames = append(s.serviceNames, name)
adapterServices[name] = func(ctx *adapters.ServiceContext) (node.Service, error) {
b := new(sync.Map)
s.mu.Lock()
defer s.mu.Unlock()
b, ok := s.buckets[ctx.Config.ID]
if !ok {
b = new(sync.Map)
}
service, cleanup, err := serviceFunc(ctx, b)
if err != nil {
return nil, err
}
s.mu.Lock()
defer s.mu.Unlock()
if cleanup != nil {
s.cleanupFuncs = append(s.cleanupFuncs, cleanup)
}

View file

@ -131,7 +131,6 @@ func BenchmarkDiscovery_128_4(b *testing.B) { benchmarkDiscovery(b, 128, 4) }
func BenchmarkDiscovery_256_4(b *testing.B) { benchmarkDiscovery(b, 256, 4) }
func TestDiscoverySimulationExecAdapter(t *testing.T) {
t.Skip("This is left broken pending ENR preparations for swarm binary. Execadapter is not currently in use, so a short pause won't hurt")
testDiscoverySimulationExecAdapter(t, *nodeCount, *initCount)
}

View file

@ -185,6 +185,7 @@ func (d *Delivery) handleRetrieveRequestMsg(ctx context.Context, sp *Peer, req *
if err != nil {
log.Warn("ERROR in handleRetrieveRequestMsg", "err", err)
}
osp.LogFields(olog.Bool("delivered", true))
return
}
osp.LogFields(olog.Bool("skipCheck", false))
@ -216,6 +217,10 @@ type ChunkDeliveryMsgSyncing ChunkDeliveryMsg
// chunk delivery msg is response to retrieverequest msg
func (d *Delivery) handleChunkDeliveryMsg(ctx context.Context, sp *Peer, req *ChunkDeliveryMsg) error {
var osp opentracing.Span
ctx, osp = spancontext.StartSpan(
ctx,
"handle.chunk.delivery")
processReceivedChunksCount.Inc(1)
@ -223,13 +228,18 @@ func (d *Delivery) handleChunkDeliveryMsg(ctx context.Context, sp *Peer, req *Ch
spanId := fmt.Sprintf("stream.send.request.%v.%v", sp.ID(), req.Addr)
span := tracing.ShiftSpanByKey(spanId)
log.Trace("handle.chunk.delivery", "ref", req.Addr, "from peer", sp.ID())
go func() {
defer osp.Finish()
if span != nil {
span.LogFields(olog.String("finish", "from handleChunkDeliveryMsg"))
defer span.Finish()
}
req.peer = sp
log.Trace("handle.chunk.delivery", "put", req.Addr)
err := d.chunkStore.Put(ctx, storage.NewChunk(req.Addr, req.SData))
if err != nil {
if err == storage.ErrChunkInvalid {
@ -239,6 +249,7 @@ func (d *Delivery) handleChunkDeliveryMsg(ctx context.Context, sp *Peer, req *Ch
req.peer.Drop(err)
}
}
log.Trace("handle.chunk.delivery", "done put", req.Addr, "err", err)
}()
return nil
}
@ -284,6 +295,7 @@ func (d *Delivery) RequestFromPeers(ctx context.Context, req *network.Request) (
// this span will finish only when delivery is handled (or times out)
ctx = context.WithValue(ctx, tracing.StoreLabelId, "stream.send.request")
ctx = context.WithValue(ctx, tracing.StoreLabelMeta, fmt.Sprintf("%v.%v", sp.ID(), req.Addr))
log.Trace("request.from.peers", "peer", sp.ID(), "ref", req.Addr)
err := sp.SendPriority(ctx, &RetrieveRequestMsg{
Addr: req.Addr,
SkipCheck: req.SkipCheck,

View file

@ -22,8 +22,6 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/swarm/testutil"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
@ -31,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/swarm/network/simulation"
"github.com/ethereum/go-ethereum/swarm/state"
"github.com/ethereum/go-ethereum/swarm/storage"
"github.com/ethereum/go-ethereum/swarm/testutil"
)
//constants for random file generation
@ -155,14 +154,15 @@ func runFileRetrievalTest(nodeCount int) error {
//array where the generated chunk hashes will be stored
conf.hashes = make([]storage.Address, 0)
err := sim.UploadSnapshot(fmt.Sprintf("testing/snapshot_%d.json", nodeCount))
ctx, cancelSimRun := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancelSimRun()
filename := fmt.Sprintf("testing/snapshot_%d.json", nodeCount)
err := sim.UploadSnapshot(ctx, filename)
if err != nil {
return err
}
ctx, cancelSimRun := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancelSimRun()
log.Info("Starting simulation")
result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error {
@ -188,9 +188,6 @@ func runFileRetrievalTest(nodeCount int) error {
if err != nil {
return err
}
if _, err := sim.WaitTillHealthy(ctx); err != nil {
return err
}
log.Info("network healthy, start file checks")
@ -253,12 +250,15 @@ func runRetrievalTest(t *testing.T, chunkCount int, nodeCount int) error {
//array where the generated chunk hashes will be stored
conf.hashes = make([]storage.Address, 0)
err := sim.UploadSnapshot(fmt.Sprintf("testing/snapshot_%d.json", nodeCount))
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
filename := fmt.Sprintf("testing/snapshot_%d.json", nodeCount)
err := sim.UploadSnapshot(ctx, filename)
if err != nil {
return err
}
ctx := context.Background()
result := sim.Run(ctx, func(ctx context.Context, sim *simulation.Simulation) error {
nodeIDs := sim.UpNodeIDs()
for _, n := range nodeIDs {
@ -283,9 +283,6 @@ func runRetrievalTest(t *testing.T, chunkCount int, nodeCount int) error {
if err != nil {
return err
}
if _, err := sim.WaitTillHealthy(ctx); err != nil {
return err
}
// File retrieval check is repeated until all uploaded files are retrieved from all nodes
// or until the timeout is reached.

View file

@ -147,20 +147,16 @@ func testSyncingViaGlobalSync(t *testing.T, chunkCount int, nodeCount int) {
//array where the generated chunk hashes will be stored
conf.hashes = make([]storage.Address, 0)
err := sim.UploadSnapshot(fmt.Sprintf("testing/snapshot_%d.json", nodeCount))
ctx, cancelSimRun := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancelSimRun()
filename := fmt.Sprintf("testing/snapshot_%d.json", nodeCount)
err := sim.UploadSnapshot(ctx, filename)
if err != nil {
t.Fatal(err)
}
ctx, cancelSimRun := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancelSimRun()
if _, err := sim.WaitTillHealthy(ctx); err != nil {
t.Fatal(err)
}
result := runSim(conf, ctx, sim, chunkCount)
if result.Error != nil {
t.Fatal(result.Error)
}

View file

@ -910,7 +910,7 @@ func (r *Registry) APIs() []rpc.API {
Namespace: "stream",
Version: "3.0",
Service: r.api,
Public: true,
Public: false,
},
}
}

View file

@ -1257,9 +1257,10 @@ func TestGetSubscriptionsRPC(t *testing.T) {
simulation.NewPeerEventsFilter().ReceivedMessages().Protocol("stream").MsgCode(subscribeMsgCode),
)
// upload a snapshot
err := sim.UploadSnapshot(fmt.Sprintf("testing/snapshot_%d.json", nodeCount))
if err != nil {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
filename := fmt.Sprintf("testing/snapshot_%d.json", nodeCount)
if err := sim.UploadSnapshot(ctx, filename); err != nil {
t.Fatal(err)
}

View file

@ -311,8 +311,12 @@ func testSwarmNetwork(t *testing.T, o *testSwarmNetworkOptions, steps ...testSwa
if err != nil {
return nil, cleanup, err
}
nodekey, err := crypto.GenerateKey()
if err != nil {
return nil, cleanup, err
}
config.Init(privkey)
config.Init(privkey, nodekey)
config.DeliverySkipCheck = o.SkipCheck
config.Port = ""

View file

@ -2,12 +2,10 @@ package pss
import (
"context"
"crypto/ecdsa"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"sync"
@ -20,7 +18,6 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/simulations"
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/swarm/network"
@ -92,7 +89,7 @@ func (d *testData) setDone() {
d.handlerDone = true
}
func getCmdParams(t *testing.T) (int, int) {
func getCmdParams(t *testing.T) (int, int, time.Duration) {
args := strings.Split(t.Name(), "/")
msgCount, err := strconv.ParseInt(args[2], 10, 16)
if err != nil {
@ -102,25 +99,12 @@ func getCmdParams(t *testing.T) (int, int) {
if err != nil {
t.Fatal(err)
}
return int(msgCount), int(nodeCount)
}
func readSnapshot(t *testing.T, nodeCount int) simulations.Snapshot {
f, err := os.Open(fmt.Sprintf("testdata/snapshot_%d.json", nodeCount))
timeoutStr := fmt.Sprintf("%ss", args[3])
timeoutDur, err := time.ParseDuration(timeoutStr)
if err != nil {
t.Fatal(err)
}
defer f.Close()
jsonbyte, err := ioutil.ReadAll(f)
if err != nil {
t.Fatal(err)
}
var snap simulations.Snapshot
err = json.Unmarshal(jsonbyte, &snap)
if err != nil {
t.Fatal(err)
}
return snap
return int(msgCount), int(nodeCount), timeoutDur
}
func newTestData() *testData {
@ -139,11 +123,27 @@ func newTestData() *testData {
}
}
func (d *testData) init(msgCount int) {
func (d *testData) getKademlia(nodeId *enode.ID) (*network.Kademlia, error) {
kadif, ok := d.sim.NodeItem(*nodeId, simulation.BucketKeyKademlia)
if !ok {
return nil, fmt.Errorf("no kademlia entry for %v", nodeId)
}
kad, ok := kadif.(*network.Kademlia)
if !ok {
return nil, fmt.Errorf("invalid kademlia entry for %v", nodeId)
}
return kad, nil
}
func (d *testData) init(msgCount int) error {
log.Debug("TestProxNetwork start")
for _, nodeId := range d.sim.NodeIDs() {
d.nodeAddrs[nodeId] = nodeIDToAddr(nodeId)
kad, err := d.getKademlia(&nodeId)
if err != nil {
return err
}
d.nodeAddrs[nodeId] = kad.BaseAddr()
}
for i := 0; i < int(msgCount); i++ {
@ -191,6 +191,7 @@ func (d *testData) init(msgCount int) {
log.Debug("nn for msg", "targets", len(d.recipients[i]), "msgidx", i, "msg", common.Bytes2Hex(msgAddr[:8]), "sender", d.senders[i], "senderpo", smallestPo)
}
log.Debug("msgs to receive", "count", d.requiredMessages)
return nil
}
// Here we test specific functionality of the pss, setting the prox property of
@ -212,7 +213,7 @@ func (d *testData) init(msgCount int) {
// nodes Y and Z will be considered required recipients of the msg,
// whereas nodes X, Y and Z will be allowed recipients.
func TestProxNetwork(t *testing.T) {
t.Run("16/16", testProxNetwork)
t.Run("16/16/15", testProxNetwork)
}
// params in run name: nodes/msgs
@ -220,33 +221,32 @@ func TestProxNetworkLong(t *testing.T) {
if !*longrunning {
t.Skip("run with --longrunning flag to run extensive network tests")
}
t.Run("8/100", testProxNetwork)
t.Run("16/100", testProxNetwork)
t.Run("32/100", testProxNetwork)
t.Run("64/100", testProxNetwork)
t.Run("128/100", testProxNetwork)
t.Run("8/100/30", testProxNetwork)
t.Run("16/100/30", testProxNetwork)
t.Run("32/100/60", testProxNetwork)
t.Run("64/100/60", testProxNetwork)
t.Run("128/100/120", testProxNetwork)
}
func testProxNetwork(t *testing.T) {
tstdata := newTestData()
msgCount, nodeCount := getCmdParams(t)
msgCount, nodeCount, timeout := getCmdParams(t)
handlerContextFuncs := make(map[Topic]handlerContextFunc)
handlerContextFuncs[topic] = nodeMsgHandler
services := newProxServices(tstdata, true, handlerContextFuncs, tstdata.kademlias)
tstdata.sim = simulation.New(services)
defer tstdata.sim.Close()
err := tstdata.sim.UploadSnapshot(fmt.Sprintf("testdata/snapshot_%d.json", nodeCount))
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
filename := fmt.Sprintf("testdata/snapshot_%d.json", nodeCount)
err := tstdata.sim.UploadSnapshot(ctx, filename)
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*120)
defer cancel()
snap := readSnapshot(t, nodeCount)
err = tstdata.sim.WaitTillSnapshotRecreated(ctx, snap)
err = tstdata.init(msgCount) // initialize the test data
if err != nil {
t.Fatalf("failed to recreate snapshot: %s", err)
t.Fatal(err)
}
tstdata.init(msgCount) // initialize the test data
wrapper := func(c context.Context, _ *simulation.Simulation) error {
return testRoutine(tstdata, c)
}
@ -256,7 +256,7 @@ func testProxNetwork(t *testing.T) {
// however, it might just mean that not all possible messages are received
// now we must check if all required messages are received
cnt := tstdata.getMsgCount()
log.Debug("TestProxNetwork finnished", "rcv", cnt)
log.Debug("TestProxNetwork finished", "rcv", cnt)
if cnt < tstdata.requiredMessages {
t.Fatal(result.Error)
}
@ -380,7 +380,7 @@ func nodeMsgHandler(tstdata *testData, config *adapters.NodeConfig) *handler {
// replaces pss_test.go when those tests are rewritten to the new swarm/network/simulation package
func newProxServices(tstdata *testData, allowRaw bool, handlerContextFuncs map[Topic]handlerContextFunc, kademlias map[enode.ID]*network.Kademlia) map[string]simulation.ServiceFunc {
stateStore := state.NewInmemoryStore()
kademlia := func(id enode.ID) *network.Kademlia {
kademlia := func(id enode.ID, bzzkey []byte) *network.Kademlia {
if k, ok := kademlias[id]; ok {
return k
}
@ -390,17 +390,24 @@ func newProxServices(tstdata *testData, allowRaw bool, handlerContextFuncs map[T
params.MaxRetries = 1000
params.RetryExponent = 2
params.RetryInterval = 1000000
kademlias[id] = network.NewKademlia(id[:], params)
kademlias[id] = network.NewKademlia(bzzkey, params)
return kademlias[id]
}
return map[string]simulation.ServiceFunc{
"bzz": func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) {
var err error
var bzzPrivateKey *ecdsa.PrivateKey
// normally translation of enode id to swarm address is concealed by the network package
// however, we need to keep track of it in the test driver as well.
// if the translation in the network package changes, that can cause these tests to unpredictably fail
// therefore we keep a local copy of the translation here
addr := network.NewAddr(ctx.Config.Node())
addr.OAddr = nodeIDToAddr(ctx.Config.Node().ID())
bzzPrivateKey, err = simulation.BzzPrivateKeyFromConfig(ctx.Config)
if err != nil {
return nil, nil, err
}
addr.OAddr = network.PrivateKeyToBzzKey(bzzPrivateKey)
b.Store(simulation.BucketKeyBzzPrivateKey, bzzPrivateKey)
hp := network.NewHiveParams()
hp.Discovery = false
config := &network.BzzConfig{
@ -408,7 +415,7 @@ func newProxServices(tstdata *testData, allowRaw bool, handlerContextFuncs map[T
UnderlayAddr: addr.Under(),
HiveParams: hp,
}
return network.NewBzz(config, kademlia(ctx.Config.ID), stateStore, nil, nil), nil, nil
return network.NewBzz(config, kademlia(ctx.Config.ID, addr.OAddr), stateStore, nil, nil), nil, nil
},
"pss": func(ctx *adapters.ServiceContext, b *sync.Map) (node.Service, func(), error) {
// execadapter does not exec init()
@ -421,12 +428,16 @@ func newProxServices(tstdata *testData, allowRaw bool, handlerContextFuncs map[T
privkey, err := w.GetPrivateKey(keys)
pssp := NewPssParams().WithPrivateKey(privkey)
pssp.AllowRaw = allowRaw
pskad := kademlia(ctx.Config.ID)
bzzPrivateKey, err := simulation.BzzPrivateKeyFromConfig(ctx.Config)
if err != nil {
return nil, nil, err
}
bzzKey := network.PrivateKeyToBzzKey(bzzPrivateKey)
pskad := kademlia(ctx.Config.ID, bzzKey)
ps, err := NewPss(pskad, pssp)
if err != nil {
return nil, nil, err
}
b.Store(simulation.BucketKeyKademlia, pskad)
// register the handlers we've been passed
var deregisters []func()
@ -448,6 +459,8 @@ func newProxServices(tstdata *testData, allowRaw bool, handlerContextFuncs map[T
Public: false,
})
b.Store(simulation.BucketKeyKademlia, pskad)
// return Pss and cleanups
return ps, func() {
// run the handler deregister functions in reverse order
@ -458,8 +471,3 @@ func newProxServices(tstdata *testData, allowRaw bool, handlerContextFuncs map[T
},
}
}
// makes sure we create the addresses the same way in driver and service setup
func nodeIDToAddr(id enode.ID) []byte {
return id.Bytes()
}

View file

@ -536,7 +536,6 @@ func (r *LazyChunkReader) join(ctx context.Context, b []byte, off int64, eoff in
chunkData, err := r.getter.Get(ctx, Reference(childAddress))
if err != nil {
metrics.GetOrRegisterResettingTimer("lcr.getter.get.err", nil).UpdateSince(startTime)
log.Debug("lazychunkreader.join", "key", fmt.Sprintf("%x", childAddress), "err", err)
select {
case errC <- fmt.Errorf("chunk %v-%v not found; key: %s", off, off+treeSize, fmt.Sprintf("%x", childAddress)):
case <-quitC:
@ -561,12 +560,12 @@ func (r *LazyChunkReader) join(ctx context.Context, b []byte, off int64, eoff in
// Read keeps a cursor so cannot be called simulateously, see ReadAt
func (r *LazyChunkReader) Read(b []byte) (read int, err error) {
log.Debug("lazychunkreader.read", "key", r.addr)
log.Trace("lazychunkreader.read", "key", r.addr)
metrics.GetOrRegisterCounter("lazychunkreader.read", nil).Inc(1)
read, err = r.ReadAt(b, r.off)
if err != nil && err != io.EOF {
log.Debug("lazychunkreader.readat", "read", read, "err", err)
log.Trace("lazychunkreader.readat", "read", read, "err", err)
metrics.GetOrRegisterCounter("lazychunkreader.read.err", nil).Inc(1)
}

View file

@ -87,7 +87,9 @@ func (n *NetStore) Put(ctx context.Context, ch Chunk) error {
// if chunk is now put in the store, check if there was an active fetcher and call deliver on it
// (this delivers the chunk to requestors via the fetcher)
log.Trace("n.getFetcher", "ref", ch.Address())
if f := n.getFetcher(ch.Address()); f != nil {
log.Trace("n.getFetcher deliver", "ref", ch.Address())
f.deliver(ctx, ch)
}
return nil
@ -341,5 +343,6 @@ func (f *fetcher) deliver(ctx context.Context, ch Chunk) {
f.chunk = ch
// closing the deliveredC channel will terminate ongoing requests
close(f.deliveredC)
log.Trace("n.getFetcher close deliveredC", "ref", ch.Address())
})
}

View file

@ -36,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/protocols"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
@ -171,10 +170,7 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e
self.accountingMetrics = protocols.SetupAccountingMetrics(10*time.Second, filepath.Join(config.Path, "metrics.db"))
}
var nodeID enode.ID
if err := nodeID.UnmarshalText([]byte(config.NodeID)); err != nil {
return nil, err
}
nodeID := config.Enode.ID()
syncing := stream.SyncingAutoSubscribe
if !config.SyncEnabled || config.LightNodeEnabled {
@ -522,6 +518,8 @@ func (s *Swarm) APIs() []rpc.API {
apis = append(apis, s.bzz.APIs()...)
apis = append(apis, s.streamer.APIs()...)
if s.ps != nil {
apis = append(apis, s.ps.APIs()...)
}

View file

@ -170,8 +170,12 @@ func TestNewSwarm(t *testing.T) {
if err != nil {
t.Fatal(err)
}
nodekey, err := crypto.GenerateKey()
if err != nil {
t.Fatal(err)
}
config.Init(privkey)
config.Init(privkey, nodekey)
if tc.configure != nil {
tc.configure(config)
@ -307,8 +311,12 @@ func TestLocalStoreAndRetrieve(t *testing.T) {
if err != nil {
t.Fatal(err)
}
nodekey, err := crypto.GenerateKey()
if err != nil {
t.Fatal(err)
}
config.Init(privkey)
config.Init(privkey, nodekey)
swarm, err := NewSwarm(config, nil)
if err != nil {

View file

@ -17,6 +17,7 @@
package trie
import (
"encoding/binary"
"fmt"
"io"
"sync"
@ -257,6 +258,19 @@ func expandNode(hash hashNode, n node) node {
}
}
// trienodeHasher is a struct to be used with BigCache, which uses a Hasher to
// determine which shard to place an entry into. It's not a cryptographic hash,
// just to provide a bit of anti-collision (default is FNV64a).
//
// Since trie keys are already hashes, we can just use the key directly to
// map shard id.
type trienodeHasher struct{}
// Sum64 implements the bigcache.Hasher interface.
func (t trienodeHasher) Sum64(key string) uint64 {
return binary.BigEndian.Uint64([]byte(key))
}
// NewDatabase creates a new trie database to store ephemeral trie content before
// its written out to disk or garbage collected. No read cache is created, so all
// data retrievals will hit the underlying disk database.
@ -276,6 +290,7 @@ func NewDatabaseWithCache(diskdb ethdb.KeyValueStore, cache int) *Database {
MaxEntriesInWindow: cache * 1024,
MaxEntrySize: 512,
HardMaxCacheSize: cache,
Hasher: trienodeHasher{},
})
}
return &Database{

View file

@ -10,5 +10,5 @@ Changes by Version
1.0.0 (2016-09-26)
-------------------
- This release implements OpenTracing Specification 1.0 (http://opentracing.io/spec)
- This release implements OpenTracing Specification 1.0 (https://opentracing.io/spec)

View file

@ -1,26 +1,15 @@
PACKAGES := . ./mocktracer/... ./ext/...
.DEFAULT_GOAL := test-and-lint
.PHONE: test-and-lint
.PHONY: test-and-lint
test-and-lint: test lint
.PHONY: test
test:
go test -v -cover -race ./...
.PHONY: cover
cover:
@rm -rf cover-all.out
$(foreach pkg, $(PACKAGES), $(MAKE) cover-pkg PKG=$(pkg) || true;)
@grep mode: cover.out > coverage.out
@cat cover-all.out >> coverage.out
go tool cover -html=coverage.out -o cover.html
@rm -rf cover.out cover-all.out coverage.out
cover-pkg:
go test -coverprofile cover.out $(PKG)
@grep -v mode: cover.out >> cover-all.out
go test -v -coverprofile=coverage.txt -covermode=atomic -race ./...
.PHONY: lint
lint:
@ -29,4 +18,3 @@ lint:
@# Run again with magic to exit non-zero if golint outputs anything.
@! (golint ./... | read dummy)
go vet ./...

View file

@ -8,8 +8,8 @@ This package is a Go platform API for OpenTracing.
## Required Reading
In order to understand the Go platform API, one must first be familiar with the
[OpenTracing project](http://opentracing.io) and
[terminology](http://opentracing.io/documentation/pages/spec.html) more specifically.
[OpenTracing project](https://opentracing.io) and
[terminology](https://opentracing.io/specification/) more specifically.
## API overview for those adding instrumentation

View file

@ -1,7 +1,12 @@
package opentracing
type registeredTracer struct {
tracer Tracer
isRegistered bool
}
var (
globalTracer Tracer = NoopTracer{}
globalTracer = registeredTracer{NoopTracer{}, false}
)
// SetGlobalTracer sets the [singleton] opentracing.Tracer returned by
@ -11,22 +16,27 @@ var (
// Prior to calling `SetGlobalTracer`, any Spans started via the `StartSpan`
// (etc) globals are noops.
func SetGlobalTracer(tracer Tracer) {
globalTracer = tracer
globalTracer = registeredTracer{tracer, true}
}
// GlobalTracer returns the global singleton `Tracer` implementation.
// Before `SetGlobalTracer()` is called, the `GlobalTracer()` is a noop
// implementation that drops all data handed to it.
func GlobalTracer() Tracer {
return globalTracer
return globalTracer.tracer
}
// StartSpan defers to `Tracer.StartSpan`. See `GlobalTracer()`.
func StartSpan(operationName string, opts ...StartSpanOption) Span {
return globalTracer.StartSpan(operationName, opts...)
return globalTracer.tracer.StartSpan(operationName, opts...)
}
// InitGlobalTracer is deprecated. Please use SetGlobalTracer.
func InitGlobalTracer(tracer Tracer) {
SetGlobalTracer(tracer)
}
// IsGlobalTracerRegistered returns a `bool` to indicate if a tracer has been globally registered
func IsGlobalTracerRegistered() bool {
return globalTracer.isRegistered
}

View file

@ -160,7 +160,7 @@ type HTTPHeadersCarrier http.Header
// Set conforms to the TextMapWriter interface.
func (c HTTPHeadersCarrier) Set(key, val string) {
h := http.Header(c)
h.Add(key, val)
h.Set(key, val)
}
// ForeachKey conforms to the TextMapReader interface.

6
vendor/vendor.json vendored
View file

@ -352,10 +352,10 @@
"revisionTime": "2017-01-28T05:05:32Z"
},
{
"checksumSHA1": "wIcN7tZiF441h08RHAm4NV8cYO4=",
"checksumSHA1": "a/DHmc9bdsYlZZcwp6i3xhvV7Pk=",
"path": "github.com/opentracing/opentracing-go",
"revision": "bd9c3193394760d98b2fa6ebb2291f0cd1d06a7d",
"revisionTime": "2018-06-06T20:41:48Z"
"revision": "25a84ff92183e2f8ac018ba1db54f8a07b3c0e04",
"revisionTime": "2019-02-18T02:30:34Z"
},
{
"checksumSHA1": "uhDxBvLEqRAMZKgpTZ8MFuLIIM8=",