1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! The authenticated-identity trust boundary for the DHT handler.
//!
//! [`AuthenticatedNodeId`] wraps a [`NodeId`] that originated from a live QUIC
//! connection's `remote_id()` — i.e. an identity iroh's handshake has bound to
//! the connection, not one a peer asserted in a wire message body. It is
//! deliberately the *only* way to obtain a `NodeId` the handler trusts as "who
//! is actually on the other end".
//!
//! # Why this type exists
//!
//! ADR 022's STORE/FIND flows hinge on distinguishing two superficially
//! identical 32-byte values:
//!
//! - the **authenticated** peer id (`conn.remote_id()`), and
//! - **wire-provided** ids a peer puts in a request body (`StoreRequest.holder`,
//! `FindNodeRequest.requester`, …).
//!
//! Conflating them is the routing-table-poisoning bug class caught in PR #643:
//! inserting `req.requester` into the routing table lets an authenticated peer
//! seed arbitrary (unreachable) ids it does not own. With this type the handler
//! signatures that update trusted state — [`super::routing::RoutingTable`]
//! insertion via `note_peer_seen`, and the `holder == authenticated id` checks
//! — take an `AuthenticatedNodeId`, so passing a wire value there is a *compile*
//! error. Extracting the inner id requires an explicit
//! [`AuthenticatedNodeId::node_id`] call,
//! which documents exactly where trust is being asserted.
//!
//! There is intentionally **no** `From<NodeId>` / `From<[u8; 32]>` impl, and the
//! only constructor takes a live [`Connection`] (not a bare `PublicKey`, which a
//! caller could mint from arbitrary bytes): the type cannot be fabricated from
//! wire data.
//!
//! # Scope
//!
//! This guards the *handler's direct trust decisions* — the per-request routing
//! refresh (`note_peer_seen`) and the `holder` checks — against substituting a
//! request-body id for the connected peer. It does **not** mean every routing
//! insert requires authentication: the iterative-lookup / bucket-refresh /
//! bootstrap paths legitimately learn peers from `FindNode` *responses* and
//! insert those plain [`NodeId`]s as probe candidates (Kademlia by design,
//! bounded by `MAX_CLOSER_NODES`-capped `closer_nodes` and the downstream
//! active-staker filter). The boundary closes the requester/holder-substitution
//! class specifically.
use Connection;
use NodeId;
/// A [`NodeId`] proven by the QUIC handshake to be the connected peer's
/// identity. Constructible only from an authenticated [`Connection`] — see the
/// module docs for the trust rationale.
;