AutoNAT spec improvement proposal: specify the reachability state machine
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 1.8k
- Forks
- 320
- Avg merge
- 11d 15h
- Merged PRs (30d)
- 1
Description
This issue distills findings from a systematic cross-implementation evaluation of AutoNAT v2, conducted by [ProbeLab](https://probelab.io/). The final report of the investigation is available in the following [link](https://github.com/probe-lab/autonat-perf-audit/blob/main/docs/final-report.md).
AutoNAT v1 and v2 are the libp2p specs that cover reachability *detection*. Both AutoNAT specs define the wire protocol but leave the **client-side state machine** implementation-defined: no confidence thresholds, no error classification, no event surface, and no rules for composing v1 and v2 results when both run on the same node. A cross-implementation study of go-libp2p, rust-libp2p, and js-libp2p ([final report](https://github.com/probe-lab/autonat-project/blob/main/docs/final-report.md#findings)) found that each implementation has independently answered these questions differently, and the combinations may produce observable reachability divergences today.
Reachability state today can be driven by up to three independent signals. First, **AutoNAT v2 per-address results** — per-multiaddr verdict, nonce-verified, stable under unreliable servers. Second, **AutoNAT v1 global result** — whole-node verdict from majority vote, which may oscillate more than v2 under unreliable servers . Third, **NAT-type classification from observed addresses** — implementation-specific: go-libp2p's `ObservedAddrManager.getNATType()` groups observations by `(IP, transport)` thin waist and classifies mapping behavior as `EndpointIndependent` (cone) or `EndpointDependent` (symmetric NAT), emitting `EvtNATDeviceTypeChanged`; rust-libp2p and js-libp2p have no equivalent. This last signal is not specified anywhere — the `identify` spec mentions `observedAddr` only as raw data ("the initiator can use this address to infer the existence of a NAT and its public address").
No spec defines how these three signals compose into a single reachability state. go-libp2p today uses signal (2) only (v1 drives DHT/AutoRelay/Address Manager/NAT Service); signals (1) and (3) exist but have zero subscribers for state purposes. rust-libp2p uses (1) only. js-libp2p emits nothing at all.
We propose to define the specs for a global reachability state transitions as a function of input NAT signals, evaluated in priority order. These transitions should cover the reachability states of UNKNOW, PRIVATE or PUBLIC and clearly define which events, signals and observability methods must trigger them.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the AutoNAT v1 and v2 specifications and the linked ProbeLab final reports, especially the findings section. Compare the go-libp2p, rust-libp2p, and js-libp2p behavior described there, then define how the three NAT signals compose into UNKNOW, PRIVATE, and PUBLIC states, including transitions, events, and observability methods.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, javascript, rust
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100