@waku/core 0.0.17 → 0.0.18

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 (69) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/bundle/{browser-2f1afe46.js → browser-bde977a3.js} +12 -9
  3. package/bundle/index.js +610 -32840
  4. package/bundle/lib/base_protocol.js +4 -1
  5. package/bundle/lib/message/version_0.js +2 -3
  6. package/bundle/{peer_exchange-1229c8b0.js → version_0-c6b47311.js} +172 -45
  7. package/dist/index.d.ts +1 -3
  8. package/dist/index.js +1 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/lib/base_protocol.js +3 -0
  11. package/dist/lib/base_protocol.js.map +1 -1
  12. package/dist/lib/connection_manager.d.ts +1 -0
  13. package/dist/lib/connection_manager.js +33 -25
  14. package/dist/lib/connection_manager.js.map +1 -1
  15. package/dist/lib/filter/filter_rpc.js +1 -0
  16. package/dist/lib/filter/filter_rpc.js.map +1 -1
  17. package/dist/lib/filter/index.js +4 -1
  18. package/dist/lib/filter/index.js.map +1 -1
  19. package/dist/lib/keep_alive_manager.d.ts +1 -0
  20. package/dist/lib/keep_alive_manager.js +5 -1
  21. package/dist/lib/keep_alive_manager.js.map +1 -1
  22. package/dist/lib/light_push/index.d.ts +1 -1
  23. package/dist/lib/light_push/index.js +27 -7
  24. package/dist/lib/light_push/index.js.map +1 -1
  25. package/dist/lib/light_push/push_rpc.js +1 -0
  26. package/dist/lib/light_push/push_rpc.js.map +1 -1
  27. package/dist/lib/message/index.d.ts +0 -1
  28. package/dist/lib/message/index.js +0 -1
  29. package/dist/lib/message/index.js.map +1 -1
  30. package/dist/lib/message/version_0.d.ts +1 -2
  31. package/dist/lib/message/version_0.js +6 -0
  32. package/dist/lib/message/version_0.js.map +1 -1
  33. package/dist/lib/store/history_rpc.js +1 -0
  34. package/dist/lib/store/history_rpc.js.map +1 -1
  35. package/dist/lib/store/index.js +2 -0
  36. package/dist/lib/store/index.js.map +1 -1
  37. package/dist/lib/waku.js +6 -0
  38. package/dist/lib/waku.js.map +1 -1
  39. package/package.json +8 -11
  40. package/src/index.ts +1 -9
  41. package/src/lib/connection_manager.ts +13 -4
  42. package/src/lib/filter/index.ts +1 -1
  43. package/src/lib/keep_alive_manager.ts +1 -2
  44. package/src/lib/light_push/index.ts +26 -9
  45. package/src/lib/message/index.ts +0 -1
  46. package/src/lib/message/version_0.ts +1 -1
  47. package/bundle/lib/message/topic_only_message.js +0 -3
  48. package/bundle/topic_only_message-e8406994.js +0 -43
  49. package/bundle/version_0-5a4becbc.js +0 -149
  50. package/dist/lib/group_by.d.ts +0 -3
  51. package/dist/lib/group_by.js +0 -13
  52. package/dist/lib/group_by.js.map +0 -1
  53. package/dist/lib/message/topic_only_message.d.ts +0 -18
  54. package/dist/lib/message/topic_only_message.js +0 -35
  55. package/dist/lib/message/topic_only_message.js.map +0 -1
  56. package/dist/lib/relay/constants.d.ts +0 -63
  57. package/dist/lib/relay/constants.js +0 -64
  58. package/dist/lib/relay/constants.js.map +0 -1
  59. package/dist/lib/relay/index.d.ts +0 -11
  60. package/dist/lib/relay/index.js +0 -181
  61. package/dist/lib/relay/index.js.map +0 -1
  62. package/dist/lib/relay/message_validator.d.ts +0 -4
  63. package/dist/lib/relay/message_validator.js +0 -25
  64. package/dist/lib/relay/message_validator.js.map +0 -1
  65. package/src/lib/group_by.ts +0 -14
  66. package/src/lib/message/topic_only_message.ts +0 -51
  67. package/src/lib/relay/constants.ts +0 -74
  68. package/src/lib/relay/index.ts +0 -294
  69. package/src/lib/relay/message_validator.ts +0 -35
@@ -1,51 +0,0 @@
1
- import type {
2
- IDecodedMessage,
3
- IDecoder,
4
- IProtoMessage,
5
- } from "@waku/interfaces";
6
- import { TopicOnlyMessage as ProtoTopicOnlyMessage } from "@waku/proto";
7
- import debug from "debug";
8
-
9
- const log = debug("waku:message:topic-only");
10
-
11
- export class TopicOnlyMessage implements IDecodedMessage {
12
- public payload: Uint8Array = new Uint8Array();
13
- public rateLimitProof: undefined;
14
- public timestamp: undefined;
15
- public meta: undefined;
16
- public ephemeral: undefined;
17
-
18
- constructor(
19
- public pubSubTopic: string,
20
- private proto: ProtoTopicOnlyMessage
21
- ) {}
22
-
23
- get contentTopic(): string {
24
- return this.proto.contentTopic;
25
- }
26
- }
27
-
28
- export class TopicOnlyDecoder implements IDecoder<TopicOnlyMessage> {
29
- public contentTopic = "";
30
-
31
- fromWireToProtoObj(bytes: Uint8Array): Promise<IProtoMessage | undefined> {
32
- const protoMessage = ProtoTopicOnlyMessage.decode(bytes);
33
- log("Message decoded", protoMessage);
34
- return Promise.resolve({
35
- contentTopic: protoMessage.contentTopic,
36
- payload: new Uint8Array(),
37
- rateLimitProof: undefined,
38
- timestamp: undefined,
39
- meta: undefined,
40
- version: undefined,
41
- ephemeral: undefined,
42
- });
43
- }
44
-
45
- async fromProtoObj(
46
- pubSubTopic: string,
47
- proto: IProtoMessage
48
- ): Promise<TopicOnlyMessage | undefined> {
49
- return new TopicOnlyMessage(pubSubTopic, proto);
50
- }
51
- }
@@ -1,74 +0,0 @@
1
- export const second = 1000;
2
- export const minute = 60 * second;
3
-
4
- /**
5
- * RelayCodec is the libp2p identifier for the waku relay protocol
6
- */
7
- export const RelayCodecs = ["/vac/waku/relay/2.0.0"];
8
-
9
- export const RelayPingContentTopic = "/relay-ping/1/ping/null";
10
-
11
- /**
12
- * RelayGossipFactor affects how many peers we will emit gossip to at each heartbeat.
13
- * We will send gossip to RelayGossipFactor * (total number of non-mesh peers), or
14
- * RelayDlazy, whichever is greater.
15
- */
16
- export const RelayGossipFactor = 0.25;
17
-
18
- /**
19
- * GossipsubHeartbeatInitialDelay is the short delay before the heartbeat timer begins
20
- * after the router is initialized.
21
- */
22
- export const RelayHeartbeatInitialDelay = 100;
23
-
24
- /**
25
- * RelayHeartbeatInterval controls the time between heartbeats.
26
- */
27
- export const RelayHeartbeatInterval = second;
28
-
29
- /**
30
- * RelayPrunePeers controls the number of peers to include in prune Peer eXchange.
31
- * When we prune a peer that's eligible for PX (has a good score, etc), we will try to
32
- * send them signed peer records for up to RelayPrunePeers other peers that we
33
- * know of.
34
- */
35
- export const RelayPrunePeers = 16;
36
-
37
- /**
38
- * RelayPruneBackoff controls the backoff time for pruned peers. This is how long
39
- * a peer must wait before attempting to graft into our mesh again after being pruned.
40
- * When pruning a peer, we send them our value of RelayPruneBackoff so they know
41
- * the minimum time to wait. Peers running older versions may not send a backoff time,
42
- * so if we receive a prune message without one, we will wait at least RelayPruneBackoff
43
- * before attempting to re-graft.
44
- */
45
- export const RelayPruneBackoff = minute;
46
-
47
- /**
48
- * RelayFanoutTTL controls how long we keep track of the fanout state. If it's been
49
- * RelayFanoutTTL since we've published to a topic that we're not subscribed to,
50
- * we'll delete the fanout map for that topic.
51
- */
52
- export const RelayFanoutTTL = minute;
53
-
54
- /**
55
- * RelayOpportunisticGraftTicks is the number of heartbeat ticks for attempting to improve the mesh
56
- * with opportunistic grafting. Every RelayOpportunisticGraftTicks we will attempt to select some
57
- * high-scoring mesh peers to replace lower-scoring ones, if the median score of our mesh peers falls
58
- * below a threshold
59
- */
60
- export const RelayOpportunisticGraftTicks = 60;
61
-
62
- /**
63
- * RelayOpportunisticGraftPeers is the number of peers to opportunistically graft.
64
- */
65
- export const RelayOpportunisticGraftPeers = 2;
66
-
67
- /**
68
- * RelayMaxIHaveLength is the maximum number of messages to include in an IHAVE message.
69
- * Also controls the maximum number of IHAVE ids we will accept and request with IWANT from a
70
- * peer within a heartbeat, to protect from IHAVE floods. You should adjust this value from the
71
- * default if your system is pushing more than 5000 messages in GossipsubHistoryGossip heartbeats;
72
- * with the defaults this is 1666 messages/s.
73
- */
74
- export const RelayMaxIHaveLength = 5000;
@@ -1,294 +0,0 @@
1
- import {
2
- GossipSub,
3
- GossipSubComponents,
4
- GossipsubMessage,
5
- GossipsubOpts,
6
- } from "@chainsafe/libp2p-gossipsub";
7
- import type { PeerIdStr, TopicStr } from "@chainsafe/libp2p-gossipsub/types";
8
- import { SignaturePolicy } from "@chainsafe/libp2p-gossipsub/types";
9
- import type { Libp2p } from "@libp2p/interface-libp2p";
10
- import type { PubSub } from "@libp2p/interface-pubsub";
11
- import { sha256 } from "@noble/hashes/sha256";
12
- import type {
13
- ActiveSubscriptions,
14
- Callback,
15
- IAsyncIterator,
16
- IDecodedMessage,
17
- IDecoder,
18
- IEncoder,
19
- IMessage,
20
- IRelay,
21
- ProtocolCreateOptions,
22
- ProtocolOptions,
23
- SendResult,
24
- } from "@waku/interfaces";
25
- import { toAsyncIterator } from "@waku/utils";
26
- import debug from "debug";
27
-
28
- import { DefaultPubSubTopic } from "../constants.js";
29
- import { groupByContentTopic } from "../group_by.js";
30
- import { TopicOnlyDecoder } from "../message/topic_only_message.js";
31
-
32
- import * as constants from "./constants.js";
33
- import { messageValidator } from "./message_validator.js";
34
-
35
- const log = debug("waku:relay");
36
-
37
- export type Observer<T extends IDecodedMessage> = {
38
- decoder: IDecoder<T>;
39
- callback: Callback<T>;
40
- };
41
-
42
- export type RelayCreateOptions = ProtocolCreateOptions & GossipsubOpts;
43
- export type ContentTopic = string;
44
-
45
- /**
46
- * Implements the [Waku v2 Relay protocol](https://rfc.vac.dev/spec/11/).
47
- * Throws if libp2p.pubsub does not support Waku Relay
48
- */
49
- class Relay implements IRelay {
50
- private readonly pubSubTopic: string;
51
- private defaultDecoder: IDecoder<IDecodedMessage>;
52
-
53
- public static multicodec: string = constants.RelayCodecs[0];
54
- public readonly gossipSub: GossipSub;
55
-
56
- /**
57
- * observers called when receiving new message.
58
- * Observers under key `""` are always called.
59
- */
60
- private observers: Map<ContentTopic, Set<unknown>>;
61
-
62
- constructor(libp2p: Libp2p, options?: Partial<RelayCreateOptions>) {
63
- if (!this.isRelayPubSub(libp2p.pubsub)) {
64
- throw Error(
65
- `Failed to initialize Relay. libp2p.pubsub does not support ${Relay.multicodec}`
66
- );
67
- }
68
-
69
- this.gossipSub = libp2p.pubsub as GossipSub;
70
- this.pubSubTopic = options?.pubSubTopic ?? DefaultPubSubTopic;
71
-
72
- if (this.gossipSub.isStarted()) {
73
- this.gossipSubSubscribe(this.pubSubTopic);
74
- }
75
-
76
- this.observers = new Map();
77
-
78
- // TODO: User might want to decide what decoder should be used (e.g. for RLN)
79
- this.defaultDecoder = new TopicOnlyDecoder();
80
- }
81
-
82
- /**
83
- * Mounts the gossipsub protocol onto the libp2p node
84
- * and subscribes to the default topic.
85
- *
86
- * @override
87
- * @returns {void}
88
- */
89
- public async start(): Promise<void> {
90
- if (this.gossipSub.isStarted()) {
91
- throw Error("GossipSub already started.");
92
- }
93
-
94
- await this.gossipSub.start();
95
- this.gossipSubSubscribe(this.pubSubTopic);
96
- }
97
-
98
- /**
99
- * Send Waku message.
100
- */
101
- public async send(encoder: IEncoder, message: IMessage): Promise<SendResult> {
102
- const msg = await encoder.toWire(message);
103
- if (!msg) {
104
- log("Failed to encode message, aborting publish");
105
- return { recipients: [] };
106
- }
107
-
108
- return this.gossipSub.publish(this.pubSubTopic, msg);
109
- }
110
-
111
- /**
112
- * Add an observer and associated Decoder to process incoming messages on a given content topic.
113
- *
114
- * @returns Function to delete the observer
115
- */
116
- public subscribe<T extends IDecodedMessage>(
117
- decoders: IDecoder<T> | IDecoder<T>[],
118
- callback: Callback<T>
119
- ): () => void {
120
- const contentTopicToObservers = Array.isArray(decoders)
121
- ? toObservers(decoders, callback)
122
- : toObservers([decoders], callback);
123
-
124
- for (const contentTopic of contentTopicToObservers.keys()) {
125
- const currObservers = this.observers.get(contentTopic) || new Set();
126
- const newObservers =
127
- contentTopicToObservers.get(contentTopic) || new Set();
128
-
129
- this.observers.set(contentTopic, union(currObservers, newObservers));
130
- }
131
-
132
- return () => {
133
- for (const contentTopic of contentTopicToObservers.keys()) {
134
- const currentObservers = this.observers.get(contentTopic) || new Set();
135
- const observersToRemove =
136
- contentTopicToObservers.get(contentTopic) || new Set();
137
-
138
- const nextObservers = leftMinusJoin(
139
- currentObservers,
140
- observersToRemove
141
- );
142
-
143
- if (nextObservers.size) {
144
- this.observers.set(contentTopic, nextObservers);
145
- } else {
146
- this.observers.delete(contentTopic);
147
- }
148
- }
149
- };
150
- }
151
-
152
- public toSubscriptionIterator<T extends IDecodedMessage>(
153
- decoders: IDecoder<T> | IDecoder<T>[],
154
- opts?: ProtocolOptions | undefined
155
- ): Promise<IAsyncIterator<T>> {
156
- return toAsyncIterator(this, decoders, opts);
157
- }
158
-
159
- public getActiveSubscriptions(): ActiveSubscriptions {
160
- const map = new Map();
161
- map.set(this.pubSubTopic, this.observers.keys());
162
- return map;
163
- }
164
-
165
- public getMeshPeers(topic?: TopicStr): PeerIdStr[] {
166
- return this.gossipSub.getMeshPeers(topic ?? this.pubSubTopic);
167
- }
168
-
169
- private async processIncomingMessage<T extends IDecodedMessage>(
170
- pubSubTopic: string,
171
- bytes: Uint8Array
172
- ): Promise<void> {
173
- const topicOnlyMsg = await this.defaultDecoder.fromWireToProtoObj(bytes);
174
- if (!topicOnlyMsg || !topicOnlyMsg.contentTopic) {
175
- log("Message does not have a content topic, skipping");
176
- return;
177
- }
178
-
179
- const observers = this.observers.get(topicOnlyMsg.contentTopic) as Set<
180
- Observer<T>
181
- >;
182
- if (!observers) {
183
- return;
184
- }
185
- await Promise.all(
186
- Array.from(observers).map(async ({ decoder, callback }) => {
187
- const protoMsg = await decoder.fromWireToProtoObj(bytes);
188
- if (!protoMsg) {
189
- log("Internal error: message previously decoded failed on 2nd pass.");
190
- return;
191
- }
192
- const msg = await decoder.fromProtoObj(pubSubTopic, protoMsg);
193
- if (msg) {
194
- callback(msg);
195
- } else {
196
- log("Failed to decode messages on", topicOnlyMsg.contentTopic);
197
- }
198
- })
199
- );
200
- }
201
-
202
- /**
203
- * Subscribe to a pubsub topic and start emitting Waku messages to observers.
204
- *
205
- * @override
206
- */
207
- private gossipSubSubscribe(pubSubTopic: string): void {
208
- this.gossipSub.addEventListener(
209
- "gossipsub:message",
210
- async (event: CustomEvent<GossipsubMessage>) => {
211
- if (event.detail.msg.topic !== pubSubTopic) return;
212
- log(`Message received on ${pubSubTopic}`);
213
-
214
- this.processIncomingMessage(
215
- event.detail.msg.topic,
216
- event.detail.msg.data
217
- ).catch((e) => log("Failed to process incoming message", e));
218
- }
219
- );
220
-
221
- this.gossipSub.topicValidators.set(pubSubTopic, messageValidator);
222
- this.gossipSub.subscribe(pubSubTopic);
223
- }
224
-
225
- private isRelayPubSub(pubsub: PubSub): boolean {
226
- return pubsub?.multicodecs?.includes(Relay.multicodec) || false;
227
- }
228
- }
229
-
230
- export function wakuRelay(
231
- init: Partial<ProtocolCreateOptions> = {}
232
- ): (libp2p: Libp2p) => IRelay {
233
- return (libp2p: Libp2p) => new Relay(libp2p, init);
234
- }
235
-
236
- export function wakuGossipSub(
237
- init: Partial<RelayCreateOptions> = {}
238
- ): (components: GossipSubComponents) => GossipSub {
239
- return (components: GossipSubComponents) => {
240
- init = {
241
- ...init,
242
- msgIdFn: ({ data }) => sha256(data),
243
- // Ensure that no signature is included nor expected in the messages.
244
- globalSignaturePolicy: SignaturePolicy.StrictNoSign,
245
- fallbackToFloodsub: false,
246
- };
247
- const pubsub = new GossipSub(components, init);
248
- pubsub.multicodecs = constants.RelayCodecs;
249
- return pubsub;
250
- };
251
- }
252
-
253
- function toObservers<T extends IDecodedMessage>(
254
- decoders: IDecoder<T>[],
255
- callback: Callback<T>
256
- ): Map<ContentTopic, Set<Observer<T>>> {
257
- const contentTopicToDecoders = Array.from(
258
- groupByContentTopic(decoders).entries()
259
- );
260
-
261
- const contentTopicToObserversEntries = contentTopicToDecoders.map(
262
- ([contentTopic, decoders]) =>
263
- [
264
- contentTopic,
265
- new Set(
266
- decoders.map(
267
- (decoder) =>
268
- ({
269
- decoder,
270
- callback,
271
- } as Observer<T>)
272
- )
273
- ),
274
- ] as [ContentTopic, Set<Observer<T>>]
275
- );
276
-
277
- return new Map(contentTopicToObserversEntries);
278
- }
279
-
280
- function union(left: Set<unknown>, right: Set<unknown>): Set<unknown> {
281
- for (const val of right.values()) {
282
- left.add(val);
283
- }
284
- return left;
285
- }
286
-
287
- function leftMinusJoin(left: Set<unknown>, right: Set<unknown>): Set<unknown> {
288
- for (const val of right.values()) {
289
- if (left.has(val)) {
290
- left.delete(val);
291
- }
292
- }
293
- return left;
294
- }
@@ -1,35 +0,0 @@
1
- import type { PeerId } from "@libp2p/interface-peer-id";
2
- import type { Message } from "@libp2p/interface-pubsub";
3
- import { TopicValidatorResult } from "@libp2p/interface-pubsub";
4
- import { proto_message as proto } from "@waku/proto";
5
- import debug from "debug";
6
-
7
- const log = debug("waku:relay");
8
-
9
- export function messageValidator(
10
- peer: PeerId,
11
- message: Message
12
- ): TopicValidatorResult {
13
- const startTime = performance.now();
14
- log(`validating message from ${peer} received on ${message.topic}`);
15
- let result = TopicValidatorResult.Accept;
16
-
17
- try {
18
- const protoMessage = proto.WakuMessage.decode(message.data);
19
-
20
- if (
21
- !protoMessage.contentTopic ||
22
- !protoMessage.contentTopic.length ||
23
- !protoMessage.payload ||
24
- !protoMessage.payload.length
25
- ) {
26
- result = TopicValidatorResult.Reject;
27
- }
28
- } catch (e) {
29
- result = TopicValidatorResult.Reject;
30
- }
31
-
32
- const endTime = performance.now();
33
- log(`Validation time (must be <100ms): ${endTime - startTime}ms`);
34
- return result;
35
- }