@waku/discovery 0.0.2-434be7b.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 +27179 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/dns/constants.d.ts +9 -0
- package/dist/dns/constants.js +13 -0
- package/dist/dns/constants.js.map +1 -0
- package/dist/dns/dns.d.ts +32 -0
- package/dist/dns/dns.js +160 -0
- package/dist/dns/dns.js.map +1 -0
- package/dist/dns/dns_discovery.d.ts +24 -0
- package/dist/dns/dns_discovery.js +95 -0
- package/dist/dns/dns_discovery.js.map +1 -0
- package/dist/dns/dns_over_https.d.ts +25 -0
- package/dist/dns/dns_over_https.js +72 -0
- package/dist/dns/dns_over_https.js.map +1 -0
- package/dist/dns/enrtree.d.ts +33 -0
- package/dist/dns/enrtree.js +76 -0
- package/dist/dns/enrtree.js.map +1 -0
- package/dist/dns/fetch_nodes.d.ts +13 -0
- package/dist/dns/fetch_nodes.js +133 -0
- package/dist/dns/fetch_nodes.js.map +1 -0
- package/dist/dns/index.d.ts +3 -0
- package/dist/dns/index.js +4 -0
- package/dist/dns/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/local-peer-cache/index.d.ts +24 -0
- package/dist/local-peer-cache/index.js +106 -0
- package/dist/local-peer-cache/index.js.map +1 -0
- package/dist/peer-exchange/index.d.ts +2 -0
- package/dist/peer-exchange/index.js +3 -0
- package/dist/peer-exchange/index.js.map +1 -0
- package/dist/peer-exchange/rpc.d.ts +22 -0
- package/dist/peer-exchange/rpc.js +41 -0
- package/dist/peer-exchange/rpc.js.map +1 -0
- package/dist/peer-exchange/waku_peer_exchange.d.ts +21 -0
- package/dist/peer-exchange/waku_peer_exchange.js +80 -0
- package/dist/peer-exchange/waku_peer_exchange.js.map +1 -0
- package/dist/peer-exchange/waku_peer_exchange_discovery.d.ts +53 -0
- package/dist/peer-exchange/waku_peer_exchange_discovery.js +136 -0
- package/dist/peer-exchange/waku_peer_exchange_discovery.js.map +1 -0
- package/package.json +1 -0
- package/src/dns/constants.ts +16 -0
- package/src/dns/dns.ts +215 -0
- package/src/dns/dns_discovery.ts +144 -0
- package/src/dns/dns_over_https.ts +83 -0
- package/src/dns/enrtree.ts +123 -0
- package/src/dns/fetch_nodes.ts +181 -0
- package/src/dns/index.ts +3 -0
- package/src/index.ts +21 -0
- package/src/local-peer-cache/index.ts +160 -0
- package/src/peer-exchange/index.ts +11 -0
- package/src/peer-exchange/rpc.ts +44 -0
- package/src/peer-exchange/waku_peer_exchange.ts +111 -0
- package/src/peer-exchange/waku_peer_exchange_discovery.ts +238 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
import { CustomEvent, TypedEventEmitter } from "@libp2p/interface";
|
2
|
+
import { peerDiscoverySymbol as symbol } from "@libp2p/interface";
|
3
|
+
import type {
|
4
|
+
IdentifyResult,
|
5
|
+
PeerDiscovery,
|
6
|
+
PeerDiscoveryEvents,
|
7
|
+
PeerId,
|
8
|
+
PeerInfo
|
9
|
+
} from "@libp2p/interface";
|
10
|
+
import {
|
11
|
+
Libp2pComponents,
|
12
|
+
PeerExchangeResult,
|
13
|
+
PubsubTopic,
|
14
|
+
Tags
|
15
|
+
} from "@waku/interfaces";
|
16
|
+
import { encodeRelayShard, Logger } from "@waku/utils";
|
17
|
+
|
18
|
+
import { PeerExchangeCodec, WakuPeerExchange } from "./waku_peer_exchange.js";
|
19
|
+
|
20
|
+
const log = new Logger("peer-exchange-discovery");
|
21
|
+
|
22
|
+
const DEFAULT_PEER_EXCHANGE_REQUEST_NODES = 10;
|
23
|
+
const DEFAULT_PEER_EXCHANGE_QUERY_INTERVAL_MS = 10 * 1000;
|
24
|
+
const DEFAULT_MAX_RETRIES = 3;
|
25
|
+
|
26
|
+
export interface Options {
|
27
|
+
/**
|
28
|
+
* Tag a bootstrap peer with this name before "discovering" it (default: 'bootstrap')
|
29
|
+
*/
|
30
|
+
tagName?: string;
|
31
|
+
|
32
|
+
/**
|
33
|
+
* The bootstrap peer tag will have this value (default: 50)
|
34
|
+
*/
|
35
|
+
tagValue?: number;
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Cause the bootstrap peer tag to be removed after this number of ms (default: 2 minutes)
|
39
|
+
*/
|
40
|
+
tagTTL?: number;
|
41
|
+
/**
|
42
|
+
* The interval between queries to a peer (default: 10 seconds)
|
43
|
+
* The interval will increase by a factor of an incrementing number (starting at 1)
|
44
|
+
* until it reaches the maximum attempts before backoff
|
45
|
+
*/
|
46
|
+
queryInterval?: number;
|
47
|
+
/**
|
48
|
+
* The number of attempts before the queries to a peer are aborted (default: 3)
|
49
|
+
*/
|
50
|
+
maxRetries?: number;
|
51
|
+
}
|
52
|
+
|
53
|
+
export const DEFAULT_PEER_EXCHANGE_TAG_NAME = Tags.PEER_EXCHANGE;
|
54
|
+
const DEFAULT_PEER_EXCHANGE_TAG_VALUE = 50;
|
55
|
+
const DEFAULT_PEER_EXCHANGE_TAG_TTL = 100_000_000;
|
56
|
+
|
57
|
+
export class PeerExchangeDiscovery
|
58
|
+
extends TypedEventEmitter<PeerDiscoveryEvents>
|
59
|
+
implements PeerDiscovery
|
60
|
+
{
|
61
|
+
private readonly components: Libp2pComponents;
|
62
|
+
private readonly peerExchange: WakuPeerExchange;
|
63
|
+
private readonly options: Options;
|
64
|
+
private isStarted: boolean;
|
65
|
+
private queryingPeers: Set<string> = new Set();
|
66
|
+
private queryAttempts: Map<string, number> = new Map();
|
67
|
+
|
68
|
+
private readonly handleDiscoveredPeer = (
|
69
|
+
event: CustomEvent<IdentifyResult>
|
70
|
+
): void => {
|
71
|
+
const { protocols, peerId } = event.detail;
|
72
|
+
|
73
|
+
if (
|
74
|
+
!protocols.includes(PeerExchangeCodec) ||
|
75
|
+
this.queryingPeers.has(peerId.toString())
|
76
|
+
)
|
77
|
+
return;
|
78
|
+
|
79
|
+
this.queryingPeers.add(peerId.toString());
|
80
|
+
this.startRecurringQueries(peerId).catch((error) =>
|
81
|
+
log.error(`Error querying peer ${error}`)
|
82
|
+
);
|
83
|
+
};
|
84
|
+
|
85
|
+
constructor(
|
86
|
+
components: Libp2pComponents,
|
87
|
+
pubsubTopics: PubsubTopic[],
|
88
|
+
options: Options = {}
|
89
|
+
) {
|
90
|
+
super();
|
91
|
+
this.components = components;
|
92
|
+
this.peerExchange = new WakuPeerExchange(components, pubsubTopics);
|
93
|
+
this.options = options;
|
94
|
+
this.isStarted = false;
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Start emitting events
|
99
|
+
*/
|
100
|
+
start(): void {
|
101
|
+
if (this.isStarted) {
|
102
|
+
return;
|
103
|
+
}
|
104
|
+
|
105
|
+
log.info("Starting peer exchange node discovery, discovering peers");
|
106
|
+
|
107
|
+
// might be better to use "peer:identify" or "peer:update"
|
108
|
+
this.components.events.addEventListener(
|
109
|
+
"peer:identify",
|
110
|
+
this.handleDiscoveredPeer
|
111
|
+
);
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Remove event listener
|
116
|
+
*/
|
117
|
+
stop(): void {
|
118
|
+
if (!this.isStarted) return;
|
119
|
+
log.info("Stopping peer exchange node discovery");
|
120
|
+
this.isStarted = false;
|
121
|
+
this.queryingPeers.clear();
|
122
|
+
this.components.events.removeEventListener(
|
123
|
+
"peer:identify",
|
124
|
+
this.handleDiscoveredPeer
|
125
|
+
);
|
126
|
+
}
|
127
|
+
|
128
|
+
get [symbol](): true {
|
129
|
+
return true;
|
130
|
+
}
|
131
|
+
|
132
|
+
get [Symbol.toStringTag](): string {
|
133
|
+
return "@waku/peer-exchange";
|
134
|
+
}
|
135
|
+
|
136
|
+
private readonly startRecurringQueries = async (
|
137
|
+
peerId: PeerId
|
138
|
+
): Promise<void> => {
|
139
|
+
const peerIdStr = peerId.toString();
|
140
|
+
const {
|
141
|
+
queryInterval = DEFAULT_PEER_EXCHANGE_QUERY_INTERVAL_MS,
|
142
|
+
maxRetries = DEFAULT_MAX_RETRIES
|
143
|
+
} = this.options;
|
144
|
+
|
145
|
+
log.info(
|
146
|
+
`Querying peer: ${peerIdStr} (attempt ${
|
147
|
+
this.queryAttempts.get(peerIdStr) ?? 1
|
148
|
+
})`
|
149
|
+
);
|
150
|
+
|
151
|
+
await this.query(peerId);
|
152
|
+
|
153
|
+
const currentAttempt = this.queryAttempts.get(peerIdStr) ?? 1;
|
154
|
+
|
155
|
+
if (currentAttempt > maxRetries) {
|
156
|
+
this.abortQueriesForPeer(peerIdStr);
|
157
|
+
return;
|
158
|
+
}
|
159
|
+
|
160
|
+
setTimeout(() => {
|
161
|
+
this.queryAttempts.set(peerIdStr, currentAttempt + 1);
|
162
|
+
this.startRecurringQueries(peerId).catch((error) => {
|
163
|
+
log.error(`Error in startRecurringQueries: ${error}`);
|
164
|
+
});
|
165
|
+
}, queryInterval * currentAttempt);
|
166
|
+
};
|
167
|
+
|
168
|
+
private async query(peerId: PeerId): Promise<PeerExchangeResult> {
|
169
|
+
const { error, peerInfos } = await this.peerExchange.query({
|
170
|
+
numPeers: DEFAULT_PEER_EXCHANGE_REQUEST_NODES,
|
171
|
+
peerId
|
172
|
+
});
|
173
|
+
|
174
|
+
if (error) {
|
175
|
+
log.error("Peer exchange query failed", error);
|
176
|
+
return { error, peerInfos: null };
|
177
|
+
}
|
178
|
+
|
179
|
+
for (const _peerInfo of peerInfos) {
|
180
|
+
const { ENR } = _peerInfo;
|
181
|
+
if (!ENR) {
|
182
|
+
log.warn("No ENR in peerInfo object, skipping");
|
183
|
+
continue;
|
184
|
+
}
|
185
|
+
|
186
|
+
const { peerId, peerInfo, shardInfo } = ENR;
|
187
|
+
if (!peerId || !peerInfo) {
|
188
|
+
continue;
|
189
|
+
}
|
190
|
+
|
191
|
+
const hasPeer = await this.components.peerStore.has(peerId);
|
192
|
+
if (hasPeer) {
|
193
|
+
continue;
|
194
|
+
}
|
195
|
+
|
196
|
+
// update the tags for the peer
|
197
|
+
await this.components.peerStore.save(peerId, {
|
198
|
+
tags: {
|
199
|
+
[DEFAULT_PEER_EXCHANGE_TAG_NAME]: {
|
200
|
+
value: this.options.tagValue ?? DEFAULT_PEER_EXCHANGE_TAG_VALUE,
|
201
|
+
ttl: this.options.tagTTL ?? DEFAULT_PEER_EXCHANGE_TAG_TTL
|
202
|
+
}
|
203
|
+
},
|
204
|
+
...(shardInfo && {
|
205
|
+
metadata: {
|
206
|
+
shardInfo: encodeRelayShard(shardInfo)
|
207
|
+
}
|
208
|
+
})
|
209
|
+
});
|
210
|
+
|
211
|
+
log.info(`Discovered peer: ${peerId.toString()}`);
|
212
|
+
|
213
|
+
this.dispatchEvent(
|
214
|
+
new CustomEvent<PeerInfo>("peer", {
|
215
|
+
detail: {
|
216
|
+
id: peerId,
|
217
|
+
multiaddrs: peerInfo.multiaddrs
|
218
|
+
}
|
219
|
+
})
|
220
|
+
);
|
221
|
+
}
|
222
|
+
|
223
|
+
return { error: null, peerInfos };
|
224
|
+
}
|
225
|
+
|
226
|
+
private abortQueriesForPeer(peerIdStr: string): void {
|
227
|
+
log.info(`Aborting queries for peer: ${peerIdStr}`);
|
228
|
+
this.queryingPeers.delete(peerIdStr);
|
229
|
+
this.queryAttempts.delete(peerIdStr);
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
export function wakuPeerExchangeDiscovery(
|
234
|
+
pubsubTopics: PubsubTopic[]
|
235
|
+
): (components: Libp2pComponents) => PeerExchangeDiscovery {
|
236
|
+
return (components: Libp2pComponents) =>
|
237
|
+
new PeerExchangeDiscovery(components, pubsubTopics);
|
238
|
+
}
|