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.
This commit is contained in:
Daniel Liu 2026-07-14 15:26:03 +08:00
parent 68f711b9de
commit 9c7fad9521
2 changed files with 20 additions and 2 deletions

View file

@ -114,8 +114,12 @@ func (n *Node) setIP4(ip netip.Addr) {
} }
func (n *Node) setIPv4Ports() { func (n *Node) setIPv4Ports() {
n.Load((*enr.UDP)(&n.udp)) if err := n.Load((*enr.UDP)(&n.udp)); err != nil {
n.Load((*enr.TCP)(&n.tcp)) 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) { func (n *Node) setIP6(ip netip.Addr) {

View file

@ -229,6 +229,20 @@ func TestNodeEndpoints(t *testing.T) {
wantIP: netip.MustParseAddr("192.168.2.2"), wantIP: netip.MustParseAddr("192.168.2.2"),
wantUDP: 30304, 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", name: "ipv4-quic",
node: func() *Node { node: func() *Node {