p2p/discover: add test for handshake repeating

This commit is contained in:
Felix Lange 2025-03-18 11:37:57 +01:00
parent ad06df0473
commit 11aa3a1680

View file

@ -140,6 +140,26 @@ func TestUDPv5_unknownPacket(t *testing.T) {
test.waitPacketOut(func(p *v5wire.Whoareyou, addr netip.AddrPort, _ v5wire.Nonce) { test.waitPacketOut(func(p *v5wire.Whoareyou, addr netip.AddrPort, _ v5wire.Nonce) {
check(p, 0) check(p, 0)
}) })
}
func TestUDPv5_unknownPacketKnownNode(t *testing.T) {
t.Parallel()
test := newUDPV5Test(t)
defer test.close()
nonce := v5wire.Nonce{1, 2, 3}
check := func(p *v5wire.Whoareyou, wantSeq uint64) {
t.Helper()
if p.Nonce != nonce {
t.Error("wrong nonce in WHOAREYOU:", p.Nonce, nonce)
}
if p.IDNonce == ([16]byte{}) {
t.Error("all zero ID nonce")
}
if p.RecordSeq != wantSeq {
t.Errorf("wrong record seq %d in WHOAREYOU, want %d", p.RecordSeq, wantSeq)
}
}
// Make node known. // Make node known.
n := test.getNode(test.remotekey, test.remoteaddr).Node() n := test.getNode(test.remotekey, test.remoteaddr).Node()
@ -151,6 +171,42 @@ func TestUDPv5_unknownPacket(t *testing.T) {
}) })
} }
// This test checks that, when multiple 'unknown' packets are received during a handshake,
// the node sticks to the first handshake attempt.
func TestUDPv5_handshakeRepeatChallenge(t *testing.T) {
t.Parallel()
test := newUDPV5Test(t)
defer test.close()
nonce1 := v5wire.Nonce{1}
nonce2 := v5wire.Nonce{2}
nonce3 := v5wire.Nonce{3}
check := func(p *v5wire.Whoareyou, wantNonce v5wire.Nonce) {
t.Helper()
if p.Nonce != wantNonce {
t.Error("wrong nonce in WHOAREYOU:", p.Nonce, wantNonce)
}
}
// Unknown packet from unknown node.
test.packetIn(&v5wire.Unknown{Nonce: nonce1})
test.waitPacketOut(func(p *v5wire.Whoareyou, addr netip.AddrPort, _ v5wire.Nonce) {
check(p, nonce1)
})
// Second unknown packet. Here we expect the response to reference the
// first unknown packet.
test.packetIn(&v5wire.Unknown{Nonce: nonce2})
test.waitPacketOut(func(p *v5wire.Whoareyou, addr netip.AddrPort, _ v5wire.Nonce) {
check(p, nonce1)
})
// Third unknown packet. This should still return the first nonce.
test.packetIn(&v5wire.Unknown{Nonce: nonce3})
test.waitPacketOut(func(p *v5wire.Whoareyou, addr netip.AddrPort, _ v5wire.Nonce) {
check(p, nonce1)
})
}
// This test checks that incoming FINDNODE calls are handled correctly. // This test checks that incoming FINDNODE calls are handled correctly.
func TestUDPv5_findnodeHandling(t *testing.T) { func TestUDPv5_findnodeHandling(t *testing.T) {
t.Parallel() t.Parallel()
@ -698,6 +754,8 @@ type testCodec struct {
test *udpV5Test test *udpV5Test
id enode.ID id enode.ID
ctr uint64 ctr uint64
sentChallenges map[enode.ID]*v5wire.Whoareyou
} }
type testCodecFrame struct { type testCodecFrame struct {
@ -712,13 +770,21 @@ func (c *testCodec) Encode(toID enode.ID, addr string, p v5wire.Packet, _ *v5wir
var authTag v5wire.Nonce var authTag v5wire.Nonce
binary.BigEndian.PutUint64(authTag[:], c.ctr) binary.BigEndian.PutUint64(authTag[:], c.ctr)
if w, ok := p.(*v5wire.Whoareyou); ok {
// Store recently sent Whoareyou challenges.
if c.sentChallenges == nil {
c.sentChallenges = make(map[enode.ID]*v5wire.Whoareyou)
}
c.sentChallenges[toID] = w
}
penc, _ := rlp.EncodeToBytes(p) penc, _ := rlp.EncodeToBytes(p)
frame, err := rlp.EncodeToBytes(testCodecFrame{c.id, authTag, p.Kind(), penc}) frame, err := rlp.EncodeToBytes(testCodecFrame{c.id, authTag, p.Kind(), penc})
return frame, authTag, err return frame, authTag, err
} }
func (c *testCodec) CurrentChallenge(enode.ID, string) *v5wire.Whoareyou { func (c *testCodec) CurrentChallenge(id enode.ID, addr string) *v5wire.Whoareyou {
return nil return c.sentChallenges[id]
} }
func (c *testCodec) Decode(input []byte, addr string) (enode.ID, *enode.Node, v5wire.Packet, error) { func (c *testCodec) Decode(input []byte, addr string) (enode.ID, *enode.Node, v5wire.Packet, error) {