smoldot 2.0.10 → 2.0.12

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.
@@ -68,7 +68,7 @@ export interface Connection {
68
68
  *
69
69
  * Must not be called after `closeSend` has been called.
70
70
  */
71
- send(data: Uint8Array, streamId?: number): void;
71
+ send(data: Array<Uint8Array>, streamId?: number): void;
72
72
  /**
73
73
  * Closes the writing side of the given stream of the given connection.
74
74
  *
@@ -69,7 +69,7 @@ export type Event = {
69
69
  ty: "stream-send";
70
70
  connectionId: number;
71
71
  streamId?: number;
72
- data: Uint8Array;
72
+ data: Array<Uint8Array>;
73
73
  } | {
74
74
  ty: "stream-send-close";
75
75
  connectionId: number;
@@ -247,9 +247,15 @@ export function startLocalInstance(config, wasmModule, eventCallback) {
247
247
  // that this function is called only when the connection is in an open state.
248
248
  stream_send: (connectionId, streamId, ptr, len) => {
249
249
  const instance = state.instance;
250
+ const mem = new Uint8Array(instance.exports.memory.buffer);
250
251
  ptr >>>= 0;
251
252
  len >>>= 0;
252
- const data = new Uint8Array(instance.exports.memory.buffer).slice(ptr, ptr + len);
253
+ const data = new Array();
254
+ for (let i = 0; i < len; ++i) {
255
+ const bufPtr = buffer.readUInt32LE(mem, ptr + 8 * i);
256
+ const bufLen = buffer.readUInt32LE(mem, ptr + 8 * i + 4);
257
+ data.push(mem.slice(bufPtr, bufPtr + bufLen));
258
+ }
253
259
  // TODO: docs says the streamId is provided only for multi-stream connections, but here it's always provided
254
260
  eventCallback({ ty: "stream-send", connectionId, streamId, data });
255
261
  },
@@ -21,6 +21,19 @@ export { AddChainError, AlreadyDestroyedError, CrashError, JsonRpcDisabledError,
21
21
  */
22
22
  export function startWithBytecode(options) {
23
23
  options.forbidTcp = true;
24
+ // When in a secure context, browsers refuse to open non-secure WebSocket connections to
25
+ // non-localhost. There is an exception if the page is localhost, in which case all connections
26
+ // are allowed.
27
+ // Detecting this ahead of time is better for the overall health of the client, as it will
28
+ // avoid storing in memory addresses that it knows it can't connect to.
29
+ // The condition below is a hint, and false-positives or false-negatives are not fundamentally
30
+ // an issue.
31
+ if ((typeof isSecureContext === 'boolean' && isSecureContext) && typeof location !== undefined) {
32
+ const loc = location.toString();
33
+ if (loc.indexOf('localhost') !== -1 && loc.indexOf('127.0.0.1') !== -1 && loc.indexOf('::1') !== -1) {
34
+ options.forbidNonLocalWs = true;
35
+ }
36
+ }
24
37
  return innerStart(options, options.bytecode, {
25
38
  performanceNow: () => {
26
39
  return performance.now();
@@ -133,12 +146,14 @@ function connect(config) {
133
146
  connection = null;
134
147
  },
135
148
  send: (data) => {
136
- connection.send(data);
137
149
  if (bufferedAmountCheck.quenedUnreportedBytes == 0) {
138
150
  bufferedAmountCheck.nextTimeout = 10;
139
151
  setTimeout(checkBufferedAmount, 10);
140
152
  }
141
- bufferedAmountCheck.quenedUnreportedBytes += data.length;
153
+ for (const buffer of data) {
154
+ bufferedAmountCheck.quenedUnreportedBytes += buffer.length;
155
+ }
156
+ connection.send(new Blob(data));
142
157
  },
143
158
  closeSend: () => { throw new Error('Wrong connection type'); },
144
159
  openOutSubstream: () => { throw new Error('Wrong connection type'); }
@@ -409,8 +424,10 @@ function connect(config) {
409
424
  },
410
425
  send: (data, streamId) => {
411
426
  const channel = state.dataChannels.get(streamId);
412
- channel.channel.send(data);
413
- channel.bufferedBytes += data.length;
427
+ for (const buffer of data) {
428
+ channel.bufferedBytes += buffer.length;
429
+ }
430
+ channel.channel.send(new Blob(data));
414
431
  },
415
432
  closeSend: () => { throw new Error('Wrong connection type'); },
416
433
  openOutSubstream: () => {
@@ -96,12 +96,14 @@ function connect(config) {
96
96
  // we thus absorb any exception thrown here.
97
97
  // See also <https://github.com/paritytech/smoldot/issues/2937>.
98
98
  try {
99
- socket.send(data);
100
99
  if (bufferedAmountCheck.quenedUnreportedBytes == 0) {
101
100
  bufferedAmountCheck.nextTimeout = 10;
102
101
  setTimeout(checkBufferedAmount, 10);
103
102
  }
104
- bufferedAmountCheck.quenedUnreportedBytes += data.length;
103
+ for (const buffer of data) {
104
+ bufferedAmountCheck.quenedUnreportedBytes += buffer.length;
105
+ }
106
+ socket.send(new Blob(data));
105
107
  }
106
108
  catch (_error) { }
107
109
  },
@@ -163,31 +165,35 @@ function connect(config) {
163
165
  socket.inner.then((connec) => connec.close());
164
166
  },
165
167
  send: (data) => {
166
- let dataCopy = Uint8Array.from(data); // Deep copy of the data
168
+ let dataCopy = data.map((buf) => Uint8Array.from(buf)); // Deep copy of the data
167
169
  socket.inner = socket.inner.then((c) => __awaiter(this, void 0, void 0, function* () {
168
- while (dataCopy.length > 0) {
169
- if (socket.destroyed || c === null)
170
- return c;
171
- let outcome;
172
- try {
173
- outcome = yield c.write(dataCopy);
174
- config.onWritableBytes(dataCopy.length);
175
- }
176
- catch (error) {
177
- // The type of `error` is unclear, but we assume that it implements `Error`
178
- outcome = error.toString();
179
- }
180
- if (typeof outcome !== 'number') {
181
- // The socket is reported closed, but `socket.destroyed` is still
182
- // `false` (see check above). As such, we must inform the inner layers.
183
- socket.destroyed = true;
184
- config.onConnectionReset(outcome);
185
- return c;
170
+ for (let buffer of dataCopy) {
171
+ while (buffer.length > 0) {
172
+ if (socket.destroyed || c === null)
173
+ return c;
174
+ let outcome;
175
+ try {
176
+ outcome = yield c.write(buffer);
177
+ config.onWritableBytes(buffer.length);
178
+ }
179
+ catch (error) {
180
+ // The type of `error` is unclear, but we assume that it
181
+ // implements `Error`
182
+ outcome = error.toString();
183
+ }
184
+ if (typeof outcome !== 'number') {
185
+ // The socket is reported closed, but `socket.destroyed` is still
186
+ // `false` (see check above). As such, we must inform the
187
+ // inner layers.
188
+ socket.destroyed = true;
189
+ config.onConnectionReset(outcome);
190
+ return c;
191
+ }
192
+ // Note that, contrary to `read`, it is possible for `outcome` to be 0.
193
+ // This happen if the write had to be interrupted, and the only thing
194
+ // we have to do is try writing again.
195
+ buffer = buffer.slice(outcome);
186
196
  }
187
- // Note that, contrary to `read`, it is possible for `outcome` to be 0.
188
- // This happen if the write had to be interrupted, and the only thing
189
- // we have to do is try writing again.
190
- dataCopy = dataCopy.slice(outcome);
191
197
  }
192
198
  return c;
193
199
  }));
@@ -97,12 +97,14 @@ function connect(config) {
97
97
  socket.close();
98
98
  },
99
99
  send: (data) => {
100
- socket.send(data);
101
100
  if (bufferedAmountCheck.quenedUnreportedBytes == 0) {
102
101
  bufferedAmountCheck.nextTimeout = 10;
103
102
  setTimeout(checkBufferedAmount, 10);
104
103
  }
105
- bufferedAmountCheck.quenedUnreportedBytes += data.length;
104
+ for (const buffer of data) {
105
+ socket.send(buffer);
106
+ bufferedAmountCheck.quenedUnreportedBytes += buffer.length;
107
+ }
106
108
  },
107
109
  closeSend: () => { throw new Error('Wrong connection type'); },
108
110
  openOutSubstream: () => { throw new Error('Wrong connection type'); }
@@ -149,17 +151,19 @@ function connect(config) {
149
151
  socket.destroy();
150
152
  },
151
153
  send: (data) => {
152
- const dataLen = data.length;
153
- const allWritten = socket.write(data);
154
- if (allWritten) {
155
- setImmediate(() => {
156
- if (!socket.writable)
157
- return;
158
- config.onWritableBytes(dataLen);
159
- });
160
- }
161
- else {
162
- drainingBytes.num += dataLen;
154
+ for (const buffer of data) {
155
+ const bufferLen = buffer.length;
156
+ const allWritten = socket.write(buffer);
157
+ if (allWritten) {
158
+ setImmediate(() => {
159
+ if (!socket.writable)
160
+ return;
161
+ config.onWritableBytes(bufferLen);
162
+ });
163
+ }
164
+ else {
165
+ drainingBytes.num += bufferLen;
166
+ }
163
167
  }
164
168
  },
165
169
  closeSend: () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smoldot",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Light client that connects to Polkadot and Substrate-based blockchains",
5
5
  "contributors": [
6
6
  "Parity Technologies <admin@parity.io>",
@@ -80,7 +80,7 @@
80
80
  "@types/ws": "^8.5.3",
81
81
  "ava": "^5.0.1",
82
82
  "dtslint": "^4.0.6",
83
- "typedoc": "^0.25.0",
84
- "typescript": "^5.1.3"
83
+ "typedoc": "^0.25.4",
84
+ "typescript": "^5.3.2"
85
85
  }
86
86
  }