@waku/core 0.0.26 → 0.0.28-070b625.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 (66) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/bundle/{base_protocol-pDODy0G6.js → base_protocol-D0Zdzb-v.js} +134 -89
  3. package/bundle/{browser-mTOOnVZp.js → browser-DoQRY-an.js} +518 -712
  4. package/bundle/{index-cmONXM-V.js → index-BJwgMx4y.js} +116 -88
  5. package/bundle/index.js +2967 -21667
  6. package/bundle/lib/base_protocol.js +3 -3
  7. package/bundle/lib/message/version_0.js +3 -3
  8. package/bundle/lib/predefined_bootstrap_nodes.js +17 -17
  9. package/bundle/version_0-C6o0DvNW.js +4055 -0
  10. package/dist/.tsbuildinfo +1 -1
  11. package/dist/index.d.ts +3 -6
  12. package/dist/index.js +3 -6
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/base_protocol.d.ts +15 -13
  15. package/dist/lib/base_protocol.js +35 -22
  16. package/dist/lib/base_protocol.js.map +1 -1
  17. package/dist/lib/connection_manager.d.ts +2 -2
  18. package/dist/lib/connection_manager.js +16 -6
  19. package/dist/lib/connection_manager.js.map +1 -1
  20. package/dist/lib/filter/index.d.ts +1 -1
  21. package/dist/lib/filter/index.js +144 -82
  22. package/dist/lib/filter/index.js.map +1 -1
  23. package/dist/lib/filterPeers.d.ts +8 -5
  24. package/dist/lib/filterPeers.js +12 -5
  25. package/dist/lib/filterPeers.js.map +1 -1
  26. package/dist/lib/keep_alive_manager.d.ts +2 -3
  27. package/dist/lib/keep_alive_manager.js.map +1 -1
  28. package/dist/lib/light_push/index.d.ts +12 -2
  29. package/dist/lib/light_push/index.js +80 -80
  30. package/dist/lib/light_push/index.js.map +1 -1
  31. package/dist/lib/message/version_0.js +1 -1
  32. package/dist/lib/message/version_0.js.map +1 -1
  33. package/dist/lib/metadata/index.d.ts +2 -2
  34. package/dist/lib/metadata/index.js +58 -16
  35. package/dist/lib/metadata/index.js.map +1 -1
  36. package/dist/lib/predefined_bootstrap_nodes.d.ts +11 -11
  37. package/dist/lib/predefined_bootstrap_nodes.js +16 -16
  38. package/dist/lib/predefined_bootstrap_nodes.js.map +1 -1
  39. package/dist/lib/store/history_rpc.js +1 -1
  40. package/dist/lib/store/history_rpc.js.map +1 -1
  41. package/dist/lib/store/index.d.ts +14 -6
  42. package/dist/lib/store/index.js +51 -235
  43. package/dist/lib/store/index.js.map +1 -1
  44. package/dist/lib/stream_manager.d.ts +2 -2
  45. package/dist/lib/stream_manager.js.map +1 -1
  46. package/dist/lib/wait_for_remote_peer.d.ts +1 -1
  47. package/dist/lib/wait_for_remote_peer.js +42 -10
  48. package/dist/lib/wait_for_remote_peer.js.map +1 -1
  49. package/package.json +1 -127
  50. package/src/index.ts +3 -7
  51. package/src/lib/base_protocol.ts +57 -37
  52. package/src/lib/connection_manager.ts +17 -10
  53. package/src/lib/filter/index.ts +234 -136
  54. package/src/lib/filterPeers.ts +15 -7
  55. package/src/lib/keep_alive_manager.ts +2 -3
  56. package/src/lib/light_push/index.ts +104 -124
  57. package/src/lib/metadata/index.ts +92 -30
  58. package/src/lib/predefined_bootstrap_nodes.ts +22 -22
  59. package/src/lib/store/index.ts +79 -344
  60. package/src/lib/stream_manager.ts +2 -3
  61. package/src/lib/wait_for_remote_peer.ts +68 -12
  62. package/bundle/version_0-LQTFNC7k.js +0 -5008
  63. package/dist/lib/waku.d.ts +0 -57
  64. package/dist/lib/waku.js +0 -130
  65. package/dist/lib/waku.js.map +0 -1
  66. package/src/lib/waku.ts +0 -214
package/CHANGELOG.md CHANGED
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
5
5
  The file is maintained by [Release Please](https://github.com/googleapis/release-please) based on [Conventional Commits](https://www.conventionalcommits.org) specification,
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.0.27](https://github.com/waku-org/js-waku/compare/core-v0.0.26...core-v0.0.27) (2024-03-04)
9
+
10
+
11
+ ### ⚠ BREAKING CHANGES
12
+
13
+ * protocols filter peers as per configured shard ([#1756](https://github.com/waku-org/js-waku/issues/1756))
14
+
15
+ ### Features
16
+
17
+ * Create node and subscription by content topic ([ee2d417](https://github.com/waku-org/js-waku/commit/ee2d4176f8cca45a51b7dac0009f0eb01952f540))
18
+ * Decouple sharding params out of core ([e138b4f](https://github.com/waku-org/js-waku/commit/e138b4f5c49a35a37830e31e8be87d824f53249f))
19
+ * Lightpush & filter send requests to multiple peers ([#1779](https://github.com/waku-org/js-waku/issues/1779)) ([7affbe2](https://github.com/waku-org/js-waku/commit/7affbe222dd30ccb6619839f4bc5eb86433a80f7))
20
+ * Local discovery ([#1811](https://github.com/waku-org/js-waku/issues/1811)) ([199f6ab](https://github.com/waku-org/js-waku/commit/199f6ab2ff83694b93e94e935e2925537e01e281))
21
+ * Make ShardingParams optional in sdk, required internally ([68d3229](https://github.com/waku-org/js-waku/commit/68d3229644f395bd84b2e2a7067c7b51e9da3dd0))
22
+ * Protocols filter peers as per configured shard ([#1756](https://github.com/waku-org/js-waku/issues/1756)) ([477c2a5](https://github.com/waku-org/js-waku/commit/477c2a5918f2f75cd2c14bc6ed75e1687c5a09b4))
23
+
24
+
25
+ ### Dependencies
26
+
27
+ * The following workspace dependencies were updated
28
+ * dependencies
29
+ * @waku/enr bumped from ^0.0.20 to ^0.0.21
30
+ * @waku/interfaces bumped from 0.0.21 to 0.0.22
31
+ * @waku/message-hash bumped from ^0.1.10 to ^0.1.11
32
+ * @waku/utils bumped from 0.0.14 to 0.0.15
33
+
8
34
  ## [0.0.26](https://github.com/waku-org/js-waku/compare/core-v0.0.25...core-v0.0.26) (2024-01-10)
9
35
 
10
36
 
@@ -1,39 +1,86 @@
1
- import { T as Tags } from './browser-mTOOnVZp.js';
2
- import { k as bytesToUtf8, L as Logger, s as shardInfoToPubsubTopics, D as DefaultPubsubTopic } from './index-cmONXM-V.js';
1
+ import { b as bytesToUtf8, L as Logger, j as ensureShardingConfigured } from './index-BJwgMx4y.js';
2
+ import { T as Tags } from './browser-DoQRY-an.js';
3
+
4
+ const decodeRelayShard = (bytes) => {
5
+ // explicitly converting to Uint8Array to avoid Buffer
6
+ // https://github.com/libp2p/js-libp2p/issues/2146
7
+ bytes = new Uint8Array(bytes);
8
+ if (bytes.length < 3)
9
+ throw new Error("Insufficient data");
10
+ const view = new DataView(bytes.buffer);
11
+ const clusterId = view.getUint16(0);
12
+ const shards = [];
13
+ if (bytes.length === 130) {
14
+ // rsv format (Bit Vector)
15
+ for (let i = 0; i < 1024; i++) {
16
+ const byteIndex = Math.floor(i / 8) + 2; // Adjusted for the 2-byte cluster field
17
+ const bitIndex = 7 - (i % 8);
18
+ if (view.getUint8(byteIndex) & (1 << bitIndex)) {
19
+ shards.push(i);
20
+ }
21
+ }
22
+ }
23
+ else {
24
+ // rs format (Index List)
25
+ const numIndices = view.getUint8(2);
26
+ for (let i = 0, offset = 3; i < numIndices; i++, offset += 2) {
27
+ if (offset + 1 >= bytes.length)
28
+ throw new Error("Unexpected end of data");
29
+ shards.push(view.getUint16(offset));
30
+ }
31
+ }
32
+ return { clusterId, shards };
33
+ };
34
+ const encodeRelayShard = (shardInfo) => {
35
+ const { clusterId, shards } = shardInfo;
36
+ const totalLength = shards.length >= 64 ? 130 : 3 + 2 * shards.length;
37
+ const buffer = new ArrayBuffer(totalLength);
38
+ const view = new DataView(buffer);
39
+ view.setUint16(0, clusterId);
40
+ if (shards.length >= 64) {
41
+ // rsv format (Bit Vector)
42
+ for (const index of shards) {
43
+ const byteIndex = Math.floor(index / 8) + 2; // Adjusted for the 2-byte cluster field
44
+ const bitIndex = 7 - (index % 8);
45
+ view.setUint8(byteIndex, view.getUint8(byteIndex) | (1 << bitIndex));
46
+ }
47
+ }
48
+ else {
49
+ // rs format (Index List)
50
+ view.setUint8(2, shards.length);
51
+ for (let i = 0, offset = 3; i < shards.length; i++, offset += 2) {
52
+ view.setUint16(offset, shards[i]);
53
+ }
54
+ }
55
+ return new Uint8Array(buffer);
56
+ };
3
57
 
4
58
  /**
5
- * Returns a pseudo-random peer that supports the given protocol.
6
- * Useful for protocols such as store and light push
7
- */
8
- function selectRandomPeer(peers) {
9
- if (peers.length === 0)
10
- return;
11
- const index = Math.round(Math.random() * (peers.length - 1));
12
- return peers[index];
13
- }
14
- /**
15
- * Returns the peer with the lowest latency.
59
+ * Function to sort peers by latency from lowest to highest
16
60
  * @param peerStore - The Libp2p PeerStore
17
61
  * @param peers - The list of peers to choose from
18
- * @returns The peer with the lowest latency, or undefined if no peer could be reached
62
+ * @returns Sorted array of peers by latency
19
63
  */
20
- async function selectLowestLatencyPeer(peerStore, peers) {
64
+ async function sortPeersByLatency(peerStore, peers) {
21
65
  if (peers.length === 0)
22
- return;
66
+ return [];
23
67
  const results = await Promise.all(peers.map(async (peer) => {
24
- const pingBytes = (await peerStore.get(peer.id)).metadata.get("ping");
25
- if (!pingBytes)
68
+ try {
69
+ const pingBytes = (await peerStore.get(peer.id)).metadata.get("ping");
70
+ if (!pingBytes)
71
+ return { peer, ping: Infinity };
72
+ const ping = Number(bytesToUtf8(pingBytes));
73
+ return { peer, ping };
74
+ }
75
+ catch (error) {
26
76
  return { peer, ping: Infinity };
27
- const ping = Number(bytesToUtf8(pingBytes)) ?? Infinity;
28
- return { peer, ping };
77
+ }
29
78
  }));
30
- const lowestLatencyResult = results.sort((a, b) => a.ping - b.ping)[0];
31
- if (!lowestLatencyResult) {
32
- return undefined;
33
- }
34
- return lowestLatencyResult.ping !== Infinity
35
- ? lowestLatencyResult.peer
36
- : undefined;
79
+ // filter out null values
80
+ const validResults = results.filter((result) => result !== null);
81
+ return validResults
82
+ .sort((a, b) => a.ping - b.ping)
83
+ .map((result) => result.peer);
37
84
  }
38
85
  /**
39
86
  * Returns the list of peers that supports the given protocol.
@@ -50,51 +97,28 @@ async function getPeersForProtocol(peerStore, protocols) {
50
97
  });
51
98
  return peers;
52
99
  }
53
- async function getConnectedPeersForProtocol(connections, peerStore, protocols) {
100
+ async function getConnectedPeersForProtocolAndShard(connections, peerStore, protocols, shardInfo) {
54
101
  const openConnections = connections.filter((connection) => connection.status === "open");
55
102
  const peerPromises = openConnections.map(async (connection) => {
56
103
  const peer = await peerStore.get(connection.remotePeer);
57
- const supportsProtocol = peer.protocols.some((protocol) => protocols.includes(protocol));
58
- return supportsProtocol ? peer : null;
104
+ const supportsProtocol = protocols.some((protocol) => peer.protocols.includes(protocol));
105
+ if (supportsProtocol) {
106
+ if (shardInfo) {
107
+ const encodedPeerShardInfo = peer.metadata.get("shardInfo");
108
+ const peerShardInfo = encodedPeerShardInfo && decodeRelayShard(encodedPeerShardInfo);
109
+ if (peerShardInfo && shardInfo.clusterId === peerShardInfo.clusterId) {
110
+ return peer;
111
+ }
112
+ }
113
+ else {
114
+ return peer;
115
+ }
116
+ }
117
+ return null;
59
118
  });
60
119
  const peersWithNulls = await Promise.all(peerPromises);
61
120
  return peersWithNulls.filter((peer) => peer !== null);
62
121
  }
63
- /**
64
- * Returns a peer that supports the given protocol.
65
- * If peerId is provided, the peer with that id is returned.
66
- * Otherwise, the peer with the lowest latency is returned.
67
- * If no peer is found from the above criteria, a random peer is returned.
68
- */
69
- async function selectPeerForProtocol(peerStore, protocols, peerId) {
70
- let peer;
71
- if (peerId) {
72
- peer = await peerStore.get(peerId);
73
- if (!peer) {
74
- throw new Error(`Failed to retrieve connection details for provided peer in peer store: ${peerId.toString()}`);
75
- }
76
- }
77
- else {
78
- const peers = await getPeersForProtocol(peerStore, protocols);
79
- peer = await selectLowestLatencyPeer(peerStore, peers);
80
- if (!peer) {
81
- peer = selectRandomPeer(peers);
82
- if (!peer)
83
- throw new Error(`Failed to find known peer that registers protocols: ${protocols}`);
84
- }
85
- }
86
- let protocol;
87
- for (const codec of protocols) {
88
- if (peer.protocols.includes(codec)) {
89
- protocol = codec;
90
- // Do not break as we want to keep the last value
91
- }
92
- }
93
- if (!protocol) {
94
- throw new Error(`Peer does not register required protocols (${peer.id.toString()}): ${protocols}`);
95
- }
96
- return { peer, protocol };
97
- }
98
122
  function selectConnection(connections) {
99
123
  if (!connections.length)
100
124
  return;
@@ -115,18 +139,25 @@ function selectConnection(connections) {
115
139
  }
116
140
 
117
141
  /**
118
- * Retrieves a list of peers based on the specified criteria.
142
+ * Retrieves a list of peers based on the specified criteria:
143
+ * 1. If numPeers is 0, return all peers
144
+ * 2. Bootstrap peers are prioritized
145
+ * 3. Non-bootstrap peers are randomly selected to fill up to numPeers
119
146
  *
120
147
  * @param peers - The list of peers to filter from.
121
- * @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
148
+ * @param numPeers - The total number of peers to retrieve. If 0, all peers are returned, irrespective of `maxBootstrapPeers`.
122
149
  * @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
123
- * @returns A Promise that resolves to an array of peers based on the specified criteria.
150
+ * @returns An array of peers based on the specified criteria.
124
151
  */
125
- async function filterPeers(peers, numPeers, maxBootstrapPeers) {
152
+ function filterPeersByDiscovery(peers, numPeers, maxBootstrapPeers) {
126
153
  // Collect the bootstrap peers up to the specified maximum
127
- const bootstrapPeers = peers
154
+ let bootstrapPeers = peers
128
155
  .filter((peer) => peer.tags.has(Tags.BOOTSTRAP))
129
156
  .slice(0, maxBootstrapPeers);
157
+ // If numPeers is less than the number of bootstrap peers, adjust the bootstrapPeers array
158
+ if (numPeers > 0 && numPeers < bootstrapPeers.length) {
159
+ bootstrapPeers = bootstrapPeers.slice(0, numPeers);
160
+ }
130
161
  // Collect non-bootstrap peers
131
162
  const nonBootstrapPeers = peers.filter((peer) => !peer.tags.has(Tags.BOOTSTRAP));
132
163
  // If numPeers is 0, return all peers
@@ -205,12 +236,18 @@ class StreamManager {
205
236
  class BaseProtocol {
206
237
  multicodec;
207
238
  components;
239
+ log;
240
+ pubsubTopics;
241
+ options;
208
242
  addLibp2pEventListener;
209
243
  removeLibp2pEventListener;
210
244
  streamManager;
211
- constructor(multicodec, components) {
245
+ constructor(multicodec, components, log, pubsubTopics, options) {
212
246
  this.multicodec = multicodec;
213
247
  this.components = components;
248
+ this.log = log;
249
+ this.pubsubTopics = pubsubTopics;
250
+ this.options = options;
214
251
  this.addLibp2pEventListener = components.events.addEventListener.bind(components.events);
215
252
  this.removeLibp2pEventListener = components.events.removeEventListener.bind(components.events);
216
253
  this.streamManager = new StreamManager(multicodec, components.connectionManager.getConnections.bind(components.connectionManager), this.addLibp2pEventListener);
@@ -226,35 +263,43 @@ class BaseProtocol {
226
263
  * the class protocol. Waku may or may not be currently connected to these
227
264
  * peers.
228
265
  */
229
- async peers() {
266
+ async allPeers() {
230
267
  return getPeersForProtocol(this.peerStore, [this.multicodec]);
231
268
  }
232
- async getPeer(peerId) {
233
- const { peer } = await selectPeerForProtocol(this.peerStore, [this.multicodec], peerId);
234
- return peer;
269
+ async connectedPeers() {
270
+ const peers = await this.allPeers();
271
+ return peers.filter((peer) => {
272
+ return (this.components.connectionManager.getConnections(peer.id).length > 0);
273
+ });
235
274
  }
236
275
  /**
237
- * Retrieves a list of connected peers based on the specified criteria.
276
+ * Retrieves a list of connected peers that support the protocol. The list is sorted by latency.
238
277
  *
239
278
  * @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
240
279
  * @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
241
- * @returns A Promise that resolves to an array of peers based on the specified criteria.
242
- */
280
+
281
+ * @returns A list of peers that support the protocol sorted by latency.
282
+ */
243
283
  async getPeers({ numPeers, maxBootstrapPeers } = {
244
284
  maxBootstrapPeers: 1,
245
285
  numPeers: 0
246
286
  }) {
247
- // Retrieve all connected peers that support the protocol
248
- const allPeersForProtocol = await getConnectedPeersForProtocol(this.components.connectionManager.getConnections(), this.peerStore, [this.multicodec]);
249
- // Filter the peers based on the specified criteria
250
- return filterPeers(allPeersForProtocol, numPeers, maxBootstrapPeers);
251
- }
252
- initializePubsubTopic(options) {
253
- return (options?.pubsubTopics ??
254
- (options?.shardInfo
255
- ? shardInfoToPubsubTopics(options.shardInfo)
256
- : [DefaultPubsubTopic]));
287
+ // Retrieve all connected peers that support the protocol & shard (if configured)
288
+ const connectedPeersForProtocolAndShard = await getConnectedPeersForProtocolAndShard(this.components.connectionManager.getConnections(), this.peerStore, [this.multicodec], this.options?.shardInfo
289
+ ? ensureShardingConfigured(this.options.shardInfo).shardInfo
290
+ : undefined);
291
+ // Filter the peers based on discovery & number of peers requested
292
+ const filteredPeers = filterPeersByDiscovery(connectedPeersForProtocolAndShard, numPeers, maxBootstrapPeers);
293
+ // Sort the peers by latency
294
+ const sortedFilteredPeers = await sortPeersByLatency(this.peerStore, filteredPeers);
295
+ if (sortedFilteredPeers.length === 0) {
296
+ this.log.warn("No peers found. Ensure you have a connection to the network.");
297
+ }
298
+ if (sortedFilteredPeers.length < numPeers) {
299
+ this.log.warn(`Only ${sortedFilteredPeers.length} peers found. Requested ${numPeers}.`);
300
+ }
301
+ return sortedFilteredPeers;
257
302
  }
258
303
  }
259
304
 
260
- export { BaseProtocol as B, StreamManager as S };
305
+ export { BaseProtocol as B, StreamManager as S, decodeRelayShard as d, encodeRelayShard as e };