@waku/core 0.0.16 → 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.
- package/CHANGELOG.md +48 -0
- package/bundle/{browser-2f1afe46.js → browser-bde977a3.js} +12 -9
- package/bundle/index.js +4417 -34898
- package/bundle/lib/base_protocol.js +4 -1
- package/bundle/lib/message/version_0.js +2 -3
- package/bundle/{peer_exchange-1229c8b0.js → version_0-c6b47311.js} +172 -45
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.js +3 -0
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/connection_manager.d.ts +1 -0
- package/dist/lib/connection_manager.js +33 -25
- package/dist/lib/connection_manager.js.map +1 -1
- package/dist/lib/filter/filter_rpc.js +1 -0
- package/dist/lib/filter/filter_rpc.js.map +1 -1
- package/dist/lib/filter/index.js +11 -4
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/keep_alive_manager.d.ts +1 -0
- package/dist/lib/keep_alive_manager.js +5 -1
- package/dist/lib/keep_alive_manager.js.map +1 -1
- package/dist/lib/light_push/index.d.ts +1 -1
- package/dist/lib/light_push/index.js +28 -8
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/light_push/push_rpc.js +1 -0
- package/dist/lib/light_push/push_rpc.js.map +1 -1
- package/dist/lib/message/index.d.ts +0 -1
- package/dist/lib/message/index.js +0 -1
- package/dist/lib/message/index.js.map +1 -1
- package/dist/lib/message/version_0.d.ts +1 -2
- package/dist/lib/message/version_0.js +12 -0
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/store/history_rpc.js +1 -0
- package/dist/lib/store/history_rpc.js.map +1 -1
- package/dist/lib/store/index.js +3 -1
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/waku.d.ts +2 -2
- package/dist/lib/waku.js +14 -2
- package/dist/lib/waku.js.map +1 -1
- package/package.json +14 -23
- package/src/index.ts +1 -9
- package/src/lib/connection_manager.ts +13 -4
- package/src/lib/filter/index.ts +14 -5
- package/src/lib/keep_alive_manager.ts +1 -2
- package/src/lib/light_push/index.ts +28 -11
- package/src/lib/message/index.ts +0 -1
- package/src/lib/message/version_0.ts +11 -3
- package/src/lib/store/index.ts +2 -2
- package/src/lib/waku.ts +13 -4
- package/bundle/lib/message/topic_only_message.js +0 -3
- package/bundle/topic_only_message-e8406994.js +0 -43
- package/bundle/version_0-e9a6cfb0.js +0 -143
- package/dist/lib/group_by.d.ts +0 -3
- package/dist/lib/group_by.js +0 -13
- package/dist/lib/group_by.js.map +0 -1
- package/dist/lib/message/topic_only_message.d.ts +0 -18
- package/dist/lib/message/topic_only_message.js +0 -35
- package/dist/lib/message/topic_only_message.js.map +0 -1
- package/dist/lib/relay/constants.d.ts +0 -63
- package/dist/lib/relay/constants.js +0 -64
- package/dist/lib/relay/constants.js.map +0 -1
- package/dist/lib/relay/index.d.ts +0 -11
- package/dist/lib/relay/index.js +0 -175
- package/dist/lib/relay/index.js.map +0 -1
- package/dist/lib/relay/message_validator.d.ts +0 -4
- package/dist/lib/relay/message_validator.js +0 -25
- package/dist/lib/relay/message_validator.js.map +0 -1
- package/src/lib/group_by.ts +0 -14
- package/src/lib/message/topic_only_message.ts +0 -51
- package/src/lib/relay/constants.ts +0 -74
- package/src/lib/relay/index.ts +0 -282
- package/src/lib/relay/message_validator.ts +0 -35
package/dist/lib/relay/index.js
DELETED
@@ -1,175 +0,0 @@
|
|
1
|
-
import { GossipSub, } from "@chainsafe/libp2p-gossipsub";
|
2
|
-
import { SignaturePolicy } from "@chainsafe/libp2p-gossipsub/types";
|
3
|
-
import debug from "debug";
|
4
|
-
import { DefaultPubSubTopic } from "../constants.js";
|
5
|
-
import { groupByContentTopic } from "../group_by.js";
|
6
|
-
import { TopicOnlyDecoder } from "../message/topic_only_message.js";
|
7
|
-
import * as constants from "./constants.js";
|
8
|
-
import { messageValidator } from "./message_validator.js";
|
9
|
-
const log = debug("waku:relay");
|
10
|
-
/**
|
11
|
-
* Implements the [Waku v2 Relay protocol](https://rfc.vac.dev/spec/11/).
|
12
|
-
* Throws if libp2p.pubsub does not support Waku Relay
|
13
|
-
*/
|
14
|
-
class Relay {
|
15
|
-
constructor(libp2p, options) {
|
16
|
-
if (!this.isRelayPubSub(libp2p.pubsub)) {
|
17
|
-
throw Error(`Failed to initialize Relay. libp2p.pubsub does not support ${Relay.multicodec}`);
|
18
|
-
}
|
19
|
-
this.gossipSub = libp2p.pubsub;
|
20
|
-
this.pubSubTopic = options?.pubSubTopic ?? DefaultPubSubTopic;
|
21
|
-
if (this.gossipSub.isStarted()) {
|
22
|
-
this.gossipSubSubscribe(this.pubSubTopic);
|
23
|
-
}
|
24
|
-
this.observers = new Map();
|
25
|
-
// TODO: User might want to decide what decoder should be used (e.g. for RLN)
|
26
|
-
this.defaultDecoder = new TopicOnlyDecoder();
|
27
|
-
}
|
28
|
-
/**
|
29
|
-
* Mounts the gossipsub protocol onto the libp2p node
|
30
|
-
* and subscribes to the default topic.
|
31
|
-
*
|
32
|
-
* @override
|
33
|
-
* @returns {void}
|
34
|
-
*/
|
35
|
-
async start() {
|
36
|
-
if (this.gossipSub.isStarted()) {
|
37
|
-
throw Error("GossipSub already started.");
|
38
|
-
}
|
39
|
-
await this.gossipSub.start();
|
40
|
-
this.gossipSubSubscribe(this.pubSubTopic);
|
41
|
-
}
|
42
|
-
/**
|
43
|
-
* Send Waku message.
|
44
|
-
*/
|
45
|
-
async send(encoder, message) {
|
46
|
-
const msg = await encoder.toWire(message);
|
47
|
-
if (!msg) {
|
48
|
-
log("Failed to encode message, aborting publish");
|
49
|
-
return { recipients: [] };
|
50
|
-
}
|
51
|
-
return this.gossipSub.publish(this.pubSubTopic, msg);
|
52
|
-
}
|
53
|
-
/**
|
54
|
-
* Add an observer and associated Decoder to process incoming messages on a given content topic.
|
55
|
-
*
|
56
|
-
* @returns Function to delete the observer
|
57
|
-
*/
|
58
|
-
subscribe(decoders, callback) {
|
59
|
-
const contentTopicToObservers = Array.isArray(decoders)
|
60
|
-
? toObservers(decoders, callback)
|
61
|
-
: toObservers([decoders], callback);
|
62
|
-
for (const contentTopic of contentTopicToObservers.keys()) {
|
63
|
-
const currObservers = this.observers.get(contentTopic) || new Set();
|
64
|
-
const newObservers = contentTopicToObservers.get(contentTopic) || new Set();
|
65
|
-
this.observers.set(contentTopic, union(currObservers, newObservers));
|
66
|
-
}
|
67
|
-
return () => {
|
68
|
-
for (const contentTopic of contentTopicToObservers.keys()) {
|
69
|
-
const currentObservers = this.observers.get(contentTopic) || new Set();
|
70
|
-
const observersToRemove = contentTopicToObservers.get(contentTopic) || new Set();
|
71
|
-
const nextObservers = leftMinusJoin(currentObservers, observersToRemove);
|
72
|
-
if (nextObservers.size) {
|
73
|
-
this.observers.set(contentTopic, nextObservers);
|
74
|
-
}
|
75
|
-
else {
|
76
|
-
this.observers.delete(contentTopic);
|
77
|
-
}
|
78
|
-
}
|
79
|
-
};
|
80
|
-
}
|
81
|
-
getActiveSubscriptions() {
|
82
|
-
const map = new Map();
|
83
|
-
map.set(this.pubSubTopic, this.observers.keys());
|
84
|
-
return map;
|
85
|
-
}
|
86
|
-
getMeshPeers(topic) {
|
87
|
-
return this.gossipSub.getMeshPeers(topic ?? this.pubSubTopic);
|
88
|
-
}
|
89
|
-
async processIncomingMessage(pubSubTopic, bytes) {
|
90
|
-
const topicOnlyMsg = await this.defaultDecoder.fromWireToProtoObj(bytes);
|
91
|
-
if (!topicOnlyMsg || !topicOnlyMsg.contentTopic) {
|
92
|
-
log("Message does not have a content topic, skipping");
|
93
|
-
return;
|
94
|
-
}
|
95
|
-
const observers = this.observers.get(topicOnlyMsg.contentTopic);
|
96
|
-
if (!observers) {
|
97
|
-
return;
|
98
|
-
}
|
99
|
-
await Promise.all(Array.from(observers).map(async ({ decoder, callback }) => {
|
100
|
-
const protoMsg = await decoder.fromWireToProtoObj(bytes);
|
101
|
-
if (!protoMsg) {
|
102
|
-
log("Internal error: message previously decoded failed on 2nd pass.");
|
103
|
-
return;
|
104
|
-
}
|
105
|
-
const msg = await decoder.fromProtoObj(pubSubTopic, protoMsg);
|
106
|
-
if (msg) {
|
107
|
-
callback(msg);
|
108
|
-
}
|
109
|
-
else {
|
110
|
-
log("Failed to decode messages on", topicOnlyMsg.contentTopic);
|
111
|
-
}
|
112
|
-
}));
|
113
|
-
}
|
114
|
-
/**
|
115
|
-
* Subscribe to a pubsub topic and start emitting Waku messages to observers.
|
116
|
-
*
|
117
|
-
* @override
|
118
|
-
*/
|
119
|
-
gossipSubSubscribe(pubSubTopic) {
|
120
|
-
this.gossipSub.addEventListener("gossipsub:message", async (event) => {
|
121
|
-
if (event.detail.msg.topic !== pubSubTopic)
|
122
|
-
return;
|
123
|
-
log(`Message received on ${pubSubTopic}`);
|
124
|
-
this.processIncomingMessage(event.detail.msg.topic, event.detail.msg.data).catch((e) => log("Failed to process incoming message", e));
|
125
|
-
});
|
126
|
-
this.gossipSub.topicValidators.set(pubSubTopic, messageValidator);
|
127
|
-
this.gossipSub.subscribe(pubSubTopic);
|
128
|
-
}
|
129
|
-
isRelayPubSub(pubsub) {
|
130
|
-
return pubsub?.multicodecs?.includes(Relay.multicodec) || false;
|
131
|
-
}
|
132
|
-
}
|
133
|
-
Relay.multicodec = constants.RelayCodecs[0];
|
134
|
-
export function wakuRelay(init = {}) {
|
135
|
-
return (libp2p) => new Relay(libp2p, init);
|
136
|
-
}
|
137
|
-
export function wakuGossipSub(init = {}) {
|
138
|
-
return (components) => {
|
139
|
-
init = {
|
140
|
-
...init,
|
141
|
-
// Ensure that no signature is included nor expected in the messages.
|
142
|
-
globalSignaturePolicy: SignaturePolicy.StrictNoSign,
|
143
|
-
fallbackToFloodsub: false,
|
144
|
-
};
|
145
|
-
const pubsub = new GossipSub(components, init);
|
146
|
-
pubsub.multicodecs = constants.RelayCodecs;
|
147
|
-
return pubsub;
|
148
|
-
};
|
149
|
-
}
|
150
|
-
function toObservers(decoders, callback) {
|
151
|
-
const contentTopicToDecoders = Array.from(groupByContentTopic(decoders).entries());
|
152
|
-
const contentTopicToObserversEntries = contentTopicToDecoders.map(([contentTopic, decoders]) => [
|
153
|
-
contentTopic,
|
154
|
-
new Set(decoders.map((decoder) => ({
|
155
|
-
decoder,
|
156
|
-
callback,
|
157
|
-
}))),
|
158
|
-
]);
|
159
|
-
return new Map(contentTopicToObserversEntries);
|
160
|
-
}
|
161
|
-
function union(left, right) {
|
162
|
-
for (const val of right.values()) {
|
163
|
-
left.add(val);
|
164
|
-
}
|
165
|
-
return left;
|
166
|
-
}
|
167
|
-
function leftMinusJoin(left, right) {
|
168
|
-
for (const val of right.values()) {
|
169
|
-
if (left.has(val)) {
|
170
|
-
left.delete(val);
|
171
|
-
}
|
172
|
-
}
|
173
|
-
return left;
|
174
|
-
}
|
175
|
-
//# 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"}
|
package/src/lib/group_by.ts
DELETED
@@ -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
|
-
}
|
@@ -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;
|
package/src/lib/relay/index.ts
DELETED
@@ -1,282 +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 type {
|
12
|
-
ActiveSubscriptions,
|
13
|
-
Callback,
|
14
|
-
IDecodedMessage,
|
15
|
-
IDecoder,
|
16
|
-
IEncoder,
|
17
|
-
IMessage,
|
18
|
-
IRelay,
|
19
|
-
ProtocolCreateOptions,
|
20
|
-
SendResult,
|
21
|
-
} from "@waku/interfaces";
|
22
|
-
import debug from "debug";
|
23
|
-
|
24
|
-
import { DefaultPubSubTopic } from "../constants.js";
|
25
|
-
import { groupByContentTopic } from "../group_by.js";
|
26
|
-
import { TopicOnlyDecoder } from "../message/topic_only_message.js";
|
27
|
-
|
28
|
-
import * as constants from "./constants.js";
|
29
|
-
import { messageValidator } from "./message_validator.js";
|
30
|
-
|
31
|
-
const log = debug("waku:relay");
|
32
|
-
|
33
|
-
export type Observer<T extends IDecodedMessage> = {
|
34
|
-
decoder: IDecoder<T>;
|
35
|
-
callback: Callback<T>;
|
36
|
-
};
|
37
|
-
|
38
|
-
export type RelayCreateOptions = ProtocolCreateOptions & GossipsubOpts;
|
39
|
-
export type ContentTopic = string;
|
40
|
-
|
41
|
-
/**
|
42
|
-
* Implements the [Waku v2 Relay protocol](https://rfc.vac.dev/spec/11/).
|
43
|
-
* Throws if libp2p.pubsub does not support Waku Relay
|
44
|
-
*/
|
45
|
-
class Relay implements IRelay {
|
46
|
-
private readonly pubSubTopic: string;
|
47
|
-
private defaultDecoder: IDecoder<IDecodedMessage>;
|
48
|
-
|
49
|
-
public static multicodec: string = constants.RelayCodecs[0];
|
50
|
-
public readonly gossipSub: GossipSub;
|
51
|
-
|
52
|
-
/**
|
53
|
-
* observers called when receiving new message.
|
54
|
-
* Observers under key `""` are always called.
|
55
|
-
*/
|
56
|
-
private observers: Map<ContentTopic, Set<unknown>>;
|
57
|
-
|
58
|
-
constructor(libp2p: Libp2p, options?: Partial<RelayCreateOptions>) {
|
59
|
-
if (!this.isRelayPubSub(libp2p.pubsub)) {
|
60
|
-
throw Error(
|
61
|
-
`Failed to initialize Relay. libp2p.pubsub does not support ${Relay.multicodec}`
|
62
|
-
);
|
63
|
-
}
|
64
|
-
|
65
|
-
this.gossipSub = libp2p.pubsub as GossipSub;
|
66
|
-
this.pubSubTopic = options?.pubSubTopic ?? DefaultPubSubTopic;
|
67
|
-
|
68
|
-
if (this.gossipSub.isStarted()) {
|
69
|
-
this.gossipSubSubscribe(this.pubSubTopic);
|
70
|
-
}
|
71
|
-
|
72
|
-
this.observers = new Map();
|
73
|
-
|
74
|
-
// TODO: User might want to decide what decoder should be used (e.g. for RLN)
|
75
|
-
this.defaultDecoder = new TopicOnlyDecoder();
|
76
|
-
}
|
77
|
-
|
78
|
-
/**
|
79
|
-
* Mounts the gossipsub protocol onto the libp2p node
|
80
|
-
* and subscribes to the default topic.
|
81
|
-
*
|
82
|
-
* @override
|
83
|
-
* @returns {void}
|
84
|
-
*/
|
85
|
-
public async start(): Promise<void> {
|
86
|
-
if (this.gossipSub.isStarted()) {
|
87
|
-
throw Error("GossipSub already started.");
|
88
|
-
}
|
89
|
-
|
90
|
-
await this.gossipSub.start();
|
91
|
-
this.gossipSubSubscribe(this.pubSubTopic);
|
92
|
-
}
|
93
|
-
|
94
|
-
/**
|
95
|
-
* Send Waku message.
|
96
|
-
*/
|
97
|
-
public async send(encoder: IEncoder, message: IMessage): Promise<SendResult> {
|
98
|
-
const msg = await encoder.toWire(message);
|
99
|
-
if (!msg) {
|
100
|
-
log("Failed to encode message, aborting publish");
|
101
|
-
return { recipients: [] };
|
102
|
-
}
|
103
|
-
|
104
|
-
return this.gossipSub.publish(this.pubSubTopic, msg);
|
105
|
-
}
|
106
|
-
|
107
|
-
/**
|
108
|
-
* Add an observer and associated Decoder to process incoming messages on a given content topic.
|
109
|
-
*
|
110
|
-
* @returns Function to delete the observer
|
111
|
-
*/
|
112
|
-
public subscribe<T extends IDecodedMessage>(
|
113
|
-
decoders: IDecoder<T> | IDecoder<T>[],
|
114
|
-
callback: Callback<T>
|
115
|
-
): () => void {
|
116
|
-
const contentTopicToObservers = Array.isArray(decoders)
|
117
|
-
? toObservers(decoders, callback)
|
118
|
-
: toObservers([decoders], callback);
|
119
|
-
|
120
|
-
for (const contentTopic of contentTopicToObservers.keys()) {
|
121
|
-
const currObservers = this.observers.get(contentTopic) || new Set();
|
122
|
-
const newObservers =
|
123
|
-
contentTopicToObservers.get(contentTopic) || new Set();
|
124
|
-
|
125
|
-
this.observers.set(contentTopic, union(currObservers, newObservers));
|
126
|
-
}
|
127
|
-
|
128
|
-
return () => {
|
129
|
-
for (const contentTopic of contentTopicToObservers.keys()) {
|
130
|
-
const currentObservers = this.observers.get(contentTopic) || new Set();
|
131
|
-
const observersToRemove =
|
132
|
-
contentTopicToObservers.get(contentTopic) || new Set();
|
133
|
-
|
134
|
-
const nextObservers = leftMinusJoin(
|
135
|
-
currentObservers,
|
136
|
-
observersToRemove
|
137
|
-
);
|
138
|
-
|
139
|
-
if (nextObservers.size) {
|
140
|
-
this.observers.set(contentTopic, nextObservers);
|
141
|
-
} else {
|
142
|
-
this.observers.delete(contentTopic);
|
143
|
-
}
|
144
|
-
}
|
145
|
-
};
|
146
|
-
}
|
147
|
-
|
148
|
-
public getActiveSubscriptions(): ActiveSubscriptions {
|
149
|
-
const map = new Map();
|
150
|
-
map.set(this.pubSubTopic, this.observers.keys());
|
151
|
-
return map;
|
152
|
-
}
|
153
|
-
|
154
|
-
public getMeshPeers(topic?: TopicStr): PeerIdStr[] {
|
155
|
-
return this.gossipSub.getMeshPeers(topic ?? this.pubSubTopic);
|
156
|
-
}
|
157
|
-
|
158
|
-
private async processIncomingMessage<T extends IDecodedMessage>(
|
159
|
-
pubSubTopic: string,
|
160
|
-
bytes: Uint8Array
|
161
|
-
): Promise<void> {
|
162
|
-
const topicOnlyMsg = await this.defaultDecoder.fromWireToProtoObj(bytes);
|
163
|
-
if (!topicOnlyMsg || !topicOnlyMsg.contentTopic) {
|
164
|
-
log("Message does not have a content topic, skipping");
|
165
|
-
return;
|
166
|
-
}
|
167
|
-
|
168
|
-
const observers = this.observers.get(topicOnlyMsg.contentTopic) as Set<
|
169
|
-
Observer<T>
|
170
|
-
>;
|
171
|
-
if (!observers) {
|
172
|
-
return;
|
173
|
-
}
|
174
|
-
await Promise.all(
|
175
|
-
Array.from(observers).map(async ({ decoder, callback }) => {
|
176
|
-
const protoMsg = await decoder.fromWireToProtoObj(bytes);
|
177
|
-
if (!protoMsg) {
|
178
|
-
log("Internal error: message previously decoded failed on 2nd pass.");
|
179
|
-
return;
|
180
|
-
}
|
181
|
-
const msg = await decoder.fromProtoObj(pubSubTopic, protoMsg);
|
182
|
-
if (msg) {
|
183
|
-
callback(msg);
|
184
|
-
} else {
|
185
|
-
log("Failed to decode messages on", topicOnlyMsg.contentTopic);
|
186
|
-
}
|
187
|
-
})
|
188
|
-
);
|
189
|
-
}
|
190
|
-
|
191
|
-
/**
|
192
|
-
* Subscribe to a pubsub topic and start emitting Waku messages to observers.
|
193
|
-
*
|
194
|
-
* @override
|
195
|
-
*/
|
196
|
-
private gossipSubSubscribe(pubSubTopic: string): void {
|
197
|
-
this.gossipSub.addEventListener(
|
198
|
-
"gossipsub:message",
|
199
|
-
async (event: CustomEvent<GossipsubMessage>) => {
|
200
|
-
if (event.detail.msg.topic !== pubSubTopic) return;
|
201
|
-
log(`Message received on ${pubSubTopic}`);
|
202
|
-
|
203
|
-
this.processIncomingMessage(
|
204
|
-
event.detail.msg.topic,
|
205
|
-
event.detail.msg.data
|
206
|
-
).catch((e) => log("Failed to process incoming message", e));
|
207
|
-
}
|
208
|
-
);
|
209
|
-
|
210
|
-
this.gossipSub.topicValidators.set(pubSubTopic, messageValidator);
|
211
|
-
this.gossipSub.subscribe(pubSubTopic);
|
212
|
-
}
|
213
|
-
|
214
|
-
private isRelayPubSub(pubsub: PubSub): boolean {
|
215
|
-
return pubsub?.multicodecs?.includes(Relay.multicodec) || false;
|
216
|
-
}
|
217
|
-
}
|
218
|
-
|
219
|
-
export function wakuRelay(
|
220
|
-
init: Partial<ProtocolCreateOptions> = {}
|
221
|
-
): (libp2p: Libp2p) => IRelay {
|
222
|
-
return (libp2p: Libp2p) => new Relay(libp2p, init);
|
223
|
-
}
|
224
|
-
|
225
|
-
export function wakuGossipSub(
|
226
|
-
init: Partial<RelayCreateOptions> = {}
|
227
|
-
): (components: GossipSubComponents) => GossipSub {
|
228
|
-
return (components: GossipSubComponents) => {
|
229
|
-
init = {
|
230
|
-
...init,
|
231
|
-
// Ensure that no signature is included nor expected in the messages.
|
232
|
-
globalSignaturePolicy: SignaturePolicy.StrictNoSign,
|
233
|
-
fallbackToFloodsub: false,
|
234
|
-
};
|
235
|
-
const pubsub = new GossipSub(components, init);
|
236
|
-
pubsub.multicodecs = constants.RelayCodecs;
|
237
|
-
return pubsub;
|
238
|
-
};
|
239
|
-
}
|
240
|
-
|
241
|
-
function toObservers<T extends IDecodedMessage>(
|
242
|
-
decoders: IDecoder<T>[],
|
243
|
-
callback: Callback<T>
|
244
|
-
): Map<ContentTopic, Set<Observer<T>>> {
|
245
|
-
const contentTopicToDecoders = Array.from(
|
246
|
-
groupByContentTopic(decoders).entries()
|
247
|
-
);
|
248
|
-
|
249
|
-
const contentTopicToObserversEntries = contentTopicToDecoders.map(
|
250
|
-
([contentTopic, decoders]) =>
|
251
|
-
[
|
252
|
-
contentTopic,
|
253
|
-
new Set(
|
254
|
-
decoders.map(
|
255
|
-
(decoder) =>
|
256
|
-
({
|
257
|
-
decoder,
|
258
|
-
callback,
|
259
|
-
} as Observer<T>)
|
260
|
-
)
|
261
|
-
),
|
262
|
-
] as [ContentTopic, Set<Observer<T>>]
|
263
|
-
);
|
264
|
-
|
265
|
-
return new Map(contentTopicToObserversEntries);
|
266
|
-
}
|
267
|
-
|
268
|
-
function union(left: Set<unknown>, right: Set<unknown>): Set<unknown> {
|
269
|
-
for (const val of right.values()) {
|
270
|
-
left.add(val);
|
271
|
-
}
|
272
|
-
return left;
|
273
|
-
}
|
274
|
-
|
275
|
-
function leftMinusJoin(left: Set<unknown>, right: Set<unknown>): Set<unknown> {
|
276
|
-
for (const val of right.values()) {
|
277
|
-
if (left.has(val)) {
|
278
|
-
left.delete(val);
|
279
|
-
}
|
280
|
-
}
|
281
|
-
return left;
|
282
|
-
}
|
@@ -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
|
-
}
|