@peerbit/stream 5.0.17 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/index.d.ts +76 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +390 -81
- package/dist/src/index.js.map +1 -1
- package/dist/src/routes.d.ts +31 -3
- package/dist/src/routes.d.ts.map +1 -1
- package/dist/src/routes.js.map +1 -1
- package/dist/src/rust-core.d.ts +561 -0
- package/dist/src/rust-core.d.ts.map +1 -0
- package/dist/src/rust-core.js +16 -0
- package/dist/src/rust-core.js.map +1 -0
- package/package.json +5 -5
- package/src/index.ts +539 -96
- package/src/routes.ts +43 -2
- package/src/rust-core.ts +696 -0
package/src/rust-core.ts
ADDED
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
// Interfaces for the optional native (wasm) DirectStream core implemented by
|
|
2
|
+
// `@peerbit/network-rust` (the `peerbit_wire` crate's `direct_stream`
|
|
3
|
+
// modules). When `DirectStreamOptions.rustCore` is set, the routing table,
|
|
4
|
+
// seen-cache dedup, outbound lane scheduling and the seek-routing/relay/ack
|
|
5
|
+
// decisions run in Rust; the TS class remains the socket owner and byte
|
|
6
|
+
// pump. With the option unset the pure TS implementations are used,
|
|
7
|
+
// unchanged.
|
|
8
|
+
import type { Uint8ArrayList } from "uint8arraylist";
|
|
9
|
+
import type { PushableLanes } from "./pushable-lanes.js";
|
|
10
|
+
import type { RoutesLike } from "./routes.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Native (wasm) batch decode+verify module for inbound frames, implemented by
|
|
14
|
+
* `@peerbit/network-rust`. The result is a flat Uint32Array with
|
|
15
|
+
* NATIVE_WIRE_RECORD_WORDS words per frame; the layout is defined by the
|
|
16
|
+
* `peerbit_wire` crate (see RECORD_* in its lib.rs) and mirrored by the
|
|
17
|
+
* NATIVE_WIRE_* constants in index.ts.
|
|
18
|
+
*/
|
|
19
|
+
export interface NativeWire {
|
|
20
|
+
decodeAndVerifyBatch(frames: Uint8Array[], nowMs: number): Uint32Array;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Seen-cache dedup counter backed by the native core. */
|
|
24
|
+
export interface RustSeenCache {
|
|
25
|
+
/**
|
|
26
|
+
* Bump the seen counter for a frame and return how many times it was seen
|
|
27
|
+
* before. `kind` 0 keys by message id (first 33 frame bytes, the
|
|
28
|
+
* `getMsgId` rule), 1 by sha256 of the whole frame (the ACK path).
|
|
29
|
+
*/
|
|
30
|
+
modify(bytes: Uint8Array, kind: 0 | 1): number;
|
|
31
|
+
clear(): void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Routing/relay/ack decision functions executed by the native core. */
|
|
35
|
+
export interface RustStreamDecisions {
|
|
36
|
+
shouldIgnoreData(args: {
|
|
37
|
+
seenBefore: number;
|
|
38
|
+
acknowledgedMode: boolean;
|
|
39
|
+
redundancy: number;
|
|
40
|
+
hops: string[];
|
|
41
|
+
me: string;
|
|
42
|
+
signedBySelf: boolean;
|
|
43
|
+
}): boolean;
|
|
44
|
+
shouldAcknowledge(args: {
|
|
45
|
+
isRecipient: boolean;
|
|
46
|
+
seenBefore: number;
|
|
47
|
+
redundancy: number;
|
|
48
|
+
}): boolean;
|
|
49
|
+
ackNextHop(
|
|
50
|
+
trace: string[],
|
|
51
|
+
me: string,
|
|
52
|
+
): { myIndex: number; next?: string };
|
|
53
|
+
seekAckRouteUpdate(args: {
|
|
54
|
+
current: string;
|
|
55
|
+
upstream?: string;
|
|
56
|
+
downstream: string;
|
|
57
|
+
}): { from: string; neighbour: string };
|
|
58
|
+
filterFloodTargets(
|
|
59
|
+
candidates: string[],
|
|
60
|
+
from: string,
|
|
61
|
+
signed: string[],
|
|
62
|
+
hops: string[],
|
|
63
|
+
): Uint32Array;
|
|
64
|
+
filterSilentRelayRecipients(
|
|
65
|
+
recipients: string[],
|
|
66
|
+
me: string,
|
|
67
|
+
from: string,
|
|
68
|
+
connected: string[],
|
|
69
|
+
hops: string[],
|
|
70
|
+
): string[];
|
|
71
|
+
selectRedundancyProbes(
|
|
72
|
+
peers: string[],
|
|
73
|
+
used: string[],
|
|
74
|
+
redundancy: number,
|
|
75
|
+
): string[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface RustRoutesInit {
|
|
79
|
+
me: string;
|
|
80
|
+
routeMaxRetentionPeriod: number;
|
|
81
|
+
signal?: AbortSignal;
|
|
82
|
+
maxFromEntries?: number;
|
|
83
|
+
maxTargetsPerFrom?: number;
|
|
84
|
+
maxRelaysPerTarget?: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface RustLanesInit {
|
|
88
|
+
lanes: number;
|
|
89
|
+
maxBufferedBytes?: number;
|
|
90
|
+
onBufferSize?(bufferedBytes: number): void;
|
|
91
|
+
onPush?(value: { byteLength: number }, lane: number): void;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** A decoded `/peerbit/direct-block` message produced by the native codec. */
|
|
95
|
+
export type RustDecodedBlockMessage =
|
|
96
|
+
| { type: "request"; cid: string }
|
|
97
|
+
| {
|
|
98
|
+
type: "response";
|
|
99
|
+
cid: string;
|
|
100
|
+
/** View into the input payload (no copy). */
|
|
101
|
+
bytes: Uint8Array;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Provider-hint cache of `RemoteBlocks` backed by the native core
|
|
106
|
+
* (`rememberProvider`/`rememberProviderHints`/lookup semantics).
|
|
107
|
+
*/
|
|
108
|
+
export interface RustBlockProviderCache {
|
|
109
|
+
get(cid: string): string[] | undefined;
|
|
110
|
+
rememberProvider(cid: string, provider: string): void;
|
|
111
|
+
rememberHints(cid: string, providers: string[]): void;
|
|
112
|
+
clear(): void;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Eager-block cache with native bookkeeping. Block bytes stay host-side;
|
|
117
|
+
* the native index decides retention/eviction.
|
|
118
|
+
*/
|
|
119
|
+
export interface RustEagerBlockCache {
|
|
120
|
+
add(cid: string, bytes: Uint8Array): void;
|
|
121
|
+
get(cid: string): Uint8Array | undefined;
|
|
122
|
+
del(cid: string): void;
|
|
123
|
+
clear(): void;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Native block-exchange components for `DirectBlock`/`RemoteBlocks`
|
|
128
|
+
* (`@peerbit/blocks`): the `BlockMessage` codec, the provider resolution
|
|
129
|
+
* rules and the caches. Part of the same rust-core mode as the DirectStream
|
|
130
|
+
* state machine.
|
|
131
|
+
*/
|
|
132
|
+
export interface RustBlockExchange {
|
|
133
|
+
encodeBlockRequest(cid: string): Uint8Array;
|
|
134
|
+
encodeBlockResponse(cid: string, bytes: Uint8Array): Uint8Array;
|
|
135
|
+
decodeBlockMessage(payload: Uint8Array): RustDecodedBlockMessage;
|
|
136
|
+
normalizeProviderHints(
|
|
137
|
+
providers: string[],
|
|
138
|
+
me: string,
|
|
139
|
+
limit: number,
|
|
140
|
+
): string[];
|
|
141
|
+
pickRequestBatch(providers: string[], me: string, attempt: number): string[];
|
|
142
|
+
defaultProviderCandidates(
|
|
143
|
+
negotiated: string[],
|
|
144
|
+
connected: string[],
|
|
145
|
+
me: string,
|
|
146
|
+
): string[];
|
|
147
|
+
createProviderCache(init: {
|
|
148
|
+
me: string;
|
|
149
|
+
maxEntries: number;
|
|
150
|
+
ttlMs: number;
|
|
151
|
+
maxProvidersPerCid: number;
|
|
152
|
+
}): RustBlockProviderCache;
|
|
153
|
+
createEagerCache(init: { max: number; ttl: number }): RustEagerBlockCache;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* A decoded `/peerbit/topic-control-plane` message produced by the native
|
|
158
|
+
* codec (borsh `PubSubMessage` variants 0-7).
|
|
159
|
+
*/
|
|
160
|
+
export type RustDecodedPubSubMessage =
|
|
161
|
+
| {
|
|
162
|
+
type: "data";
|
|
163
|
+
topics: string[];
|
|
164
|
+
strict: boolean;
|
|
165
|
+
/** View into the input payload (no copy). */
|
|
166
|
+
data: Uint8Array;
|
|
167
|
+
}
|
|
168
|
+
| { type: "subscribe"; topics: string[]; requestSubscribers: boolean }
|
|
169
|
+
| { type: "unsubscribe"; topics: string[] }
|
|
170
|
+
| { type: "get-subscribers"; topics: string[] }
|
|
171
|
+
| { type: "topic-root-candidates"; candidates: string[] }
|
|
172
|
+
| {
|
|
173
|
+
type: "peer-unavailable";
|
|
174
|
+
publicKeyHash: string;
|
|
175
|
+
session: bigint;
|
|
176
|
+
timestamp: bigint;
|
|
177
|
+
topics: string[];
|
|
178
|
+
}
|
|
179
|
+
| { type: "topic-root-query"; requestId: number; topic: string }
|
|
180
|
+
| {
|
|
181
|
+
type: "topic-root-query-response";
|
|
182
|
+
requestId: number;
|
|
183
|
+
topic: string;
|
|
184
|
+
root?: string;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* `TopicRootDirectory` root-resolution state backed by the native core
|
|
189
|
+
* (explicit per-topic roots plus the normalized deterministic candidate
|
|
190
|
+
* set). Trackers and the resolver callback stay host-side.
|
|
191
|
+
*/
|
|
192
|
+
export interface RustTopicRootDirectoryState {
|
|
193
|
+
setRoot(topic: string, root: string): void;
|
|
194
|
+
deleteRoot(topic: string): void;
|
|
195
|
+
getRoot(topic: string): string | undefined;
|
|
196
|
+
setDefaultCandidates(candidates: string[]): void;
|
|
197
|
+
getDefaultCandidates(): string[];
|
|
198
|
+
resolveDeterministicCandidate(topic: string): string | undefined;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Native topic-control-plane components consumed by `@peerbit/pubsub`: the
|
|
203
|
+
* `PubSubMessage` codec, the topic hashing that keys shard mapping and
|
|
204
|
+
* deterministic root selection, the root-directory state and the
|
|
205
|
+
* subscribe-state convergence rules. The observable subscription maps stay
|
|
206
|
+
* host-side (they are public API); every protocol decision that feeds them
|
|
207
|
+
* runs natively.
|
|
208
|
+
*/
|
|
209
|
+
export interface RustTopicControl {
|
|
210
|
+
encodePubSubData(
|
|
211
|
+
topics: string[],
|
|
212
|
+
strict: boolean,
|
|
213
|
+
data: Uint8Array,
|
|
214
|
+
): Uint8Array;
|
|
215
|
+
encodeSubscribe(topics: string[], requestSubscribers: boolean): Uint8Array;
|
|
216
|
+
encodeUnsubscribe(topics: string[]): Uint8Array;
|
|
217
|
+
encodeGetSubscribers(topics: string[]): Uint8Array;
|
|
218
|
+
encodeTopicRootCandidates(candidates: string[]): Uint8Array;
|
|
219
|
+
encodePeerUnavailable(
|
|
220
|
+
publicKeyHash: string,
|
|
221
|
+
session: bigint,
|
|
222
|
+
timestamp: bigint,
|
|
223
|
+
topics: string[],
|
|
224
|
+
): Uint8Array;
|
|
225
|
+
encodeTopicRootQuery(requestId: number, topic: string): Uint8Array;
|
|
226
|
+
encodeTopicRootQueryResponse(
|
|
227
|
+
requestId: number,
|
|
228
|
+
topic: string,
|
|
229
|
+
root?: string,
|
|
230
|
+
): Uint8Array;
|
|
231
|
+
decodePubSubMessage(payload: Uint8Array): RustDecodedPubSubMessage;
|
|
232
|
+
/** `getShardTopicForUserTopic`: user topic -> internal shard topic. */
|
|
233
|
+
shardTopic(topic: string, shardCount: number, prefix: string): string;
|
|
234
|
+
/**
|
|
235
|
+
* `normalizeAutoTopicRootCandidates`: dedupe, include self, sort and cap
|
|
236
|
+
* at the auto-candidate bound.
|
|
237
|
+
*/
|
|
238
|
+
normalizeAutoCandidates(candidates: string[], me: string): string[];
|
|
239
|
+
/**
|
|
240
|
+
* The `subscriptionStateIsLatest` comparison rule. `lasts` carries
|
|
241
|
+
* interleaved (session, timestamp) watermark pairs for the relevant
|
|
242
|
+
* topics that have one; the watermark write-back stays host-side.
|
|
243
|
+
*/
|
|
244
|
+
subscriptionIsLatest(
|
|
245
|
+
lasts: BigUint64Array,
|
|
246
|
+
session: bigint,
|
|
247
|
+
timestamp: bigint,
|
|
248
|
+
): boolean;
|
|
249
|
+
/**
|
|
250
|
+
* The subscribe-apply replacement rule: replace tracked subscription data
|
|
251
|
+
* for new subscribers or strictly newer sessions, else only refresh.
|
|
252
|
+
*/
|
|
253
|
+
subscribeShouldReplace(
|
|
254
|
+
existingSession: bigint | undefined,
|
|
255
|
+
session: bigint,
|
|
256
|
+
): boolean;
|
|
257
|
+
createRootDirectoryState(): RustTopicRootDirectoryState;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Decoded fanout-tree frames produced by the native codec. The decoders
|
|
261
|
+
* mirror the tolerance of the TS parsers exactly: `undefined` means the
|
|
262
|
+
* frame fails the same minimum-length checks, and truncated lists end at
|
|
263
|
+
* the same element. Multiaddr bytes are returned raw; validity filtering
|
|
264
|
+
* (and `multiaddr()` construction) stays host-side in both modes. */
|
|
265
|
+
export type RustDecodedFanoutJoinReq = {
|
|
266
|
+
reqId: number;
|
|
267
|
+
bidPerByte: number;
|
|
268
|
+
parentUpgradeReservationToken: number;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export type RustDecodedFanoutJoinAccept = {
|
|
272
|
+
parentLevel: number;
|
|
273
|
+
parentRouteFromRoot: string[];
|
|
274
|
+
haveRange?: { haveFrom: number; haveToExclusive: number };
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export type RustDecodedFanoutJoinReject = {
|
|
278
|
+
reason: number;
|
|
279
|
+
redirects: { hash: string; addrs: Uint8Array[] }[];
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
export type RustDecodedFanoutUnicast = {
|
|
283
|
+
ackToken?: bigint;
|
|
284
|
+
route: string[];
|
|
285
|
+
replyRoute?: string[];
|
|
286
|
+
payloadOffset: number;
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
export type RustDecodedFanoutTrackerReplyEntry = {
|
|
290
|
+
hash: string;
|
|
291
|
+
level: number;
|
|
292
|
+
freeSlots: number;
|
|
293
|
+
bidPerByte: number;
|
|
294
|
+
addrs: Uint8Array[];
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
export type RustDecodedFanoutParentProbeReply = {
|
|
298
|
+
reqId: number;
|
|
299
|
+
hash: string;
|
|
300
|
+
rooted: boolean;
|
|
301
|
+
accepting: boolean;
|
|
302
|
+
repairing: boolean;
|
|
303
|
+
overloaded: boolean;
|
|
304
|
+
reservationToken: number;
|
|
305
|
+
level: number;
|
|
306
|
+
maxChildren: number;
|
|
307
|
+
freeSlots: number;
|
|
308
|
+
children: number;
|
|
309
|
+
haveToExclusive: number;
|
|
310
|
+
missingSeqs: number;
|
|
311
|
+
dataWriteDrops: number;
|
|
312
|
+
droppedForwards: number;
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
export type RustDecodedFanoutProviderEntry = {
|
|
316
|
+
hash: string;
|
|
317
|
+
addrs: Uint8Array[];
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/** `normalizeParentUpgradePolicy` result shape (fanout-tree-parent-upgrade). */
|
|
321
|
+
export type RustParentUpgradePolicy = {
|
|
322
|
+
intervalMs: number;
|
|
323
|
+
leafOnly: boolean;
|
|
324
|
+
minLevelGain: number;
|
|
325
|
+
rootMinLevelGain: number;
|
|
326
|
+
rootMinSubtreeGain: number;
|
|
327
|
+
nonRootMinLevelGain: number;
|
|
328
|
+
minFreeSlots: number;
|
|
329
|
+
rootMinFreeSlots: number;
|
|
330
|
+
maxChildLoadRatio: number;
|
|
331
|
+
rootMaxChildLoadRatio: number;
|
|
332
|
+
staleRootProbeProbability: number;
|
|
333
|
+
cooldownMs: number;
|
|
334
|
+
quietMs: number;
|
|
335
|
+
repairQuietMs: number;
|
|
336
|
+
maxPerPeer: number;
|
|
337
|
+
repairGuard: boolean;
|
|
338
|
+
dataGuard: boolean;
|
|
339
|
+
mode: "direct" | "probe" | "shadow";
|
|
340
|
+
verifyStaleRootCapacity: boolean;
|
|
341
|
+
failedBackoff: { minMs: number; maxMs: number };
|
|
342
|
+
probe: {
|
|
343
|
+
timeoutMs: number;
|
|
344
|
+
maxPerRound: number;
|
|
345
|
+
maxLagMessages: number;
|
|
346
|
+
rejectCooldownMs: number;
|
|
347
|
+
rejectCooldownMaxMs: number;
|
|
348
|
+
};
|
|
349
|
+
shadow: {
|
|
350
|
+
observeMs: number;
|
|
351
|
+
minObservations: number;
|
|
352
|
+
dualPathMs: number;
|
|
353
|
+
dualPathMinMessages: number;
|
|
354
|
+
};
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
export type RustParentUpgradeOptions = {
|
|
358
|
+
parentUpgradeIntervalMs?: number;
|
|
359
|
+
parentUpgradeLeafOnly?: boolean;
|
|
360
|
+
parentUpgradeMinLevelGain?: number;
|
|
361
|
+
parentUpgradeRootMinLevelGain?: number;
|
|
362
|
+
parentUpgradeRootMinSubtreeGain?: number;
|
|
363
|
+
parentUpgradeNonRootMinLevelGain?: number;
|
|
364
|
+
parentUpgradeMinFreeSlots?: number;
|
|
365
|
+
parentUpgradeRootMinFreeSlots?: number;
|
|
366
|
+
parentUpgradeMaxChildLoadRatio?: number;
|
|
367
|
+
parentUpgradeRootMaxChildLoadRatio?: number;
|
|
368
|
+
parentUpgradeCooldownMs?: number;
|
|
369
|
+
parentUpgradeFailedBackoffMinMs?: number;
|
|
370
|
+
parentUpgradeFailedBackoffMaxMs?: number;
|
|
371
|
+
parentUpgradeQuietMs?: number;
|
|
372
|
+
parentUpgradeRepairQuietMs?: number;
|
|
373
|
+
parentUpgradeMaxPerPeer?: number;
|
|
374
|
+
parentUpgradeRepairGuard?: boolean;
|
|
375
|
+
parentUpgradeDataGuard?: boolean;
|
|
376
|
+
parentUpgradeMode?: string;
|
|
377
|
+
parentUpgradeVerifyStaleRootCapacity?: boolean;
|
|
378
|
+
parentUpgradeStaleRootProbeProbability?: number;
|
|
379
|
+
parentProbeTimeoutMs?: number;
|
|
380
|
+
parentProbeMaxPerRound?: number;
|
|
381
|
+
parentProbeMaxLagMessages?: number;
|
|
382
|
+
parentProbeRejectCooldownMs?: number;
|
|
383
|
+
parentProbeRejectCooldownMaxMs?: number;
|
|
384
|
+
parentShadowObserveMs?: number;
|
|
385
|
+
parentShadowMinObservations?: number;
|
|
386
|
+
parentShadowDualPathMs?: number;
|
|
387
|
+
parentShadowDualPathMinMessages?: number;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
export type RustParentUpgradeGateState = {
|
|
391
|
+
children: { size: number };
|
|
392
|
+
missingSeqs: { size: number };
|
|
393
|
+
lastRepairSentAt: number;
|
|
394
|
+
endSeqExclusive: number;
|
|
395
|
+
parentUpgradeRetryAfterSeq: number;
|
|
396
|
+
maxSeqSeen: number;
|
|
397
|
+
parentUpgradeCount: number;
|
|
398
|
+
parentUpgradeBackoffUntil: number;
|
|
399
|
+
parentUpgradeLastAt: number;
|
|
400
|
+
lastParentDataAt: number;
|
|
401
|
+
lastParentUpgradeActivityAt?: number;
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
export type RustParentUpgradeGateOptions = {
|
|
405
|
+
leafOnly: boolean;
|
|
406
|
+
repairGuard: boolean;
|
|
407
|
+
dataGuard: boolean;
|
|
408
|
+
endedAndComplete: boolean;
|
|
409
|
+
maxPerPeer: number;
|
|
410
|
+
cooldownMs: number;
|
|
411
|
+
quietMs: number;
|
|
412
|
+
repairQuietMs: number;
|
|
413
|
+
now: number;
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Native fanout-tree components consumed by `@peerbit/pubsub`'s FanoutTree
|
|
418
|
+
* in rust-core mode: the complete `/peerbit/fanout-tree/0.5.0` big-endian
|
|
419
|
+
* frame codec (byte-identical to `fanout-tree-codec.ts`, all message kinds
|
|
420
|
+
* MSG_JOIN_REQ(1)..MSG_PARENT_PROBE_REPLY(41)) plus the parent-upgrade
|
|
421
|
+
* policy/gate decisions merged in PR #911. The channel state machine,
|
|
422
|
+
* timers and events stay host-side.
|
|
423
|
+
*/
|
|
424
|
+
export interface RustFanoutTree {
|
|
425
|
+
encodeJoinReq(
|
|
426
|
+
channelKey: Uint8Array,
|
|
427
|
+
reqId: number,
|
|
428
|
+
bidPerByte: number,
|
|
429
|
+
parentUpgradeReservationToken?: number,
|
|
430
|
+
): Uint8Array;
|
|
431
|
+
encodeJoinAccept(
|
|
432
|
+
channelKey: Uint8Array,
|
|
433
|
+
reqId: number,
|
|
434
|
+
level: number,
|
|
435
|
+
parentRouteFromRoot?: string[],
|
|
436
|
+
haveRange?: { haveFrom: number; haveToExclusive: number },
|
|
437
|
+
): Uint8Array;
|
|
438
|
+
encodeJoinReject(
|
|
439
|
+
channelKey: Uint8Array,
|
|
440
|
+
reqId: number,
|
|
441
|
+
reason: number,
|
|
442
|
+
redirects?: { hash: string; addrs: Uint8Array[] }[],
|
|
443
|
+
): Uint8Array;
|
|
444
|
+
encodeKick(channelKey: Uint8Array): Uint8Array;
|
|
445
|
+
encodeEnd(channelKey: Uint8Array, lastSeqExclusive: number): Uint8Array;
|
|
446
|
+
encodeRepairReq(
|
|
447
|
+
channelKey: Uint8Array,
|
|
448
|
+
reqId: number,
|
|
449
|
+
missingSeqs: number[],
|
|
450
|
+
): Uint8Array;
|
|
451
|
+
encodeFetchReq(
|
|
452
|
+
channelKey: Uint8Array,
|
|
453
|
+
reqId: number,
|
|
454
|
+
missingSeqs: number[],
|
|
455
|
+
): Uint8Array;
|
|
456
|
+
encodeIHave(
|
|
457
|
+
channelKey: Uint8Array,
|
|
458
|
+
haveFrom: number,
|
|
459
|
+
haveToExclusive: number,
|
|
460
|
+
): Uint8Array;
|
|
461
|
+
encodeData(payload: Uint8Array): Uint8Array;
|
|
462
|
+
encodePublishProxy(channelKey: Uint8Array, payload: Uint8Array): Uint8Array;
|
|
463
|
+
encodeLeave(channelKey: Uint8Array): Uint8Array;
|
|
464
|
+
encodeUnicast(
|
|
465
|
+
channelKey: Uint8Array,
|
|
466
|
+
route: string[],
|
|
467
|
+
payload: Uint8Array,
|
|
468
|
+
options?: { ackToken?: bigint; replyRoute?: string[] },
|
|
469
|
+
): Uint8Array;
|
|
470
|
+
encodeUnicastAck(
|
|
471
|
+
channelKey: Uint8Array,
|
|
472
|
+
ackToken: bigint,
|
|
473
|
+
route: string[],
|
|
474
|
+
): Uint8Array;
|
|
475
|
+
encodeRouteQuery(
|
|
476
|
+
channelKey: Uint8Array,
|
|
477
|
+
reqId: number,
|
|
478
|
+
targetHash: string,
|
|
479
|
+
): Uint8Array;
|
|
480
|
+
encodeRouteReply(
|
|
481
|
+
channelKey: Uint8Array,
|
|
482
|
+
reqId: number,
|
|
483
|
+
route?: string[],
|
|
484
|
+
): Uint8Array;
|
|
485
|
+
encodeTrackerAnnounce(
|
|
486
|
+
channelKey: Uint8Array,
|
|
487
|
+
ttlMs: number,
|
|
488
|
+
level: number,
|
|
489
|
+
maxChildren: number,
|
|
490
|
+
freeSlots: number,
|
|
491
|
+
bidPerByte: number,
|
|
492
|
+
addrs: { bytes: Uint8Array }[],
|
|
493
|
+
): Uint8Array;
|
|
494
|
+
encodeTrackerQuery(
|
|
495
|
+
channelKey: Uint8Array,
|
|
496
|
+
reqId: number,
|
|
497
|
+
want: number,
|
|
498
|
+
): Uint8Array;
|
|
499
|
+
encodeTrackerReply(
|
|
500
|
+
channelKey: Uint8Array,
|
|
501
|
+
reqId: number,
|
|
502
|
+
entries: {
|
|
503
|
+
hash: string;
|
|
504
|
+
level: number;
|
|
505
|
+
freeSlots: number;
|
|
506
|
+
bidPerByte: number;
|
|
507
|
+
addrs: Uint8Array[];
|
|
508
|
+
}[],
|
|
509
|
+
): Uint8Array;
|
|
510
|
+
encodeTrackerFeedback(
|
|
511
|
+
channelKey: Uint8Array,
|
|
512
|
+
candidateHash: string,
|
|
513
|
+
event: number,
|
|
514
|
+
reason: number,
|
|
515
|
+
): Uint8Array;
|
|
516
|
+
encodeParentProbeReq(
|
|
517
|
+
channelKey: Uint8Array,
|
|
518
|
+
reqId: number,
|
|
519
|
+
minFreeSlots?: number,
|
|
520
|
+
reserveRootCapacity?: boolean,
|
|
521
|
+
): Uint8Array;
|
|
522
|
+
encodeParentProbeReply(
|
|
523
|
+
channelKey: Uint8Array,
|
|
524
|
+
reqId: number,
|
|
525
|
+
options: {
|
|
526
|
+
flags: number;
|
|
527
|
+
level: number;
|
|
528
|
+
maxChildren: number;
|
|
529
|
+
freeSlots: number;
|
|
530
|
+
children: number;
|
|
531
|
+
haveToExclusive: number;
|
|
532
|
+
missingSeqs: number;
|
|
533
|
+
dataWriteDrops: number;
|
|
534
|
+
droppedForwards: number;
|
|
535
|
+
reservationToken?: number;
|
|
536
|
+
},
|
|
537
|
+
): Uint8Array;
|
|
538
|
+
encodeProviderAnnounce(
|
|
539
|
+
namespaceKey: Uint8Array,
|
|
540
|
+
ttlMs: number,
|
|
541
|
+
addrs: { bytes: Uint8Array }[],
|
|
542
|
+
): Uint8Array;
|
|
543
|
+
encodeProviderQuery(
|
|
544
|
+
namespaceKey: Uint8Array,
|
|
545
|
+
reqId: number,
|
|
546
|
+
want: number,
|
|
547
|
+
seed: number,
|
|
548
|
+
): Uint8Array;
|
|
549
|
+
encodeProviderReply(
|
|
550
|
+
namespaceKey: Uint8Array,
|
|
551
|
+
reqId: number,
|
|
552
|
+
entries: { hash: string; addrs: Uint8Array[] }[],
|
|
553
|
+
): Uint8Array;
|
|
554
|
+
encodeProviderSubscribe(
|
|
555
|
+
namespaceKey: Uint8Array,
|
|
556
|
+
want: number,
|
|
557
|
+
ttlMs: number,
|
|
558
|
+
): Uint8Array;
|
|
559
|
+
encodeProviderUnsubscribe(namespaceKey: Uint8Array): Uint8Array;
|
|
560
|
+
encodeProviderNotify(
|
|
561
|
+
namespaceKey: Uint8Array,
|
|
562
|
+
entries: { hash: string; addrs: Uint8Array[] }[],
|
|
563
|
+
): Uint8Array;
|
|
564
|
+
|
|
565
|
+
decodeJoinReq(data: Uint8Array): RustDecodedFanoutJoinReq | undefined;
|
|
566
|
+
/** The shared JOIN_ACCEPT/JOIN_REJECT head (reqId) parsed before the
|
|
567
|
+
* pending-join lookup. */
|
|
568
|
+
decodeJoinResponseReqId(data: Uint8Array): number | undefined;
|
|
569
|
+
decodeJoinAccept(data: Uint8Array): RustDecodedFanoutJoinAccept | undefined;
|
|
570
|
+
decodeJoinReject(data: Uint8Array): RustDecodedFanoutJoinReject | undefined;
|
|
571
|
+
decodeEnd(data: Uint8Array): number | undefined;
|
|
572
|
+
/** MSG_REPAIR_REQ / MSG_FETCH_REQ sequence list. */
|
|
573
|
+
decodeRepairSeqs(data: Uint8Array): number[] | undefined;
|
|
574
|
+
decodeIHave(
|
|
575
|
+
data: Uint8Array,
|
|
576
|
+
): { haveFrom: number; haveToExclusive: number } | undefined;
|
|
577
|
+
decodeUnicast(data: Uint8Array): RustDecodedFanoutUnicast | undefined;
|
|
578
|
+
decodeUnicastAck(
|
|
579
|
+
data: Uint8Array,
|
|
580
|
+
): { ackToken: bigint; route: string[] } | undefined;
|
|
581
|
+
decodeRouteQuery(
|
|
582
|
+
data: Uint8Array,
|
|
583
|
+
): { reqId: number; targetHash?: string } | undefined;
|
|
584
|
+
decodeRouteReply(
|
|
585
|
+
data: Uint8Array,
|
|
586
|
+
): { reqId: number; route: string[] } | undefined;
|
|
587
|
+
decodeTrackerAnnounce(data: Uint8Array):
|
|
588
|
+
| {
|
|
589
|
+
ttlMs: number;
|
|
590
|
+
level: number;
|
|
591
|
+
freeSlots: number;
|
|
592
|
+
bidPerByte: number;
|
|
593
|
+
addrs: Uint8Array[];
|
|
594
|
+
}
|
|
595
|
+
| undefined;
|
|
596
|
+
decodeTrackerQuery(
|
|
597
|
+
data: Uint8Array,
|
|
598
|
+
): { reqId: number; want: number } | undefined;
|
|
599
|
+
decodeTrackerReply(
|
|
600
|
+
data: Uint8Array,
|
|
601
|
+
):
|
|
602
|
+
| { reqId: number; entries: RustDecodedFanoutTrackerReplyEntry[] }
|
|
603
|
+
| undefined;
|
|
604
|
+
decodeTrackerFeedback(
|
|
605
|
+
data: Uint8Array,
|
|
606
|
+
): { candidateHash: string; event: number; reason: number } | undefined;
|
|
607
|
+
decodeParentProbeReq(data: Uint8Array):
|
|
608
|
+
| {
|
|
609
|
+
reqId: number;
|
|
610
|
+
minFreeSlots: number;
|
|
611
|
+
reserveRootCapacity: boolean;
|
|
612
|
+
}
|
|
613
|
+
| undefined;
|
|
614
|
+
decodeParentProbeReply(
|
|
615
|
+
data: Uint8Array,
|
|
616
|
+
hash: string,
|
|
617
|
+
): RustDecodedFanoutParentProbeReply | undefined;
|
|
618
|
+
decodeProviderAnnounce(
|
|
619
|
+
data: Uint8Array,
|
|
620
|
+
): { ttlMs: number; addrs: Uint8Array[] } | undefined;
|
|
621
|
+
decodeProviderQuery(
|
|
622
|
+
data: Uint8Array,
|
|
623
|
+
): { reqId: number; want: number; seed: number } | undefined;
|
|
624
|
+
decodeProviderReply(
|
|
625
|
+
data: Uint8Array,
|
|
626
|
+
):
|
|
627
|
+
| { reqId: number; entries: RustDecodedFanoutProviderEntry[] }
|
|
628
|
+
| undefined;
|
|
629
|
+
decodeProviderNotify(
|
|
630
|
+
data: Uint8Array,
|
|
631
|
+
): { entries: RustDecodedFanoutProviderEntry[] } | undefined;
|
|
632
|
+
decodeProviderSubscribe(
|
|
633
|
+
data: Uint8Array,
|
|
634
|
+
): { want: number; ttlMs: number } | undefined;
|
|
635
|
+
|
|
636
|
+
/** `normalizeParentUpgradePolicy` (PR #911). */
|
|
637
|
+
normalizeParentUpgradePolicy(
|
|
638
|
+
options: RustParentUpgradeOptions,
|
|
639
|
+
): RustParentUpgradePolicy;
|
|
640
|
+
/**
|
|
641
|
+
* `evaluateParentUpgradeGate` (PR #911); applies the retry-after-seq
|
|
642
|
+
* reset to `state` in place, like the TS implementation.
|
|
643
|
+
*/
|
|
644
|
+
evaluateParentUpgradeGate(
|
|
645
|
+
state: RustParentUpgradeGateState,
|
|
646
|
+
options: RustParentUpgradeGateOptions,
|
|
647
|
+
):
|
|
648
|
+
| { run: true }
|
|
649
|
+
| {
|
|
650
|
+
run: false;
|
|
651
|
+
reason: "leaf" | "repair" | "data" | "cooldown" | "quiet" | "budget";
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* The full native DirectStream core: created by
|
|
657
|
+
* `@peerbit/network-rust`'s `createRustCoreStream()` and passed as
|
|
658
|
+
* `DirectStreamOptions.rustCore`.
|
|
659
|
+
*/
|
|
660
|
+
export interface RustCoreStream {
|
|
661
|
+
/** Batched inbound decode + signature verification (implies nativeWire). */
|
|
662
|
+
nativeWire?: NativeWire;
|
|
663
|
+
createRoutes(init: RustRoutesInit): RoutesLike;
|
|
664
|
+
createSeenCache(init: { max: number; ttl: number }): RustSeenCache;
|
|
665
|
+
createLanes(init: RustLanesInit): PushableLanes<Uint8Array | Uint8ArrayList>;
|
|
666
|
+
decisions: RustStreamDecisions;
|
|
667
|
+
/** Native block-exchange components consumed by `@peerbit/blocks`. */
|
|
668
|
+
blockExchange?: RustBlockExchange;
|
|
669
|
+
/** Native topic-control-plane components consumed by `@peerbit/pubsub`. */
|
|
670
|
+
topicControl?: RustTopicControl;
|
|
671
|
+
/** Native fanout-tree components consumed by `@peerbit/pubsub`. */
|
|
672
|
+
fanout?: RustFanoutTree;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Test-only injection point: when the `PEERBIT_STREAM_RUST_CORE` env flag is
|
|
677
|
+
* set, DirectStream instances constructed without an explicit `rustCore`
|
|
678
|
+
* option pick up the core installed on globalThis under this key. This lets
|
|
679
|
+
* the full @peerbit/stream test-suite run unmodified against the native core
|
|
680
|
+
* (`rustCore: false` opts a specific instance out).
|
|
681
|
+
*/
|
|
682
|
+
export const RUST_CORE_GLOBAL_KEY = "__peerbitStreamRustCore";
|
|
683
|
+
|
|
684
|
+
export const resolveInjectedRustCore = (): RustCoreStream | undefined => {
|
|
685
|
+
const processLike = (
|
|
686
|
+
globalThis as {
|
|
687
|
+
process?: { env?: Record<string, string | undefined> };
|
|
688
|
+
}
|
|
689
|
+
).process;
|
|
690
|
+
if (!processLike?.env?.PEERBIT_STREAM_RUST_CORE) {
|
|
691
|
+
return undefined;
|
|
692
|
+
}
|
|
693
|
+
return (globalThis as Record<string, unknown>)[RUST_CORE_GLOBAL_KEY] as
|
|
694
|
+
| RustCoreStream
|
|
695
|
+
| undefined;
|
|
696
|
+
};
|