@waku/core 0.0.27 → 0.0.28-b5e8b17.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/bundle/{base_protocol-LhsIWF3-.js → base_protocol-BCwLeb-A.js} +2 -5
- package/bundle/{browser-BQyFvtq6.js → browser-DoQRY-an.js} +18 -13
- package/bundle/{index-8YyfzF9R.js → index-vlQahmUj.js} +3 -1
- package/bundle/index.js +153 -98
- 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-FXfzO8Km.js → version_0-DiakMc1A.js} +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/base_protocol.d.ts +4 -5
- package/dist/lib/base_protocol.js +0 -3
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/filter/index.js +4 -0
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/light_push/index.d.ts +12 -2
- package/dist/lib/light_push/index.js +79 -76
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/metadata/index.d.ts +1 -1
- package/dist/lib/metadata/index.js +42 -14
- package/dist/lib/metadata/index.js.map +1 -1
- package/dist/lib/wait_for_remote_peer.js +3 -1
- package/dist/lib/wait_for_remote_peer.js.map +1 -1
- package/package.json +1 -129
- package/src/index.ts +1 -1
- package/src/lib/base_protocol.ts +4 -9
- package/src/lib/filter/index.ts +7 -0
- package/src/lib/light_push/index.ts +97 -118
- package/src/lib/metadata/index.ts +56 -26
- package/src/lib/wait_for_remote_peer.ts +13 -3
@@ -1,18 +1,16 @@
|
|
1
|
-
import type { PeerId, Stream } from "@libp2p/interface";
|
1
|
+
import type { Peer, PeerId, Stream } from "@libp2p/interface";
|
2
2
|
import {
|
3
|
+
Failure,
|
4
|
+
IBaseProtocolCore,
|
3
5
|
IEncoder,
|
4
|
-
ILightPush,
|
5
6
|
IMessage,
|
6
7
|
Libp2p,
|
7
8
|
ProtocolCreateOptions,
|
8
|
-
|
9
|
-
|
9
|
+
ProtocolError,
|
10
|
+
ProtocolResult
|
10
11
|
} from "@waku/interfaces";
|
11
12
|
import { PushResponse } from "@waku/proto";
|
12
|
-
import {
|
13
|
-
ensurePubsubTopicIsConfigured,
|
14
|
-
isMessageSizeUnderCap
|
15
|
-
} from "@waku/utils";
|
13
|
+
import { isMessageSizeUnderCap } from "@waku/utils";
|
16
14
|
import { Logger } from "@waku/utils";
|
17
15
|
import all from "it-all";
|
18
16
|
import * as lp from "it-length-prefixed";
|
@@ -28,20 +26,14 @@ const log = new Logger("light-push");
|
|
28
26
|
export const LightPushCodec = "/vac/waku/lightpush/2.0.0-beta1";
|
29
27
|
export { PushResponse };
|
30
28
|
|
31
|
-
type PreparePushMessageResult =
|
32
|
-
|
33
|
-
|
34
|
-
error: null;
|
35
|
-
}
|
36
|
-
| {
|
37
|
-
query: null;
|
38
|
-
error: SendError;
|
39
|
-
};
|
29
|
+
type PreparePushMessageResult = ProtocolResult<"query", PushRpc>;
|
30
|
+
|
31
|
+
type CoreSendResult = ProtocolResult<"success", PeerId, "failure", Failure>;
|
40
32
|
|
41
33
|
/**
|
42
34
|
* Implements the [Waku v2 Light Push protocol](https://rfc.vac.dev/spec/19/).
|
43
35
|
*/
|
44
|
-
class
|
36
|
+
export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
|
45
37
|
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
46
38
|
super(
|
47
39
|
LightPushCodec,
|
@@ -54,18 +46,17 @@ class LightPush extends BaseProtocol implements ILightPush {
|
|
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,132 +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
|
-
|
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
|
+
);
|
117
111
|
return {
|
118
|
-
|
119
|
-
|
112
|
+
success: null,
|
113
|
+
failure: {
|
114
|
+
error: ProtocolError.REMOTE_PEER_FAULT,
|
115
|
+
peerId: peer.id
|
116
|
+
}
|
120
117
|
};
|
121
118
|
}
|
122
119
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
async (source) => await all(source)
|
143
|
-
);
|
144
|
-
} catch (err) {
|
145
|
-
log.error("Failed to send waku light push request", err);
|
146
|
-
return { recipients, error: SendError.GENERIC_FAIL };
|
147
|
-
}
|
148
|
-
|
149
|
-
const bytes = new Uint8ArrayList();
|
150
|
-
res.forEach((chunk) => {
|
151
|
-
bytes.append(chunk);
|
152
|
-
});
|
153
|
-
|
154
|
-
let response: PushResponse | undefined;
|
155
|
-
try {
|
156
|
-
response = PushRpc.decode(bytes).response;
|
157
|
-
} catch (err) {
|
158
|
-
log.error("Failed to decode push reply", err);
|
159
|
-
return { recipients, error: SendError.DECODE_FAILED };
|
160
|
-
}
|
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
|
+
}
|
161
139
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
140
|
+
const bytes = new Uint8ArrayList();
|
141
|
+
res.forEach((chunk) => {
|
142
|
+
bytes.append(chunk);
|
143
|
+
});
|
166
144
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
+
}
|
171
158
|
|
172
|
-
|
173
|
-
|
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
|
+
}
|
174
169
|
|
175
|
-
|
176
|
-
|
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
|
+
}
|
177
180
|
|
178
|
-
|
179
|
-
|
180
|
-
// TODO: handle renewing faulty peers with new peers (https://github.com/waku-org/js-waku/issues/1463)
|
181
|
-
const errors = results
|
182
|
-
.filter(
|
183
|
-
(
|
184
|
-
result
|
185
|
-
): result is PromiseFulfilledResult<{
|
186
|
-
recipients: PeerId[];
|
187
|
-
error: SendError | undefined;
|
188
|
-
}> => result.status === "fulfilled"
|
189
|
-
)
|
190
|
-
.map((result) => result.value.error)
|
191
|
-
.filter((error) => error !== undefined) as SendError[];
|
192
|
-
|
193
|
-
return {
|
194
|
-
recipients,
|
195
|
-
errors
|
196
|
-
};
|
181
|
+
return { success: peer.id, failure: null };
|
197
182
|
}
|
198
183
|
}
|
199
|
-
|
200
|
-
export function wakuLightPush(
|
201
|
-
init: Partial<ProtocolCreateOptions> = {}
|
202
|
-
): (libp2p: Libp2p) => ILightPush {
|
203
|
-
return (libp2p: Libp2p) => new LightPush(libp2p, init);
|
204
|
-
}
|
@@ -1,10 +1,12 @@
|
|
1
1
|
import type { PeerId } from "@libp2p/interface";
|
2
2
|
import { IncomingStreamData } from "@libp2p/interface";
|
3
|
-
import
|
4
|
-
IMetadata,
|
5
|
-
Libp2pComponents,
|
6
|
-
PeerIdStr,
|
7
|
-
|
3
|
+
import {
|
4
|
+
type IMetadata,
|
5
|
+
type Libp2pComponents,
|
6
|
+
type PeerIdStr,
|
7
|
+
ProtocolError,
|
8
|
+
QueryResult,
|
9
|
+
type ShardInfo
|
8
10
|
} from "@waku/interfaces";
|
9
11
|
import { proto_metadata } from "@waku/proto";
|
10
12
|
import { encodeRelayShard, Logger, shardInfoToPubsubTopics } from "@waku/utils";
|
@@ -21,7 +23,7 @@ export const MetadataCodec = "/vac/waku/metadata/1.0.0";
|
|
21
23
|
|
22
24
|
class Metadata extends BaseProtocol implements IMetadata {
|
23
25
|
private libp2pComponents: Libp2pComponents;
|
24
|
-
handshakesConfirmed:
|
26
|
+
handshakesConfirmed: Map<PeerIdStr, ShardInfo> = new Map();
|
25
27
|
|
26
28
|
constructor(
|
27
29
|
public shardInfo: ShardInfo,
|
@@ -57,13 +59,13 @@ class Metadata extends BaseProtocol implements IMetadata {
|
|
57
59
|
async (source) => await all(source)
|
58
60
|
);
|
59
61
|
|
60
|
-
const
|
61
|
-
this.decodeMetadataResponse(encodedResponse);
|
62
|
+
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
if (error) {
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
|
68
|
+
await this.savePeerShardInfo(connection.remotePeer, shardInfo);
|
67
69
|
} catch (error) {
|
68
70
|
log.error("Error handling metadata request", error);
|
69
71
|
}
|
@@ -72,12 +74,15 @@ class Metadata extends BaseProtocol implements IMetadata {
|
|
72
74
|
/**
|
73
75
|
* Make a metadata query to a peer
|
74
76
|
*/
|
75
|
-
async query(peerId: PeerId): Promise<
|
77
|
+
async query(peerId: PeerId): Promise<QueryResult> {
|
76
78
|
const request = proto_metadata.WakuMetadataRequest.encode(this.shardInfo);
|
77
79
|
|
78
80
|
const peer = await this.peerStore.get(peerId);
|
79
81
|
if (!peer) {
|
80
|
-
|
82
|
+
return {
|
83
|
+
shardInfo: null,
|
84
|
+
error: ProtocolError.NO_PEER_AVAILABLE
|
85
|
+
};
|
81
86
|
}
|
82
87
|
|
83
88
|
const stream = await this.getStream(peer);
|
@@ -90,22 +95,38 @@ class Metadata extends BaseProtocol implements IMetadata {
|
|
90
95
|
async (source) => await all(source)
|
91
96
|
);
|
92
97
|
|
93
|
-
const
|
98
|
+
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
|
99
|
+
|
100
|
+
if (error) {
|
101
|
+
return {
|
102
|
+
shardInfo: null,
|
103
|
+
error
|
104
|
+
};
|
105
|
+
}
|
94
106
|
|
95
|
-
await this.savePeerShardInfo(peerId,
|
107
|
+
await this.savePeerShardInfo(peerId, shardInfo);
|
96
108
|
|
97
|
-
return
|
109
|
+
return {
|
110
|
+
shardInfo,
|
111
|
+
error: null
|
112
|
+
};
|
98
113
|
}
|
99
114
|
|
100
|
-
public async confirmOrAttemptHandshake(peerId: PeerId): Promise<
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
+
}
|
104
123
|
|
105
|
-
return;
|
124
|
+
return await this.query(peerId);
|
106
125
|
}
|
107
126
|
|
108
|
-
private decodeMetadataResponse(
|
127
|
+
private decodeMetadataResponse(
|
128
|
+
encodedResponse: Uint8ArrayList[]
|
129
|
+
): QueryResult {
|
109
130
|
const bytes = new Uint8ArrayList();
|
110
131
|
|
111
132
|
encodedResponse.forEach((chunk) => {
|
@@ -115,9 +136,18 @@ class Metadata extends BaseProtocol implements IMetadata {
|
|
115
136
|
bytes
|
116
137
|
) as ShardInfo;
|
117
138
|
|
118
|
-
if (!response)
|
139
|
+
if (!response) {
|
140
|
+
log.error("Error decoding metadata response");
|
141
|
+
return {
|
142
|
+
shardInfo: null,
|
143
|
+
error: ProtocolError.DECODE_FAILED
|
144
|
+
};
|
145
|
+
}
|
119
146
|
|
120
|
-
return
|
147
|
+
return {
|
148
|
+
shardInfo: response,
|
149
|
+
error: null
|
150
|
+
};
|
121
151
|
}
|
122
152
|
|
123
153
|
private async savePeerShardInfo(
|
@@ -131,7 +161,7 @@ class Metadata extends BaseProtocol implements IMetadata {
|
|
131
161
|
}
|
132
162
|
});
|
133
163
|
|
134
|
-
this.handshakesConfirmed.
|
164
|
+
this.handshakesConfirmed.set(peerId.toString(), shardInfo);
|
135
165
|
}
|
136
166
|
}
|
137
167
|
|
@@ -1,10 +1,16 @@
|
|
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
11
|
const log = new Logger("wait-for-remote-peer");
|
7
12
|
|
13
|
+
//TODO: move this function within the Waku class: https://github.com/waku-org/js-waku/issues/1761
|
8
14
|
/**
|
9
15
|
* Wait for a remote peer to be ready given the passed protocols.
|
10
16
|
* Must be used after attempting to connect to nodes, using
|
@@ -53,7 +59,10 @@ export async function waitForRemotePeer(
|
|
53
59
|
if (!waku.lightPush)
|
54
60
|
throw new Error("Cannot wait for LightPush peer: protocol not mounted");
|
55
61
|
promises.push(
|
56
|
-
waitForConnectedPeer(
|
62
|
+
waitForConnectedPeer(
|
63
|
+
waku.lightPush.protocol,
|
64
|
+
waku.libp2p.services.metadata
|
65
|
+
)
|
57
66
|
);
|
58
67
|
}
|
59
68
|
|
@@ -76,12 +85,13 @@ export async function waitForRemotePeer(
|
|
76
85
|
}
|
77
86
|
}
|
78
87
|
|
88
|
+
//TODO: move this function within protocol SDK class: https://github.com/waku-org/js-waku/issues/1761
|
79
89
|
/**
|
80
90
|
* Wait for a peer with the given protocol to be connected.
|
81
91
|
* If sharding is enabled on the node, it will also wait for the peer to be confirmed by the metadata service.
|
82
92
|
*/
|
83
93
|
async function waitForConnectedPeer(
|
84
|
-
protocol:
|
94
|
+
protocol: IBaseProtocolCore,
|
85
95
|
metadataService?: IMetadata
|
86
96
|
): Promise<void> {
|
87
97
|
const codec = protocol.multicodec;
|