@waku/core 0.0.26-7eb3375.0 → 0.0.27
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 +56 -0
- package/bundle/base_protocol-LhsIWF3-.js +308 -0
- package/bundle/{browser-9a6558bb.js → browser-BQyFvtq6.js} +579 -699
- package/bundle/index-8YyfzF9R.js +650 -0
- package/bundle/index.js +3076 -21759
- package/bundle/lib/base_protocol.js +3 -3
- package/bundle/lib/message/version_0.js +3 -3
- package/bundle/lib/predefined_bootstrap_nodes.js +1 -1
- package/bundle/{version_0-7190df43.js → version_0-FXfzO8Km.js} +1368 -2459
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +2 -5
- package/dist/index.js +2 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +14 -10
- package/dist/lib/base_protocol.js +38 -16
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/connection_manager.d.ts +2 -2
- package/dist/lib/connection_manager.js +16 -6
- package/dist/lib/connection_manager.js.map +1 -1
- package/dist/lib/filter/index.d.ts +1 -1
- package/dist/lib/filter/index.js +146 -85
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/filterPeers.d.ts +8 -5
- package/dist/lib/filterPeers.js +12 -5
- package/dist/lib/filterPeers.js.map +1 -1
- package/dist/lib/keep_alive_manager.d.ts +2 -3
- package/dist/lib/keep_alive_manager.js +2 -2
- package/dist/lib/keep_alive_manager.js.map +1 -1
- package/dist/lib/light_push/index.js +3 -7
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/message/version_0.d.ts +3 -3
- package/dist/lib/message/version_0.js +5 -6
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/metadata/index.d.ts +3 -0
- package/dist/lib/metadata/index.js +81 -0
- package/dist/lib/metadata/index.js.map +1 -0
- package/dist/lib/predefined_bootstrap_nodes.js.map +1 -1
- package/dist/lib/store/history_rpc.js.map +1 -1
- package/dist/lib/store/index.js +1 -4
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/stream_manager.d.ts +2 -2
- package/dist/lib/stream_manager.js.map +1 -1
- package/dist/lib/wait_for_remote_peer.d.ts +1 -1
- package/dist/lib/wait_for_remote_peer.js +40 -10
- package/dist/lib/wait_for_remote_peer.js.map +1 -1
- package/package.json +129 -1
- package/src/index.ts +3 -6
- package/src/lib/base_protocol.ts +71 -24
- package/src/lib/connection_manager.ts +17 -10
- package/src/lib/filter/index.ts +237 -139
- package/src/lib/filterPeers.ts +15 -7
- package/src/lib/keep_alive_manager.ts +4 -5
- package/src/lib/light_push/index.ts +11 -11
- package/src/lib/message/version_0.ts +16 -8
- package/src/lib/metadata/index.ts +142 -0
- package/src/lib/store/index.ts +3 -7
- package/src/lib/stream_manager.ts +2 -3
- package/src/lib/wait_for_remote_peer.ts +58 -12
- package/bundle/base_protocol-46017f51.js +0 -468
- package/bundle/index-7581d519.js +0 -31
- package/dist/lib/constants.d.ts +0 -4
- package/dist/lib/constants.js +0 -5
- package/dist/lib/constants.js.map +0 -1
- package/dist/lib/waku.d.ts +0 -57
- package/dist/lib/waku.js +0 -124
- package/dist/lib/waku.js.map +0 -1
- package/src/lib/constants.ts +0 -4
- package/src/lib/waku.ts +0 -204
@@ -7,12 +7,11 @@ import type {
|
|
7
7
|
IMetaSetter,
|
8
8
|
IProtoMessage,
|
9
9
|
IRateLimitProof,
|
10
|
-
PubsubTopic
|
10
|
+
PubsubTopic,
|
11
|
+
SingleShardInfo
|
11
12
|
} from "@waku/interfaces";
|
12
13
|
import { proto_message as proto } from "@waku/proto";
|
13
|
-
import { Logger } from "@waku/utils";
|
14
|
-
|
15
|
-
import { DefaultPubsubTopic } from "../constants.js";
|
14
|
+
import { determinePubsubTopic, Logger } from "@waku/utils";
|
16
15
|
|
17
16
|
const log = new Logger("message:version-0");
|
18
17
|
const OneMillion = BigInt(1_000_000);
|
@@ -119,12 +118,18 @@ export class Encoder implements IEncoder {
|
|
119
118
|
* messages.
|
120
119
|
*/
|
121
120
|
export function createEncoder({
|
122
|
-
pubsubTopic
|
121
|
+
pubsubTopic,
|
122
|
+
pubsubTopicShardInfo,
|
123
123
|
contentTopic,
|
124
124
|
ephemeral,
|
125
125
|
metaSetter
|
126
126
|
}: EncoderOptions): Encoder {
|
127
|
-
return new Encoder(
|
127
|
+
return new Encoder(
|
128
|
+
contentTopic,
|
129
|
+
ephemeral,
|
130
|
+
determinePubsubTopic(contentTopic, pubsubTopic ?? pubsubTopicShardInfo),
|
131
|
+
metaSetter
|
132
|
+
);
|
128
133
|
}
|
129
134
|
|
130
135
|
export class Decoder implements IDecoder<DecodedMessage> {
|
@@ -182,7 +187,10 @@ export class Decoder implements IDecoder<DecodedMessage> {
|
|
182
187
|
*/
|
183
188
|
export function createDecoder(
|
184
189
|
contentTopic: string,
|
185
|
-
|
190
|
+
pubsubTopicShardInfo?: SingleShardInfo | PubsubTopic
|
186
191
|
): Decoder {
|
187
|
-
return new Decoder(
|
192
|
+
return new Decoder(
|
193
|
+
determinePubsubTopic(contentTopic, pubsubTopicShardInfo),
|
194
|
+
contentTopic
|
195
|
+
);
|
188
196
|
}
|
@@ -0,0 +1,142 @@
|
|
1
|
+
import type { PeerId } from "@libp2p/interface";
|
2
|
+
import { IncomingStreamData } from "@libp2p/interface";
|
3
|
+
import type {
|
4
|
+
IMetadata,
|
5
|
+
Libp2pComponents,
|
6
|
+
PeerIdStr,
|
7
|
+
ShardInfo
|
8
|
+
} from "@waku/interfaces";
|
9
|
+
import { proto_metadata } from "@waku/proto";
|
10
|
+
import { encodeRelayShard, Logger, shardInfoToPubsubTopics } from "@waku/utils";
|
11
|
+
import all from "it-all";
|
12
|
+
import * as lp from "it-length-prefixed";
|
13
|
+
import { pipe } from "it-pipe";
|
14
|
+
import { Uint8ArrayList } from "uint8arraylist";
|
15
|
+
|
16
|
+
import { BaseProtocol } from "../base_protocol.js";
|
17
|
+
|
18
|
+
const log = new Logger("metadata");
|
19
|
+
|
20
|
+
export const MetadataCodec = "/vac/waku/metadata/1.0.0";
|
21
|
+
|
22
|
+
class Metadata extends BaseProtocol implements IMetadata {
|
23
|
+
private libp2pComponents: Libp2pComponents;
|
24
|
+
handshakesConfirmed: Set<PeerIdStr> = new Set();
|
25
|
+
|
26
|
+
constructor(
|
27
|
+
public shardInfo: ShardInfo,
|
28
|
+
libp2p: Libp2pComponents
|
29
|
+
) {
|
30
|
+
super(
|
31
|
+
MetadataCodec,
|
32
|
+
libp2p.components,
|
33
|
+
log,
|
34
|
+
shardInfoToPubsubTopics(shardInfo)
|
35
|
+
);
|
36
|
+
this.libp2pComponents = libp2p;
|
37
|
+
void libp2p.registrar.handle(MetadataCodec, (streamData) => {
|
38
|
+
void this.onRequest(streamData);
|
39
|
+
});
|
40
|
+
}
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Handle an incoming metadata request
|
44
|
+
*/
|
45
|
+
private async onRequest(streamData: IncomingStreamData): Promise<void> {
|
46
|
+
try {
|
47
|
+
const { stream, connection } = streamData;
|
48
|
+
const encodedShardInfo = proto_metadata.WakuMetadataResponse.encode(
|
49
|
+
this.shardInfo
|
50
|
+
);
|
51
|
+
|
52
|
+
const encodedResponse = await pipe(
|
53
|
+
[encodedShardInfo],
|
54
|
+
lp.encode,
|
55
|
+
stream,
|
56
|
+
lp.decode,
|
57
|
+
async (source) => await all(source)
|
58
|
+
);
|
59
|
+
|
60
|
+
const remoteShardInfoResponse =
|
61
|
+
this.decodeMetadataResponse(encodedResponse);
|
62
|
+
|
63
|
+
await this.savePeerShardInfo(
|
64
|
+
connection.remotePeer,
|
65
|
+
remoteShardInfoResponse
|
66
|
+
);
|
67
|
+
} catch (error) {
|
68
|
+
log.error("Error handling metadata request", error);
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Make a metadata query to a peer
|
74
|
+
*/
|
75
|
+
async query(peerId: PeerId): Promise<ShardInfo> {
|
76
|
+
const request = proto_metadata.WakuMetadataRequest.encode(this.shardInfo);
|
77
|
+
|
78
|
+
const peer = await this.peerStore.get(peerId);
|
79
|
+
if (!peer) {
|
80
|
+
throw new Error(`Peer ${peerId.toString()} not found`);
|
81
|
+
}
|
82
|
+
|
83
|
+
const stream = await this.getStream(peer);
|
84
|
+
|
85
|
+
const encodedResponse = await pipe(
|
86
|
+
[request],
|
87
|
+
lp.encode,
|
88
|
+
stream,
|
89
|
+
lp.decode,
|
90
|
+
async (source) => await all(source)
|
91
|
+
);
|
92
|
+
|
93
|
+
const decodedResponse = this.decodeMetadataResponse(encodedResponse);
|
94
|
+
|
95
|
+
await this.savePeerShardInfo(peerId, decodedResponse);
|
96
|
+
|
97
|
+
return decodedResponse;
|
98
|
+
}
|
99
|
+
|
100
|
+
public async confirmOrAttemptHandshake(peerId: PeerId): Promise<void> {
|
101
|
+
if (this.handshakesConfirmed.has(peerId.toString())) return;
|
102
|
+
|
103
|
+
await this.query(peerId);
|
104
|
+
|
105
|
+
return;
|
106
|
+
}
|
107
|
+
|
108
|
+
private decodeMetadataResponse(encodedResponse: Uint8ArrayList[]): ShardInfo {
|
109
|
+
const bytes = new Uint8ArrayList();
|
110
|
+
|
111
|
+
encodedResponse.forEach((chunk) => {
|
112
|
+
bytes.append(chunk);
|
113
|
+
});
|
114
|
+
const response = proto_metadata.WakuMetadataResponse.decode(
|
115
|
+
bytes
|
116
|
+
) as ShardInfo;
|
117
|
+
|
118
|
+
if (!response) log.error("Error decoding metadata response");
|
119
|
+
|
120
|
+
return response;
|
121
|
+
}
|
122
|
+
|
123
|
+
private async savePeerShardInfo(
|
124
|
+
peerId: PeerId,
|
125
|
+
shardInfo: ShardInfo
|
126
|
+
): Promise<void> {
|
127
|
+
// add or update the shardInfo to peer store
|
128
|
+
await this.libp2pComponents.peerStore.merge(peerId, {
|
129
|
+
metadata: {
|
130
|
+
shardInfo: encodeRelayShard(shardInfo)
|
131
|
+
}
|
132
|
+
});
|
133
|
+
|
134
|
+
this.handshakesConfirmed.add(peerId.toString());
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
export function wakuMetadata(
|
139
|
+
shardInfo: ShardInfo
|
140
|
+
): (components: Libp2pComponents) => IMetadata {
|
141
|
+
return (components: Libp2pComponents) => new Metadata(shardInfo, components);
|
142
|
+
}
|
package/src/lib/store/index.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import type { Stream } from "@libp2p/interface
|
1
|
+
import type { Stream } from "@libp2p/interface";
|
2
2
|
import { sha256 } from "@noble/hashes/sha256";
|
3
3
|
import {
|
4
4
|
Cursor,
|
@@ -6,8 +6,7 @@ import {
|
|
6
6
|
IDecoder,
|
7
7
|
IStore,
|
8
8
|
Libp2p,
|
9
|
-
ProtocolCreateOptions
|
10
|
-
PubsubTopic
|
9
|
+
ProtocolCreateOptions
|
11
10
|
} from "@waku/interfaces";
|
12
11
|
import { proto_store as proto } from "@waku/proto";
|
13
12
|
import { ensurePubsubTopicIsConfigured, isDefined } from "@waku/utils";
|
@@ -19,7 +18,6 @@ import { pipe } from "it-pipe";
|
|
19
18
|
import { Uint8ArrayList } from "uint8arraylist";
|
20
19
|
|
21
20
|
import { BaseProtocol } from "../base_protocol.js";
|
22
|
-
import { DefaultPubsubTopic } from "../constants.js";
|
23
21
|
import { toProtoMessage } from "../to_proto_message.js";
|
24
22
|
|
25
23
|
import { HistoryRpc, PageDirection, Params } from "./history_rpc.js";
|
@@ -75,12 +73,10 @@ export interface QueryOptions {
|
|
75
73
|
* The Waku Store protocol can be used to retrieved historical messages.
|
76
74
|
*/
|
77
75
|
class Store extends BaseProtocol implements IStore {
|
78
|
-
private readonly pubsubTopics: PubsubTopic[];
|
79
76
|
private readonly NUM_PEERS_PROTOCOL = 1;
|
80
77
|
|
81
78
|
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
82
|
-
super(StoreCodec, libp2p.components);
|
83
|
-
this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubsubTopic];
|
79
|
+
super(StoreCodec, libp2p.components, log, options!.pubsubTopics!, options);
|
84
80
|
}
|
85
81
|
|
86
82
|
/**
|
@@ -1,6 +1,5 @@
|
|
1
|
-
import type { PeerUpdate } from "@libp2p/interface";
|
2
|
-
import
|
3
|
-
import { Peer } from "@libp2p/interface/peer-store";
|
1
|
+
import type { PeerUpdate, Stream } from "@libp2p/interface";
|
2
|
+
import { Peer } from "@libp2p/interface";
|
4
3
|
import { Libp2p } from "@waku/interfaces";
|
5
4
|
import { Logger } from "@waku/utils";
|
6
5
|
import { selectConnection } from "@waku/utils/libp2p";
|
@@ -1,15 +1,14 @@
|
|
1
1
|
import type { IdentifyResult } from "@libp2p/interface";
|
2
|
-
import type { IBaseProtocol, IRelay, Waku } from "@waku/interfaces";
|
2
|
+
import type { IBaseProtocol, IMetadata, IRelay, Waku } from "@waku/interfaces";
|
3
3
|
import { Protocols } from "@waku/interfaces";
|
4
4
|
import { Logger } from "@waku/utils";
|
5
5
|
import { pEvent } from "p-event";
|
6
|
-
|
7
6
|
const log = new Logger("wait-for-remote-peer");
|
8
7
|
|
9
8
|
/**
|
10
9
|
* Wait for a remote peer to be ready given the passed protocols.
|
11
10
|
* Must be used after attempting to connect to nodes, using
|
12
|
-
* {@link @waku/
|
11
|
+
* {@link @waku/sdk!WakuNode.dial} or a bootstrap method with
|
13
12
|
* {@link @waku/sdk!createLightNode}.
|
14
13
|
*
|
15
14
|
* If the passed protocols is a GossipSub protocol, then it resolves only once
|
@@ -45,19 +44,25 @@ export async function waitForRemotePeer(
|
|
45
44
|
if (protocols.includes(Protocols.Store)) {
|
46
45
|
if (!waku.store)
|
47
46
|
throw new Error("Cannot wait for Store peer: protocol not mounted");
|
48
|
-
promises.push(
|
47
|
+
promises.push(
|
48
|
+
waitForConnectedPeer(waku.store, waku.libp2p.services.metadata)
|
49
|
+
);
|
49
50
|
}
|
50
51
|
|
51
52
|
if (protocols.includes(Protocols.LightPush)) {
|
52
53
|
if (!waku.lightPush)
|
53
54
|
throw new Error("Cannot wait for LightPush peer: protocol not mounted");
|
54
|
-
promises.push(
|
55
|
+
promises.push(
|
56
|
+
waitForConnectedPeer(waku.lightPush, waku.libp2p.services.metadata)
|
57
|
+
);
|
55
58
|
}
|
56
59
|
|
57
60
|
if (protocols.includes(Protocols.Filter)) {
|
58
61
|
if (!waku.filter)
|
59
62
|
throw new Error("Cannot wait for Filter peer: protocol not mounted");
|
60
|
-
promises.push(
|
63
|
+
promises.push(
|
64
|
+
waitForConnectedPeer(waku.filter, waku.libp2p.services.metadata)
|
65
|
+
);
|
61
66
|
}
|
62
67
|
|
63
68
|
if (timeoutMs) {
|
@@ -73,21 +78,62 @@ export async function waitForRemotePeer(
|
|
73
78
|
|
74
79
|
/**
|
75
80
|
* Wait for a peer with the given protocol to be connected.
|
81
|
+
* If sharding is enabled on the node, it will also wait for the peer to be confirmed by the metadata service.
|
76
82
|
*/
|
77
|
-
async function waitForConnectedPeer(
|
83
|
+
async function waitForConnectedPeer(
|
84
|
+
protocol: IBaseProtocol,
|
85
|
+
metadataService?: IMetadata
|
86
|
+
): Promise<void> {
|
78
87
|
const codec = protocol.multicodec;
|
79
|
-
const peers = await protocol.
|
88
|
+
const peers = await protocol.connectedPeers();
|
80
89
|
|
81
90
|
if (peers.length) {
|
82
|
-
|
83
|
-
|
91
|
+
if (!metadataService) {
|
92
|
+
log.info(`${codec} peer found: `, peers[0].id.toString());
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
|
96
|
+
// once a peer is connected, we need to confirm the metadata handshake with at least one of those peers if sharding is enabled
|
97
|
+
try {
|
98
|
+
await Promise.any(
|
99
|
+
peers.map((peer) => metadataService.confirmOrAttemptHandshake(peer.id))
|
100
|
+
);
|
101
|
+
return;
|
102
|
+
} catch (e) {
|
103
|
+
if ((e as any).code === "ERR_CONNECTION_BEING_CLOSED")
|
104
|
+
log.error(
|
105
|
+
`Connection with the peer was closed and possibly because it's on a different shard. Error: ${e}`
|
106
|
+
);
|
107
|
+
|
108
|
+
log.error(`Error waiting for handshake confirmation: ${e}`);
|
109
|
+
}
|
84
110
|
}
|
85
111
|
|
112
|
+
log.info(`Waiting for ${codec} peer`);
|
113
|
+
|
114
|
+
// else we'll just wait for the next peer to connect
|
86
115
|
await new Promise<void>((resolve) => {
|
87
116
|
const cb = (evt: CustomEvent<IdentifyResult>): void => {
|
88
117
|
if (evt.detail?.protocols?.includes(codec)) {
|
89
|
-
|
90
|
-
|
118
|
+
if (metadataService) {
|
119
|
+
metadataService
|
120
|
+
.confirmOrAttemptHandshake(evt.detail.peerId)
|
121
|
+
.then(() => {
|
122
|
+
protocol.removeLibp2pEventListener("peer:identify", cb);
|
123
|
+
resolve();
|
124
|
+
})
|
125
|
+
.catch((e) => {
|
126
|
+
if (e.code === "ERR_CONNECTION_BEING_CLOSED")
|
127
|
+
log.error(
|
128
|
+
`Connection with the peer was closed and possibly because it's on a different shard. Error: ${e}`
|
129
|
+
);
|
130
|
+
|
131
|
+
log.error(`Error waiting for handshake confirmation: ${e}`);
|
132
|
+
});
|
133
|
+
} else {
|
134
|
+
protocol.removeLibp2pEventListener("peer:identify", cb);
|
135
|
+
resolve();
|
136
|
+
}
|
91
137
|
}
|
92
138
|
};
|
93
139
|
protocol.addLibp2pEventListener("peer:identify", cb);
|