@leofcoin/chain 1.10.16 → 1.10.18
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/exports/beacon-envelope.js +6 -6
- package/exports/beacon-epoch.js +1 -1
- package/exports/beacon-lifecycle.js +1 -1
- package/exports/beacon-round.js +1 -1
- package/exports/beacon.js +15 -14
- package/exports/browser/_commonjsHelpers-B85MJLTf.js +5 -0
- package/exports/browser/beacon-envelope.js +61 -150
- package/exports/browser/beacon-epoch.js +2 -2
- package/exports/browser/beacon-lifecycle.js +3 -3
- package/exports/browser/beacon-round.js +2 -2
- package/exports/browser/beacon-wire.js +3 -3
- package/exports/browser/beacon.js +2483 -1228
- package/exports/browser/{browser-CCfR9KOM-CvhDZrGu.js → browser-CCfR9KOM-CpStHgTj.js} +4 -4
- package/exports/browser/{browser-crypto-CeE-yId5.js → browser-crypto-CH0ua22L.js} +1 -1
- package/exports/browser/chain.js +151 -81
- package/exports/browser/{client-CAC7RVMf-Dmz_2A_5.js → client-C_pBoi1g-_pfKzCvX.js} +256 -80
- package/exports/browser/{connection-monitor-Cmv00mwl.js → connection-monitor-D-krNiRH.js} +1 -1
- package/exports/browser/{hkdf-CnZvwpZ9.js → hkdf-BUHINPFj.js} +2 -94
- package/exports/browser/{index-BC-KRBgE.js → index-DmuI-29u.js} +1 -1
- package/exports/browser/{index-dTQVgkpf-CuHJWO2l.js → index-dTQVgkpf-BbdshWB0.js} +4 -4
- package/exports/browser/index.browser-CFfJpgKV.js +857 -0
- package/exports/browser/{messages-Dw86z0zq-DrPw_nlZ.js → messages-BGHaihSi-eHZVl0y9.js} +4 -4
- package/exports/browser/{node-browser-DWSdi-XP.js → node-browser-BNe-en1l.js} +5 -5
- package/exports/browser/node-browser.js +4 -4
- package/exports/browser/{sha2-piimb6xL.js → sha2-BKcEJzgd.js} +144 -3
- package/exports/browser/weierstrass-BVfhtHbl.js +3596 -0
- package/exports/browser/workers/machine-worker.js +61 -19
- package/exports/chain.js +146 -73
- package/exports/workers/machine-worker.js +61 -19
- package/package.json +14 -13
- package/exports/browser/weierstrass-Q0QND1ZT.js +0 -2156
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { i as inflate_1, c as createDebugger, d as deflate_1, L as LittlePubSub } from './node-browser-
|
|
2
|
-
import './browser-crypto-
|
|
3
|
-
import './connection-monitor-
|
|
1
|
+
import { i as inflate_1, c as createDebugger, d as deflate_1, L as LittlePubSub } from './node-browser-BNe-en1l.js';
|
|
2
|
+
import './browser-crypto-CH0ua22L.js';
|
|
3
|
+
import './connection-monitor-D-krNiRH.js';
|
|
4
4
|
import './index-CvKt4UDE.js';
|
|
5
|
-
import './sha2-
|
|
5
|
+
import './sha2-BKcEJzgd.js';
|
|
6
6
|
|
|
7
7
|
class Api {
|
|
8
8
|
_pubsub;
|
|
@@ -233,7 +233,7 @@ class SocketRequestClient {
|
|
|
233
233
|
const init = async () => {
|
|
234
234
|
// @ts-ignore
|
|
235
235
|
if (!globalThis.WebSocket && !this.#experimentalWebsocket)
|
|
236
|
-
globalThis.WebSocket = (await import('./browser-CCfR9KOM-
|
|
236
|
+
globalThis.WebSocket = (await import('./browser-CCfR9KOM-CpStHgTj.js').then(function (n) { return n.b; })).default.w3cwebsocket;
|
|
237
237
|
const client = new WebSocket(this.#url, this.#protocol);
|
|
238
238
|
if (this.#experimentalWebsocket) {
|
|
239
239
|
client.addEventListener('error', this.onerror);
|
|
@@ -820,8 +820,61 @@ class WebRTCPeer {
|
|
|
820
820
|
}
|
|
821
821
|
}
|
|
822
822
|
|
|
823
|
-
|
|
823
|
+
// WebTransport streams carry bytes, not application message boundaries.
|
|
824
|
+
const MAX_FRAME_BYTES = 64 * 1024;
|
|
825
|
+
const encodeFrame = (payload) => {
|
|
826
|
+
if (!(payload instanceof Uint8Array) || !payload.length || payload.length > MAX_FRAME_BYTES) {
|
|
827
|
+
throw new Error('invalid transport frame length');
|
|
828
|
+
}
|
|
829
|
+
const frame = new Uint8Array(payload.length + 4);
|
|
830
|
+
new DataView(frame.buffer).setUint32(0, payload.length);
|
|
831
|
+
frame.set(payload, 4);
|
|
832
|
+
return frame;
|
|
833
|
+
};
|
|
834
|
+
class FrameReader {
|
|
835
|
+
constructor(reader) { this.reader = reader; this.chunk = new Uint8Array(); this.offset = 0; }
|
|
836
|
+
async exact(length, allowEnd = false) {
|
|
837
|
+
const result = new Uint8Array(length);
|
|
838
|
+
let written = 0;
|
|
839
|
+
while (written < length) {
|
|
840
|
+
if (this.offset === this.chunk.length) {
|
|
841
|
+
const { done, value } = await this.reader.read();
|
|
842
|
+
if (done) {
|
|
843
|
+
if (allowEnd && written === 0)
|
|
844
|
+
return null;
|
|
845
|
+
throw new Error('truncated transport frame');
|
|
846
|
+
}
|
|
847
|
+
this.chunk = value;
|
|
848
|
+
this.offset = 0;
|
|
849
|
+
if (!value?.length)
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
const count = Math.min(length - written, this.chunk.length - this.offset);
|
|
853
|
+
result.set(this.chunk.subarray(this.offset, this.offset + count), written);
|
|
854
|
+
this.offset += count;
|
|
855
|
+
written += count;
|
|
856
|
+
}
|
|
857
|
+
return result;
|
|
858
|
+
}
|
|
859
|
+
async read() {
|
|
860
|
+
const header = await this.exact(4, true);
|
|
861
|
+
if (!header)
|
|
862
|
+
return null;
|
|
863
|
+
const length = new DataView(header.buffer).getUint32(0);
|
|
864
|
+
if (!length || length > MAX_FRAME_BYTES)
|
|
865
|
+
throw new Error('invalid transport frame length');
|
|
866
|
+
return this.exact(length);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
const jsonBytes = (value) => new TextEncoder().encode(JSON.stringify(value));
|
|
870
|
+
const parseJson = (bytes) => JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
|
|
871
|
+
|
|
872
|
+
const getWebTransportCtor = async () => {
|
|
824
873
|
const candidate = globalThis;
|
|
874
|
+
if (!candidate.WebTransport && candidate.process?.versions?.node) {
|
|
875
|
+
const { WebTransport } = await import('./index.browser-CFfJpgKV.js');
|
|
876
|
+
return WebTransport;
|
|
877
|
+
}
|
|
825
878
|
if (!candidate.WebTransport) {
|
|
826
879
|
throw new Error('WebTransport is not available in this runtime');
|
|
827
880
|
}
|
|
@@ -855,7 +908,12 @@ class WebTransportPeer {
|
|
|
855
908
|
kind: 'webtransport-bidi',
|
|
856
909
|
isConnected: () => this.connected,
|
|
857
910
|
sendRaw: (payload) => {
|
|
858
|
-
void this.#sendRaw(payload)
|
|
911
|
+
void this.#sendRaw(payload).catch(error => {
|
|
912
|
+
if (!this.#destroyed) {
|
|
913
|
+
this.#emit('error', error);
|
|
914
|
+
this.destroy();
|
|
915
|
+
}
|
|
916
|
+
});
|
|
859
917
|
}
|
|
860
918
|
}, {
|
|
861
919
|
maxMessageSize: MAX_MESSAGE_SIZE,
|
|
@@ -866,7 +924,7 @@ class WebTransportPeer {
|
|
|
866
924
|
}
|
|
867
925
|
});
|
|
868
926
|
queueMicrotask(() => {
|
|
869
|
-
void this.#open(options
|
|
927
|
+
void this.#open(options);
|
|
870
928
|
});
|
|
871
929
|
}
|
|
872
930
|
#createMessageId() {
|
|
@@ -893,41 +951,55 @@ class WebTransportPeer {
|
|
|
893
951
|
for (const handler of listeners)
|
|
894
952
|
handler(...args);
|
|
895
953
|
}
|
|
896
|
-
async #open(
|
|
954
|
+
async #open(options) {
|
|
897
955
|
try {
|
|
898
|
-
const
|
|
899
|
-
|
|
956
|
+
const ticket = await options.getTicket();
|
|
957
|
+
if (this.#destroyed)
|
|
958
|
+
return;
|
|
959
|
+
const WebTransportCtor = await getWebTransportCtor();
|
|
960
|
+
const session = new WebTransportCtor(options.url);
|
|
900
961
|
this.#session = session;
|
|
962
|
+
void session.closed.then(() => this.destroy(), error => {
|
|
963
|
+
if (!this.#destroyed) {
|
|
964
|
+
this.#emit('error', error);
|
|
965
|
+
this.destroy();
|
|
966
|
+
}
|
|
967
|
+
});
|
|
901
968
|
await session.ready;
|
|
969
|
+
if (this.#destroyed)
|
|
970
|
+
return;
|
|
902
971
|
const stream = (await session.createBidirectionalStream());
|
|
972
|
+
if (this.#destroyed)
|
|
973
|
+
return;
|
|
903
974
|
this.#reader = stream.readable.getReader();
|
|
904
975
|
this.#writer = stream.writable.getWriter();
|
|
976
|
+
const frames = new FrameReader(this.#reader);
|
|
977
|
+
await this.#writer.write(encodeFrame(jsonBytes({ protocol: 'swarm-relay/1', ticket })));
|
|
978
|
+
const ready = parseJson(await frames.read());
|
|
979
|
+
if (ready.protocol !== 'swarm-relay/1' || ready.peerId !== this.peerId || String(ready.version) !== this.version) {
|
|
980
|
+
throw new Error('invalid WebTransport relay handshake');
|
|
981
|
+
}
|
|
982
|
+
if (this.#destroyed)
|
|
983
|
+
return;
|
|
905
984
|
this.#connected = true;
|
|
906
985
|
this.#emit('connect');
|
|
907
|
-
void this.#readLoop();
|
|
908
|
-
void session.closed.catch((error) => {
|
|
909
|
-
if (this.#destroyed)
|
|
910
|
-
return;
|
|
911
|
-
this.#emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
912
|
-
});
|
|
986
|
+
void this.#readLoop(frames);
|
|
913
987
|
}
|
|
914
988
|
catch (error) {
|
|
915
989
|
this.#emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
916
990
|
this.destroy();
|
|
917
991
|
}
|
|
918
992
|
}
|
|
919
|
-
async #readLoop() {
|
|
993
|
+
async #readLoop(frames) {
|
|
920
994
|
const reader = this.#reader;
|
|
921
995
|
if (!reader)
|
|
922
996
|
return;
|
|
923
997
|
try {
|
|
924
998
|
while (!this.#destroyed) {
|
|
925
999
|
// eslint-disable-next-line no-await-in-loop
|
|
926
|
-
const
|
|
927
|
-
if (done)
|
|
928
|
-
break;
|
|
1000
|
+
const value = await frames.read();
|
|
929
1001
|
if (!value)
|
|
930
|
-
|
|
1002
|
+
break;
|
|
931
1003
|
this.bw.down += value.length;
|
|
932
1004
|
this.#emit('data', value);
|
|
933
1005
|
}
|
|
@@ -943,7 +1015,7 @@ class WebTransportPeer {
|
|
|
943
1015
|
async #sendRaw(payload) {
|
|
944
1016
|
if (!this.#writer)
|
|
945
1017
|
throw new Error('WebTransport writer is not ready');
|
|
946
|
-
await this.#writer.write(payload);
|
|
1018
|
+
await this.#writer.write(encodeFrame(payload));
|
|
947
1019
|
}
|
|
948
1020
|
on(event, handler) {
|
|
949
1021
|
const listeners = this.#listeners.get(event) ?? new Set();
|
|
@@ -973,13 +1045,13 @@ class WebTransportPeer {
|
|
|
973
1045
|
this.#destroyed = true;
|
|
974
1046
|
this.#connected = false;
|
|
975
1047
|
try {
|
|
976
|
-
void this.#reader?.cancel?.();
|
|
1048
|
+
void this.#reader?.cancel?.().catch(() => { });
|
|
977
1049
|
}
|
|
978
1050
|
catch (e) { }
|
|
979
1051
|
this.#reader?.releaseLock?.();
|
|
980
1052
|
this.#reader = null;
|
|
981
1053
|
try {
|
|
982
|
-
void this.#writer?.close?.();
|
|
1054
|
+
void this.#writer?.close?.().catch(() => { });
|
|
983
1055
|
}
|
|
984
1056
|
catch (e) { }
|
|
985
1057
|
this.#writer?.releaseLock?.();
|
|
@@ -1007,6 +1079,7 @@ class CircuitPeer {
|
|
|
1007
1079
|
#destroyed = false;
|
|
1008
1080
|
#connected = false;
|
|
1009
1081
|
#sendViaCircuit;
|
|
1082
|
+
#core;
|
|
1010
1083
|
initiator = true;
|
|
1011
1084
|
peerId;
|
|
1012
1085
|
channelName;
|
|
@@ -1020,12 +1093,40 @@ class CircuitPeer {
|
|
|
1020
1093
|
this.channelName = `circuit:${options.from}:${options.to}`;
|
|
1021
1094
|
this.version = String(options.version);
|
|
1022
1095
|
this.#sendViaCircuit = options.sendViaCircuit;
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1096
|
+
this.#core = new PeerCore({
|
|
1097
|
+
kind: 'circuit',
|
|
1098
|
+
isConnected: () => this.connected,
|
|
1099
|
+
sendRaw: data => {
|
|
1100
|
+
void this.#sendViaCircuit({ id: this.#createMessageId(), data: Array.from(data) }).catch(error => {
|
|
1101
|
+
if (this.#destroyed)
|
|
1102
|
+
return;
|
|
1103
|
+
this.#emit('error', error);
|
|
1104
|
+
this.destroy();
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
}, {
|
|
1108
|
+
// JSON byte arrays expand up to four characters per byte. Keep the whole
|
|
1109
|
+
// WebSocket frame below its default 64 KiB limit, including wrapper/ID.
|
|
1110
|
+
maxMessageSize: 14_000,
|
|
1111
|
+
compressionThreshold: 0.98,
|
|
1112
|
+
getPubSub,
|
|
1113
|
+
onPayloadSend: bytes => { this.bw.up += bytes; }
|
|
1114
|
+
});
|
|
1115
|
+
queueMicrotask(async () => {
|
|
1116
|
+
try {
|
|
1117
|
+
await options.handshake();
|
|
1118
|
+
if (this.#destroyed)
|
|
1119
|
+
return;
|
|
1120
|
+
this.#connected = true;
|
|
1121
|
+
this.#emit('connect');
|
|
1122
|
+
}
|
|
1123
|
+
catch (error) {
|
|
1124
|
+
if (this.#destroyed)
|
|
1125
|
+
return;
|
|
1126
|
+
this.#emit('error', error);
|
|
1127
|
+
this.destroy();
|
|
1128
|
+
}
|
|
1129
|
+
});
|
|
1029
1130
|
}
|
|
1030
1131
|
#createMessageId() {
|
|
1031
1132
|
const randomUUID = globalThis.crypto?.randomUUID;
|
|
@@ -1055,43 +1156,21 @@ class CircuitPeer {
|
|
|
1055
1156
|
// Circuit transport does not use SDP/ICE signaling.
|
|
1056
1157
|
}
|
|
1057
1158
|
send(data, id = this.#createMessageId()) {
|
|
1159
|
+
if (new TextEncoder().encode(id).length > 1024) {
|
|
1160
|
+
this.#emit('error', new Error('circuit message id exceeds 1024 bytes'));
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1058
1163
|
if (this.#destroyed) {
|
|
1059
1164
|
this.#emit('error', new Error('circuit peer is destroyed'));
|
|
1060
1165
|
return;
|
|
1061
1166
|
}
|
|
1062
|
-
this.
|
|
1063
|
-
void this.#sendViaCircuit({ id, data: Array.from(data) }).catch((error) => {
|
|
1064
|
-
this.#emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
1065
|
-
});
|
|
1167
|
+
this.#core.send(data, id);
|
|
1066
1168
|
}
|
|
1067
1169
|
request(data, id = this.#createMessageId()) {
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
return Promise.reject(new Error('globalThis.pubsub is not available'));
|
|
1170
|
+
if (new TextEncoder().encode(id).length > 1024) {
|
|
1171
|
+
return Promise.reject(new Error('circuit message id exceeds 1024 bytes'));
|
|
1071
1172
|
}
|
|
1072
|
-
return
|
|
1073
|
-
let timeout;
|
|
1074
|
-
let settled = false;
|
|
1075
|
-
const finish = (fn) => {
|
|
1076
|
-
if (settled)
|
|
1077
|
-
return;
|
|
1078
|
-
settled = true;
|
|
1079
|
-
clearTimeout(timeout);
|
|
1080
|
-
try {
|
|
1081
|
-
pubsub.unsubscribe(id, onResponse);
|
|
1082
|
-
}
|
|
1083
|
-
catch (e) { }
|
|
1084
|
-
fn();
|
|
1085
|
-
};
|
|
1086
|
-
const onResponse = ({ data: response }) => {
|
|
1087
|
-
finish(() => resolve(response));
|
|
1088
|
-
};
|
|
1089
|
-
timeout = setTimeout(() => {
|
|
1090
|
-
finish(() => reject(new Error(`request for ${id} timed out`)));
|
|
1091
|
-
}, 30_000);
|
|
1092
|
-
pubsub.subscribe(id, onResponse);
|
|
1093
|
-
this.send(data, id);
|
|
1094
|
-
});
|
|
1173
|
+
return this.#core.request(data, id);
|
|
1095
1174
|
}
|
|
1096
1175
|
async getNetworkStats() {
|
|
1097
1176
|
return null;
|
|
@@ -1164,6 +1243,8 @@ class Client {
|
|
|
1164
1243
|
#fallbackCircuitMethod = 'swarm:fallback:send';
|
|
1165
1244
|
#testHooks;
|
|
1166
1245
|
#webTransportUrlTemplate;
|
|
1246
|
+
#discoverWebTransport = true;
|
|
1247
|
+
#relayUrls = new WeakMap();
|
|
1167
1248
|
#circuitHandlers = new Map();
|
|
1168
1249
|
#pendingCircuitRequests = new Map();
|
|
1169
1250
|
#circuitRequestTimeoutMs = 30_000;
|
|
@@ -1202,7 +1283,9 @@ class Client {
|
|
|
1202
1283
|
? options.transport.kinds
|
|
1203
1284
|
: options.transport?.kind
|
|
1204
1285
|
? [options.transport.kind]
|
|
1205
|
-
:
|
|
1286
|
+
: (options.transport?.webtransport?.urlTemplate
|
|
1287
|
+
? ['webrtc', 'webtransport']
|
|
1288
|
+
: ['webrtc']);
|
|
1206
1289
|
this.#supportedTransports = new Set(this.#normalizeTransportKinds(configuredKinds));
|
|
1207
1290
|
if (!this.#supportedTransports.size)
|
|
1208
1291
|
this.#supportedTransports.add('webrtc');
|
|
@@ -1213,6 +1296,11 @@ class Client {
|
|
|
1213
1296
|
? 'webrtc'
|
|
1214
1297
|
: 'webtransport';
|
|
1215
1298
|
this.#webTransportUrlTemplate = options.transport?.webtransport?.urlTemplate;
|
|
1299
|
+
this.#discoverWebTransport = !options.transport?.kind && !options.transport?.kinds ||
|
|
1300
|
+
!!options.transport?.kinds?.includes('webtransport') || options.transport?.kind === 'webtransport';
|
|
1301
|
+
if (this.#discoverWebTransport && (typeof globalThis.WebTransport === 'function' || globalThis.process?.versions?.node)) {
|
|
1302
|
+
this.#supportedTransports.add('webtransport');
|
|
1303
|
+
}
|
|
1216
1304
|
const wrtcBackend = options.transport?.webrtc?.backend ||
|
|
1217
1305
|
globalThis.process?.env?.NETPEER_SWARM_WRTC_BACKEND ||
|
|
1218
1306
|
'vandeurenglenn';
|
|
@@ -1230,6 +1318,9 @@ class Client {
|
|
|
1230
1318
|
if (options?.retry)
|
|
1231
1319
|
this.#retryOptions = { ...this.#retryOptions, ...options.retry };
|
|
1232
1320
|
this.#circuitHandlers.set(this.#fallbackCircuitMethod, (payload, context) => this.#handleFallbackCircuitPayload(payload, context));
|
|
1321
|
+
this.#circuitHandlers.set('swarm:fallback:hello', () => ({
|
|
1322
|
+
peerId: this.peerId, version: this.version, encoding: 'peer-core/1'
|
|
1323
|
+
}));
|
|
1233
1324
|
if (!this.#testHooks?.skipInit) {
|
|
1234
1325
|
this._init();
|
|
1235
1326
|
}
|
|
@@ -1368,6 +1459,30 @@ class Client {
|
|
|
1368
1459
|
const onServerData = (message) => {
|
|
1369
1460
|
globalThis.pubsub.publish('server:data', message);
|
|
1370
1461
|
};
|
|
1462
|
+
const onRelayReady = (message) => {
|
|
1463
|
+
if (!this.#discoverWebTransport || message?.protocol !== 'swarm-relay/1' || typeof message.url !== 'string')
|
|
1464
|
+
return;
|
|
1465
|
+
let url;
|
|
1466
|
+
try {
|
|
1467
|
+
url = new URL(message.url);
|
|
1468
|
+
}
|
|
1469
|
+
catch {
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
if (url.protocol !== 'https:' || url.username || url.password || url.hash)
|
|
1473
|
+
return;
|
|
1474
|
+
if (this.#relayUrls.get(starConnection) === url.href)
|
|
1475
|
+
return;
|
|
1476
|
+
this.#relayUrls.set(starConnection, url.href);
|
|
1477
|
+
this.#supportedTransports.add('webtransport');
|
|
1478
|
+
// Update capabilities on this same authenticated star connection. The
|
|
1479
|
+
// server sends relay metadata before its peer snapshot, so fallback can
|
|
1480
|
+
// resolve a real endpoint without users configuring transport URLs.
|
|
1481
|
+
starConnection.send({ url: 'join', params: {
|
|
1482
|
+
version: this.version, peerId: this.peerId,
|
|
1483
|
+
transport: { kind: this.#preferredTransportKind, kinds: [...this.#supportedTransports] }
|
|
1484
|
+
} });
|
|
1485
|
+
};
|
|
1371
1486
|
starConnection.pubsub.subscribe('peer:joined', onPeerJoined);
|
|
1372
1487
|
starConnection.pubsub.subscribe('peer:left', onPeerLeft);
|
|
1373
1488
|
starConnection.pubsub.subscribe('star:joined', onStarJoined);
|
|
@@ -1375,6 +1490,7 @@ class Client {
|
|
|
1375
1490
|
starConnection.pubsub.subscribe('signal', onSignal);
|
|
1376
1491
|
starConnection.pubsub.subscribe('circuit', onCircuit);
|
|
1377
1492
|
starConnection.pubsub.subscribe('server:data', onServerData);
|
|
1493
|
+
starConnection.pubsub.subscribe('relay:ready', onRelayReady);
|
|
1378
1494
|
this.#starListeners[starId] = [
|
|
1379
1495
|
{ topic: 'peer:joined', handler: onPeerJoined },
|
|
1380
1496
|
{ topic: 'peer:left', handler: onPeerLeft },
|
|
@@ -1382,7 +1498,8 @@ class Client {
|
|
|
1382
1498
|
{ topic: 'star:left', handler: onStarLeft },
|
|
1383
1499
|
{ topic: 'signal', handler: onSignal },
|
|
1384
1500
|
{ topic: 'circuit', handler: onCircuit },
|
|
1385
|
-
{ topic: 'server:data', handler: onServerData }
|
|
1501
|
+
{ topic: 'server:data', handler: onServerData },
|
|
1502
|
+
{ topic: 'relay:ready', handler: onRelayReady }
|
|
1386
1503
|
];
|
|
1387
1504
|
}
|
|
1388
1505
|
#starJoined = (id) => {
|
|
@@ -1588,12 +1705,12 @@ class Client {
|
|
|
1588
1705
|
peer = this.#createRTCPeerConnection(peerId, attempt.star, attempt.version, attempt.initiator);
|
|
1589
1706
|
}
|
|
1590
1707
|
else if (transportKind === 'webtransport') {
|
|
1591
|
-
const url = this.#resolveWebTransportUrl(peerId);
|
|
1708
|
+
const url = this.#resolveWebTransportUrl(peerId, attempt.star);
|
|
1592
1709
|
if (!url) {
|
|
1593
1710
|
this.#advanceTransportAttempt(peerId);
|
|
1594
1711
|
return;
|
|
1595
1712
|
}
|
|
1596
|
-
peer = this.#createWebTransportConnection(peerId, url, attempt.version);
|
|
1713
|
+
peer = this.#createWebTransportConnection(peerId, url, attempt.version, attempt.star);
|
|
1597
1714
|
}
|
|
1598
1715
|
else {
|
|
1599
1716
|
peer = this.#createCircuitConnection(peerId, attempt.version);
|
|
@@ -1640,7 +1757,25 @@ class Client {
|
|
|
1640
1757
|
if (!peer) {
|
|
1641
1758
|
peer = this.#createCircuitConnection(context.from, this.version);
|
|
1642
1759
|
}
|
|
1643
|
-
|
|
1760
|
+
if (!peer)
|
|
1761
|
+
throw new Error('circuit peer unavailable');
|
|
1762
|
+
if (!peer.connected) {
|
|
1763
|
+
const waitingPeer = peer;
|
|
1764
|
+
await new Promise((resolve, reject) => {
|
|
1765
|
+
const finish = (error) => {
|
|
1766
|
+
clearTimeout(timer);
|
|
1767
|
+
waitingPeer.off('connect', onConnect);
|
|
1768
|
+
waitingPeer.off('close', onClose);
|
|
1769
|
+
error ? reject(error) : resolve();
|
|
1770
|
+
};
|
|
1771
|
+
const onConnect = () => finish();
|
|
1772
|
+
const onClose = () => finish(new Error('circuit peer closed during handshake'));
|
|
1773
|
+
const timer = setTimeout(() => finish(new Error('circuit handshake timed out')), this.#transportConnectTimeoutMs);
|
|
1774
|
+
waitingPeer.on('connect', onConnect);
|
|
1775
|
+
waitingPeer.on('close', onClose);
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
this.#peerData(peer, decoded.data);
|
|
1644
1779
|
return { ok: true };
|
|
1645
1780
|
}
|
|
1646
1781
|
#createCircuitId() {
|
|
@@ -1698,15 +1833,22 @@ class Client {
|
|
|
1698
1833
|
this.#pendingCircuitRequests.delete(id);
|
|
1699
1834
|
reject(new Error(`circuit request for ${id} timed out`));
|
|
1700
1835
|
}, timeoutMs);
|
|
1701
|
-
this.#pendingCircuitRequests.set(id, { resolve, reject, timeout });
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1836
|
+
this.#pendingCircuitRequests.set(id, { resolve, reject, timeout, peerId, starConnection });
|
|
1837
|
+
try {
|
|
1838
|
+
this.#sendCircuit(starConnection, {
|
|
1839
|
+
to: peerId,
|
|
1840
|
+
from: this.peerId,
|
|
1841
|
+
id,
|
|
1842
|
+
phase: 'request',
|
|
1843
|
+
method,
|
|
1844
|
+
data: this.#encodeCircuitData(data)
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1847
|
+
catch (error) {
|
|
1848
|
+
clearTimeout(timeout);
|
|
1849
|
+
this.#pendingCircuitRequests.delete(id);
|
|
1850
|
+
reject(error);
|
|
1851
|
+
}
|
|
1710
1852
|
});
|
|
1711
1853
|
}
|
|
1712
1854
|
#inComingCircuit = async ({ from, to, id, phase, method, data, error }, starConnection) => {
|
|
@@ -1716,6 +1858,10 @@ class Client {
|
|
|
1716
1858
|
const pending = this.#pendingCircuitRequests.get(id);
|
|
1717
1859
|
if (!pending)
|
|
1718
1860
|
return;
|
|
1861
|
+
if (pending.starConnection !== starConnection)
|
|
1862
|
+
return;
|
|
1863
|
+
if (from !== pending.peerId && !(from === 'server' && error))
|
|
1864
|
+
return;
|
|
1719
1865
|
clearTimeout(pending.timeout);
|
|
1720
1866
|
this.#pendingCircuitRequests.delete(id);
|
|
1721
1867
|
if (error) {
|
|
@@ -1789,17 +1935,16 @@ class Client {
|
|
|
1789
1935
|
connectWebTransport(peerId, url) {
|
|
1790
1936
|
this.#createWebTransportConnection(peerId, url, this.version);
|
|
1791
1937
|
}
|
|
1792
|
-
#resolveWebTransportUrl(peerId) {
|
|
1793
|
-
const urlTemplate = this.#webTransportUrlTemplate;
|
|
1938
|
+
#resolveWebTransportUrl(peerId, starConnection) {
|
|
1939
|
+
const urlTemplate = this.#webTransportUrlTemplate || (starConnection && this.#relayUrls.get(starConnection));
|
|
1794
1940
|
if (!urlTemplate) {
|
|
1795
|
-
console.warn('WebTransport requires transport.webtransport.urlTemplate in client options');
|
|
1796
1941
|
return null;
|
|
1797
1942
|
}
|
|
1798
1943
|
return urlTemplate
|
|
1799
1944
|
.replace('{peerId}', encodeURIComponent(peerId))
|
|
1800
1945
|
.replace('{selfId}', encodeURIComponent(this.peerId));
|
|
1801
1946
|
}
|
|
1802
|
-
#createWebTransportConnection(peerId, url, version) {
|
|
1947
|
+
#createWebTransportConnection(peerId, url, version, starConnection) {
|
|
1803
1948
|
if (this.#connections[peerId]) {
|
|
1804
1949
|
debug(`peer ${peerId} already connected`);
|
|
1805
1950
|
return null;
|
|
@@ -1824,7 +1969,27 @@ class Client {
|
|
|
1824
1969
|
from: this.peerId,
|
|
1825
1970
|
to: peerId,
|
|
1826
1971
|
version,
|
|
1827
|
-
url
|
|
1972
|
+
url,
|
|
1973
|
+
getTicket: async () => {
|
|
1974
|
+
const star = starConnection || this.#pickStarConnection();
|
|
1975
|
+
if (!star)
|
|
1976
|
+
throw new Error('no connected star available for WebTransport ticket');
|
|
1977
|
+
let timer;
|
|
1978
|
+
try {
|
|
1979
|
+
const response = await Promise.race([
|
|
1980
|
+
star.request({ url: 'webtransport-ticket', params: { from: this.peerId, to: peerId } }),
|
|
1981
|
+
new Promise((_, reject) => {
|
|
1982
|
+
timer = setTimeout(() => reject(new Error('WebTransport ticket request timed out')), this.#transportConnectTimeoutMs);
|
|
1983
|
+
})
|
|
1984
|
+
]);
|
|
1985
|
+
if (typeof response?.ticket !== 'string')
|
|
1986
|
+
throw new Error('star did not authorize WebTransport relay');
|
|
1987
|
+
return response.ticket;
|
|
1988
|
+
}
|
|
1989
|
+
finally {
|
|
1990
|
+
clearTimeout(timer);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1828
1993
|
});
|
|
1829
1994
|
peer.on('connect', () => this.#peerConnect(peer));
|
|
1830
1995
|
peer.on('close', () => this.#peerClose(peer));
|
|
@@ -1858,6 +2023,12 @@ class Client {
|
|
|
1858
2023
|
from: this.peerId,
|
|
1859
2024
|
to: peerId,
|
|
1860
2025
|
version,
|
|
2026
|
+
handshake: async () => {
|
|
2027
|
+
const response = await this.circuitRequest(peerId, 'swarm:fallback:hello', undefined, this.#transportConnectTimeoutMs);
|
|
2028
|
+
if (response?.peerId !== peerId || String(response?.version) !== String(version) || response.encoding !== 'peer-core/1') {
|
|
2029
|
+
throw new Error('invalid circuit handshake response');
|
|
2030
|
+
}
|
|
2031
|
+
},
|
|
1861
2032
|
sendViaCircuit: (payload) => this.circuitRequest(peerId, this.#fallbackCircuitMethod, payload)
|
|
1862
2033
|
});
|
|
1863
2034
|
peer.on('connect', () => this.#peerConnect(peer));
|
|
@@ -2174,6 +2345,11 @@ class Client {
|
|
|
2174
2345
|
peer.destroy();
|
|
2175
2346
|
};
|
|
2176
2347
|
async close() {
|
|
2348
|
+
for (const pending of this.#pendingCircuitRequests.values()) {
|
|
2349
|
+
clearTimeout(pending.timeout);
|
|
2350
|
+
pending.reject(new Error('client closed'));
|
|
2351
|
+
}
|
|
2352
|
+
this.#pendingCircuitRequests.clear();
|
|
2177
2353
|
for (const peerId of this.#peerTransportAttempts.keys()) {
|
|
2178
2354
|
this.#clearTransportAttempt(peerId);
|
|
2179
2355
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FormatInterface, o as proto$2, q as proto$3, r as encodeFrames, s as decodeFrames, t as proto$4 } from './browser-crypto-
|
|
1
|
+
import { F as FormatInterface, o as proto$2, q as proto$3, r as encodeFrames, s as decodeFrames, t as proto$4 } from './browser-crypto-CH0ua22L.js';
|
|
2
2
|
|
|
3
3
|
class ValidatorMessage extends FormatInterface {
|
|
4
4
|
get messageName() {
|
|
@@ -1,97 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* HMAC: RFC2104 message authentication code.
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Internal class for HMAC.
|
|
9
|
-
* Accepts any byte key, although RFC 2104 §3 recommends keys at least
|
|
10
|
-
* `HashLen` bytes long.
|
|
11
|
-
*/
|
|
12
|
-
class _HMAC {
|
|
13
|
-
oHash;
|
|
14
|
-
iHash;
|
|
15
|
-
blockLen;
|
|
16
|
-
outputLen;
|
|
17
|
-
canXOF = false;
|
|
18
|
-
finished = false;
|
|
19
|
-
destroyed = false;
|
|
20
|
-
constructor(hash, key) {
|
|
21
|
-
ahash(hash);
|
|
22
|
-
abytes(key, undefined, 'key');
|
|
23
|
-
this.iHash = hash.create();
|
|
24
|
-
if (typeof this.iHash.update !== 'function')
|
|
25
|
-
throw new Error('expected Hash instance');
|
|
26
|
-
this.blockLen = this.iHash.blockLen;
|
|
27
|
-
this.outputLen = this.iHash.outputLen;
|
|
28
|
-
const blockLen = this.blockLen;
|
|
29
|
-
const pad = new Uint8Array(blockLen);
|
|
30
|
-
// blockLen can be bigger than outputLen
|
|
31
|
-
pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
|
|
32
|
-
for (let i = 0; i < pad.length; i++)
|
|
33
|
-
pad[i] ^= 0x36;
|
|
34
|
-
this.iHash.update(pad);
|
|
35
|
-
// By doing update (processing of the first block) of the outer hash here,
|
|
36
|
-
// we can re-use it between multiple calls via clone.
|
|
37
|
-
this.oHash = hash.create();
|
|
38
|
-
// Undo internal XOR && apply outer XOR
|
|
39
|
-
for (let i = 0; i < pad.length; i++)
|
|
40
|
-
pad[i] ^= 0x36 ^ 0x5c;
|
|
41
|
-
this.oHash.update(pad);
|
|
42
|
-
clean(pad);
|
|
43
|
-
}
|
|
44
|
-
update(buf) {
|
|
45
|
-
aexists(this);
|
|
46
|
-
this.iHash.update(buf);
|
|
47
|
-
return this;
|
|
48
|
-
}
|
|
49
|
-
digestInto(out) {
|
|
50
|
-
aexists(this);
|
|
51
|
-
aoutput(out, this);
|
|
52
|
-
this.finished = true;
|
|
53
|
-
const buf = out.subarray(0, this.outputLen);
|
|
54
|
-
// Reuse the first outputLen bytes for the inner digest; the outer hash consumes them before
|
|
55
|
-
// overwriting that same prefix with the final tag, leaving any oversized tail untouched.
|
|
56
|
-
this.iHash.digestInto(buf);
|
|
57
|
-
this.oHash.update(buf);
|
|
58
|
-
this.oHash.digestInto(buf);
|
|
59
|
-
this.destroy();
|
|
60
|
-
}
|
|
61
|
-
digest() {
|
|
62
|
-
const out = new Uint8Array(this.oHash.outputLen);
|
|
63
|
-
this.digestInto(out);
|
|
64
|
-
return out;
|
|
65
|
-
}
|
|
66
|
-
_cloneInto(to) {
|
|
67
|
-
// Create new instance without calling constructor since the key
|
|
68
|
-
// is already in state and we don't know it.
|
|
69
|
-
to ||= Object.create(Object.getPrototypeOf(this), {});
|
|
70
|
-
const { oHash, iHash, finished, destroyed, blockLen, outputLen, canXOF } = this;
|
|
71
|
-
to = to;
|
|
72
|
-
to.finished = finished;
|
|
73
|
-
to.destroyed = destroyed;
|
|
74
|
-
to.blockLen = blockLen;
|
|
75
|
-
to.outputLen = outputLen;
|
|
76
|
-
to.canXOF = canXOF;
|
|
77
|
-
to.oHash = oHash._cloneInto(to.oHash);
|
|
78
|
-
to.iHash = iHash._cloneInto(to.iHash);
|
|
79
|
-
return to;
|
|
80
|
-
}
|
|
81
|
-
clone() {
|
|
82
|
-
return this._cloneInto();
|
|
83
|
-
}
|
|
84
|
-
destroy() {
|
|
85
|
-
this.destroyed = true;
|
|
86
|
-
this.oHash.destroy();
|
|
87
|
-
this.iHash.destroy();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
const hmac = /* @__PURE__ */ (() => {
|
|
91
|
-
const hmac_ = ((hash, key, message) => new _HMAC(hash, key).update(message).digest());
|
|
92
|
-
hmac_.create = (hash, key) => new _HMAC(hash, key);
|
|
93
|
-
return hmac_;
|
|
94
|
-
})();
|
|
1
|
+
import { h as hmac } from './weierstrass-BVfhtHbl.js';
|
|
2
|
+
import { a as ahash, b as anumber, c as abytes, d as clean } from './sha2-BKcEJzgd.js';
|
|
95
3
|
|
|
96
4
|
/**
|
|
97
5
|
* HKDF (RFC 5869): extract + expand in one step.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FormatInterface, e as proto, T as TransactionMessage, C as ContractMessage, i as index$1, f as index$2, g as createRIPEMD160, h as createHMAC, k as createSHA512, l as createKeccak, B as BinaryWriter, v as varUintLength, m as BinaryReader, n as createHash$1 } from './browser-crypto-
|
|
1
|
+
import { F as FormatInterface, e as proto, T as TransactionMessage, C as ContractMessage, i as index$1, f as index$2, g as createRIPEMD160, h as createHMAC, k as createSHA512, l as createKeccak, B as BinaryWriter, v as varUintLength, m as BinaryReader, n as createHash$1 } from './browser-crypto-CH0ua22L.js';
|
|
2
2
|
import { t as toBase58, b as base58$1, i as index$3 } from './index-CvKt4UDE.js';
|
|
3
3
|
|
|
4
4
|
/* Do NOT modify this file; see /src.ts/_admin/update-version.ts */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { M as MultiWallet, e as encrypt, b as base58$1 } from './node-browser-
|
|
2
|
-
import './browser-crypto-
|
|
3
|
-
import './connection-monitor-
|
|
1
|
+
import { M as MultiWallet, e as encrypt, b as base58$1 } from './node-browser-BNe-en1l.js';
|
|
2
|
+
import './browser-crypto-CH0ua22L.js';
|
|
3
|
+
import './connection-monitor-D-krNiRH.js';
|
|
4
4
|
import './index-CvKt4UDE.js';
|
|
5
|
-
import './sha2-
|
|
5
|
+
import './sha2-BKcEJzgd.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @params {String} network
|