Skip to main content

Crate dig_pex

Crate dig_pex 

Source
Expand description

§dig-pex — Peer Exchange (PEX) for the DIG Node peer network

PEX lets a participant that already holds an authenticated link to another participant tell it, incrementally, which peers it knows first-hand — so the network’s address books stay warm without polling and without a central directory. It adapts the proven mechanics of BitTorrent PEX (ut_pex): peers exchange deltas of their first-hand known-peer set over already-established connections, on a bounded periodic cadence, with hard per-message caps and no third-party re-flooding. This crate is the normative implementation of SPEC.md (wire version 1).

PEX runs in exactly two places (SPEC §1.1):

  1. Node ↔ Node — over the mutual-TLS dig-nat mux stream transport (PexMessage::encode / PexMessage::decode, a u32-BE length prefix + JSON body).
  2. Relay → Node — by the dig-relay introducer, riding the existing RelayMessage WebSocket (RLY-008) as bare JSON text frames (PexMessage::to_json / PexMessage::from_json).

§What it is not (SPEC §1.3)

  • Not a trust channel. Every received entry is a hint — a candidate to dial and verify via the mTLS handshake, never an authenticated fact (PexEvent::Candidates).
  • Not a gossip flood. A participant advertises only what it knows first-hand; the Provenance type has no "pex" token, so a PEX-learned entry can never be re-advertised until independently verified.
  • Not a payment authority. An entry MAY carry a self-signed payment address (PeerEntry::verified_payment_address, SPEC §3.4) so the incentive layer can pay the peer that earned it. The claim proves itself — it carries the peer’s TLS SPKI and a signature this crate binds to peer_id — but PEX neither holds keys nor moves money.
  • Not content discovery. Locating which peers hold content is the DHT’s job (dig-dht); PEX populates the pool of dialable peers underneath it.

§The engine (SPEC Appendix A)

The crate ships a transport-agnostic, sans-IO PexEngine: you feed it link events, inbound messages, local peer-set changes, and clock ticks; it returns the messages to send and the events to act on. Both a DIG Node and the relay embed the same engine — only the I/O adapter differs.

use dig_pex::{PexConfig, PexEngine, PexMessage, PeerEntry, Provenance, Address};

let me = "a".repeat(64);
let peer = "b".repeat(64);
let mut engine = PexEngine::new(PexConfig::new(me, "mainnet").with_jitter(false));

// A first-hand peer we know enters our advertise set.
engine.upsert_known(
    PeerEntry::new("c".repeat(64), "mainnet", 1_000, Provenance::Direct)
        .with_address(Address::direct("203.0.113.7", 9444)),
);

// A link comes up → we emit our handshake + a snapshot of our first-hand set.
let out = engine.link_up(&peer, 1_000_000);
assert!(matches!(out[0], PexMessage::PexHandshake { .. }));
assert!(matches!(out[1], PexMessage::PexSnapshot { .. }));

§DIG Node embedding (node↔node, SPEC §10.1)

On each established peer connection call PexEngine::link_up and write the returned frames on a freshly opened mux stream (that stream is your sending direction). Feed each decoded inbound message to PexEngine::on_message; send its replies and honor a muting PexEvent::Violation. Drive PexEngine::tick ~1/s and write the returned deltas. Feed first-hand knowledge back with PexEngine::upsert_known / PexEngine::remove_known, and on close call PexEngine::link_down. Route PexEvent::Candidates into the dig-gossip AddressManager as new-table candidates to dial + verify (SPEC §9.3).

§dig-relay embedding (relay→node, SPEC §10.2)

Create one engine for the introducer role (flags ["introducer"]). Only after a registered connection sends its pex_handshake do you PexEngine::link_up + PexEngine::on_message and reply as WebSocket text frames. Mirror the registry into the engine (PexEngine::upsert_known on register, PexEngine::remove_known on unregister); never fold inbound node PEX data into the registry — discard node-sent PexEvent::Candidates (the registry is registration-backed only, SPEC §10.2).

Re-exports§

pub use caps::PEX_ARRIVAL_GRACE;
pub use caps::PEX_DEFAULT_INTERVAL;
pub use caps::PEX_MAX_ADDED;
pub use caps::PEX_MAX_ADDRESSES;
pub use caps::PEX_MAX_DROPPED;
pub use caps::PEX_MAX_ENTRY_AGE;
pub use caps::PEX_MAX_FLAGS;
pub use caps::PEX_MAX_FLAG_LEN;
pub use caps::PEX_MAX_FRAME;
pub use caps::PEX_MAX_INTERVAL;
pub use caps::PEX_MAX_SNAPSHOT;
pub use caps::PEX_MIN_INTERVAL;
pub use caps::PEX_VERSION;
pub use caps::PEX_VIOLATION_LIMIT;
pub use engine::PexConfig;
pub use engine::PexEngine;
pub use engine::PexEvent;
pub use engine::PexOutcome;
pub use entry::Address;
pub use entry::AddressKind;
pub use entry::PeerEntry;
pub use entry::Provenance;
pub use entry::ValidateCtx;
pub use error::EntrySkip;
pub use error::PexErrorCode;
pub use payment::payment_signing_bytes;
pub use payment::peer_id_for_spki;
pub use payment::PaymentClaim;
pub use payment::PaymentClaimError;
pub use payment::SignatureVerifier;
pub use payment::PEX_MAX_PAYMENT_ADDRESS_LEN;
pub use payment::PEX_MAX_PAYMENT_SIG_LEN;
pub use payment::PEX_MAX_PAYMENT_SPKI_LEN;
pub use state::LinkState;
pub use state::RecvPhase;
pub use wire::PexMessage;

Modules§

caps
The frozen version-1 protocol constants and the message-level cap checks (SPEC §7.1, §7.2).
engine
The PexEngine — the transport-agnostic, sans-IO core both a DIG Node and the relay embed (SPEC Appendix A).
entry
The peer entry — the unit of exchange (SPEC §3). It is the L7 PeerRecord shape extended with a flags list, carrying a peer_id, candidate addresses, the network_id, a last_seen Unix-seconds timestamp, a via provenance, and per-peer capability flags.
error
The PEX error code space (SPEC §4.5) — the code carried by a pex_error message, and the reasons an inbound peer entry is skipped by receiver-side validation (SPEC §3.3).
payment
The signed payment address (SPEC §3.4) — how a peer says “pay my earnings here” in a way a third party can check.
state
Per-link, per-direction PEX state (SPEC §5, §9).
timer
Timing math (SPEC §6) — interval negotiation, the sender’s effective interval + additive jitter, and the receiver’s anti-flood minimum inter-arrival floor.
wire
The PEX wire — the four type-tagged JSON messages (SPEC §4) and their framing.