Skip to content

discv5/EIP-778: unspecified ENR port range and NODES per-record tolerance #273

Description

@MysticRyuujin

Summary

Two related points where the discv5 wire spec and EIP-778 are silent, which has led implementations to diverge in ways that create a peer-acquisition availability surface. Filing to get normative guidance.

1. Port value range in ENR

EIP-778 defines the predefined keys tcp/udp (and tcp6/udp6) only as "big endian integer". It does not state a uint16 bound, and gives no guidance on what a decoder should do with a value outside 1–65535. The only size constraint in the document is the 300-byte whole-record limit.

Consequences observed across clients:

  • Some decoders reject the whole ENR when a port doesn't fit u16 (strict uint16 decode).
  • Others read the value and later produce an undialable endpoint (e.g. a tcp of 0, or a truncated value).

Question: should ENR port values be normatively constrained to uint16 (1–65535), and should a decoder reject just the offending key, reject the record, or clamp?

2. Per-record tolerance inside a NODES response

The wire spec defines NODES as [request-id, total, [ENR, ...]] and says records are "encoded and verified as specified in EIP-778", and that a recipient "should verify that the received nodes match the requested distances" — but it says nothing about what to do when one record in the list fails to decode or verify.

Implementations diverge:

  • Several abort decoding of the entire NODES message when any single record fails (so one bad record discards up to N good sibling records).
  • At least one isolates per-record and skips only the bad one.

Because NODES records are relayed from a responder's own routing table, a single malformed-but-signed ENR propagating through honest nodes degrades the NODES responses those honest nodes serve — an availability surface, not just a per-peer nuisance.

Question: should the spec state that a recipient MUST/SHOULD skip an individual invalid record and process the remainder, rather than dropping the whole response?

Why raise it

The spec being silent means all current behaviors are equally "compliant," yet they differ in robustness. A one-line normative statement on each point would let clients converge on the resilient behavior. This came out of a cross-client audit where the "one bad record poisons the batch" pattern appeared independently in multiple discv5 implementations (client-side issue filed at sigp/discv5#308).

Possibly relevant to the discv5 v5.2 work (#226) and the attack-mitigation collection (#161).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions