Skip to content

feat(p2p): wire dig-node to its P2P crates (full ladder, DHT locator, address book, dials)#23

Merged
MichaelTaylor3d merged 5 commits into
mainfrom
feat/p2p-crate-integration
Jul 11, 2026
Merged

feat(p2p): wire dig-node to its P2P crates (full ladder, DHT locator, address book, dials)#23
MichaelTaylor3d merged 5 commits into
mainfrom
feat/p2p-crate-integration

Conversation

@MichaelTaylor3d

@MichaelTaylor3d MichaelTaylor3d commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Wires the dig-node to use its P2P crates (dig-gossip / dig-nat / dig-dht / dig-pex / dig-peer-selector) more fully — one cohesive p2p-wiring branch for the #376 sub-batch. Minor bump to v0.19.0 (dig-node-core 0.6.0).

  • #385 — every node peer dial uses the FULL dig-nat traversal ladder (Direct→UPnP→NAT-PMP→PCP→hole-punch→Relayed) via one shared net::full_nat_config helper; relay is a genuine last resort. STUN reflexive-address discovery added to the advertised candidate set (IPv6-first).
  • #386 — removed the orphaned pool-based PeerRpcClient::find_holders seam (0 live callers); dig-dht is the sole content locator.
  • #381 — durable, IPv6-first, provenance+TTL peer address book (address_book::AddressBook); learned addresses accumulate instead of being dial-and-dropped.
  • #387 — PEX-discovered peers (incl. relay-only) feed the address book; dials are sourced from the accumulated book so persisted hints are retried.
  • #384 — the shared dig-peer-selector ranks PEX dial choice (content-agnostic per-peer quality); one selector instance, IPv6-first preserved among ties.

Crate-API findings (release-first follow-ups — NOT editable here; single-writer for dig-node only)

The pinned dig-gossip rev (9177a9b) lacks two intended crate APIs; realized node-side in the interim + flagged for follow-up crate tickets:

  1. AddressManager ingest (#381): no public production API to feed AddressManager (only a #[doc(hidden)] __seed_address_book_for_tests hook). Node keeps its own book; flushes into the crate AddressManager once dig-gossip ships a public offer_addresses(candidates, provenance).
  2. Pool dial-priority hook (#384): PeerPoolConfig has no ranking hook. Selector ordering applies to the node's PEX candidate dials; when dig-gossip ships a pool dial-priority hook the same ranking can drive the pool's own maintenance dial loop.

Verification (local)

  • cargo fmt --all -- --check — clean
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo test -p dig-node-core --lib247 passed, 0 failed (incl. new address_book / net-ladder / STUN / ranker / entry-conversion tests)
  • Build: dig-node-core / dig-runtime / dig-wallet all compile
  • Integration-test execution deferred to CI (local disk hit 100%); they compile clean under clippy --all-targets.

IPv6-first (§5.2) preserved at every touched dial/candidate/advertise path (full-ladder config inherits dig-nat IPv6-first ordering; merge_reflexive + address-book keep IPv6 ahead of IPv4).

SPEC §19 documents the peer-network integration contract.

Closes #381, #384, #385, #386, #387

🤖 Generated with Claude Code

MichaelTaylor3d and others added 5 commits July 11, 2026 14:28
…covery (#385)

Every node peer dial (DHT lookups, multi-source range fetches, PEX candidate
verification) enabled only [Direct, Relayed] — a NAT'd peer skipped UPnP/NAT-PMP/
PCP + hole-punch and jumped straight to the relay, over-loading relay.dig.net and
defeating the "attempt direct traversal before relaying" intent of the IPv6-first
rule (§5.2). dig-nat already implements the full ladder; the node just capped it.

- Add `net::full_nat_config(timeout, stun_server)` — the ONE shared NatConfig
  (full ladder from `NatConfig::default`, relay last) used by all call sites.
- Wire it at `dht::NatDhtTransport::nat_config`, `download::NodeContent::for_dht`,
  and `pex::GossipPexPool::offer_candidates` (the 4th site, `find_holders`, is
  orphaned dead code removed in #386).
- Resolve the relay-colocated STUN server once at bring-up (`<relay-host>:3478`)
  and thread it through so dig-nat's hole-punch tier has a reflexive-address input.
- Discover this node's server-reflexive (public) address via STUN and merge it
  into the advertised candidate set IPv6-first (`net::merge_reflexive`), so a
  remote peer behind a different NAT can dial/hole-punch to it.

IPv6-first preserved: the shared config inherits dig-nat's IPv6-first candidate
ordering; `merge_reflexive` keeps IPv6 ahead of IPv4; advertised discovery unchanged.

Tests: full ladder enabled (regression guard vs Direct+Relayed), STUN set only when
provided, relay-host parsing, reflexive merge ordering (IPv6-first + dedup).

Refs #376, #381, #384, #385, #386, #387
Co-Authored-By: Claude <noreply@anthropic.com>
…is the sole locator (#386)

`PeerRpcClient` + `find_holders` + `PeerAvailability` predated the DHT and had ZERO
live callers (only definitions + a stale doc claiming "#163 dig-dht plugs in behind
Self::find_holders" — an integration that never landed; the DHT went in via
`NodeContent` instead). Removing the dead seam leaves ONE unambiguous provider path:
the dig-dht provider index (`DhtProviderLocator` -> `find_providers`) inside
`NodeContent`, used by both the redirect-on-miss and multi-source fetch paths.

Rewrites the module doc's stale "clean seam for #163" note accordingly.

Refs #376, #253
Co-Authored-By: Claude <noreply@anthropic.com>
Learned peer addresses (PEX, dig.getPeers, introducer, observed pool peers) were
dialed-immediately-or-discarded — nothing accumulated a durable, ordered address
book to seed later candidate selection. Adds `address_book::AddressBook`: one entry
per peer_id, unions dialable addresses IPv6-first (§5.2), records provenance (a
first-hand sighting is not downgraded by a later PEX hint) + a freshen timestamp,
persists relay-only / not-currently-dialable hints, and reads back a ranked,
non-stale candidate list (IPv6-dialable first, then dialable, then relay-only) with
a staleness TTL + capacity eviction.

Crate-API note (release-first follow-up): dig-gossip owns the canonical
AddressManager but exposes NO public production ingest API (only a #[doc(hidden)]
test hook), so this book lives node-side for now; when dig-gossip ships a public
`offer_addresses` ingest API the book flushes into the crate AddressManager (one
source of truth). Documented in the module doc + SPEC §19.7.

Tests: IPv6-first ordering + dedup, relay-only persistence, upsert union/freshen,
provenance non-downgrade, readback ordering, TTL staleness, capacity eviction.

Refs #376
Co-Authored-By: Claude <noreply@anthropic.com>
…l ordering (#387, #384)

Two coupled changes to the PEX pool sink (`GossipPexPool::offer_candidates`):

#387 — feed PEX-discovered peers into the address book, not dial-and-drop. Every
learned candidate (INCLUDING relay-only / not-currently-dialable hints) is offered
into the durable address book (#381) with provenance PEX, so nothing is discarded;
a hint that can't be reached now persists to seed a later dial. Dials are now sourced
from the accumulated book (a superset of this batch), so previously-learned +
relay-only-turned-dialable hints are retried; a failed dial keeps the hint in the book.

#384 — let dig-peer-selector drive dial choice. Adds a `DialRanker` seam
(`SelectorDialRanker` over the shared PeerSelector via its content-agnostic
peer_snapshot) that orders which book candidates are dialed first — reliability
blended with throughput, banned peers last, cold peers explored at a neutral rank.
Reuses the ONE selector instance already ranking download sources (never a second);
IPv6-first order preserved among equally-ranked peers.

Crate-API note (release-first follow-up): dig-gossip's PeerPoolConfig exposes NO
dial-priority hook, so selector ordering applies to the node's PEX candidate dials;
when dig-gossip ships a pool dial-priority hook the same ranking drives the pool's
own maintenance dial loop. Documented in SPEC §19.6/§19.7.

Removes the now-unused `best_socket_addr` helper (superseded by the book's IPv6-first
CandidateAddr ordering). Tests: entry→candidate conversion (dialable IPs, relay-only),
ranker ordering (good→neutral→bad, None ranker no-op).

Refs #376, #381
Co-Authored-By: Claude <noreply@anthropic.com>
Adds SPEC §19 (peer network: full NAT ladder, STUN reflexive discovery, DHT-only
locator, durable address book, PEX handling, selector-driven dial ordering, and the
release-first crate-API integration status). Applies rustfmt across the P2P-wiring
changes and bumps the workspace to v0.19.0 (dig-node-core 0.6.0) — MINOR: new
node-side capability (address book + dial ordering), backwards-compatible.

Refs #376, #381, #384, #385, #386, #387
Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d MichaelTaylor3d changed the title feat(p2p): wire dig-node to its P2P crates — full NAT ladder, DHT-only locator, address book, selector-driven + PEX dials (#381, #384, #385, #386, #387) feat(p2p): wire dig-node to its P2P crates (full ladder, DHT locator, address book, dials) Jul 11, 2026
@MichaelTaylor3d MichaelTaylor3d marked this pull request as ready for review July 11, 2026 22:03
@MichaelTaylor3d MichaelTaylor3d merged commit c6cfe57 into main Jul 11, 2026
9 of 11 checks passed
@MichaelTaylor3d MichaelTaylor3d deleted the feat/p2p-crate-integration branch July 11, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant