aboutsummaryrefslogtreecommitdiffstats
path: root/p2p/discover/v4_udp_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'p2p/discover/v4_udp_test.go')
-rw-r--r--p2p/discover/v4_udp_test.go98
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{}