@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,149 +0,0 @@
1
- import { W as WakuMessage, m as message } from './peer_exchange-1229c8b0.js';
2
- import { d as debug } from './browser-2f1afe46.js';
3
-
4
- const log = debug("waku:message:version-0");
5
- const OneMillion = BigInt(1000000);
6
- const Version = 0;
7
- class DecodedMessage {
8
- constructor(pubSubTopic, proto) {
9
- this.pubSubTopic = pubSubTopic;
10
- this.proto = proto;
11
- }
12
- get ephemeral() {
13
- return Boolean(this.proto.ephemeral);
14
- }
15
- get payload() {
16
- return this.proto.payload;
17
- }
18
- get contentTopic() {
19
- return this.proto.contentTopic;
20
- }
21
- get _rawTimestamp() {
22
- return this.proto.timestamp;
23
- }
24
- get timestamp() {
25
- // In the case we receive a value that is bigger than JS's max number,
26
- // we catch the error and return undefined.
27
- try {
28
- if (this.proto.timestamp) {
29
- // nanoseconds 10^-9 to milliseconds 10^-3
30
- const timestamp = this.proto.timestamp / OneMillion;
31
- return new Date(Number(timestamp));
32
- }
33
- return;
34
- }
35
- catch (e) {
36
- return;
37
- }
38
- }
39
- get meta() {
40
- return this.proto.meta;
41
- }
42
- get version() {
43
- // https://rfc.vac.dev/spec/14/
44
- // > If omitted, the value SHOULD be interpreted as version 0.
45
- return this.proto.version ?? 0;
46
- }
47
- get rateLimitProof() {
48
- return this.proto.rateLimitProof;
49
- }
50
- }
51
- class Encoder {
52
- constructor(contentTopic, ephemeral = false, metaSetter) {
53
- this.contentTopic = contentTopic;
54
- this.ephemeral = ephemeral;
55
- this.metaSetter = metaSetter;
56
- if (!contentTopic || contentTopic === "") {
57
- throw new Error("Content topic must be specified");
58
- }
59
- }
60
- async toWire(message$1) {
61
- return WakuMessage.encode(await this.toProtoObj(message$1));
62
- }
63
- async toProtoObj(message) {
64
- const timestamp = message.timestamp ?? new Date();
65
- const protoMessage = {
66
- payload: message.payload,
67
- version: Version,
68
- contentTopic: this.contentTopic,
69
- timestamp: BigInt(timestamp.valueOf()) * OneMillion,
70
- meta: undefined,
71
- rateLimitProof: message.rateLimitProof,
72
- ephemeral: this.ephemeral,
73
- };
74
- if (this.metaSetter) {
75
- const meta = this.metaSetter(protoMessage);
76
- return { ...protoMessage, meta };
77
- }
78
- return protoMessage;
79
- }
80
- }
81
- /**
82
- * Creates an encoder that encode messages without Waku level encryption or signature.
83
- *
84
- * An encoder is used to encode messages in the [`14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/)
85
- * format to be sent over the Waku network. The resulting encoder can then be
86
- * pass to { @link @waku/interfaces.LightPush.push } or
87
- * { @link @waku/interfaces.Relay.send } to automatically encode outgoing
88
- * messages.
89
- */
90
- function createEncoder({ contentTopic, ephemeral, metaSetter, }) {
91
- return new Encoder(contentTopic, ephemeral, metaSetter);
92
- }
93
- class Decoder {
94
- constructor(contentTopic) {
95
- this.contentTopic = contentTopic;
96
- if (!contentTopic || contentTopic === "") {
97
- throw new Error("Content topic must be specified");
98
- }
99
- }
100
- fromWireToProtoObj(bytes) {
101
- const protoMessage = WakuMessage.decode(bytes);
102
- log("Message decoded", protoMessage);
103
- return Promise.resolve({
104
- payload: protoMessage.payload,
105
- contentTopic: protoMessage.contentTopic,
106
- version: protoMessage.version ?? undefined,
107
- timestamp: protoMessage.timestamp ?? undefined,
108
- meta: protoMessage.meta ?? undefined,
109
- rateLimitProof: protoMessage.rateLimitProof ?? undefined,
110
- ephemeral: protoMessage.ephemeral ?? false,
111
- });
112
- }
113
- async fromProtoObj(pubSubTopic, proto) {
114
- // https://rfc.vac.dev/spec/14/
115
- // > If omitted, the value SHOULD be interpreted as version 0.
116
- if (proto.version ?? 0 !== Version) {
117
- log("Failed to decode due to incorrect version, expected:", Version, ", actual:", proto.version);
118
- return Promise.resolve(undefined);
119
- }
120
- return new DecodedMessage(pubSubTopic, proto);
121
- }
122
- }
123
- /**
124
- * Creates a decoder that decode messages without Waku level encryption.
125
- *
126
- * A decoder is used to decode messages from the [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/)
127
- * format when received from the Waku network. The resulting decoder can then be
128
- * pass to { @link @waku/interfaces.Filter.subscribe } or
129
- * { @link @waku/interfaces.Relay.subscribe } to automatically decode incoming
130
- * messages.
131
- *
132
- * @param contentTopic The resulting decoder will only decode messages with this content topic.
133
- */
134
- function createDecoder(contentTopic) {
135
- return new Decoder(contentTopic);
136
- }
137
-
138
- var version_0 = /*#__PURE__*/Object.freeze({
139
- __proto__: null,
140
- DecodedMessage: DecodedMessage,
141
- Decoder: Decoder,
142
- Encoder: Encoder,
143
- Version: Version,
144
- createDecoder: createDecoder,
145
- createEncoder: createEncoder,
146
- proto: message
147
- });
148
-
149
- export { DecodedMessage as D, Encoder as E, Version as V, createDecoder as a, Decoder as b, createEncoder as c, version_0 as v };
@@ -1,3 +0,0 @@
1
- export declare function groupByContentTopic<T extends {
2
- contentTopic: string;
3
- }>(values: readonly T[]): Map<string, Array<T>>;
@@ -1,13 +0,0 @@
1
- export function groupByContentTopic(values) {
2
- const groupedDecoders = new Map();
3
- values.forEach((value) => {
4
- let decs = groupedDecoders.get(value.contentTopic);
5
- if (!decs) {
6
- groupedDecoders.set(value.contentTopic, []);
7
- decs = groupedDecoders.get(value.contentTopic);
8
- }
9
- decs.push(value);
10
- });
11
- return groupedDecoders;
12
- }
13
- //# sourceMappingURL=group_by.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"group_by.js","sourceRoot":"","sources":["../../src/lib/group_by.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,mBAAmB,CACjC,MAAoB;IAEpB,MAAM,eAAe,GAAG,IAAI,GAAG,EAAE,CAAC;IAClC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACvB,IAAI,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,EAAE;YACT,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC5C,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;SAChD;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -1,18 +0,0 @@
1
- import type { IDecodedMessage, IDecoder, IProtoMessage } from "@waku/interfaces";
2
- import { TopicOnlyMessage as ProtoTopicOnlyMessage } from "@waku/proto";
3
- export declare class TopicOnlyMessage implements IDecodedMessage {
4
- pubSubTopic: string;
5
- private proto;
6
- payload: Uint8Array;
7
- rateLimitProof: undefined;
8
- timestamp: undefined;
9
- meta: undefined;
10
- ephemeral: undefined;
11
- constructor(pubSubTopic: string, proto: ProtoTopicOnlyMessage);
12
- get contentTopic(): string;
13
- }
14
- export declare class TopicOnlyDecoder implements IDecoder<TopicOnlyMessage> {
15
- contentTopic: string;
16
- fromWireToProtoObj(bytes: Uint8Array): Promise<IProtoMessage | undefined>;
17
- fromProtoObj(pubSubTopic: string, proto: IProtoMessage): Promise<TopicOnlyMessage | undefined>;
18
- }
@@ -1,35 +0,0 @@
1
- import { TopicOnlyMessage as ProtoTopicOnlyMessage } from "@waku/proto";
2
- import debug from "debug";
3
- const log = debug("waku:message:topic-only");
4
- export class TopicOnlyMessage {
5
- constructor(pubSubTopic, proto) {
6
- this.pubSubTopic = pubSubTopic;
7
- this.proto = proto;
8
- this.payload = new Uint8Array();
9
- }
10
- get contentTopic() {
11
- return this.proto.contentTopic;
12
- }
13
- }
14
- export class TopicOnlyDecoder {
15
- constructor() {
16
- this.contentTopic = "";
17
- }
18
- fromWireToProtoObj(bytes) {
19
- const protoMessage = ProtoTopicOnlyMessage.decode(bytes);
20
- log("Message decoded", protoMessage);
21
- return Promise.resolve({
22
- contentTopic: protoMessage.contentTopic,
23
- payload: new Uint8Array(),
24
- rateLimitProof: undefined,
25
- timestamp: undefined,
26
- meta: undefined,
27
- version: undefined,
28
- ephemeral: undefined,
29
- });
30
- }
31
- async fromProtoObj(pubSubTopic, proto) {
32
- return new TopicOnlyMessage(pubSubTopic, proto);
33
- }
34
- }
35
- //# sourceMappingURL=topic_only_message.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"topic_only_message.js","sourceRoot":"","sources":["../../../src/lib/message/topic_only_message.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,IAAI,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,GAAG,GAAG,KAAK,CAAC,yBAAyB,CAAC,CAAC;AAE7C,MAAM,OAAO,gBAAgB;IAO3B,YACS,WAAmB,EAClB,KAA4B;QAD7B,gBAAW,GAAX,WAAW,CAAQ;QAClB,UAAK,GAAL,KAAK,CAAuB;QAR/B,YAAO,GAAe,IAAI,UAAU,EAAE,CAAC;IAS3C,CAAC;IAEJ,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,gBAAgB;IAA7B;QACS,iBAAY,GAAG,EAAE,CAAC;IAsB3B,CAAC;IApBC,kBAAkB,CAAC,KAAiB;QAClC,MAAM,YAAY,GAAG,qBAAqB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,GAAG,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;QACrC,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,YAAY,EAAE,YAAY,CAAC,YAAY;YACvC,OAAO,EAAE,IAAI,UAAU,EAAE;YACzB,cAAc,EAAE,SAAS;YACzB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,SAAS;YAClB,SAAS,EAAE,SAAS;SACrB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,WAAmB,EACnB,KAAoB;QAEpB,OAAO,IAAI,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;CACF"}
@@ -1,63 +0,0 @@
1
- export declare const second = 1000;
2
- export declare const minute: number;
3
- /**
4
- * RelayCodec is the libp2p identifier for the waku relay protocol
5
- */
6
- export declare const RelayCodecs: string[];
7
- export declare const RelayPingContentTopic = "/relay-ping/1/ping/null";
8
- /**
9
- * RelayGossipFactor affects how many peers we will emit gossip to at each heartbeat.
10
- * We will send gossip to RelayGossipFactor * (total number of non-mesh peers), or
11
- * RelayDlazy, whichever is greater.
12
- */
13
- export declare const RelayGossipFactor = 0.25;
14
- /**
15
- * GossipsubHeartbeatInitialDelay is the short delay before the heartbeat timer begins
16
- * after the router is initialized.
17
- */
18
- export declare const RelayHeartbeatInitialDelay = 100;
19
- /**
20
- * RelayHeartbeatInterval controls the time between heartbeats.
21
- */
22
- export declare const RelayHeartbeatInterval = 1000;
23
- /**
24
- * RelayPrunePeers controls the number of peers to include in prune Peer eXchange.
25
- * When we prune a peer that's eligible for PX (has a good score, etc), we will try to
26
- * send them signed peer records for up to RelayPrunePeers other peers that we
27
- * know of.
28
- */
29
- export declare const RelayPrunePeers = 16;
30
- /**
31
- * RelayPruneBackoff controls the backoff time for pruned peers. This is how long
32
- * a peer must wait before attempting to graft into our mesh again after being pruned.
33
- * When pruning a peer, we send them our value of RelayPruneBackoff so they know
34
- * the minimum time to wait. Peers running older versions may not send a backoff time,
35
- * so if we receive a prune message without one, we will wait at least RelayPruneBackoff
36
- * before attempting to re-graft.
37
- */
38
- export declare const RelayPruneBackoff: number;
39
- /**
40
- * RelayFanoutTTL controls how long we keep track of the fanout state. If it's been
41
- * RelayFanoutTTL since we've published to a topic that we're not subscribed to,
42
- * we'll delete the fanout map for that topic.
43
- */
44
- export declare const RelayFanoutTTL: number;
45
- /**
46
- * RelayOpportunisticGraftTicks is the number of heartbeat ticks for attempting to improve the mesh
47
- * with opportunistic grafting. Every RelayOpportunisticGraftTicks we will attempt to select some
48
- * high-scoring mesh peers to replace lower-scoring ones, if the median score of our mesh peers falls
49
- * below a threshold
50
- */
51
- export declare const RelayOpportunisticGraftTicks = 60;
52
- /**
53
- * RelayOpportunisticGraftPeers is the number of peers to opportunistically graft.
54
- */
55
- export declare const RelayOpportunisticGraftPeers = 2;
56
- /**
57
- * RelayMaxIHaveLength is the maximum number of messages to include in an IHAVE message.
58
- * Also controls the maximum number of IHAVE ids we will accept and request with IWANT from a
59
- * peer within a heartbeat, to protect from IHAVE floods. You should adjust this value from the
60
- * default if your system is pushing more than 5000 messages in GossipsubHistoryGossip heartbeats;
61
- * with the defaults this is 1666 messages/s.
62
- */
63
- export declare const RelayMaxIHaveLength = 5000;
@@ -1,64 +0,0 @@
1
- export const second = 1000;
2
- export const minute = 60 * second;
3
- /**
4
- * RelayCodec is the libp2p identifier for the waku relay protocol
5
- */
6
- export const RelayCodecs = ["/vac/waku/relay/2.0.0"];
7
- export const RelayPingContentTopic = "/relay-ping/1/ping/null";
8
- /**
9
- * RelayGossipFactor affects how many peers we will emit gossip to at each heartbeat.
10
- * We will send gossip to RelayGossipFactor * (total number of non-mesh peers), or
11
- * RelayDlazy, whichever is greater.
12
- */
13
- export const RelayGossipFactor = 0.25;
14
- /**
15
- * GossipsubHeartbeatInitialDelay is the short delay before the heartbeat timer begins
16
- * after the router is initialized.
17
- */
18
- export const RelayHeartbeatInitialDelay = 100;
19
- /**
20
- * RelayHeartbeatInterval controls the time between heartbeats.
21
- */
22
- export const RelayHeartbeatInterval = second;
23
- /**
24
- * RelayPrunePeers controls the number of peers to include in prune Peer eXchange.
25
- * When we prune a peer that's eligible for PX (has a good score, etc), we will try to
26
- * send them signed peer records for up to RelayPrunePeers other peers that we
27
- * know of.
28
- */
29
- export const RelayPrunePeers = 16;
30
- /**
31
- * RelayPruneBackoff controls the backoff time for pruned peers. This is how long
32
- * a peer must wait before attempting to graft into our mesh again after being pruned.
33
- * When pruning a peer, we send them our value of RelayPruneBackoff so they know
34
- * the minimum time to wait. Peers running older versions may not send a backoff time,
35
- * so if we receive a prune message without one, we will wait at least RelayPruneBackoff
36
- * before attempting to re-graft.
37
- */
38
- export const RelayPruneBackoff = minute;
39
- /**
40
- * RelayFanoutTTL controls how long we keep track of the fanout state. If it's been
41
- * RelayFanoutTTL since we've published to a topic that we're not subscribed to,
42
- * we'll delete the fanout map for that topic.
43
- */
44
- export const RelayFanoutTTL = minute;
45
- /**
46
- * RelayOpportunisticGraftTicks is the number of heartbeat ticks for attempting to improve the mesh
47
- * with opportunistic grafting. Every RelayOpportunisticGraftTicks we will attempt to select some
48
- * high-scoring mesh peers to replace lower-scoring ones, if the median score of our mesh peers falls
49
- * below a threshold
50
- */
51
- export const RelayOpportunisticGraftTicks = 60;
52
- /**
53
- * RelayOpportunisticGraftPeers is the number of peers to opportunistically graft.
54
- */
55
- export const RelayOpportunisticGraftPeers = 2;
56
- /**
57
- * RelayMaxIHaveLength is the maximum number of messages to include in an IHAVE message.
58
- * Also controls the maximum number of IHAVE ids we will accept and request with IWANT from a
59
- * peer within a heartbeat, to protect from IHAVE floods. You should adjust this value from the
60
- * default if your system is pushing more than 5000 messages in GossipsubHistoryGossip heartbeats;
61
- * with the defaults this is 1666 messages/s.
62
- */
63
- export const RelayMaxIHaveLength = 5000;
64
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/relay/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;AAC3B,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAErD,MAAM,CAAC,MAAM,qBAAqB,GAAG,yBAAyB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AAErC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC"}
@@ -1,11 +0,0 @@
1
- import { GossipSub, GossipSubComponents, GossipsubOpts } from "@chainsafe/libp2p-gossipsub";
2
- import type { Libp2p } from "@libp2p/interface-libp2p";
3
- import type { Callback, IDecodedMessage, IDecoder, IRelay, ProtocolCreateOptions } from "@waku/interfaces";
4
- export type Observer<T extends IDecodedMessage> = {
5
- decoder: IDecoder<T>;
6
- callback: Callback<T>;
7
- };
8
- export type RelayCreateOptions = ProtocolCreateOptions & GossipsubOpts;
9
- export type ContentTopic = string;
10
- export declare function wakuRelay(init?: Partial<ProtocolCreateOptions>): (libp2p: Libp2p) => IRelay;
11
- export declare function wakuGossipSub(init?: Partial<RelayCreateOptions>): (components: GossipSubComponents) => GossipSub;
@@ -1,181 +0,0 @@
1
- import { GossipSub, } from "@chainsafe/libp2p-gossipsub";
2
- import { SignaturePolicy } from "@chainsafe/libp2p-gossipsub/types";
3
- import { sha256 } from "@noble/hashes/sha256";
4
- import { toAsyncIterator } from "@waku/utils";
5
- import debug from "debug";
6
- import { DefaultPubSubTopic } from "../constants.js";
7
- import { groupByContentTopic } from "../group_by.js";
8
- import { TopicOnlyDecoder } from "../message/topic_only_message.js";
9
- import * as constants from "./constants.js";
10
- import { messageValidator } from "./message_validator.js";
11
- const log = debug("waku:relay");
12
- /**
13
- * Implements the [Waku v2 Relay protocol](https://rfc.vac.dev/spec/11/).
14
- * Throws if libp2p.pubsub does not support Waku Relay
15
- */
16
- class Relay {
17
- constructor(libp2p, options) {
18
- if (!this.isRelayPubSub(libp2p.pubsub)) {
19
- throw Error(`Failed to initialize Relay. libp2p.pubsub does not support ${Relay.multicodec}`);
20
- }
21
- this.gossipSub = libp2p.pubsub;
22
- this.pubSubTopic = options?.pubSubTopic ?? DefaultPubSubTopic;
23
- if (this.gossipSub.isStarted()) {
24
- this.gossipSubSubscribe(this.pubSubTopic);
25
- }
26
- this.observers = new Map();
27
- // TODO: User might want to decide what decoder should be used (e.g. for RLN)
28
- this.defaultDecoder = new TopicOnlyDecoder();
29
- }
30
- /**
31
- * Mounts the gossipsub protocol onto the libp2p node
32
- * and subscribes to the default topic.
33
- *
34
- * @override
35
- * @returns {void}
36
- */
37
- async start() {
38
- if (this.gossipSub.isStarted()) {
39
- throw Error("GossipSub already started.");
40
- }
41
- await this.gossipSub.start();
42
- this.gossipSubSubscribe(this.pubSubTopic);
43
- }
44
- /**
45
- * Send Waku message.
46
- */
47
- async send(encoder, message) {
48
- const msg = await encoder.toWire(message);
49
- if (!msg) {
50
- log("Failed to encode message, aborting publish");
51
- return { recipients: [] };
52
- }
53
- return this.gossipSub.publish(this.pubSubTopic, msg);
54
- }
55
- /**
56
- * Add an observer and associated Decoder to process incoming messages on a given content topic.
57
- *
58
- * @returns Function to delete the observer
59
- */
60
- subscribe(decoders, callback) {
61
- const contentTopicToObservers = Array.isArray(decoders)
62
- ? toObservers(decoders, callback)
63
- : toObservers([decoders], callback);
64
- for (const contentTopic of contentTopicToObservers.keys()) {
65
- const currObservers = this.observers.get(contentTopic) || new Set();
66
- const newObservers = contentTopicToObservers.get(contentTopic) || new Set();
67
- this.observers.set(contentTopic, union(currObservers, newObservers));
68
- }
69
- return () => {
70
- for (const contentTopic of contentTopicToObservers.keys()) {
71
- const currentObservers = this.observers.get(contentTopic) || new Set();
72
- const observersToRemove = contentTopicToObservers.get(contentTopic) || new Set();
73
- const nextObservers = leftMinusJoin(currentObservers, observersToRemove);
74
- if (nextObservers.size) {
75
- this.observers.set(contentTopic, nextObservers);
76
- }
77
- else {
78
- this.observers.delete(contentTopic);
79
- }
80
- }
81
- };
82
- }
83
- toSubscriptionIterator(decoders, opts) {
84
- return toAsyncIterator(this, decoders, opts);
85
- }
86
- getActiveSubscriptions() {
87
- const map = new Map();
88
- map.set(this.pubSubTopic, this.observers.keys());
89
- return map;
90
- }
91
- getMeshPeers(topic) {
92
- return this.gossipSub.getMeshPeers(topic ?? this.pubSubTopic);
93
- }
94
- async processIncomingMessage(pubSubTopic, bytes) {
95
- const topicOnlyMsg = await this.defaultDecoder.fromWireToProtoObj(bytes);
96
- if (!topicOnlyMsg || !topicOnlyMsg.contentTopic) {
97
- log("Message does not have a content topic, skipping");
98
- return;
99
- }
100
- const observers = this.observers.get(topicOnlyMsg.contentTopic);
101
- if (!observers) {
102
- return;
103
- }
104
- await Promise.all(Array.from(observers).map(async ({ decoder, callback }) => {
105
- const protoMsg = await decoder.fromWireToProtoObj(bytes);
106
- if (!protoMsg) {
107
- log("Internal error: message previously decoded failed on 2nd pass.");
108
- return;
109
- }
110
- const msg = await decoder.fromProtoObj(pubSubTopic, protoMsg);
111
- if (msg) {
112
- callback(msg);
113
- }
114
- else {
115
- log("Failed to decode messages on", topicOnlyMsg.contentTopic);
116
- }
117
- }));
118
- }
119
- /**
120
- * Subscribe to a pubsub topic and start emitting Waku messages to observers.
121
- *
122
- * @override
123
- */
124
- gossipSubSubscribe(pubSubTopic) {
125
- this.gossipSub.addEventListener("gossipsub:message", async (event) => {
126
- if (event.detail.msg.topic !== pubSubTopic)
127
- return;
128
- log(`Message received on ${pubSubTopic}`);
129
- this.processIncomingMessage(event.detail.msg.topic, event.detail.msg.data).catch((e) => log("Failed to process incoming message", e));
130
- });
131
- this.gossipSub.topicValidators.set(pubSubTopic, messageValidator);
132
- this.gossipSub.subscribe(pubSubTopic);
133
- }
134
- isRelayPubSub(pubsub) {
135
- return pubsub?.multicodecs?.includes(Relay.multicodec) || false;
136
- }
137
- }
138
- Relay.multicodec = constants.RelayCodecs[0];
139
- export function wakuRelay(init = {}) {
140
- return (libp2p) => new Relay(libp2p, init);
141
- }
142
- export function wakuGossipSub(init = {}) {
143
- return (components) => {
144
- init = {
145
- ...init,
146
- msgIdFn: ({ data }) => sha256(data),
147
- // Ensure that no signature is included nor expected in the messages.
148
- globalSignaturePolicy: SignaturePolicy.StrictNoSign,
149
- fallbackToFloodsub: false,
150
- };
151
- const pubsub = new GossipSub(components, init);
152
- pubsub.multicodecs = constants.RelayCodecs;
153
- return pubsub;
154
- };
155
- }
156
- function toObservers(decoders, callback) {
157
- const contentTopicToDecoders = Array.from(groupByContentTopic(decoders).entries());
158
- const contentTopicToObserversEntries = contentTopicToDecoders.map(([contentTopic, decoders]) => [
159
- contentTopic,
160
- new Set(decoders.map((decoder) => ({
161
- decoder,
162
- callback,
163
- }))),
164
- ]);
165
- return new Map(contentTopicToObserversEntries);
166
- }
167
- function union(left, right) {
168
- for (const val of right.values()) {
169
- left.add(val);
170
- }
171
- return left;
172
- }
173
- function leftMinusJoin(left, right) {
174
- for (const val of right.values()) {
175
- if (left.has(val)) {
176
- left.delete(val);
177
- }
178
- }
179
- return left;
180
- }
181
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/relay/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +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
- export declare function messageValidator(peer: PeerId, message: Message): TopicValidatorResult;
@@ -1,25 +0,0 @@
1
- import { TopicValidatorResult } from "@libp2p/interface-pubsub";
2
- import { proto_message as proto } from "@waku/proto";
3
- import debug from "debug";
4
- const log = debug("waku:relay");
5
- export function messageValidator(peer, message) {
6
- const startTime = performance.now();
7
- log(`validating message from ${peer} received on ${message.topic}`);
8
- let result = TopicValidatorResult.Accept;
9
- try {
10
- const protoMessage = proto.WakuMessage.decode(message.data);
11
- if (!protoMessage.contentTopic ||
12
- !protoMessage.contentTopic.length ||
13
- !protoMessage.payload ||
14
- !protoMessage.payload.length) {
15
- result = TopicValidatorResult.Reject;
16
- }
17
- }
18
- catch (e) {
19
- result = TopicValidatorResult.Reject;
20
- }
21
- const endTime = performance.now();
22
- log(`Validation time (must be <100ms): ${endTime - startTime}ms`);
23
- return result;
24
- }
25
- //# sourceMappingURL=message_validator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"message_validator.js","sourceRoot":"","sources":["../../../src/lib/relay/message_validator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,aAAa,IAAI,KAAK,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;AAEhC,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,OAAgB;IAEhB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IACpC,GAAG,CAAC,2BAA2B,IAAI,gBAAgB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACpE,IAAI,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC;IAEzC,IAAI;QACF,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE5D,IACE,CAAC,YAAY,CAAC,YAAY;YAC1B,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM;YACjC,CAAC,YAAY,CAAC,OAAO;YACrB,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAC5B;YACA,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC;SACtC;KACF;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC;KACtC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAClC,GAAG,CAAC,qCAAqC,OAAO,GAAG,SAAS,IAAI,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1,14 +0,0 @@
1
- export function groupByContentTopic<T extends { contentTopic: string }>(
2
- values: readonly T[]
3
- ): Map<string, Array<T>> {
4
- const groupedDecoders = new Map();
5
- values.forEach((value) => {
6
- let decs = groupedDecoders.get(value.contentTopic);
7
- if (!decs) {
8
- groupedDecoders.set(value.contentTopic, []);
9
- decs = groupedDecoders.get(value.contentTopic);
10
- }
11
- decs.push(value);
12
- });
13
- return groupedDecoders;
14
- }