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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! **The DHT rendezvous client** (yog's `docs/REMOTE.md` §13.2; DESIGN
//! §3.11) — a pure client of the BitTorrent mainline DHT: outbound-UDP
//! iterative lookups and BEP 44 signed mutable get/put, and never a node. No
//! listener, no routing answers, no storage offered — nothing for the commons
//! to dial back, which is REMOTE §13's ruling 2 applied to the rendezvous
//! itself and DESIGN §2's *it never listens* kept at the DHT.
//!
//! **Reimplemented here rather than shared** (REMOTE §13.7 ruling 2): the
//! engine's `src/dht` is the original and this is its mirror, byte for byte
//! on the wire, because a DHT client is substrate and not protocol — nothing
//! yog-shaped crosses its interface — and a crate of its own would cost more
//! in release machinery than the copy costs.
//!
//! The shape the punched wire consumes is this module root: a caller hands
//! [`Dht::new`] a [`Transport`] (the std UDP socket [`Udp`], or a stand-in),
//! the bootstrap addresses and a [`Config`], then asks [`Dht::get`] for the
//! newest item under a key and salt or [`Dht::put`] to store one a
//! [`Keypair`] signed. Everything the commons answers is untrusted until it
//! verifies: an item without a good signature under the asked-for key is not
//! an item.
//!
//! Four files under this root, one concern each: `bencode` the encoding,
//! `krpc` the datagram shapes, `mutable` the signed item, `transport` the
//! socket seam; `lookup` is the walk, `frontier` its state, `flight` the
//! window of queries in the air, and `items` the two BEP 44 verbs over it.
//! **The walk is yog's as measured on the live mainline** (REMOTE §13.7
//! ruling 3; thrall bl-921e ported yog bl-f6e1, bl-9408, bl-d00f and
//! bl-d9c1): same frontier, same window, same defaults. Synchronous throughout — `std::net` with socket timeouts, no tokio —
//! and every duration is a [`Config`] field a test can shorten, so the fake
//! DHT the suite runs on loopback UDP answers in milliseconds where the
//! commons answers in seconds.
pub
pub
pub
pub
pub use Node;
pub use NodeId;
pub use Keypair;
pub use ;
use SecureRandom;
use SocketAddr;
use Duration;
/// The walk's parameters — stated so a test can shrink them and a caller
/// can widen them. K is BEP 5's; the deadline and α are yog's measurements
/// (REMOTE §13.7 ruling 3): on the live mainline p99 of answers landed inside
/// 0.9 s, and with ~40% of queried nodes silent a window of 8 walked in about
/// half the time BEP 5's 3 did, losing no result (yog bl-d9c1).
pub
/// One client: a transport, the nodes it starts from, and the id it queries
/// as. The id is random per client — a client is not a node and nobody
/// routes by it, so nothing is lost by minting a fresh one every run.
pub
/// Fill `buf` from the system's randomness.
pub
pub