@waku/core 0.0.33-00c3261.0 → 0.0.33-11bf1c1.0

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.
Files changed (34) hide show
  1. package/bundle/{base_protocol-iQ9XIkPz.js → base_protocol-Dzv-QHPR.js} +55 -122
  2. package/bundle/{index-tdQNdKHx.js → index-BIW3qNYx.js} +19 -450
  3. package/bundle/index.js +100 -417
  4. package/bundle/lib/base_protocol.js +2 -2
  5. package/bundle/lib/message/version_0.js +2 -2
  6. package/bundle/{version_0-BrbNEwD-.js → version_0-CdmZMfkQ.js} +451 -2
  7. package/dist/.tsbuildinfo +1 -1
  8. package/dist/index.d.ts +1 -2
  9. package/dist/index.js +1 -2
  10. package/dist/index.js.map +1 -1
  11. package/dist/lib/base_protocol.d.ts +4 -6
  12. package/dist/lib/base_protocol.js +10 -14
  13. package/dist/lib/base_protocol.js.map +1 -1
  14. package/dist/lib/filter/index.js +2 -2
  15. package/dist/lib/filter/index.js.map +1 -1
  16. package/dist/lib/metadata/index.js +1 -1
  17. package/dist/lib/metadata/index.js.map +1 -1
  18. package/dist/lib/stream_manager/stream_manager.d.ts +6 -4
  19. package/dist/lib/stream_manager/stream_manager.js +40 -16
  20. package/dist/lib/stream_manager/stream_manager.js.map +1 -1
  21. package/dist/lib/stream_manager/utils.d.ts +1 -1
  22. package/dist/lib/stream_manager/utils.js +5 -17
  23. package/dist/lib/stream_manager/utils.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/index.ts +1 -3
  26. package/src/lib/base_protocol.ts +14 -28
  27. package/src/lib/filter/index.ts +5 -2
  28. package/src/lib/metadata/index.ts +1 -1
  29. package/src/lib/stream_manager/stream_manager.ts +52 -31
  30. package/src/lib/stream_manager/utils.ts +5 -17
  31. package/dist/lib/wait_for_remote_peer.d.ts +0 -22
  32. package/dist/lib/wait_for_remote_peer.js +0 -142
  33. package/dist/lib/wait_for_remote_peer.js.map +0 -1
  34. package/src/lib/wait_for_remote_peer.ts +0 -200
@@ -1,58 +1,4 @@
1
- import { h as bytesToUtf8, T as Tags, L as Logger, e as pubsubTopicsToShardInfo } from './index-tdQNdKHx.js';
2
-
3
- const decodeRelayShard = (bytes) => {
4
- // explicitly converting to Uint8Array to avoid Buffer
5
- // https://github.com/libp2p/js-libp2p/issues/2146
6
- bytes = new Uint8Array(bytes);
7
- if (bytes.length < 3)
8
- throw new Error("Insufficient data");
9
- const view = new DataView(bytes.buffer);
10
- const clusterId = view.getUint16(0);
11
- const shards = [];
12
- if (bytes.length === 130) {
13
- // rsv format (Bit Vector)
14
- for (let i = 0; i < 1024; i++) {
15
- const byteIndex = Math.floor(i / 8) + 2; // Adjusted for the 2-byte cluster field
16
- const bitIndex = 7 - (i % 8);
17
- if (view.getUint8(byteIndex) & (1 << bitIndex)) {
18
- shards.push(i);
19
- }
20
- }
21
- }
22
- else {
23
- // rs format (Index List)
24
- const numIndices = view.getUint8(2);
25
- for (let i = 0, offset = 3; i < numIndices; i++, offset += 2) {
26
- if (offset + 1 >= bytes.length)
27
- throw new Error("Unexpected end of data");
28
- shards.push(view.getUint16(offset));
29
- }
30
- }
31
- return { clusterId, shards };
32
- };
33
- const encodeRelayShard = (shardInfo) => {
34
- const { clusterId, shards } = shardInfo;
35
- const totalLength = shards.length >= 64 ? 130 : 3 + 2 * shards.length;
36
- const buffer = new ArrayBuffer(totalLength);
37
- const view = new DataView(buffer);
38
- view.setUint16(0, clusterId);
39
- if (shards.length >= 64) {
40
- // rsv format (Bit Vector)
41
- for (const index of shards) {
42
- const byteIndex = Math.floor(index / 8) + 2; // Adjusted for the 2-byte cluster field
43
- const bitIndex = 7 - (index % 8);
44
- view.setUint8(byteIndex, view.getUint8(byteIndex) | (1 << bitIndex));
45
- }
46
- }
47
- else {
48
- // rs format (Index List)
49
- view.setUint8(2, shards.length);
50
- for (let i = 0, offset = 3; i < shards.length; i++, offset += 2) {
51
- view.setUint16(offset, shards[i]);
52
- }
53
- }
54
- return new Uint8Array(buffer);
55
- };
1
+ import { g as bytesToUtf8, T as Tags, L as Logger } from './index-BIW3qNYx.js';
56
2
 
57
3
  /**
58
4
  * Function to sort peers by latency from lowest to highest
@@ -96,28 +42,6 @@ async function getPeersForProtocol(peerStore, protocols) {
96
42
  });
97
43
  return peers;
98
44
  }
99
- async function getConnectedPeersForProtocolAndShard(connections, peerStore, protocols, shardInfo) {
100
- const openConnections = connections.filter((connection) => connection.status === "open");
101
- const peerPromises = openConnections.map(async (connection) => {
102
- const peer = await peerStore.get(connection.remotePeer);
103
- const supportsProtocol = protocols.some((protocol) => peer.protocols.includes(protocol));
104
- if (supportsProtocol) {
105
- if (shardInfo) {
106
- const encodedPeerShardInfo = peer.metadata.get("shardInfo");
107
- const peerShardInfo = encodedPeerShardInfo && decodeRelayShard(encodedPeerShardInfo);
108
- if (peerShardInfo && shardInfo.clusterId === peerShardInfo.clusterId) {
109
- return peer;
110
- }
111
- }
112
- else {
113
- return peer;
114
- }
115
- }
116
- return null;
117
- });
118
- const peersWithNulls = await Promise.all(peerPromises);
119
- return peersWithNulls.filter((peer) => peer !== null);
120
- }
121
45
 
122
46
  /**
123
47
  * Retrieves a list of peers based on the specified criteria:
@@ -156,26 +80,14 @@ function filterPeersByDiscovery(peers, numPeers, maxBootstrapPeers) {
156
80
  return selectedPeers;
157
81
  }
158
82
 
159
- function selectConnection(connections) {
160
- if (!connections.length)
161
- return;
162
- if (connections.length === 1)
163
- return connections[0];
164
- let latestConnection;
165
- connections.forEach((connection) => {
166
- if (connection.status === "open") {
167
- if (!latestConnection) {
168
- latestConnection = connection;
169
- }
170
- else if (connection.timeline.open > latestConnection.timeline.open) {
171
- latestConnection = connection;
172
- }
173
- }
174
- });
175
- return latestConnection;
83
+ function selectOpenConnection(connections) {
84
+ return connections
85
+ .filter((c) => c.status === "open")
86
+ .sort((left, right) => right.timeline.open - left.timeline.open)
87
+ .at(0);
176
88
  }
177
89
 
178
- const CONNECTION_TIMEOUT = 5_000;
90
+ const STREAM_LOCK_KEY = "consumed";
179
91
  class StreamManager {
180
92
  multicodec;
181
93
  getConnections;
@@ -193,18 +105,23 @@ class StreamManager {
193
105
  async getStream(peer) {
194
106
  const peerId = peer.id.toString();
195
107
  const scheduledStream = this.streamPool.get(peerId);
196
- this.streamPool.delete(peerId);
197
- await scheduledStream;
198
- const stream = this.getStreamForCodec(peer.id);
108
+ if (scheduledStream) {
109
+ this.streamPool.delete(peerId);
110
+ await scheduledStream;
111
+ }
112
+ let stream = this.getOpenStreamForCodec(peer.id);
199
113
  if (stream) {
200
114
  this.log.info(`Found existing stream peerId=${peer.id.toString()} multicodec=${this.multicodec}`);
115
+ this.lockStream(peer.id.toString(), stream);
201
116
  return stream;
202
117
  }
203
- return this.createStream(peer);
118
+ stream = await this.createStream(peer);
119
+ this.lockStream(peer.id.toString(), stream);
120
+ return stream;
204
121
  }
205
122
  async createStream(peer, retries = 0) {
206
123
  const connections = this.getConnections(peer.id);
207
- const connection = selectConnection(connections);
124
+ const connection = selectOpenConnection(connections);
208
125
  if (!connection) {
209
126
  throw new Error(`Failed to get a connection to the peer peerId=${peer.id.toString()} multicodec=${this.multicodec}`);
210
127
  }
@@ -215,6 +132,7 @@ class StreamManager {
215
132
  this.log.info(`Attempting to create a stream for peerId=${peer.id.toString()} multicodec=${this.multicodec}`);
216
133
  stream = await connection.newStream(this.multicodec);
217
134
  this.log.info(`Created stream for peerId=${peer.id.toString()} multicodec=${this.multicodec}`);
135
+ break;
218
136
  }
219
137
  catch (error) {
220
138
  lastError = error;
@@ -236,16 +154,20 @@ class StreamManager {
236
154
  this.ongoingCreation.add(peerId);
237
155
  await this.createStream(peer);
238
156
  }
157
+ catch (error) {
158
+ this.log.error(`Failed to createStreamWithLock:`, error);
159
+ }
239
160
  finally {
240
161
  this.ongoingCreation.delete(peerId);
241
162
  }
163
+ return;
242
164
  }
243
165
  handlePeerUpdateStreamPool = (evt) => {
244
166
  const { peer } = evt.detail;
245
167
  if (!peer.protocols.includes(this.multicodec)) {
246
168
  return;
247
169
  }
248
- const stream = this.getStreamForCodec(peer.id);
170
+ const stream = this.getOpenStreamForCodec(peer.id);
249
171
  if (stream) {
250
172
  return;
251
173
  }
@@ -253,21 +175,35 @@ class StreamManager {
253
175
  };
254
176
  scheduleNewStream(peer) {
255
177
  this.log.info(`Scheduling creation of a stream for peerId=${peer.id.toString()} multicodec=${this.multicodec}`);
256
- const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve(undefined), CONNECTION_TIMEOUT));
257
- const streamPromise = Promise.race([
258
- this.createStreamWithLock(peer),
259
- timeoutPromise
260
- ]);
261
- this.streamPool.set(peer.id.toString(), streamPromise);
178
+ // abandon previous attempt
179
+ if (this.streamPool.has(peer.id.toString())) {
180
+ this.streamPool.delete(peer.id.toString());
181
+ }
182
+ this.streamPool.set(peer.id.toString(), this.createStreamWithLock(peer));
262
183
  }
263
- getStreamForCodec(peerId) {
264
- const connection = this.getConnections(peerId).find((c) => c.status === "open");
184
+ getOpenStreamForCodec(peerId) {
185
+ const connections = this.getConnections(peerId);
186
+ const connection = selectOpenConnection(connections);
265
187
  if (!connection) {
266
188
  return;
267
189
  }
268
190
  const stream = connection.streams.find((s) => s.protocol === this.multicodec);
191
+ if (!stream) {
192
+ return;
193
+ }
194
+ const isStreamUnusable = ["done", "closed", "closing"].includes(stream.writeStatus || "");
195
+ if (isStreamUnusable || this.isStreamLocked(stream)) {
196
+ return;
197
+ }
269
198
  return stream;
270
199
  }
200
+ lockStream(peerId, stream) {
201
+ this.log.info(`Locking stream for peerId:${peerId}\tstreamId:${stream.id}`);
202
+ stream.metadata[STREAM_LOCK_KEY] = true;
203
+ }
204
+ isStreamLocked(stream) {
205
+ return !!stream.metadata[STREAM_LOCK_KEY];
206
+ }
271
207
  }
272
208
 
273
209
  /**
@@ -294,21 +230,19 @@ class BaseProtocol {
294
230
  async getStream(peer) {
295
231
  return this.streamManager.getStream(peer);
296
232
  }
297
- get peerStore() {
298
- return this.components.peerStore;
299
- }
300
233
  /**
301
234
  * Returns known peers from the address book (`libp2p.peerStore`) that support
302
235
  * the class protocol. Waku may or may not be currently connected to these
303
236
  * peers.
304
237
  */
305
238
  async allPeers() {
306
- return getPeersForProtocol(this.peerStore, [this.multicodec]);
239
+ return getPeersForProtocol(this.components.peerStore, [this.multicodec]);
307
240
  }
308
241
  async connectedPeers() {
309
242
  const peers = await this.allPeers();
310
243
  return peers.filter((peer) => {
311
- return (this.components.connectionManager.getConnections(peer.id).length > 0);
244
+ const connections = this.components.connectionManager.getConnections(peer.id);
245
+ return connections.length > 0;
312
246
  });
313
247
  }
314
248
  /**
@@ -316,19 +250,18 @@ class BaseProtocol {
316
250
  *
317
251
  * @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
318
252
  * @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
319
-
320
- * @returns A list of peers that support the protocol sorted by latency.
321
- */
253
+ * @returns A list of peers that support the protocol sorted by latency. By default, returns all peers available, including bootstrap.
254
+ */
322
255
  async getPeers({ numPeers, maxBootstrapPeers } = {
323
- maxBootstrapPeers: 1,
256
+ maxBootstrapPeers: 0,
324
257
  numPeers: 0
325
258
  }) {
326
259
  // Retrieve all connected peers that support the protocol & shard (if configured)
327
- const connectedPeersForProtocolAndShard = await getConnectedPeersForProtocolAndShard(this.components.connectionManager.getConnections(), this.peerStore, [this.multicodec], pubsubTopicsToShardInfo(this.pubsubTopics));
260
+ const allAvailableConnectedPeers = await this.connectedPeers();
328
261
  // Filter the peers based on discovery & number of peers requested
329
- const filteredPeers = filterPeersByDiscovery(connectedPeersForProtocolAndShard, numPeers, maxBootstrapPeers);
262
+ const filteredPeers = filterPeersByDiscovery(allAvailableConnectedPeers, numPeers, maxBootstrapPeers);
330
263
  // Sort the peers by latency
331
- const sortedFilteredPeers = await sortPeersByLatency(this.peerStore, filteredPeers);
264
+ const sortedFilteredPeers = await sortPeersByLatency(this.components.peerStore, filteredPeers);
332
265
  if (sortedFilteredPeers.length === 0) {
333
266
  this.log.warn("No peers found. Ensure you have a connection to the network.");
334
267
  }
@@ -339,4 +272,4 @@ class BaseProtocol {
339
272
  }
340
273
  }
341
274
 
342
- export { BaseProtocol as B, StreamManager as S, decodeRelayShard as d, encodeRelayShard as e };
275
+ export { BaseProtocol as B, StreamManager as S };