mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
p2p/discover: return errNoUDPEndpoint from RequestENR
Mirror the guard applied to (*UDPv4).Dial in #34916: when the target node has no usable UDP endpoint, return errNoUDPEndpoint instead of silently sending the ENRRequest to an invalid AddrPort and waiting for a timeout. The other UDPEndpoint-using request paths in this file already do this: ping v4_udp.go:215 errNoUDPEndpoint Ping v4_udp.go:228 errNoUDPEndpoint newLookup v4_udp.go:309 errNoUDPEndpoint RequestENR v4_udp.go:358 addr, _ := n.UDPEndpoint() <-- outlier RequestENR is reachable from external callers like cmd/devp2p/crawl.go, which feeds in arbitrary nodes that may not have a UDP port set. Before this change, such nodes burn one full RPC timeout; after it, the caller gets a clean error immediately. The added test fails on master with "RPC timeout" and the trace logs "PING/v4 addr=invalid AddrPort", confirming packets are being written to an unspecified address; with the fix it returns errNoUDPEndpoint without doing any I/O.
This commit is contained in:
parent
934a0091fa
commit
6bb35af2b0
2 changed files with 21 additions and 1 deletions
|
|
@ -355,7 +355,10 @@ func (t *UDPv4) findnode(toid enode.ID, toAddrPort netip.AddrPort, target v4wire
|
|||
|
||||
// RequestENR sends ENRRequest to the given node and waits for a response.
|
||||
func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||
addr, _ := n.UDPEndpoint()
|
||||
addr, ok := n.UDPEndpoint()
|
||||
if !ok {
|
||||
return nil, errNoUDPEndpoint
|
||||
}
|
||||
t.ensureBond(n.ID(), addr)
|
||||
|
||||
req := &v4wire.ENRRequest{
|
||||
|
|
|
|||
|
|
@ -158,6 +158,23 @@ func TestUDPv4_pingTimeout(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestUDPv4_RequestENRNoUDPEndpoint verifies that RequestENR returns a clean
|
||||
// errNoUDPEndpoint error for a node without a usable UDP endpoint, instead of
|
||||
// silently sending a packet to the zero address and waiting for a timeout.
|
||||
// This mirrors the existing guards in ping/Ping/findnode.
|
||||
func TestUDPv4_RequestENRNoUDPEndpoint(t *testing.T) {
|
||||
t.Parallel()
|
||||
test := newUDPTest(t)
|
||||
defer test.close()
|
||||
|
||||
key := newkey()
|
||||
// UDP port 0 makes UDPEndpoint return ok=false.
|
||||
node := enode.NewV4(&key.PublicKey, net.ParseIP("1.2.3.4"), 2222, 0)
|
||||
if _, err := test.udp.RequestENR(node); err != errNoUDPEndpoint {
|
||||
t.Errorf("expected errNoUDPEndpoint, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type testPacket byte
|
||||
|
||||
func (req testPacket) Kind() byte { return byte(req) }
|
||||
|
|
|
|||
Loading…
Reference in a new issue