Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

cmd/swarm, p2p, swarm: Enable ENR in binary/execadapter #1302

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions cmd/swarm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion cmd/swarm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions p2p/simulations/adapters/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -407,6 +411,14 @@ func startExecNodeStack() (*node.Node, error) {
if err := json.Unmarshal([]byte(confEnv), &conf); err != nil {
return nil, fmt.Errorf("error decoding %s: %v", envNodeConfig, err)
}
// TODO verify that ListenAddr will contain the correct tcp addr
// if we should start using exec adapters with other host than local
nodeTcpConn, err := net.ResolveTCPAddr("tcp", conf.Stack.P2P.ListenAddr)
if err != nil {
conf.Node.initDummyEnode()
} 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())

Expand Down
18 changes: 2 additions & 16 deletions p2p/simulations/adapters/inproc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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)
if err != nil {
return nil, fmt.Errorf("unable to generate ENR: %v", err)
}
nod, err := enode.New(enode.V4ID{}, &config.Record)
err := config.initDummyEnode()
if err != nil {
return nil, fmt.Errorf("unable to create enode: %v", err)
return nil, err
}
log.Trace("simnode new", "record", config.Record)
config.node = nod

n, err := node.New(&node.Config{
P2P: p2p.Config{
Expand Down
28 changes: 28 additions & 0 deletions p2p/simulations/adapters/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(tcpport)
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
frncmx marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

func (n *NodeConfig) initDummyEnode() error {
return n.initEnode(net.IPv4(127, 0, 0, 1), 0, 0)
}
62 changes: 44 additions & 18 deletions swarm/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -58,7 +57,7 @@ type Config struct {
Port string
PublicKey string
BzzKey string
NodeID string
Enode *enode.Node `toml:"-"`
nolash marked this conversation as resolved.
Show resolved Hide resolved
NetworkID uint64
SwapEnabled bool
SyncEnabled bool
Expand Down Expand Up @@ -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) {
Expand All @@ -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
}
10 changes: 9 additions & 1 deletion swarm/api/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is always there whenever you call config.Init() could we not just put the nodkey generation into Init?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zelig no because we want to generate it with node/Config.NodeKey() when in cmd/swarm

if err != nil {
t.Fatalf("failed to load private key: %v", err)
}

one := NewConfig()
two := NewConfig()
Expand All @@ -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 == "" {
Expand Down
35 changes: 35 additions & 0 deletions swarm/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
18 changes: 9 additions & 9 deletions swarm/network/simulation/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,16 @@ 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)

var lightnode network.ENRLightNodeEntry
var bootnode network.ENRBootNodeEntry
conf.Record.Set(bzzAddr)
conf.Record.Set(&lightnode)
conf.Record.Set(&bootnode)
enodeParams := &network.EnodeParams{
PrivateKey: conf.PrivateKey,
}
record, err := network.NewEnodeRecord(enodeParams)
if err != nil {
return enode.ID{}, err
}
conf.Record = *record

// Add the bzz address to the node config
node, err := s.Net.NewNodeWithConfig(conf)
Expand Down
6 changes: 5 additions & 1 deletion swarm/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ""

Expand Down
6 changes: 1 addition & 5 deletions swarm/swarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 10 additions & 2 deletions swarm/swarm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down