@genkaku/protocol 0.1.11 → 0.1.13
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/dial.d.ts +13 -0
- package/dist/dial.d.ts.map +1 -1
- package/dist/dial.js +53 -24
- package/package.json +1 -1
package/dist/dial.d.ts
CHANGED
|
@@ -5,6 +5,15 @@ import type { OpenEnvelope } from './workerSession.ts';
|
|
|
5
5
|
/** Direct dials before a worker's address is considered unreachable and the
|
|
6
6
|
* seed-VM relay path is preferred for subsequent sessions. */
|
|
7
7
|
export declare const DIRECT_ATTEMPTS_BEFORE_RELAY = 3;
|
|
8
|
+
/** A circuit-relayed connection carries a relay-imposed byte/duration limit, so
|
|
9
|
+
* libp2p marks it "limited" and refuses new streams unless the caller opts in.
|
|
10
|
+
* Every GenKaKu protocol is application data and must opt in; on a direct
|
|
11
|
+
* connection the flag is ignored.
|
|
12
|
+
*
|
|
13
|
+
* The timeout is per call — sharing one AbortSignal would abort every dial made
|
|
14
|
+
* after the module's first five seconds. An unreachable peer must not stall a
|
|
15
|
+
* marketplace listing behind a TCP timeout. */
|
|
16
|
+
export declare const DIAL_TIMEOUT_MS = 5000;
|
|
8
17
|
export type DialRoute = 'direct' | 'relay';
|
|
9
18
|
/** Build `/p2p-circuit` addresses for `peerId` from the relays the seed handed
|
|
10
19
|
* out. The relay hop keeps its own `/p2p/<id>`; ours is appended last. */
|
|
@@ -42,6 +51,10 @@ export declare function dialWorkerAny(node: Libp2p, addr: string, opts?: {
|
|
|
42
51
|
route: DialRoute;
|
|
43
52
|
addr: string;
|
|
44
53
|
}>;
|
|
54
|
+
/** Open (or reuse) a connection to a relay hop. The circuit transport only
|
|
55
|
+
* reserves a slot while a HOP-capable peer is connected, so a seed restart
|
|
56
|
+
* needs this again with the seed's new peer id. */
|
|
57
|
+
export declare function connectRelay(node: Libp2p, relay: string): void;
|
|
45
58
|
/** Fetch + deserialize a worker's offer board (one dial, whole-board read). */
|
|
46
59
|
export declare function fetchOffers(node: Libp2p, addr: string): Promise<Offer[]>;
|
|
47
60
|
/** P4.5 seed discovery: ask a bootstrap seed which peers it currently sees.
|
package/dist/dial.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dial.d.ts","sourceRoot":"","sources":["../src/dial.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEpC,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAEnE,OAAO,EAAY,KAAK,KAAK,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAQtD;+DAC+D;AAC/D,eAAO,MAAM,4BAA4B,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"dial.d.ts","sourceRoot":"","sources":["../src/dial.ts"],"names":[],"mappings":"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"}
|
package/dist/dial.js
CHANGED
|
@@ -22,8 +22,15 @@ const directFailures = new Map();
|
|
|
22
22
|
/** A circuit-relayed connection carries a relay-imposed byte/duration limit, so
|
|
23
23
|
* libp2p marks it "limited" and refuses new streams unless the caller opts in.
|
|
24
24
|
* Every GenKaKu protocol is application data and must opt in; on a direct
|
|
25
|
-
* connection the flag is ignored.
|
|
26
|
-
|
|
25
|
+
* connection the flag is ignored.
|
|
26
|
+
*
|
|
27
|
+
* The timeout is per call — sharing one AbortSignal would abort every dial made
|
|
28
|
+
* after the module's first five seconds. An unreachable peer must not stall a
|
|
29
|
+
* marketplace listing behind a TCP timeout. */
|
|
30
|
+
export const DIAL_TIMEOUT_MS = 5_000;
|
|
31
|
+
function streamOpts(timeoutMs = DIAL_TIMEOUT_MS) {
|
|
32
|
+
return { signal: AbortSignal.timeout(timeoutMs), runOnLimitedConnection: true };
|
|
33
|
+
}
|
|
27
34
|
/** Build `/p2p-circuit` addresses for `peerId` from the relays the seed handed
|
|
28
35
|
* out. The relay hop keeps its own `/p2p/<id>`; ours is appended last. */
|
|
29
36
|
export function circuitAddrsFor(relays, peerId) {
|
|
@@ -121,7 +128,7 @@ export async function dialWorker(node, addr) {
|
|
|
121
128
|
}
|
|
122
129
|
return {
|
|
123
130
|
async open(env) {
|
|
124
|
-
openStream = await node.dialProtocol(ma, '/genkaku/open/0',
|
|
131
|
+
openStream = await node.dialProtocol(ma, '/genkaku/open/0', streamOpts());
|
|
125
132
|
// errors surface via the read side
|
|
126
133
|
openSinkDone = openStream.sink(oq.source()).catch(() => { });
|
|
127
134
|
oq.push(lpEncode(env));
|
|
@@ -155,7 +162,7 @@ export async function dialWorker(node, addr) {
|
|
|
155
162
|
onError(cb) { errCbs.add(cb); },
|
|
156
163
|
async sendReceipt(jobId, seq, amount, sig = '', inputHash = ZERO_HASH, outputHash = ZERO_HASH) {
|
|
157
164
|
if (!receiptStream) {
|
|
158
|
-
receiptStream = await node.dialProtocol(ma, '/genkaku/receipt/0',
|
|
165
|
+
receiptStream = await node.dialProtocol(ma, '/genkaku/receipt/0', streamOpts());
|
|
159
166
|
receiptSinkDone = receiptStream.sink(rq.source()).catch(() => { });
|
|
160
167
|
}
|
|
161
168
|
rq.push(lpEncode({
|
|
@@ -183,7 +190,7 @@ export async function dialWorker(node, addr) {
|
|
|
183
190
|
export async function helloWorker(node, addr) {
|
|
184
191
|
const expectedPeer = peerIdOf(addr);
|
|
185
192
|
const nonce = newNonce();
|
|
186
|
-
const stream = await node.dialProtocol(multiaddr(addr), '/genkaku/hello/0',
|
|
193
|
+
const stream = await node.dialProtocol(multiaddr(addr), '/genkaku/hello/0', streamOpts());
|
|
187
194
|
let reply;
|
|
188
195
|
try {
|
|
189
196
|
stream.sink([lpEncode({ proto: 'hello/0', nonce })]).catch(() => { });
|
|
@@ -278,6 +285,14 @@ export async function dialWorkerAny(node, addr, opts = {}) {
|
|
|
278
285
|
}
|
|
279
286
|
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
280
287
|
}
|
|
288
|
+
/** Open (or reuse) a connection to a relay hop. The circuit transport only
|
|
289
|
+
* reserves a slot while a HOP-capable peer is connected, so a seed restart
|
|
290
|
+
* needs this again with the seed's new peer id. */
|
|
291
|
+
export function connectRelay(node, relay) {
|
|
292
|
+
if (!relay.startsWith('/'))
|
|
293
|
+
return;
|
|
294
|
+
void node.dial(multiaddr(relay)).catch(() => { });
|
|
295
|
+
}
|
|
281
296
|
/** Fetch + deserialize a worker's offer board (one dial, whole-board read). */
|
|
282
297
|
export async function fetchOffers(node, addr) {
|
|
283
298
|
const offers = await fetchOfferBoard(node, addr);
|
|
@@ -300,7 +315,7 @@ export async function fetchOffers(node, addr) {
|
|
|
300
315
|
});
|
|
301
316
|
}
|
|
302
317
|
async function fetchOfferBoard(node, addr) {
|
|
303
|
-
const s = await node.dialProtocol(multiaddr(addr), '/genkaku/offers/0',
|
|
318
|
+
const s = await node.dialProtocol(multiaddr(addr), '/genkaku/offers/0', streamOpts());
|
|
304
319
|
const reader = new FrameReader();
|
|
305
320
|
let board = [];
|
|
306
321
|
for await (const chunk of s.source) {
|
|
@@ -327,7 +342,7 @@ export async function fetchSeedPeers(node, addr) {
|
|
|
327
342
|
// takes the native path.
|
|
328
343
|
if (addr.startsWith('http://') || addr.startsWith('https://')) {
|
|
329
344
|
try {
|
|
330
|
-
const res = await fetch(`${addr.replace(/\/$/, '')}/peers
|
|
345
|
+
const res = await fetch(`${addr.replace(/\/$/, '')}/peers`, { signal: AbortSignal.timeout(DIAL_TIMEOUT_MS) });
|
|
331
346
|
if (!res.ok)
|
|
332
347
|
return [];
|
|
333
348
|
const body = (await res.json());
|
|
@@ -339,7 +354,7 @@ export async function fetchSeedPeers(node, addr) {
|
|
|
339
354
|
return [];
|
|
340
355
|
}
|
|
341
356
|
}
|
|
342
|
-
const s = await node.dialProtocol(multiaddr(addr), '/genkaku/peers/0',
|
|
357
|
+
const s = await node.dialProtocol(multiaddr(addr), '/genkaku/peers/0', streamOpts());
|
|
343
358
|
const reader = new FrameReader();
|
|
344
359
|
for await (const chunk of s.source) {
|
|
345
360
|
reader.push(chunk);
|
|
@@ -358,7 +373,7 @@ export async function fetchSeedPeers(node, addr) {
|
|
|
358
373
|
export async function fetchSeedRelays(node, seed) {
|
|
359
374
|
if (seed.startsWith('http://') || seed.startsWith('https://')) {
|
|
360
375
|
try {
|
|
361
|
-
const res = await fetch(`${seed.replace(/\/$/, '')}/peers
|
|
376
|
+
const res = await fetch(`${seed.replace(/\/$/, '')}/peers`, { signal: AbortSignal.timeout(DIAL_TIMEOUT_MS) });
|
|
362
377
|
if (!res.ok)
|
|
363
378
|
return [];
|
|
364
379
|
const body = (await res.json());
|
|
@@ -373,7 +388,7 @@ export async function fetchSeedRelays(node, seed) {
|
|
|
373
388
|
if (node == null)
|
|
374
389
|
return [];
|
|
375
390
|
try {
|
|
376
|
-
const s = await node.dialProtocol(multiaddr(seed), '/genkaku/peers/0',
|
|
391
|
+
const s = await node.dialProtocol(multiaddr(seed), '/genkaku/peers/0', streamOpts());
|
|
377
392
|
const reader = new FrameReader();
|
|
378
393
|
for await (const chunk of s.source) {
|
|
379
394
|
reader.push(chunk);
|
|
@@ -401,7 +416,7 @@ export async function fetchSeedRelays(node, seed) {
|
|
|
401
416
|
* digest JobEscrow.settle recovers against the session's worker address.
|
|
402
417
|
*/
|
|
403
418
|
export async function requestSettleCosign(node, addr, args) {
|
|
404
|
-
const s = await node.dialProtocol(multiaddr(addr), '/genkaku/settle/0',
|
|
419
|
+
const s = await node.dialProtocol(multiaddr(addr), '/genkaku/settle/0', streamOpts());
|
|
405
420
|
const reader = new FrameReader();
|
|
406
421
|
let reply = null;
|
|
407
422
|
const sinkDone = s.sink([lpEncode({
|
|
@@ -435,20 +450,34 @@ export async function requestSettleCosign(node, addr, args) {
|
|
|
435
450
|
export async function announceToSeed(node, seed, addrs) {
|
|
436
451
|
if (addrs.length === 0)
|
|
437
452
|
return false;
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
453
|
+
// A seed may be configured as a URL (the shipped default): its peer id
|
|
454
|
+
// changes on restart, so the address to dial is whatever it reports right
|
|
455
|
+
// now. `relay` is the seed's own address; `peers` are workers, never dial
|
|
456
|
+
// those for an announcement.
|
|
457
|
+
const targets = seed.startsWith('http://') || seed.startsWith('https://')
|
|
458
|
+
? await fetchSeedRelays(node, seed)
|
|
459
|
+
: [seed];
|
|
460
|
+
for (const target of targets) {
|
|
461
|
+
try {
|
|
462
|
+
const s = await node.dialProtocol(multiaddr(target), '/genkaku/announce/0', streamOpts());
|
|
463
|
+
try {
|
|
464
|
+
s.sink([lpEncode({ proto: 'announce/0', addrs })]).catch(() => { });
|
|
465
|
+
const reader = new FrameReader();
|
|
466
|
+
for await (const chunk of s.source) {
|
|
467
|
+
reader.push(chunk);
|
|
468
|
+
const f = reader.next();
|
|
469
|
+
if (f?.proto === 'announced/0' && f.ok === true)
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
finally {
|
|
474
|
+
await s.close().catch(() => { });
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
catch {
|
|
478
|
+
// try the next address the URL reported
|
|
447
479
|
}
|
|
448
|
-
return false;
|
|
449
|
-
}
|
|
450
|
-
finally {
|
|
451
|
-
await s.close().catch(() => { });
|
|
452
480
|
}
|
|
481
|
+
return false;
|
|
453
482
|
}
|
|
454
483
|
//# sourceMappingURL=dial.js.map
|
package/package.json
CHANGED