@serfab/cadre-core 1.13.0 → 1.15.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 +293 -274
- package/dist/cadre-invite-protocol.d.ts +383 -0
- package/dist/cadre-invite-protocol.js +774 -0
- package/dist/cadre-invite-protocol.js.map +1 -0
- package/dist/cadre-join-request.d.ts +42 -0
- package/dist/cadre-join-request.js +144 -0
- package/dist/cadre-join-request.js.map +1 -0
- package/dist/cadre-node.d.ts +849 -210
- package/dist/cadre-node.js +1574 -374
- package/dist/cadre-node.js.map +1 -1
- package/dist/claim-proof.d.ts +45 -0
- package/dist/claim-proof.js +132 -0
- package/dist/claim-proof.js.map +1 -0
- package/dist/control-authorization.d.ts +80 -19
- package/dist/control-authorization.js +55 -13
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.js +1 -1
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +605 -108
- package/dist/control-database.js +1299 -280
- package/dist/control-database.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +142 -0
- package/dist/control-protocol-guard.js +293 -0
- package/dist/control-protocol-guard.js.map +1 -0
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +817 -1067
- package/dist/control-schema.js.map +1 -1
- package/dist/control-stream.d.ts +4 -0
- package/dist/control-stream.js +22 -7
- package/dist/control-stream.js.map +1 -1
- package/dist/delegate-admission.d.ts +1 -1
- package/dist/delegate-admission.js +1 -1
- package/dist/device-token.d.ts +11 -9
- package/dist/device-token.js +14 -12
- package/dist/device-token.js.map +1 -1
- package/dist/ed25519-key.d.ts +22 -9
- package/dist/ed25519-key.js +47 -10
- package/dist/ed25519-key.js.map +1 -1
- package/dist/fetch-impl.d.ts +12 -0
- package/dist/fetch-impl.js +23 -0
- package/dist/fetch-impl.js.map +1 -0
- package/dist/file-durable-slot.js +2 -1
- package/dist/file-durable-slot.js.map +1 -1
- package/dist/file-safe-name.d.ts +25 -0
- package/dist/file-safe-name.js +29 -0
- package/dist/file-safe-name.js.map +1 -0
- package/dist/formation-approval.js +5 -11
- package/dist/formation-approval.js.map +1 -1
- package/dist/fs-atomic.d.ts +0 -19
- package/dist/fs-atomic.js +3 -24
- package/dist/fs-atomic.js.map +1 -1
- package/dist/index.d.ts +22 -10
- package/dist/index.js +54 -11
- package/dist/index.js.map +1 -1
- package/dist/invitation-bootstrap.d.ts +50 -12
- package/dist/invitation-bootstrap.js +76 -13
- package/dist/invitation-bootstrap.js.map +1 -1
- package/dist/joined-strand-store.d.ts +7 -0
- package/dist/joined-strand-store.js +9 -0
- package/dist/joined-strand-store.js.map +1 -1
- package/dist/key-store-file.js +2 -1
- package/dist/key-store-file.js.map +1 -1
- package/dist/link-budget.d.ts +25 -33
- package/dist/link-budget.js +25 -35
- package/dist/link-budget.js.map +1 -1
- package/dist/machine-removal.d.ts +78 -0
- package/dist/machine-removal.js +166 -0
- package/dist/machine-removal.js.map +1 -0
- package/dist/membership-connection-gater.d.ts +191 -151
- package/dist/membership-connection-gater.js +236 -173
- package/dist/membership-connection-gater.js.map +1 -1
- package/dist/node-claim-payload.d.ts +74 -0
- package/dist/node-claim-payload.js +224 -0
- package/dist/node-claim-payload.js.map +1 -0
- package/dist/node-default-transports.d.ts +27 -0
- package/dist/node-default-transports.js +35 -0
- package/dist/node-default-transports.js.map +1 -0
- package/dist/node-transports.d.ts +30 -0
- package/dist/node-transports.js +40 -0
- package/dist/node-transports.js.map +1 -0
- package/dist/owner-anchor-sync.d.ts +22 -0
- package/dist/owner-anchor-sync.js +143 -0
- package/dist/owner-anchor-sync.js.map +1 -0
- package/dist/peer-authorization.d.ts +113 -18
- package/dist/peer-authorization.js +225 -29
- package/dist/peer-authorization.js.map +1 -1
- package/dist/peer-dial.d.ts +143 -27
- package/dist/peer-dial.js +276 -31
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +26 -2
- package/dist/peer-join-backfill.js +60 -12
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/peer-record.d.ts +17 -52
- package/dist/peer-record.js +20 -58
- package/dist/peer-record.js.map +1 -1
- package/dist/pending-join-runner.d.ts +66 -58
- package/dist/pending-join-runner.js +136 -145
- package/dist/pending-join-runner.js.map +1 -1
- package/dist/primary-lan-address.d.ts +8 -0
- package/dist/primary-lan-address.js +46 -0
- package/dist/primary-lan-address.js.map +1 -0
- package/dist/provider/client.d.ts +131 -0
- package/dist/provider/client.js +226 -0
- package/dist/provider/client.js.map +1 -0
- package/dist/provider/descriptor.d.ts +41 -0
- package/dist/provider/descriptor.js +103 -0
- package/dist/provider/descriptor.js.map +1 -0
- package/dist/provider/index.d.ts +9 -0
- package/dist/provider/index.js +10 -0
- package/dist/provider/index.js.map +1 -0
- package/dist/provider/oauth.d.ts +125 -0
- package/dist/provider/oauth.js +199 -0
- package/dist/provider/oauth.js.map +1 -0
- package/dist/provider/rent-node.d.ts +101 -0
- package/dist/provider/rent-node.js +220 -0
- package/dist/provider/rent-node.js.map +1 -0
- package/dist/push-fanout.d.ts +8 -2
- package/dist/push-fanout.js +8 -2
- package/dist/push-fanout.js.map +1 -1
- package/dist/relay-addrs.d.ts +9 -4
- package/dist/relay-addrs.js +9 -4
- package/dist/relay-addrs.js.map +1 -1
- package/dist/relay-reservation.d.ts +51 -16
- package/dist/relay-reservation.js +107 -24
- package/dist/relay-reservation.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +165 -123
- package/dist/seed-bootstrap.js +313 -275
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.d.ts +98 -37
- package/dist/seed-trust-policy.js +188 -2
- package/dist/seed-trust-policy.js.map +1 -1
- package/dist/strand-addr-protocol.d.ts +24 -26
- package/dist/strand-addr-protocol.js +19 -26
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-commit-durability.d.ts +54 -0
- package/dist/strand-commit-durability.js +74 -0
- package/dist/strand-commit-durability.js.map +1 -0
- package/dist/strand-database.d.ts +23 -8
- package/dist/strand-database.js +41 -13
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +7 -1
- package/dist/strand-first-sync-gate.js +7 -1
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-formation-protocol.js +5 -2
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-fret-addrs.d.ts +19 -1
- package/dist/strand-fret-addrs.js +27 -9
- package/dist/strand-fret-addrs.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +81 -19
- package/dist/strand-instance-manager.js +216 -105
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-move.d.ts +124 -0
- package/dist/strand-move.js +438 -0
- package/dist/strand-move.js.map +1 -0
- package/dist/strand-network-config.js +7 -6
- package/dist/strand-network-config.js.map +1 -1
- package/dist/strand-peer-redial.d.ts +113 -0
- package/dist/strand-peer-redial.js +236 -0
- package/dist/strand-peer-redial.js.map +1 -0
- package/dist/strand-revocation-enforcer.d.ts +11 -11
- package/dist/strand-revocation-enforcer.js +11 -11
- package/dist/strand-wake-protocol.d.ts +13 -16
- package/dist/strand-wake-protocol.js +23 -27
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/trusted-owner-store.d.ts +35 -5
- package/dist/trusted-owner-store.js +50 -8
- package/dist/trusted-owner-store.js.map +1 -1
- package/dist/types.d.ts +512 -89
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/package.json +19 -10
- package/src/cadre-invite-protocol.ts +1052 -0
- package/src/cadre-join-request.ts +167 -0
- package/src/cadre-node.ts +1703 -386
- package/src/claim-proof.ts +147 -0
- package/src/control-authorization.ts +203 -117
- package/src/control-cohort.ts +1 -1
- package/src/control-database.ts +4663 -3453
- package/src/control-protocol-guard.ts +348 -0
- package/src/control-schema.ts +828 -1078
- package/src/control-stream.ts +26 -7
- package/src/delegate-admission.ts +1 -1
- package/src/device-token.ts +14 -10
- package/src/ed25519-key.ts +47 -10
- package/src/fetch-impl.ts +23 -0
- package/src/file-durable-slot.ts +64 -63
- package/src/file-safe-name.ts +32 -0
- package/src/formation-approval.ts +604 -610
- package/src/fs-atomic.ts +92 -117
- package/src/index.ts +789 -648
- package/src/invitation-bootstrap.ts +91 -13
- package/src/joined-strand-store.ts +508 -498
- package/src/key-store-file.ts +142 -141
- package/src/link-budget.ts +25 -36
- package/src/machine-removal.ts +216 -0
- package/src/membership-connection-gater.ts +259 -191
- package/src/node-claim-payload.ts +259 -0
- package/src/node-default-transports.ts +38 -0
- package/src/node-transports.ts +49 -0
- package/src/owner-anchor-sync.ts +171 -0
- package/src/peer-authorization.ts +258 -29
- package/src/peer-dial.ts +604 -315
- package/src/peer-join-backfill.ts +62 -11
- package/src/peer-record.ts +159 -197
- package/src/pending-join-runner.ts +729 -735
- package/src/primary-lan-address.ts +47 -0
- package/src/provider/client.ts +326 -0
- package/src/provider/descriptor.ts +129 -0
- package/src/provider/index.ts +59 -0
- package/src/provider/oauth.ts +285 -0
- package/src/provider/rent-node.ts +275 -0
- package/src/push-fanout.ts +8 -2
- package/src/relay-addrs.ts +9 -4
- package/src/relay-reservation.ts +1211 -1121
- package/src/seed-bootstrap.ts +1502 -1448
- package/src/seed-trust-policy.ts +353 -140
- package/src/strand-addr-protocol.ts +26 -35
- package/src/strand-commit-durability.ts +116 -0
- package/src/strand-database.ts +46 -14
- package/src/strand-first-sync-gate.ts +7 -1
- package/src/strand-formation-protocol.ts +1039 -1036
- package/src/strand-fret-addrs.ts +179 -145
- package/src/strand-instance-manager.ts +2026 -1883
- package/src/strand-move.ts +585 -0
- package/src/strand-network-config.ts +7 -6
- package/src/strand-peer-redial.ts +307 -0
- package/src/strand-revocation-enforcer.ts +11 -11
- package/src/strand-wake-protocol.ts +23 -30
- package/src/trusted-owner-store.ts +242 -171
- package/src/types.ts +2687 -2242
package/dist/peer-dial.d.ts
CHANGED
|
@@ -16,17 +16,60 @@
|
|
|
16
16
|
* borrowing a node from a cadre-host whose only reachable address was the
|
|
17
17
|
* forwarded loopback one never connected for this reason.
|
|
18
18
|
*
|
|
19
|
-
* So the addresses are dialed here, each as its own
|
|
20
|
-
*
|
|
21
|
-
* ({@link PeerDialBudget.totalMs}). One address
|
|
22
|
-
* sorter has nothing to reorder, so the order is
|
|
23
|
-
* ({@link directBeforeRelayed}).
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
19
|
+
* So the addresses are dialed here, each as its own transport-manager dial
|
|
20
|
+
* ({@link dialAddr}) with its own time limit ({@link PeerDialBudget.perAddressMs}),
|
|
21
|
+
* inside a limit for the whole peer ({@link PeerDialBudget.totalMs}). One address
|
|
22
|
+
* per call also means libp2p's sorter has nothing to reorder, so the order is
|
|
23
|
+
* chosen here ({@link directBeforeRelayed}). The dial goes around libp2p's dial
|
|
24
|
+
* queue because the queue joins any dial of a peer to a queued job for that peer
|
|
25
|
+
* id, whatever address the new dial names — see {@link dialAddr}. Every address
|
|
26
|
+
* is bound to the peer the caller expects ({@link withTrailingPeerId}) so the
|
|
27
|
+
* handshake verifies who answered.
|
|
28
|
+
*
|
|
29
|
+
* Dependency-free apart from `control-stream.ts` and `link-budget.ts`, so any
|
|
30
|
+
* module may import it without creating an import cycle. That is why the two
|
|
31
|
+
* address helpers ({@link trailingPeerId}, {@link withTrailingPeerId}) live here
|
|
32
|
+
* rather than in `peer-record.ts`, which pulls in the crypto plugin.
|
|
27
33
|
*/
|
|
28
|
-
import type { Connection, PeerId } from '@libp2p/interface';
|
|
34
|
+
import type { Connection, Libp2pStatus, PeerId } from '@libp2p/interface';
|
|
29
35
|
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
36
|
+
/**
|
|
37
|
+
* The peer id a multiaddr terminates in, or `null` when it names none.
|
|
38
|
+
*
|
|
39
|
+
* The LAST `/p2p/` component is the dial target: a circuit address
|
|
40
|
+
* (`…/p2p/<relay>/p2p-circuit/p2p/<target>`) names the relay first and the peer
|
|
41
|
+
* being reached last. Replaces the deprecated `Multiaddr.getPeerId()`, which
|
|
42
|
+
* cannot express that distinction.
|
|
43
|
+
*/
|
|
44
|
+
export declare function trailingPeerId(addr: Multiaddr): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* `addr` guaranteed to terminate in `/p2p/<peerId>` — the shape every dial needs,
|
|
47
|
+
* since the upgrader verifies that id during the handshake — or `null` when it
|
|
48
|
+
* cannot, because the address already terminates in a DIFFERENT peer id and
|
|
49
|
+
* therefore does not reach `peerId` at all.
|
|
50
|
+
*
|
|
51
|
+
* Three input shapes, matching what a `CadrePeer` record can legitimately carry:
|
|
52
|
+
*
|
|
53
|
+
* - no `/p2p/` component (`/ip4/1.2.3.4/tcp/4001`) — the suffix is appended;
|
|
54
|
+
* - a relay hop with the destination missing (`…/p2p/<relay>/p2p-circuit`) — the
|
|
55
|
+
* last component is the circuit, not a peer id, so the suffix is appended and
|
|
56
|
+
* the address becomes the full `…/p2p/<relay>/p2p-circuit/p2p/<peerId>`;
|
|
57
|
+
* - already terminating in `/p2p/<X>` — returned untouched when `X` is `peerId`,
|
|
58
|
+
* dropped otherwise.
|
|
59
|
+
*
|
|
60
|
+
* This is deliberately the same rule libp2p applies internally in
|
|
61
|
+
* `calculateMultiaddrs` (append when the LAST component is not `p2p`) followed by
|
|
62
|
+
* its wrong-peer-id filter, so a normalized list matches what libp2p would have
|
|
63
|
+
* built anyway. Normalizing before a list dial is what keeps a list from mixing
|
|
64
|
+
* suffixed and unsuffixed entries, which `getPeerAddress` rejects outright
|
|
65
|
+
* ("Multiaddrs must all have the same peer id or have no peer id") — taking the
|
|
66
|
+
* whole peer down with it, not just the odd address.
|
|
67
|
+
*
|
|
68
|
+
* Throws when `peerId` does not parse as a peer id (the encapsulation validates
|
|
69
|
+
* it). Never use before signature verification: verification runs against the
|
|
70
|
+
* original on-record strings.
|
|
71
|
+
*/
|
|
72
|
+
export declare function withTrailingPeerId(addr: Multiaddr, peerId: string): Multiaddr | null;
|
|
30
73
|
/**
|
|
31
74
|
* Default limit on ONE address's dial attempt, in ms, at the DEFAULT declared link round trip:
|
|
32
75
|
* `RELAYED_DIAL_ROUND_TRIPS` (5) x `DECLARED_LINK_ROUND_TRIP_MS` (3500 ms) plus
|
|
@@ -103,14 +146,60 @@ export interface PeerDialBudget {
|
|
|
103
146
|
}
|
|
104
147
|
/** {@link PeerDialBudget} built from the two defaults above. */
|
|
105
148
|
export declare const DEFAULT_PEER_DIAL_BUDGET: Readonly<PeerDialBudget>;
|
|
149
|
+
/** What {@link dialAddr} reads of a connection the node holds, to decide whether to hand it back instead of dialing. */
|
|
150
|
+
export interface ReusableConnection {
|
|
151
|
+
remotePeer: {
|
|
152
|
+
toString(): string;
|
|
153
|
+
};
|
|
154
|
+
status?: Connection['status'];
|
|
155
|
+
limits?: Connection['limits'];
|
|
156
|
+
/** Whether the connection is direct rather than relayed; absent counts as direct. */
|
|
157
|
+
direct?: boolean;
|
|
158
|
+
}
|
|
106
159
|
/** The slice of a libp2p node {@link dialPeerAddrs} uses. */
|
|
107
160
|
export interface AddrDialer {
|
|
108
161
|
/** This node's id, to recognise an address that relays through this node ({@link relaysThrough}). */
|
|
109
162
|
readonly peerId: PeerId;
|
|
163
|
+
/** libp2p's lifecycle state: {@link dialAddr} refuses to start an attempt once it is not `started`. */
|
|
164
|
+
readonly status?: Libp2pStatus;
|
|
165
|
+
/**
|
|
166
|
+
* The connections this node holds to `peerId`. {@link dialAddr} returns an open one without relay
|
|
167
|
+
* limits rather than opening a second — what libp2p's dial queue did (`findExistingConnection`)
|
|
168
|
+
* and the transport manager does not. Optional so a double need not provide it, and typed by
|
|
169
|
+
* what is read of each connection so the strand redial's node slice (bare `remotePeer`s, which
|
|
170
|
+
* never count as open) satisfies it without a cast.
|
|
171
|
+
*/
|
|
172
|
+
getConnections?(peerId?: PeerId): ReadonlyArray<ReusableConnection>;
|
|
110
173
|
dial(addr: Multiaddr, options: {
|
|
111
174
|
signal: AbortSignal;
|
|
112
175
|
}): Promise<Connection>;
|
|
113
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Dial ONE address outside libp2p's dial queue. The queue joins any new dial to a queued job
|
|
179
|
+
* for the same peer id, whatever address the new dial names, and a joined job ends only when
|
|
180
|
+
* every caller has aborted — so while another caller dials this peer (FRET's membership probe,
|
|
181
|
+
* an Optimystic cluster client), a per-address attempt through the queue waits on whatever
|
|
182
|
+
* address that job is on instead of its own. The transport manager dials exactly the address
|
|
183
|
+
* given; the two gater hooks the queue would have consulted are run here, and the upgrader
|
|
184
|
+
* still runs `denyOutboundConnection` and verifies the peer id the address carries during the
|
|
185
|
+
* Noise handshake, so the address must carry the id of the peer expected to answer
|
|
186
|
+
* ({@link withTrailingPeerId}). An open connection to that peer without relay limits is handed
|
|
187
|
+
* back instead of dialing ({@link reusableConnection}), as the queue would have. A relayed
|
|
188
|
+
* address still passes through the queue for its relay leg (the circuit transport dials the
|
|
189
|
+
* relay by peer id).
|
|
190
|
+
*
|
|
191
|
+
* The queue would also have aborted the attempt at shutdown; here the node's `status` is
|
|
192
|
+
* checked before dialing and its `stop` event aborts an attempt in flight. Without
|
|
193
|
+
* `transportManager.dial` (libp2p internals moved) the attempt goes through the queue, logged.
|
|
194
|
+
*
|
|
195
|
+
* What else the queue did that this does not: record the outcome in the peer store
|
|
196
|
+
* (`LAST_DIAL_SUCCESS_KEY` / `LAST_DIAL_FAILURE_KEY`, read only by libp2p's own address sorter,
|
|
197
|
+
* which these dials do not use); apply `maxParallelDials` and `maxDialQueueLength`; and refuse
|
|
198
|
+
* a dial of this node's own id before touching the network — the upgrader still throws
|
|
199
|
+
* `Can not dial self` after the handshake, `dialPeerAddrs` drops addresses relaying through this
|
|
200
|
+
* node, `applySeed` skips itself, and the reconcile pass never lists itself.
|
|
201
|
+
*/
|
|
202
|
+
export declare function dialAddr(dialer: AddrDialer, addr: Multiaddr, signal: AbortSignal, label: string): Promise<Connection>;
|
|
114
203
|
/**
|
|
115
204
|
* Thrown by {@link dialPeerAddrs} when it was given addresses but every one reaches the peer by
|
|
116
205
|
* relaying through this node, so none was dialed.
|
|
@@ -125,25 +214,46 @@ export declare class SelfRelayOnlyError extends Error {
|
|
|
125
214
|
constructor(label: string);
|
|
126
215
|
}
|
|
127
216
|
/**
|
|
128
|
-
*
|
|
217
|
+
* No connection to the peer formed, so nothing was sent to it. `cause` is what the dial threw:
|
|
218
|
+
* {@link dialPeerAddrs}'s error naming every address and why it failed, or a
|
|
219
|
+
* {@link SelfRelayOnlyError}.
|
|
220
|
+
*
|
|
221
|
+
* Kept apart from failures after a connection formed so a caller can tell "this device could not
|
|
222
|
+
* reach the peer" from "the peer was reached and then something else failed" without reading
|
|
223
|
+
* libp2p's error text. `SeedBootstrapService.deliverSeed` throws it, and so `CadreNode.claimNode`.
|
|
224
|
+
*/
|
|
225
|
+
export declare class PeerUnreachableError extends Error {
|
|
226
|
+
readonly peerId: string;
|
|
227
|
+
constructor(peerId: string, cause: unknown);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Dial `peerId` from `addrs`, one address per {@link dialAddr} call, and return the
|
|
129
231
|
* first connection that forms. Direct addresses are tried before relayed ones
|
|
130
232
|
* ({@link directBeforeRelayed}); otherwise the given order is kept.
|
|
131
233
|
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
234
|
+
* Every address is first bound to `peerId` ({@link withTrailingPeerId}), so the
|
|
235
|
+
* handshake verifies that the peer expected is the one that answered; an address
|
|
236
|
+
* naming another peer is dropped and logged. When that leaves nothing of a
|
|
237
|
+
* non-empty list — every address names someone else, or `peerId` does not parse —
|
|
238
|
+
* this throws without dialing.
|
|
239
|
+
*
|
|
240
|
+
* Addresses that relay through this node are dropped next ({@link relaysThrough}):
|
|
241
|
+
* dialing one could only fail with `Can not dial self`. When that leaves nothing,
|
|
242
|
+
* this throws {@link SelfRelayOnlyError} without dialing.
|
|
135
243
|
*
|
|
136
|
-
* Addresses naming a transport this node lacks are not filtered out first:
|
|
137
|
-
*
|
|
244
|
+
* Addresses naming a transport this node lacks are not filtered out first: the
|
|
245
|
+
* transport manager rejects those at once (`TransportUnavailableError`), so they
|
|
138
246
|
* cost a log line, not time.
|
|
139
247
|
*
|
|
140
248
|
* Otherwise throws when no address connects — see {@link tryAddrsInTurn} for the error.
|
|
141
249
|
*
|
|
250
|
+
* @param peerId The peer every address must reach, as every caller already holds it
|
|
251
|
+
* (a `CadrePeer` row key, a seed peer's id, a strand member's id).
|
|
142
252
|
* @param label Names the dial in timeout messages and logs, e.g.
|
|
143
253
|
* `reconcileControlCohort dial of sibling <peerId>`; each attempt reads
|
|
144
254
|
* `<label> via <addr>`.
|
|
145
255
|
*/
|
|
146
|
-
export declare function dialPeerAddrs(dialer: AddrDialer, addrs: readonly Multiaddr[], budget: PeerDialBudget, label: string): Promise<Connection>;
|
|
256
|
+
export declare function dialPeerAddrs(dialer: AddrDialer, peerId: string, addrs: readonly Multiaddr[], budget: PeerDialBudget, label: string): Promise<Connection>;
|
|
147
257
|
/**
|
|
148
258
|
* Run `attempt` against each address in the given order until one succeeds, and
|
|
149
259
|
* return its result.
|
|
@@ -158,17 +268,17 @@ export declare function dialPeerAddrs(dialer: AddrDialer, addrs: readonly Multia
|
|
|
158
268
|
* failed, in order, with the first failure as `cause` — so the report shows the
|
|
159
269
|
* address that mattered, not only whichever happened to be tried last.
|
|
160
270
|
*
|
|
161
|
-
* Between attempts this waits for one macrotask (`setTimeout(0)`).
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* queue's
|
|
171
|
-
*
|
|
271
|
+
* Between attempts this waits for one macrotask (`setTimeout(0)`). A direct
|
|
272
|
+
* address is dialed outside libp2p's dial queue ({@link dialAddr}), but a relayed
|
|
273
|
+
* address still passes through it for the relay leg, and the queue lets a new
|
|
274
|
+
* dial join any queued job for the same peer id WITHOUT checking whether that
|
|
275
|
+
* job has already finished: an aborted job leaves the queue a few microtasks
|
|
276
|
+
* after its callers are rejected, so a next attempt through the same relay made
|
|
277
|
+
* at once would join the dying job and be rejected with `AbortError` before it
|
|
278
|
+
* touches the network. All of the queue's cleanup runs as microtasks, so it has
|
|
279
|
+
* finished by the time a macrotask runs. Seen against libp2p 3.1.3, and the
|
|
280
|
+
* queue's join is unchanged in 3.3.11; `test/peer-dial.spec.ts` dials real nodes
|
|
281
|
+
* so an upgrade that changes it shows up there.
|
|
172
282
|
*/
|
|
173
283
|
export declare function tryAddrsInTurn<T>(addrs: readonly Multiaddr[], budget: PeerDialBudget, label: string, attempt: (addr: Multiaddr, signal: AbortSignal, attemptMs: number) => Promise<T>): Promise<T>;
|
|
174
284
|
/**
|
|
@@ -184,3 +294,9 @@ export declare function tryAddrsInTurn<T>(addrs: readonly Multiaddr[], budget: P
|
|
|
184
294
|
* bounded amount of time, so the caller's order is the better guide.
|
|
185
295
|
*/
|
|
186
296
|
export declare function directBeforeRelayed(addrs: readonly Multiaddr[]): Multiaddr[];
|
|
297
|
+
/**
|
|
298
|
+
* Yield one macrotask: libp2p's dial queue drops an aborted job only on the next turn, so a
|
|
299
|
+
* dialer that moves on to another address after an abort waits this long first. Shared with
|
|
300
|
+
* the cadre invitation dialer (`cadre-invite-protocol.ts`).
|
|
301
|
+
*/
|
|
302
|
+
export declare function nextMacrotask(): Promise<void>;
|
package/dist/peer-dial.js
CHANGED
|
@@ -16,20 +16,72 @@
|
|
|
16
16
|
* borrowing a node from a cadre-host whose only reachable address was the
|
|
17
17
|
* forwarded loopback one never connected for this reason.
|
|
18
18
|
*
|
|
19
|
-
* So the addresses are dialed here, each as its own
|
|
20
|
-
*
|
|
21
|
-
* ({@link PeerDialBudget.totalMs}). One address
|
|
22
|
-
* sorter has nothing to reorder, so the order is
|
|
23
|
-
* ({@link directBeforeRelayed}).
|
|
19
|
+
* So the addresses are dialed here, each as its own transport-manager dial
|
|
20
|
+
* ({@link dialAddr}) with its own time limit ({@link PeerDialBudget.perAddressMs}),
|
|
21
|
+
* inside a limit for the whole peer ({@link PeerDialBudget.totalMs}). One address
|
|
22
|
+
* per call also means libp2p's sorter has nothing to reorder, so the order is
|
|
23
|
+
* chosen here ({@link directBeforeRelayed}). The dial goes around libp2p's dial
|
|
24
|
+
* queue because the queue joins any dial of a peer to a queued job for that peer
|
|
25
|
+
* id, whatever address the new dial names — see {@link dialAddr}. Every address
|
|
26
|
+
* is bound to the peer the caller expects ({@link withTrailingPeerId}) so the
|
|
27
|
+
* handshake verifies who answered.
|
|
24
28
|
*
|
|
25
|
-
* Dependency-free apart from `control-stream.ts`, so any
|
|
26
|
-
* without creating an import cycle.
|
|
29
|
+
* Dependency-free apart from `control-stream.ts` and `link-budget.ts`, so any
|
|
30
|
+
* module may import it without creating an import cycle. That is why the two
|
|
31
|
+
* address helpers ({@link trailingPeerId}, {@link withTrailingPeerId}) live here
|
|
32
|
+
* rather than in `peer-record.ts`, which pulls in the crypto plugin.
|
|
27
33
|
*/
|
|
28
34
|
import debug from 'debug';
|
|
29
35
|
import { peerIdFromString } from '@libp2p/peer-id';
|
|
30
36
|
import { withDeadline } from './control-stream.js';
|
|
31
37
|
import { relayedDialBudgetMs } from './link-budget.js';
|
|
32
38
|
const log = debug('sereus:cadre:peer-dial');
|
|
39
|
+
/**
|
|
40
|
+
* The peer id a multiaddr terminates in, or `null` when it names none.
|
|
41
|
+
*
|
|
42
|
+
* The LAST `/p2p/` component is the dial target: a circuit address
|
|
43
|
+
* (`…/p2p/<relay>/p2p-circuit/p2p/<target>`) names the relay first and the peer
|
|
44
|
+
* being reached last. Replaces the deprecated `Multiaddr.getPeerId()`, which
|
|
45
|
+
* cannot express that distinction.
|
|
46
|
+
*/
|
|
47
|
+
export function trailingPeerId(addr) {
|
|
48
|
+
const p2p = addr.getComponents().filter((c) => c.name === 'p2p');
|
|
49
|
+
return p2p.length > 0 ? (p2p[p2p.length - 1].value ?? null) : null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* `addr` guaranteed to terminate in `/p2p/<peerId>` — the shape every dial needs,
|
|
53
|
+
* since the upgrader verifies that id during the handshake — or `null` when it
|
|
54
|
+
* cannot, because the address already terminates in a DIFFERENT peer id and
|
|
55
|
+
* therefore does not reach `peerId` at all.
|
|
56
|
+
*
|
|
57
|
+
* Three input shapes, matching what a `CadrePeer` record can legitimately carry:
|
|
58
|
+
*
|
|
59
|
+
* - no `/p2p/` component (`/ip4/1.2.3.4/tcp/4001`) — the suffix is appended;
|
|
60
|
+
* - a relay hop with the destination missing (`…/p2p/<relay>/p2p-circuit`) — the
|
|
61
|
+
* last component is the circuit, not a peer id, so the suffix is appended and
|
|
62
|
+
* the address becomes the full `…/p2p/<relay>/p2p-circuit/p2p/<peerId>`;
|
|
63
|
+
* - already terminating in `/p2p/<X>` — returned untouched when `X` is `peerId`,
|
|
64
|
+
* dropped otherwise.
|
|
65
|
+
*
|
|
66
|
+
* This is deliberately the same rule libp2p applies internally in
|
|
67
|
+
* `calculateMultiaddrs` (append when the LAST component is not `p2p`) followed by
|
|
68
|
+
* its wrong-peer-id filter, so a normalized list matches what libp2p would have
|
|
69
|
+
* built anyway. Normalizing before a list dial is what keeps a list from mixing
|
|
70
|
+
* suffixed and unsuffixed entries, which `getPeerAddress` rejects outright
|
|
71
|
+
* ("Multiaddrs must all have the same peer id or have no peer id") — taking the
|
|
72
|
+
* whole peer down with it, not just the odd address.
|
|
73
|
+
*
|
|
74
|
+
* Throws when `peerId` does not parse as a peer id (the encapsulation validates
|
|
75
|
+
* it). Never use before signature verification: verification runs against the
|
|
76
|
+
* original on-record strings.
|
|
77
|
+
*/
|
|
78
|
+
export function withTrailingPeerId(addr, peerId) {
|
|
79
|
+
const components = addr.getComponents();
|
|
80
|
+
if (components[components.length - 1]?.name !== 'p2p') {
|
|
81
|
+
return addr.encapsulate(`/p2p/${peerId}`);
|
|
82
|
+
}
|
|
83
|
+
return trailingPeerId(addr) === peerId ? addr : null;
|
|
84
|
+
}
|
|
33
85
|
/**
|
|
34
86
|
* Default limit on ONE address's dial attempt, in ms, at the DEFAULT declared link round trip:
|
|
35
87
|
* `RELAYED_DIAL_ROUND_TRIPS` (5) x `DECLARED_LINK_ROUND_TRIP_MS` (3500 ms) plus
|
|
@@ -102,6 +154,140 @@ export const DEFAULT_PEER_DIAL_BUDGET = {
|
|
|
102
154
|
perAddressMs: DEFAULT_CONTROL_COHORT_PER_ADDRESS_DIAL_TIMEOUT_MS,
|
|
103
155
|
totalMs: DEFAULT_CONTROL_COHORT_DIAL_TIMEOUT_MS,
|
|
104
156
|
};
|
|
157
|
+
/**
|
|
158
|
+
* Dial ONE address outside libp2p's dial queue. The queue joins any new dial to a queued job
|
|
159
|
+
* for the same peer id, whatever address the new dial names, and a joined job ends only when
|
|
160
|
+
* every caller has aborted — so while another caller dials this peer (FRET's membership probe,
|
|
161
|
+
* an Optimystic cluster client), a per-address attempt through the queue waits on whatever
|
|
162
|
+
* address that job is on instead of its own. The transport manager dials exactly the address
|
|
163
|
+
* given; the two gater hooks the queue would have consulted are run here, and the upgrader
|
|
164
|
+
* still runs `denyOutboundConnection` and verifies the peer id the address carries during the
|
|
165
|
+
* Noise handshake, so the address must carry the id of the peer expected to answer
|
|
166
|
+
* ({@link withTrailingPeerId}). An open connection to that peer without relay limits is handed
|
|
167
|
+
* back instead of dialing ({@link reusableConnection}), as the queue would have. A relayed
|
|
168
|
+
* address still passes through the queue for its relay leg (the circuit transport dials the
|
|
169
|
+
* relay by peer id).
|
|
170
|
+
*
|
|
171
|
+
* The queue would also have aborted the attempt at shutdown; here the node's `status` is
|
|
172
|
+
* checked before dialing and its `stop` event aborts an attempt in flight. Without
|
|
173
|
+
* `transportManager.dial` (libp2p internals moved) the attempt goes through the queue, logged.
|
|
174
|
+
*
|
|
175
|
+
* What else the queue did that this does not: record the outcome in the peer store
|
|
176
|
+
* (`LAST_DIAL_SUCCESS_KEY` / `LAST_DIAL_FAILURE_KEY`, read only by libp2p's own address sorter,
|
|
177
|
+
* which these dials do not use); apply `maxParallelDials` and `maxDialQueueLength`; and refuse
|
|
178
|
+
* a dial of this node's own id before touching the network — the upgrader still throws
|
|
179
|
+
* `Can not dial self` after the handshake, `dialPeerAddrs` drops addresses relaying through this
|
|
180
|
+
* node, `applySeed` skips itself, and the reconcile pass never lists itself.
|
|
181
|
+
*/
|
|
182
|
+
export async function dialAddr(dialer, addr, signal, label) {
|
|
183
|
+
if (dialer.status !== undefined && dialer.status !== 'started') {
|
|
184
|
+
throw new Error(`${label}: not dialed, the node is ${dialer.status}`);
|
|
185
|
+
}
|
|
186
|
+
const components = dialer.components;
|
|
187
|
+
const manager = components?.transportManager;
|
|
188
|
+
if (typeof manager?.dial !== 'function') {
|
|
189
|
+
log('%s: no transportManager.dial on this node — libp2p internals moved? dialing through the queue', label);
|
|
190
|
+
return dialer.dial(addr, { signal });
|
|
191
|
+
}
|
|
192
|
+
const target = boundPeer(addr, label);
|
|
193
|
+
const open = reusableConnection(dialer, target, addr);
|
|
194
|
+
if (open !== undefined) {
|
|
195
|
+
log('%s: reusing the open connection to %s', label, target);
|
|
196
|
+
return open;
|
|
197
|
+
}
|
|
198
|
+
const attempt = attemptSignal(dialer, signal, label);
|
|
199
|
+
try {
|
|
200
|
+
await assertDialAllowed(components?.connectionGater, target, addr, label);
|
|
201
|
+
if (attempt.signal.aborted) {
|
|
202
|
+
throw attempt.signal.reason;
|
|
203
|
+
}
|
|
204
|
+
// NOTE: a relayed address's relay leg still goes through the dial queue (the circuit
|
|
205
|
+
// transport dials the relay by peer id), so another dial of the relay can join it. Fine
|
|
206
|
+
// while a relay connection is normally already open for the reservation; revisit if a
|
|
207
|
+
// relayed attempt is ever seen timing out while a dial of the relay by id is in flight.
|
|
208
|
+
return await manager.dial(addr, { signal: attempt.signal });
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
// A transport reports an aborted connect as its own failure ("Could not connect to …");
|
|
212
|
+
// why it was aborted — the deadline, or the stop — is the error worth surfacing.
|
|
213
|
+
throw attempt.signal.aborted ? attempt.signal.reason : err;
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
attempt.release();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* The signal one attempt dials under: aborted when the caller's `signal` aborts, with its
|
|
221
|
+
* reason, or when the node stops. Linked before anything in the attempt awaits (the gater
|
|
222
|
+
* hooks are async), so neither event can fall between the check and the dial; a `signal`
|
|
223
|
+
* already aborted on entry aborts it at once, since no `abort` event will come. `release`
|
|
224
|
+
* unhooks both listeners.
|
|
225
|
+
*/
|
|
226
|
+
function attemptSignal(dialer, signal, label) {
|
|
227
|
+
const events = dialer;
|
|
228
|
+
const controller = new AbortController();
|
|
229
|
+
const onAbort = () => controller.abort(signal.reason);
|
|
230
|
+
const onStop = () => controller.abort(new Error(`${label}: the node stopped`));
|
|
231
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
232
|
+
events.addEventListener?.('stop', onStop);
|
|
233
|
+
if (signal.aborted) {
|
|
234
|
+
onAbort();
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
signal: controller.signal,
|
|
238
|
+
release: () => {
|
|
239
|
+
signal.removeEventListener('abort', onAbort);
|
|
240
|
+
events.removeEventListener?.('stop', onStop);
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* The peer `addr` is bound to, or `undefined` when it names none. Throws, naming the address,
|
|
246
|
+
* when the id it carries does not parse: the upgrader would reject the same address after
|
|
247
|
+
* connecting, so failing before the network costs nothing and says why.
|
|
248
|
+
*/
|
|
249
|
+
function boundPeer(addr, label) {
|
|
250
|
+
const id = trailingPeerId(addr);
|
|
251
|
+
if (id === null) {
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
return peerIdFromString(id);
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
throw new Error(`${label}: ${addr.toString()} does not end in a peer id that parses`, { cause: err });
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* An open connection to `target` without relay limits, when the node holds one — the rule
|
|
263
|
+
* libp2p's dial queue applied before dialing (`findExistingConnection`): a direct connection is
|
|
264
|
+
* preferred, and a relayed one is not reused for a direct address, so the dial can upgrade the
|
|
265
|
+
* link. `undefined` when the node holds none, or does not expose its connections.
|
|
266
|
+
*
|
|
267
|
+
* Returned as the `Connection` it is on a real node. A double that reports an open connection
|
|
268
|
+
* must supply what its caller uses of one.
|
|
269
|
+
*/
|
|
270
|
+
function reusableConnection(dialer, target, addr) {
|
|
271
|
+
if (target === undefined || dialer.getConnections === undefined) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
const expected = target.toString();
|
|
275
|
+
const open = dialer.getConnections(target)
|
|
276
|
+
.filter((c) => c.status === 'open' && c.limits === undefined && c.remotePeer.toString() === expected);
|
|
277
|
+
const existing = open.find((c) => c.direct !== false) ?? open[0];
|
|
278
|
+
if (existing === undefined || (existing.direct === false && !isRelayed(addr))) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
return existing;
|
|
282
|
+
}
|
|
283
|
+
async function assertDialAllowed(gater, target, addr, label) {
|
|
284
|
+
if (target !== undefined && await gater?.denyDialPeer?.(target)) {
|
|
285
|
+
throw new Error(`${label}: the connection gater denies dialing ${target.toString()}`);
|
|
286
|
+
}
|
|
287
|
+
if (await gater?.denyDialMultiaddr?.(addr)) {
|
|
288
|
+
throw new Error(`${label}: the connection gater denies dialing ${addr.toString()}`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
105
291
|
/**
|
|
106
292
|
* Thrown by {@link dialPeerAddrs} when it was given addresses but every one reaches the peer by
|
|
107
293
|
* relaying through this node, so none was dialed.
|
|
@@ -119,30 +305,81 @@ export class SelfRelayOnlyError extends Error {
|
|
|
119
305
|
}
|
|
120
306
|
}
|
|
121
307
|
/**
|
|
122
|
-
*
|
|
308
|
+
* No connection to the peer formed, so nothing was sent to it. `cause` is what the dial threw:
|
|
309
|
+
* {@link dialPeerAddrs}'s error naming every address and why it failed, or a
|
|
310
|
+
* {@link SelfRelayOnlyError}.
|
|
311
|
+
*
|
|
312
|
+
* Kept apart from failures after a connection formed so a caller can tell "this device could not
|
|
313
|
+
* reach the peer" from "the peer was reached and then something else failed" without reading
|
|
314
|
+
* libp2p's error text. `SeedBootstrapService.deliverSeed` throws it, and so `CadreNode.claimNode`.
|
|
315
|
+
*/
|
|
316
|
+
export class PeerUnreachableError extends Error {
|
|
317
|
+
constructor(peerId, cause) {
|
|
318
|
+
super(`Could not reach ${peerId}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
319
|
+
this.peerId = peerId;
|
|
320
|
+
this.name = 'PeerUnreachableError';
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Dial `peerId` from `addrs`, one address per {@link dialAddr} call, and return the
|
|
123
325
|
* first connection that forms. Direct addresses are tried before relayed ones
|
|
124
326
|
* ({@link directBeforeRelayed}); otherwise the given order is kept.
|
|
125
327
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
328
|
+
* Every address is first bound to `peerId` ({@link withTrailingPeerId}), so the
|
|
329
|
+
* handshake verifies that the peer expected is the one that answered; an address
|
|
330
|
+
* naming another peer is dropped and logged. When that leaves nothing of a
|
|
331
|
+
* non-empty list — every address names someone else, or `peerId` does not parse —
|
|
332
|
+
* this throws without dialing.
|
|
129
333
|
*
|
|
130
|
-
* Addresses
|
|
131
|
-
* one
|
|
334
|
+
* Addresses that relay through this node are dropped next ({@link relaysThrough}):
|
|
335
|
+
* dialing one could only fail with `Can not dial self`. When that leaves nothing,
|
|
336
|
+
* this throws {@link SelfRelayOnlyError} without dialing.
|
|
337
|
+
*
|
|
338
|
+
* Addresses naming a transport this node lacks are not filtered out first: the
|
|
339
|
+
* transport manager rejects those at once (`TransportUnavailableError`), so they
|
|
132
340
|
* cost a log line, not time.
|
|
133
341
|
*
|
|
134
342
|
* Otherwise throws when no address connects — see {@link tryAddrsInTurn} for the error.
|
|
135
343
|
*
|
|
344
|
+
* @param peerId The peer every address must reach, as every caller already holds it
|
|
345
|
+
* (a `CadrePeer` row key, a seed peer's id, a strand member's id).
|
|
136
346
|
* @param label Names the dial in timeout messages and logs, e.g.
|
|
137
347
|
* `reconcileControlCohort dial of sibling <peerId>`; each attempt reads
|
|
138
348
|
* `<label> via <addr>`.
|
|
139
349
|
*/
|
|
140
|
-
export async function dialPeerAddrs(dialer, addrs, budget, label) {
|
|
141
|
-
const
|
|
142
|
-
if (addrs.length > 0 &&
|
|
350
|
+
export async function dialPeerAddrs(dialer, peerId, addrs, budget, label) {
|
|
351
|
+
const bound = boundTo(peerId, addrs, label);
|
|
352
|
+
if (addrs.length > 0 && bound.length === 0) {
|
|
353
|
+
throw new Error(`${label}: none of the ${addrs.length} candidate addresses binds to ${peerId}`);
|
|
354
|
+
}
|
|
355
|
+
const dialable = withoutSelfRelayed(dialer, bound, label);
|
|
356
|
+
if (bound.length > 0 && dialable.length === 0) {
|
|
143
357
|
throw new SelfRelayOnlyError(label);
|
|
144
358
|
}
|
|
145
|
-
return tryAddrsInTurn(directBeforeRelayed(dialable), budget, label, (addr, signal) => dialer
|
|
359
|
+
return tryAddrsInTurn(directBeforeRelayed(dialable), budget, label, (addr, signal) => dialAddr(dialer, addr, signal, label));
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* `addrs` each bound to `peerId` ({@link withTrailingPeerId}). An address naming another peer
|
|
363
|
+
* is dropped, as is every address when `peerId` cannot be encapsulated (it does not parse);
|
|
364
|
+
* each drop is logged with its reason.
|
|
365
|
+
*/
|
|
366
|
+
function boundTo(peerId, addrs, label) {
|
|
367
|
+
const bound = [];
|
|
368
|
+
for (const addr of addrs) {
|
|
369
|
+
try {
|
|
370
|
+
const withId = withTrailingPeerId(addr, peerId);
|
|
371
|
+
if (withId === null) {
|
|
372
|
+
log('%s: dropping %s — it names a peer other than %s', label, addr.toString(), peerId);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
bound.push(withId);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
log('%s: cannot bind %s to %s: %o', label, addr.toString(), peerId, err);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return bound;
|
|
146
383
|
}
|
|
147
384
|
/**
|
|
148
385
|
* Run `attempt` against each address in the given order until one succeeds, and
|
|
@@ -158,17 +395,17 @@ export async function dialPeerAddrs(dialer, addrs, budget, label) {
|
|
|
158
395
|
* failed, in order, with the first failure as `cause` — so the report shows the
|
|
159
396
|
* address that mattered, not only whichever happened to be tried last.
|
|
160
397
|
*
|
|
161
|
-
* Between attempts this waits for one macrotask (`setTimeout(0)`).
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* queue's
|
|
171
|
-
*
|
|
398
|
+
* Between attempts this waits for one macrotask (`setTimeout(0)`). A direct
|
|
399
|
+
* address is dialed outside libp2p's dial queue ({@link dialAddr}), but a relayed
|
|
400
|
+
* address still passes through it for the relay leg, and the queue lets a new
|
|
401
|
+
* dial join any queued job for the same peer id WITHOUT checking whether that
|
|
402
|
+
* job has already finished: an aborted job leaves the queue a few microtasks
|
|
403
|
+
* after its callers are rejected, so a next attempt through the same relay made
|
|
404
|
+
* at once would join the dying job and be rejected with `AbortError` before it
|
|
405
|
+
* touches the network. All of the queue's cleanup runs as microtasks, so it has
|
|
406
|
+
* finished by the time a macrotask runs. Seen against libp2p 3.1.3, and the
|
|
407
|
+
* queue's join is unchanged in 3.3.11; `test/peer-dial.spec.ts` dials real nodes
|
|
408
|
+
* so an upgrade that changes it shows up there.
|
|
172
409
|
*/
|
|
173
410
|
export async function tryAddrsInTurn(addrs, budget, label, attempt) {
|
|
174
411
|
const deadline = Date.now() + budget.totalMs;
|
|
@@ -207,8 +444,11 @@ export async function tryAddrsInTurn(addrs, budget, label, attempt) {
|
|
|
207
444
|
* bounded amount of time, so the caller's order is the better guide.
|
|
208
445
|
*/
|
|
209
446
|
export function directBeforeRelayed(addrs) {
|
|
210
|
-
|
|
211
|
-
|
|
447
|
+
return [...addrs.filter((addr) => !isRelayed(addr)), ...addrs.filter(isRelayed)];
|
|
448
|
+
}
|
|
449
|
+
/** Whether `addr` reaches its target through a circuit relay. */
|
|
450
|
+
function isRelayed(addr) {
|
|
451
|
+
return addr.getComponents().some((c) => c.name === 'p2p-circuit');
|
|
212
452
|
}
|
|
213
453
|
/** `addrs` without those that relay through `dialer` itself, each dropped one logged. */
|
|
214
454
|
function withoutSelfRelayed(dialer, addrs, label) {
|
|
@@ -263,7 +503,12 @@ function allAttemptsFailed(label, failures) {
|
|
|
263
503
|
const detail = failures.map((f) => `${f.addr.toString()} — ${f.error.message}`).join('; ');
|
|
264
504
|
return new Error(`${label} failed for all ${failures.length} candidate addresses: ${detail}`, { cause: failures[0].error });
|
|
265
505
|
}
|
|
266
|
-
|
|
506
|
+
/**
|
|
507
|
+
* Yield one macrotask: libp2p's dial queue drops an aborted job only on the next turn, so a
|
|
508
|
+
* dialer that moves on to another address after an abort waits this long first. Shared with
|
|
509
|
+
* the cadre invitation dialer (`cadre-invite-protocol.ts`).
|
|
510
|
+
*/
|
|
511
|
+
export function nextMacrotask() {
|
|
267
512
|
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
268
513
|
}
|
|
269
514
|
//# sourceMappingURL=peer-dial.js.map
|
package/dist/peer-dial.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peer-dial.js","sourceRoot":"","sources":["../src/peer-dial.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"peer-dial.js","sourceRoot":"","sources":["../src/peer-dial.ts"],"names":[],"mappings":"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"}
|