@waku/core 0.0.1

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 (235) hide show
  1. package/CHANGELOG.md +614 -0
  2. package/README.md +56 -0
  3. package/bundle/browser-1e1a2f27.js +722 -0
  4. package/bundle/crypto-8551d579.js +2585 -0
  5. package/bundle/crypto-b00764b7.js +1772 -0
  6. package/bundle/enr-564d4a51.js +20785 -0
  7. package/bundle/enr-9fc5eed8.js +20786 -0
  8. package/bundle/enr-f6e82a53.js +20785 -0
  9. package/bundle/events-158407bb.js +1929 -0
  10. package/bundle/events-fcbda4dc.js +76 -0
  11. package/bundle/index-02d21809.js +20 -0
  12. package/bundle/index-0a4bdddc.js +2976 -0
  13. package/bundle/index-2ae915be.js +1854 -0
  14. package/bundle/index-64ce43f0.js +69 -0
  15. package/bundle/index-691c0be6.js +4059 -0
  16. package/bundle/index-a013a259.js +20 -0
  17. package/bundle/index-ba42b4fc.js +862 -0
  18. package/bundle/index.js +13428 -0
  19. package/bundle/lib/enr.js +8 -0
  20. package/bundle/lib/peer_discovery_dns.js +5018 -0
  21. package/bundle/lib/peer_discovery_static_list.js +75 -0
  22. package/bundle/lib/predefined_bootstrap_nodes.js +59 -0
  23. package/bundle/lib/utils.js +1 -0
  24. package/bundle/lib/wait_for_remote_peer.js +327 -0
  25. package/bundle/lib/waku_message/topic_only_message.js +4 -0
  26. package/bundle/lib/waku_message/version_0.js +4 -0
  27. package/bundle/lib/waku_message/version_1.js +463 -0
  28. package/bundle/message-e2db79d7.js +8393 -0
  29. package/bundle/multiaddr_to_peer_info-c406b1e1.js +19 -0
  30. package/bundle/multiaddr_to_peer_info-fd1de516.js +19 -0
  31. package/bundle/random_subset-75d1c511.js +26 -0
  32. package/bundle/topic_only_message-34f36fa6.js +82 -0
  33. package/bundle/utils-9a3221f2.js +815 -0
  34. package/bundle/version_0-e6fe440c.js +317 -0
  35. package/dist/index.d.ts +16 -0
  36. package/dist/index.js +17 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/lib/constants.d.ts +4 -0
  39. package/dist/lib/constants.js +5 -0
  40. package/dist/lib/constants.js.map +1 -0
  41. package/dist/lib/crypto.d.ts +34 -0
  42. package/dist/lib/crypto.js +79 -0
  43. package/dist/lib/crypto.js.map +1 -0
  44. package/dist/lib/enr/constants.d.ts +4 -0
  45. package/dist/lib/enr/constants.js +8 -0
  46. package/dist/lib/enr/constants.js.map +1 -0
  47. package/dist/lib/enr/enr.d.ts +90 -0
  48. package/dist/lib/enr/enr.js +432 -0
  49. package/dist/lib/enr/enr.js.map +1 -0
  50. package/dist/lib/enr/index.d.ts +5 -0
  51. package/dist/lib/enr/index.js +6 -0
  52. package/dist/lib/enr/index.js.map +1 -0
  53. package/dist/lib/enr/keypair/index.d.ts +8 -0
  54. package/dist/lib/enr/keypair/index.js +53 -0
  55. package/dist/lib/enr/keypair/index.js.map +1 -0
  56. package/dist/lib/enr/keypair/secp256k1.d.ts +13 -0
  57. package/dist/lib/enr/keypair/secp256k1.js +57 -0
  58. package/dist/lib/enr/keypair/secp256k1.js.map +1 -0
  59. package/dist/lib/enr/keypair/types.d.ts +13 -0
  60. package/dist/lib/enr/keypair/types.js +7 -0
  61. package/dist/lib/enr/keypair/types.js.map +1 -0
  62. package/dist/lib/enr/multiaddr_from_fields.d.ts +2 -0
  63. package/dist/lib/enr/multiaddr_from_fields.js +8 -0
  64. package/dist/lib/enr/multiaddr_from_fields.js.map +1 -0
  65. package/dist/lib/enr/multiaddrs_codec.d.ts +3 -0
  66. package/dist/lib/enr/multiaddrs_codec.js +32 -0
  67. package/dist/lib/enr/multiaddrs_codec.js.map +1 -0
  68. package/dist/lib/enr/types.d.ts +8 -0
  69. package/dist/lib/enr/types.js +3 -0
  70. package/dist/lib/enr/types.js.map +1 -0
  71. package/dist/lib/enr/v4.d.ts +3 -0
  72. package/dist/lib/enr/v4.js +14 -0
  73. package/dist/lib/enr/v4.js.map +1 -0
  74. package/dist/lib/enr/waku2_codec.d.ts +8 -0
  75. package/dist/lib/enr/waku2_codec.js +36 -0
  76. package/dist/lib/enr/waku2_codec.js.map +1 -0
  77. package/dist/lib/group_by.d.ts +3 -0
  78. package/dist/lib/group_by.js +13 -0
  79. package/dist/lib/group_by.js.map +1 -0
  80. package/dist/lib/multiaddr_to_peer_info.d.ts +3 -0
  81. package/dist/lib/multiaddr_to_peer_info.js +15 -0
  82. package/dist/lib/multiaddr_to_peer_info.js.map +1 -0
  83. package/dist/lib/peer_discovery_dns/dns.d.ts +48 -0
  84. package/dist/lib/peer_discovery_dns/dns.js +158 -0
  85. package/dist/lib/peer_discovery_dns/dns.js.map +1 -0
  86. package/dist/lib/peer_discovery_dns/dns_over_https.d.ts +32 -0
  87. package/dist/lib/peer_discovery_dns/dns_over_https.js +87 -0
  88. package/dist/lib/peer_discovery_dns/dns_over_https.js.map +1 -0
  89. package/dist/lib/peer_discovery_dns/enrtree.d.ts +33 -0
  90. package/dist/lib/peer_discovery_dns/enrtree.js +76 -0
  91. package/dist/lib/peer_discovery_dns/enrtree.js.map +1 -0
  92. package/dist/lib/peer_discovery_dns/fetch_nodes.d.ts +14 -0
  93. package/dist/lib/peer_discovery_dns/fetch_nodes.js +133 -0
  94. package/dist/lib/peer_discovery_dns/fetch_nodes.js.map +1 -0
  95. package/dist/lib/peer_discovery_dns/index.d.ts +30 -0
  96. package/dist/lib/peer_discovery_dns/index.js +54 -0
  97. package/dist/lib/peer_discovery_dns/index.js.map +1 -0
  98. package/dist/lib/peer_discovery_static_list.d.ts +44 -0
  99. package/dist/lib/peer_discovery_static_list.js +72 -0
  100. package/dist/lib/peer_discovery_static_list.js.map +1 -0
  101. package/dist/lib/predefined_bootstrap_nodes.d.ts +35 -0
  102. package/dist/lib/predefined_bootstrap_nodes.js +56 -0
  103. package/dist/lib/predefined_bootstrap_nodes.js.map +1 -0
  104. package/dist/lib/push_or_init_map.d.ts +1 -0
  105. package/dist/lib/push_or_init_map.js +9 -0
  106. package/dist/lib/push_or_init_map.js.map +1 -0
  107. package/dist/lib/random_subset.d.ts +4 -0
  108. package/dist/lib/random_subset.js +25 -0
  109. package/dist/lib/random_subset.js.map +1 -0
  110. package/dist/lib/select_connection.d.ts +2 -0
  111. package/dist/lib/select_connection.js +19 -0
  112. package/dist/lib/select_connection.js.map +1 -0
  113. package/dist/lib/select_peer.d.ts +15 -0
  114. package/dist/lib/select_peer.js +59 -0
  115. package/dist/lib/select_peer.js.map +1 -0
  116. package/dist/lib/to_proto_message.d.ts +3 -0
  117. package/dist/lib/to_proto_message.js +11 -0
  118. package/dist/lib/to_proto_message.js.map +1 -0
  119. package/dist/lib/utils.d.ts +22 -0
  120. package/dist/lib/utils.js +40 -0
  121. package/dist/lib/utils.js.map +1 -0
  122. package/dist/lib/wait_for_remote_peer.d.ts +22 -0
  123. package/dist/lib/wait_for_remote_peer.js +113 -0
  124. package/dist/lib/wait_for_remote_peer.js.map +1 -0
  125. package/dist/lib/waku.d.ts +61 -0
  126. package/dist/lib/waku.js +174 -0
  127. package/dist/lib/waku.js.map +1 -0
  128. package/dist/lib/waku_filter/filter_rpc.d.ts +25 -0
  129. package/dist/lib/waku_filter/filter_rpc.js +44 -0
  130. package/dist/lib/waku_filter/filter_rpc.js.map +1 -0
  131. package/dist/lib/waku_filter/index.d.ts +50 -0
  132. package/dist/lib/waku_filter/index.js +181 -0
  133. package/dist/lib/waku_filter/index.js.map +1 -0
  134. package/dist/lib/waku_light_push/index.d.ts +38 -0
  135. package/dist/lib/waku_light_push/index.js +83 -0
  136. package/dist/lib/waku_light_push/index.js.map +1 -0
  137. package/dist/lib/waku_light_push/push_rpc.d.ts +11 -0
  138. package/dist/lib/waku_light_push/push_rpc.js +31 -0
  139. package/dist/lib/waku_light_push/push_rpc.js.map +1 -0
  140. package/dist/lib/waku_message/constants.d.ts +12 -0
  141. package/dist/lib/waku_message/constants.js +10 -0
  142. package/dist/lib/waku_message/constants.js.map +1 -0
  143. package/dist/lib/waku_message/ecies.d.ts +17 -0
  144. package/dist/lib/waku_message/ecies.js +126 -0
  145. package/dist/lib/waku_message/ecies.js.map +1 -0
  146. package/dist/lib/waku_message/symmetric.d.ts +3 -0
  147. package/dist/lib/waku_message/symmetric.js +18 -0
  148. package/dist/lib/waku_message/symmetric.js.map +1 -0
  149. package/dist/lib/waku_message/topic_only_message.d.ts +15 -0
  150. package/dist/lib/waku_message/topic_only_message.js +31 -0
  151. package/dist/lib/waku_message/topic_only_message.js.map +1 -0
  152. package/dist/lib/waku_message/version_0.d.ts +26 -0
  153. package/dist/lib/waku_message/version_0.js +96 -0
  154. package/dist/lib/waku_message/version_0.js.map +1 -0
  155. package/dist/lib/waku_message/version_1.d.ts +93 -0
  156. package/dist/lib/waku_message/version_1.js +325 -0
  157. package/dist/lib/waku_message/version_1.js.map +1 -0
  158. package/dist/lib/waku_relay/constants.d.ts +63 -0
  159. package/dist/lib/waku_relay/constants.js +67 -0
  160. package/dist/lib/waku_relay/constants.js.map +1 -0
  161. package/dist/lib/waku_relay/index.d.ts +65 -0
  162. package/dist/lib/waku_relay/index.js +111 -0
  163. package/dist/lib/waku_relay/index.js.map +1 -0
  164. package/dist/lib/waku_store/history_rpc.d.ts +27 -0
  165. package/dist/lib/waku_store/history_rpc.js +71 -0
  166. package/dist/lib/waku_store/history_rpc.js.map +1 -0
  167. package/dist/lib/waku_store/index.d.ts +126 -0
  168. package/dist/lib/waku_store/index.js +218 -0
  169. package/dist/lib/waku_store/index.js.map +1 -0
  170. package/dist/proto/filter.d.ts +65 -0
  171. package/dist/proto/filter.js +425 -0
  172. package/dist/proto/filter.js.map +1 -0
  173. package/dist/proto/light_push.d.ts +57 -0
  174. package/dist/proto/light_push.js +369 -0
  175. package/dist/proto/light_push.js.map +1 -0
  176. package/dist/proto/message.d.ts +29 -0
  177. package/dist/proto/message.js +215 -0
  178. package/dist/proto/message.js.map +1 -0
  179. package/dist/proto/store.d.ts +104 -0
  180. package/dist/proto/store.js +602 -0
  181. package/dist/proto/store.js.map +1 -0
  182. package/dist/proto/topic_only_message.d.ts +10 -0
  183. package/dist/proto/topic_only_message.js +46 -0
  184. package/dist/proto/topic_only_message.js.map +1 -0
  185. package/package.json +292 -0
  186. package/src/index.ts +33 -0
  187. package/src/lib/constants.ts +4 -0
  188. package/src/lib/crypto.ts +100 -0
  189. package/src/lib/enr/constants.ts +10 -0
  190. package/src/lib/enr/enr.ts +516 -0
  191. package/src/lib/enr/index.ts +5 -0
  192. package/src/lib/enr/keypair/index.ts +76 -0
  193. package/src/lib/enr/keypair/secp256k1.ts +69 -0
  194. package/src/lib/enr/keypair/types.ts +14 -0
  195. package/src/lib/enr/multiaddr_from_fields.ts +18 -0
  196. package/src/lib/enr/multiaddrs_codec.ts +50 -0
  197. package/src/lib/enr/types.ts +11 -0
  198. package/src/lib/enr/v4.ts +22 -0
  199. package/src/lib/enr/waku2_codec.ts +39 -0
  200. package/src/lib/group_by.ts +14 -0
  201. package/src/lib/multiaddr_to_peer_info.ts +17 -0
  202. package/src/lib/peer_discovery_dns/dns.ts +223 -0
  203. package/src/lib/peer_discovery_dns/dns_over_https.ts +98 -0
  204. package/src/lib/peer_discovery_dns/enrtree.ts +123 -0
  205. package/src/lib/peer_discovery_dns/fetch_nodes.ts +180 -0
  206. package/src/lib/peer_discovery_dns/index.ts +84 -0
  207. package/src/lib/peer_discovery_static_list.ts +118 -0
  208. package/src/lib/predefined_bootstrap_nodes.ts +72 -0
  209. package/src/lib/push_or_init_map.ts +13 -0
  210. package/src/lib/random_subset.ts +30 -0
  211. package/src/lib/select_connection.ts +24 -0
  212. package/src/lib/select_peer.ts +77 -0
  213. package/src/lib/to_proto_message.ts +15 -0
  214. package/src/lib/utils.ts +50 -0
  215. package/src/lib/wait_for_remote_peer.ts +151 -0
  216. package/src/lib/waku.ts +258 -0
  217. package/src/lib/waku_filter/filter_rpc.ts +57 -0
  218. package/src/lib/waku_filter/index.ts +291 -0
  219. package/src/lib/waku_light_push/index.ts +137 -0
  220. package/src/lib/waku_light_push/push_rpc.ts +39 -0
  221. package/src/lib/waku_message/constants.ts +10 -0
  222. package/src/lib/waku_message/ecies.ts +194 -0
  223. package/src/lib/waku_message/symmetric.ts +33 -0
  224. package/src/lib/waku_message/topic_only_message.ts +40 -0
  225. package/src/lib/waku_message/version_0.ts +121 -0
  226. package/src/lib/waku_message/version_1.ts +457 -0
  227. package/src/lib/waku_relay/constants.ts +77 -0
  228. package/src/lib/waku_relay/index.ts +189 -0
  229. package/src/lib/waku_store/history_rpc.ts +94 -0
  230. package/src/lib/waku_store/index.ts +372 -0
  231. package/src/proto/filter.ts +602 -0
  232. package/src/proto/light_push.ts +526 -0
  233. package/src/proto/message.ts +304 -0
  234. package/src/proto/store.ts +844 -0
  235. package/src/proto/topic_only_message.ts +67 -0
@@ -0,0 +1,180 @@
1
+ import debug from "debug";
2
+
3
+ import { ENR, Waku2 } from "../enr";
4
+
5
+ import { NodeCapabilityCount } from "./dns";
6
+
7
+ const log = debug("waku:discovery:fetch_nodes");
8
+
9
+ /**
10
+ * Fetch nodes using passed [[getNode]] until all wanted capabilities are
11
+ * fulfilled or the number of [[getNode]] call exceeds the sum of
12
+ * [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
13
+ */
14
+ export async function fetchNodesUntilCapabilitiesFulfilled(
15
+ wantedNodeCapabilityCount: Partial<NodeCapabilityCount>,
16
+ errorTolerance: number,
17
+ getNode: () => Promise<ENR | null>
18
+ ): Promise<ENR[]> {
19
+ const wanted = {
20
+ relay: wantedNodeCapabilityCount.relay ?? 0,
21
+ store: wantedNodeCapabilityCount.store ?? 0,
22
+ filter: wantedNodeCapabilityCount.filter ?? 0,
23
+ lightPush: wantedNodeCapabilityCount.lightPush ?? 0,
24
+ };
25
+
26
+ const maxSearches =
27
+ wanted.relay + wanted.store + wanted.filter + wanted.lightPush;
28
+
29
+ const actual = {
30
+ relay: 0,
31
+ store: 0,
32
+ filter: 0,
33
+ lightPush: 0,
34
+ };
35
+
36
+ let totalSearches = 0;
37
+ const peers: ENR[] = [];
38
+
39
+ while (
40
+ !isSatisfied(wanted, actual) &&
41
+ totalSearches < maxSearches + errorTolerance
42
+ ) {
43
+ const peer = await getNode();
44
+ if (peer && isNewPeer(peer, peers)) {
45
+ // ENRs without a waku2 key are ignored.
46
+ if (peer.waku2) {
47
+ if (helpsSatisfyCapabilities(peer.waku2, wanted, actual)) {
48
+ addCapabilities(peer.waku2, actual);
49
+ peers.push(peer);
50
+ }
51
+ }
52
+ log(`got new peer candidate from DNS address=${peer.nodeId}@${peer.ip}`);
53
+ }
54
+
55
+ totalSearches++;
56
+ }
57
+ return peers;
58
+ }
59
+
60
+ /**
61
+ * Fetch nodes using passed [[getNode]] until all wanted capabilities are
62
+ * fulfilled or the number of [[getNode]] call exceeds the sum of
63
+ * [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
64
+ */
65
+ export async function* yieldNodesUntilCapabilitiesFulfilled(
66
+ wantedNodeCapabilityCount: Partial<NodeCapabilityCount>,
67
+ errorTolerance: number,
68
+ getNode: () => Promise<ENR | null>
69
+ ): AsyncGenerator<ENR> {
70
+ const wanted = {
71
+ relay: wantedNodeCapabilityCount.relay ?? 0,
72
+ store: wantedNodeCapabilityCount.store ?? 0,
73
+ filter: wantedNodeCapabilityCount.filter ?? 0,
74
+ lightPush: wantedNodeCapabilityCount.lightPush ?? 0,
75
+ };
76
+
77
+ const maxSearches =
78
+ wanted.relay + wanted.store + wanted.filter + wanted.lightPush;
79
+
80
+ const actual = {
81
+ relay: 0,
82
+ store: 0,
83
+ filter: 0,
84
+ lightPush: 0,
85
+ };
86
+
87
+ let totalSearches = 0;
88
+ const peerNodeIds = new Set();
89
+
90
+ while (
91
+ !isSatisfied(wanted, actual) &&
92
+ totalSearches < maxSearches + errorTolerance
93
+ ) {
94
+ const peer = await getNode();
95
+ if (peer && peer.nodeId && !peerNodeIds.has(peer.nodeId)) {
96
+ peerNodeIds.add(peer.nodeId);
97
+ // ENRs without a waku2 key are ignored.
98
+ if (peer.waku2) {
99
+ if (helpsSatisfyCapabilities(peer.waku2, wanted, actual)) {
100
+ addCapabilities(peer.waku2, actual);
101
+ yield peer;
102
+ }
103
+ }
104
+ log(`got new peer candidate from DNS address=${peer.nodeId}@${peer.ip}`);
105
+ }
106
+ totalSearches++;
107
+ }
108
+ }
109
+
110
+ function isSatisfied(
111
+ wanted: NodeCapabilityCount,
112
+ actual: NodeCapabilityCount
113
+ ): boolean {
114
+ return (
115
+ actual.relay >= wanted.relay &&
116
+ actual.store >= wanted.store &&
117
+ actual.filter >= wanted.filter &&
118
+ actual.lightPush >= wanted.lightPush
119
+ );
120
+ }
121
+
122
+ function isNewPeer(peer: ENR, peers: ENR[]): boolean {
123
+ if (!peer.nodeId) return false;
124
+
125
+ for (const existingPeer of peers) {
126
+ if (peer.nodeId === existingPeer.nodeId) {
127
+ return false;
128
+ }
129
+ }
130
+
131
+ return true;
132
+ }
133
+
134
+ function addCapabilities(node: Waku2, total: NodeCapabilityCount): void {
135
+ if (node.relay) total.relay += 1;
136
+ if (node.store) total.store += 1;
137
+ if (node.filter) total.filter += 1;
138
+ if (node.lightPush) total.lightPush += 1;
139
+ }
140
+
141
+ /**
142
+ * Checks if the proposed ENR [[node]] helps satisfy the [[wanted]] capabilities,
143
+ * considering the [[actual]] capabilities of nodes retrieved so far..
144
+ *
145
+ * @throws If the function is called when the wanted capabilities are already fulfilled.
146
+ */
147
+ function helpsSatisfyCapabilities(
148
+ node: Waku2,
149
+ wanted: NodeCapabilityCount,
150
+ actual: NodeCapabilityCount
151
+ ): boolean {
152
+ if (isSatisfied(wanted, actual)) {
153
+ throw "Internal Error: Waku2 wanted capabilities are already fulfilled";
154
+ }
155
+
156
+ const missing = missingCapabilities(wanted, actual);
157
+
158
+ return (
159
+ (missing.relay && node.relay) ||
160
+ (missing.store && node.store) ||
161
+ (missing.filter && node.filter) ||
162
+ (missing.lightPush && node.lightPush)
163
+ );
164
+ }
165
+
166
+ /**
167
+ * Return a [[Waku2]] Object for which capabilities are set to true if they are
168
+ * [[wanted]] yet missing from [[actual]].
169
+ */
170
+ function missingCapabilities(
171
+ wanted: NodeCapabilityCount,
172
+ actual: NodeCapabilityCount
173
+ ): Waku2 {
174
+ return {
175
+ relay: actual.relay < wanted.relay,
176
+ store: actual.store < wanted.store,
177
+ filter: actual.filter < wanted.filter,
178
+ lightPush: actual.lightPush < wanted.lightPush,
179
+ };
180
+ }
@@ -0,0 +1,84 @@
1
+ import type {
2
+ PeerDiscovery,
3
+ PeerDiscoveryEvents,
4
+ } from "@libp2p/interface-peer-discovery";
5
+ import { symbol } from "@libp2p/interface-peer-discovery";
6
+ import type { PeerInfo } from "@libp2p/interface-peer-info";
7
+ import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
8
+ import debug from "debug";
9
+
10
+ import { ENR } from "../enr";
11
+ import { multiaddrsToPeerInfo } from "../multiaddr_to_peer_info";
12
+
13
+ import { DnsNodeDiscovery, NodeCapabilityCount } from "./dns";
14
+
15
+ const log = debug("waku:peer-discovery-dns");
16
+
17
+ /**
18
+ * Parse options and expose function to return bootstrap peer addresses.
19
+ *
20
+ * @throws if an invalid combination of options is passed, see [[BootstrapOptions]] for details.
21
+ */
22
+ export class PeerDiscoveryDns
23
+ extends EventEmitter<PeerDiscoveryEvents>
24
+ implements PeerDiscovery
25
+ {
26
+ private readonly nextPeer: () => AsyncGenerator<ENR>;
27
+ private _started: boolean;
28
+
29
+ /**
30
+ * @param enrUrl An EIP-1459 ENR Tree URL. For example:
31
+ * "enrtree://AOFTICU2XWDULNLZGRMQS4RIZPAZEHYMV4FYHAPW563HNRAOERP7C@test.nodes.vac.dev"
32
+ * @param wantedNodeCapabilityCount Specifies what node capabilities
33
+ * (protocol) must be returned.
34
+ */
35
+ constructor(
36
+ enrUrl: string,
37
+ wantedNodeCapabilityCount: Partial<NodeCapabilityCount>
38
+ ) {
39
+ super();
40
+ this._started = false;
41
+ log("Use following EIP-1459 ENR Tree URL: ", enrUrl);
42
+
43
+ const dns = DnsNodeDiscovery.dnsOverHttp();
44
+
45
+ this.nextPeer = dns.getNextPeer.bind(
46
+ {},
47
+ [enrUrl],
48
+ wantedNodeCapabilityCount
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Start discovery process
54
+ */
55
+ async start(): Promise<void> {
56
+ log("Starting peer discovery via dns");
57
+
58
+ this._started = true;
59
+ for await (const peer of this.nextPeer()) {
60
+ if (!this._started) return;
61
+ const peerInfos = multiaddrsToPeerInfo(peer.getFullMultiaddrs());
62
+ peerInfos.forEach((peerInfo) => {
63
+ this.dispatchEvent(
64
+ new CustomEvent<PeerInfo>("peer", { detail: peerInfo })
65
+ );
66
+ });
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Stop emitting events
72
+ */
73
+ stop(): void {
74
+ this._started = false;
75
+ }
76
+
77
+ get [symbol](): true {
78
+ return true;
79
+ }
80
+
81
+ get [Symbol.toStringTag](): string {
82
+ return "@waku/bootstrap";
83
+ }
84
+ }
@@ -0,0 +1,118 @@
1
+ import type {
2
+ PeerDiscovery,
3
+ PeerDiscoveryEvents,
4
+ } from "@libp2p/interface-peer-discovery";
5
+ import { symbol } from "@libp2p/interface-peer-discovery";
6
+ import type { PeerInfo } from "@libp2p/interface-peer-info";
7
+ import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
8
+ import type { Multiaddr } from "@multiformats/multiaddr";
9
+ import { multiaddr } from "@multiformats/multiaddr";
10
+ import debug from "debug";
11
+
12
+ import { multiaddrsToPeerInfo } from "./multiaddr_to_peer_info";
13
+ import { getPseudoRandomSubset } from "./random_subset";
14
+
15
+ const log = debug("waku:peer-discovery-static-list");
16
+
17
+ export interface Options {
18
+ /**
19
+ * The maximum of peers to connect to as part of the bootstrap process.
20
+ *
21
+ * @default The length of the passed `peers` array.
22
+ */
23
+ maxPeers?: number;
24
+ /**
25
+ * The interval between emitting addresses in milliseconds.
26
+ *
27
+ * @default {@link PeerDiscoveryStaticPeers.DefaultInterval}
28
+ */
29
+ interval?: number;
30
+ }
31
+
32
+ /**
33
+ * Pass a list of multiaddr that will be used to bootstrap a node.
34
+ */
35
+ export class PeerDiscoveryStaticPeers
36
+ extends EventEmitter<PeerDiscoveryEvents>
37
+ implements PeerDiscovery
38
+ {
39
+ static DefaultInterval = 200;
40
+ private readonly peers: PeerInfo[];
41
+ private timer?: ReturnType<typeof setInterval>;
42
+ private readonly interval: number;
43
+
44
+ /**
45
+ * @param peers Multiaddrs of peers to connect to.
46
+ * @param opts
47
+ */
48
+ constructor(peers: string[] | Multiaddr[], opts?: Options) {
49
+ super();
50
+
51
+ this.interval = opts?.interval ?? PeerDiscoveryStaticPeers.DefaultInterval;
52
+ const maxPeers = opts?.maxPeers ?? peers?.length;
53
+
54
+ const peerMas = peers.map((peer: string | Multiaddr) => {
55
+ if (typeof peer === "string") {
56
+ return multiaddr(peer);
57
+ } else {
58
+ return peer;
59
+ }
60
+ });
61
+ this.peers = multiaddrsToPeerInfo(getPseudoRandomSubset(peerMas, maxPeers));
62
+ log(
63
+ "Use provided list of peers (reduced to maxPeers)",
64
+ this.peers.map((ma) => ma.toString())
65
+ );
66
+ }
67
+
68
+ /**
69
+ * Start emitting static peers.
70
+ */
71
+ start(): void {
72
+ this._startTimer();
73
+ }
74
+
75
+ private _startTimer(): void {
76
+ if (this.peers) {
77
+ log("Starting to emit static peers.");
78
+ if (this.timer != null) {
79
+ return;
80
+ }
81
+
82
+ this.timer = setInterval(() => this._returnPeers(), this.interval);
83
+
84
+ this._returnPeers();
85
+ }
86
+ }
87
+
88
+ _returnPeers(): void {
89
+ if (this.timer == null) {
90
+ return;
91
+ }
92
+
93
+ this.peers.forEach((peerData) => {
94
+ this.dispatchEvent(
95
+ new CustomEvent<PeerInfo>("peer", { detail: peerData })
96
+ );
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Stop emitting peers.
102
+ */
103
+ stop(): void {
104
+ if (this.timer != null) {
105
+ clearInterval(this.timer);
106
+ }
107
+
108
+ this.timer = undefined;
109
+ }
110
+
111
+ get [symbol](): true {
112
+ return true;
113
+ }
114
+
115
+ get [Symbol.toStringTag](): string {
116
+ return "@waku/peer-discovery-static-list";
117
+ }
118
+ }
@@ -0,0 +1,72 @@
1
+ import type { Multiaddr } from "@multiformats/multiaddr";
2
+ import { multiaddr } from "@multiformats/multiaddr";
3
+
4
+ import { getPseudoRandomSubset } from "./random_subset";
5
+
6
+ export const DefaultWantedNumber = 1;
7
+
8
+ export enum Fleet {
9
+ Prod = "prod",
10
+ Test = "test",
11
+ }
12
+
13
+ /**
14
+ * Return list of pre-defined (hardcoded) bootstrap nodes.
15
+ *
16
+ * Default behavior is to return nodes of the nwaku Status Prod fleet.
17
+ *
18
+ * @param fleet The fleet to be returned. Defaults to production fleet.
19
+ * @param wantedNumber The number of connections desired. Defaults to {@link DefaultWantedNumber}.
20
+ *
21
+ * @returns An array of multiaddresses.
22
+ */
23
+ export function getPredefinedBootstrapNodes(
24
+ fleet: Fleet = Fleet.Prod,
25
+ wantedNumber: number = DefaultWantedNumber
26
+ ): Multiaddr[] {
27
+ if (wantedNumber <= 0) {
28
+ return [];
29
+ }
30
+
31
+ let nodes;
32
+ switch (fleet) {
33
+ case Fleet.Prod:
34
+ nodes = fleets.fleets["wakuv2.prod"]["waku-websocket"];
35
+ break;
36
+ case Fleet.Test:
37
+ nodes = fleets.fleets["wakuv2.test"]["waku-websocket"];
38
+ break;
39
+ default:
40
+ nodes = fleets.fleets["wakuv2.prod"]["waku-websocket"];
41
+ }
42
+
43
+ nodes = Object.values(nodes) as string[];
44
+
45
+ nodes = nodes.map((node: string) => multiaddr(node));
46
+ return getPseudoRandomSubset(nodes, wantedNumber);
47
+ }
48
+
49
+ export const fleets = {
50
+ fleets: {
51
+ "wakuv2.prod": {
52
+ "waku-websocket": {
53
+ "node-01.ac-cn-hongkong-c.wakuv2.prod":
54
+ "/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
55
+ "node-01.do-ams3.wakuv2.prod":
56
+ "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
57
+ "node-01.gc-us-central1-a.wakuv2.prod":
58
+ "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA",
59
+ },
60
+ },
61
+ "wakuv2.test": {
62
+ "waku-websocket": {
63
+ "node-01.ac-cn-hongkong-c.wakuv2.test":
64
+ "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
65
+ "node-01.do-ams3.wakuv2.test":
66
+ "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
67
+ "node-01.gc-us-central1-a.wakuv2.test":
68
+ "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS",
69
+ },
70
+ },
71
+ },
72
+ };
@@ -0,0 +1,13 @@
1
+ export function pushOrInitMapSet<K, V>(
2
+ map: Map<K, Set<V>>,
3
+ key: K,
4
+ newValue: V
5
+ ): void {
6
+ let arr = map.get(key);
7
+ if (typeof arr === "undefined") {
8
+ map.set(key, new Set());
9
+ arr = map.get(key) as Set<V>;
10
+ }
11
+
12
+ arr.add(newValue);
13
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Return pseudo random subset of the input.
3
+ */
4
+ export function getPseudoRandomSubset<T>(
5
+ values: T[],
6
+ wantedNumber: number
7
+ ): T[] {
8
+ if (values.length <= wantedNumber || values.length <= 1) {
9
+ return values;
10
+ }
11
+
12
+ return shuffle(values).slice(0, wantedNumber);
13
+ }
14
+
15
+ function shuffle<T>(arr: T[]): T[] {
16
+ if (arr.length <= 1) {
17
+ return arr;
18
+ }
19
+ const randInt = (): number => {
20
+ return Math.floor(Math.random() * Math.floor(arr.length));
21
+ };
22
+
23
+ for (let i = 0; i < arr.length; i++) {
24
+ const j = randInt();
25
+ const tmp = arr[i];
26
+ arr[i] = arr[j];
27
+ arr[j] = tmp;
28
+ }
29
+ return arr;
30
+ }
@@ -0,0 +1,24 @@
1
+ import { Connection } from "@libp2p/interface-connection";
2
+
3
+ export function selectConnection(
4
+ connections: Connection[]
5
+ ): Connection | undefined {
6
+ if (!connections.length) return;
7
+ if (connections.length === 1) return connections[0];
8
+
9
+ let latestConnection: Connection | undefined;
10
+
11
+ connections.forEach((connection) => {
12
+ if (connection.stat.status === "OPEN") {
13
+ if (!latestConnection) {
14
+ latestConnection = connection;
15
+ } else if (
16
+ connection.stat.timeline.open > latestConnection.stat.timeline.open
17
+ ) {
18
+ latestConnection = connection;
19
+ }
20
+ }
21
+ });
22
+
23
+ return latestConnection;
24
+ }
@@ -0,0 +1,77 @@
1
+ import type { PeerId } from "@libp2p/interface-peer-id";
2
+ import type { Peer, PeerStore } from "@libp2p/interface-peer-store";
3
+ import debug from "debug";
4
+
5
+ const log = debug("waku:select-peer");
6
+
7
+ /**
8
+ * Returns a pseudo-random peer that supports the given protocol.
9
+ * Useful for protocols such as store and light push
10
+ */
11
+ export function selectRandomPeer(peers: Peer[]): Peer | undefined {
12
+ if (peers.length === 0) return;
13
+
14
+ const index = Math.round(Math.random() * (peers.length - 1));
15
+ return peers[index];
16
+ }
17
+
18
+ /**
19
+ * Returns the list of peers that supports the given protocol.
20
+ */
21
+ export async function getPeersForProtocol(
22
+ peerStore: PeerStore,
23
+ protocols: string[]
24
+ ): Promise<Peer[]> {
25
+ const peers: Peer[] = [];
26
+ await peerStore.forEach((peer) => {
27
+ for (let i = 0; i < protocols.length; i++) {
28
+ if (peer.protocols.includes(protocols[i])) {
29
+ peers.push(peer);
30
+ break;
31
+ }
32
+ }
33
+ });
34
+ return peers;
35
+ }
36
+
37
+ export async function selectPeerForProtocol(
38
+ peerStore: PeerStore,
39
+ protocols: string[],
40
+ peerId?: PeerId
41
+ ): Promise<{ peer: Peer; protocol: string } | undefined> {
42
+ let peer;
43
+ if (peerId) {
44
+ peer = await peerStore.get(peerId);
45
+ if (!peer) {
46
+ log(
47
+ `Failed to retrieve connection details for provided peer in peer store: ${peerId.toString()}`
48
+ );
49
+ return;
50
+ }
51
+ } else {
52
+ const peers = await getPeersForProtocol(peerStore, protocols);
53
+ peer = selectRandomPeer(peers);
54
+ if (!peer) {
55
+ log("Failed to find known peer that registers protocols", protocols);
56
+ return;
57
+ }
58
+ }
59
+
60
+ let protocol;
61
+ for (const codec of protocols) {
62
+ if (peer.protocols.includes(codec)) {
63
+ protocol = codec;
64
+ // Do not break as we want to keep the last value
65
+ }
66
+ }
67
+ log(`Using codec ${protocol}`);
68
+ if (!protocol) {
69
+ log(
70
+ `Peer does not register required protocols: ${peer.id.toString()}`,
71
+ protocols
72
+ );
73
+ return;
74
+ }
75
+
76
+ return { peer, protocol };
77
+ }
@@ -0,0 +1,15 @@
1
+ import { ProtoMessage } from "@waku/interfaces";
2
+
3
+ import { WakuMessage as WakuMessageProto } from "../proto/message";
4
+
5
+ const EmptyMessage: ProtoMessage = {
6
+ payload: undefined,
7
+ contentTopic: undefined,
8
+ version: undefined,
9
+ timestamp: undefined,
10
+ rateLimitProof: undefined,
11
+ };
12
+
13
+ export function toProtoMessage(wire: WakuMessageProto): ProtoMessage {
14
+ return { ...EmptyMessage, ...wire };
15
+ }
@@ -0,0 +1,50 @@
1
+ import { fromString } from "uint8arrays/from-string";
2
+ import { toString } from "uint8arrays/to-string";
3
+
4
+ /**
5
+ * Convert input to a byte array.
6
+ *
7
+ * Handles both `0x` prefixed and non-prefixed strings.
8
+ */
9
+ export function hexToBytes(hex: string | Uint8Array): Uint8Array {
10
+ if (typeof hex === "string") {
11
+ const _hex = hex.replace(/^0x/i, "");
12
+ return fromString(_hex.toLowerCase(), "base16");
13
+ }
14
+ return hex;
15
+ }
16
+
17
+ /**
18
+ * Convert byte array to hex string (no `0x` prefix).
19
+ */
20
+ export const bytesToHex = (bytes: Uint8Array): string =>
21
+ toString(bytes, "base16");
22
+
23
+ /**
24
+ * Decode byte array to utf-8 string.
25
+ */
26
+ export const bytesToUtf8 = (b: Uint8Array): string => toString(b, "utf8");
27
+
28
+ /**
29
+ * Encode utf-8 string to byte array.
30
+ */
31
+ export const utf8ToBytes = (s: string): Uint8Array => fromString(s, "utf8");
32
+
33
+ /**
34
+ * Concatenate using Uint8Arrays as `Buffer` has a different behavior with `DataView`
35
+ */
36
+ export function concat(
37
+ byteArrays: Uint8Array[],
38
+ totalLength?: number
39
+ ): Uint8Array {
40
+ const len =
41
+ totalLength ?? byteArrays.reduce((acc, curr) => acc + curr.length, 0);
42
+ const res = new Uint8Array(len);
43
+
44
+ let offset = 0;
45
+ for (const bytes of byteArrays) {
46
+ res.set(bytes, offset);
47
+ offset += bytes.length;
48
+ }
49
+ return res;
50
+ }