@waku/core 0.0.26 → 0.0.28-434be7b.0
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 +26 -0
- package/bundle/{base_protocol-pDODy0G6.js → base_protocol-BCwLeb-A.js} +134 -89
- package/bundle/{browser-mTOOnVZp.js → browser-DoQRY-an.js} +518 -712
- package/bundle/{index-cmONXM-V.js → index-vlQahmUj.js} +98 -41
- package/bundle/index.js +3081 -21642
- 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-LQTFNC7k.js → version_0-DiakMc1A.js} +1246 -2444
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +15 -13
- package/dist/lib/base_protocol.js +35 -22
- 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 +144 -82
- 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.map +1 -1
- package/dist/lib/light_push/index.d.ts +12 -2
- package/dist/lib/light_push/index.js +80 -80
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/metadata/index.d.ts +2 -2
- package/dist/lib/metadata/index.js +58 -16
- package/dist/lib/metadata/index.js.map +1 -1
- package/dist/lib/store/index.js +1 -3
- 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 +42 -10
- package/dist/lib/wait_for_remote_peer.js.map +1 -1
- package/package.json +1 -127
- package/src/index.ts +1 -6
- package/src/lib/base_protocol.ts +57 -37
- package/src/lib/connection_manager.ts +17 -10
- package/src/lib/filter/index.ts +234 -136
- package/src/lib/filterPeers.ts +15 -7
- package/src/lib/keep_alive_manager.ts +2 -3
- package/src/lib/light_push/index.ts +104 -124
- package/src/lib/metadata/index.ts +92 -30
- package/src/lib/store/index.ts +3 -6
- package/src/lib/stream_manager.ts +2 -3
- package/src/lib/wait_for_remote_peer.ts +68 -12
- package/dist/lib/waku.d.ts +0 -57
- package/dist/lib/waku.js +0 -130
- package/dist/lib/waku.js.map +0 -1
- package/src/lib/waku.ts +0 -214
@@ -1,20 +1,16 @@
|
|
1
|
-
import type { Stream } from "@libp2p/interface
|
2
|
-
import type { PeerId } from "@libp2p/interface/peer-id";
|
1
|
+
import type { Peer, PeerId, Stream } from "@libp2p/interface";
|
3
2
|
import {
|
3
|
+
Failure,
|
4
|
+
IBaseProtocolCore,
|
4
5
|
IEncoder,
|
5
|
-
ILightPush,
|
6
6
|
IMessage,
|
7
7
|
Libp2p,
|
8
8
|
ProtocolCreateOptions,
|
9
|
-
|
10
|
-
|
11
|
-
SendResult
|
9
|
+
ProtocolError,
|
10
|
+
ProtocolResult
|
12
11
|
} from "@waku/interfaces";
|
13
12
|
import { PushResponse } from "@waku/proto";
|
14
|
-
import {
|
15
|
-
ensurePubsubTopicIsConfigured,
|
16
|
-
isMessageSizeUnderCap
|
17
|
-
} from "@waku/utils";
|
13
|
+
import { isMessageSizeUnderCap } from "@waku/utils";
|
18
14
|
import { Logger } from "@waku/utils";
|
19
15
|
import all from "it-all";
|
20
16
|
import * as lp from "it-length-prefixed";
|
@@ -30,42 +26,37 @@ const log = new Logger("light-push");
|
|
30
26
|
export const LightPushCodec = "/vac/waku/lightpush/2.0.0-beta1";
|
31
27
|
export { PushResponse };
|
32
28
|
|
33
|
-
type PreparePushMessageResult =
|
34
|
-
|
35
|
-
|
36
|
-
error: null;
|
37
|
-
}
|
38
|
-
| {
|
39
|
-
query: null;
|
40
|
-
error: SendError;
|
41
|
-
};
|
29
|
+
type PreparePushMessageResult = ProtocolResult<"query", PushRpc>;
|
30
|
+
|
31
|
+
type CoreSendResult = ProtocolResult<"success", PeerId, "failure", Failure>;
|
42
32
|
|
43
33
|
/**
|
44
34
|
* Implements the [Waku v2 Light Push protocol](https://rfc.vac.dev/spec/19/).
|
45
35
|
*/
|
46
|
-
class
|
47
|
-
private readonly pubsubTopics: PubsubTopic[];
|
48
|
-
private readonly NUM_PEERS_PROTOCOL = 1;
|
49
|
-
|
36
|
+
export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
|
50
37
|
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
51
|
-
super(
|
52
|
-
|
38
|
+
super(
|
39
|
+
LightPushCodec,
|
40
|
+
libp2p.components,
|
41
|
+
log,
|
42
|
+
options!.pubsubTopics!,
|
43
|
+
options
|
44
|
+
);
|
53
45
|
}
|
54
46
|
|
55
47
|
private async preparePushMessage(
|
56
48
|
encoder: IEncoder,
|
57
|
-
message: IMessage
|
58
|
-
pubsubTopic: string
|
49
|
+
message: IMessage
|
59
50
|
): Promise<PreparePushMessageResult> {
|
60
51
|
try {
|
61
52
|
if (!message.payload || message.payload.length === 0) {
|
62
53
|
log.error("Failed to send waku light push: payload is empty");
|
63
|
-
return { query: null, error:
|
54
|
+
return { query: null, error: ProtocolError.EMPTY_PAYLOAD };
|
64
55
|
}
|
65
56
|
|
66
57
|
if (!(await isMessageSizeUnderCap(encoder, message))) {
|
67
58
|
log.error("Failed to send waku light push: message is bigger than 1MB");
|
68
|
-
return { query: null, error:
|
59
|
+
return { query: null, error: ProtocolError.SIZE_TOO_BIG };
|
69
60
|
}
|
70
61
|
|
71
62
|
const protoMessage = await encoder.toProtoObj(message);
|
@@ -73,131 +64,120 @@ class LightPush extends BaseProtocol implements ILightPush {
|
|
73
64
|
log.error("Failed to encode to protoMessage, aborting push");
|
74
65
|
return {
|
75
66
|
query: null,
|
76
|
-
error:
|
67
|
+
error: ProtocolError.ENCODE_FAILED
|
77
68
|
};
|
78
69
|
}
|
79
70
|
|
80
|
-
const query = PushRpc.createRequest(protoMessage, pubsubTopic);
|
71
|
+
const query = PushRpc.createRequest(protoMessage, encoder.pubsubTopic);
|
81
72
|
return { query, error: null };
|
82
73
|
} catch (error) {
|
83
74
|
log.error("Failed to prepare push message", error);
|
84
75
|
|
85
76
|
return {
|
86
77
|
query: null,
|
87
|
-
error:
|
78
|
+
error: ProtocolError.GENERIC_FAIL
|
88
79
|
};
|
89
80
|
}
|
90
81
|
}
|
91
82
|
|
92
|
-
async send(
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
83
|
+
async send(
|
84
|
+
encoder: IEncoder,
|
85
|
+
message: IMessage,
|
86
|
+
peer: Peer
|
87
|
+
): Promise<CoreSendResult> {
|
98
88
|
const { query, error: preparationError } = await this.preparePushMessage(
|
99
89
|
encoder,
|
100
|
-
message
|
101
|
-
pubsubTopic
|
90
|
+
message
|
102
91
|
);
|
103
92
|
|
104
93
|
if (preparationError || !query) {
|
105
94
|
return {
|
106
|
-
|
107
|
-
|
95
|
+
success: null,
|
96
|
+
failure: {
|
97
|
+
error: preparationError,
|
98
|
+
peerId: peer.id
|
99
|
+
}
|
108
100
|
};
|
109
101
|
}
|
110
102
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
103
|
+
let stream: Stream | undefined;
|
104
|
+
try {
|
105
|
+
stream = await this.getStream(peer);
|
106
|
+
} catch (err) {
|
107
|
+
log.error(
|
108
|
+
`Failed to get a stream for remote peer${peer.id.toString()}`,
|
109
|
+
err
|
110
|
+
);
|
118
111
|
return {
|
119
|
-
|
120
|
-
|
112
|
+
success: null,
|
113
|
+
failure: {
|
114
|
+
error: ProtocolError.REMOTE_PEER_FAULT,
|
115
|
+
peerId: peer.id
|
116
|
+
}
|
121
117
|
};
|
122
118
|
}
|
123
119
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
async (source) => await all(source)
|
144
|
-
);
|
145
|
-
} catch (err) {
|
146
|
-
log.error("Failed to send waku light push request", err);
|
147
|
-
return { recipients, error: SendError.GENERIC_FAIL };
|
148
|
-
}
|
149
|
-
|
150
|
-
const bytes = new Uint8ArrayList();
|
151
|
-
res.forEach((chunk) => {
|
152
|
-
bytes.append(chunk);
|
153
|
-
});
|
154
|
-
|
155
|
-
let response: PushResponse | undefined;
|
156
|
-
try {
|
157
|
-
response = PushRpc.decode(bytes).response;
|
158
|
-
} catch (err) {
|
159
|
-
log.error("Failed to decode push reply", err);
|
160
|
-
return { recipients, error: SendError.DECODE_FAILED };
|
161
|
-
}
|
120
|
+
let res: Uint8ArrayList[] | undefined;
|
121
|
+
try {
|
122
|
+
res = await pipe(
|
123
|
+
[query.encode()],
|
124
|
+
lp.encode,
|
125
|
+
stream,
|
126
|
+
lp.decode,
|
127
|
+
async (source) => await all(source)
|
128
|
+
);
|
129
|
+
} catch (err) {
|
130
|
+
log.error("Failed to send waku light push request", err);
|
131
|
+
return {
|
132
|
+
success: null,
|
133
|
+
failure: {
|
134
|
+
error: ProtocolError.GENERIC_FAIL,
|
135
|
+
peerId: peer.id
|
136
|
+
}
|
137
|
+
};
|
138
|
+
}
|
162
139
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
140
|
+
const bytes = new Uint8ArrayList();
|
141
|
+
res.forEach((chunk) => {
|
142
|
+
bytes.append(chunk);
|
143
|
+
});
|
167
144
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
145
|
+
let response: PushResponse | undefined;
|
146
|
+
try {
|
147
|
+
response = PushRpc.decode(bytes).response;
|
148
|
+
} catch (err) {
|
149
|
+
log.error("Failed to decode push reply", err);
|
150
|
+
return {
|
151
|
+
success: null,
|
152
|
+
failure: {
|
153
|
+
error: ProtocolError.DECODE_FAILED,
|
154
|
+
peerId: peer.id
|
155
|
+
}
|
156
|
+
};
|
157
|
+
}
|
172
158
|
|
173
|
-
|
174
|
-
|
159
|
+
if (!response) {
|
160
|
+
log.error("Remote peer fault: No response in PushRPC");
|
161
|
+
return {
|
162
|
+
success: null,
|
163
|
+
failure: {
|
164
|
+
error: ProtocolError.REMOTE_PEER_FAULT,
|
165
|
+
peerId: peer.id
|
166
|
+
}
|
167
|
+
};
|
168
|
+
}
|
175
169
|
|
176
|
-
|
177
|
-
|
170
|
+
if (!response.isSuccess) {
|
171
|
+
log.error("Remote peer rejected the message: ", response.info);
|
172
|
+
return {
|
173
|
+
success: null,
|
174
|
+
failure: {
|
175
|
+
error: ProtocolError.REMOTE_PEER_REJECTED,
|
176
|
+
peerId: peer.id
|
177
|
+
}
|
178
|
+
};
|
179
|
+
}
|
178
180
|
|
179
|
-
|
180
|
-
const errors = results
|
181
|
-
.filter(
|
182
|
-
(
|
183
|
-
result
|
184
|
-
): result is PromiseFulfilledResult<{
|
185
|
-
recipients: PeerId[];
|
186
|
-
error: SendError | undefined;
|
187
|
-
}> => result.status === "fulfilled"
|
188
|
-
)
|
189
|
-
.map((result) => result.value.error)
|
190
|
-
.filter((error) => error !== undefined) as SendError[];
|
191
|
-
|
192
|
-
return {
|
193
|
-
recipients,
|
194
|
-
errors
|
195
|
-
};
|
181
|
+
return { success: peer.id, failure: null };
|
196
182
|
}
|
197
183
|
}
|
198
|
-
|
199
|
-
export function wakuLightPush(
|
200
|
-
init: Partial<ProtocolCreateOptions> = {}
|
201
|
-
): (libp2p: Libp2p) => ILightPush {
|
202
|
-
return (libp2p: Libp2p) => new LightPush(libp2p, init);
|
203
|
-
}
|
@@ -1,14 +1,15 @@
|
|
1
|
-
import type { PeerId } from "@libp2p/interface
|
2
|
-
import { IncomingStreamData } from "@libp2p/interface
|
3
|
-
import {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
import type { PeerId } from "@libp2p/interface";
|
2
|
+
import { IncomingStreamData } from "@libp2p/interface";
|
3
|
+
import {
|
4
|
+
type IMetadata,
|
5
|
+
type Libp2pComponents,
|
6
|
+
type PeerIdStr,
|
7
|
+
ProtocolError,
|
8
|
+
QueryResult,
|
9
|
+
type ShardInfo
|
9
10
|
} from "@waku/interfaces";
|
10
11
|
import { proto_metadata } from "@waku/proto";
|
11
|
-
import { Logger } from "@waku/utils";
|
12
|
+
import { encodeRelayShard, Logger, shardInfoToPubsubTopics } from "@waku/utils";
|
12
13
|
import all from "it-all";
|
13
14
|
import * as lp from "it-length-prefixed";
|
14
15
|
import { pipe } from "it-pipe";
|
@@ -20,13 +21,21 @@ const log = new Logger("metadata");
|
|
20
21
|
|
21
22
|
export const MetadataCodec = "/vac/waku/metadata/1.0.0";
|
22
23
|
|
23
|
-
class Metadata extends BaseProtocol {
|
24
|
-
private readonly shardInfo: ShardingParams;
|
24
|
+
class Metadata extends BaseProtocol implements IMetadata {
|
25
25
|
private libp2pComponents: Libp2pComponents;
|
26
|
-
|
27
|
-
|
26
|
+
handshakesConfirmed: Map<PeerIdStr, ShardInfo> = new Map();
|
27
|
+
|
28
|
+
constructor(
|
29
|
+
public shardInfo: ShardInfo,
|
30
|
+
libp2p: Libp2pComponents
|
31
|
+
) {
|
32
|
+
super(
|
33
|
+
MetadataCodec,
|
34
|
+
libp2p.components,
|
35
|
+
log,
|
36
|
+
shardInfoToPubsubTopics(shardInfo)
|
37
|
+
);
|
28
38
|
this.libp2pComponents = libp2p;
|
29
|
-
this.shardInfo = shardInfo;
|
30
39
|
void libp2p.registrar.handle(MetadataCodec, (streamData) => {
|
31
40
|
void this.onRequest(streamData);
|
32
41
|
});
|
@@ -50,15 +59,13 @@ class Metadata extends BaseProtocol {
|
|
50
59
|
async (source) => await all(source)
|
51
60
|
);
|
52
61
|
|
53
|
-
const
|
54
|
-
|
62
|
+
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
|
63
|
+
|
64
|
+
if (error) {
|
65
|
+
return;
|
66
|
+
}
|
55
67
|
|
56
|
-
|
57
|
-
await this.libp2pComponents.peerStore.merge(connection.remotePeer, {
|
58
|
-
metadata: {
|
59
|
-
shardInfo: encodeRelayShard(remoteShardInfoResponse)
|
60
|
-
}
|
61
|
-
});
|
68
|
+
await this.savePeerShardInfo(connection.remotePeer, shardInfo);
|
62
69
|
} catch (error) {
|
63
70
|
log.error("Error handling metadata request", error);
|
64
71
|
}
|
@@ -67,10 +74,16 @@ class Metadata extends BaseProtocol {
|
|
67
74
|
/**
|
68
75
|
* Make a metadata query to a peer
|
69
76
|
*/
|
70
|
-
async query(peerId: PeerId): Promise<
|
77
|
+
async query(peerId: PeerId): Promise<QueryResult> {
|
71
78
|
const request = proto_metadata.WakuMetadataRequest.encode(this.shardInfo);
|
72
79
|
|
73
|
-
const peer = await this.
|
80
|
+
const peer = await this.peerStore.get(peerId);
|
81
|
+
if (!peer) {
|
82
|
+
return {
|
83
|
+
shardInfo: null,
|
84
|
+
error: ProtocolError.NO_PEER_AVAILABLE
|
85
|
+
};
|
86
|
+
}
|
74
87
|
|
75
88
|
const stream = await this.getStream(peer);
|
76
89
|
|
@@ -82,12 +95,38 @@ class Metadata extends BaseProtocol {
|
|
82
95
|
async (source) => await all(source)
|
83
96
|
);
|
84
97
|
|
85
|
-
const
|
98
|
+
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
|
99
|
+
|
100
|
+
if (error) {
|
101
|
+
return {
|
102
|
+
shardInfo: null,
|
103
|
+
error
|
104
|
+
};
|
105
|
+
}
|
106
|
+
|
107
|
+
await this.savePeerShardInfo(peerId, shardInfo);
|
86
108
|
|
87
|
-
return
|
109
|
+
return {
|
110
|
+
shardInfo,
|
111
|
+
error: null
|
112
|
+
};
|
88
113
|
}
|
89
114
|
|
90
|
-
|
115
|
+
public async confirmOrAttemptHandshake(peerId: PeerId): Promise<QueryResult> {
|
116
|
+
const shardInfo = this.handshakesConfirmed.get(peerId.toString());
|
117
|
+
if (shardInfo) {
|
118
|
+
return {
|
119
|
+
shardInfo,
|
120
|
+
error: null
|
121
|
+
};
|
122
|
+
}
|
123
|
+
|
124
|
+
return await this.query(peerId);
|
125
|
+
}
|
126
|
+
|
127
|
+
private decodeMetadataResponse(
|
128
|
+
encodedResponse: Uint8ArrayList[]
|
129
|
+
): QueryResult {
|
91
130
|
const bytes = new Uint8ArrayList();
|
92
131
|
|
93
132
|
encodedResponse.forEach((chunk) => {
|
@@ -97,14 +136,37 @@ class Metadata extends BaseProtocol {
|
|
97
136
|
bytes
|
98
137
|
) as ShardInfo;
|
99
138
|
|
100
|
-
if (!response)
|
139
|
+
if (!response) {
|
140
|
+
log.error("Error decoding metadata response");
|
141
|
+
return {
|
142
|
+
shardInfo: null,
|
143
|
+
error: ProtocolError.DECODE_FAILED
|
144
|
+
};
|
145
|
+
}
|
146
|
+
|
147
|
+
return {
|
148
|
+
shardInfo: response,
|
149
|
+
error: null
|
150
|
+
};
|
151
|
+
}
|
152
|
+
|
153
|
+
private async savePeerShardInfo(
|
154
|
+
peerId: PeerId,
|
155
|
+
shardInfo: ShardInfo
|
156
|
+
): Promise<void> {
|
157
|
+
// add or update the shardInfo to peer store
|
158
|
+
await this.libp2pComponents.peerStore.merge(peerId, {
|
159
|
+
metadata: {
|
160
|
+
shardInfo: encodeRelayShard(shardInfo)
|
161
|
+
}
|
162
|
+
});
|
101
163
|
|
102
|
-
|
164
|
+
this.handshakesConfirmed.set(peerId.toString(), shardInfo);
|
103
165
|
}
|
104
166
|
}
|
105
167
|
|
106
168
|
export function wakuMetadata(
|
107
|
-
shardInfo:
|
169
|
+
shardInfo: ShardInfo
|
108
170
|
): (components: Libp2pComponents) => IMetadata {
|
109
171
|
return (components: Libp2pComponents) => new Metadata(shardInfo, components);
|
110
172
|
}
|
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";
|
@@ -74,12 +73,10 @@ export interface QueryOptions {
|
|
74
73
|
* The Waku Store protocol can be used to retrieved historical messages.
|
75
74
|
*/
|
76
75
|
class Store extends BaseProtocol implements IStore {
|
77
|
-
private readonly pubsubTopics: PubsubTopic[];
|
78
76
|
private readonly NUM_PEERS_PROTOCOL = 1;
|
79
77
|
|
80
78
|
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
81
|
-
super(StoreCodec, libp2p.components);
|
82
|
-
this.pubsubTopics = this.initializePubsubTopic(options);
|
79
|
+
super(StoreCodec, libp2p.components, log, options!.pubsubTopics!, options);
|
83
80
|
}
|
84
81
|
|
85
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,20 @@
|
|
1
1
|
import type { IdentifyResult } from "@libp2p/interface";
|
2
|
-
import type {
|
2
|
+
import type {
|
3
|
+
IBaseProtocolCore,
|
4
|
+
IMetadata,
|
5
|
+
IRelay,
|
6
|
+
Waku
|
7
|
+
} from "@waku/interfaces";
|
3
8
|
import { Protocols } from "@waku/interfaces";
|
4
9
|
import { Logger } from "@waku/utils";
|
5
10
|
import { pEvent } from "p-event";
|
6
|
-
|
7
11
|
const log = new Logger("wait-for-remote-peer");
|
8
12
|
|
13
|
+
//TODO: move this function within the Waku class: https://github.com/waku-org/js-waku/issues/1761
|
9
14
|
/**
|
10
15
|
* Wait for a remote peer to be ready given the passed protocols.
|
11
16
|
* Must be used after attempting to connect to nodes, using
|
12
|
-
* {@link @waku/
|
17
|
+
* {@link @waku/sdk!WakuNode.dial} or a bootstrap method with
|
13
18
|
* {@link @waku/sdk!createLightNode}.
|
14
19
|
*
|
15
20
|
* If the passed protocols is a GossipSub protocol, then it resolves only once
|
@@ -45,19 +50,28 @@ export async function waitForRemotePeer(
|
|
45
50
|
if (protocols.includes(Protocols.Store)) {
|
46
51
|
if (!waku.store)
|
47
52
|
throw new Error("Cannot wait for Store peer: protocol not mounted");
|
48
|
-
promises.push(
|
53
|
+
promises.push(
|
54
|
+
waitForConnectedPeer(waku.store, waku.libp2p.services.metadata)
|
55
|
+
);
|
49
56
|
}
|
50
57
|
|
51
58
|
if (protocols.includes(Protocols.LightPush)) {
|
52
59
|
if (!waku.lightPush)
|
53
60
|
throw new Error("Cannot wait for LightPush peer: protocol not mounted");
|
54
|
-
promises.push(
|
61
|
+
promises.push(
|
62
|
+
waitForConnectedPeer(
|
63
|
+
waku.lightPush.protocol,
|
64
|
+
waku.libp2p.services.metadata
|
65
|
+
)
|
66
|
+
);
|
55
67
|
}
|
56
68
|
|
57
69
|
if (protocols.includes(Protocols.Filter)) {
|
58
70
|
if (!waku.filter)
|
59
71
|
throw new Error("Cannot wait for Filter peer: protocol not mounted");
|
60
|
-
promises.push(
|
72
|
+
promises.push(
|
73
|
+
waitForConnectedPeer(waku.filter, waku.libp2p.services.metadata)
|
74
|
+
);
|
61
75
|
}
|
62
76
|
|
63
77
|
if (timeoutMs) {
|
@@ -71,23 +85,65 @@ export async function waitForRemotePeer(
|
|
71
85
|
}
|
72
86
|
}
|
73
87
|
|
88
|
+
//TODO: move this function within protocol SDK class: https://github.com/waku-org/js-waku/issues/1761
|
74
89
|
/**
|
75
90
|
* Wait for a peer with the given protocol to be connected.
|
91
|
+
* If sharding is enabled on the node, it will also wait for the peer to be confirmed by the metadata service.
|
76
92
|
*/
|
77
|
-
async function waitForConnectedPeer(
|
93
|
+
async function waitForConnectedPeer(
|
94
|
+
protocol: IBaseProtocolCore,
|
95
|
+
metadataService?: IMetadata
|
96
|
+
): Promise<void> {
|
78
97
|
const codec = protocol.multicodec;
|
79
|
-
const peers = await protocol.
|
98
|
+
const peers = await protocol.connectedPeers();
|
80
99
|
|
81
100
|
if (peers.length) {
|
82
|
-
|
83
|
-
|
101
|
+
if (!metadataService) {
|
102
|
+
log.info(`${codec} peer found: `, peers[0].id.toString());
|
103
|
+
return;
|
104
|
+
}
|
105
|
+
|
106
|
+
// once a peer is connected, we need to confirm the metadata handshake with at least one of those peers if sharding is enabled
|
107
|
+
try {
|
108
|
+
await Promise.any(
|
109
|
+
peers.map((peer) => metadataService.confirmOrAttemptHandshake(peer.id))
|
110
|
+
);
|
111
|
+
return;
|
112
|
+
} catch (e) {
|
113
|
+
if ((e as any).code === "ERR_CONNECTION_BEING_CLOSED")
|
114
|
+
log.error(
|
115
|
+
`Connection with the peer was closed and possibly because it's on a different shard. Error: ${e}`
|
116
|
+
);
|
117
|
+
|
118
|
+
log.error(`Error waiting for handshake confirmation: ${e}`);
|
119
|
+
}
|
84
120
|
}
|
85
121
|
|
122
|
+
log.info(`Waiting for ${codec} peer`);
|
123
|
+
|
124
|
+
// else we'll just wait for the next peer to connect
|
86
125
|
await new Promise<void>((resolve) => {
|
87
126
|
const cb = (evt: CustomEvent<IdentifyResult>): void => {
|
88
127
|
if (evt.detail?.protocols?.includes(codec)) {
|
89
|
-
|
90
|
-
|
128
|
+
if (metadataService) {
|
129
|
+
metadataService
|
130
|
+
.confirmOrAttemptHandshake(evt.detail.peerId)
|
131
|
+
.then(() => {
|
132
|
+
protocol.removeLibp2pEventListener("peer:identify", cb);
|
133
|
+
resolve();
|
134
|
+
})
|
135
|
+
.catch((e) => {
|
136
|
+
if (e.code === "ERR_CONNECTION_BEING_CLOSED")
|
137
|
+
log.error(
|
138
|
+
`Connection with the peer was closed and possibly because it's on a different shard. Error: ${e}`
|
139
|
+
);
|
140
|
+
|
141
|
+
log.error(`Error waiting for handshake confirmation: ${e}`);
|
142
|
+
});
|
143
|
+
} else {
|
144
|
+
protocol.removeLibp2pEventListener("peer:identify", cb);
|
145
|
+
resolve();
|
146
|
+
}
|
91
147
|
}
|
92
148
|
};
|
93
149
|
protocol.addLibp2pEventListener("peer:identify", cb);
|