@waku/discovery 0.0.11-e224c05.0 → 0.0.11-e800af3.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.
- package/bundle/index.js +324 -384
- package/dist/.tsbuildinfo +1 -1
- package/dist/dns/constants.d.ts +1 -2
- package/dist/dns/constants.js +0 -5
- package/dist/dns/constants.js.map +1 -1
- package/dist/dns/dns.d.ts +3 -12
- package/dist/dns/dns.js +16 -39
- package/dist/dns/dns.js.map +1 -1
- package/dist/dns/dns_discovery.d.ts +3 -3
- package/dist/dns/dns_discovery.js +6 -7
- package/dist/dns/dns_discovery.js.map +1 -1
- package/dist/dns/fetch_nodes.d.ts +5 -11
- package/dist/dns/fetch_nodes.js +15 -117
- package/dist/dns/fetch_nodes.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -6
- package/dist/index.js.map +1 -1
- package/dist/peer-cache/constants.d.ts +3 -0
- package/dist/peer-cache/constants.js +4 -0
- package/dist/peer-cache/constants.js.map +1 -0
- package/dist/peer-cache/index.d.ts +1 -0
- package/dist/peer-cache/index.js +2 -0
- package/dist/peer-cache/index.js.map +1 -0
- package/dist/peer-cache/peer_cache.d.ts +17 -0
- package/dist/peer-cache/peer_cache.js +99 -0
- package/dist/peer-cache/peer_cache.js.map +1 -0
- package/dist/peer-cache/utils.d.ts +2 -0
- package/dist/peer-cache/utils.js +65 -0
- package/dist/peer-cache/utils.js.map +1 -0
- package/dist/peer-exchange/constants.d.ts +6 -0
- package/dist/peer-exchange/constants.js +8 -0
- package/dist/peer-exchange/constants.js.map +1 -0
- package/dist/peer-exchange/index.d.ts +2 -2
- package/dist/peer-exchange/index.js +2 -2
- package/dist/peer-exchange/index.js.map +1 -1
- package/dist/peer-exchange/{waku_peer_exchange.d.ts → peer_exchange.d.ts} +1 -7
- package/dist/peer-exchange/{waku_peer_exchange.js → peer_exchange.js} +8 -18
- package/dist/peer-exchange/peer_exchange.js.map +1 -0
- package/dist/peer-exchange/peer_exchange_discovery.d.ts +42 -0
- package/dist/peer-exchange/peer_exchange_discovery.js +165 -0
- package/dist/peer-exchange/peer_exchange_discovery.js.map +1 -0
- package/package.json +1 -1
- package/src/dns/constants.ts +1 -7
- package/src/dns/dns.ts +20 -68
- package/src/dns/dns_discovery.ts +10 -16
- package/src/dns/fetch_nodes.ts +20 -157
- package/src/index.ts +6 -13
- package/src/peer-cache/constants.ts +4 -0
- package/src/peer-cache/index.ts +1 -0
- package/src/peer-cache/peer_cache.ts +152 -0
- package/src/peer-cache/utils.ts +73 -0
- package/src/peer-exchange/constants.ts +10 -0
- package/src/peer-exchange/index.ts +3 -8
- package/src/peer-exchange/{waku_peer_exchange.ts → peer_exchange.ts} +10 -20
- package/src/peer-exchange/peer_exchange_discovery.ts +264 -0
- package/dist/local-peer-cache/index.d.ts +0 -23
- package/dist/local-peer-cache/index.js +0 -110
- package/dist/local-peer-cache/index.js.map +0 -1
- package/dist/peer-exchange/waku_peer_exchange.js.map +0 -1
- package/dist/peer-exchange/waku_peer_exchange_discovery.d.ts +0 -57
- package/dist/peer-exchange/waku_peer_exchange_discovery.js +0 -182
- package/dist/peer-exchange/waku_peer_exchange_discovery.js.map +0 -1
- package/src/local-peer-cache/index.ts +0 -163
- package/src/peer-exchange/waku_peer_exchange_discovery.ts +0 -317
package/bundle/index.js
CHANGED
|
@@ -286,12 +286,18 @@ var ProtocolError;
|
|
|
286
286
|
ProtocolError["INVALID_DECODER_TOPICS"] = "Invalid decoder topics";
|
|
287
287
|
})(ProtocolError || (ProtocolError = {}));
|
|
288
288
|
|
|
289
|
+
var WakuEventType;
|
|
290
|
+
(function (WakuEventType) {
|
|
291
|
+
WakuEventType["Connection"] = "waku:connection";
|
|
292
|
+
WakuEventType["Health"] = "waku:health";
|
|
293
|
+
})(WakuEventType || (WakuEventType = {}));
|
|
294
|
+
|
|
289
295
|
// Peer tags
|
|
290
296
|
var Tags;
|
|
291
297
|
(function (Tags) {
|
|
292
298
|
Tags["BOOTSTRAP"] = "bootstrap";
|
|
293
299
|
Tags["PEER_EXCHANGE"] = "peer-exchange";
|
|
294
|
-
Tags["
|
|
300
|
+
Tags["PEER_CACHE"] = "peer-cache";
|
|
295
301
|
})(Tags || (Tags = {}));
|
|
296
302
|
|
|
297
303
|
const DNS_DISCOVERY_TAG = "@waku/bootstrap";
|
|
@@ -316,6 +322,25 @@ function isDefined(value) {
|
|
|
316
322
|
return Boolean(value);
|
|
317
323
|
}
|
|
318
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Return pseudo random subset of the input.
|
|
327
|
+
*/
|
|
328
|
+
function shuffle(arr) {
|
|
329
|
+
if (arr.length <= 1) {
|
|
330
|
+
return arr;
|
|
331
|
+
}
|
|
332
|
+
const randInt = () => {
|
|
333
|
+
return Math.floor(Math.random() * Math.floor(arr.length));
|
|
334
|
+
};
|
|
335
|
+
for (let i = 0; i < arr.length; i++) {
|
|
336
|
+
const j = randInt();
|
|
337
|
+
const tmp = arr[i];
|
|
338
|
+
arr[i] = arr[j];
|
|
339
|
+
arr[j] = tmp;
|
|
340
|
+
}
|
|
341
|
+
return arr;
|
|
342
|
+
}
|
|
343
|
+
|
|
319
344
|
const crypto$2 = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
|
|
320
345
|
|
|
321
346
|
/**
|
|
@@ -2355,14 +2380,6 @@ const encodeRelayShard = (shardInfo) => {
|
|
|
2355
2380
|
return new Uint8Array(buffer);
|
|
2356
2381
|
};
|
|
2357
2382
|
|
|
2358
|
-
function getWsMultiaddrFromMultiaddrs(addresses) {
|
|
2359
|
-
const wsMultiaddr = addresses.find((addr) => addr.toString().includes("ws") || addr.toString().includes("wss"));
|
|
2360
|
-
if (!wsMultiaddr) {
|
|
2361
|
-
throw new Error("No ws multiaddr found in the given addresses");
|
|
2362
|
-
}
|
|
2363
|
-
return wsMultiaddr;
|
|
2364
|
-
}
|
|
2365
|
-
|
|
2366
2383
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
2367
2384
|
|
|
2368
2385
|
function getDefaultExportFromCjs (x) {
|
|
@@ -3151,11 +3168,6 @@ const enrTree = {
|
|
|
3151
3168
|
const DEFAULT_BOOTSTRAP_TAG_NAME = Tags.BOOTSTRAP;
|
|
3152
3169
|
const DEFAULT_BOOTSTRAP_TAG_VALUE = 50;
|
|
3153
3170
|
const DEFAULT_BOOTSTRAP_TAG_TTL = 100_000_000;
|
|
3154
|
-
const DEFAULT_NODE_REQUIREMENTS = {
|
|
3155
|
-
store: 1,
|
|
3156
|
-
filter: 2,
|
|
3157
|
-
lightPush: 2
|
|
3158
|
-
};
|
|
3159
3171
|
|
|
3160
3172
|
// Maximum encoded size of an ENR
|
|
3161
3173
|
const ERR_INVALID_ID = "Invalid record id";
|
|
@@ -15099,188 +15111,63 @@ class ENRTree {
|
|
|
15099
15111
|
|
|
15100
15112
|
const log$5 = new Logger$1("discovery:fetch_nodes");
|
|
15101
15113
|
/**
|
|
15102
|
-
* Fetch nodes using passed [[getNode]] until
|
|
15103
|
-
*
|
|
15104
|
-
*
|
|
15114
|
+
* Fetch nodes using passed [[getNode]] until it has been called [[maxGet]]
|
|
15115
|
+
* times, or it has returned empty or duplicate results more than [[maxErrors]]
|
|
15116
|
+
* times.
|
|
15105
15117
|
*/
|
|
15106
|
-
async function
|
|
15107
|
-
const
|
|
15108
|
-
relay: wantedNodeCapabilityCount.relay ?? 0,
|
|
15109
|
-
store: wantedNodeCapabilityCount.store ?? 0,
|
|
15110
|
-
filter: wantedNodeCapabilityCount.filter ?? 0,
|
|
15111
|
-
lightPush: wantedNodeCapabilityCount.lightPush ?? 0
|
|
15112
|
-
};
|
|
15113
|
-
const maxSearches = wanted.relay + wanted.store + wanted.filter + wanted.lightPush;
|
|
15114
|
-
const actual = {
|
|
15115
|
-
relay: 0,
|
|
15116
|
-
store: 0,
|
|
15117
|
-
filter: 0,
|
|
15118
|
-
lightPush: 0
|
|
15119
|
-
};
|
|
15118
|
+
async function* fetchNodes(getNode, maxGet = 10, maxErrors = 3) {
|
|
15119
|
+
const peerNodeIds = new Set();
|
|
15120
15120
|
let totalSearches = 0;
|
|
15121
|
-
|
|
15122
|
-
while (
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
if (peer && isNewPeer(peer, peers)) {
|
|
15126
|
-
// ENRs without a waku2 key are ignored.
|
|
15127
|
-
if (peer.waku2) {
|
|
15128
|
-
if (helpsSatisfyCapabilities(peer.waku2, wanted, actual)) {
|
|
15129
|
-
addCapabilities(peer.waku2, actual);
|
|
15130
|
-
peers.push(peer);
|
|
15131
|
-
}
|
|
15132
|
-
}
|
|
15133
|
-
log$5.info(`got new peer candidate from DNS address=${peer.nodeId}@${peer.ip}`);
|
|
15134
|
-
}
|
|
15121
|
+
let erroneousSearches = 0;
|
|
15122
|
+
while (totalSearches < maxGet &&
|
|
15123
|
+
erroneousSearches < maxErrors // Allows a couple of empty results before calling it quit
|
|
15124
|
+
) {
|
|
15135
15125
|
totalSearches++;
|
|
15136
|
-
}
|
|
15137
|
-
return peers;
|
|
15138
|
-
}
|
|
15139
|
-
/**
|
|
15140
|
-
* Fetch nodes using passed [[getNode]] until all wanted capabilities are
|
|
15141
|
-
* fulfilled or the number of [[getNode]] call exceeds the sum of
|
|
15142
|
-
* [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
|
|
15143
|
-
*/
|
|
15144
|
-
async function* yieldNodesUntilCapabilitiesFulfilled(wantedNodeCapabilityCount, errorTolerance, getNode) {
|
|
15145
|
-
const wanted = {
|
|
15146
|
-
relay: wantedNodeCapabilityCount.relay ?? 0,
|
|
15147
|
-
store: wantedNodeCapabilityCount.store ?? 0,
|
|
15148
|
-
filter: wantedNodeCapabilityCount.filter ?? 0,
|
|
15149
|
-
lightPush: wantedNodeCapabilityCount.lightPush ?? 0
|
|
15150
|
-
};
|
|
15151
|
-
const maxSearches = wanted.relay + wanted.store + wanted.filter + wanted.lightPush;
|
|
15152
|
-
const actual = {
|
|
15153
|
-
relay: 0,
|
|
15154
|
-
store: 0,
|
|
15155
|
-
filter: 0,
|
|
15156
|
-
lightPush: 0
|
|
15157
|
-
};
|
|
15158
|
-
let totalSearches = 0;
|
|
15159
|
-
const peerNodeIds = new Set();
|
|
15160
|
-
while (!isSatisfied(wanted, actual) &&
|
|
15161
|
-
totalSearches < maxSearches + errorTolerance) {
|
|
15162
15126
|
const peer = await getNode();
|
|
15163
|
-
if (peer
|
|
15127
|
+
if (!peer || !peer.nodeId) {
|
|
15128
|
+
erroneousSearches++;
|
|
15129
|
+
continue;
|
|
15130
|
+
}
|
|
15131
|
+
if (!peerNodeIds.has(peer.nodeId)) {
|
|
15164
15132
|
peerNodeIds.add(peer.nodeId);
|
|
15165
15133
|
// ENRs without a waku2 key are ignored.
|
|
15166
15134
|
if (peer.waku2) {
|
|
15167
|
-
|
|
15168
|
-
addCapabilities(peer.waku2, actual);
|
|
15169
|
-
yield peer;
|
|
15170
|
-
}
|
|
15135
|
+
yield peer;
|
|
15171
15136
|
}
|
|
15172
15137
|
log$5.info(`got new peer candidate from DNS address=${peer.nodeId}@${peer.ip}`);
|
|
15173
15138
|
}
|
|
15174
|
-
totalSearches++;
|
|
15175
|
-
}
|
|
15176
|
-
}
|
|
15177
|
-
function isSatisfied(wanted, actual) {
|
|
15178
|
-
return (actual.relay >= wanted.relay &&
|
|
15179
|
-
actual.store >= wanted.store &&
|
|
15180
|
-
actual.filter >= wanted.filter &&
|
|
15181
|
-
actual.lightPush >= wanted.lightPush);
|
|
15182
|
-
}
|
|
15183
|
-
function isNewPeer(peer, peers) {
|
|
15184
|
-
if (!peer.nodeId)
|
|
15185
|
-
return false;
|
|
15186
|
-
for (const existingPeer of peers) {
|
|
15187
|
-
if (peer.nodeId === existingPeer.nodeId) {
|
|
15188
|
-
return false;
|
|
15189
|
-
}
|
|
15190
15139
|
}
|
|
15191
|
-
return true;
|
|
15192
|
-
}
|
|
15193
|
-
function addCapabilities(node, total) {
|
|
15194
|
-
if (node.relay)
|
|
15195
|
-
total.relay += 1;
|
|
15196
|
-
if (node.store)
|
|
15197
|
-
total.store += 1;
|
|
15198
|
-
if (node.filter)
|
|
15199
|
-
total.filter += 1;
|
|
15200
|
-
if (node.lightPush)
|
|
15201
|
-
total.lightPush += 1;
|
|
15202
|
-
}
|
|
15203
|
-
/**
|
|
15204
|
-
* Checks if the proposed ENR [[node]] helps satisfy the [[wanted]] capabilities,
|
|
15205
|
-
* considering the [[actual]] capabilities of nodes retrieved so far..
|
|
15206
|
-
*
|
|
15207
|
-
* @throws If the function is called when the wanted capabilities are already fulfilled.
|
|
15208
|
-
*/
|
|
15209
|
-
function helpsSatisfyCapabilities(node, wanted, actual) {
|
|
15210
|
-
if (isSatisfied(wanted, actual)) {
|
|
15211
|
-
throw "Internal Error: Waku2 wanted capabilities are already fulfilled";
|
|
15212
|
-
}
|
|
15213
|
-
const missing = missingCapabilities(wanted, actual);
|
|
15214
|
-
return ((missing.relay && node.relay) ||
|
|
15215
|
-
(missing.store && node.store) ||
|
|
15216
|
-
(missing.filter && node.filter) ||
|
|
15217
|
-
(missing.lightPush && node.lightPush));
|
|
15218
|
-
}
|
|
15219
|
-
/**
|
|
15220
|
-
* Return a [[Waku2]] Object for which capabilities are set to true if they are
|
|
15221
|
-
* [[wanted]] yet missing from [[actual]].
|
|
15222
|
-
*/
|
|
15223
|
-
function missingCapabilities(wanted, actual) {
|
|
15224
|
-
return {
|
|
15225
|
-
relay: actual.relay < wanted.relay,
|
|
15226
|
-
store: actual.store < wanted.store,
|
|
15227
|
-
filter: actual.filter < wanted.filter,
|
|
15228
|
-
lightPush: actual.lightPush < wanted.lightPush
|
|
15229
|
-
};
|
|
15230
15140
|
}
|
|
15231
15141
|
|
|
15232
15142
|
const log$4 = new Logger$1("discovery:dns");
|
|
15233
15143
|
class DnsNodeDiscovery {
|
|
15234
15144
|
dns;
|
|
15235
15145
|
_DNSTreeCache;
|
|
15236
|
-
_errorTolerance = 10;
|
|
15237
15146
|
static async dnsOverHttp(dnsClient) {
|
|
15238
15147
|
if (!dnsClient) {
|
|
15239
15148
|
dnsClient = await DnsOverHttps.create();
|
|
15240
15149
|
}
|
|
15241
15150
|
return new DnsNodeDiscovery(dnsClient);
|
|
15242
15151
|
}
|
|
15243
|
-
/**
|
|
15244
|
-
* Returns a list of verified peers listed in an EIP-1459 DNS tree. Method may
|
|
15245
|
-
* return fewer peers than requested if @link wantedNodeCapabilityCount requires
|
|
15246
|
-
* larger quantity of peers than available or the number of errors/duplicate
|
|
15247
|
-
* peers encountered by randomized search exceeds the sum of the fields of
|
|
15248
|
-
* @link wantedNodeCapabilityCount plus the @link _errorTolerance factor.
|
|
15249
|
-
*/
|
|
15250
|
-
async getPeers(enrTreeUrls, wantedNodeCapabilityCount) {
|
|
15251
|
-
const networkIndex = Math.floor(Math.random() * enrTreeUrls.length);
|
|
15252
|
-
const { publicKey, domain } = ENRTree.parseTree(enrTreeUrls[networkIndex]);
|
|
15253
|
-
const context = {
|
|
15254
|
-
domain,
|
|
15255
|
-
publicKey,
|
|
15256
|
-
visits: {}
|
|
15257
|
-
};
|
|
15258
|
-
const peers = await fetchNodesUntilCapabilitiesFulfilled(wantedNodeCapabilityCount, this._errorTolerance, () => this._search(domain, context));
|
|
15259
|
-
log$4.info("retrieved peers: ", peers.map((peer) => {
|
|
15260
|
-
return {
|
|
15261
|
-
id: peer.peerId?.toString(),
|
|
15262
|
-
multiaddrs: peer.multiaddrs?.map((ma) => ma.toString())
|
|
15263
|
-
};
|
|
15264
|
-
}));
|
|
15265
|
-
return peers;
|
|
15266
|
-
}
|
|
15267
15152
|
constructor(dns) {
|
|
15268
15153
|
this._DNSTreeCache = {};
|
|
15269
15154
|
this.dns = dns;
|
|
15270
15155
|
}
|
|
15271
15156
|
/**
|
|
15272
|
-
*
|
|
15157
|
+
* Retrieve the next peers from the passed [[enrTreeUrls]],
|
|
15273
15158
|
*/
|
|
15274
|
-
async *getNextPeer(enrTreeUrls
|
|
15275
|
-
|
|
15276
|
-
const
|
|
15277
|
-
|
|
15278
|
-
|
|
15279
|
-
|
|
15280
|
-
|
|
15281
|
-
|
|
15282
|
-
|
|
15283
|
-
|
|
15159
|
+
async *getNextPeer(enrTreeUrls) {
|
|
15160
|
+
// Shuffle the ENR Trees so that not all clients connect to same nodes first.
|
|
15161
|
+
for (const enrTreeUrl of shuffle(enrTreeUrls)) {
|
|
15162
|
+
const { publicKey, domain } = ENRTree.parseTree(enrTreeUrl);
|
|
15163
|
+
const context = {
|
|
15164
|
+
domain,
|
|
15165
|
+
publicKey,
|
|
15166
|
+
visits: {}
|
|
15167
|
+
};
|
|
15168
|
+
for await (const peer of fetchNodes(() => this._search(domain, context))) {
|
|
15169
|
+
yield peer;
|
|
15170
|
+
}
|
|
15284
15171
|
}
|
|
15285
15172
|
}
|
|
15286
15173
|
/**
|
|
@@ -15338,7 +15225,7 @@ class DnsNodeDiscovery {
|
|
|
15338
15225
|
throw new Error("Received empty result array while fetching TXT record");
|
|
15339
15226
|
if (!response[0].length)
|
|
15340
15227
|
throw new Error("Received empty TXT record");
|
|
15341
|
-
// Branch entries can be an array of strings of comma
|
|
15228
|
+
// Branch entries can be an array of strings of comma-delimited subdomains, with
|
|
15342
15229
|
// some subdomain strings split across the array elements
|
|
15343
15230
|
const result = response.join("");
|
|
15344
15231
|
this._DNSTreeCache[subdomain] = result;
|
|
@@ -15414,9 +15301,8 @@ class PeerDiscoveryDns extends TypedEventEmitter {
|
|
|
15414
15301
|
let { enrUrls } = this._options;
|
|
15415
15302
|
if (!Array.isArray(enrUrls))
|
|
15416
15303
|
enrUrls = [enrUrls];
|
|
15417
|
-
const { wantedNodeCapabilityCount } = this._options;
|
|
15418
15304
|
const dns = await DnsNodeDiscovery.dnsOverHttp();
|
|
15419
|
-
this.nextPeer = dns.getNextPeer.bind(dns, enrUrls
|
|
15305
|
+
this.nextPeer = dns.getNextPeer.bind(dns, enrUrls);
|
|
15420
15306
|
}
|
|
15421
15307
|
for await (const peerEnr of this.nextPeer()) {
|
|
15422
15308
|
if (!this._started) {
|
|
@@ -15433,8 +15319,8 @@ class PeerDiscoveryDns extends TypedEventEmitter {
|
|
|
15433
15319
|
}
|
|
15434
15320
|
};
|
|
15435
15321
|
let isPeerChanged = false;
|
|
15436
|
-
const
|
|
15437
|
-
if (
|
|
15322
|
+
const isPeerAlreadyInPeerStore = await this._components.peerStore.has(peerInfo.id);
|
|
15323
|
+
if (isPeerAlreadyInPeerStore) {
|
|
15438
15324
|
const peer = await this._components.peerStore.get(peerInfo.id);
|
|
15439
15325
|
const hasBootstrapTag = peer.tags.has(DEFAULT_BOOTSTRAP_TAG_NAME);
|
|
15440
15326
|
if (!hasBootstrapTag) {
|
|
@@ -15473,10 +15359,17 @@ class PeerDiscoveryDns extends TypedEventEmitter {
|
|
|
15473
15359
|
return DNS_DISCOVERY_TAG;
|
|
15474
15360
|
}
|
|
15475
15361
|
}
|
|
15476
|
-
function wakuDnsDiscovery(enrUrls
|
|
15477
|
-
return (components) => new PeerDiscoveryDns(components, { enrUrls
|
|
15362
|
+
function wakuDnsDiscovery(enrUrls) {
|
|
15363
|
+
return (components) => new PeerDiscoveryDns(components, { enrUrls });
|
|
15478
15364
|
}
|
|
15479
15365
|
|
|
15366
|
+
// amount of peers available per specification
|
|
15367
|
+
const DEFAULT_PEER_EXCHANGE_REQUEST_NODES = 60;
|
|
15368
|
+
const DEFAULT_PEER_EXCHANGE_TAG_NAME = Tags.PEER_EXCHANGE;
|
|
15369
|
+
const DEFAULT_PEER_EXCHANGE_TAG_VALUE = 50;
|
|
15370
|
+
const DEFAULT_PEER_EXCHANGE_TAG_TTL = 30_000;
|
|
15371
|
+
const PeerExchangeCodec = "/vac/waku/peer-exchange/2.0.0-alpha1";
|
|
15372
|
+
|
|
15480
15373
|
/* eslint-disable import/export */
|
|
15481
15374
|
/* eslint-disable complexity */
|
|
15482
15375
|
/* eslint-disable @typescript-eslint/no-namespace */
|
|
@@ -18020,6 +17913,10 @@ var SdsMessage;
|
|
|
18020
17913
|
if (opts.lengthDelimited !== false) {
|
|
18021
17914
|
w.fork();
|
|
18022
17915
|
}
|
|
17916
|
+
if ((obj.senderId != null && obj.senderId !== '')) {
|
|
17917
|
+
w.uint32(10);
|
|
17918
|
+
w.string(obj.senderId);
|
|
17919
|
+
}
|
|
18023
17920
|
if ((obj.messageId != null && obj.messageId !== '')) {
|
|
18024
17921
|
w.uint32(18);
|
|
18025
17922
|
w.string(obj.messageId);
|
|
@@ -18051,6 +17948,7 @@ var SdsMessage;
|
|
|
18051
17948
|
}
|
|
18052
17949
|
}, (reader, length, opts = {}) => {
|
|
18053
17950
|
const obj = {
|
|
17951
|
+
senderId: '',
|
|
18054
17952
|
messageId: '',
|
|
18055
17953
|
channelId: '',
|
|
18056
17954
|
causalHistory: []
|
|
@@ -18059,6 +17957,10 @@ var SdsMessage;
|
|
|
18059
17957
|
while (reader.pos < end) {
|
|
18060
17958
|
const tag = reader.uint32();
|
|
18061
17959
|
switch (tag >>> 3) {
|
|
17960
|
+
case 1: {
|
|
17961
|
+
obj.senderId = reader.string();
|
|
17962
|
+
break;
|
|
17963
|
+
}
|
|
18062
17964
|
case 2: {
|
|
18063
17965
|
obj.messageId = reader.string();
|
|
18064
17966
|
break;
|
|
@@ -19072,27 +18974,32 @@ class StreamManager {
|
|
|
19072
18974
|
this.libp2p.events.addEventListener("peer:update", this.handlePeerUpdateStreamPool);
|
|
19073
18975
|
}
|
|
19074
18976
|
async getStream(peerId) {
|
|
19075
|
-
|
|
19076
|
-
|
|
19077
|
-
|
|
19078
|
-
|
|
19079
|
-
|
|
19080
|
-
|
|
19081
|
-
|
|
19082
|
-
|
|
19083
|
-
|
|
18977
|
+
try {
|
|
18978
|
+
const peerIdStr = peerId.toString();
|
|
18979
|
+
const scheduledStream = this.streamPool.get(peerIdStr);
|
|
18980
|
+
if (scheduledStream) {
|
|
18981
|
+
this.streamPool.delete(peerIdStr);
|
|
18982
|
+
await scheduledStream;
|
|
18983
|
+
}
|
|
18984
|
+
const stream = this.getOpenStreamForCodec(peerId) || (await this.createStream(peerId));
|
|
18985
|
+
if (!stream) {
|
|
18986
|
+
return;
|
|
18987
|
+
}
|
|
18988
|
+
this.log.info(`Using stream for peerId=${peerIdStr} multicodec=${this.multicodec}`);
|
|
19084
18989
|
this.lockStream(peerIdStr, stream);
|
|
19085
18990
|
return stream;
|
|
19086
18991
|
}
|
|
19087
|
-
|
|
19088
|
-
|
|
19089
|
-
|
|
18992
|
+
catch (error) {
|
|
18993
|
+
this.log.error(`Failed to getStream:`, error);
|
|
18994
|
+
return;
|
|
18995
|
+
}
|
|
19090
18996
|
}
|
|
19091
18997
|
async createStream(peerId, retries = 0) {
|
|
19092
18998
|
const connections = this.libp2p.connectionManager.getConnections(peerId);
|
|
19093
18999
|
const connection = selectOpenConnection(connections);
|
|
19094
19000
|
if (!connection) {
|
|
19095
|
-
|
|
19001
|
+
this.log.error(`Failed to get a connection to the peer peerId=${peerId.toString()} multicodec=${this.multicodec}`);
|
|
19002
|
+
return;
|
|
19096
19003
|
}
|
|
19097
19004
|
let lastError;
|
|
19098
19005
|
let stream;
|
|
@@ -19108,7 +19015,8 @@ class StreamManager {
|
|
|
19108
19015
|
}
|
|
19109
19016
|
}
|
|
19110
19017
|
if (!stream) {
|
|
19111
|
-
|
|
19018
|
+
this.log.error(`Failed to create a new stream for ${peerId.toString()} -- ` + lastError);
|
|
19019
|
+
return;
|
|
19112
19020
|
}
|
|
19113
19021
|
return stream;
|
|
19114
19022
|
}
|
|
@@ -19153,16 +19061,20 @@ class StreamManager {
|
|
|
19153
19061
|
const connections = this.libp2p.connectionManager.getConnections(peerId);
|
|
19154
19062
|
const connection = selectOpenConnection(connections);
|
|
19155
19063
|
if (!connection) {
|
|
19064
|
+
this.log.info(`No open connection found for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
|
|
19156
19065
|
return;
|
|
19157
19066
|
}
|
|
19158
19067
|
const stream = connection.streams.find((s) => s.protocol === this.multicodec);
|
|
19159
19068
|
if (!stream) {
|
|
19069
|
+
this.log.info(`No open stream found for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
|
|
19160
19070
|
return;
|
|
19161
19071
|
}
|
|
19162
19072
|
const isStreamUnusable = ["done", "closed", "closing"].includes(stream.writeStatus || "");
|
|
19163
19073
|
if (isStreamUnusable || this.isStreamLocked(stream)) {
|
|
19074
|
+
this.log.info(`Stream for peerId=${peerId.toString()} multicodec=${this.multicodec} is unusable`);
|
|
19164
19075
|
return;
|
|
19165
19076
|
}
|
|
19077
|
+
this.log.info(`Found open stream for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
|
|
19166
19078
|
return stream;
|
|
19167
19079
|
}
|
|
19168
19080
|
lockStream(peerId, stream) {
|
|
@@ -19234,12 +19146,11 @@ class PeerExchangeRPC {
|
|
|
19234
19146
|
}
|
|
19235
19147
|
}
|
|
19236
19148
|
|
|
19237
|
-
const PeerExchangeCodec = "/vac/waku/peer-exchange/2.0.0-alpha1";
|
|
19238
19149
|
const log$2 = new Logger$1("peer-exchange");
|
|
19239
19150
|
/**
|
|
19240
19151
|
* Implementation of the Peer Exchange protocol (https://rfc.vac.dev/spec/34/)
|
|
19241
19152
|
*/
|
|
19242
|
-
class
|
|
19153
|
+
class PeerExchange {
|
|
19243
19154
|
components;
|
|
19244
19155
|
streamManager;
|
|
19245
19156
|
/**
|
|
@@ -19257,19 +19168,16 @@ class WakuPeerExchange {
|
|
|
19257
19168
|
const rpcQuery = PeerExchangeRPC.createRequest({
|
|
19258
19169
|
numPeers: BigInt(numPeers)
|
|
19259
19170
|
});
|
|
19260
|
-
const
|
|
19261
|
-
if (!
|
|
19171
|
+
const hasPeer = await this.components.peerStore.has(peerId);
|
|
19172
|
+
if (!hasPeer) {
|
|
19262
19173
|
return {
|
|
19263
19174
|
peerInfos: null,
|
|
19264
19175
|
error: ProtocolError.NO_PEER_AVAILABLE
|
|
19265
19176
|
};
|
|
19266
19177
|
}
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
stream
|
|
19270
|
-
}
|
|
19271
|
-
catch (err) {
|
|
19272
|
-
log$2.error("Failed to get stream", err);
|
|
19178
|
+
const stream = await this.streamManager.getStream(peerId);
|
|
19179
|
+
if (!stream) {
|
|
19180
|
+
log$2.error(`Failed to get a stream for remote peer:${peerId?.toString?.()}`);
|
|
19273
19181
|
return {
|
|
19274
19182
|
peerInfos: null,
|
|
19275
19183
|
error: ProtocolError.NO_STREAM_AVAILABLE
|
|
@@ -19309,64 +19217,56 @@ class WakuPeerExchange {
|
|
|
19309
19217
|
}
|
|
19310
19218
|
}
|
|
19311
19219
|
}
|
|
19312
|
-
/**
|
|
19313
|
-
*
|
|
19314
|
-
* @returns A function that creates a new peer exchange protocol
|
|
19315
|
-
*/
|
|
19316
|
-
function wakuPeerExchange() {
|
|
19317
|
-
return (components) => new WakuPeerExchange(components);
|
|
19318
|
-
}
|
|
19319
19220
|
|
|
19320
19221
|
const log$1 = new Logger$1("peer-exchange-discovery");
|
|
19321
|
-
const DEFAULT_PEER_EXCHANGE_REQUEST_NODES = 10;
|
|
19322
|
-
const DEFAULT_PEER_EXCHANGE_QUERY_INTERVAL_MS = 10 * 1000;
|
|
19323
|
-
const DEFAULT_MAX_RETRIES = 3;
|
|
19324
|
-
const DEFAULT_PEER_EXCHANGE_TAG_NAME = Tags.PEER_EXCHANGE;
|
|
19325
|
-
const DEFAULT_PEER_EXCHANGE_TAG_VALUE = 50;
|
|
19326
|
-
const DEFAULT_PEER_EXCHANGE_TAG_TTL = 100_000_000;
|
|
19327
19222
|
class PeerExchangeDiscovery extends TypedEventEmitter {
|
|
19328
19223
|
components;
|
|
19329
19224
|
peerExchange;
|
|
19330
19225
|
options;
|
|
19331
|
-
isStarted;
|
|
19226
|
+
isStarted = false;
|
|
19332
19227
|
queryingPeers = new Set();
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
const { protocols, peerId } = event.detail;
|
|
19336
|
-
if (!protocols.includes(PeerExchangeCodec) ||
|
|
19337
|
-
this.queryingPeers.has(peerId.toString()))
|
|
19338
|
-
return;
|
|
19339
|
-
this.queryingPeers.add(peerId.toString());
|
|
19340
|
-
this.startRecurringQueries(peerId).catch((error) => log$1.error(`Error querying peer ${error}`));
|
|
19341
|
-
};
|
|
19228
|
+
peerExpirationRecords = new Map();
|
|
19229
|
+
continuousDiscoveryInterval = null;
|
|
19342
19230
|
constructor(components, options = {}) {
|
|
19343
19231
|
super();
|
|
19344
19232
|
this.components = components;
|
|
19345
|
-
this.peerExchange = new
|
|
19346
|
-
this.options =
|
|
19347
|
-
|
|
19233
|
+
this.peerExchange = new PeerExchange(components);
|
|
19234
|
+
this.options = {
|
|
19235
|
+
...options,
|
|
19236
|
+
TTL: options.TTL ?? DEFAULT_PEER_EXCHANGE_TAG_TTL
|
|
19237
|
+
};
|
|
19238
|
+
this.handleDiscoveredPeer = this.handleDiscoveredPeer.bind(this);
|
|
19348
19239
|
}
|
|
19349
19240
|
/**
|
|
19350
|
-
* Start
|
|
19241
|
+
* Start Peer Exchange.
|
|
19242
|
+
* Subscribe to "peer:identify" events and handle them.
|
|
19351
19243
|
*/
|
|
19352
19244
|
start() {
|
|
19353
19245
|
if (this.isStarted) {
|
|
19354
19246
|
return;
|
|
19355
19247
|
}
|
|
19356
|
-
this.dispatchEvent(new CustomEvent("waku:peer-exchange:started", { detail: true }));
|
|
19357
19248
|
log$1.info("Starting peer exchange node discovery, discovering peers");
|
|
19358
|
-
|
|
19249
|
+
this.isStarted = true;
|
|
19359
19250
|
this.components.events.addEventListener("peer:identify", this.handleDiscoveredPeer);
|
|
19251
|
+
this.continuousDiscoveryInterval = setInterval(() => {
|
|
19252
|
+
void this.handlePeriodicDiscovery();
|
|
19253
|
+
}, this.options.TTL);
|
|
19360
19254
|
}
|
|
19361
19255
|
/**
|
|
19362
|
-
*
|
|
19256
|
+
* Stop Peer Exchange.
|
|
19257
|
+
* Unsubscribe from "peer:identify" events.
|
|
19363
19258
|
*/
|
|
19364
19259
|
stop() {
|
|
19365
|
-
if (!this.isStarted)
|
|
19260
|
+
if (!this.isStarted) {
|
|
19366
19261
|
return;
|
|
19262
|
+
}
|
|
19367
19263
|
log$1.info("Stopping peer exchange node discovery");
|
|
19368
19264
|
this.isStarted = false;
|
|
19369
19265
|
this.queryingPeers.clear();
|
|
19266
|
+
this.peerExpirationRecords.clear();
|
|
19267
|
+
if (this.continuousDiscoveryInterval) {
|
|
19268
|
+
clearInterval(this.continuousDiscoveryInterval);
|
|
19269
|
+
}
|
|
19370
19270
|
this.components.events.removeEventListener("peer:identify", this.handleDiscoveredPeer);
|
|
19371
19271
|
}
|
|
19372
19272
|
get [peerDiscoverySymbol]() {
|
|
@@ -19375,228 +19275,268 @@ class PeerExchangeDiscovery extends TypedEventEmitter {
|
|
|
19375
19275
|
get [Symbol.toStringTag]() {
|
|
19376
19276
|
return "@waku/peer-exchange";
|
|
19377
19277
|
}
|
|
19378
|
-
|
|
19379
|
-
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19383
|
-
|
|
19384
|
-
|
|
19385
|
-
|
|
19278
|
+
async handleDiscoveredPeer(event) {
|
|
19279
|
+
void this.runQuery(event.detail.peerId, event.detail.protocols);
|
|
19280
|
+
}
|
|
19281
|
+
async handlePeriodicDiscovery() {
|
|
19282
|
+
const connections = this.components.connectionManager.getConnections();
|
|
19283
|
+
await Promise.all(connections.map(async (connection) => {
|
|
19284
|
+
try {
|
|
19285
|
+
const peerIdStr = connection.remotePeer.toString();
|
|
19286
|
+
const shouldQuery = this.peerExpirationRecords.has(peerIdStr)
|
|
19287
|
+
? this.peerExpirationRecords.get(peerIdStr) <= Date.now()
|
|
19288
|
+
: true;
|
|
19289
|
+
if (!shouldQuery) {
|
|
19290
|
+
return null;
|
|
19291
|
+
}
|
|
19292
|
+
const peer = await this.components.peerStore.get(connection.remotePeer);
|
|
19293
|
+
return this.runQuery(connection.remotePeer, peer.protocols);
|
|
19294
|
+
}
|
|
19295
|
+
catch (error) {
|
|
19296
|
+
log$1.warn("Error getting peer info", error);
|
|
19297
|
+
return null;
|
|
19298
|
+
}
|
|
19299
|
+
}));
|
|
19300
|
+
}
|
|
19301
|
+
async runQuery(peerId, protocols) {
|
|
19302
|
+
if (!protocols.includes(PeerExchangeCodec) ||
|
|
19303
|
+
this.queryingPeers.has(peerId.toString())) {
|
|
19304
|
+
log$1.info(`Skipping peer ${peerId} as it is already querying or does not support peer exchange`);
|
|
19386
19305
|
return;
|
|
19387
19306
|
}
|
|
19388
|
-
|
|
19389
|
-
this.
|
|
19390
|
-
this.
|
|
19391
|
-
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
|
|
19307
|
+
try {
|
|
19308
|
+
this.queryingPeers.add(peerId.toString());
|
|
19309
|
+
await this.query(peerId);
|
|
19310
|
+
}
|
|
19311
|
+
catch (error) {
|
|
19312
|
+
log$1.error("Error querying peer", error);
|
|
19313
|
+
}
|
|
19314
|
+
this.peerExpirationRecords.set(peerId.toString(), Date.now() + this.options.TTL);
|
|
19315
|
+
this.queryingPeers.delete(peerId.toString());
|
|
19316
|
+
}
|
|
19395
19317
|
async query(peerId) {
|
|
19318
|
+
const peerIdStr = peerId.toString();
|
|
19319
|
+
log$1.info(`Querying peer exchange for ${peerIdStr}`);
|
|
19396
19320
|
const { error, peerInfos } = await this.peerExchange.query({
|
|
19397
19321
|
numPeers: DEFAULT_PEER_EXCHANGE_REQUEST_NODES,
|
|
19398
19322
|
peerId
|
|
19399
19323
|
});
|
|
19400
19324
|
if (error) {
|
|
19401
|
-
log$1.error(
|
|
19402
|
-
return
|
|
19325
|
+
log$1.error(`Peer exchange query to ${peerIdStr} failed`, error);
|
|
19326
|
+
return;
|
|
19403
19327
|
}
|
|
19404
|
-
for (const
|
|
19405
|
-
const { ENR } = _peerInfo;
|
|
19328
|
+
for (const { ENR } of peerInfos) {
|
|
19406
19329
|
if (!ENR) {
|
|
19407
|
-
log$1.warn(
|
|
19330
|
+
log$1.warn(`No ENR in peerInfo object from ${peerIdStr}, skipping`);
|
|
19408
19331
|
continue;
|
|
19409
19332
|
}
|
|
19410
|
-
const {
|
|
19411
|
-
if (!
|
|
19333
|
+
const { peerInfo, shardInfo } = ENR;
|
|
19334
|
+
if (!peerInfo) {
|
|
19335
|
+
log$1.warn(`No peerInfo in ENR from ${peerIdStr}, skipping`);
|
|
19412
19336
|
continue;
|
|
19413
19337
|
}
|
|
19414
|
-
const
|
|
19415
|
-
|
|
19416
|
-
|
|
19417
|
-
|
|
19418
|
-
|
|
19419
|
-
|
|
19420
|
-
log$1.info(`Peer ${peerId.toString()} has updated multiaddrs, updating`);
|
|
19421
|
-
await this.components.peerStore.patch(peerId, {
|
|
19422
|
-
multiaddrs: peerInfo.multiaddrs
|
|
19423
|
-
});
|
|
19424
|
-
}
|
|
19425
|
-
if (hasShardDiff && shardInfo) {
|
|
19426
|
-
log$1.info(`Peer ${peerId.toString()} has updated shardInfo, updating`);
|
|
19427
|
-
await this.components.peerStore.merge(peerId, {
|
|
19428
|
-
metadata: {
|
|
19429
|
-
shardInfo: encodeRelayShard(shardInfo)
|
|
19430
|
-
}
|
|
19431
|
-
});
|
|
19432
|
-
this.dispatchEvent(new CustomEvent("peer", {
|
|
19433
|
-
detail: {
|
|
19434
|
-
id: peerId,
|
|
19435
|
-
multiaddrs: peerInfo.multiaddrs
|
|
19436
|
-
}
|
|
19437
|
-
}));
|
|
19438
|
-
}
|
|
19439
|
-
continue;
|
|
19440
|
-
}
|
|
19441
|
-
}
|
|
19442
|
-
// update the tags for the peer
|
|
19443
|
-
await this.components.peerStore.save(peerId, {
|
|
19338
|
+
const hasPrevShardInfo = await this.hasShardInfo(peerInfo.id);
|
|
19339
|
+
const metadata = !hasPrevShardInfo && shardInfo
|
|
19340
|
+
? { metadata: { shardInfo: encodeRelayShard(shardInfo) } }
|
|
19341
|
+
: undefined;
|
|
19342
|
+
// merge is smart enough to overwrite only changed parts
|
|
19343
|
+
await this.components.peerStore.merge(peerInfo.id, {
|
|
19444
19344
|
tags: {
|
|
19445
19345
|
[DEFAULT_PEER_EXCHANGE_TAG_NAME]: {
|
|
19446
|
-
value:
|
|
19447
|
-
ttl: this.options.tagTTL ?? DEFAULT_PEER_EXCHANGE_TAG_TTL
|
|
19346
|
+
value: DEFAULT_PEER_EXCHANGE_TAG_VALUE
|
|
19448
19347
|
}
|
|
19449
19348
|
},
|
|
19450
|
-
...
|
|
19451
|
-
metadata: {
|
|
19452
|
-
shardInfo: encodeRelayShard(shardInfo)
|
|
19453
|
-
}
|
|
19454
|
-
}),
|
|
19349
|
+
...metadata,
|
|
19455
19350
|
...(peerInfo.multiaddrs && {
|
|
19456
19351
|
multiaddrs: peerInfo.multiaddrs
|
|
19457
19352
|
})
|
|
19458
19353
|
});
|
|
19459
|
-
log$1.info(`Discovered peer: ${
|
|
19354
|
+
log$1.info(`Discovered peer: ${peerInfo.id.toString()}`);
|
|
19460
19355
|
this.dispatchEvent(new CustomEvent("peer", {
|
|
19461
19356
|
detail: {
|
|
19462
|
-
id:
|
|
19357
|
+
id: peerInfo.id,
|
|
19463
19358
|
multiaddrs: peerInfo.multiaddrs
|
|
19464
19359
|
}
|
|
19465
19360
|
}));
|
|
19466
19361
|
}
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
}
|
|
19474
|
-
async checkPeerInfoDiff(peerInfo, shardInfo) {
|
|
19475
|
-
const { id: peerId } = peerInfo;
|
|
19476
|
-
const peer = await this.components.peerStore.get(peerId);
|
|
19477
|
-
const existingMultiaddrs = peer.addresses.map((a) => a.multiaddr.toString());
|
|
19478
|
-
const newMultiaddrs = peerInfo.multiaddrs.map((ma) => ma.toString());
|
|
19479
|
-
const hasMultiaddrDiff = existingMultiaddrs.some((ma) => !newMultiaddrs.includes(ma));
|
|
19480
|
-
let hasShardDiff = false;
|
|
19481
|
-
const existingShardInfoBytes = peer.metadata.get("shardInfo");
|
|
19482
|
-
if (existingShardInfoBytes) {
|
|
19483
|
-
const existingShardInfo = decodeRelayShard(existingShardInfoBytes);
|
|
19484
|
-
if (existingShardInfo || shardInfo) {
|
|
19485
|
-
hasShardDiff =
|
|
19486
|
-
existingShardInfo.clusterId !== shardInfo?.clusterId ||
|
|
19487
|
-
existingShardInfo.shards.some((shard) => !shardInfo?.shards.includes(shard));
|
|
19362
|
+
}
|
|
19363
|
+
async hasShardInfo(peerId) {
|
|
19364
|
+
try {
|
|
19365
|
+
const peer = await this.components.peerStore.get(peerId);
|
|
19366
|
+
if (!peer) {
|
|
19367
|
+
return false;
|
|
19488
19368
|
}
|
|
19369
|
+
return peer.metadata.has("shardInfo");
|
|
19370
|
+
}
|
|
19371
|
+
catch (err) {
|
|
19372
|
+
log$1.warn(`Error getting shard info for ${peerId.toString()}`, err);
|
|
19489
19373
|
}
|
|
19490
|
-
return
|
|
19374
|
+
return false;
|
|
19491
19375
|
}
|
|
19492
19376
|
}
|
|
19493
|
-
function wakuPeerExchangeDiscovery() {
|
|
19494
|
-
return (components) => new PeerExchangeDiscovery(components);
|
|
19377
|
+
function wakuPeerExchangeDiscovery(options = {}) {
|
|
19378
|
+
return (components) => new PeerExchangeDiscovery(components, options);
|
|
19379
|
+
}
|
|
19380
|
+
|
|
19381
|
+
const DEFAULT_PEER_CACHE_TAG_NAME = Tags.PEER_CACHE;
|
|
19382
|
+
const DEFAULT_PEER_CACHE_TAG_VALUE = 50;
|
|
19383
|
+
|
|
19384
|
+
const isValidStoredPeer = (peer) => {
|
|
19385
|
+
return (!!peer &&
|
|
19386
|
+
typeof peer === "object" &&
|
|
19387
|
+
"id" in peer &&
|
|
19388
|
+
typeof peer.id === "string" &&
|
|
19389
|
+
"multiaddrs" in peer &&
|
|
19390
|
+
Array.isArray(peer.multiaddrs));
|
|
19391
|
+
};
|
|
19392
|
+
/**
|
|
19393
|
+
* A noop cache that will be used in environments where localStorage is not available.
|
|
19394
|
+
*/
|
|
19395
|
+
class NoopCache {
|
|
19396
|
+
get() {
|
|
19397
|
+
return [];
|
|
19398
|
+
}
|
|
19399
|
+
set(_value) {
|
|
19400
|
+
return;
|
|
19401
|
+
}
|
|
19402
|
+
remove() {
|
|
19403
|
+
return;
|
|
19404
|
+
}
|
|
19405
|
+
}
|
|
19406
|
+
/**
|
|
19407
|
+
* A cache that uses localStorage to store peer information.
|
|
19408
|
+
*/
|
|
19409
|
+
class LocalStorageCache {
|
|
19410
|
+
get() {
|
|
19411
|
+
try {
|
|
19412
|
+
const cachedPeers = localStorage.getItem("waku:peers");
|
|
19413
|
+
const peers = cachedPeers ? JSON.parse(cachedPeers) : [];
|
|
19414
|
+
return peers.filter(isValidStoredPeer);
|
|
19415
|
+
}
|
|
19416
|
+
catch (e) {
|
|
19417
|
+
return [];
|
|
19418
|
+
}
|
|
19419
|
+
}
|
|
19420
|
+
set(_value) {
|
|
19421
|
+
try {
|
|
19422
|
+
localStorage.setItem("waku:peers", JSON.stringify(_value));
|
|
19423
|
+
}
|
|
19424
|
+
catch (e) {
|
|
19425
|
+
// ignore
|
|
19426
|
+
}
|
|
19427
|
+
}
|
|
19428
|
+
remove() {
|
|
19429
|
+
try {
|
|
19430
|
+
localStorage.removeItem("waku:peers");
|
|
19431
|
+
}
|
|
19432
|
+
catch (e) {
|
|
19433
|
+
// ignore
|
|
19434
|
+
}
|
|
19435
|
+
}
|
|
19495
19436
|
}
|
|
19437
|
+
const defaultCache = () => {
|
|
19438
|
+
try {
|
|
19439
|
+
if (typeof localStorage !== "undefined") {
|
|
19440
|
+
return new LocalStorageCache();
|
|
19441
|
+
}
|
|
19442
|
+
}
|
|
19443
|
+
catch (_e) {
|
|
19444
|
+
// ignore
|
|
19445
|
+
}
|
|
19446
|
+
return new NoopCache();
|
|
19447
|
+
};
|
|
19496
19448
|
|
|
19497
|
-
const log = new Logger$1("
|
|
19498
|
-
|
|
19499
|
-
const DEFAULT_LOCAL_TAG_VALUE = 50;
|
|
19500
|
-
const DEFAULT_LOCAL_TAG_TTL = 100_000_000;
|
|
19501
|
-
class LocalPeerCacheDiscovery extends TypedEventEmitter {
|
|
19449
|
+
const log = new Logger$1("peer-cache");
|
|
19450
|
+
class PeerCacheDiscovery extends TypedEventEmitter {
|
|
19502
19451
|
components;
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
peers = [];
|
|
19452
|
+
isStarted = false;
|
|
19453
|
+
cache;
|
|
19506
19454
|
constructor(components, options) {
|
|
19507
19455
|
super();
|
|
19508
19456
|
this.components = components;
|
|
19509
|
-
this.
|
|
19510
|
-
this.isStarted = false;
|
|
19511
|
-
this.peers = this.getPeersFromLocalStorage();
|
|
19457
|
+
this.cache = options?.cache ?? defaultCache();
|
|
19512
19458
|
}
|
|
19513
19459
|
get [Symbol.toStringTag]() {
|
|
19514
|
-
return
|
|
19460
|
+
return `@waku/${DEFAULT_PEER_CACHE_TAG_NAME}`;
|
|
19515
19461
|
}
|
|
19516
19462
|
async start() {
|
|
19517
|
-
if (this.isStarted)
|
|
19463
|
+
if (this.isStarted) {
|
|
19518
19464
|
return;
|
|
19519
|
-
log.info("Starting Local Storage Discovery");
|
|
19520
|
-
this.components.events.addEventListener("peer:identify", this.handleNewPeers);
|
|
19521
|
-
for (const { id: idStr, address } of this.peers) {
|
|
19522
|
-
const peerId = peerIdFromString(idStr);
|
|
19523
|
-
if (await this.components.peerStore.has(peerId))
|
|
19524
|
-
continue;
|
|
19525
|
-
await this.components.peerStore.save(peerId, {
|
|
19526
|
-
multiaddrs: [multiaddr(address)],
|
|
19527
|
-
tags: {
|
|
19528
|
-
[this.options?.tagName ?? DEFAULT_LOCAL_TAG_NAME]: {
|
|
19529
|
-
value: this.options?.tagValue ?? DEFAULT_LOCAL_TAG_VALUE,
|
|
19530
|
-
ttl: this.options?.tagTTL ?? DEFAULT_LOCAL_TAG_TTL
|
|
19531
|
-
}
|
|
19532
|
-
}
|
|
19533
|
-
});
|
|
19534
|
-
this.dispatchEvent(new CustomEvent("peer", {
|
|
19535
|
-
detail: {
|
|
19536
|
-
id: peerId,
|
|
19537
|
-
multiaddrs: [multiaddr(address)]
|
|
19538
|
-
}
|
|
19539
|
-
}));
|
|
19540
19465
|
}
|
|
19541
|
-
log.info(
|
|
19466
|
+
log.info("Starting Peer Cache Discovery");
|
|
19467
|
+
this.components.events.addEventListener("peer:identify", this.handleDiscoveredPeer);
|
|
19468
|
+
await this.discoverPeers();
|
|
19542
19469
|
this.isStarted = true;
|
|
19543
19470
|
}
|
|
19544
19471
|
stop() {
|
|
19545
|
-
if (!this.isStarted)
|
|
19472
|
+
if (!this.isStarted) {
|
|
19546
19473
|
return;
|
|
19547
|
-
|
|
19548
|
-
|
|
19474
|
+
}
|
|
19475
|
+
log.info("Stopping Peer Cache Discovery");
|
|
19476
|
+
this.components.events.removeEventListener("peer:identify", this.handleDiscoveredPeer);
|
|
19549
19477
|
this.isStarted = false;
|
|
19550
|
-
this.savePeersToLocalStorage();
|
|
19551
19478
|
}
|
|
19552
|
-
|
|
19479
|
+
handleDiscoveredPeer = (event) => {
|
|
19553
19480
|
const { peerId, listenAddrs } = event.detail;
|
|
19554
|
-
const
|
|
19555
|
-
const
|
|
19556
|
-
const
|
|
19557
|
-
|
|
19558
|
-
|
|
19559
|
-
|
|
19481
|
+
const multiaddrs = listenAddrs.map((addr) => addr.toString());
|
|
19482
|
+
const peerIdStr = peerId.toString();
|
|
19483
|
+
const knownPeers = this.readPeerInfoFromCache();
|
|
19484
|
+
const peerIndex = knownPeers.findIndex((p) => p.id === peerIdStr);
|
|
19485
|
+
if (peerIndex !== -1) {
|
|
19486
|
+
knownPeers[peerIndex].multiaddrs = multiaddrs;
|
|
19560
19487
|
}
|
|
19561
19488
|
else {
|
|
19562
|
-
|
|
19563
|
-
id:
|
|
19564
|
-
|
|
19489
|
+
knownPeers.push({
|
|
19490
|
+
id: peerIdStr,
|
|
19491
|
+
multiaddrs
|
|
19565
19492
|
});
|
|
19566
19493
|
}
|
|
19567
|
-
this.
|
|
19568
|
-
this.savePeersToLocalStorage();
|
|
19494
|
+
this.writePeerInfoToCache(knownPeers);
|
|
19569
19495
|
};
|
|
19570
|
-
|
|
19496
|
+
async discoverPeers() {
|
|
19497
|
+
const knownPeers = this.readPeerInfoFromCache();
|
|
19498
|
+
for (const peer of knownPeers) {
|
|
19499
|
+
const peerId = peerIdFromString(peer.id);
|
|
19500
|
+
const multiaddrs = peer.multiaddrs.map((addr) => multiaddr(addr));
|
|
19501
|
+
if (await this.components.peerStore.has(peerId)) {
|
|
19502
|
+
continue;
|
|
19503
|
+
}
|
|
19504
|
+
await this.components.peerStore.save(peerId, {
|
|
19505
|
+
multiaddrs,
|
|
19506
|
+
tags: {
|
|
19507
|
+
[DEFAULT_PEER_CACHE_TAG_NAME]: {
|
|
19508
|
+
value: DEFAULT_PEER_CACHE_TAG_VALUE
|
|
19509
|
+
}
|
|
19510
|
+
}
|
|
19511
|
+
});
|
|
19512
|
+
this.dispatchEvent(new CustomEvent("peer", {
|
|
19513
|
+
detail: {
|
|
19514
|
+
id: peerId,
|
|
19515
|
+
multiaddrs
|
|
19516
|
+
}
|
|
19517
|
+
}));
|
|
19518
|
+
}
|
|
19519
|
+
}
|
|
19520
|
+
readPeerInfoFromCache() {
|
|
19571
19521
|
try {
|
|
19572
|
-
|
|
19573
|
-
if (!storedPeersData)
|
|
19574
|
-
return [];
|
|
19575
|
-
const peers = JSON.parse(storedPeersData);
|
|
19576
|
-
return peers.filter(isValidStoredPeer);
|
|
19522
|
+
return this.cache.get();
|
|
19577
19523
|
}
|
|
19578
19524
|
catch (error) {
|
|
19579
|
-
log.error("Error parsing peers from
|
|
19525
|
+
log.error("Error parsing peers from cache:", error);
|
|
19580
19526
|
return [];
|
|
19581
19527
|
}
|
|
19582
19528
|
}
|
|
19583
|
-
|
|
19529
|
+
writePeerInfoToCache(peers) {
|
|
19584
19530
|
try {
|
|
19585
|
-
|
|
19531
|
+
this.cache.set(peers);
|
|
19586
19532
|
}
|
|
19587
19533
|
catch (error) {
|
|
19588
|
-
log.error("Error saving peers to
|
|
19534
|
+
log.error("Error saving peers to cache:", error);
|
|
19589
19535
|
}
|
|
19590
19536
|
}
|
|
19591
19537
|
}
|
|
19592
|
-
function
|
|
19593
|
-
return (
|
|
19594
|
-
typeof peer === "object" &&
|
|
19595
|
-
typeof peer.id === "string" &&
|
|
19596
|
-
typeof peer.address === "string");
|
|
19597
|
-
}
|
|
19598
|
-
function wakuLocalPeerCacheDiscovery() {
|
|
19599
|
-
return (components, options) => new LocalPeerCacheDiscovery(components, options);
|
|
19538
|
+
function wakuPeerCacheDiscovery(options = {}) {
|
|
19539
|
+
return (components) => new PeerCacheDiscovery(components, options);
|
|
19600
19540
|
}
|
|
19601
19541
|
|
|
19602
|
-
export { DnsNodeDiscovery,
|
|
19542
|
+
export { DnsNodeDiscovery, PeerCacheDiscovery, PeerDiscoveryDns, PeerExchangeCodec, PeerExchangeDiscovery, enrTree, wakuDnsDiscovery, wakuPeerCacheDiscovery, wakuPeerExchangeDiscovery };
|