From 8abc81022727a850fea85e883cf60096cdff3b89 Mon Sep 17 00:00:00 2001 From: RekCuy63 Date: Wed, 13 May 2026 09:31:12 +0800 Subject: [PATCH] p2p/discover: check UDP endpoint in discv5 calls --- p2p/discover/v5_udp.go | 24 ++++++++++++++++++------ p2p/discover/v5_udp_test.go | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go index c13032e1af..89e99a4a60 100644 --- a/p2p/discover/v5_udp.go +++ b/p2p/discover/v5_udp.go @@ -303,7 +303,10 @@ func (t *UDPv5) RegisterTalkHandler(protocol string, handler TalkRequestHandler) // TalkRequest sends a talk request to a node and waits for a response. func (t *UDPv5) TalkRequest(n *enode.Node, protocol string, request []byte) ([]byte, error) { req := &v5wire.TalkRequest{Protocol: protocol, Message: request} - resp := t.callToNode(n, v5wire.TalkResponseMsg, req) + resp, err := t.callToNode(n, v5wire.TalkResponseMsg, req) + if err != nil { + return nil, err + } defer t.callDone(resp) select { case respMsg := <-resp.ch: @@ -411,7 +414,10 @@ func (t *UDPv5) ping(n *enode.Node) (uint64, error) { // Ping calls PING on a node and waits for a PONG response. func (t *UDPv5) Ping(n *enode.Node) (*v5wire.Pong, error) { req := &v5wire.Ping{ENRSeq: t.localNode.Node().Seq()} - resp := t.callToNode(n, v5wire.PongMsg, req) + resp, err := t.callToNode(n, v5wire.PongMsg, req) + if err != nil { + return nil, err + } defer t.callDone(resp) select { @@ -436,7 +442,10 @@ func (t *UDPv5) RequestENR(n *enode.Node) (*enode.Node, error) { // Findnode calls FINDNODE on a node and waits for responses. func (t *UDPv5) Findnode(n *enode.Node, distances []uint) ([]*enode.Node, error) { - resp := t.callToNode(n, v5wire.NodesMsg, &v5wire.Findnode{Distances: distances}) + resp, err := t.callToNode(n, v5wire.NodesMsg, &v5wire.Findnode{Distances: distances}) + if err != nil { + return nil, err + } return t.waitForNodes(resp, distances) } @@ -503,11 +512,14 @@ func (t *UDPv5) verifyResponseNode(c *callV5, r *enr.Record, distances []uint, s // callToNode sends the given call and sets up a handler for response packets (of message // type responseType). Responses are dispatched to the call's response channel. -func (t *UDPv5) callToNode(n *enode.Node, responseType byte, req v5wire.Packet) *callV5 { - addr, _ := n.UDPEndpoint() +func (t *UDPv5) callToNode(n *enode.Node, responseType byte, req v5wire.Packet) (*callV5, error) { + addr, ok := n.UDPEndpoint() + if !ok { + return nil, errNoUDPEndpoint + } c := &callV5{id: n.ID(), addr: addr, node: n} t.initCall(c, responseType, req) - return c + return c, nil } // callToID is like callToNode, but for cases where the node record is not available. diff --git a/p2p/discover/v5_udp_test.go b/p2p/discover/v5_udp_test.go index 1c41941c70..109884a6bd 100644 --- a/p2p/discover/v5_udp_test.go +++ b/p2p/discover/v5_udp_test.go @@ -333,6 +333,26 @@ func TestUDPv5_pingCall(t *testing.T) { } } +func TestUDPv5_requestNoEndpoint(t *testing.T) { + t.Parallel() + test := newUDPV5Test(t) + defer test.close() + + n := enode.NewV4(&test.remotekey.PublicKey, nil, 0, 0) + if _, err := test.udp.TalkRequest(n, "", nil); err != errNoUDPEndpoint { + t.Fatalf("TalkRequest error: got %q, want %q", err, errNoUDPEndpoint) + } + if _, err := test.udp.Ping(n); err != errNoUDPEndpoint { + t.Fatalf("Ping error: got %q, want %q", err, errNoUDPEndpoint) + } + if _, err := test.udp.Findnode(n, []uint{0}); err != errNoUDPEndpoint { + t.Fatalf("Findnode error: got %q, want %q", err, errNoUDPEndpoint) + } + if _, err := test.udp.RequestENR(n); err != errNoUDPEndpoint { + t.Fatalf("RequestENR error: got %q, want %q", err, errNoUDPEndpoint) + } +} + // This test checks that outgoing FINDNODE calls work and multiple NODES // replies are aggregated. func TestUDPv5_findnodeCall(t *testing.T) {