From 9c7fad9521e4728631b5bc802610dcd7fbd2b51d Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Tue, 14 Jul 2026 15:26:03 +0800 Subject: [PATCH] p2p/enode: fallback to v6 ports for selected ipv4 endpoint When IPv4 is selected as the preferred address but only UDP6/TCP6 ports are present in ENR, the previous logic left UDP/TCP as zero and produced a non-usable endpoint. Load IPv4 ports first and fall back to UDP6/TCP6 ports only when the IPv4 keys are missing, matching the existing missing-key fallback semantics in function `setIP6`. Add a regression test covering the mixed-stack case where IPv4 is selected while only IPv6-family ports are populated. --- p2p/enode/node.go | 8 ++++++-- p2p/enode/node_test.go | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/p2p/enode/node.go b/p2p/enode/node.go index dafde51d6a..5c71d5bd95 100644 --- a/p2p/enode/node.go +++ b/p2p/enode/node.go @@ -114,8 +114,12 @@ func (n *Node) setIP4(ip netip.Addr) { } func (n *Node) setIPv4Ports() { - n.Load((*enr.UDP)(&n.udp)) - n.Load((*enr.TCP)(&n.tcp)) + if err := n.Load((*enr.UDP)(&n.udp)); err != nil { + n.Load((*enr.UDP6)(&n.udp)) + } + if err := n.Load((*enr.TCP)(&n.tcp)); err != nil { + n.Load((*enr.TCP6)(&n.tcp)) + } } func (n *Node) setIP6(ip netip.Addr) { diff --git a/p2p/enode/node_test.go b/p2p/enode/node_test.go index 51bc4ebe15..340aa8e2cf 100644 --- a/p2p/enode/node_test.go +++ b/p2p/enode/node_test.go @@ -229,6 +229,20 @@ func TestNodeEndpoints(t *testing.T) { wantIP: netip.MustParseAddr("192.168.2.2"), wantUDP: 30304, }, + { + name: "ipv4-selected-falls-back-to-ipv6-family-ports", + node: func() *Node { + var r enr.Record + r.Set(enr.IPv4Addr(netip.MustParseAddr("99.22.33.1"))) + r.Set(enr.IPv6Addr(netip.MustParseAddr("fd00::abcd:1"))) + r.Set(enr.UDP6(30306)) + r.Set(enr.TCP6(30307)) + return SignNull(&r, id) + }(), + wantIP: netip.MustParseAddr("99.22.33.1"), + wantUDP: 30306, + wantTCP: 30307, + }, { name: "ipv4-quic", node: func() *Node {