cmd/swarm: Support using Mainnet for resolving ENS names

Signed-off-by: Lewis Marshall <lewis@lmars.net>
This commit is contained in:
Lewis Marshall 2017-06-18 00:25:39 +02:00
parent feb2932706
commit f3359d5e58
4 changed files with 109 additions and 18 deletions

View File

@ -17,21 +17,25 @@
package main package main
import ( import (
"context"
"crypto/ecdsa" "crypto/ecdsa"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math/big"
"os" "os"
"os/signal" "os/signal"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
"time"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/console"
"github.com/ethereum/go-ethereum/contracts/ens"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/debug"
@ -40,6 +44,7 @@ import (
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/swarm" "github.com/ethereum/go-ethereum/swarm"
bzzapi "github.com/ethereum/go-ethereum/swarm/api" bzzapi "github.com/ethereum/go-ethereum/swarm/api"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
@ -87,15 +92,27 @@ var (
Name: "swap", Name: "swap",
Usage: "Swarm SWAP enabled (default false)", Usage: "Swarm SWAP enabled (default false)",
} }
SwarmSwapAPIFlag = cli.StringFlag{
Name: "swap-api",
Usage: "URL of the Ethereum API provider to use to settle SWAP payments",
}
SwarmSyncEnabledFlag = cli.BoolTFlag{ SwarmSyncEnabledFlag = cli.BoolTFlag{
Name: "sync", Name: "sync",
Usage: "Swarm Syncing enabled (default true)", Usage: "Swarm Syncing enabled (default true)",
} }
EthAPIFlag = cli.StringFlag{ EthAPIFlag = cli.StringFlag{
Name: "ethapi", Name: "ethapi",
Usage: "URL of the Ethereum API provider", Usage: "DEPRECATED: please use --ens-api and --swap-api",
}
EnsAPIFlag = cli.StringFlag{
Name: "ens-api",
Usage: "URL of the Ethereum API provider to use for ENS record lookups",
Value: node.DefaultIPCEndpoint("geth"), Value: node.DefaultIPCEndpoint("geth"),
} }
EnsAddrFlag = cli.StringFlag{
Name: "ens-addr",
Usage: "ENS contract address (default is detected as testnet or mainnet using --ens-api)",
}
SwarmApiFlag = cli.StringFlag{ SwarmApiFlag = cli.StringFlag{
Name: "bzzapi", Name: "bzzapi",
Usage: "Swarm HTTP endpoint", Usage: "Swarm HTTP endpoint",
@ -250,8 +267,11 @@ Cleans database of corrupted entries.
// bzzd-specific flags // bzzd-specific flags
CorsStringFlag, CorsStringFlag,
EthAPIFlag, EthAPIFlag,
EnsAPIFlag,
EnsAddrFlag,
SwarmConfigPathFlag, SwarmConfigPathFlag,
SwarmSwapEnabledFlag, SwarmSwapEnabledFlag,
SwarmSwapAPIFlag,
SwarmSyncEnabledFlag, SwarmSyncEnabledFlag,
SwarmListenAddrFlag, SwarmListenAddrFlag,
SwarmPortFlag, SwarmPortFlag,
@ -333,6 +353,38 @@ func bzzd(ctx *cli.Context) error {
return nil return nil
} }
// detectEnsAddr determines the ENS contract address by getting both the
// version and genesis hash using the client and matching them to either
// mainnet or testnet addresses
func detectEnsAddr(client *rpc.Client) (common.Address, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var version string
if err := client.CallContext(ctx, &version, "net_version"); err != nil {
return common.Address{}, err
}
block, err := ethclient.NewClient(client).BlockByNumber(ctx, big.NewInt(0))
if err != nil {
return common.Address{}, err
}
switch {
case version == "1" && block.Hash() == params.MainNetGenesisHash:
log.Info("using Mainnet ENS contract address", "addr", ens.MainNetAddress)
return ens.MainNetAddress, nil
case version == "3" && block.Hash() == params.TestNetGenesisHash:
log.Info("using Testnet ENS contract address", "addr", ens.TestNetAddress)
return ens.TestNetAddress, nil
default:
return common.Address{}, fmt.Errorf("unknown version and genesis hash: %s %s", version, block.Hash())
}
}
func registerBzzService(ctx *cli.Context, stack *node.Node) { func registerBzzService(ctx *cli.Context, stack *node.Node) {
prvkey := getAccount(ctx, stack) prvkey := getAccount(ctx, stack)
@ -357,19 +409,56 @@ func registerBzzService(ctx *cli.Context, stack *node.Node) {
syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabledFlag.Name) syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabledFlag.Name)
ethapi := ctx.GlobalString(EthAPIFlag.Name) ethapi := ctx.GlobalString(EthAPIFlag.Name)
if ethapi != "" {
log.Warn("DEPRECATED: --ethapi is deprecated and will be removed in a future version, please use --ens-api and --swap-api")
}
swapapi := ctx.GlobalString(SwarmSwapAPIFlag.Name)
if swapEnabled && swapapi == "" {
utils.Fatalf("SWAP is enabled but --swap-api is not set")
}
ensapi := ctx.GlobalString(EnsAPIFlag.Name)
// use the deprecated --ethapi if --ens-api is not set
if ensapi == "" {
ensapi = ethapi
}
ensAddr := ctx.GlobalString(EnsAddrFlag.Name)
cors := ctx.GlobalString(CorsStringFlag.Name) cors := ctx.GlobalString(CorsStringFlag.Name)
boot := func(ctx *node.ServiceContext) (node.Service, error) { boot := func(ctx *node.ServiceContext) (node.Service, error) {
var client *ethclient.Client var swapClient *ethclient.Client
if len(ethapi) > 0 { if swapapi != "" {
client, err = ethclient.Dial(ethapi) log.Info("connecting to SWAP API", "url", swapapi)
swapClient, err = ethclient.Dial(swapapi)
if err != nil { if err != nil {
utils.Fatalf("Can't connect: %v", err) return nil, fmt.Errorf("error connecting to SWAP API %s: %s", swapapi, err)
} }
}
var ensClient *ethclient.Client
if ensapi != "" {
log.Info("connecting to ENS API", "url", ensapi)
client, err := rpc.Dial(ensapi)
if err != nil {
return nil, fmt.Errorf("error connecting to ENS API %s: %s", ensapi, err)
}
ensClient = ethclient.NewClient(client)
if ensAddr != "" {
bzzconfig.EnsRoot = common.HexToAddress(ensAddr)
} else { } else {
swapEnabled = false ensAddr, err := detectEnsAddr(client)
if err == nil {
bzzconfig.EnsRoot = ensAddr
} else {
log.Warn(fmt.Sprintf("could not determine ENS contract address, using default %s", bzzconfig.EnsRoot), "err", err)
} }
return swarm.NewSwarm(ctx, client, bzzconfig, swapEnabled, syncEnabled, cors) }
}
return swarm.NewSwarm(ctx, swapClient, ensClient, bzzconfig, swapEnabled, syncEnabled, cors)
} }
if err := stack.Register(boot); err != nil { if err := stack.Register(boot); err != nil {
utils.Fatalf("Failed to register the Swarm service: %v", err) utils.Fatalf("Failed to register the Swarm service: %v", err)

View File

@ -29,6 +29,11 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
var (
MainNetAddress = common.HexToAddress("0x314159265dD8dbb310642f98f50C066173C1259b")
TestNetAddress = common.HexToAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010")
)
// swarm domain name registry and resolver // swarm domain name registry and resolver
type ENS struct { type ENS struct {
*contract.ENSSession *contract.ENSSession

View File

@ -25,6 +25,7 @@ import (
"path/filepath" "path/filepath"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts/ens"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/swarm/network" "github.com/ethereum/go-ethereum/swarm/network"
"github.com/ethereum/go-ethereum/swarm/services/swap" "github.com/ethereum/go-ethereum/swarm/services/swap"
@ -36,10 +37,6 @@ const (
DefaultHTTPPort = "8500" DefaultHTTPPort = "8500"
) )
var (
ensRootAddress = common.HexToAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010")
)
// separate bzz directories // separate bzz directories
// allow several bzz nodes running in parallel // allow several bzz nodes running in parallel
type Config struct { type Config struct {
@ -84,7 +81,7 @@ func NewConfig(path string, contract common.Address, prvKey *ecdsa.PrivateKey, n
Swap: swap.DefaultSwapParams(contract, prvKey), Swap: swap.DefaultSwapParams(contract, prvKey),
PublicKey: pubkeyhex, PublicKey: pubkeyhex,
BzzKey: keyhex, BzzKey: keyhex,
EnsRoot: ensRootAddress, EnsRoot: ens.TestNetAddress,
NetworkId: networkId, NetworkId: networkId,
} }
data, err = ioutil.ReadFile(confpath) data, err = ioutil.ReadFile(confpath)
@ -129,7 +126,7 @@ func NewConfig(path string, contract common.Address, prvKey *ecdsa.PrivateKey, n
self.Swap.SetKey(prvKey) self.Swap.SetKey(prvKey)
if (self.EnsRoot == common.Address{}) { if (self.EnsRoot == common.Address{}) {
self.EnsRoot = ensRootAddress self.EnsRoot = ens.TestNetAddress
} }
return return

View File

@ -76,7 +76,7 @@ func (self *Swarm) API() *SwarmAPI {
// creates a new swarm service instance // creates a new swarm service instance
// implements node.Service // implements node.Service
func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.Config, swapEnabled, syncEnabled bool, cors string) (self *Swarm, err error) { func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, ensClient *ethclient.Client, config *api.Config, swapEnabled, syncEnabled bool, cors string) (self *Swarm, err error) {
if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) { if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) {
return nil, fmt.Errorf("empty public key") return nil, fmt.Errorf("empty public key")
} }
@ -136,10 +136,10 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.
// set up high level api // set up high level api
transactOpts := bind.NewKeyedTransactor(self.privateKey) transactOpts := bind.NewKeyedTransactor(self.privateKey)
if backend == (*ethclient.Client)(nil) { if ensClient == nil {
log.Warn("No ENS, please specify non-empty --ethapi to use domain name resolution") log.Warn("No ENS, please specify non-empty --ens-api to use domain name resolution")
} else { } else {
self.dns, err = ens.NewENS(transactOpts, config.EnsRoot, self.backend) self.dns, err = ens.NewENS(transactOpts, config.EnsRoot, ensClient)
if err != nil { if err != nil {
return nil, err return nil, err
} }