@serfab/cadre-core 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cadre-node.d.ts +148 -17
- package/dist/cadre-node.js +361 -45
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-authorization.d.ts +2 -2
- package/dist/control-authorization.js +1 -0
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.d.ts +1 -1
- package/dist/control-cohort.js +1 -1
- package/dist/control-database.d.ts +105 -14
- package/dist/control-database.js +242 -73
- package/dist/control-database.js.map +1 -1
- package/dist/control-formation-recorder.d.ts +6 -6
- package/dist/control-formation-recorder.js +7 -8
- package/dist/control-formation-recorder.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +90 -3
- package/dist/control-schema.js.map +1 -1
- package/dist/control-write-retry.d.ts +21 -15
- package/dist/control-write-retry.js +21 -15
- package/dist/control-write-retry.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/invitation-bootstrap.d.ts +32 -0
- package/dist/invitation-bootstrap.js +30 -0
- package/dist/invitation-bootstrap.js.map +1 -0
- package/dist/link-budget.d.ts +204 -119
- package/dist/link-budget.js +208 -120
- package/dist/link-budget.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +3 -3
- package/dist/membership-connection-gater.js +3 -3
- package/dist/peer-dial.d.ts +18 -14
- package/dist/peer-dial.js +18 -14
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +3 -3
- package/dist/pending-join-runner.d.ts +186 -0
- package/dist/pending-join-runner.js +649 -0
- package/dist/pending-join-runner.js.map +1 -0
- package/dist/push-fanout.d.ts +1 -1
- package/dist/push-fanout.js +1 -1
- package/dist/seed-bootstrap.d.ts +2 -2
- package/dist/seed-bootstrap.js +1 -1
- package/dist/strand-addr-protocol.js +2 -2
- package/dist/strand-formation-deadlines.d.ts +5 -5
- package/dist/strand-formation-deadlines.js +5 -5
- package/dist/strand-formation-manager.d.ts +18 -4
- package/dist/strand-formation-manager.js +48 -33
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +71 -14
- package/dist/strand-formation-protocol.js +222 -47
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-formation-rejection.d.ts +94 -0
- package/dist/strand-formation-rejection.js +77 -0
- package/dist/strand-formation-rejection.js.map +1 -0
- package/dist/strand-instance-manager.js +4 -1
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-solicitation.d.ts +11 -3
- package/dist/strand-solicitation.js +9 -0
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/types.d.ts +103 -17
- package/dist/types.js +5 -9
- package/dist/types.js.map +1 -1
- package/package.json +22 -22
- package/src/cadre-node.ts +399 -46
- package/src/control-authorization.ts +117 -116
- package/src/control-cohort.ts +1 -1
- package/src/control-database.ts +303 -82
- package/src/control-formation-recorder.ts +8 -9
- package/src/control-schema.ts +90 -3
- package/src/control-write-retry.ts +21 -15
- package/src/index.ts +21 -1
- package/src/invitation-bootstrap.ts +40 -0
- package/src/link-budget.ts +221 -120
- package/src/membership-connection-gater.ts +3 -3
- package/src/peer-dial.ts +18 -14
- package/src/peer-join-backfill.ts +3 -3
- package/src/pending-join-runner.ts +735 -0
- package/src/push-fanout.ts +1 -1
- package/src/seed-bootstrap.ts +2 -2
- package/src/strand-addr-protocol.ts +2 -2
- package/src/strand-formation-deadlines.ts +5 -5
- package/src/strand-formation-manager.ts +62 -37
- package/src/strand-formation-protocol.ts +1036 -802
- package/src/strand-formation-rejection.ts +129 -0
- package/src/strand-instance-manager.ts +4 -1
- package/src/strand-solicitation.ts +17 -4
- package/src/types.ts +99 -17
package/dist/link-budget.js
CHANGED
|
@@ -58,66 +58,87 @@
|
|
|
58
58
|
*
|
|
59
59
|
* ── The counts, and what they cost ──
|
|
60
60
|
*
|
|
61
|
-
* | operation
|
|
62
|
-
* |
|
|
63
|
-
* | open a relayed connection
|
|
64
|
-
* | dial the relay itself
|
|
65
|
-
* |
|
|
66
|
-
* |
|
|
67
|
-
* |
|
|
68
|
-
* |
|
|
69
|
-
* | open a relayed connection, then one
|
|
70
|
-
* |
|
|
71
|
-
*
|
|
72
|
-
*
|
|
61
|
+
* | operation | link round trips | at the declared default |
|
|
62
|
+
* | ---------------------------------------------------------------- | ---------------- | ----------------------- |
|
|
63
|
+
* | open a relayed connection over a relay connection already open | 4 | 14 000 ms |
|
|
64
|
+
* | dial the relay itself | 1 | 3 500 ms |
|
|
65
|
+
* | open a relayed connection, opening the relay connection first | 5 | 17 500 ms |
|
|
66
|
+
* | request a reservation on an open relay connection | 1 | 3 500 ms |
|
|
67
|
+
* | negotiate a protocol over an established circuit | 1 | 3 500 ms |
|
|
68
|
+
* | one request and its answer over an open circuit | 2 | 7 000 ms |
|
|
69
|
+
* | open a relayed connection, then negotiate one protocol | 6 | 21 000 ms |
|
|
70
|
+
* | open a relayed connection, then one request on it | 7 | 24 500 ms |
|
|
71
|
+
* | one Optimystic commit over connections already open | 20 | 70 000 ms |
|
|
72
|
+
*
|
|
73
|
+
* Every row that opens a relayed connection counts opening the relay connection too
|
|
74
|
+
* ({@link RELAYED_DIAL_ROUND_TRIPS}), because a dialer cannot know beforehand whether it holds
|
|
75
|
+
* one, and a budget that is too short fails as silently as an absent peer. The
|
|
76
|
+
* reservation-request row is {@link RELAY_RESERVE_REQUEST_ROUND_TRIPS}, which also sizes how long
|
|
73
77
|
* a party-run relay waits for a stranger's reservation ({@link relayAdmissionReserveDeadlineMs}).
|
|
74
78
|
* The commit row is a measurement of a whole write, not a count of exchanges; its doc comment
|
|
75
79
|
* ({@link COMMIT_ROUND_TRIPS}) holds the figures and says when to re-measure it.
|
|
76
80
|
*
|
|
77
|
-
* **Measured** 2026-09-26, one Windows machine, loopback dedicated relay: a relayed dial
|
|
78
|
-
* 20-25 ms at no delay, **7 255-7 279 ms at 900 ms
|
|
79
|
-
* one-way
|
|
80
|
-
* sits about 60-95 ms ABOVE the arithmetic — the
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
81
|
+
* **Measured** 2026-09-26, one Windows machine, loopback dedicated relay: a relayed dial over a
|
|
82
|
+
* relay connection the dialer already held took 20-25 ms at no delay, **7 255-7 279 ms at 900 ms
|
|
83
|
+
* one-way**, and **12 066-12 094 ms at 1 500 ms one-way**. Four link round trips of pure delay
|
|
84
|
+
* would be 7 200 and 12 000, so the real cost sits about 60-95 ms ABOVE the arithmetic — the
|
|
85
|
+
* handshakes, which no delay figure contains. On 2026-10-01 (libp2p 3.3.11), a dialer holding no
|
|
86
|
+
* relay connection took **15 113 ms at 1 500 ms one-way**: ten one-way delays, five link round
|
|
87
|
+
* trips, 113 ms above the arithmetic. That residue is why {@link DECLARED_LINK_ROUND_TRIP_MS}
|
|
88
|
+
* carries headroom over the link sereus supports rather than matching it exactly: a declaration
|
|
89
|
+
* equal to the supported round trip would derive a budget marginally BELOW the dial it has to
|
|
90
|
+
* contain.
|
|
91
|
+
*
|
|
92
|
+
* NOTE: the instrument splits the delay evenly across both hops (each node's own dialed socket
|
|
93
|
+
* gets the same one-way figure). On a link whose whole round trip sits on one machine's hop to
|
|
94
|
+
* the relay (a phone on a congested mobile link), the exchanges that cross only that hop — the
|
|
95
|
+
* relay dial, the hop-stream negotiation and CONNECT — may cost up to twice their share of the
|
|
96
|
+
* count. Not measured. If relayed dials are seen failing near their budget on such a link,
|
|
97
|
+
* measure that split before raising any count or the declaration.
|
|
98
|
+
*
|
|
99
|
+
* ── Admission decisions ──
|
|
86
100
|
*
|
|
87
101
|
* The table is link time only. Every budget that OPENS a connection also adds
|
|
88
|
-
* {@link ADMISSION_DECISION_TIMEOUT_MS} (2 000 ms)
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* (the instrument dials the relay first). A relayed dial that has to open that connection itself
|
|
101
|
-
* spends one more link round trip, plus the relay's own admission decision when the relay is a
|
|
102
|
-
* party-run control node, and the count counts neither; at the supported link such a dial fits
|
|
103
|
-
* only while the called machine decides in under about 0.9 s.
|
|
104
|
-
* `bug-relayed-dial-budget-omits-opening-the-relay-connection`.
|
|
102
|
+
* {@link ADMISSION_DECISION_TIMEOUT_MS} (2 000 ms) once for each gate the open may pass, because
|
|
103
|
+
* each gate runs on the dialer's clock (the constant's doc says why). A relayed dial passes
|
|
104
|
+
* {@link DIAL_ADMISSION_DECISIONS}, two: a party-run relay's, on the dialer's connection to it,
|
|
105
|
+
* then the called machine's. So a relayed dial is budgeted at 17 500 + 2 x 2 000 = 21 500 ms at
|
|
106
|
+
* the default declaration, a dial plus one request at 28 500 ms, and a reservation drive, which
|
|
107
|
+
* a party-run relay decides twice, at 18 000 ms. The allowance is flat: it is local decision
|
|
108
|
+
* time, not link time, so it does not scale with the declaration. One allowance per gate, rather
|
|
109
|
+
* than slack in the count, is what keeps each budget valid at every declaration.
|
|
110
|
+
*
|
|
111
|
+
* The measurement above crossed no gate. The instrument is bare libp2p on every side, with no
|
|
112
|
+
* cadre connection gater, so the 15 113 ms contains no admission decision at all. The
|
|
113
|
+
* allowances are therefore on top of the measured dial rather than already inside it.
|
|
105
114
|
*
|
|
106
115
|
* ── Optimystic's deadlines, from the same declaration ──
|
|
107
116
|
*
|
|
108
117
|
* cadre states its declared link to Optimystic on the control node and every strand node
|
|
109
|
-
* (`@optimystic/db-p2p`'s `NodeOptions.linkRoundTripMs
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* |
|
|
116
|
-
* |
|
|
117
|
-
* | one
|
|
118
|
-
* |
|
|
119
|
-
*
|
|
120
|
-
*
|
|
118
|
+
* (`@optimystic/db-p2p`'s `NodeOptions.linkRoundTripMs`), and Optimystic derives its network
|
|
119
|
+
* deadlines from it (`resolveLinkDeadlines` in its `rpc-deadline.ts`), each never below the LAN
|
|
120
|
+
* value it replaced. Optimystic's derivation is link time only, so cadre states the three limits
|
|
121
|
+
* that cover opening a connection itself ({@link optimysticDialLimits}): Optimystic's value plus
|
|
122
|
+
* {@link DIAL_ADMISSION_DECISIONS} admission decisions. At the default declaration:
|
|
123
|
+
*
|
|
124
|
+
* | deadline | link round trips | at the default | undeclared |
|
|
125
|
+
* | ------------------------------------------------------- | ---------------------- | -------------- | ---------- |
|
|
126
|
+
* | libp2p `addressDialTimeout`, one address of a dial | 10, + 2 decisions | 39 000 ms | 6 000 ms |
|
|
127
|
+
* | libp2p `dialTimeout`, a dial that carries no signal | 10, + 2 decisions | 39 000 ms | 10 000 ms |
|
|
128
|
+
* | libp2p `inboundUpgradeTimeout`, the listener's side | 5 | 17 500 ms | 10 000 ms |
|
|
129
|
+
* | one request's dial, stream negotiation included | 11, + 2 decisions | 42 500 ms | 3 000 ms |
|
|
130
|
+
* | one request's response | 3 | 10 500 ms | 10 000 ms |
|
|
131
|
+
* | a rebalance transfer's dial, and again its reply | request dial, ≥ 30 000 | 42 500 ms | 30 000 ms |
|
|
132
|
+
*
|
|
133
|
+
* Ten round trips is Optimystic's count for opening a relayed connection through a relay the
|
|
134
|
+
* dialer is not yet connected to, which opens that connection first (about 8.6 round trips over
|
|
135
|
+
* WebSocket, 9.6 over `wss`), with a margin. The two decisions are the gates that open runs
|
|
136
|
+
* through on the dialer's clock: a party-run relay's, on the dialer's connection to it, then the
|
|
137
|
+
* called machine's. Each may take {@link ADMISSION_DECISION_TIMEOUT_MS}.
|
|
138
|
+
*
|
|
139
|
+
* Its churn and under-replication pushes take the request rows' values, and the Quereus plugin
|
|
140
|
+
* derives a write's budgets from the request dial: four of them for the transaction (170 000 ms)
|
|
141
|
+
* and one for cancelling it (42 500 ms). The undeclared column
|
|
121
142
|
* is why cadre always states the value, default included. A fixed 3 000 ms request dial cannot
|
|
122
143
|
* open a relayed connection above 375 ms one-way, and it also bounded the protocol negotiation
|
|
123
144
|
* on a connection that was already open, which is one link round trip: at the supported link
|
|
@@ -128,29 +149,38 @@
|
|
|
128
149
|
* ({@link cohortReadDeadlineMs} says why).
|
|
129
150
|
*
|
|
130
151
|
* NOTE: the longer deadlines are paid against a machine that is gone. An Optimystic request
|
|
131
|
-
* to a peer that never completes a connection
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* The dial case was not measured. cadre's cut-off budgets
|
|
136
|
-
* `CONTROL_READ_RETRY_BUDGET_MS`) are checked between
|
|
137
|
-
* them by that much. If writes on a fast link are seen
|
|
138
|
-
* unreachable machine, declare that deployment's real
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
152
|
+
* to a peer that never completes a connection waits up to the 42 500 ms dial deadline, each of
|
|
153
|
+
* that peer's addresses up to 39 000 ms inside it, and one that connects and never answers
|
|
154
|
+
* waits 10 500. A control write against a connected, silent member fails after about 84 s
|
|
155
|
+
* (one pend round and three cancel rounds; `docs/cadre-consistency.md` → "Deadlines Over
|
|
156
|
+
* Optimystic's Reads and Commits"). The dial case was not measured. cadre's cut-off budgets
|
|
157
|
+
* (`CONTROL_WRITE_RETRY_BUDGET_MS`, `CONTROL_READ_RETRY_BUDGET_MS`) are checked between
|
|
158
|
+
* attempts, so one attempt can outlast them by that much. If writes on a fast link are seen
|
|
159
|
+
* waiting out the dial deadline against an unreachable machine, declare that deployment's real
|
|
160
|
+
* round trip instead of the default.
|
|
161
|
+
*
|
|
162
|
+
* The LISTENER's `inboundUpgradeTimeout` is how long the machine being called lets a half-built
|
|
163
|
+
* connection finish its handshakes, and it is the limit that makes a dial outlasting it silent:
|
|
164
|
+
* at libp2p's 10 000 ms and 1 500 ms one-way, the dialer's own 12 094 ms dial RESOLVED while
|
|
165
|
+
* the listener had already thrown the connection away at 10 s, so the first stream over it died
|
|
166
|
+
* with `Unexpected EOF - stream closed while reading 0/1 bytes` and the listener reported no
|
|
167
|
+
* peer at all. cadre leaves it to Optimystic, with no decisions added: its timer starts when the
|
|
168
|
+
* relay hands the listener the inbound circuit, so it runs over the listener's own upgrade and
|
|
169
|
+
* the listener's own decision, never over the dialer's connection to the relay or the relay's
|
|
170
|
+
* decision. So it has to contain the part of {@link relayedDialBudgetMs} its clock covers, not
|
|
171
|
+
* the whole budget: at most the circuit leg ({@link CIRCUIT_DIAL_ROUND_TRIPS}) plus one
|
|
172
|
+
* {@link ADMISSION_DECISION_TIMEOUT_MS}. Optimystic's derivation does at every declaration: five
|
|
173
|
+
* round trips are at least four plus the allowance once the round trip reaches 2 000 ms, and the
|
|
174
|
+
* 10 000 ms floor covers every shorter one. `link-budget.spec.ts` pins that against Optimystic's
|
|
175
|
+
* own derivation, so a change on either side that breaks it fails there rather than silently on
|
|
176
|
+
* a slow link.
|
|
177
|
+
*
|
|
178
|
+
* NOTE: the whole {@link relayedDialBudgetMs} is longer than the listener's limit (21 500 ms
|
|
179
|
+
* against 17 500 ms at the default), so on a link SLOWER than the one declared, a dial over a
|
|
180
|
+
* relay connection the dialer already holds can outlast the listener while its own budget still
|
|
181
|
+
* runs (at the default, between about a 4.4 s and a 5.4 s round trip), and fails silently
|
|
182
|
+
* instead of with a timeout. At or below the declared link it cannot. If streams dying with
|
|
183
|
+
* `Unexpected EOF` are seen on such a link, declare that link's real round trip.
|
|
154
184
|
*
|
|
155
185
|
* NOTE: derived from the declaration alone, so a per-field override that raises a cadre dial
|
|
156
186
|
* budget above it (`controlCohort.perAddressDialTimeoutMs`, `strandBackfill.dialTimeoutMs`)
|
|
@@ -173,20 +203,20 @@
|
|
|
173
203
|
* declaring a faster link than a client closes that client's connection before its request
|
|
174
204
|
* arrives.
|
|
175
205
|
*/
|
|
206
|
+
import { resolveLinkDeadlines } from '@optimystic/db-p2p';
|
|
176
207
|
/**
|
|
177
208
|
* The link round trip cadre assumes when a host declares none, in milliseconds. A deployment
|
|
178
209
|
* that knows its own link states it with `NetworkConfig.linkRoundTripMs` instead.
|
|
179
210
|
*
|
|
180
211
|
* **Why 3 500.** Sereus supports two machines that reach each other only through a relay up to
|
|
181
212
|
* a **3-second link round trip** (1 500 ms each way — a congested mobile or satellite link;
|
|
182
|
-
* `docs/architecture.md` → "Relay Integration"). The worst relayed dial measured at that link
|
|
183
|
-
* was
|
|
184
|
-
* declaration rounds the supported link up to the next half
|
|
185
|
-
* of link time and leaves about
|
|
186
|
-
* which the loopback measurement on a desktop does not contain. The
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* 1.8 s band sereus supported before, with about 720 ms to spare.)
|
|
213
|
+
* `docs/architecture.md` → "Relay Integration"). The worst relayed dial measured at that link,
|
|
214
|
+
* opening the relay connection first, was 15 113 ms, above the 15 000 ms a declaration of
|
|
215
|
+
* exactly 3 000 would derive, so the declaration rounds the supported link up to the next half
|
|
216
|
+
* second. 3 500 derives 17 500 ms of link time and leaves about 2.4 s over that dial: room for a
|
|
217
|
+
* phone's Noise handshakes, which the loopback measurement on a desktop does not contain. The
|
|
218
|
+
* admission decisions are not in that 2.4 s; they have their own allowance on top (the module
|
|
219
|
+
* doc's "Admission decisions").
|
|
190
220
|
*
|
|
191
221
|
* One budget outside this module does NOT move with it: `DEFAULT_STRAND_FIRST_SYNC_TIMEOUT_MS`
|
|
192
222
|
* (`strand-first-sync-gate.ts`) bounds a whole first sync, which has no round-trip count, so it
|
|
@@ -195,31 +225,35 @@
|
|
|
195
225
|
* ({@link cohortReadDeadlineMs}).
|
|
196
226
|
*
|
|
197
227
|
* What 3 500 costs, against 2 000: a peer that is genuinely gone holds each operation longer
|
|
198
|
-
* before it is abandoned and retried — the link part of a relayed dial
|
|
199
|
-
* 14 s instead of 8 s, and of a control-cohort dial of one peer across
|
|
200
|
-
* instead of
|
|
228
|
+
* before it is abandoned and retried — the link part of a relayed dial 17.5 s instead of 10 s,
|
|
229
|
+
* of a reservation drive 14 s instead of 8 s, and of a control-cohort dial of one peer across
|
|
230
|
+
* all its addresses 70 s instead of 40 s. The admission allowances add to each (see
|
|
231
|
+
* {@link relayedDialBudgetMs}).
|
|
201
232
|
* Raise it further for a link slower still; lower it only on a deployment where EVERY machine
|
|
202
233
|
* of the party is that close, for the reason the "What still fails" list gives.
|
|
203
234
|
*/
|
|
204
235
|
export const DECLARED_LINK_ROUND_TRIP_MS = 3500;
|
|
205
236
|
/**
|
|
206
|
-
* Link round trips
|
|
207
|
-
*
|
|
208
|
-
*
|
|
237
|
+
* Link round trips opening a relayed connection costs over a relay connection the dialer
|
|
238
|
+
* ALREADY holds: the circuit open through the relay (hop-stream negotiation and CONNECT, then
|
|
239
|
+
* the relay's stop stream to the called machine), then the encryption and multiplexer
|
|
240
|
+
* handshakes end to end through it. Measured at 8 one-way delays.
|
|
209
241
|
*/
|
|
210
|
-
export const
|
|
242
|
+
export const CIRCUIT_DIAL_ROUND_TRIPS = 4;
|
|
211
243
|
/**
|
|
212
|
-
* Link round trips
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
* The protocol work measured is 2 — dial the relay (1) plus request the reservation (1). It is
|
|
217
|
-
* budgeted at 4, the relayed-dial count, because the wait afterwards may instead be satisfied
|
|
218
|
-
* by libp2p's own relay discovery, which repeats both legs after identify has run; 4 is
|
|
219
|
-
* therefore the largest thing this one deadline can be asked to contain, and the poll interval
|
|
220
|
-
* (`DEFAULT_RELAY_RESERVE_POLL_MS`) rounds up on top of it.
|
|
244
|
+
* Link round trips the dialer spends opening its own connection to the relay: transport,
|
|
245
|
+
* encryption and multiplexer handshakes on its one hop. Measured at 2 one-way delays. libp2p's
|
|
246
|
+
* circuit transport opens it inside the relayed dial, under the caller's signal, whenever no
|
|
247
|
+
* relay connection is open yet.
|
|
221
248
|
*/
|
|
222
|
-
export const
|
|
249
|
+
export const RELAY_DIAL_ROUND_TRIPS = 1;
|
|
250
|
+
/**
|
|
251
|
+
* Link round trips a relayed dial is budgeted for: opening the relay connection
|
|
252
|
+
* ({@link RELAY_DIAL_ROUND_TRIPS}) and then the circuit over it ({@link CIRCUIT_DIAL_ROUND_TRIPS}).
|
|
253
|
+
* Measured at 10 one-way delays from a dialer holding no relay connection. Counted for every
|
|
254
|
+
* relayed dial, because a dialer cannot know beforehand whether that connection is open.
|
|
255
|
+
*/
|
|
256
|
+
export const RELAYED_DIAL_ROUND_TRIPS = RELAY_DIAL_ROUND_TRIPS + CIRCUIT_DIAL_ROUND_TRIPS;
|
|
223
257
|
/**
|
|
224
258
|
* Link round trips from the moment a party-run relay admits a stranger's connection for relay
|
|
225
259
|
* use to the moment that stranger's RESERVE request reaches it. libp2p's reservation store
|
|
@@ -237,6 +271,19 @@ export const RELAY_RESERVATION_ROUND_TRIPS = 4;
|
|
|
237
271
|
* {@link relayAdmissionReserveDeadlineMs} adds it separately.
|
|
238
272
|
*/
|
|
239
273
|
export const RELAY_RESERVE_REQUEST_ROUND_TRIPS = 1;
|
|
274
|
+
/**
|
|
275
|
+
* Link round trips one whole reservation drive is budgeted for
|
|
276
|
+
* (`relay-reservation.ts`'s `driveRelayReservation`, whose ONE deadline covers the dial, the
|
|
277
|
+
* reservation request and the wait together).
|
|
278
|
+
*
|
|
279
|
+
* The protocol work measured is 2 — dial the relay ({@link RELAY_DIAL_ROUND_TRIPS}) plus request
|
|
280
|
+
* the reservation ({@link RELAY_RESERVE_REQUEST_ROUND_TRIPS}). It is budgeted at twice that,
|
|
281
|
+
* because the wait afterwards may instead be satisfied by libp2p's own relay discovery, which
|
|
282
|
+
* repeats both legs after identify has run; 4 is therefore the largest thing this one deadline
|
|
283
|
+
* can be asked to contain, and the poll interval (`DEFAULT_RELAY_RESERVE_POLL_MS`) rounds up on
|
|
284
|
+
* top of it.
|
|
285
|
+
*/
|
|
286
|
+
export const RELAY_RESERVATION_ROUND_TRIPS = 2 * (RELAY_DIAL_ROUND_TRIPS + RELAY_RESERVE_REQUEST_ROUND_TRIPS);
|
|
240
287
|
/**
|
|
241
288
|
* Link round trips negotiating one protocol over an ALREADY-OPEN connection costs: the
|
|
242
289
|
* multistream-select exchange that `dialProtocol` / `newStream` runs before the stream is
|
|
@@ -282,7 +329,7 @@ export const COMMIT_ROUND_TRIPS = 20;
|
|
|
282
329
|
* possibly through a relay: {@link RELAYED_DIAL_ROUND_TRIPS} + {@link CIRCUIT_REQUEST_ROUND_TRIPS}.
|
|
283
330
|
* The shape of cadre's own one-frame control protocols (strand wake, strand address, seed
|
|
284
331
|
* delivery), each of which bounds the dial and the exchange with ONE deadline. Link time only:
|
|
285
|
-
* {@link relayedRequestBudgetMs} adds the
|
|
332
|
+
* {@link relayedRequestBudgetMs} adds the dial's admission allowances on top.
|
|
286
333
|
*/
|
|
287
334
|
export const RELAYED_REQUEST_ROUND_TRIPS = RELAYED_DIAL_ROUND_TRIPS + CIRCUIT_REQUEST_ROUND_TRIPS;
|
|
288
335
|
/**
|
|
@@ -340,11 +387,13 @@ export const PUSH_TRANSFER_ALLOWANCE_MS = 6000;
|
|
|
340
387
|
* - **The decision is spent on the dialing machine's clock.** libp2p's listener
|
|
341
388
|
* runs this gate before it answers the multiplexer negotiation the dialer is
|
|
342
389
|
* waiting on (`libp2p/dist/src/upgrader.js`), and the listener's own
|
|
343
|
-
* `inboundUpgradeTimeout` is already running while it does
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
390
|
+
* `inboundUpgradeTimeout` is already running while it does; a party-run
|
|
391
|
+
* relay runs the same gate on the dialer's connection to it. So
|
|
392
|
+
* {@link relayedDialBudgetMs}, every budget built on it, and the dial limits
|
|
393
|
+
* cadre states to Optimystic ({@link optimysticDialLimits}) add this deadline
|
|
394
|
+
* once for each of the {@link DIAL_ADMISSION_DECISIONS} gates a dial passes,
|
|
395
|
+
* and the listener's limit Optimystic derives contains the called machine's
|
|
396
|
+
* (the module doc's "Optimystic's deadlines, from the same declaration").
|
|
348
397
|
* Raising it therefore lengthens every dial budget with it: a slow decision
|
|
349
398
|
* still fits, and a dial to a peer that is gone takes that much longer to
|
|
350
399
|
* give up.
|
|
@@ -379,30 +428,37 @@ export function resolveLinkRoundTripMs(linkRoundTripMs) {
|
|
|
379
428
|
}
|
|
380
429
|
return linkRoundTripMs;
|
|
381
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* Admission decisions a relayed dial may wait on, each on the dialer's clock: a party-run relay's,
|
|
433
|
+
* on the dialer's connection to it (`denyInboundEncryptedConnection`), then the called machine's.
|
|
434
|
+
*/
|
|
435
|
+
export const DIAL_ADMISSION_DECISIONS = 2;
|
|
382
436
|
/**
|
|
383
437
|
* Deadline for OPENING a connection to another machine that may only be reachable through a
|
|
384
|
-
* relay: {@link RELAYED_DIAL_ROUND_TRIPS} at the declared link round trip,
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
438
|
+
* relay: {@link RELAYED_DIAL_ROUND_TRIPS} at the declared link round trip, which includes opening
|
|
439
|
+
* the dialer's own connection to the relay, plus one {@link ADMISSION_DECISION_TIMEOUT_MS} for
|
|
440
|
+
* each of the {@link DIAL_ADMISSION_DECISIONS} gates that run on this dial's clock.
|
|
441
|
+
* 5 x 3 500 + 2 x 2 000 = 21 500 ms at the default declaration.
|
|
442
|
+
*
|
|
443
|
+
* What it costs: a peer that is truly gone holds each dial this long before it is abandoned — a
|
|
444
|
+
* per-address dial 21.5 s, a control-cohort dial of one peer across its 4 addresses 86 s, and a
|
|
445
|
+
* wake call's two attempts 57 s — of which the relay leg and the relay's decision are 5.5 s per
|
|
446
|
+
* dial. A dial over a relay connection already open, or to a machine that runs no gate (the
|
|
447
|
+
* dedicated relay container, an open-strand node), gets the same budget; the unused part only
|
|
448
|
+
* lengthens a failure there, never a success.
|
|
393
449
|
*
|
|
394
450
|
* A per-field override of a deadline derived from this one
|
|
395
451
|
* (`network.controlCohort.perAddressDialTimeoutMs`, `strandBackfill.dialTimeoutMs`,
|
|
396
|
-
* `DialWakeOptions.timeoutMs`, …) replaces the whole derived value,
|
|
452
|
+
* `DialWakeOptions.timeoutMs`, …) replaces the whole derived value, allowances included.
|
|
397
453
|
*/
|
|
398
454
|
export function relayedDialBudgetMs(linkRoundTripMs) {
|
|
399
|
-
return RELAYED_DIAL_ROUND_TRIPS * resolveLinkRoundTripMs(linkRoundTripMs) + ADMISSION_DECISION_TIMEOUT_MS;
|
|
455
|
+
return RELAYED_DIAL_ROUND_TRIPS * resolveLinkRoundTripMs(linkRoundTripMs) + DIAL_ADMISSION_DECISIONS * ADMISSION_DECISION_TIMEOUT_MS;
|
|
400
456
|
}
|
|
401
457
|
/**
|
|
402
458
|
* Deadline for what `dialProtocol` does end to end: OPEN a possibly relayed connection
|
|
403
|
-
* ({@link relayedDialBudgetMs}, admission
|
|
404
|
-
* on it ({@link PROTOCOL_NEGOTIATION_ROUND_TRIPS} at the declared link round trip).
|
|
405
|
-
* 3 500 =
|
|
459
|
+
* ({@link relayedDialBudgetMs}, admission allowances included) and then NEGOTIATE one protocol
|
|
460
|
+
* on it ({@link PROTOCOL_NEGOTIATION_ROUND_TRIPS} at the declared link round trip). 21 500 +
|
|
461
|
+
* 3 500 = 25 000 ms at the default declaration. The strand formation dial is bounded by this;
|
|
406
462
|
* the one-frame control exchanges bound the negotiation together with their request instead
|
|
407
463
|
* ({@link relayedRequestBudgetMs}).
|
|
408
464
|
*/
|
|
@@ -459,9 +515,9 @@ export function circuitRequestBudgetMs(linkRoundTripMs, transferAllowanceMs = PU
|
|
|
459
515
|
}
|
|
460
516
|
/**
|
|
461
517
|
* Deadline for opening a (possibly relayed) connection and completing one small request on it:
|
|
462
|
-
* {@link relayedDialBudgetMs}, admission
|
|
518
|
+
* {@link relayedDialBudgetMs}, admission allowances included, plus
|
|
463
519
|
* {@link CIRCUIT_REQUEST_ROUND_TRIPS} at the declared link round trip — so
|
|
464
|
-
* {@link RELAYED_REQUEST_ROUND_TRIPS} of link time in all.
|
|
520
|
+
* {@link RELAYED_REQUEST_ROUND_TRIPS} of link time in all. 21 500 + 2 x 3 500 = 28 500 ms at the
|
|
465
521
|
* default declaration.
|
|
466
522
|
*
|
|
467
523
|
* No transfer allowance, unlike {@link circuitRequestBudgetMs}: the requests this bounds are a few
|
|
@@ -539,4 +595,36 @@ export function peerJoinPushBudget(linkRoundTripMs) {
|
|
|
539
595
|
responseTimeoutMs: circuitRequestBudgetMs(linkRoundTripMs)
|
|
540
596
|
};
|
|
541
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* The three limits that cover opening a connection, as cadre states them to Optimystic on the
|
|
600
|
+
* control node and every strand node: Optimystic's own derivation from the declared link
|
|
601
|
+
* (`resolveLinkDeadlines`), which is link time only, plus one {@link ADMISSION_DECISION_TIMEOUT_MS}
|
|
602
|
+
* for each of the {@link DIAL_ADMISSION_DECISIONS} gates the open runs through. 39 000 ms per
|
|
603
|
+
* address, 39 000 ms per dial and a 42 500 ms request dial at the default declaration.
|
|
604
|
+
*
|
|
605
|
+
* Built on Optimystic's derivation rather than restating its round-trip counts, so a change to
|
|
606
|
+
* them reaches every node without an edit here. `dialTimeout` stays at least `addressDialTimeout`,
|
|
607
|
+
* as Optimystic's derivation has it, because both take the same addition. The request dial stays
|
|
608
|
+
* one round trip longer than `addressDialTimeout`, also as Optimystic derives them, although
|
|
609
|
+
* Optimystic's `rpcDeadlines` doc asks for it to be no longer: that round trip is the stream
|
|
610
|
+
* negotiation after the connection opens, which the per-address limit does not cover.
|
|
611
|
+
*
|
|
612
|
+
* The listener's `inboundUpgradeTimeout` and the request response deadline are left to Optimystic:
|
|
613
|
+
* the listener's timer runs over its own upgrade and its own decision only (the module doc's
|
|
614
|
+
* "Optimystic's deadlines, from the same declaration"), and a response waits on no gate.
|
|
615
|
+
*
|
|
616
|
+
* The declaration is resolved first, so an invalid one fails with cadre's message. A round trip
|
|
617
|
+
* above Optimystic's `MAX_LINK_ROUND_TRIP_MS` throws from Optimystic, here.
|
|
618
|
+
*/
|
|
619
|
+
export function optimysticDialLimits(linkRoundTripMs) {
|
|
620
|
+
const derived = resolveLinkDeadlines(resolveLinkRoundTripMs(linkRoundTripMs));
|
|
621
|
+
const decisionsMs = DIAL_ADMISSION_DECISIONS * ADMISSION_DECISION_TIMEOUT_MS;
|
|
622
|
+
return {
|
|
623
|
+
connectionManager: {
|
|
624
|
+
addressDialTimeout: derived.addressDialTimeoutMs + decisionsMs,
|
|
625
|
+
dialTimeout: derived.libp2pDialTimeoutMs + decisionsMs
|
|
626
|
+
},
|
|
627
|
+
rpcDeadlines: { dialTimeoutMs: derived.dialTimeoutMs + decisionsMs }
|
|
628
|
+
};
|
|
629
|
+
}
|
|
542
630
|
//# sourceMappingURL=link-budget.js.map
|
package/dist/link-budget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-budget.js","sourceRoot":"","sources":["../src/link-budget.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"link-budget.js","sourceRoot":"","sources":["../src/link-budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
* node has at least one UNEXPIRED, NOT-FULLY-CONSUMED open invitation
|
|
37
37
|
* outstanding (`StrandSolicitationService.hasOutstandingInvitation` — the
|
|
38
38
|
* tokens this process minted or published, plus any still-redeemable
|
|
39
|
-
* `FormationInvite` row the usage recorder can see).
|
|
40
|
-
* responder
|
|
41
|
-
*
|
|
39
|
+
* `FormationInvite` row the usage recorder can see). Registering the
|
|
40
|
+
* responder does NOT suspend it, so every node — each registers one at
|
|
41
|
+
* `CadreNode.start` — keeps a live gate. The
|
|
42
42
|
* handler's own trust decision remains the per-token check, which is
|
|
43
43
|
* strictly finer than this one: a peer admitted here can still be rejected
|
|
44
44
|
* in-protocol for a bogus or spent token.
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
* node has at least one UNEXPIRED, NOT-FULLY-CONSUMED open invitation
|
|
37
37
|
* outstanding (`StrandSolicitationService.hasOutstandingInvitation` — the
|
|
38
38
|
* tokens this process minted or published, plus any still-redeemable
|
|
39
|
-
* `FormationInvite` row the usage recorder can see).
|
|
40
|
-
* responder
|
|
41
|
-
*
|
|
39
|
+
* `FormationInvite` row the usage recorder can see). Registering the
|
|
40
|
+
* responder does NOT suspend it, so every node — each registers one at
|
|
41
|
+
* `CadreNode.start` — keeps a live gate. The
|
|
42
42
|
* handler's own trust decision remains the per-token check, which is
|
|
43
43
|
* strictly finer than this one: a peer admitted here can still be rejected
|
|
44
44
|
* in-protocol for a bogus or spent token.
|
package/dist/peer-dial.d.ts
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
* Dialing one peer from a list of candidate addresses, so that an address that
|
|
3
3
|
* never answers cannot use up the time the others needed.
|
|
4
4
|
*
|
|
5
|
-
* libp2p's own multi-address dial (`libp2p.dial(addrs)`,
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* libp2p's own multi-address dial (`libp2p.dial(addrs)`, `DialQueue.dialPeer`)
|
|
6
|
+
* tries the addresses ONE AT A TIME under ONE signal. Its only per-address limit
|
|
7
|
+
* is the connection manager's `addressDialTimeout` (libp2p 3.3+), which cadre
|
|
8
|
+
* sizes for a cold relayed open through two admission decisions
|
|
9
|
+
* (`optimysticDialLimits` in `link-budget.ts`: 39 s at the default declared
|
|
10
|
+
* link). An address whose connection attempt is silently dropped — a firewall, a
|
|
11
|
+
* subnet the dialer cannot route to, a virtual adapter's address a Windows host
|
|
12
|
+
* reports alongside its real ones — holds that dial for that long or until the
|
|
13
|
+
* whole signal expires, and the addresses sorted after it get what is left. It
|
|
11
14
|
* also sorts the list itself (`defaultAddressSorter`), putting loopback addresses
|
|
12
15
|
* last, behind exactly the LAN addresses most likely to be dropped. A phone
|
|
13
16
|
* borrowing a node from a cadre-host whose only reachable address was the
|
|
@@ -26,17 +29,17 @@ import type { Connection, PeerId } from '@libp2p/interface';
|
|
|
26
29
|
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
27
30
|
/**
|
|
28
31
|
* Default limit on ONE address's dial attempt, in ms, at the DEFAULT declared link round trip:
|
|
29
|
-
* `RELAYED_DIAL_ROUND_TRIPS` (
|
|
30
|
-
*
|
|
31
|
-
* was a fixed 8000 ms before it was derived.
|
|
32
|
+
* `RELAYED_DIAL_ROUND_TRIPS` (5) x `DECLARED_LINK_ROUND_TRIP_MS` (3500 ms) plus
|
|
33
|
+
* `DIAL_ADMISSION_DECISIONS` (2) x `ADMISSION_DECISION_TIMEOUT_MS` (2000 ms) = 21 500 ms
|
|
34
|
+
* (`relayedDialBudgetMs`). It was a fixed 8000 ms before it was derived.
|
|
32
35
|
*
|
|
33
36
|
* It has to cover the slowest address that should succeed, because an attempt
|
|
34
37
|
* that needs longer fails the same way on every retry. That is a relayed dial on
|
|
35
38
|
* a mobile link: connect to the relay (transport, encryption and multiplexer
|
|
36
39
|
* handshakes, when no relay connection is open yet), open the circuit, then run
|
|
37
40
|
* both handshakes again end to end through the relay. `link-budget.ts` is where that
|
|
38
|
-
* reasoning is now a measured count instead of an estimate —
|
|
39
|
-
*
|
|
41
|
+
* reasoning is now a measured count instead of an estimate — five link round trips, measured at
|
|
42
|
+
* 15 113 ms on a link whose round trip is 3 s — so the value MOVES with a host's
|
|
40
43
|
* `NetworkConfig.linkRoundTripMs` rather than pinning the band this node can reach to whatever
|
|
41
44
|
* number was typed here. A direct dial that works is far quicker — a phone's WebSocket dial to
|
|
42
45
|
* a node forwarded over `adb reverse` measured 1.6 s end to end.
|
|
@@ -162,9 +165,10 @@ export declare function dialPeerAddrs(dialer: AddrDialer, addrs: readonly Multia
|
|
|
162
165
|
* one address and immediately dialing the next for the same peer therefore
|
|
163
166
|
* joins the dying job, which rejects the new dial with `AbortError` before it
|
|
164
167
|
* touches the network — the next address is never tried. Seen against libp2p
|
|
165
|
-
* 3.1.3; `test/peer-dial.spec.ts`
|
|
166
|
-
*
|
|
167
|
-
* finished by the time a
|
|
168
|
+
* 3.1.3, and the queue's join is unchanged in 3.3.11; `test/peer-dial.spec.ts`
|
|
169
|
+
* dials real nodes so an upgrade that changes it shows up there. All of the
|
|
170
|
+
* queue's cleanup runs as microtasks, so it has finished by the time a
|
|
171
|
+
* macrotask runs.
|
|
168
172
|
*/
|
|
169
173
|
export declare function tryAddrsInTurn<T>(addrs: readonly Multiaddr[], budget: PeerDialBudget, label: string, attempt: (addr: Multiaddr, signal: AbortSignal, attemptMs: number) => Promise<T>): Promise<T>;
|
|
170
174
|
/**
|