Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

smoldot

Package Overview
Dependencies
Maintainers
1
Versions
104
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

smoldot - npm Package Compare versions

Comparing version 1.0.11 to 1.0.12

2

dist/cjs/internals/buffer.d.ts
export declare function utf8BytesToString(buffer: Uint8Array, offset: number, length: number): string;
export declare function readUInt8(buffer: Uint8Array, offset: number): number;
export declare function readUInt16BE(buffer: Uint8Array, offset: number): number;
export declare function readUInt32LE(buffer: Uint8Array, offset: number): number;

@@ -3,0 +5,0 @@ /**

@@ -6,3 +6,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.writeUInt64LE = exports.writeUInt32LE = exports.writeUInt8 = exports.readUInt32LE = exports.utf8BytesToString = void 0;
exports.writeUInt64LE = exports.writeUInt32LE = exports.writeUInt8 = exports.readUInt32LE = exports.readUInt16BE = exports.readUInt8 = exports.utf8BytesToString = void 0;
// This program is free software: you can redistribute it and/or modify

@@ -25,2 +25,12 @@ // it under the terms of the GNU General Public License as published by

exports.utf8BytesToString = utf8BytesToString;
function readUInt8(buffer, offset) {
checkRange(buffer, offset, 1);
return buffer[offset];
}
exports.readUInt8 = readUInt8;
function readUInt16BE(buffer, offset) {
checkRange(buffer, offset, 2);
return ((buffer[offset] << 8) | buffer[offset + 1]);
}
exports.readUInt16BE = readUInt16BE;
function readUInt32LE(buffer, offset) {

@@ -27,0 +37,0 @@ checkRange(buffer, offset, 4);

5

dist/cjs/internals/client.d.ts

@@ -123,8 +123,7 @@ import { Client, ClientOptions, SmoldotBytecode } from '../public-types.js';

initialWritableBytes: number;
writeClosable: boolean;
} | {
type: 'multi-stream';
handshake: 'webrtc';
localTlsCertificateMultihash: Uint8Array;
remoteTlsCertificateMultihash: Uint8Array;
localTlsCertificateSha256: Uint8Array;
remoteTlsCertificateSha256: Uint8Array;
}) => void;

@@ -131,0 +130,0 @@ /**

@@ -290,4 +290,7 @@ "use strict";

}
// Sanitize `databaseContent`.
if (options.databaseContent !== undefined && typeof options.databaseContent !== 'string')
throw new public_types_js_1.AddChainError("`databaseContent` is not a string");
const promise = new Promise((resolve) => state.addChainResults.push(resolve));
state.instance.instance.addChain(options.chainSpec, typeof options.databaseContent === 'string' ? options.databaseContent : "", potentialRelayChainsIds, !!options.disableJsonRpc, jsonRpcMaxPendingRequests, jsonRpcMaxSubscriptions);
state.instance.instance.addChain(options.chainSpec, options.databaseContent || "", potentialRelayChainsIds, !!options.disableJsonRpc, jsonRpcMaxPendingRequests, jsonRpcMaxSubscriptions);
const outcome = yield promise;

@@ -294,0 +297,0 @@ if (!outcome.success)

@@ -87,6 +87,6 @@ /**

ty: "webrtc";
targetPort: string;
targetPort: number;
ipVersion: string;
targetIp: string;
remoteCertMultibase: string;
remoteTlsCertificateSha256: Uint8Array;
};

@@ -111,8 +111,7 @@ export interface Instance {

initialWritableBytes: number;
writeClosable: boolean;
} | {
type: 'multi-stream';
handshake: 'webrtc';
localTlsCertificateMultihash: Uint8Array;
remoteTlsCertificateMultihash: Uint8Array;
localTlsCertificateSha256: Uint8Array;
remoteTlsCertificateSha256: Uint8Array;
}) => void;

@@ -138,8 +137,1 @@ connectionReset: (connectionId: number, message: string) => void;

export declare function startLocalInstance(config: Config, wasmModule: WebAssembly.Module, eventCallback: (event: Event) => void): Promise<Instance>;
export declare function parseMultiaddr(address: string, forbidTcp: boolean, forbidWs: boolean, forbidNonLocalWs: boolean, forbidWss: boolean, forbidWebRtc: boolean): {
success: true;
address: ParsedMultiaddr;
} | {
success: false;
error: string;
};

@@ -15,3 +15,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseMultiaddr = exports.startLocalInstance = void 0;
exports.startLocalInstance = void 0;
// This program is free software: you can redistribute it and/or modify

@@ -131,22 +131,86 @@ // it under the terms of the GNU General Public License as published by

},
// Must indicate whether the given connection type is supported.
connection_type_supported: (ty) => {
// TODO: consider extracting config options so user can't change the fields dynamically
switch (ty) {
case 0:
case 1:
case 2: {
return config.forbidTcp ? 0 : 1;
}
case 4:
case 5:
case 6: {
return config.forbidWs ? 0 : 1;
}
case 7: {
return config.forbidNonLocalWs ? 0 : 1;
}
case 14: {
return config.forbidWss ? 0 : 1;
}
case 16:
case 17: {
return config.forbidWebRtc ? 0 : 1;
}
default:
// Indicates a bug somewhere.
throw new Error("Invalid connection type passed to `connection_type_supported`");
}
},
// Must create a new connection object. This implementation stores the created object in
// `connections`.
connection_new: (connectionId, addrPtr, addrLen, errorBufferIndexPtr) => {
connection_new: (connectionId, addrPtr, addrLen) => {
const instance = state.instance;
const mem = new Uint8Array(instance.exports.memory.buffer);
addrPtr >>>= 0;
addrLen >>>= 0;
errorBufferIndexPtr >>>= 0;
const address = buffer.utf8BytesToString(new Uint8Array(instance.exports.memory.buffer), addrPtr, addrLen);
// TODO: consider extracting config options so user can't change the fields dynamically
const result = parseMultiaddr(address, config.forbidTcp, config.forbidWs, config.forbidNonLocalWs, config.forbidWss, config.forbidWebRtc);
if (result.success) {
eventCallback({ ty: "new-connection", connectionId, address: result.address });
return 0;
let address;
switch (buffer.readUInt8(mem, addrPtr)) {
case 0:
case 1:
case 2: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "tcp", port, hostname };
break;
}
case 4:
case 6: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "websocket", url: "ws://" + hostname + ":" + port };
break;
}
case 5: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "websocket", url: "ws://[" + hostname + "]:" + port };
break;
}
case 14: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "websocket", url: "wss://" + hostname + ":" + port };
break;
}
case 16: {
const targetPort = buffer.readUInt16BE(mem, addrPtr + 1);
const remoteTlsCertificateSha256 = mem.slice(addrPtr + 3, addrPtr + 35);
const targetIp = buffer.utf8BytesToString(mem, addrPtr + 35, addrLen - 3);
address = { ty: "webrtc", ipVersion: '4', remoteTlsCertificateSha256, targetIp, targetPort };
break;
}
case 17: {
const targetPort = buffer.readUInt16BE(mem, addrPtr + 1);
const remoteTlsCertificateSha256 = mem.slice(addrPtr + 3, addrPtr + 35);
const targetIp = buffer.utf8BytesToString(mem, addrPtr + 35, addrLen - 3);
address = { ty: "webrtc", ipVersion: '6', remoteTlsCertificateSha256, targetIp, targetPort };
break;
}
default:
// Indicates a bug somewhere.
throw new Error("Invalid encoded address passed to `connection_new`");
}
else {
const mem = new Uint8Array(instance.exports.memory.buffer);
state.bufferIndices[0] = new TextEncoder().encode(result.error);
buffer.writeUInt32LE(mem, errorBufferIndexPtr, 0);
return 1;
}
eventCallback({ ty: "new-connection", connectionId, address });
},

@@ -481,10 +545,10 @@ // Must close and destroy the connection object.

case 'single-stream': {
state.instance.exports.connection_open_single_stream(connectionId, 0, info.initialWritableBytes, info.writeClosable ? 1 : 0);
state.instance.exports.connection_open_single_stream(connectionId, info.initialWritableBytes);
break;
}
case 'multi-stream': {
const handshakeTy = new Uint8Array(1 + info.localTlsCertificateMultihash.length + info.remoteTlsCertificateMultihash.length);
const handshakeTy = new Uint8Array(1 + info.localTlsCertificateSha256.length + info.remoteTlsCertificateSha256.length);
buffer.writeUInt8(handshakeTy, 0, 0);
handshakeTy.set(info.localTlsCertificateMultihash, 1);
handshakeTy.set(info.remoteTlsCertificateMultihash, 1 + info.localTlsCertificateMultihash.length);
handshakeTy.set(info.localTlsCertificateSha256, 1);
handshakeTy.set(info.remoteTlsCertificateSha256, 1 + info.localTlsCertificateSha256.length);
state.bufferIndices[0] = handshakeTy;

@@ -530,47 +594,1 @@ state.instance.exports.connection_open_multi_stream(connectionId, 0);

exports.startLocalInstance = startLocalInstance;
// TODO: consider moving this function somewhere else or something
function parseMultiaddr(address, forbidTcp, forbidWs, forbidNonLocalWs, forbidWss, forbidWebRtc) {
const tcpParsed = address.match(/^\/(ip4|ip6|dns4|dns6|dns)\/(.*?)\/tcp\/(.*?)$/);
// TODO: remove support for `/wss` in a long time (https://github.com/paritytech/smoldot/issues/1940)
const wsParsed = address.match(/^\/(ip4|ip6|dns4|dns6|dns)\/(.*?)\/tcp\/(.*?)\/(ws|wss|tls\/ws)$/);
const webRTCParsed = address.match(/^\/(ip4|ip6)\/(.*?)\/udp\/(.*?)\/webrtc-direct\/certhash\/(.*?)$/);
if (wsParsed != null) {
const proto = (wsParsed[4] == 'ws') ? 'ws' : 'wss';
if (proto == 'ws' && forbidWs) {
return { success: false, error: 'WebSocket connections not available' };
}
if (proto == 'wss' && forbidWss) {
return { success: false, error: 'WebSocket secure connections not available' };
}
if (proto == 'ws' && wsParsed[2] != 'localhost' && wsParsed[2] != '127.0.0.1' && forbidNonLocalWs) {
return { success: false, error: 'Non-local WebSocket connections not available' };
}
const url = (wsParsed[1] == 'ip6') ?
(proto + "://[" + wsParsed[2] + "]:" + wsParsed[3]) :
(proto + "://" + wsParsed[2] + ":" + wsParsed[3]);
return { success: true, address: { ty: "websocket", url } };
}
else if (tcpParsed != null) {
if (forbidTcp) {
return { success: false, error: 'TCP connections not available' };
}
return { success: true, address: { ty: "tcp", hostname: tcpParsed[2], port: parseInt(tcpParsed[3]) } };
}
else if (webRTCParsed != null) {
const targetPort = webRTCParsed[3];
if (forbidWebRtc) {
return { success: false, error: 'WebRTC connections not available' };
}
if (targetPort === '0') {
return { success: false, error: 'Invalid WebRTC target port' };
}
const ipVersion = webRTCParsed[1] == 'ip4' ? '4' : '6';
const targetIp = webRTCParsed[2];
const remoteCertMultibase = webRTCParsed[4];
return { success: true, address: { ty: "webrtc", targetPort, ipVersion, targetIp, remoteCertMultibase } };
}
else {
return { success: false, error: 'Unrecognized multiaddr format' };
}
}
exports.parseMultiaddr = parseMultiaddr;

@@ -17,3 +17,2 @@ "use strict";

const client_js_1 = require("./internals/client.js");
const base64_js_1 = require("./internals/base64.js");
var public_types_js_1 = require("./public-types.js");

@@ -111,3 +110,3 @@ Object.defineProperty(exports, "AddChainError", { enumerable: true, get: function () { return public_types_js_1.AddChainError; } });

type: 'single-stream', handshake: 'multistream-select-noise-yamux',
initialWritableBytes: 1024 * 1024, writeClosable: false,
initialWritableBytes: 1024 * 1024
});

@@ -164,9 +163,3 @@ };

else if (config.address.ty === "webrtc") {
const { targetPort, ipVersion, targetIp, remoteCertMultibase } = config.address;
// The payload of `/certhash` is the hash of the self-generated certificate that the
// server presents.
// This function throws an exception if the certhash isn't correct. For this reason, this call
// is performed as part of the parsing of the multiaddr.
const remoteCertMultihash = (0, base64_js_1.multibaseBase64Decode)(remoteCertMultibase);
const remoteCertSha256Hash = multihashToSha256(remoteCertMultihash);
const { targetPort, ipVersion, targetIp, remoteTlsCertificateSha256 } = config.address;
// TODO: detect localhost for Firefox? https://bugzilla.mozilla.org/show_bug.cgi?id=1659672

@@ -185,6 +178,6 @@ // Note that `pc` can be the connection, but also null or undefined.

let handshakeDataChannel;
// Multihash-encoded DTLS certificate of the local node. Unknown as long as it hasn't been
// SHA256 hash of the DTLS certificate of the local node. Unknown as long as it hasn't been
// generated.
// TODO: could be merged with `pc` in one variable, and maybe even the other fields as well
let localTlsCertificateMultihash;
let localTlsCertificateSha256;
// Kills all the JavaScript objects (the connection and all its substreams), ensuring that no

@@ -239,4 +232,4 @@ // callback will be called again. Doesn't report anything to smoldot, as this should be done

// value is always defined.
localTlsCertificateMultihash: localTlsCertificateMultihash,
remoteTlsCertificateMultihash: remoteCertMultihash
localTlsCertificateSha256: localTlsCertificateSha256,
remoteTlsCertificateSha256,
});

@@ -346,5 +339,4 @@ }

}
localTlsCertificateMultihash = new Uint8Array(34);
localTlsCertificateMultihash.set([0x12, 32], 0);
localTlsCertificateMultihash.set(localTlsCertificateHex.split(':').map((s) => parseInt(s, 16)), 2);
localTlsCertificateSha256 = new Uint8Array(32);
localTlsCertificateSha256.set(localTlsCertificateHex.split(':').map((s) => parseInt(s, 16)), 0);
// `onconnectionstatechange` is used to detect when the connection has closed or has failed

@@ -385,3 +377,3 @@ // to open.

// Transform certificate hash into fingerprint (upper-hex; each byte separated by ":").
const fingerprint = Array.from(remoteCertSha256Hash).map((n) => ("0" + n.toString(16)).slice(-2).toUpperCase()).join(':');
const fingerprint = Array.from(remoteTlsCertificateSha256).map((n) => ("0" + n.toString(16)).slice(-2).toUpperCase()).join(':');
// Note that the trailing line feed is important, as otherwise Chrome

@@ -413,3 +405,3 @@ // fails to parse the payload.

// RFCs: 8839, 8866, 8841
"m=application " + targetPort + " " + "UDP/DTLS/SCTP webrtc-datachannel" + "\n" +
"m=application " + String(targetPort) + " " + "UDP/DTLS/SCTP webrtc-datachannel" + "\n" +
// Indicates the IP address of the remote.

@@ -445,3 +437,3 @@ // Note that "IN" means "Internet" (and not "input").

// checks (RFC8839).
"a=candidate:1 1 UDP 1 " + targetIp + " " + targetPort + " typ host" + "\n";
"a=candidate:1 1 UDP 1 " + targetIp + " " + String(targetPort) + " typ host" + "\n";
yield pc.setRemoteDescription({ type: "answer", sdp: remoteSdp });

@@ -518,10 +510,1 @@ });

}
/// Parses a multihash-multibase-encoded string into a SHA256 hash.
///
/// Throws an exception if the multihash algorithm isn't SHA256.
const multihashToSha256 = (certMultihash) => {
if (certMultihash.length != 34 || certMultihash[0] != 0x12 || certMultihash[1] != 32) {
throw new Error('Certificate multihash is not SHA-256');
}
return new Uint8Array(certMultihash.slice(2));
};

@@ -83,3 +83,3 @@ "use strict";

socket.onopen = () => {
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024, writeClosable: false });
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
};

@@ -139,3 +139,3 @@ socket.onclose = (event) => {

established === null || established === void 0 ? void 0 : established.setNoDelay();
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024, writeClosable: true });
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
// Spawns an asynchronous task that continuously reads from the socket.

@@ -142,0 +142,0 @@ // Every time data is read, the task re-executes itself in order to continue reading.

@@ -79,3 +79,3 @@ "use strict";

socket.onopen = () => {
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024, writeClosable: false });
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
};

@@ -135,3 +135,3 @@ socket.onclose = (event) => {

type: 'single-stream', handshake: 'multistream-select-noise-yamux',
initialWritableBytes: socket.writableHighWaterMark, writeClosable: true
initialWritableBytes: socket.writableHighWaterMark
});

@@ -138,0 +138,0 @@ });

export declare function utf8BytesToString(buffer: Uint8Array, offset: number, length: number): string;
export declare function readUInt8(buffer: Uint8Array, offset: number): number;
export declare function readUInt16BE(buffer: Uint8Array, offset: number): number;
export declare function readUInt32LE(buffer: Uint8Array, offset: number): number;

@@ -3,0 +5,0 @@ /**

@@ -20,2 +20,10 @@ // Smoldot

}
export function readUInt8(buffer, offset) {
checkRange(buffer, offset, 1);
return buffer[offset];
}
export function readUInt16BE(buffer, offset) {
checkRange(buffer, offset, 2);
return ((buffer[offset] << 8) | buffer[offset + 1]);
}
export function readUInt32LE(buffer, offset) {

@@ -22,0 +30,0 @@ checkRange(buffer, offset, 4);

@@ -123,8 +123,7 @@ import { Client, ClientOptions, SmoldotBytecode } from '../public-types.js';

initialWritableBytes: number;
writeClosable: boolean;
} | {
type: 'multi-stream';
handshake: 'webrtc';
localTlsCertificateMultihash: Uint8Array;
remoteTlsCertificateMultihash: Uint8Array;
localTlsCertificateSha256: Uint8Array;
remoteTlsCertificateSha256: Uint8Array;
}) => void;

@@ -131,0 +130,0 @@ /**

@@ -287,4 +287,7 @@ // Smoldot

}
// Sanitize `databaseContent`.
if (options.databaseContent !== undefined && typeof options.databaseContent !== 'string')
throw new AddChainError("`databaseContent` is not a string");
const promise = new Promise((resolve) => state.addChainResults.push(resolve));
state.instance.instance.addChain(options.chainSpec, typeof options.databaseContent === 'string' ? options.databaseContent : "", potentialRelayChainsIds, !!options.disableJsonRpc, jsonRpcMaxPendingRequests, jsonRpcMaxSubscriptions);
state.instance.instance.addChain(options.chainSpec, options.databaseContent || "", potentialRelayChainsIds, !!options.disableJsonRpc, jsonRpcMaxPendingRequests, jsonRpcMaxSubscriptions);
const outcome = yield promise;

@@ -291,0 +294,0 @@ if (!outcome.success)

@@ -87,6 +87,6 @@ /**

ty: "webrtc";
targetPort: string;
targetPort: number;
ipVersion: string;
targetIp: string;
remoteCertMultibase: string;
remoteTlsCertificateSha256: Uint8Array;
};

@@ -111,8 +111,7 @@ export interface Instance {

initialWritableBytes: number;
writeClosable: boolean;
} | {
type: 'multi-stream';
handshake: 'webrtc';
localTlsCertificateMultihash: Uint8Array;
remoteTlsCertificateMultihash: Uint8Array;
localTlsCertificateSha256: Uint8Array;
remoteTlsCertificateSha256: Uint8Array;
}) => void;

@@ -138,8 +137,1 @@ connectionReset: (connectionId: number, message: string) => void;

export declare function startLocalInstance(config: Config, wasmModule: WebAssembly.Module, eventCallback: (event: Event) => void): Promise<Instance>;
export declare function parseMultiaddr(address: string, forbidTcp: boolean, forbidWs: boolean, forbidNonLocalWs: boolean, forbidWss: boolean, forbidWebRtc: boolean): {
success: true;
address: ParsedMultiaddr;
} | {
success: false;
error: string;
};

@@ -127,22 +127,86 @@ // Smoldot

},
// Must indicate whether the given connection type is supported.
connection_type_supported: (ty) => {
// TODO: consider extracting config options so user can't change the fields dynamically
switch (ty) {
case 0:
case 1:
case 2: {
return config.forbidTcp ? 0 : 1;
}
case 4:
case 5:
case 6: {
return config.forbidWs ? 0 : 1;
}
case 7: {
return config.forbidNonLocalWs ? 0 : 1;
}
case 14: {
return config.forbidWss ? 0 : 1;
}
case 16:
case 17: {
return config.forbidWebRtc ? 0 : 1;
}
default:
// Indicates a bug somewhere.
throw new Error("Invalid connection type passed to `connection_type_supported`");
}
},
// Must create a new connection object. This implementation stores the created object in
// `connections`.
connection_new: (connectionId, addrPtr, addrLen, errorBufferIndexPtr) => {
connection_new: (connectionId, addrPtr, addrLen) => {
const instance = state.instance;
const mem = new Uint8Array(instance.exports.memory.buffer);
addrPtr >>>= 0;
addrLen >>>= 0;
errorBufferIndexPtr >>>= 0;
const address = buffer.utf8BytesToString(new Uint8Array(instance.exports.memory.buffer), addrPtr, addrLen);
// TODO: consider extracting config options so user can't change the fields dynamically
const result = parseMultiaddr(address, config.forbidTcp, config.forbidWs, config.forbidNonLocalWs, config.forbidWss, config.forbidWebRtc);
if (result.success) {
eventCallback({ ty: "new-connection", connectionId, address: result.address });
return 0;
let address;
switch (buffer.readUInt8(mem, addrPtr)) {
case 0:
case 1:
case 2: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "tcp", port, hostname };
break;
}
case 4:
case 6: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "websocket", url: "ws://" + hostname + ":" + port };
break;
}
case 5: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "websocket", url: "ws://[" + hostname + "]:" + port };
break;
}
case 14: {
const port = buffer.readUInt16BE(mem, addrPtr + 1);
const hostname = buffer.utf8BytesToString(mem, addrPtr + 3, addrLen - 3);
address = { ty: "websocket", url: "wss://" + hostname + ":" + port };
break;
}
case 16: {
const targetPort = buffer.readUInt16BE(mem, addrPtr + 1);
const remoteTlsCertificateSha256 = mem.slice(addrPtr + 3, addrPtr + 35);
const targetIp = buffer.utf8BytesToString(mem, addrPtr + 35, addrLen - 3);
address = { ty: "webrtc", ipVersion: '4', remoteTlsCertificateSha256, targetIp, targetPort };
break;
}
case 17: {
const targetPort = buffer.readUInt16BE(mem, addrPtr + 1);
const remoteTlsCertificateSha256 = mem.slice(addrPtr + 3, addrPtr + 35);
const targetIp = buffer.utf8BytesToString(mem, addrPtr + 35, addrLen - 3);
address = { ty: "webrtc", ipVersion: '6', remoteTlsCertificateSha256, targetIp, targetPort };
break;
}
default:
// Indicates a bug somewhere.
throw new Error("Invalid encoded address passed to `connection_new`");
}
else {
const mem = new Uint8Array(instance.exports.memory.buffer);
state.bufferIndices[0] = new TextEncoder().encode(result.error);
buffer.writeUInt32LE(mem, errorBufferIndexPtr, 0);
return 1;
}
eventCallback({ ty: "new-connection", connectionId, address });
},

@@ -477,10 +541,10 @@ // Must close and destroy the connection object.

case 'single-stream': {
state.instance.exports.connection_open_single_stream(connectionId, 0, info.initialWritableBytes, info.writeClosable ? 1 : 0);
state.instance.exports.connection_open_single_stream(connectionId, info.initialWritableBytes);
break;
}
case 'multi-stream': {
const handshakeTy = new Uint8Array(1 + info.localTlsCertificateMultihash.length + info.remoteTlsCertificateMultihash.length);
const handshakeTy = new Uint8Array(1 + info.localTlsCertificateSha256.length + info.remoteTlsCertificateSha256.length);
buffer.writeUInt8(handshakeTy, 0, 0);
handshakeTy.set(info.localTlsCertificateMultihash, 1);
handshakeTy.set(info.remoteTlsCertificateMultihash, 1 + info.localTlsCertificateMultihash.length);
handshakeTy.set(info.localTlsCertificateSha256, 1);
handshakeTy.set(info.remoteTlsCertificateSha256, 1 + info.localTlsCertificateSha256.length);
state.bufferIndices[0] = handshakeTy;

@@ -525,46 +589,1 @@ state.instance.exports.connection_open_multi_stream(connectionId, 0);

}
// TODO: consider moving this function somewhere else or something
export function parseMultiaddr(address, forbidTcp, forbidWs, forbidNonLocalWs, forbidWss, forbidWebRtc) {
const tcpParsed = address.match(/^\/(ip4|ip6|dns4|dns6|dns)\/(.*?)\/tcp\/(.*?)$/);
// TODO: remove support for `/wss` in a long time (https://github.com/paritytech/smoldot/issues/1940)
const wsParsed = address.match(/^\/(ip4|ip6|dns4|dns6|dns)\/(.*?)\/tcp\/(.*?)\/(ws|wss|tls\/ws)$/);
const webRTCParsed = address.match(/^\/(ip4|ip6)\/(.*?)\/udp\/(.*?)\/webrtc-direct\/certhash\/(.*?)$/);
if (wsParsed != null) {
const proto = (wsParsed[4] == 'ws') ? 'ws' : 'wss';
if (proto == 'ws' && forbidWs) {
return { success: false, error: 'WebSocket connections not available' };
}
if (proto == 'wss' && forbidWss) {
return { success: false, error: 'WebSocket secure connections not available' };
}
if (proto == 'ws' && wsParsed[2] != 'localhost' && wsParsed[2] != '127.0.0.1' && forbidNonLocalWs) {
return { success: false, error: 'Non-local WebSocket connections not available' };
}
const url = (wsParsed[1] == 'ip6') ?
(proto + "://[" + wsParsed[2] + "]:" + wsParsed[3]) :
(proto + "://" + wsParsed[2] + ":" + wsParsed[3]);
return { success: true, address: { ty: "websocket", url } };
}
else if (tcpParsed != null) {
if (forbidTcp) {
return { success: false, error: 'TCP connections not available' };
}
return { success: true, address: { ty: "tcp", hostname: tcpParsed[2], port: parseInt(tcpParsed[3]) } };
}
else if (webRTCParsed != null) {
const targetPort = webRTCParsed[3];
if (forbidWebRtc) {
return { success: false, error: 'WebRTC connections not available' };
}
if (targetPort === '0') {
return { success: false, error: 'Invalid WebRTC target port' };
}
const ipVersion = webRTCParsed[1] == 'ip4' ? '4' : '6';
const targetIp = webRTCParsed[2];
const remoteCertMultibase = webRTCParsed[4];
return { success: true, address: { ty: "webrtc", targetPort, ipVersion, targetIp, remoteCertMultibase } };
}
else {
return { success: false, error: 'Unrecognized multiaddr format' };
}
}

@@ -14,3 +14,2 @@ // Smoldot

import { start as innerStart } from './internals/client.js';
import { multibaseBase64Decode } from './internals/base64.js';
export { AddChainError, AlreadyDestroyedError, CrashError, JsonRpcDisabledError, MalformedJsonRpcError, QueueFullError } from './public-types.js';

@@ -101,3 +100,3 @@ /**

type: 'single-stream', handshake: 'multistream-select-noise-yamux',
initialWritableBytes: 1024 * 1024, writeClosable: false,
initialWritableBytes: 1024 * 1024
});

@@ -154,9 +153,3 @@ };

else if (config.address.ty === "webrtc") {
const { targetPort, ipVersion, targetIp, remoteCertMultibase } = config.address;
// The payload of `/certhash` is the hash of the self-generated certificate that the
// server presents.
// This function throws an exception if the certhash isn't correct. For this reason, this call
// is performed as part of the parsing of the multiaddr.
const remoteCertMultihash = multibaseBase64Decode(remoteCertMultibase);
const remoteCertSha256Hash = multihashToSha256(remoteCertMultihash);
const { targetPort, ipVersion, targetIp, remoteTlsCertificateSha256 } = config.address;
// TODO: detect localhost for Firefox? https://bugzilla.mozilla.org/show_bug.cgi?id=1659672

@@ -175,6 +168,6 @@ // Note that `pc` can be the connection, but also null or undefined.

let handshakeDataChannel;
// Multihash-encoded DTLS certificate of the local node. Unknown as long as it hasn't been
// SHA256 hash of the DTLS certificate of the local node. Unknown as long as it hasn't been
// generated.
// TODO: could be merged with `pc` in one variable, and maybe even the other fields as well
let localTlsCertificateMultihash;
let localTlsCertificateSha256;
// Kills all the JavaScript objects (the connection and all its substreams), ensuring that no

@@ -229,4 +222,4 @@ // callback will be called again. Doesn't report anything to smoldot, as this should be done

// value is always defined.
localTlsCertificateMultihash: localTlsCertificateMultihash,
remoteTlsCertificateMultihash: remoteCertMultihash
localTlsCertificateSha256: localTlsCertificateSha256,
remoteTlsCertificateSha256,
});

@@ -336,5 +329,4 @@ }

}
localTlsCertificateMultihash = new Uint8Array(34);
localTlsCertificateMultihash.set([0x12, 32], 0);
localTlsCertificateMultihash.set(localTlsCertificateHex.split(':').map((s) => parseInt(s, 16)), 2);
localTlsCertificateSha256 = new Uint8Array(32);
localTlsCertificateSha256.set(localTlsCertificateHex.split(':').map((s) => parseInt(s, 16)), 0);
// `onconnectionstatechange` is used to detect when the connection has closed or has failed

@@ -375,3 +367,3 @@ // to open.

// Transform certificate hash into fingerprint (upper-hex; each byte separated by ":").
const fingerprint = Array.from(remoteCertSha256Hash).map((n) => ("0" + n.toString(16)).slice(-2).toUpperCase()).join(':');
const fingerprint = Array.from(remoteTlsCertificateSha256).map((n) => ("0" + n.toString(16)).slice(-2).toUpperCase()).join(':');
// Note that the trailing line feed is important, as otherwise Chrome

@@ -403,3 +395,3 @@ // fails to parse the payload.

// RFCs: 8839, 8866, 8841
"m=application " + targetPort + " " + "UDP/DTLS/SCTP webrtc-datachannel" + "\n" +
"m=application " + String(targetPort) + " " + "UDP/DTLS/SCTP webrtc-datachannel" + "\n" +
// Indicates the IP address of the remote.

@@ -435,3 +427,3 @@ // Note that "IN" means "Internet" (and not "input").

// checks (RFC8839).
"a=candidate:1 1 UDP 1 " + targetIp + " " + targetPort + " typ host" + "\n";
"a=candidate:1 1 UDP 1 " + targetIp + " " + String(targetPort) + " typ host" + "\n";
yield pc.setRemoteDescription({ type: "answer", sdp: remoteSdp });

@@ -508,10 +500,1 @@ });

}
/// Parses a multihash-multibase-encoded string into a SHA256 hash.
///
/// Throws an exception if the multihash algorithm isn't SHA256.
const multihashToSha256 = (certMultihash) => {
if (certMultihash.length != 34 || certMultihash[0] != 0x12 || certMultihash[1] != 32) {
throw new Error('Certificate multihash is not SHA-256');
}
return new Uint8Array(certMultihash.slice(2));
};

@@ -73,3 +73,3 @@ // Smoldot

socket.onopen = () => {
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024, writeClosable: false });
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
};

@@ -129,3 +129,3 @@ socket.onclose = (event) => {

established === null || established === void 0 ? void 0 : established.setNoDelay();
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024, writeClosable: true });
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
// Spawns an asynchronous task that continuously reads from the socket.

@@ -132,0 +132,0 @@ // Every time data is read, the task re-executes itself in order to continue reading.

@@ -69,3 +69,3 @@ // Smoldot

socket.onopen = () => {
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024, writeClosable: false });
config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
};

@@ -125,3 +125,3 @@ socket.onclose = (event) => {

type: 'single-stream', handshake: 'multistream-select-noise-yamux',
initialWritableBytes: socket.writableHighWaterMark, writeClosable: true
initialWritableBytes: socket.writableHighWaterMark
});

@@ -128,0 +128,0 @@ });

{
"name": "smoldot",
"version": "1.0.11",
"version": "1.0.12",
"description": "Light client that connects to Polkadot and Substrate-based blockchains",

@@ -5,0 +5,0 @@ "contributors": [

@@ -128,1 +128,8 @@ # Light client for Polkadot and Substrate-based chains

```
Note that importing sub-paths (for example importing `smoldot/worker`) relies on a relatively
modern JavaScript feature. If you import a smoldot sub-path from a TypeScript file, you might have
to configure TypeScript to use `"moduleResolution": "node16"`. [The official TypeScript
documentation itself recommends setting this configuration option to
`node`](https://www.typescriptlang.org/docs/handbook/module-resolution.html#module-resolution-strategies),
and it is likely that `node16` becomes the go-to module resolution scheme in the future.

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc