p2p/discover: add discv5 invalid findnodes result test cases (#32481)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled

Supersedes #32470.

### What
- snap: shorten stall watchdog in `eth/protocols/snap/sync_test.go` from
1m to 10s.
- discover/v5: consolidate FINDNODE negative tests into a single
table-driven test:
  - `TestUDPv5_findnodeCall_InvalidNodes` covers:
    - invalid IP (unspecified `0.0.0.0`) → ignored
    - low UDP port (`<=1024`) → ignored

### Why
- Addresses TODOs:
  - “Make tests smaller” (reduce long 1m timeout).
- “check invalid IPs”; also cover low port per `verifyResponseNode`
rules (UDP must be >1024).

### How it’s validated
- Test-only changes; no production code touched.
- Local runs:
  - `go test ./p2p/discover -count=1 -timeout=300s` → ok
  - `go test ./eth/protocols/snap -count=1 -timeout=600s` → ok
- Lint:
  - `go run build/ci.go lint` → 0 issues on modified files.

### Notes
- The test harness uses `enode.ValidSchemesForTesting` (which includes
the “null” scheme), so records signed with `enode.SignNull` are
signature-valid; failures here are due to IP/port validation in
`verifyResponseNode` and `netutil.CheckRelayAddr`.
- Tests are written as a single table-driven function for clarity; no
helpers or environment switching.

---------

Co-authored-by: lightclient <lightclient@protonmail.com>
This commit is contained in:
Ocenka 2025-08-22 20:44:11 +03:00 committed by GitHub
parent e9656238a7
commit 276ed4848c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -378,9 +378,93 @@ func TestUDPv5_findnodeCall(t *testing.T) {
if !reflect.DeepEqual(response, nodes) {
t.Fatalf("wrong nodes in response")
}
}
// TODO: check invalid IPs
// TODO: check invalid/unsigned record
// BadIdentityScheme mocks an identity scheme not supported by the test node.
type BadIdentityScheme struct{}
func (s BadIdentityScheme) Verify(r *enr.Record, sig []byte) error { return nil }
func (s BadIdentityScheme) NodeAddr(r *enr.Record) []byte {
var id enode.ID
r.Load(enr.WithEntry("badaddr", &id))
return id[:]
}
// This test covers invalid NODES responses for the FINDNODE call in a single table-driven test.
func TestUDPv5_findnodeCall_InvalidNodes(t *testing.T) {
t.Parallel()
test := newUDPV5Test(t)
defer test.close()
for i, tt := range []struct {
name string
ip enr.Entry
port enr.Entry
sign func(r *enr.Record, id enode.ID) *enode.Node
}{
{
name: "invalid ip (unspecified 0.0.0.0)",
ip: enr.IP(net.IPv4zero),
},
{
name: "invalid udp port (<=1024)",
port: enr.UDP(1024),
},
{
name: "invalid record, no signature",
sign: func(r *enr.Record, id enode.ID) *enode.Node {
r.Set(enr.ID("bad"))
r.Set(enr.WithEntry("badaddr", id))
r.SetSig(BadIdentityScheme{}, []byte{})
n, _ := enode.New(BadIdentityScheme{}, r)
return n
},
},
} {
t.Run(tt.name, func(t *testing.T) {
// Build ENR node for test.
var (
distance = 230
remote = test.getNode(test.remotekey, test.remoteaddr).Node()
id = idAtDistance(remote.ID(), distance)
r enr.Record
)
r.Set(enr.IP(intIP(i)))
if tt.ip != nil {
r.Set(tt.ip)
}
r.Set(enr.UDP(30303))
if tt.port != nil {
r.Set(tt.port)
}
r = *enode.SignNull(&r, id).Record()
if tt.sign != nil {
r = *tt.sign(&r, id).Record()
}
// Launch findnode request.
var (
done = make(chan error, 1)
got []*enode.Node
)
go func() {
var err error
got, err = test.udp.Findnode(remote, []uint{uint(distance)})
done <- err
}()
// Handle request.
test.waitPacketOut(func(p *v5wire.Findnode, _ netip.AddrPort, _ v5wire.Nonce) {
test.packetIn(&v5wire.Nodes{ReqID: p.ReqID, RespCount: 1, Nodes: []*enr.Record{&r}})
})
if err := <-done; err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(got) != 0 {
t.Fatalf("expected 0 nodes, got %d", len(got))
}
})
}
}
// This test checks that pending calls are re-sent when a handshake happens.