diff options
Diffstat (limited to 'p2p/discover/v4_udp_test.go')
-rw-r--r-- | p2p/discover/v4_udp_test.go | 98 |
1 files changed, 75 insertions, 23 deletions
diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go index 0aa4c01e5..9d7badea1 100644 --- a/p2p/discover/v4_udp_test.go +++ b/p2p/discover/v4_udp_test.go @@ -37,6 +37,7 @@ import ( "github.com/ethereum/go-ethereum/internal/testlog" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/rlp" ) @@ -91,19 +92,19 @@ func (test *udpTest) close() { } // handles a packet as if it had been sent to the transport. -func (test *udpTest) packetIn(wantError error, ptype byte, data packetV4) { +func (test *udpTest) packetIn(wantError error, data packetV4) { test.t.Helper() - test.packetInFrom(wantError, test.remotekey, test.remoteaddr, ptype, data) + test.packetInFrom(wantError, test.remotekey, test.remoteaddr, data) } // handles a packet as if it had been sent to the transport by the key/endpoint. -func (test *udpTest) packetInFrom(wantError error, key *ecdsa.PrivateKey, addr *net.UDPAddr, ptype byte, data packetV4) { +func (test *udpTest) packetInFrom(wantError error, key *ecdsa.PrivateKey, addr *net.UDPAddr, data packetV4) { test.t.Helper() - enc, _, err := test.udp.encode(key, ptype, data) + enc, _, err := test.udp.encode(key, data) if err != nil { - test.t.Errorf("packet (%d) encode error: %v", ptype, err) + test.t.Errorf("%s encode error: %v", data.name(), err) } test.sent = append(test.sent, enc) if err = test.udp.handlePacket(addr, enc); err != wantError { @@ -139,10 +140,10 @@ func TestUDPv4_packetErrors(t *testing.T) { test := newUDPTest(t) defer test.close() - test.packetIn(errExpired, p_pingV4, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4}) - test.packetIn(errUnsolicitedReply, p_pongV4, &pongV4{ReplyTok: []byte{}, Expiration: futureExp}) - test.packetIn(errUnknownNode, p_findnodeV4, &findnodeV4{Expiration: futureExp}) - test.packetIn(errUnsolicitedReply, p_neighborsV4, &neighborsV4{Expiration: futureExp}) + test.packetIn(errExpired, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4}) + test.packetIn(errUnsolicitedReply, &pongV4{ReplyTok: []byte{}, Expiration: futureExp}) + test.packetIn(errUnknownNode, &findnodeV4{Expiration: futureExp}) + test.packetIn(errUnsolicitedReply, &neighborsV4{Expiration: futureExp}) } func TestUDPv4_pingTimeout(t *testing.T) { @@ -153,11 +154,21 @@ func TestUDPv4_pingTimeout(t *testing.T) { key := newkey() toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222} node := enode.NewV4(&key.PublicKey, toaddr.IP, 0, toaddr.Port) - if err := test.udp.ping(node); err != errTimeout { + if _, err := test.udp.ping(node); err != errTimeout { t.Error("expected timeout error, got", err) } } +type testPacket byte + +func (req testPacket) kind() byte { return byte(req) } +func (req testPacket) name() string { return "" } +func (req testPacket) preverify(*UDPv4, *net.UDPAddr, enode.ID, encPubkey) error { + return nil +} +func (req testPacket) handle(*UDPv4, *net.UDPAddr, enode.ID, []byte) { +} + func TestUDPv4_responseTimeouts(t *testing.T) { t.Parallel() test := newUDPTest(t) @@ -192,7 +203,7 @@ func TestUDPv4_responseTimeouts(t *testing.T) { p.errc = nilErr test.udp.addReplyMatcher <- p time.AfterFunc(randomDuration(60*time.Millisecond), func() { - if !test.udp.handleReply(p.from, p.ip, p.ptype, nil) { + if !test.udp.handleReply(p.from, p.ip, testPacket(p.ptype)) { t.Logf("not matched: %v", p) } }) @@ -277,7 +288,7 @@ func TestUDPv4_findnode(t *testing.T) { // check that closest neighbors are returned. expected := test.table.closest(testTarget.id(), bucketSize, true) - test.packetIn(nil, p_findnodeV4, &findnodeV4{Target: testTarget, Expiration: futureExp}) + test.packetIn(nil, &findnodeV4{Target: testTarget, Expiration: futureExp}) waitNeighbors := func(want []*node) { test.waitPacketOut(func(p *neighborsV4, to *net.UDPAddr, hash []byte) { if len(p.Nodes) != len(want) { @@ -340,8 +351,8 @@ func TestUDPv4_findnodeMultiReply(t *testing.T) { for i := range list { rpclist[i] = nodeToRPC(list[i]) } - test.packetIn(nil, p_neighborsV4, &neighborsV4{Expiration: futureExp, Nodes: rpclist[:2]}) - test.packetIn(nil, p_neighborsV4, &neighborsV4{Expiration: futureExp, Nodes: rpclist[2:]}) + test.packetIn(nil, &neighborsV4{Expiration: futureExp, Nodes: rpclist[:2]}) + test.packetIn(nil, &neighborsV4{Expiration: futureExp, Nodes: rpclist[2:]}) // check that the sent neighbors are all returned by findnode select { @@ -357,6 +368,7 @@ func TestUDPv4_findnodeMultiReply(t *testing.T) { } } +// This test checks that reply matching of pong verifies the ping hash. func TestUDPv4_pingMatch(t *testing.T) { test := newUDPTest(t) defer test.close() @@ -364,22 +376,23 @@ func TestUDPv4_pingMatch(t *testing.T) { randToken := make([]byte, 32) crand.Read(randToken) - test.packetIn(nil, p_pingV4, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp}) + test.packetIn(nil, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp}) test.waitPacketOut(func(*pongV4, *net.UDPAddr, []byte) {}) test.waitPacketOut(func(*pingV4, *net.UDPAddr, []byte) {}) - test.packetIn(errUnsolicitedReply, p_pongV4, &pongV4{ReplyTok: randToken, To: testLocalAnnounced, Expiration: futureExp}) + test.packetIn(errUnsolicitedReply, &pongV4{ReplyTok: randToken, To: testLocalAnnounced, Expiration: futureExp}) } +// This test checks that reply matching of pong verifies the sender IP address. func TestUDPv4_pingMatchIP(t *testing.T) { test := newUDPTest(t) defer test.close() - test.packetIn(nil, p_pingV4, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp}) + test.packetIn(nil, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp}) test.waitPacketOut(func(*pongV4, *net.UDPAddr, []byte) {}) test.waitPacketOut(func(p *pingV4, to *net.UDPAddr, hash []byte) { wrongAddr := &net.UDPAddr{IP: net.IP{33, 44, 1, 2}, Port: 30000} - test.packetInFrom(errUnsolicitedReply, test.remotekey, wrongAddr, p_pongV4, &pongV4{ + test.packetInFrom(errUnsolicitedReply, test.remotekey, wrongAddr, &pongV4{ ReplyTok: hash, To: testLocalAnnounced, Expiration: futureExp, @@ -394,9 +407,9 @@ func TestUDPv4_successfulPing(t *testing.T) { defer test.close() // The remote side sends a ping packet to initiate the exchange. - go test.packetIn(nil, p_pingV4, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp}) + go test.packetIn(nil, &pingV4{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp}) - // the ping is replied to. + // The ping is replied to. test.waitPacketOut(func(p *pongV4, to *net.UDPAddr, hash []byte) { pinghash := test.sent[0][:macSize] if !bytes.Equal(p.ReplyTok, pinghash) { @@ -413,7 +426,7 @@ func TestUDPv4_successfulPing(t *testing.T) { } }) - // remote is unknown, the table pings back. + // Remote is unknown, the table pings back. test.waitPacketOut(func(p *pingV4, to *net.UDPAddr, hash []byte) { if !reflect.DeepEqual(p.From, test.udp.ourEndpoint()) { t.Errorf("got ping.From %#v, want %#v", p.From, test.udp.ourEndpoint()) @@ -427,10 +440,10 @@ func TestUDPv4_successfulPing(t *testing.T) { if !reflect.DeepEqual(p.To, wantTo) { t.Errorf("got ping.To %v, want %v", p.To, wantTo) } - test.packetIn(nil, p_pongV4, &pongV4{ReplyTok: hash, Expiration: futureExp}) + test.packetIn(nil, &pongV4{ReplyTok: hash, Expiration: futureExp}) }) - // the node should be added to the table shortly after getting the + // The node should be added to the table shortly after getting the // pong packet. select { case n := <-added: @@ -452,6 +465,45 @@ func TestUDPv4_successfulPing(t *testing.T) { } } +// This test checks that EIP-868 requests work. +func TestUDPv4_EIP868(t *testing.T) { + test := newUDPTest(t) + defer test.close() + + test.udp.localNode.Set(enr.WithEntry("foo", "bar")) + wantNode := test.udp.localNode.Node() + + // ENR requests aren't allowed before endpoint proof. + test.packetIn(errUnknownNode, &enrRequestV4{Expiration: futureExp}) + + // Perform endpoint proof and check for sequence number in packet tail. + test.packetIn(nil, &pingV4{Expiration: futureExp}) + test.waitPacketOut(func(p *pongV4, addr *net.UDPAddr, hash []byte) { + if seq := seqFromTail(p.Rest); seq != wantNode.Seq() { + t.Errorf("wrong sequence number in pong: %d, want %d", seq, wantNode.Seq()) + } + }) + test.waitPacketOut(func(p *pingV4, addr *net.UDPAddr, hash []byte) { + if seq := seqFromTail(p.Rest); seq != wantNode.Seq() { + t.Errorf("wrong sequence number in ping: %d, want %d", seq, wantNode.Seq()) + } + test.packetIn(nil, &pongV4{Expiration: futureExp, ReplyTok: hash}) + }) + + // Request should work now. + test.packetIn(nil, &enrRequestV4{Expiration: futureExp}) + test.waitPacketOut(func(p *enrResponseV4, addr *net.UDPAddr, hash []byte) { + n, err := enode.New(enode.ValidSchemes, &p.Record) + if err != nil { + t.Fatalf("invalid record: %v", err) + } + if !reflect.DeepEqual(n, wantNode) { + t.Fatalf("wrong node in enrResponse: %v", n) + } + }) +} + +// EIP-8 test vectors. var testPackets = []struct { input string wantPacket interface{} |