From 52995f7117ae22b305085eaef681a202b2b59a4c Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 13 Mar 2019 08:54:29 +0100 Subject: [PATCH] swarm, p2p: Add full sim node configs for protocoltester --- p2p/simulations/adapters/inproc.go | 8 ++- p2p/testing/protocoltester.go | 30 ++++----- swarm/api/config.go | 7 +-- swarm/network/discovery_test.go | 7 ++- swarm/network/hive_test.go | 35 ++++++++--- swarm/network/protocol.go | 6 ++ swarm/network/protocol_test.go | 97 +++++++++++++++++++++++------- swarm/network/simulation/node.go | 3 +- 8 files changed, 137 insertions(+), 56 deletions(-) diff --git a/p2p/simulations/adapters/inproc.go b/p2p/simulations/adapters/inproc.go index 48c45f99a4..991573c2dc 100644 --- a/p2p/simulations/adapters/inproc.go +++ b/p2p/simulations/adapters/inproc.go @@ -72,8 +72,13 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) { s.mtx.Lock() defer s.mtx.Unlock() - // check a node with the ID doesn't already exist id := config.ID + // verify that the node has a private key in the config + if config.PrivateKey == nil { + return nil, fmt.Errorf("node is missing private key: %s", id) + } + + // check a node with the ID doesn't already exist if _, exists := s.nodes[id]; exists { return nil, fmt.Errorf("node already exists: %s", id) } @@ -103,6 +108,7 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) { 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{ diff --git a/p2p/testing/protocoltester.go b/p2p/testing/protocoltester.go index bfa913ff9c..e7f2d05bdb 100644 --- a/p2p/testing/protocoltester.go +++ b/p2p/testing/protocoltester.go @@ -25,6 +25,7 @@ package testing import ( "bytes" + "crypto/ecdsa" "fmt" "io" "io/ioutil" @@ -51,7 +52,7 @@ type ProtocolTester struct { // NewProtocolTester constructs a new ProtocolTester // it takes as argument the pivot node id, the number of dummy peers and the // protocol run function called on a peer connection by the p2p server -func NewProtocolTester(id enode.ID, nodeCount int, run func(*p2p.Peer, p2p.MsgReadWriter) error) *ProtocolTester { +func NewProtocolTester(prvkey *ecdsa.PrivateKey, nodeCount int, run func(*p2p.Peer, p2p.MsgReadWriter) error) *ProtocolTester { services := adapters.Services{ "test": func(ctx *adapters.ServiceContext) (node.Service, error) { return &testNode{run}, nil @@ -62,23 +63,31 @@ func NewProtocolTester(id enode.ID, nodeCount int, run func(*p2p.Peer, p2p.MsgRe } adapter := adapters.NewSimAdapter(services) net := simulations.NewNetwork(adapter, &simulations.NetworkConfig{}) - if _, err := net.NewNodeWithConfig(&adapters.NodeConfig{ - ID: id, + nodeConfig := &adapters.NodeConfig{ + PrivateKey: prvkey, EnableMsgEvents: true, Services: []string{"test"}, - }); err != nil { + } + if _, err := net.NewNodeWithConfig(nodeConfig); err != nil { panic(err.Error()) } - if err := net.Start(id); err != nil { + if err := net.Start(nodeConfig.ID); err != nil { panic(err.Error()) } - node := net.GetNode(id).Node.(*adapters.SimNode) + node := net.GetNode(nodeConfig.ID).Node.(*adapters.SimNode) peers := make([]*adapters.NodeConfig, nodeCount) nodes := make([]*enode.Node, nodeCount) for i := 0; i < nodeCount; i++ { peers[i] = adapters.RandomNodeConfig() peers[i].Services = []string{"mock"} + if _, err := net.NewNodeWithConfig(peers[i]); err != nil { + panic(fmt.Sprintf("error initializing peer %v: %v", peers[i].ID, err)) + } + if err := net.Start(peers[i].ID); err != nil { + panic(fmt.Sprintf("error starting peer %v: %v", peers[i].ID, err)) + panic(err.Error()) + } nodes[i] = peers[i].Node() } events := make(chan *p2p.PeerEvent, 1000) @@ -94,7 +103,7 @@ func NewProtocolTester(id enode.ID, nodeCount int, run func(*p2p.Peer, p2p.MsgRe network: net, } - self.Connect(id, peers...) + self.Connect(nodeConfig.ID, peers...) return self } @@ -108,13 +117,6 @@ func (t *ProtocolTester) Stop() { // p2p/simulations network connection with the in memory network adapter func (t *ProtocolTester) Connect(selfID enode.ID, peers ...*adapters.NodeConfig) { for _, peer := range peers { - log.Trace(fmt.Sprintf("start node %v", peer.ID)) - if _, err := t.network.NewNodeWithConfig(peer); err != nil { - panic(fmt.Sprintf("error starting peer %v: %v", peer.ID, err)) - } - if err := t.network.Start(peer.ID); err != nil { - panic(fmt.Sprintf("error starting peer %v: %v", peer.ID, err)) - } log.Trace(fmt.Sprintf("connect to %v", peer.ID)) if err := t.network.Connect(selfID, peer.ID); err != nil { panic(fmt.Sprintf("error connecting to peer %v: %v", peer.ID, err)) diff --git a/swarm/api/config.go b/swarm/api/config.go index b4448f9073..b2071933d5 100644 --- a/swarm/api/config.go +++ b/swarm/api/config.go @@ -119,7 +119,7 @@ func (c *Config) Init(prvKey *ecdsa.PrivateKey) { pubkey := crypto.FromECDSAPub(&prvKey.PublicKey) pubkeyhex := common.ToHex(pubkey) //keyhex := crypto.Keccak256Hash(pubkey).Hex() - keyhex := hexutil.Encode(PrivateKeyToBzzKey(prvKey)) + keyhex := hexutil.Encode(network.PrivateKeyToBzzKey(prvKey)) c.PublicKey = pubkeyhex c.BzzKey = keyhex @@ -136,11 +136,6 @@ func (c *Config) Init(prvKey *ecdsa.PrivateKey) { c.Pss = c.Pss.WithPrivateKey(c.privateKey) } -func PrivateKeyToBzzKey(prvKey *ecdsa.PrivateKey) []byte { - pubkeyBytes := crypto.FromECDSAPub(&prvKey.PublicKey) - return crypto.Keccak256Hash(pubkeyBytes).Bytes() -} - func (c *Config) ShiftPrivateKey() (privKey *ecdsa.PrivateKey) { if c.privateKey != nil { privKey = c.privateKey diff --git a/swarm/network/discovery_test.go b/swarm/network/discovery_test.go index dd3299c0f1..ea0d776e61 100644 --- a/swarm/network/discovery_test.go +++ b/swarm/network/discovery_test.go @@ -29,7 +29,10 @@ import ( */ func TestDiscovery(t *testing.T) { params := NewHiveParams() - s, pp := newHiveTester(t, params, 1, nil) + s, pp, err := newHiveTester(t, params, 1, nil) + if err != nil { + t.Fatal(err) + } node := s.Nodes[0] raddr := NewAddr(node) @@ -40,7 +43,7 @@ func TestDiscovery(t *testing.T) { defer pp.Stop() // send subPeersMsg to the peer - err := s.TestExchanges(p2ptest.Exchange{ + err = s.TestExchanges(p2ptest.Exchange{ Label: "outgoing subPeersMsg", Expects: []p2ptest.Expect{ { diff --git a/swarm/network/hive_test.go b/swarm/network/hive_test.go index fea4347ead..ddae95a458 100644 --- a/swarm/network/hive_test.go +++ b/swarm/network/hive_test.go @@ -22,31 +22,43 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/crypto" p2ptest "github.com/ethereum/go-ethereum/p2p/testing" "github.com/ethereum/go-ethereum/swarm/state" ) -func newHiveTester(t *testing.T, params *HiveParams, n int, store state.Store) (*bzzTester, *Hive) { +func newHiveTester(t *testing.T, params *HiveParams, n int, store state.Store) (*bzzTester, *Hive, error) { // setup - addr := RandomAddr() // tested peers peer address - to := NewKademlia(addr.OAddr, NewKadParams()) + prvkey, err := crypto.GenerateKey() + if err != nil { + return nil, nil, err + } + addr := PrivateKeyToBzzKey(prvkey) + to := NewKademlia(addr, NewKadParams()) pp := NewHive(params, to, store) // hive - return newBzzBaseTester(t, n, addr, DiscoverySpec, pp.Run), pp + bt, err := newBzzBaseTester(t, n, prvkey, DiscoverySpec, pp.Run) + if err != nil { + return nil, nil, err + } + return bt, pp, nil } // TestRegisterAndConnect verifies that the protocol runs successfully // and that the peer connection exists afterwards func TestRegisterAndConnect(t *testing.T) { params := NewHiveParams() - s, pp := newHiveTester(t, params, 1, nil) + s, pp, err := newHiveTester(t, params, 1, nil) + if err != nil { + t.Fatal(err) + } node := s.Nodes[0] raddr := NewAddr(node) pp.Register(raddr) // start the hive - err := pp.Start(s.Server) + err = pp.Start(s.Server) if err != nil { t.Fatal(err) } @@ -109,8 +121,10 @@ func TestHiveStatePersistance(t *testing.T) { } params := NewHiveParams() - s, pp := newHiveTester(t, params, 5, store) - + s, pp, err := newHiveTester(t, params, 5, store) + if err != nil { + t.Fatal(err) + } peers := make(map[string]bool) for _, node := range s.Nodes { raddr := NewAddr(node) @@ -133,7 +147,10 @@ func TestHiveStatePersistance(t *testing.T) { t.Fatal(err) } - s1, pp := newHiveTester(t, params, 0, persistedStore) + s1, pp, err := newHiveTester(t, params, 0, persistedStore) + if err != nil { + t.Fatal(err) + } // start the hive and check that we know of all expected peers pp.Start(s1.Server) diff --git a/swarm/network/protocol.go b/swarm/network/protocol.go index 6f8eadad2a..b02f2a1576 100644 --- a/swarm/network/protocol.go +++ b/swarm/network/protocol.go @@ -18,6 +18,7 @@ package network import ( "context" + "crypto/ecdsa" "errors" "fmt" "net" @@ -387,3 +388,8 @@ func RandomAddr() *BzzAddr { func NewAddr(node *enode.Node) *BzzAddr { return &BzzAddr{OAddr: node.ID().Bytes(), UAddr: []byte(node.String())} } + +func PrivateKeyToBzzKey(prvKey *ecdsa.PrivateKey) []byte { + pubkeyBytes := crypto.FromECDSAPub(&prvKey.PublicKey) + return crypto.Keccak256Hash(pubkeyBytes).Bytes() +} diff --git a/swarm/network/protocol_test.go b/swarm/network/protocol_test.go index 64ce7ba4ab..1e7bb04aaa 100644 --- a/swarm/network/protocol_test.go +++ b/swarm/network/protocol_test.go @@ -17,15 +17,18 @@ package network import ( + "crypto/ecdsa" "flag" "fmt" "os" "testing" "time" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "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/protocols" p2ptest "github.com/ethereum/go-ethereum/p2p/testing" ) @@ -67,7 +70,7 @@ func HandshakeMsgExchange(lhs, rhs *HandshakeMsg, id enode.ID) []p2ptest.Exchang } } -func newBzzBaseTester(t *testing.T, n int, addr *BzzAddr, spec *protocols.Spec, run func(*BzzPeer) error) *bzzTester { +func newBzzBaseTester(t *testing.T, n int, prvkey *ecdsa.PrivateKey, spec *protocols.Spec, run func(*BzzPeer) error) (*bzzTester, error) { cs := make(map[string]chan bool) srv := func(p *BzzPeer) error { @@ -83,9 +86,22 @@ func newBzzBaseTester(t *testing.T, n int, addr *BzzAddr, spec *protocols.Spec, return srv(&BzzPeer{Peer: protocols.NewPeer(p, rw, spec), BzzAddr: NewAddr(p.Node())}) } - s := p2ptest.NewProtocolTester(addr.ID(), n, protocol) + s := p2ptest.NewProtocolTester(prvkey, n, protocol) + var record enr.Record + bzzKey := PrivateKeyToBzzKey(prvkey) + record.Set(NewENRAddrEntry(bzzKey)) + err := enode.SignV4(&record, prvkey) + if err != nil { + return nil, fmt.Errorf("unable to generate ENR: %v", err) + } + nod, err := enode.New(enode.V4ID{}, &record) + if err != nil { + return nil, fmt.Errorf("unable to create enode: %v", err) + } + addr := getENRBzzAddr(nod) for _, node := range s.Nodes { + log.Warn("node", "node", node) cs[node.ID().String()] = make(chan bool) } @@ -93,7 +109,7 @@ func newBzzBaseTester(t *testing.T, n int, addr *BzzAddr, spec *protocols.Spec, addr: addr, ProtocolTester: s, cs: cs, - } + }, nil } type bzzTester struct { @@ -116,15 +132,28 @@ func newBzz(addr *BzzAddr, lightNode bool) *Bzz { return bzz } -func newBzzHandshakeTester(n int, addr *BzzAddr, lightNode bool) *bzzTester { +func newBzzHandshakeTester(n int, prvkey *ecdsa.PrivateKey, lightNode bool) (*bzzTester, error) { + + var record enr.Record + bzzkey := PrivateKeyToBzzKey(prvkey) + record.Set(NewENRAddrEntry(bzzkey)) + record.Set(ENRLightNodeEntry(lightNode)) + err := enode.SignV4(&record, prvkey) + if err != nil { + return nil, err + } + nod, err := enode.New(enode.V4ID{}, &record) + addr := getENRBzzAddr(nod) + bzz := newBzz(addr, lightNode) - pt := p2ptest.NewProtocolTester(addr.ID(), n, bzz.runBzz) + + pt := p2ptest.NewProtocolTester(prvkey, n, bzz.runBzz) return &bzzTester{ addr: addr, ProtocolTester: pt, bzz: bzz, - } + }, nil } // should test handshakes in one exchange? parallelisation @@ -165,12 +194,18 @@ func correctBzzHandshake(addr *BzzAddr, lightNode bool) *HandshakeMsg { func TestBzzHandshakeNetworkIDMismatch(t *testing.T) { lightNode := false - addr := RandomAddr() - s := newBzzHandshakeTester(1, addr, lightNode) + prvkey, err := crypto.GenerateKey() + if err != nil { + t.Fatal(err) + } + s, err := newBzzHandshakeTester(1, prvkey, lightNode) + if err != nil { + t.Fatal(err) + } node := s.Nodes[0] - err := s.testHandshake( - correctBzzHandshake(addr, lightNode), + err = s.testHandshake( + correctBzzHandshake(s.addr, lightNode), &HandshakeMsg{Version: TestProtocolVersion, NetworkID: 321, Addr: NewAddr(node)}, &p2ptest.Disconnect{Peer: node.ID(), Error: fmt.Errorf("Handshake error: Message handler error: (msg code 0): network id mismatch 321 (!= 3)")}, ) @@ -182,12 +217,18 @@ func TestBzzHandshakeNetworkIDMismatch(t *testing.T) { func TestBzzHandshakeVersionMismatch(t *testing.T) { lightNode := false - addr := RandomAddr() - s := newBzzHandshakeTester(1, addr, lightNode) + prvkey, err := crypto.GenerateKey() + if err != nil { + t.Fatal(err) + } + s, err := newBzzHandshakeTester(1, prvkey, lightNode) + if err != nil { + t.Fatal(err) + } node := s.Nodes[0] - err := s.testHandshake( - correctBzzHandshake(addr, lightNode), + err = s.testHandshake( + correctBzzHandshake(s.addr, lightNode), &HandshakeMsg{Version: 0, NetworkID: TestProtocolNetworkID, Addr: NewAddr(node)}, &p2ptest.Disconnect{Peer: node.ID(), Error: fmt.Errorf("Handshake error: Message handler error: (msg code 0): version mismatch 0 (!= %d)", TestProtocolVersion)}, ) @@ -199,12 +240,18 @@ func TestBzzHandshakeVersionMismatch(t *testing.T) { func TestBzzHandshakeSuccess(t *testing.T) { lightNode := false - addr := RandomAddr() - s := newBzzHandshakeTester(1, addr, lightNode) + prvkey, err := crypto.GenerateKey() + if err != nil { + t.Fatal(err) + } + s, err := newBzzHandshakeTester(1, prvkey, lightNode) + if err != nil { + t.Fatal(err) + } node := s.Nodes[0] - err := s.testHandshake( - correctBzzHandshake(addr, lightNode), + err = s.testHandshake( + correctBzzHandshake(s.addr, lightNode), &HandshakeMsg{Version: TestProtocolVersion, NetworkID: TestProtocolNetworkID, Addr: NewAddr(node)}, ) @@ -224,14 +271,20 @@ func TestBzzHandshakeLightNode(t *testing.T) { for _, test := range lightNodeTests { t.Run(test.name, func(t *testing.T) { - randomAddr := RandomAddr() - pt := newBzzHandshakeTester(1, randomAddr, false) + prvkey, err := crypto.GenerateKey() + if err != nil { + t.Fatal(err) + } + pt, err := newBzzHandshakeTester(1, prvkey, false) + if err != nil { + t.Fatal(err) + } node := pt.Nodes[0] addr := NewAddr(node) - err := pt.testHandshake( - correctBzzHandshake(randomAddr, false), + err = pt.testHandshake( + correctBzzHandshake(pt.addr, false), &HandshakeMsg{Version: TestProtocolVersion, NetworkID: TestProtocolNetworkID, Addr: addr, LightNode: test.lightNode}, ) diff --git a/swarm/network/simulation/node.go b/swarm/network/simulation/node.go index 16f754e196..1ab9ddfd0d 100644 --- a/swarm/network/simulation/node.go +++ b/swarm/network/simulation/node.go @@ -28,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/simulations" "github.com/ethereum/go-ethereum/p2p/simulations/adapters" - bzzapi "github.com/ethereum/go-ethereum/swarm/api" "github.com/ethereum/go-ethereum/swarm/network" ) @@ -105,7 +104,7 @@ func (s *Simulation) AddNode(opts ...AddNodeOption) (id enode.ID, err error) { // for now we have no way of setting bootnodes or lightnodes in sims // so we just set them as false // they should perhaps be possible to override them with AddNodeOption - bzzKey := bzzapi.PrivateKeyToBzzKey(conf.PrivateKey) + bzzKey := network.PrivateKeyToBzzKey(conf.PrivateKey) bzzAddr := network.NewENRAddrEntry(bzzKey) var lightnode network.ENRLightNodeEntry