feat:change the discv5 challenge behavior to send same node only one time.

Signed-off-by: Chen Kai <281165273grape@gmail.com>
This commit is contained in:
Chen Kai 2025-02-02 12:58:28 +08:00
parent fc12dbe40b
commit fd550f5408
2 changed files with 48 additions and 12 deletions

View File

@ -104,18 +104,19 @@ var DefaultProtocolID = [6]byte{'d', 'i', 's', 'c', 'v', '5'}
// Errors.
var (
errTooShort = errors.New("packet too short")
errInvalidHeader = errors.New("invalid packet header")
errInvalidFlag = errors.New("invalid flag value in header")
errMinVersion = errors.New("version of packet header below minimum")
errMsgTooShort = errors.New("message/handshake packet below minimum size")
errAuthSize = errors.New("declared auth size is beyond packet length")
errUnexpectedHandshake = errors.New("unexpected auth response, not in handshake")
errInvalidAuthKey = errors.New("invalid ephemeral pubkey")
errNoRecord = errors.New("expected ENR in handshake but none sent")
errInvalidNonceSig = errors.New("invalid ID nonce signature")
errMessageTooShort = errors.New("message contains no data")
errMessageDecrypt = errors.New("cannot decrypt message")
errTooShort = errors.New("packet too short")
errInvalidHeader = errors.New("invalid packet header")
errInvalidFlag = errors.New("invalid flag value in header")
errMinVersion = errors.New("version of packet header below minimum")
errMsgTooShort = errors.New("message/handshake packet below minimum size")
errAuthSize = errors.New("declared auth size is beyond packet length")
errUnexpectedHandshake = errors.New("unexpected auth response, not in handshake")
errInvalidAuthKey = errors.New("invalid ephemeral pubkey")
errNoRecord = errors.New("expected ENR in handshake but none sent")
errInvalidNonceSig = errors.New("invalid ID nonce signature")
errMessageTooShort = errors.New("message contains no data")
errMessageDecrypt = errors.New("cannot decrypt message")
errChallengeAlreadySent = errors.New("challenge already sent to this node")
)
// Public errors.
@ -217,6 +218,10 @@ func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoar
// Store sent WHOAREYOU challenges.
if challenge, ok := packet.(*Whoareyou); ok {
// check if we already sent a challenge to this node
if c.sc.getHandshake(id, addr) != nil {
return nil, Nonce{}, errChallengeAlreadySent
}
challenge.ChallengeData = bytesCopy(&c.buf)
c.sc.storeSentHandshake(id, addr, challenge)
} else if msgData == nil {

View File

@ -155,6 +155,37 @@ func TestHandshake_norecord(t *testing.T) {
net.nodeA.expectDecode(t, NodesMsg, nodes)
}
func TestEncodeWhoareyouAlreadySent(t *testing.T) {
t.Parallel()
net := newHandshakeTest()
defer net.close()
// A -> B RANDOM PACKET
packet, _ := net.nodeA.encode(t, net.nodeB, &Findnode{})
resp := net.nodeB.expectDecode(t, UnknownPacket, packet)
// A <- B First WHOAREYOU
challenge1 := &Whoareyou{
Nonce: resp.(*Unknown).Nonce,
IDNonce: testIDnonce,
RecordSeq: 0,
}
whoareyou1, _ := net.nodeB.encode(t, net.nodeA, challenge1)
net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou1)
// A <- B Second WHOAREYOU (should fail)
challenge2 := &Whoareyou{
Nonce: resp.(*Unknown).Nonce,
IDNonce: testIDnonce,
RecordSeq: 0,
}
_, _, err := net.nodeB.c.Encode(net.nodeA.id(), net.nodeA.addr(), challenge2, nil)
if !errors.Is(err, errChallengeAlreadySent) {
t.Fatalf("second challenge should fail with errChallengeAlreadySent, got %v", err)
}
}
// In this test, A tries to send FINDNODE with existing secrets but B doesn't know
// anything about A.
func TestHandshake_rekey(t *testing.T) {