@serfab/cadre-core 0.12.0 → 0.13.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/README.md +3 -2
- package/dist/cadre-node.d.ts +328 -25
- package/dist/cadre-node.js +760 -59
- package/dist/cadre-node.js.map +1 -1
- package/dist/control-database.d.ts +19 -0
- package/dist/control-database.js +51 -9
- package/dist/control-database.js.map +1 -1
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +30 -2
- package/dist/control-schema.js.map +1 -1
- package/dist/enrolled-machine-store-file.d.ts +13 -0
- package/dist/enrolled-machine-store-file.js +41 -0
- package/dist/enrolled-machine-store-file.js.map +1 -0
- package/dist/enrolled-machine-store.d.ts +81 -0
- package/dist/enrolled-machine-store.js +225 -0
- package/dist/enrolled-machine-store.js.map +1 -0
- package/dist/file-durable-slot.js +5 -3
- package/dist/file-durable-slot.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +23 -5
- package/dist/index.js.map +1 -1
- package/dist/membership-connection-gater.d.ts +15 -1
- package/dist/membership-connection-gater.js +9 -3
- package/dist/membership-connection-gater.js.map +1 -1
- package/dist/node-local-snapshot.d.ts +6 -0
- package/dist/node-local-snapshot.js +7 -1
- package/dist/node-local-snapshot.js.map +1 -1
- package/dist/{strand-backfill.d.ts → peer-join-backfill.d.ts} +49 -20
- package/dist/{strand-backfill.js → peer-join-backfill.js} +133 -52
- package/dist/peer-join-backfill.js.map +1 -0
- package/dist/relay-addrs.d.ts +73 -0
- package/dist/relay-addrs.js +195 -0
- package/dist/relay-addrs.js.map +1 -1
- package/dist/strand-database.d.ts +12 -0
- package/dist/strand-database.js +16 -0
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-formation-manager.d.ts +12 -0
- package/dist/strand-formation-manager.js +10 -3
- package/dist/strand-formation-manager.js.map +1 -1
- package/dist/strand-formation-protocol.d.ts +76 -2
- package/dist/strand-formation-protocol.js +78 -2
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +147 -14
- package/dist/strand-instance-manager.js +225 -45
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-membership-writer.d.ts +12 -0
- package/dist/strand-membership-writer.js +23 -1
- package/dist/strand-membership-writer.js.map +1 -1
- package/dist/strand-network-config.d.ts +84 -0
- package/dist/strand-network-config.js +136 -0
- package/dist/strand-network-config.js.map +1 -0
- package/dist/strand-revocation-enforcer.d.ts +392 -0
- package/dist/strand-revocation-enforcer.js +533 -0
- package/dist/strand-revocation-enforcer.js.map +1 -0
- package/dist/strand-solicitation.d.ts +7 -0
- package/dist/strand-solicitation.js +8 -2
- package/dist/strand-solicitation.js.map +1 -1
- package/dist/strand-watcher.js +6 -1
- package/dist/strand-watcher.js.map +1 -1
- package/dist/types.d.ts +210 -16
- package/dist/types.js +7 -1
- package/dist/types.js.map +1 -1
- package/package.json +16 -8
- package/src/cadre-node.ts +6353 -5603
- package/src/control-database.ts +53 -9
- package/src/control-schema.ts +30 -2
- package/src/enrolled-machine-store-file.ts +43 -0
- package/src/enrolled-machine-store.ts +280 -0
- package/src/file-durable-slot.ts +5 -3
- package/src/index.ts +52 -10
- package/src/membership-connection-gater.ts +9 -3
- package/src/node-local-snapshot.ts +13 -1
- package/src/peer-addr-book.ts +251 -250
- package/src/{strand-backfill.ts → peer-join-backfill.ts} +478 -389
- package/src/relay-addrs.ts +218 -0
- package/src/strand-database.ts +17 -0
- package/src/strand-formation-manager.ts +22 -3
- package/src/strand-formation-protocol.ts +808 -692
- package/src/strand-instance-manager.ts +317 -54
- package/src/strand-membership-writer.ts +23 -1
- package/src/strand-network-config.ts +172 -0
- package/src/strand-revocation-enforcer.ts +653 -0
- package/src/strand-solicitation.ts +484 -471
- package/src/strand-watcher.ts +319 -314
- package/src/types.ts +1554 -1354
- package/dist/strand-backfill.js.map +0 -1
package/dist/relay-addrs.js
CHANGED
|
@@ -100,6 +100,201 @@ export function resolveListenAddrs(network, route = 'configured') {
|
|
|
100
100
|
// acquiring a slot is the whole point of configuring a relay.
|
|
101
101
|
return dedupe([...(listenAddrs ?? [DEFAULT_DIRECT_LISTEN_ADDR]), ...relayEntries]);
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* The `wsPort` value passed purely to turn `@optimystic/db-p2p`'s WebSocket transport
|
|
105
|
+
* ON. It is never bound, so it is deliberately `0` rather than a port scraped from a
|
|
106
|
+
* listen entry.
|
|
107
|
+
*
|
|
108
|
+
* WHY it is a switch and not a port: `createLibp2pNode`
|
|
109
|
+
* (`../optimystic/packages/db-p2p/src/libp2p-node.ts`) feeds `wsPort` into BOTH its
|
|
110
|
+
* default transports and its default listen addrs, and `createLibp2pNodeBase`
|
|
111
|
+
* (`libp2p-node-base.ts:490-491`) falls back to those two defaults INDEPENDENTLY:
|
|
112
|
+
*
|
|
113
|
+
* ```ts
|
|
114
|
+
* const listenAddrs = options.listenAddrs ?? defaults.listenAddrs;
|
|
115
|
+
* const transports = options.transports ?? defaults.transports;
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* `cadre-core` always supplies explicit `listenAddrs` alongside it, so the synthesized
|
|
119
|
+
* `/ip4/<wsHost>/tcp/<wsPort>/ws` default ADDRESS is discarded while the `webSockets()`
|
|
120
|
+
* transport it added survives. A scraped port would also be a lie whenever a config
|
|
121
|
+
* names several WebSocket addresses on different ports, and the strand path rewrites
|
|
122
|
+
* fixed ports to `0` regardless (`strand-network-config.ts`).
|
|
123
|
+
*
|
|
124
|
+
* NOTE: db-p2p's own doc comment on `wsPort` (`libp2p-node-base.ts:170-172`) says it is
|
|
125
|
+
* "Ignored when `transports`/`listenAddrs` are explicitly provided" — true of the
|
|
126
|
+
* address half, NOT of the transport half, which is the half this depends on. Re-verify
|
|
127
|
+
* empirically rather than trusting that comment: `test/listen-transport-options.spec.ts`
|
|
128
|
+
* boots a real node and asserts a `/ws` multiaddr appears. If db-p2p ever makes the
|
|
129
|
+
* comment true of both halves, it needs an explicit `enableWebSockets` switch and this
|
|
130
|
+
* constant becomes unusable.
|
|
131
|
+
*/
|
|
132
|
+
const WS_TRANSPORT_SWITCH_PORT = 0;
|
|
133
|
+
/**
|
|
134
|
+
* The transport-derived libp2p options `listenAddrs` implies, and the gate that stops a
|
|
135
|
+
* listen address the node has no transport for from being SILENTLY dropped.
|
|
136
|
+
*
|
|
137
|
+
* libp2p's transport manager sorts configured listen addresses by which transport claims
|
|
138
|
+
* them, discards the unclaimed ones, and raises `UnsupportedListenAddressesError` only
|
|
139
|
+
* when EVERY address was discarded. Pair a TCP address with a WebSocket one — which is
|
|
140
|
+
* exactly what the shipped configs do — and the TCP address carries the start while the
|
|
141
|
+
* missing WebSocket listener is never reported. Two halves of `NetworkConfig` that have
|
|
142
|
+
* to agree (`listenAddrs`, and the transports the node will actually have) were never
|
|
143
|
+
* checked against each other; this is that check, and it covers both node kinds because
|
|
144
|
+
* both resolve their listen set through {@link resolveListenAddrs}.
|
|
145
|
+
*
|
|
146
|
+
* The two transport classes are handled differently, on purpose:
|
|
147
|
+
*
|
|
148
|
+
* - **WebSocket is DERIVED.** It is the one non-TCP transport the shipped configs need
|
|
149
|
+
* (the React Native reference app's companion drone; `cadre start --ws-port`), and
|
|
150
|
+
* `@optimystic/db-p2p` already knows how to add it. `cadre-core` grows no dependency
|
|
151
|
+
* and decides no transport policy — it flips db-p2p's own switch
|
|
152
|
+
* ({@link WS_TRANSPORT_SWITCH_PORT}).
|
|
153
|
+
* - **Everything else is REFUSED.** Deriving `/quic-v1`, `/webrtc` or `/webtransport`
|
|
154
|
+
* would mean importing transport packages into every `cadre-core` consumer including
|
|
155
|
+
* the React Native and browser bundles (against the cross-platform rule in
|
|
156
|
+
* `AGENTS.md`) and duplicating policy `libp2p-node.ts` owns. So name the address, name
|
|
157
|
+
* the transport it needs, and refuse to start — matching how `network.relayAddrs` and
|
|
158
|
+
* `network.announceAddrs` already treat an operator typo.
|
|
159
|
+
*
|
|
160
|
+
* Returns `{}` unconditionally when `network.transports` is set: a programmatic embedder
|
|
161
|
+
* supplying transport factories owns the policy, and the factories are opaque — nothing
|
|
162
|
+
* can be inferred from them. That is what keeps the RN phone, the web app, and the
|
|
163
|
+
* integration-test harness unaffected.
|
|
164
|
+
*
|
|
165
|
+
* NOTE: pairing this with {@link resolveListenAddrs} is a CONVENTION, not a structure —
|
|
166
|
+
* a third libp2p-node build site could resolve listen addrs and forget to call this,
|
|
167
|
+
* putting the original bug back on that path. Both existing sites are covered
|
|
168
|
+
* (`cadre-node.ts` → `buildControlNodeOptions`, `strand-network-config.ts` →
|
|
169
|
+
* `strandNodeAddrs`), and they are the only two `createLibp2pNode` callers in this repo
|
|
170
|
+
* that derive their listen set from a `NetworkConfig` — the other callers
|
|
171
|
+
* (`integration-tests/src/harness/test-party.ts`, `quereus-plugin-sereus`'s `connect.ts`
|
|
172
|
+
* and `connect-browser.ts`) pass no `listenAddrs` at all, or pass their own transports
|
|
173
|
+
* with it. If a third CONFIG-derived site appears, fold the two functions into one that
|
|
174
|
+
* returns listen addrs and transport options together, so forgetting becomes impossible
|
|
175
|
+
* rather than merely unlikely.
|
|
176
|
+
*
|
|
177
|
+
* @param listenAddrs the ALREADY-resolved listen set — the output of
|
|
178
|
+
* {@link resolveListenAddrs} after any per-node rewriting — so the check reads what
|
|
179
|
+
* this node will actually bind.
|
|
180
|
+
* @throws {UnbindableListenAddressError} when a listen entry names a transport outside
|
|
181
|
+
* {tcp, ws/wss, p2p-circuit}.
|
|
182
|
+
*/
|
|
183
|
+
export function resolveTransportOptions(network, listenAddrs) {
|
|
184
|
+
if (network?.transports) {
|
|
185
|
+
return {};
|
|
186
|
+
}
|
|
187
|
+
const kinds = (listenAddrs ?? []).map((addr) => [addr, listenTransportKind(addr)]);
|
|
188
|
+
const unsupported = kinds.filter(([, kind]) => kind === 'unsupported').map(([addr]) => addr);
|
|
189
|
+
if (unsupported.length > 0) {
|
|
190
|
+
throw new UnbindableListenAddressError(unsupported);
|
|
191
|
+
}
|
|
192
|
+
return kinds.some(([, kind]) => kind === 'websockets') ? { wsPort: WS_TRANSPORT_SWITCH_PORT } : {};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Thrown at config resolution when `network.listenAddrs` names an address none of the
|
|
196
|
+
* default transports can bind. Names each offending address alongside the libp2p
|
|
197
|
+
* transport package it would need — what the operator has without this is a node that
|
|
198
|
+
* starts and silently never listens there.
|
|
199
|
+
*/
|
|
200
|
+
export class UnbindableListenAddressError extends Error {
|
|
201
|
+
constructor(listenAddrs) {
|
|
202
|
+
super('network.listenAddrs names an address this node has no transport for: ' +
|
|
203
|
+
`${listenAddrs.map((a) => `${a} — ${unbindableReason(a)}`).join('; ')}. ` +
|
|
204
|
+
'Default transports bind TCP (including /unix/<path>), WebSocket (/ws, /wss) and circuit-relay addresses only. ' +
|
|
205
|
+
'Either drop the address, or supply the transport programmatically via network.transports.');
|
|
206
|
+
this.listenAddrs = listenAddrs;
|
|
207
|
+
this.name = 'UnbindableListenAddressError';
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Which default transport claims `listenAddr`, or `'unsupported'` when none does.
|
|
212
|
+
*
|
|
213
|
+
* Classification is a multiaddr COMPONENT question, not a string question, so this
|
|
214
|
+
* parses and reads the transport stack — the component names left once the addressing
|
|
215
|
+
* and security layers are dropped. That stack is outermost-LAST
|
|
216
|
+
* (`/ip4/…/tcp/443/tls/ws` → `['tcp', 'ws']`), which is why its terminal entry decides.
|
|
217
|
+
*
|
|
218
|
+
* An unparsable entry is `'ignored'` and passes through untouched, following
|
|
219
|
+
* `isConfiguredCircuitListenAddr` below and `ephemeralPortListenAddr`
|
|
220
|
+
* (`strand-network-config.ts`): libp2p reports a bad listen addr itself, and this check
|
|
221
|
+
* must only ever ADD a denial.
|
|
222
|
+
*/
|
|
223
|
+
function listenTransportKind(listenAddr) {
|
|
224
|
+
let stack;
|
|
225
|
+
try {
|
|
226
|
+
stack = transportStack(listenAddr);
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return 'ignored';
|
|
230
|
+
}
|
|
231
|
+
const outermost = stack.at(-1);
|
|
232
|
+
if (outermost === undefined) {
|
|
233
|
+
// Nothing but addressing components — a bare `/ip4/1.2.3.4`. No transport claims
|
|
234
|
+
// it, so it is dropped by exactly the same silent path this check exists to close.
|
|
235
|
+
return 'unsupported';
|
|
236
|
+
}
|
|
237
|
+
if (outermost === 'p2p-circuit') {
|
|
238
|
+
return 'circuit';
|
|
239
|
+
}
|
|
240
|
+
if (outermost === 'ws' || outermost === 'wss') {
|
|
241
|
+
return 'websockets';
|
|
242
|
+
}
|
|
243
|
+
// Only a BARE tcp or unix stack is TCP. `@libp2p/tcp` binds both — its `listenFilter`
|
|
244
|
+
// accepts an exact TCP match OR a `/unix/<path>` address (a named pipe on Windows) —
|
|
245
|
+
// and nothing layered on top of either, which is why `/tcp/<port>/<anything else>` is
|
|
246
|
+
// NOT waved through merely because a `tcp` component happens to appear.
|
|
247
|
+
return stack.length === 1 && (outermost === 'tcp' || outermost === 'unix') ? 'tcp' : 'unsupported';
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Component names of `listenAddr` with the addressing and security layers removed, so
|
|
251
|
+
* what remains names transports. Host components (`ip4`, `dns4`, …) and the layers that
|
|
252
|
+
* ride inside a transport without being one (`tls`, `sni`, `certhash`, `p2p`) say
|
|
253
|
+
* nothing about which transport has to be configured.
|
|
254
|
+
*/
|
|
255
|
+
function transportStack(listenAddr) {
|
|
256
|
+
return multiaddr(listenAddr).getComponents()
|
|
257
|
+
.map((component) => component.name)
|
|
258
|
+
.filter((name) => !NON_TRANSPORT_COMPONENTS.has(name));
|
|
259
|
+
}
|
|
260
|
+
/** Components that address or secure a connection rather than name its transport. */
|
|
261
|
+
const NON_TRANSPORT_COMPONENTS = new Set([
|
|
262
|
+
'ip4', 'ip6', 'ip6zone', 'dns', 'dns4', 'dns6', 'dnsaddr',
|
|
263
|
+
'tls', 'sni', 'certhash', 'p2p', 'noise'
|
|
264
|
+
]);
|
|
265
|
+
/**
|
|
266
|
+
* Why `listenAddr` cannot be bound, phrased for the operator: the libp2p package that
|
|
267
|
+
* would make it bindable where one is known, and otherwise what is wrong with it.
|
|
268
|
+
*
|
|
269
|
+
* Read OUTERMOST-first (`/udp/…/quic-v1/webtransport` needs `@libp2p/webtransport`,
|
|
270
|
+
* not the `@libp2p/quic` it rides on), matching how `listenTransportKind` decides.
|
|
271
|
+
*/
|
|
272
|
+
function unbindableReason(listenAddr) {
|
|
273
|
+
let stack;
|
|
274
|
+
try {
|
|
275
|
+
stack = transportStack(listenAddr);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return 'not a parsable multiaddr';
|
|
279
|
+
}
|
|
280
|
+
if (stack.length === 0) {
|
|
281
|
+
return 'it names no transport component';
|
|
282
|
+
}
|
|
283
|
+
const pkg = [...stack].reverse().map((name) => TRANSPORT_PACKAGES[name]).find((p) => p !== undefined);
|
|
284
|
+
return pkg === undefined ? 'needs an unrecognized transport' : `needs ${pkg}`;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* The libp2p package each unbindable transport component comes from. Naming the package
|
|
288
|
+
* is the actionable half of the refusal — the operator either drops the address or wires
|
|
289
|
+
* that package in through `network.transports`.
|
|
290
|
+
*/
|
|
291
|
+
const TRANSPORT_PACKAGES = {
|
|
292
|
+
'quic': '@libp2p/quic',
|
|
293
|
+
'quic-v1': '@libp2p/quic',
|
|
294
|
+
'webtransport': '@libp2p/webtransport',
|
|
295
|
+
'webrtc': '@libp2p/webrtc',
|
|
296
|
+
'webrtc-direct': '@libp2p/webrtc'
|
|
297
|
+
};
|
|
103
298
|
/**
|
|
104
299
|
* Thrown out of `CadreNode.start()` when the boot-path reservation drive for
|
|
105
300
|
* `network.relayAddrs` produces no `/p2p-circuit` address on its FIRST attempt.
|
package/dist/relay-addrs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-addrs.js","sourceRoot":"","sources":["../src/relay-addrs.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"relay-addrs.js","sourceRoot":"","sources":["../src/relay-addrs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,SAAS,EAAkB,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIpE;;;;;;;;;GASG;AACH,MAAM,0BAA0B,GAAG,oBAAoB,CAAC;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CAAC;AASvD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA6B;IAC7D,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAkC,EAClC,QAA0B,YAAY;IAEtC,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,KAAK,KAAK,QAAQ;QACrC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,CAAC,CAAC,UAAU,CAAC;IACf,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,CAAC;IACzC,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,kCAAkC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,WAAW,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,kFAAkF;IAClF,4EAA4E;IAC5E,8DAA8D;IAC9D,OAAO,MAAM,CAAC,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,0BAA0B,CAAC,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;AACrF,CAAC;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAkC,EAClC,WAA0C;IAE1C,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAU,CAAC,CAAC;IAC5F,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC7F,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,4BAA4B,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACrG,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrD,YAAqB,WAA8B;QACjD,KAAK,CACH,uEAAuE;YACvE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YACzE,gHAAgH;YAChH,2FAA2F,CAC5F,CAAC;QANiB,gBAAW,GAAX,WAAW,CAAmB;QAOjD,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;IAC7C,CAAC;CACF;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,mBAAmB,CAAC,UAAkB;IAC7C,IAAI,KAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,iFAAiF;QACjF,mFAAmF;QACnF,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QAC9C,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,sFAAsF;IACtF,qFAAqF;IACrF,sFAAsF;IACtF,wEAAwE;IACxE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;AACrG,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,UAAkB;IACxC,OAAO,SAAS,CAAC,UAAU,CAAC,CAAC,aAAa,EAAE;SACzC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;SAClC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,qFAAqF;AACrF,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC;IACvC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS;IACzD,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO;CACzC,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,UAAkB;IAC1C,IAAI,KAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,0BAA0B,CAAC;IACpC,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,iCAAiC,CAAC;IAC3C,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACtG,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,kBAAkB,GAA2B;IACjD,MAAM,EAAE,cAAc;IACtB,SAAS,EAAE,cAAc;IACzB,cAAc,EAAE,sBAAsB;IACtC,QAAQ,EAAE,gBAAgB;IAC1B,eAAe,EAAE,gBAAgB;CAClC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IACpD,YACW,UAA6B,EAC7B,KAA4B;QAErC,KAAK,CACH,kDAAkD,KAAK,CAAC,MAAM,KAAK;YACnE,GAAG,KAAK,CAAC,KAAK,IAAI,kCAAkC,cAAc,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1F,CAAC;QANO,eAAU,GAAV,UAAU,CAAmB;QAC7B,UAAK,GAAL,KAAK,CAAuB;QAMrC,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;IAC5C,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,SAAS,kCAAkC,CAAC,WAA8B;IACxE,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC;IACrE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,6CAA6C;YAC7C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,yDAAyD;YAClF,6EAA6E;YAC7E,mFAAmF,CACpF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,4FAA4F;AAC5F,SAAS,6BAA6B,CAAC,UAAkB;IACvD,IAAI,UAAU,KAAK,wBAAwB,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,UAAU,CAAC,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;QAC/E,uCAAuC;QACvC,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,MAAM,cAAc,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;IACxF,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,cAAc,CAAC;IAC3E,IAAI,CAAC;QACH,yBAAyB,CAAC,UAAU,CAAC,CAAC,CAAC,6BAA6B;IACtE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,4FAA4F,SAAS,EAAE,EACvG,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,2FAA2F;AAC3F,SAAS,eAAe,CAAC,SAAiB;IACxC,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,sDAAsD,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACrG,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,SAAS,MAAM,CAAC,KAAwB;IACtC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -74,6 +74,18 @@ export declare class StrandDatabase {
|
|
|
74
74
|
* Manager can never admit anyone).
|
|
75
75
|
*/
|
|
76
76
|
private deriveFounderKeyPair;
|
|
77
|
+
/**
|
|
78
|
+
* Run the founder membership bootstrap against an ALREADY-LIVE database — the
|
|
79
|
+
* seam {@link StrandInstanceManager.foundExistingStrand} uses when a founder
|
|
80
|
+
* request arrives for an instance that was first launched as a joiner.
|
|
81
|
+
* Idempotent: every bootstrap write is insert-if-absent
|
|
82
|
+
* ({@link bootstrapFounderMembership}), so calling it on an instance that
|
|
83
|
+
* already founded writes nothing. Also flips the captured config's `founder`,
|
|
84
|
+
* so this object's own record of how it was launched stays coherent with what
|
|
85
|
+
* actually ran (a construction-time `founder: false` is a statement about the
|
|
86
|
+
* launch, not a permanent identity).
|
|
87
|
+
*/
|
|
88
|
+
ensureFounderBootstrap(): Promise<void>;
|
|
77
89
|
/**
|
|
78
90
|
* Get the underlying database for queries
|
|
79
91
|
*/
|
package/dist/strand-database.js
CHANGED
|
@@ -103,6 +103,22 @@ export class StrandDatabase {
|
|
|
103
103
|
}
|
|
104
104
|
return strandMemberKeyPair(memberPrivateKey);
|
|
105
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Run the founder membership bootstrap against an ALREADY-LIVE database — the
|
|
108
|
+
* seam {@link StrandInstanceManager.foundExistingStrand} uses when a founder
|
|
109
|
+
* request arrives for an instance that was first launched as a joiner.
|
|
110
|
+
* Idempotent: every bootstrap write is insert-if-absent
|
|
111
|
+
* ({@link bootstrapFounderMembership}), so calling it on an instance that
|
|
112
|
+
* already founded writes nothing. Also flips the captured config's `founder`,
|
|
113
|
+
* so this object's own record of how it was launched stays coherent with what
|
|
114
|
+
* actually ran (a construction-time `founder: false` is a statement about the
|
|
115
|
+
* launch, not a permanent identity).
|
|
116
|
+
*/
|
|
117
|
+
async ensureFounderBootstrap() {
|
|
118
|
+
this.ensureInitialized();
|
|
119
|
+
this.config.founder = true;
|
|
120
|
+
await this.bootstrapFounder();
|
|
121
|
+
}
|
|
106
122
|
/**
|
|
107
123
|
* Get the underlying database for queries
|
|
108
124
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strand-database.js","sourceRoot":"","sources":["../src/strand-database.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"strand-database.js","sourceRoot":"","sources":["../src/strand-database.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,6 +40,17 @@ export interface StrandFormationManagerOptions {
|
|
|
40
40
|
partyId: string;
|
|
41
41
|
/** This party's cadre peer addresses */
|
|
42
42
|
cadrePeerAddrs?: string[];
|
|
43
|
+
/**
|
|
44
|
+
* This node's live STRAND-network multiaddrs for a strand it is running (responder
|
|
45
|
+
* side). Wired by `CadreNode` to its own per-strand address lookup; the manager has no
|
|
46
|
+
* route to the strand runtime itself.
|
|
47
|
+
*
|
|
48
|
+
* A hook, not a `config` knob, so it sits with the other responder-side seams
|
|
49
|
+
* (`strandProvisioner`, `formationUsageRecorder`) rather than among the timeouts. Left
|
|
50
|
+
* unwired — every mock/transport test — the responder simply discloses no strand
|
|
51
|
+
* addresses and cross-party joiners fall back to an empty seed.
|
|
52
|
+
*/
|
|
53
|
+
resolveStrandAddrs?: (strandId: string) => string[];
|
|
43
54
|
/** Configuration options */
|
|
44
55
|
config?: StrandFormationManagerConfig;
|
|
45
56
|
}
|
|
@@ -63,6 +74,7 @@ export declare class StrandFormationManager {
|
|
|
63
74
|
private readonly formationResponseValidator?;
|
|
64
75
|
private readonly partyId;
|
|
65
76
|
private readonly cadrePeerAddrs;
|
|
77
|
+
private readonly resolveStrandAddrs?;
|
|
66
78
|
private readonly config;
|
|
67
79
|
private readonly listener;
|
|
68
80
|
private readonly registeredNodes;
|
|
@@ -49,12 +49,16 @@ export class StrandFormationManager {
|
|
|
49
49
|
this.formationResponseValidator = options.formationResponseValidator;
|
|
50
50
|
this.partyId = options.partyId;
|
|
51
51
|
this.cadrePeerAddrs = options.cadrePeerAddrs ?? [];
|
|
52
|
+
this.resolveStrandAddrs = options.resolveStrandAddrs;
|
|
52
53
|
this.config = options.config ?? {};
|
|
53
54
|
this.listener = new FormationListener({
|
|
54
55
|
validateToken: (token) => this.validateToken(token),
|
|
55
56
|
validateDisclosure: (token, disclosure) => this.validateDisclosure(token, disclosure),
|
|
56
57
|
provisionStrand: (contact, signal) => this.provisionAsResponder(contact, signal),
|
|
57
58
|
getResponderIdentity: () => ({ partyId: this.partyId, cadrePeerAddrs: this.cadrePeerAddrs }),
|
|
59
|
+
// Forwarded only when wired, so `FormationListenerOptions.resolveStrandAddrs`
|
|
60
|
+
// stays genuinely absent (and the listener short-circuits) for an unwired manager.
|
|
61
|
+
...(this.resolveStrandAddrs && { resolveStrandAddrs: this.resolveStrandAddrs }),
|
|
58
62
|
sessionTimeoutMs: this.config.sessionTimeoutMs,
|
|
59
63
|
stepTimeoutMs: this.config.stepTimeoutMs,
|
|
60
64
|
provisionTimeoutMs: this.config.provisionTimeoutMs,
|
|
@@ -108,7 +112,7 @@ export class StrandFormationManager {
|
|
|
108
112
|
};
|
|
109
113
|
this.dialerSessions++;
|
|
110
114
|
try {
|
|
111
|
-
const
|
|
115
|
+
const dialed = await dialFormation(node, {
|
|
112
116
|
contact,
|
|
113
117
|
responderAddrs: invitation.bootstrap,
|
|
114
118
|
validateResponse: (response) => this.validateResponse(invitation, disclosure, response),
|
|
@@ -117,7 +121,8 @@ export class StrandFormationManager {
|
|
|
117
121
|
provisionTimeoutMs: this.initiatorProvisionTimeoutMs(),
|
|
118
122
|
protocolId: this.config.protocolId
|
|
119
123
|
});
|
|
120
|
-
|
|
124
|
+
const provision = dialed.provision;
|
|
125
|
+
log('Strand formed: %s (%d cross-party strand addr(s))', provision.strand.strandId, dialed.strandAddrs.length);
|
|
121
126
|
return {
|
|
122
127
|
memberKey: contact.partyId,
|
|
123
128
|
invitePrivateKey: '',
|
|
@@ -125,7 +130,9 @@ export class StrandFormationManager {
|
|
|
125
130
|
// The host strand's membership key, delivered through the protocol (provision-then-record).
|
|
126
131
|
// Undefined for an open strand. Kept separate from invitePrivateKey (the initiator's
|
|
127
132
|
// generated signing key), which is set by the StrandSolicitationService layer.
|
|
128
|
-
memberPrivateKey: provision.memberPrivateKey
|
|
133
|
+
memberPrivateKey: provision.memberPrivateKey,
|
|
134
|
+
// Possibly empty — the responder may hold no live strand node yet.
|
|
135
|
+
strandAddrs: dialed.strandAddrs
|
|
129
136
|
};
|
|
130
137
|
}
|
|
131
138
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strand-formation-manager.js","sourceRoot":"","sources":["../src/strand-formation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOjE,OAAO,EACL,sBAAsB,EAEvB,MAAM,yBAAyB,CAAC;AACjC,qFAAqF;AACrF,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQpD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,mCAAmC,EACnC,aAAa,EACb,6BAA6B,EAK9B,MAAM,gCAAgC,CAAC;AAExC,MAAM,GAAG,GAAG,KAAK,CAAC,gCAAgC,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,CAAC,GAAG,IAAI,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,0BAA0B,GAA6C;IAC3E,OAAO,EAAE,4BAA4B;IACrC,WAAW,EAAE,uCAAuC;IACpD,SAAS,EAAE,4BAA4B;IACvC,UAAU,EAAE,wCAAwC;IACpD,aAAa,EAAE,kCAAkC;CAClD,CAAC;
|
|
1
|
+
{"version":3,"file":"strand-formation-manager.js","sourceRoot":"","sources":["../src/strand-formation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOjE,OAAO,EACL,sBAAsB,EAEvB,MAAM,yBAAyB,CAAC;AACjC,qFAAqF;AACrF,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQpD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,mCAAmC,EACnC,aAAa,EACb,6BAA6B,EAK9B,MAAM,gCAAgC,CAAC;AAExC,MAAM,GAAG,GAAG,KAAK,CAAC,gCAAgC,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,CAAC,GAAG,IAAI,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,0BAA0B,GAA6C;IAC3E,OAAO,EAAE,4BAA4B;IACrC,WAAW,EAAE,uCAAuC;IACpD,SAAS,EAAE,4BAA4B;IACvC,UAAU,EAAE,wCAAwC;IACpD,aAAa,EAAE,kCAAkC;CAClD,CAAC;AAyDF;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,sBAAsB;IAajC,YAAY,OAAsC;QAHjC,oBAAe,GAAG,IAAI,GAAG,EAAU,CAAC;QAC7C,mBAAc,GAAG,CAAC,CAAC;QAGzB,IAAI,CAAC,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;QACvD,IAAI,CAAC,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC;QAC7D,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACnD,IAAI,CAAC,0BAA0B,GAAG,OAAO,CAAC,0BAA0B,CAAC;QACrE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;QACrD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;QAEnC,IAAI,CAAC,QAAQ,GAAG,IAAI,iBAAiB,CAAC;YACpC,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;YACnD,kBAAkB,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,UAAU,CAAC;YACrF,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CACnC,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC;YAC5C,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC;YAC5F,8EAA8E;YAC9E,mFAAmF;YACnF,GAAG,CAAC,IAAI,CAAC,kBAAkB,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC/E,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB;YAC9C,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;YACxC,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,kBAAkB;YAClD,qBAAqB,EAAE,IAAI,CAAC,MAAM,CAAC,qBAAqB;SACzD,CAAC,CAAC;QAEH,GAAG,CAAC,8CAA8C,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED;;;OAGG;IACH,iBAAiB,CAAC,IAAY,EAAE,UAAmB;QACjD,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACnE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,IAAY,EAAE,UAAmB;QACnD,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACrE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,UAAU,CACd,UAA0B,EAC1B,UAAqC,EACrC,OAAyE,EACzE,IAAY;QAEZ,GAAG,CAAC,0CAA0C,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;QAElE,MAAM,OAAO,GAA4B;YACvC,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;YAC3C,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,UAAU;YACV,cAAc,EAAE,IAAI,CAAC,cAAc;SACpC,CAAC;QAEF,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE;gBACvC,OAAO;gBACP,cAAc,EAAE,UAAU,CAAC,SAAS;gBACpC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC;gBACvF,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB;gBAC9C,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;gBACxC,kBAAkB,EAAE,IAAI,CAAC,2BAA2B,EAAE;gBACtD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;aACnC,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,GAAG,CAAC,mDAAmD,EAAE,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAE/G,OAAO;gBACL,SAAS,EAAE,OAAO,CAAC,OAAO;gBAC1B,gBAAgB,EAAE,EAAE;gBACpB,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,QAAQ;gBACnC,4FAA4F;gBAC5F,qFAAqF;gBACrF,+EAA+E;gBAC/E,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;gBAC5C,mEAAmE;gBACnE,WAAW,EAAE,MAAM,CAAC,WAAW;aAChC,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC;IAChF,CAAC;IAED;;;;;;;;OAQG;IACK,2BAA2B;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;QAC5C,OAAO,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,mCAAmC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnF,CAAC;IAED,gFAAgF;IAExE,KAAK,CAAC,aAAa,CAAC,KAAa;QACvC,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACjC,8CAA8C;YAC9C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACzE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACtB,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;YAChC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,MAAM,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,GAAG,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;YACrC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC1B,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,KAAa,EAAE,UAAqC;QACnF,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC9B,oDAAoD;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACxE,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACK,KAAK,CAAC,oBAAoB,CAChC,OAAgC,EAChC,MAAoB;QAEpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,qFAAqF;QACrF,wFAAwF;QACxF,qFAAqF;QACrF,yCAAyC;QACzC,MAAM,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,oBAAoB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,UAAU,GAAG,oBAAoB,EAAE,CAAC;YACnF,GAAG,CAAC,8CAA8C,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QAC7D,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC;QAC7C,MAAM,QAAQ,GAAuB,QAAQ,EAAE,aAAa;YAC1D,CAAC,CAAC,MAAM,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;YACrC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAExB,IAAI,CAAC;YACH,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACtB,KAAK,OAAO,CAAC,CAAC,CAAC;oBACb,8EAA8E;oBAC9E,MAAM,QAAS,CAAC,WAAW,CAAC;wBAC1B,KAAK;wBACL,OAAO,EAAE,OAAO,CAAC,OAAO;wBACxB,aAAa,EAAE,OAAO,CAAC,aAAa;wBACpC,YAAY,EAAE,OAAO,CAAC,YAAY;wBAClC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wBAC3B,UAAU,EAAE,cAAc;wBAC1B,MAAM;qBACP,CAAC,CAAC;oBACH,OAAO,IAAI,CAAC,OAAO,CAAC;wBAClB,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE;wBAC/D,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,IAAI,SAAS;wBACxD,gBAAgB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;qBAC5D,CAAC,CAAC;gBACL,CAAC;gBACD,KAAK,SAAS,CAAC,CAAC,CAAC;oBACf,GAAG,CAAC,wEAAwE,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;oBACxG,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,iDAAiD,EAAE,CAAC;gBACxF,CAAC;gBACD,KAAK,SAAS;oBACZ,OAAO,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,qBAAqB,EAAE,CAAC;gBACzC,oFAAoF;gBACpF,0EAA0E;gBAC1E,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,IAAI,GAAG,YAAY,sBAAsB,EAAE,CAAC;gBAC1C,GAAG,CAAC,uCAAuC,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;gBACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9E,CAAC;YACD,IAAI,GAAG,YAAY,wBAAwB,EAAE,CAAC;gBAC5C,yFAAyF;gBACzF,qFAAqF;gBACrF,4EAA4E;gBAC5E,kDAAkD;gBAClD,uFAAuF;gBACvF,uEAAuE;gBACvE,GAAG,CACD,qEAAqE,EACrE,GAAG,CAAC,KAAK,EACT,GAAG,CAAC,YAAY,EAChB,GAAG,CAAC,SAAS,CACd,CAAC;gBACF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;YAC3D,CAAC;YACD,sFAAsF;YACtF,uFAAuF;YACvF,oFAAoF;YACpF,6EAA6E;YAC7E,GAAG,CAAC,8CAA8C,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YAChE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;QAClE,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACK,KAAK,CAAC,gBAAgB,CAC5B,OAAgC,EAChC,cAAsB,EACtB,MAAoB;QAEpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC;QAC7C,IAAI,QAAQ,EAAE,kBAAkB,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC;gBACpD,KAAK;gBACL,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,MAAM;gBACN,UAAU,EAAE,cAAc;gBAC1B,MAAM;aACP,CAAC,CAAC;YACH,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE;gBAClE,gBAAgB,EAAE,WAAW,CAAC,gBAAgB,IAAI,SAAS;gBAC3D,gBAAgB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;aAC5D,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACnG,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE;gBAC7D,gBAAgB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;aAC5D,CAAC,CAAC;QACL,CAAC;QAED,4FAA4F;QAC5F,MAAM,QAAQ,GAAG,UAAU,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAClF,OAAO,IAAI,CAAC,OAAO,CAAC;YAClB,MAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE;YAC5C,gBAAgB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;SAC5D,CAAC,CAAC;IACL,CAAC;IAED,iFAAiF;IACzE,OAAO,CAAC,MAAgC;QAC9C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,mBAAmB,CAAC,KAAa;QAC7C,IAAI,CAAC,IAAI,CAAC,sBAAsB;YAAE,OAAO,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC,UAAU,EAAE,MAAM,IAAI,EAAE,CAAC;IACxC,CAAC;IAED,gFAAgF;IAExE,KAAK,CAAC,gBAAgB,CAC5B,UAA0B,EAC1B,UAAqC,EACrC,QAAgC;QAEhC,IAAI,IAAI,CAAC,0BAA0B,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,0BAA0B,CAAC,gBAAgB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,OAAO,6BAA6B,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAC1C,OAAsC;IAEtC,OAAO,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -45,6 +45,17 @@ export declare const INVALID_TOKEN_REASON = "Invalid token";
|
|
|
45
45
|
* responder's reply again — raise it, or derive it from an observed round-trip.
|
|
46
46
|
*/
|
|
47
47
|
export declare const PROVISION_RESPONSE_TRAVEL_MARGIN_MS = 3000;
|
|
48
|
+
/**
|
|
49
|
+
* Cap on the strand-network addresses a formation result carries
|
|
50
|
+
* ({@link FormationResultMessage.strandAddrs}). A node's own strand multiaddrs are a
|
|
51
|
+
* handful of entries (one per listen transport, plus a circuit-relay reservation), so
|
|
52
|
+
* 16 is generous for the honest case while keeping the result frame bounded against a
|
|
53
|
+
* peer that would pad it — either direction, since both sides run the list through
|
|
54
|
+
* {@link sanitizeStrandAddrs}. Exported because the same bound has to hold on the
|
|
55
|
+
* initiator's stored copy: `CadreNode` accumulates across repeat formations against one
|
|
56
|
+
* strand, so it caps the accumulation rather than only each arriving list.
|
|
57
|
+
*/
|
|
58
|
+
export declare const MAX_STRAND_ADDRS = 16;
|
|
48
59
|
export type FormationParty = 'initiator' | 'responder';
|
|
49
60
|
export interface FormationStrandInfo {
|
|
50
61
|
strandId: string;
|
|
@@ -114,9 +125,35 @@ export interface FormationResultMessage {
|
|
|
114
125
|
partyId?: string;
|
|
115
126
|
/** Responder's real multiaddrs (omitted on rejection). */
|
|
116
127
|
cadrePeerAddrs?: string[];
|
|
128
|
+
/**
|
|
129
|
+
* The responder's live STRAND-network multiaddrs for the provisioned strand — the
|
|
130
|
+
* initiator's only cross-party discovery seed, since the strand-addr RPC that resolves
|
|
131
|
+
* a sibling's strand addrs is membership-gated and answers own-party callers only.
|
|
132
|
+
*
|
|
133
|
+
* Disclosed on the same terms as `partyId`/`cadrePeerAddrs`: only after token +
|
|
134
|
+
* disclosure validation AND an approving provisioning outcome; a rejection carries
|
|
135
|
+
* none. Signaling-first, each entry ending in `/p2p/<responder strand transport
|
|
136
|
+
* peerId>` so the initiator can attribute it. OMITTED when the responder holds no live
|
|
137
|
+
* strand node for the provisioned strand (the responder-provisions path mints a strand
|
|
138
|
+
* that has not launched yet) — an absent or empty list is legal and means "no
|
|
139
|
+
* cross-party seed", never a protocol error.
|
|
140
|
+
*/
|
|
141
|
+
strandAddrs?: string[];
|
|
117
142
|
/** The provisioned strand/db result (always present on approval). */
|
|
118
143
|
provisionResult?: FormationProvisionResult;
|
|
119
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Normalize a strand-address list arriving from — or heading to — the wire: keep only
|
|
147
|
+
* parsable multiaddr strings, drop duplicates, and cap at {@link MAX_STRAND_ADDRS}.
|
|
148
|
+
* Order is preserved, so the responder's signaling-first ordering survives.
|
|
149
|
+
*
|
|
150
|
+
* Applied on BOTH sides on purpose. The responder bounds what it sends; the initiator
|
|
151
|
+
* bounds what it stores, because a peer is free to ignore the cap. A malformed entry is
|
|
152
|
+
* SKIPPED rather than fatal — these are runtime-discovered addresses (same posture as
|
|
153
|
+
* `extractCircuitRelayTargets` in `delegate-admission.ts`), and one bad entry must not
|
|
154
|
+
* cost a formation that has otherwise succeeded.
|
|
155
|
+
*/
|
|
156
|
+
export declare function sanitizeStrandAddrs(addrs: unknown): string[];
|
|
120
157
|
/**
|
|
121
158
|
* Structural check on a `responderCreates` result: the responder must have approved,
|
|
122
159
|
* disclosed a non-empty real identity + cadre (not the legacy `cadre-*.local`
|
|
@@ -158,6 +195,17 @@ export interface FormationListenerOptions {
|
|
|
158
195
|
partyId: string;
|
|
159
196
|
cadrePeerAddrs: string[];
|
|
160
197
|
};
|
|
198
|
+
/**
|
|
199
|
+
* This node's live STRAND-network multiaddrs for a provisioned strand, read on the
|
|
200
|
+
* approval path only (same disclosure timing as {@link getResponderIdentity}) and
|
|
201
|
+
* carried back as {@link FormationResultMessage.strandAddrs}.
|
|
202
|
+
*
|
|
203
|
+
* Optional, and an empty answer is legal: the strand may not be running here yet (the
|
|
204
|
+
* responder-provisions path mints it during this very session). The listener cannot
|
|
205
|
+
* reach the strand runtime itself, so this is the seam `CadreNode` wires to its own
|
|
206
|
+
* per-strand address lookup.
|
|
207
|
+
*/
|
|
208
|
+
resolveStrandAddrs?(strandId: string): string[];
|
|
161
209
|
sessionTimeoutMs?: number;
|
|
162
210
|
stepTimeoutMs?: number;
|
|
163
211
|
/**
|
|
@@ -234,6 +282,14 @@ export declare class FormationListener {
|
|
|
234
282
|
* multihash, and `partyId` itself is never stored.
|
|
235
283
|
*/
|
|
236
284
|
private isJoinerConsentValid;
|
|
285
|
+
/**
|
|
286
|
+
* The strand addresses to disclose for an APPROVED provisioning, sanitized and capped.
|
|
287
|
+
*
|
|
288
|
+
* Never throws: a hook that fails (a strand runtime torn down mid-session) costs the
|
|
289
|
+
* joiner its cross-party seed, not the formation it has already earned — the seed is
|
|
290
|
+
* an optimization, the consent row is the commitment.
|
|
291
|
+
*/
|
|
292
|
+
private strandAddrsFor;
|
|
237
293
|
private runSession;
|
|
238
294
|
}
|
|
239
295
|
export interface FormationDialOptions {
|
|
@@ -253,9 +309,27 @@ export interface FormationDialOptions {
|
|
|
253
309
|
provisionTimeoutMs?: number;
|
|
254
310
|
protocolId?: string;
|
|
255
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* What one successful formation dial yields the initiator.
|
|
314
|
+
*
|
|
315
|
+
* The provisioned strand travels in {@link FormationProvisionResult}, but the responder's
|
|
316
|
+
* strand-network addresses are NOT part of that structure — they are a disclosure of the
|
|
317
|
+
* responder's live runtime, alongside `partyId`/`cadrePeerAddrs`, not a property of the
|
|
318
|
+
* strand row. Returning them beside the provision result keeps that separation while
|
|
319
|
+
* still handing the caller the one thing it needs to seed a cross-party mesh.
|
|
320
|
+
*
|
|
321
|
+
* `strandAddrs` is always an array and is frequently EMPTY — see
|
|
322
|
+
* {@link FormationResultMessage.strandAddrs}.
|
|
323
|
+
*/
|
|
324
|
+
export interface FormationDialResult {
|
|
325
|
+
provision: FormationProvisionResult;
|
|
326
|
+
/** Sanitized + capped ({@link sanitizeStrandAddrs}); `[]` when the responder sent none. */
|
|
327
|
+
strandAddrs: string[];
|
|
328
|
+
}
|
|
256
329
|
/**
|
|
257
330
|
* Initiator side of the native formation protocol. Dials the responder, sends the
|
|
258
331
|
* contact (carrying the real disclosure/token/cadre), validates the responder's
|
|
259
|
-
* result, and returns the strand the responder provisioned
|
|
332
|
+
* result, and returns the strand the responder provisioned plus the responder's
|
|
333
|
+
* strand-network addresses (see {@link FormationDialResult}).
|
|
260
334
|
*/
|
|
261
|
-
export declare function dialFormation(node: Libp2p, options: FormationDialOptions): Promise<
|
|
335
|
+
export declare function dialFormation(node: Libp2p, options: FormationDialOptions): Promise<FormationDialResult>;
|
|
@@ -101,6 +101,56 @@ const DEFAULT_INITIATOR_PROVISION_TIMEOUT_MS = DEFAULT_PROVISION_TIMEOUT_MS + PR
|
|
|
101
101
|
* raised well above its default or this cap is lowered.
|
|
102
102
|
*/
|
|
103
103
|
const DEFAULT_MAX_CONCURRENT_SESSIONS = 100;
|
|
104
|
+
/**
|
|
105
|
+
* Cap on the strand-network addresses a formation result carries
|
|
106
|
+
* ({@link FormationResultMessage.strandAddrs}). A node's own strand multiaddrs are a
|
|
107
|
+
* handful of entries (one per listen transport, plus a circuit-relay reservation), so
|
|
108
|
+
* 16 is generous for the honest case while keeping the result frame bounded against a
|
|
109
|
+
* peer that would pad it — either direction, since both sides run the list through
|
|
110
|
+
* {@link sanitizeStrandAddrs}. Exported because the same bound has to hold on the
|
|
111
|
+
* initiator's stored copy: `CadreNode` accumulates across repeat formations against one
|
|
112
|
+
* strand, so it caps the accumulation rather than only each arriving list.
|
|
113
|
+
*/
|
|
114
|
+
export const MAX_STRAND_ADDRS = 16;
|
|
115
|
+
/**
|
|
116
|
+
* Normalize a strand-address list arriving from — or heading to — the wire: keep only
|
|
117
|
+
* parsable multiaddr strings, drop duplicates, and cap at {@link MAX_STRAND_ADDRS}.
|
|
118
|
+
* Order is preserved, so the responder's signaling-first ordering survives.
|
|
119
|
+
*
|
|
120
|
+
* Applied on BOTH sides on purpose. The responder bounds what it sends; the initiator
|
|
121
|
+
* bounds what it stores, because a peer is free to ignore the cap. A malformed entry is
|
|
122
|
+
* SKIPPED rather than fatal — these are runtime-discovered addresses (same posture as
|
|
123
|
+
* `extractCircuitRelayTargets` in `delegate-admission.ts`), and one bad entry must not
|
|
124
|
+
* cost a formation that has otherwise succeeded.
|
|
125
|
+
*/
|
|
126
|
+
export function sanitizeStrandAddrs(addrs) {
|
|
127
|
+
if (!Array.isArray(addrs))
|
|
128
|
+
return [];
|
|
129
|
+
const out = [];
|
|
130
|
+
const seen = new Set();
|
|
131
|
+
for (const entry of addrs) {
|
|
132
|
+
if (out.length >= MAX_STRAND_ADDRS)
|
|
133
|
+
break;
|
|
134
|
+
if (typeof entry !== 'string' || entry.length === 0) {
|
|
135
|
+
log('strandAddrs: skipping non-string entry %o', entry);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (seen.has(entry))
|
|
139
|
+
continue;
|
|
140
|
+
try {
|
|
141
|
+
multiaddr(entry);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// Deliberately not echoing the raw value at error level: it arrived from a remote
|
|
145
|
+
// peer. The log line below is the observability for a responder announcing junk.
|
|
146
|
+
log('strandAddrs: skipping unparsable entry: %o', error);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
seen.add(entry);
|
|
150
|
+
out.push(entry);
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
104
154
|
// ── Stream framing helpers ───────────────────────────────────────────────────
|
|
105
155
|
/**
|
|
106
156
|
* Reads length-prefixed JSON frames from a libp2p stream one frame at a time.
|
|
@@ -398,6 +448,24 @@ export class FormationListener {
|
|
|
398
448
|
}
|
|
399
449
|
return true;
|
|
400
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* The strand addresses to disclose for an APPROVED provisioning, sanitized and capped.
|
|
453
|
+
*
|
|
454
|
+
* Never throws: a hook that fails (a strand runtime torn down mid-session) costs the
|
|
455
|
+
* joiner its cross-party seed, not the formation it has already earned — the seed is
|
|
456
|
+
* an optimization, the consent row is the commitment.
|
|
457
|
+
*/
|
|
458
|
+
strandAddrsFor(id, strandId) {
|
|
459
|
+
if (!this.options.resolveStrandAddrs)
|
|
460
|
+
return [];
|
|
461
|
+
try {
|
|
462
|
+
return sanitizeStrandAddrs(this.options.resolveStrandAddrs(strandId));
|
|
463
|
+
}
|
|
464
|
+
catch (err) {
|
|
465
|
+
log('formation session #%d: strand-addr lookup for %s failed (continuing): %o', id, strandId, err);
|
|
466
|
+
return [];
|
|
467
|
+
}
|
|
468
|
+
}
|
|
401
469
|
async runSession(id, stream) {
|
|
402
470
|
// Track whether ANY frame has been written so the catch below can convert an
|
|
403
471
|
// unexpected internal error into a non-disclosing rejection ONLY when nothing has
|
|
@@ -440,10 +508,15 @@ export class FormationListener {
|
|
|
440
508
|
}
|
|
441
509
|
// Validation + provisioning passed → safe to disclose responder identity/cadre.
|
|
442
510
|
const identity = this.options.getResponderIdentity();
|
|
511
|
+
const strandAddrs = this.strandAddrsFor(id, outcome.result.strand.strandId);
|
|
443
512
|
send({
|
|
444
513
|
approved: true,
|
|
445
514
|
partyId: identity.partyId,
|
|
446
515
|
cadrePeerAddrs: identity.cadrePeerAddrs,
|
|
516
|
+
// Omitted rather than sent empty: an absent field and an empty list mean the same
|
|
517
|
+
// thing to the initiator, and omitting keeps every rejection-parity assertion a
|
|
518
|
+
// plain `toBeUndefined()`.
|
|
519
|
+
...(strandAddrs.length > 0 ? { strandAddrs } : {}),
|
|
447
520
|
provisionResult: outcome.result
|
|
448
521
|
});
|
|
449
522
|
}
|
|
@@ -468,7 +541,8 @@ export class FormationListener {
|
|
|
468
541
|
/**
|
|
469
542
|
* Initiator side of the native formation protocol. Dials the responder, sends the
|
|
470
543
|
* contact (carrying the real disclosure/token/cadre), validates the responder's
|
|
471
|
-
* result, and returns the strand the responder provisioned
|
|
544
|
+
* result, and returns the strand the responder provisioned plus the responder's
|
|
545
|
+
* strand-network addresses (see {@link FormationDialResult}).
|
|
472
546
|
*/
|
|
473
547
|
export async function dialFormation(node, options) {
|
|
474
548
|
if (options.responderAddrs.length === 0) {
|
|
@@ -494,7 +568,9 @@ export async function dialFormation(node, options) {
|
|
|
494
568
|
throw new Error('Responder result failed validation');
|
|
495
569
|
if (!response.provisionResult)
|
|
496
570
|
throw new Error('Missing provision result for responderCreates mode');
|
|
497
|
-
|
|
571
|
+
// Sanitized HERE — the wire boundary — so nothing above this call ever handles an
|
|
572
|
+
// unvalidated, unbounded address list from a remote peer.
|
|
573
|
+
return { provision: response.provisionResult, strandAddrs: sanitizeStrandAddrs(response.strandAddrs) };
|
|
498
574
|
}
|
|
499
575
|
finally {
|
|
500
576
|
try {
|