From bc2483eaffdf2a0e53b4a455936af357a5e23e61 Mon Sep 17 00:00:00 2001 From: lash Date: Mon, 18 Mar 2019 12:54:02 +0100 Subject: [PATCH] cmd/swarm, p2p, swarm: Enable ENR in binary/execadapter --- cmd/swarm/config.go | 12 +++++--- cmd/swarm/config_test.go | 43 +++++++++++++++----------- cmd/swarm/main.go | 5 ++- cmd/swarm/run_test.go | 13 ++++++-- p2p/simulations/adapters/exec.go | 14 +++++++++ p2p/simulations/adapters/inproc.go | 20 +++--------- p2p/simulations/adapters/types.go | 29 ++++++++++++++++++ swarm/api/config.go | 49 ++++++++++++++++++++---------- swarm/swarm.go | 11 ++++--- 9 files changed, 133 insertions(+), 63 deletions(-) diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index a941b37579..dad8cdbbd2 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -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) 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) + if err != nil { + return err + } //configuration phase completed here - log.Debug("Starting Swarm with the following parameters:") + log.Info("Starting Swarm with the following parameters:") //after having created the config, print it to screen - log.Debug(printConfig(config)) + log.Info(printConfig(config)) + return nil } //configFileOverride overrides the current config with the config file, if a config file has been provided diff --git a/cmd/swarm/config_test.go b/cmd/swarm/config_test.go index 869edd0f70..ee6b0c0825 100644 --- a/cmd/swarm/config_test.go +++ b/cmd/swarm/config_test.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/swarm" "github.com/ethereum/go-ethereum/swarm/api" + "github.com/ethereum/go-ethereum/swarm/log" ) func TestConfigDump(t *testing.T) { @@ -161,6 +162,16 @@ func TestConfigFileOverrides(t *testing.T) { defaultConf.HiveParams.KeepAliveInterval = 6000000000 defaultConf.Swap.Params.Strategy.AutoCashInterval = 600 * time.Second //defaultConf.SyncParams.KeyBufferSize = 512 + + dir, err := ioutil.TempDir("", "bzztest") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + conf, account, pk := getTestAccountWithPrivateKey(t, dir) + node := &testNode{Dir: dir} + defaultConf.Init(pk) + //create a TOML string out, err := tomlSettings.Marshal(&defaultConf) if err != nil { @@ -178,14 +189,6 @@ func TestConfigFileOverrides(t *testing.T) { } f.Sync() - dir, err := ioutil.TempDir("", "bzztest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - conf, account := getTestAccount(t, dir) - node := &testNode{Dir: dir} - flags := []string{ fmt.Sprintf("--%s", SwarmTomlConfigPathFlag.Name), f.Name(), fmt.Sprintf("--%s", SwarmAccountFlag.Name), account.Address.String(), @@ -372,6 +375,19 @@ func TestConfigCmdLineOverridesFile(t *testing.T) { defaultConf.HiveParams.KeepAliveInterval = 6000000000 defaultConf.Swap.Params.Strategy.AutoCashInterval = 600 * time.Second //defaultConf.SyncParams.KeyBufferSize = 512 + + dir, err := ioutil.TempDir("", "bzztest") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + conf, account, pk := getTestAccountWithPrivateKey(t, dir) + node := &testNode{Dir: dir} + + expectNetworkId := uint64(77) + + defaultConf.Init(pk) + //create a TOML file out, err := tomlSettings.Marshal(&defaultConf) if err != nil { @@ -391,16 +407,6 @@ func TestConfigCmdLineOverridesFile(t *testing.T) { } f.Sync() - dir, err := ioutil.TempDir("", "bzztest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - conf, account := getTestAccount(t, dir) - node := &testNode{Dir: dir} - - expectNetworkId := uint64(77) - flags := []string{ fmt.Sprintf("--%s", SwarmNetworkIdFlag.Name), "77", fmt.Sprintf("--%s", SwarmPortFlag.Name), httpPort, @@ -411,6 +417,7 @@ func TestConfigCmdLineOverridesFile(t *testing.T) { fmt.Sprintf("--%s", utils.DataDirFlag.Name), dir, fmt.Sprintf("--%s", utils.IPCPathFlag.Name), conf.IPCPath, } + log.Warn("exec with flags", "f", flags) node.Cmd = runSwarm(t, flags...) node.Cmd.InputLine(testPassphrase) defer func() { diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index 06d5b0bb2b..a7b5d400d0 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -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) + if err != nil { + return err + } //register BZZ as node.Service in the ethereum node registerBzzService(bzzconfig, stack) //start the node diff --git a/cmd/swarm/run_test.go b/cmd/swarm/run_test.go index 9681c8990a..2fff3c7063 100644 --- a/cmd/swarm/run_test.go +++ b/cmd/swarm/run_test.go @@ -222,7 +222,12 @@ type testNode struct { const testPassphrase = "swarm-test-passphrase" func getTestAccount(t *testing.T, dir string) (conf *node.Config, account accounts.Account) { - // create key + conf, account, _ = getTestAccountWithPrivateKey(t, dir) + return +} + +func getTestAccountWithPrivateKey(t *testing.T, dir string) (conf *node.Config, account accounts.Account, pk *ecdsa.PrivateKey) { + // create kej conf = &node.Config{ DataDir: dir, IPCPath: "bzzd.ipc", @@ -232,17 +237,19 @@ func getTestAccount(t *testing.T, dir string) (conf *node.Config, account accoun if err != nil { t.Fatal(err) } - account, err = n.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore).NewAccount(testPassphrase) + ks := n.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + account, err = ks.NewAccount(testPassphrase) if err != nil { t.Fatal(err) } + pk = decryptStoreAccount(ks, account.Address.String(), []string{testPassphrase}) // use a unique IPCPath when running tests on Windows if runtime.GOOS == "windows" { conf.IPCPath = fmt.Sprintf("bzzd-%s.ipc", account.Address.String()) } - return conf, account + return conf, account, pk } func existingTestNode(t *testing.T, dir string, bzzaccount string) *testNode { diff --git a/p2p/simulations/adapters/exec.go b/p2p/simulations/adapters/exec.go index bd8bcbc856..1326621da4 100644 --- a/p2p/simulations/adapters/exec.go +++ b/p2p/simulations/adapters/exec.go @@ -92,6 +92,11 @@ func (e *ExecAdapter) NewNode(config *NodeConfig) (Node, error) { return nil, fmt.Errorf("error creating node directory: %s", err) } + err := config.initDefaultEnode() + if err != nil { + return nil, err + } + log.Warn("set default enr", "e", config) // generate the config conf := &execNodeConfig{ Stack: node.DefaultConfig, @@ -114,6 +119,9 @@ func (e *ExecAdapter) NewNode(config *NodeConfig) (Node, error) { // listen on a localhost port, which we set when we // initialise NodeConfig (usually a random port) conf.Stack.P2P.ListenAddr = fmt.Sprintf(":%d", config.Port) + if err != nil { + return nil, err + } node := &ExecNode{ ID: config.ID, @@ -407,6 +415,12 @@ func startExecNodeStack() (*node.Node, error) { if err := json.Unmarshal([]byte(confEnv), &conf); err != nil { return nil, fmt.Errorf("error decoding %s: %v", envNodeConfig, err) } + nodeTcpConn, err := net.ResolveTCPAddr("tcp", conf.Stack.P2P.ListenAddr) + if err != nil { + conf.Node.initDefaultEnode() + } else { + 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()) diff --git a/p2p/simulations/adapters/inproc.go b/p2p/simulations/adapters/inproc.go index 991573c2dc..682e48530b 100644 --- a/p2p/simulations/adapters/inproc.go +++ b/p2p/simulations/adapters/inproc.go @@ -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,12 @@ 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) + // set up ENR record + // + err := config.initDefaultEnode() 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{ diff --git a/p2p/simulations/adapters/types.go b/p2p/simulations/adapters/types.go index e5e4d159cb..47b0e85695 100644 --- a/p2p/simulations/adapters/types.go +++ b/p2p/simulations/adapters/types.go @@ -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,31 @@ func RegisterServices(services Services) { os.Exit(0) } } + +func (n *NodeConfig) initDefaultEnode() error { + return n.initEnode(net.IPv4(127, 0, 0, 1), 0, 0) +} + +func (n *NodeConfig) initEnode(ip net.IP, tcpport int, udpport int) error { + + // dialer in simulations based on ENR records + // doesn't work unless we explicitly set localhost record + enrIp := enr.IP(net.IPv4(127, 0, 0, 1)) + n.Record.Set(&enrIp) + enrTcpPort := enr.TCP(0) + n.Record.Set(&enrTcpPort) + enrUdpPort := enr.UDP(0) + 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 +} diff --git a/swarm/api/config.go b/swarm/api/config.go index 1fa6c4fdff..8e057365a4 100644 --- a/swarm/api/config.go +++ b/swarm/api/config.go @@ -29,6 +29,7 @@ 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/p2p/enr" "github.com/ethereum/go-ethereum/swarm/log" "github.com/ethereum/go-ethereum/swarm/network" "github.com/ethereum/go-ethereum/swarm/pss" @@ -48,17 +49,18 @@ type Config struct { *storage.FileStoreParams *storage.LocalStoreParams *network.HiveParams - Swap *swap.LocalProfile - Pss *pss.PssParams - Contract common.Address - EnsRoot common.Address - EnsAPIs []string - Path string - ListenAddr string - Port string - PublicKey string - BzzKey string - NodeID string + Swap *swap.LocalProfile + Pss *pss.PssParams + Contract common.Address + EnsRoot common.Address + EnsAPIs []string + Path string + ListenAddr string + Port string + PublicKey string + BzzKey string + //NodeID string + Enode *enode.Node `toml:",omit"` NetworkID uint64 SwapEnabled bool SyncEnabled bool @@ -87,6 +89,7 @@ func NewConfig() (c *Config) { ListenAddr: DefaultHTTPListenAddr, Port: DefaultHTTPPort, Path: node.DefaultDataDir(), + Enode: &enode.Node{}, EnsAPIs: nil, EnsRoot: ens.TestNetAddress, NetworkID: network.DefaultNetworkID, @@ -104,23 +107,36 @@ 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) error { address := crypto.PubkeyToAddress(prvKey.PublicKey) c.Path = filepath.Join(c.Path, "bzz-"+common.Bytes2Hex(address.Bytes())) err := os.MkdirAll(c.Path, os.ModePerm) 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) } pubkey := crypto.FromECDSAPub(&prvKey.PublicKey) pubkeyhex := common.ToHex(pubkey) - keyhex := hexutil.Encode(network.PrivateKeyToBzzKey(prvKey)) + bzzkeybytes := network.PrivateKeyToBzzKey(prvKey) + keyhex := hexutil.Encode(bzzkeybytes) c.PublicKey = pubkeyhex c.BzzKey = keyhex - c.NodeID = enode.PubkeyToIDV4(&prvKey.PublicKey).String() + //c.NodeID = enode.PubkeyToIDV4(&prvKey.PublicKey).String() + var record enr.Record + record.Set(network.NewENRAddrEntry(bzzkeybytes)) + record.Set(network.ENRLightNodeEntry(c.LightNodeEnabled)) + record.Set(network.ENRBootNodeEntry(c.BootnodeMode)) + err = enode.SignV4(&record, prvKey) + if err != nil { + return fmt.Errorf("ENR create fail: %v", err) + } + c.Enode, err = enode.New(enode.V4ID{}, &record) + if err != nil { + return fmt.Errorf("Enode create fail: %v", err) + } + log.Warn("setting enode record", "node", c.Enode) if c.SwapEnabled { c.Swap.Init(c.Contract, prvKey) @@ -131,6 +147,7 @@ func (c *Config) Init(prvKey *ecdsa.PrivateKey) { c.LocalStoreParams.BaseKey = common.FromHex(keyhex) c.Pss = c.Pss.WithPrivateKey(c.privateKey) + return nil } func (c *Config) ShiftPrivateKey() (privKey *ecdsa.PrivateKey) { diff --git a/swarm/swarm.go b/swarm/swarm.go index b4b08c5c54..08cdd0cd4c 100644 --- a/swarm/swarm.go +++ b/swarm/swarm.go @@ -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,12 @@ 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 - } + // var nodeID enode.ID + // if err := nodeID.UnmarshalText([]byte(config.NodeID)); err != nil { + // return nil, err + // } + nodeID := config.Enode.ID() + bzzconfig.UnderlayAddr = []byte(nodeID.String()) syncing := stream.SyncingAutoSubscribe if !config.SyncEnabled || config.LightNodeEnabled {