smoldot 1.0.11 → 1.0.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/README.md +7 -0
- package/dist/cjs/internals/buffer.d.ts +2 -0
- package/dist/cjs/internals/buffer.js +11 -1
- package/dist/cjs/internals/bytecode/wasm0.js +1 -1
- package/dist/cjs/internals/bytecode/wasm1.js +1 -1
- package/dist/cjs/internals/bytecode/wasm2.js +1 -1
- package/dist/cjs/internals/client.d.ts +2 -3
- package/dist/cjs/internals/client.js +4 -1
- package/dist/cjs/internals/local-instance.d.ts +4 -12
- package/dist/cjs/internals/local-instance.js +83 -65
- package/dist/cjs/no-auto-bytecode-browser.js +11 -28
- package/dist/cjs/no-auto-bytecode-deno.js +2 -2
- package/dist/cjs/no-auto-bytecode-nodejs.js +2 -2
- package/dist/mjs/internals/buffer.d.ts +2 -0
- package/dist/mjs/internals/buffer.js +8 -0
- package/dist/mjs/internals/bytecode/wasm0.js +1 -1
- package/dist/mjs/internals/bytecode/wasm1.js +1 -1
- package/dist/mjs/internals/bytecode/wasm2.js +1 -1
- package/dist/mjs/internals/client.d.ts +2 -3
- package/dist/mjs/internals/client.js +4 -1
- package/dist/mjs/internals/local-instance.d.ts +4 -12
- package/dist/mjs/internals/local-instance.js +82 -63
- package/dist/mjs/no-auto-bytecode-browser.js +11 -28
- package/dist/mjs/no-auto-bytecode-deno.js +2 -2
- package/dist/mjs/no-auto-bytecode-nodejs.js +2 -2
- package/package.json +1 -1
- package/dist/cjs/internals/base64.d.ts +0 -22
- package/dist/cjs/internals/base64.js +0 -104
- package/dist/mjs/internals/base64.d.ts +0 -22
- package/dist/mjs/internals/base64.js +0 -97
|
@@ -120,12 +120,11 @@ export interface ConnectionConfig {
|
|
|
120
120
|
type: 'single-stream';
|
|
121
121
|
handshake: 'multistream-select-noise-yamux';
|
|
122
122
|
initialWritableBytes: number;
|
|
123
|
-
writeClosable: boolean;
|
|
124
123
|
} | {
|
|
125
124
|
type: 'multi-stream';
|
|
126
125
|
handshake: 'webrtc';
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
localTlsCertificateSha256: Uint8Array;
|
|
127
|
+
remoteTlsCertificateSha256: Uint8Array;
|
|
129
128
|
}) => void;
|
|
130
129
|
/**
|
|
131
130
|
* Callback called when the connection transitions to the `Reset` state.
|
|
@@ -284,8 +284,11 @@ export function start(options, wasmModule, platformBindings) {
|
|
|
284
284
|
if (jsonRpcMaxSubscriptions > 0xffffffff) {
|
|
285
285
|
jsonRpcMaxSubscriptions = 0xffffffff;
|
|
286
286
|
}
|
|
287
|
+
// Sanitize `databaseContent`.
|
|
288
|
+
if (options.databaseContent !== undefined && typeof options.databaseContent !== 'string')
|
|
289
|
+
throw new AddChainError("`databaseContent` is not a string");
|
|
287
290
|
const promise = new Promise((resolve) => state.addChainResults.push(resolve));
|
|
288
|
-
state.instance.instance.addChain(options.chainSpec,
|
|
291
|
+
state.instance.instance.addChain(options.chainSpec, options.databaseContent || "", potentialRelayChainsIds, !!options.disableJsonRpc, jsonRpcMaxPendingRequests, jsonRpcMaxSubscriptions);
|
|
289
292
|
const outcome = yield promise;
|
|
290
293
|
if (!outcome.success)
|
|
291
294
|
throw new AddChainError(outcome.error);
|
|
@@ -84,10 +84,10 @@ export type ParsedMultiaddr = {
|
|
|
84
84
|
url: string;
|
|
85
85
|
} | {
|
|
86
86
|
ty: "webrtc";
|
|
87
|
-
targetPort:
|
|
87
|
+
targetPort: number;
|
|
88
88
|
ipVersion: string;
|
|
89
89
|
targetIp: string;
|
|
90
|
-
|
|
90
|
+
remoteTlsCertificateSha256: Uint8Array;
|
|
91
91
|
};
|
|
92
92
|
export interface Instance {
|
|
93
93
|
request: (request: string, chainId: number) => number;
|
|
@@ -107,12 +107,11 @@ export interface Instance {
|
|
|
107
107
|
type: 'single-stream';
|
|
108
108
|
handshake: 'multistream-select-noise-yamux';
|
|
109
109
|
initialWritableBytes: number;
|
|
110
|
-
writeClosable: boolean;
|
|
111
110
|
} | {
|
|
112
111
|
type: 'multi-stream';
|
|
113
112
|
handshake: 'webrtc';
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
localTlsCertificateSha256: Uint8Array;
|
|
114
|
+
remoteTlsCertificateSha256: Uint8Array;
|
|
116
115
|
}) => void;
|
|
117
116
|
connectionReset: (connectionId: number, message: string) => void;
|
|
118
117
|
streamWritableBytes: (connectionId: number, numExtra: number, streamId?: number) => void;
|
|
@@ -133,10 +132,3 @@ export interface Instance {
|
|
|
133
132
|
* isn't sanitized. In other words, you know what you're doing.
|
|
134
133
|
*/
|
|
135
134
|
export declare function startLocalInstance(config: Config, wasmModule: WebAssembly.Module, eventCallback: (event: Event) => void): Promise<Instance>;
|
|
136
|
-
export declare function parseMultiaddr(address: string, forbidTcp: boolean, forbidWs: boolean, forbidNonLocalWs: boolean, forbidWss: boolean, forbidWebRtc: boolean): {
|
|
137
|
-
success: true;
|
|
138
|
-
address: ParsedMultiaddr;
|
|
139
|
-
} | {
|
|
140
|
-
success: false;
|
|
141
|
-
error: string;
|
|
142
|
-
};
|
|
@@ -124,26 +124,90 @@ export function startLocalInstance(config, wasmModule, eventCallback) {
|
|
|
124
124
|
}, ms);
|
|
125
125
|
}
|
|
126
126
|
},
|
|
127
|
+
// Must indicate whether the given connection type is supported.
|
|
128
|
+
connection_type_supported: (ty) => {
|
|
129
|
+
// TODO: consider extracting config options so user can't change the fields dynamically
|
|
130
|
+
switch (ty) {
|
|
131
|
+
case 0:
|
|
132
|
+
case 1:
|
|
133
|
+
case 2: {
|
|
134
|
+
return config.forbidTcp ? 0 : 1;
|
|
135
|
+
}
|
|
136
|
+
case 4:
|
|
137
|
+
case 5:
|
|
138
|
+
case 6: {
|
|
139
|
+
return config.forbidNonLocalWs ? 0 : 1;
|
|
140
|
+
}
|
|
141
|
+
case 7: {
|
|
142
|
+
return config.forbidWs ? 0 : 1;
|
|
143
|
+
}
|
|
144
|
+
case 14: {
|
|
145
|
+
return config.forbidWss ? 0 : 1;
|
|
146
|
+
}
|
|
147
|
+
case 16:
|
|
148
|
+
case 17: {
|
|
149
|
+
return config.forbidWebRtc ? 0 : 1;
|
|
150
|
+
}
|
|
151
|
+
default:
|
|
152
|
+
// Indicates a bug somewhere.
|
|
153
|
+
throw new Error("Invalid connection type passed to `connection_type_supported`");
|
|
154
|
+
}
|
|
155
|
+
},
|
|
127
156
|
// Must create a new connection object. This implementation stores the created object in
|
|
128
157
|
// `connections`.
|
|
129
|
-
connection_new: (connectionId, addrPtr, addrLen
|
|
158
|
+
connection_new: (connectionId, addrPtr, addrLen) => {
|
|
130
159
|
const instance = state.instance;
|
|
160
|
+
const mem = new Uint8Array(instance.exports.memory.buffer);
|
|
131
161
|
addrPtr >>>= 0;
|
|
132
162
|
addrLen >>>= 0;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
163
|
+
let address;
|
|
164
|
+
switch (buffer.readUInt8(mem, addrPtr)) {
|
|
165
|
+
case 0:
|
|
166
|
+
case 1:
|
|
167
|
+
case 2: {
|
|
168
|
+
const port = buffer.readUInt16BE(mem, addrPtr + 1);
|
|
169
|
+
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
|
|
170
|
+
address = { ty: "tcp", port, hostname };
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 4:
|
|
174
|
+
case 6: {
|
|
175
|
+
const port = buffer.readUInt16BE(mem, addrPtr + 1);
|
|
176
|
+
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
|
|
177
|
+
address = { ty: "websocket", url: "ws://" + hostname + ":" + port };
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case 5: {
|
|
181
|
+
const port = buffer.readUInt16BE(mem, addrPtr + 1);
|
|
182
|
+
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
|
|
183
|
+
address = { ty: "websocket", url: "ws://[" + hostname + "]:" + port };
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case 14: {
|
|
187
|
+
const port = buffer.readUInt16BE(mem, addrPtr + 1);
|
|
188
|
+
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
|
|
189
|
+
address = { ty: "websocket", url: "wss://" + hostname + ":" + port };
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
case 16: {
|
|
193
|
+
const targetPort = buffer.readUInt16BE(mem, addrPtr + 1);
|
|
194
|
+
const remoteTlsCertificateSha256 = mem.slice(addrPtr + 3, addrPtr + 35);
|
|
195
|
+
const targetIp = buffer.utf8BytesToString(mem, addrPtr + 35, addrLen - 3);
|
|
196
|
+
address = { ty: "webrtc", ipVersion: '4', remoteTlsCertificateSha256, targetIp, targetPort };
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
case 17: {
|
|
200
|
+
const targetPort = buffer.readUInt16BE(mem, addrPtr + 1);
|
|
201
|
+
const remoteTlsCertificateSha256 = mem.slice(addrPtr + 3, addrPtr + 35);
|
|
202
|
+
const targetIp = buffer.utf8BytesToString(mem, addrPtr + 35, addrLen - 3);
|
|
203
|
+
address = { ty: "webrtc", ipVersion: '6', remoteTlsCertificateSha256, targetIp, targetPort };
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
default:
|
|
207
|
+
// Indicates a bug somewhere.
|
|
208
|
+
throw new Error("Invalid encoded address passed to `connection_new`");
|
|
146
209
|
}
|
|
210
|
+
eventCallback({ ty: "new-connection", connectionId, address });
|
|
147
211
|
},
|
|
148
212
|
// Must close and destroy the connection object.
|
|
149
213
|
reset_connection: (connectionId) => {
|
|
@@ -473,14 +537,14 @@ export function startLocalInstance(config, wasmModule, eventCallback) {
|
|
|
473
537
|
return;
|
|
474
538
|
switch (info.type) {
|
|
475
539
|
case 'single-stream': {
|
|
476
|
-
state.instance.exports.connection_open_single_stream(connectionId,
|
|
540
|
+
state.instance.exports.connection_open_single_stream(connectionId, info.initialWritableBytes);
|
|
477
541
|
break;
|
|
478
542
|
}
|
|
479
543
|
case 'multi-stream': {
|
|
480
|
-
const handshakeTy = new Uint8Array(1 + info.
|
|
544
|
+
const handshakeTy = new Uint8Array(1 + info.localTlsCertificateSha256.length + info.remoteTlsCertificateSha256.length);
|
|
481
545
|
buffer.writeUInt8(handshakeTy, 0, 0);
|
|
482
|
-
handshakeTy.set(info.
|
|
483
|
-
handshakeTy.set(info.
|
|
546
|
+
handshakeTy.set(info.localTlsCertificateSha256, 1);
|
|
547
|
+
handshakeTy.set(info.remoteTlsCertificateSha256, 1 + info.localTlsCertificateSha256.length);
|
|
484
548
|
state.bufferIndices[0] = handshakeTy;
|
|
485
549
|
state.instance.exports.connection_open_multi_stream(connectionId, 0);
|
|
486
550
|
delete state.bufferIndices[0];
|
|
@@ -520,48 +584,3 @@ export function startLocalInstance(config, wasmModule, eventCallback) {
|
|
|
520
584
|
};
|
|
521
585
|
});
|
|
522
586
|
}
|
|
523
|
-
// TODO: consider moving this function somewhere else or something
|
|
524
|
-
export function parseMultiaddr(address, forbidTcp, forbidWs, forbidNonLocalWs, forbidWss, forbidWebRtc) {
|
|
525
|
-
const tcpParsed = address.match(/^\/(ip4|ip6|dns4|dns6|dns)\/(.*?)\/tcp\/(.*?)$/);
|
|
526
|
-
// TODO: remove support for `/wss` in a long time (https://github.com/paritytech/smoldot/issues/1940)
|
|
527
|
-
const wsParsed = address.match(/^\/(ip4|ip6|dns4|dns6|dns)\/(.*?)\/tcp\/(.*?)\/(ws|wss|tls\/ws)$/);
|
|
528
|
-
const webRTCParsed = address.match(/^\/(ip4|ip6)\/(.*?)\/udp\/(.*?)\/webrtc-direct\/certhash\/(.*?)$/);
|
|
529
|
-
if (wsParsed != null) {
|
|
530
|
-
const proto = (wsParsed[4] == 'ws') ? 'ws' : 'wss';
|
|
531
|
-
if (proto == 'ws' && forbidWs) {
|
|
532
|
-
return { success: false, error: 'WebSocket connections not available' };
|
|
533
|
-
}
|
|
534
|
-
if (proto == 'wss' && forbidWss) {
|
|
535
|
-
return { success: false, error: 'WebSocket secure connections not available' };
|
|
536
|
-
}
|
|
537
|
-
if (proto == 'ws' && wsParsed[2] != 'localhost' && wsParsed[2] != '127.0.0.1' && forbidNonLocalWs) {
|
|
538
|
-
return { success: false, error: 'Non-local WebSocket connections not available' };
|
|
539
|
-
}
|
|
540
|
-
const url = (wsParsed[1] == 'ip6') ?
|
|
541
|
-
(proto + "://[" + wsParsed[2] + "]:" + wsParsed[3]) :
|
|
542
|
-
(proto + "://" + wsParsed[2] + ":" + wsParsed[3]);
|
|
543
|
-
return { success: true, address: { ty: "websocket", url } };
|
|
544
|
-
}
|
|
545
|
-
else if (tcpParsed != null) {
|
|
546
|
-
if (forbidTcp) {
|
|
547
|
-
return { success: false, error: 'TCP connections not available' };
|
|
548
|
-
}
|
|
549
|
-
return { success: true, address: { ty: "tcp", hostname: tcpParsed[2], port: parseInt(tcpParsed[3]) } };
|
|
550
|
-
}
|
|
551
|
-
else if (webRTCParsed != null) {
|
|
552
|
-
const targetPort = webRTCParsed[3];
|
|
553
|
-
if (forbidWebRtc) {
|
|
554
|
-
return { success: false, error: 'WebRTC connections not available' };
|
|
555
|
-
}
|
|
556
|
-
if (targetPort === '0') {
|
|
557
|
-
return { success: false, error: 'Invalid WebRTC target port' };
|
|
558
|
-
}
|
|
559
|
-
const ipVersion = webRTCParsed[1] == 'ip4' ? '4' : '6';
|
|
560
|
-
const targetIp = webRTCParsed[2];
|
|
561
|
-
const remoteCertMultibase = webRTCParsed[4];
|
|
562
|
-
return { success: true, address: { ty: "webrtc", targetPort, ipVersion, targetIp, remoteCertMultibase } };
|
|
563
|
-
}
|
|
564
|
-
else {
|
|
565
|
-
return { success: false, error: 'Unrecognized multiaddr format' };
|
|
566
|
-
}
|
|
567
|
-
}
|
|
@@ -11,7 +11,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
13
|
import { start as innerStart } from './internals/client.js';
|
|
14
|
-
import { multibaseBase64Decode } from './internals/base64.js';
|
|
15
14
|
export { AddChainError, AlreadyDestroyedError, CrashError, JsonRpcDisabledError, MalformedJsonRpcError, QueueFullError } from './public-types.js';
|
|
16
15
|
/**
|
|
17
16
|
* Initializes a new client. This is a pre-requisite to connecting to a blockchain.
|
|
@@ -97,7 +96,7 @@ function connect(config) {
|
|
|
97
96
|
connection.onopen = () => {
|
|
98
97
|
config.onOpen({
|
|
99
98
|
type: 'single-stream', handshake: 'multistream-select-noise-yamux',
|
|
100
|
-
initialWritableBytes: 1024 * 1024
|
|
99
|
+
initialWritableBytes: 1024 * 1024
|
|
101
100
|
});
|
|
102
101
|
};
|
|
103
102
|
connection.onclose = (event) => {
|
|
@@ -149,13 +148,7 @@ function connect(config) {
|
|
|
149
148
|
};
|
|
150
149
|
}
|
|
151
150
|
else if (config.address.ty === "webrtc") {
|
|
152
|
-
const { targetPort, ipVersion, targetIp,
|
|
153
|
-
// The payload of `/certhash` is the hash of the self-generated certificate that the
|
|
154
|
-
// server presents.
|
|
155
|
-
// This function throws an exception if the certhash isn't correct. For this reason, this call
|
|
156
|
-
// is performed as part of the parsing of the multiaddr.
|
|
157
|
-
const remoteCertMultihash = multibaseBase64Decode(remoteCertMultibase);
|
|
158
|
-
const remoteCertSha256Hash = multihashToSha256(remoteCertMultihash);
|
|
151
|
+
const { targetPort, ipVersion, targetIp, remoteTlsCertificateSha256 } = config.address;
|
|
159
152
|
// TODO: detect localhost for Firefox? https://bugzilla.mozilla.org/show_bug.cgi?id=1659672
|
|
160
153
|
// Note that `pc` can be the connection, but also null or undefined.
|
|
161
154
|
// `undefined` means "certificate generation in progress", while `null` means "opening must
|
|
@@ -169,10 +162,10 @@ function connect(config) {
|
|
|
169
162
|
// to smoldot. This data channel is stored in this variable. Once it is reported to smoldot,
|
|
170
163
|
// it is inserted in `dataChannels`.
|
|
171
164
|
let handshakeDataChannel;
|
|
172
|
-
//
|
|
165
|
+
// SHA256 hash of the DTLS certificate of the local node. Unknown as long as it hasn't been
|
|
173
166
|
// generated.
|
|
174
167
|
// TODO: could be merged with `pc` in one variable, and maybe even the other fields as well
|
|
175
|
-
let
|
|
168
|
+
let localTlsCertificateSha256;
|
|
176
169
|
// Kills all the JavaScript objects (the connection and all its substreams), ensuring that no
|
|
177
170
|
// callback will be called again. Doesn't report anything to smoldot, as this should be done
|
|
178
171
|
// by the caller.
|
|
@@ -222,8 +215,8 @@ function connect(config) {
|
|
|
222
215
|
handshake: 'webrtc',
|
|
223
216
|
// `addChannel` can never be called before the local certificate is generated, so this
|
|
224
217
|
// value is always defined.
|
|
225
|
-
|
|
226
|
-
|
|
218
|
+
localTlsCertificateSha256: localTlsCertificateSha256,
|
|
219
|
+
remoteTlsCertificateSha256,
|
|
227
220
|
});
|
|
228
221
|
}
|
|
229
222
|
else {
|
|
@@ -328,9 +321,8 @@ function connect(config) {
|
|
|
328
321
|
config.onConnectionReset('Failed to obtain the browser certificate fingerprint');
|
|
329
322
|
return;
|
|
330
323
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
localTlsCertificateMultihash.set(localTlsCertificateHex.split(':').map((s) => parseInt(s, 16)), 2);
|
|
324
|
+
localTlsCertificateSha256 = new Uint8Array(32);
|
|
325
|
+
localTlsCertificateSha256.set(localTlsCertificateHex.split(':').map((s) => parseInt(s, 16)), 0);
|
|
334
326
|
// `onconnectionstatechange` is used to detect when the connection has closed or has failed
|
|
335
327
|
// to open.
|
|
336
328
|
// Note that smoldot will think that the connection is open even when it is still opening.
|
|
@@ -366,7 +358,7 @@ function connect(config) {
|
|
|
366
358
|
sdpOffer = sdpOffer.replace(/^a=ice-pwd.*$/m, 'a=ice-pwd:' + ufragPwd);
|
|
367
359
|
yield pc.setLocalDescription({ type: 'offer', sdp: sdpOffer });
|
|
368
360
|
// Transform certificate hash into fingerprint (upper-hex; each byte separated by ":").
|
|
369
|
-
const fingerprint = Array.from(
|
|
361
|
+
const fingerprint = Array.from(remoteTlsCertificateSha256).map((n) => ("0" + n.toString(16)).slice(-2).toUpperCase()).join(':');
|
|
370
362
|
// Note that the trailing line feed is important, as otherwise Chrome
|
|
371
363
|
// fails to parse the payload.
|
|
372
364
|
const remoteSdp =
|
|
@@ -393,7 +385,7 @@ function connect(config) {
|
|
|
393
385
|
// The `<fmt>` component must always be `webrtc-datachannel` for WebRTC.
|
|
394
386
|
// The rest of the SDP payload adds attributes to this specific media stream.
|
|
395
387
|
// RFCs: 8839, 8866, 8841
|
|
396
|
-
"m=application " + targetPort + " " + "UDP/DTLS/SCTP webrtc-datachannel" + "\n" +
|
|
388
|
+
"m=application " + String(targetPort) + " " + "UDP/DTLS/SCTP webrtc-datachannel" + "\n" +
|
|
397
389
|
// Indicates the IP address of the remote.
|
|
398
390
|
// Note that "IN" means "Internet" (and not "input").
|
|
399
391
|
"c=IN IP" + ipVersion + " " + targetIp + "\n" +
|
|
@@ -424,7 +416,7 @@ function connect(config) {
|
|
|
424
416
|
"a=max-message-size:16384" + "\n" +
|
|
425
417
|
// A transport address for a candidate that can be used for connectivity
|
|
426
418
|
// checks (RFC8839).
|
|
427
|
-
"a=candidate:1 1 UDP 1 " + targetIp + " " + targetPort + " typ host" + "\n";
|
|
419
|
+
"a=candidate:1 1 UDP 1 " + targetIp + " " + String(targetPort) + " typ host" + "\n";
|
|
428
420
|
yield pc.setRemoteDescription({ type: "answer", sdp: remoteSdp });
|
|
429
421
|
});
|
|
430
422
|
pc.ondatachannel = ({ channel }) => {
|
|
@@ -496,12 +488,3 @@ function connect(config) {
|
|
|
496
488
|
throw new Error();
|
|
497
489
|
}
|
|
498
490
|
}
|
|
499
|
-
/// Parses a multihash-multibase-encoded string into a SHA256 hash.
|
|
500
|
-
///
|
|
501
|
-
/// Throws an exception if the multihash algorithm isn't SHA256.
|
|
502
|
-
const multihashToSha256 = (certMultihash) => {
|
|
503
|
-
if (certMultihash.length != 34 || certMultihash[0] != 0x12 || certMultihash[1] != 32) {
|
|
504
|
-
throw new Error('Certificate multihash is not SHA-256');
|
|
505
|
-
}
|
|
506
|
-
return new Uint8Array(certMultihash.slice(2));
|
|
507
|
-
};
|
|
@@ -70,7 +70,7 @@ function connect(config) {
|
|
|
70
70
|
config.onWritableBytes(wasSent);
|
|
71
71
|
};
|
|
72
72
|
socket.onopen = () => {
|
|
73
|
-
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024
|
|
73
|
+
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
|
|
74
74
|
};
|
|
75
75
|
socket.onclose = (event) => {
|
|
76
76
|
const message = "Error code " + event.code + (!!event.reason ? (": " + event.reason) : "");
|
|
@@ -125,7 +125,7 @@ function connect(config) {
|
|
|
125
125
|
if (socket.destroyed)
|
|
126
126
|
return established;
|
|
127
127
|
established === null || established === void 0 ? void 0 : established.setNoDelay();
|
|
128
|
-
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024
|
|
128
|
+
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
|
|
129
129
|
// Spawns an asynchronous task that continuously reads from the socket.
|
|
130
130
|
// Every time data is read, the task re-executes itself in order to continue reading.
|
|
131
131
|
// The task ends automatically if an EOF or error is detected, which should also happen
|
|
@@ -66,7 +66,7 @@ function connect(config) {
|
|
|
66
66
|
config.onWritableBytes(wasSent);
|
|
67
67
|
};
|
|
68
68
|
socket.onopen = () => {
|
|
69
|
-
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024
|
|
69
|
+
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
|
|
70
70
|
};
|
|
71
71
|
socket.onclose = (event) => {
|
|
72
72
|
const message = "Error code " + event.code + (!!event.reason ? (": " + event.reason) : "");
|
|
@@ -121,7 +121,7 @@ function connect(config) {
|
|
|
121
121
|
return;
|
|
122
122
|
config.onOpen({
|
|
123
123
|
type: 'single-stream', handshake: 'multistream-select-noise-yamux',
|
|
124
|
-
initialWritableBytes: socket.writableHighWaterMark
|
|
124
|
+
initialWritableBytes: socket.writableHighWaterMark
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
socket.on('close', (hasError) => {
|
package/package.json
CHANGED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decodes a multibase-encoded string.
|
|
3
|
-
*
|
|
4
|
-
* Throws an exception if the encoding isn't base64 or one of its variants.
|
|
5
|
-
*/
|
|
6
|
-
export declare function multibaseBase64Decode(input: string): Uint8Array;
|
|
7
|
-
/**
|
|
8
|
-
* Decodes a base64-encoded string into bytes using the original alphabet from RFC4648.
|
|
9
|
-
*
|
|
10
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-4>.
|
|
11
|
-
*/
|
|
12
|
-
export declare function classicDecode(input: string): Uint8Array;
|
|
13
|
-
/**
|
|
14
|
-
* Decodes a base64-encoded string into bytes using the URL-safe alphabet.
|
|
15
|
-
*
|
|
16
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-5>.
|
|
17
|
-
*/
|
|
18
|
-
export declare function urlSafeDecode(input: string): Uint8Array;
|
|
19
|
-
/**
|
|
20
|
-
* Decodes a base64-encoded string into bytes using the given alphabet.
|
|
21
|
-
*/
|
|
22
|
-
export declare function base64Decode(input: string, alphabet: Map<string, number>): Uint8Array;
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Smoldot
|
|
3
|
-
// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
|
|
4
|
-
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.base64Decode = exports.urlSafeDecode = exports.classicDecode = exports.multibaseBase64Decode = void 0;
|
|
7
|
-
// This program is free software: you can redistribute it and/or modify
|
|
8
|
-
// it under the terms of the GNU General Public License as published by
|
|
9
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
10
|
-
// (at your option) any later version.
|
|
11
|
-
// This program is distributed in the hope that it will be useful,
|
|
12
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
-
// GNU General Public License for more details.
|
|
15
|
-
// You should have received a copy of the GNU General Public License
|
|
16
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
-
let rfc4648Alphabet = new Map();
|
|
18
|
-
const rfc4648AlphabetAsStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
19
|
-
for (let i = 0; i < rfc4648AlphabetAsStr.length; ++i) {
|
|
20
|
-
rfc4648Alphabet.set(rfc4648AlphabetAsStr[i], i);
|
|
21
|
-
}
|
|
22
|
-
let urlSafeAlphabet = new Map();
|
|
23
|
-
const urlSafeAlphabetAsStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
24
|
-
for (let i = 0; i < urlSafeAlphabetAsStr.length; ++i) {
|
|
25
|
-
urlSafeAlphabet.set(urlSafeAlphabetAsStr[i], i);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Decodes a multibase-encoded string.
|
|
29
|
-
*
|
|
30
|
-
* Throws an exception if the encoding isn't base64 or one of its variants.
|
|
31
|
-
*/
|
|
32
|
-
function multibaseBase64Decode(input) {
|
|
33
|
-
if (input.length === 0)
|
|
34
|
-
throw new Error("Invalid multibase");
|
|
35
|
-
switch (input[0]) {
|
|
36
|
-
case 'm':
|
|
37
|
-
case 'M':
|
|
38
|
-
return classicDecode(input.slice(1));
|
|
39
|
-
case 'u':
|
|
40
|
-
case 'U':
|
|
41
|
-
return urlSafeDecode(input.slice(1));
|
|
42
|
-
default:
|
|
43
|
-
throw new Error('Unknown multibase prefix: ' + input[0]);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
exports.multibaseBase64Decode = multibaseBase64Decode;
|
|
47
|
-
/**
|
|
48
|
-
* Decodes a base64-encoded string into bytes using the original alphabet from RFC4648.
|
|
49
|
-
*
|
|
50
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-4>.
|
|
51
|
-
*/
|
|
52
|
-
function classicDecode(input) {
|
|
53
|
-
return base64Decode(input, rfc4648Alphabet);
|
|
54
|
-
}
|
|
55
|
-
exports.classicDecode = classicDecode;
|
|
56
|
-
/**
|
|
57
|
-
* Decodes a base64-encoded string into bytes using the URL-safe alphabet.
|
|
58
|
-
*
|
|
59
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-5>.
|
|
60
|
-
*/
|
|
61
|
-
function urlSafeDecode(input) {
|
|
62
|
-
return base64Decode(input, urlSafeAlphabet);
|
|
63
|
-
}
|
|
64
|
-
exports.urlSafeDecode = urlSafeDecode;
|
|
65
|
-
/**
|
|
66
|
-
* Decodes a base64-encoded string into bytes using the given alphabet.
|
|
67
|
-
*/
|
|
68
|
-
function base64Decode(input, alphabet) {
|
|
69
|
-
// Remove the padding bytes at the end of the string. We don't check whether the padding is
|
|
70
|
-
// accurate.
|
|
71
|
-
while (input.length !== 0 && input[input.length - 1] === '=')
|
|
72
|
-
input = input.slice(0, -1);
|
|
73
|
-
// Contains the output data.
|
|
74
|
-
const out = new Uint8Array(Math.floor(input.length * 6 / 8));
|
|
75
|
-
// Position within `out` of the next byte to write.
|
|
76
|
-
let outPos = 0;
|
|
77
|
-
// The bits decoded from the input are added to the right of this value.
|
|
78
|
-
let currentByte = 0;
|
|
79
|
-
// The left-most `validBitsInCurrentByte` bits of `currentByte` must be written out.
|
|
80
|
-
let validBitsInCurrentByte = 0;
|
|
81
|
-
for (let i = 0; i < input.length; ++i) {
|
|
82
|
-
const inputChr = input[i];
|
|
83
|
-
const bitsToAppend = alphabet.get(inputChr);
|
|
84
|
-
if (bitsToAppend === undefined)
|
|
85
|
-
throw new Error('Invalid base64 character: ' + inputChr);
|
|
86
|
-
console.assert(bitsToAppend < (1 << 6));
|
|
87
|
-
currentByte = (currentByte << 6) | bitsToAppend;
|
|
88
|
-
validBitsInCurrentByte += 6;
|
|
89
|
-
if (validBitsInCurrentByte >= 8) {
|
|
90
|
-
let outByte = currentByte >> (validBitsInCurrentByte - 8);
|
|
91
|
-
out[outPos] = outByte;
|
|
92
|
-
outPos += 1;
|
|
93
|
-
validBitsInCurrentByte -= 8;
|
|
94
|
-
}
|
|
95
|
-
console.assert(validBitsInCurrentByte < 8);
|
|
96
|
-
currentByte &= 0xff;
|
|
97
|
-
}
|
|
98
|
-
if ((currentByte & ((1 << validBitsInCurrentByte) - 1)) !== 0)
|
|
99
|
-
throw new Error("Unexpected EOF");
|
|
100
|
-
if (validBitsInCurrentByte >= 6)
|
|
101
|
-
throw new Error("Unexpected EOF");
|
|
102
|
-
return out;
|
|
103
|
-
}
|
|
104
|
-
exports.base64Decode = base64Decode;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decodes a multibase-encoded string.
|
|
3
|
-
*
|
|
4
|
-
* Throws an exception if the encoding isn't base64 or one of its variants.
|
|
5
|
-
*/
|
|
6
|
-
export declare function multibaseBase64Decode(input: string): Uint8Array;
|
|
7
|
-
/**
|
|
8
|
-
* Decodes a base64-encoded string into bytes using the original alphabet from RFC4648.
|
|
9
|
-
*
|
|
10
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-4>.
|
|
11
|
-
*/
|
|
12
|
-
export declare function classicDecode(input: string): Uint8Array;
|
|
13
|
-
/**
|
|
14
|
-
* Decodes a base64-encoded string into bytes using the URL-safe alphabet.
|
|
15
|
-
*
|
|
16
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-5>.
|
|
17
|
-
*/
|
|
18
|
-
export declare function urlSafeDecode(input: string): Uint8Array;
|
|
19
|
-
/**
|
|
20
|
-
* Decodes a base64-encoded string into bytes using the given alphabet.
|
|
21
|
-
*/
|
|
22
|
-
export declare function base64Decode(input: string, alphabet: Map<string, number>): Uint8Array;
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// Smoldot
|
|
2
|
-
// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
|
|
3
|
-
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
|
4
|
-
// This program is free software: you can redistribute it and/or modify
|
|
5
|
-
// it under the terms of the GNU General Public License as published by
|
|
6
|
-
// the Free Software Foundation, either version 3 of the License, or
|
|
7
|
-
// (at your option) any later version.
|
|
8
|
-
// This program is distributed in the hope that it will be useful,
|
|
9
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
-
// GNU General Public License for more details.
|
|
12
|
-
// You should have received a copy of the GNU General Public License
|
|
13
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
14
|
-
let rfc4648Alphabet = new Map();
|
|
15
|
-
const rfc4648AlphabetAsStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
16
|
-
for (let i = 0; i < rfc4648AlphabetAsStr.length; ++i) {
|
|
17
|
-
rfc4648Alphabet.set(rfc4648AlphabetAsStr[i], i);
|
|
18
|
-
}
|
|
19
|
-
let urlSafeAlphabet = new Map();
|
|
20
|
-
const urlSafeAlphabetAsStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
21
|
-
for (let i = 0; i < urlSafeAlphabetAsStr.length; ++i) {
|
|
22
|
-
urlSafeAlphabet.set(urlSafeAlphabetAsStr[i], i);
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Decodes a multibase-encoded string.
|
|
26
|
-
*
|
|
27
|
-
* Throws an exception if the encoding isn't base64 or one of its variants.
|
|
28
|
-
*/
|
|
29
|
-
export function multibaseBase64Decode(input) {
|
|
30
|
-
if (input.length === 0)
|
|
31
|
-
throw new Error("Invalid multibase");
|
|
32
|
-
switch (input[0]) {
|
|
33
|
-
case 'm':
|
|
34
|
-
case 'M':
|
|
35
|
-
return classicDecode(input.slice(1));
|
|
36
|
-
case 'u':
|
|
37
|
-
case 'U':
|
|
38
|
-
return urlSafeDecode(input.slice(1));
|
|
39
|
-
default:
|
|
40
|
-
throw new Error('Unknown multibase prefix: ' + input[0]);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Decodes a base64-encoded string into bytes using the original alphabet from RFC4648.
|
|
45
|
-
*
|
|
46
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-4>.
|
|
47
|
-
*/
|
|
48
|
-
export function classicDecode(input) {
|
|
49
|
-
return base64Decode(input, rfc4648Alphabet);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Decodes a base64-encoded string into bytes using the URL-safe alphabet.
|
|
53
|
-
*
|
|
54
|
-
* See <https://datatracker.ietf.org/doc/html/rfc4648#section-5>.
|
|
55
|
-
*/
|
|
56
|
-
export function urlSafeDecode(input) {
|
|
57
|
-
return base64Decode(input, urlSafeAlphabet);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Decodes a base64-encoded string into bytes using the given alphabet.
|
|
61
|
-
*/
|
|
62
|
-
export function base64Decode(input, alphabet) {
|
|
63
|
-
// Remove the padding bytes at the end of the string. We don't check whether the padding is
|
|
64
|
-
// accurate.
|
|
65
|
-
while (input.length !== 0 && input[input.length - 1] === '=')
|
|
66
|
-
input = input.slice(0, -1);
|
|
67
|
-
// Contains the output data.
|
|
68
|
-
const out = new Uint8Array(Math.floor(input.length * 6 / 8));
|
|
69
|
-
// Position within `out` of the next byte to write.
|
|
70
|
-
let outPos = 0;
|
|
71
|
-
// The bits decoded from the input are added to the right of this value.
|
|
72
|
-
let currentByte = 0;
|
|
73
|
-
// The left-most `validBitsInCurrentByte` bits of `currentByte` must be written out.
|
|
74
|
-
let validBitsInCurrentByte = 0;
|
|
75
|
-
for (let i = 0; i < input.length; ++i) {
|
|
76
|
-
const inputChr = input[i];
|
|
77
|
-
const bitsToAppend = alphabet.get(inputChr);
|
|
78
|
-
if (bitsToAppend === undefined)
|
|
79
|
-
throw new Error('Invalid base64 character: ' + inputChr);
|
|
80
|
-
console.assert(bitsToAppend < (1 << 6));
|
|
81
|
-
currentByte = (currentByte << 6) | bitsToAppend;
|
|
82
|
-
validBitsInCurrentByte += 6;
|
|
83
|
-
if (validBitsInCurrentByte >= 8) {
|
|
84
|
-
let outByte = currentByte >> (validBitsInCurrentByte - 8);
|
|
85
|
-
out[outPos] = outByte;
|
|
86
|
-
outPos += 1;
|
|
87
|
-
validBitsInCurrentByte -= 8;
|
|
88
|
-
}
|
|
89
|
-
console.assert(validBitsInCurrentByte < 8);
|
|
90
|
-
currentByte &= 0xff;
|
|
91
|
-
}
|
|
92
|
-
if ((currentByte & ((1 << validBitsInCurrentByte) - 1)) !== 0)
|
|
93
|
-
throw new Error("Unexpected EOF");
|
|
94
|
-
if (validBitsInCurrentByte >= 6)
|
|
95
|
-
throw new Error("Unexpected EOF");
|
|
96
|
-
return out;
|
|
97
|
-
}
|