@aztec/p2p 1.2.1 → 2.0.0-nightly.20250813
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/dest/client/factory.d.ts +5 -1
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +29 -12
- package/dest/client/interface.d.ts +8 -13
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +18 -22
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +86 -83
- package/dest/config.d.ts +30 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +34 -1
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +13 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +117 -10
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +4 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +22 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +4 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +21 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +2 -10
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +8 -3
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +64 -37
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +8 -3
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +18 -10
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +11 -2
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +73 -44
- package/dest/msg_validators/attestation_validator/attestation_validator.js +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +2 -2
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +35 -59
- package/dest/msg_validators/tx_validator/double_spend_validator.js +2 -2
- package/dest/msg_validators/tx_validator/gas_validator.js +4 -4
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +21 -21
- package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +3 -3
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +4 -1
- package/dest/services/dummy_service.d.ts +13 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +26 -3
- package/dest/services/index.d.ts +3 -1
- package/dest/services/index.d.ts.map +1 -1
- package/dest/services/index.js +3 -1
- package/dest/services/libp2p/libp2p_service.d.ts +13 -20
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +123 -46
- package/dest/services/peer-manager/interface.d.ts +8 -1
- package/dest/services/peer-manager/interface.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts +70 -3
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +369 -39
- package/dest/services/reqresp/config.d.ts +3 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/config.js +3 -3
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +3 -4
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +35 -52
- package/dest/services/reqresp/index.d.ts +2 -1
- package/dest/services/reqresp/index.d.ts.map +1 -1
- package/dest/services/reqresp/index.js +2 -1
- package/dest/services/reqresp/interface.d.ts +61 -10
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +41 -6
- package/dest/services/reqresp/protocols/auth.d.ts +43 -0
- package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/auth.js +71 -0
- package/dest/services/reqresp/protocols/block.d.ts +5 -0
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.js +28 -5
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +39 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +49 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +75 -0
- package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
- package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
- package/dest/services/reqresp/protocols/goodbye.js +3 -5
- package/dest/services/reqresp/protocols/index.d.ts +2 -0
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +2 -0
- package/dest/services/reqresp/protocols/status.d.ts +2 -0
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +7 -0
- package/dest/services/reqresp/protocols/tx.d.ts +12 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +34 -6
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +20 -0
- package/dest/services/reqresp/reqresp.d.ts +37 -39
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +220 -220
- package/dest/services/reqresp/status.d.ts +8 -3
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/reqresp/status.js +6 -2
- package/dest/services/service.d.ts +10 -10
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +25 -0
- package/dest/services/tx_collection/config.d.ts.map +1 -0
- package/dest/services/tx_collection/config.js +58 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +56 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/fast_tx_collection.js +295 -0
- package/dest/services/tx_collection/index.d.ts +3 -0
- package/dest/services/tx_collection/index.d.ts.map +1 -0
- package/dest/services/tx_collection/index.js +2 -0
- package/dest/services/tx_collection/instrumentation.d.ts +10 -0
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
- package/dest/services/tx_collection/instrumentation.js +34 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +54 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/slow_tx_collection.js +176 -0
- package/dest/services/tx_collection/tx_collection.d.ts +109 -0
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_collection.js +127 -0
- package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_collection_sink.js +81 -0
- package/dest/services/tx_collection/tx_source.d.ts +18 -0
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_source.js +31 -0
- package/dest/services/tx_provider.d.ts +49 -0
- package/dest/services/tx_provider.d.ts.map +1 -0
- package/dest/services/tx_provider.js +206 -0
- package/dest/services/{tx_collect_instrumentation.d.ts → tx_provider_instrumentation.d.ts} +2 -2
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
- package/dest/services/{tx_collect_instrumentation.js → tx_provider_instrumentation.js} +5 -5
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +4 -3
- package/dest/test-helpers/mock-pubsub.d.ts +2 -1
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +2 -1
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +8 -4
- package/dest/testbench/p2p_client_testbench_worker.js +11 -5
- package/dest/util.d.ts +1 -1
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -15
- package/src/client/factory.ts +87 -12
- package/src/client/interface.ts +19 -15
- package/src/client/p2p_client.ts +108 -92
- package/src/config.ts +52 -1
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +15 -1
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +155 -4
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +28 -1
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +28 -2
- package/src/mem_pools/attestation_pool/mocks.ts +1 -3
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +59 -41
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +19 -9
- package/src/mem_pools/tx_pool/tx_pool.ts +7 -2
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +63 -40
- package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
- package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
- package/src/msg_validators/tx_validator/data_validator.ts +36 -27
- package/src/msg_validators/tx_validator/double_spend_validator.ts +2 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +4 -4
- package/src/msg_validators/tx_validator/metadata_validator.ts +22 -28
- package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -2
- package/src/services/discv5/discV5_service.ts +4 -1
- package/src/services/dummy_service.ts +44 -4
- package/src/services/index.ts +3 -1
- package/src/services/libp2p/libp2p_service.ts +147 -55
- package/src/services/peer-manager/interface.ts +10 -1
- package/src/services/peer-manager/peer_manager.ts +441 -41
- package/src/services/reqresp/config.ts +3 -3
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +38 -63
- package/src/services/reqresp/index.ts +2 -0
- package/src/services/reqresp/interface.ts +63 -17
- package/src/services/reqresp/protocols/auth.ts +83 -0
- package/src/services/reqresp/protocols/block.ts +24 -3
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -0
- package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
- package/src/services/reqresp/protocols/goodbye.ts +3 -3
- package/src/services/reqresp/protocols/index.ts +2 -0
- package/src/services/reqresp/protocols/status.ts +20 -0
- package/src/services/reqresp/protocols/tx.ts +35 -6
- package/src/services/reqresp/rate-limiter/rate_limits.ts +20 -0
- package/src/services/reqresp/reqresp.ts +294 -264
- package/src/services/reqresp/status.ts +9 -3
- package/src/services/service.ts +23 -14
- package/src/services/tx_collection/config.ts +84 -0
- package/src/services/tx_collection/fast_tx_collection.ts +338 -0
- package/src/services/tx_collection/index.ts +2 -0
- package/src/services/tx_collection/instrumentation.ts +43 -0
- package/src/services/tx_collection/slow_tx_collection.ts +232 -0
- package/src/services/tx_collection/tx_collection.ts +214 -0
- package/src/services/tx_collection/tx_collection_sink.ts +98 -0
- package/src/services/tx_collection/tx_source.ts +37 -0
- package/src/services/tx_provider.ts +215 -0
- package/src/services/{tx_collect_instrumentation.ts → tx_provider_instrumentation.ts} +5 -5
- package/src/test-helpers/make-test-p2p-clients.ts +4 -2
- package/src/test-helpers/mock-pubsub.ts +1 -0
- package/src/test-helpers/reqresp-nodes.ts +7 -1
- package/src/testbench/p2p_client_testbench_worker.ts +9 -2
- package/src/util.ts +1 -1
- package/dest/services/tx_collect_instrumentation.d.ts.map +0 -1
- package/dest/services/tx_collector.d.ts +0 -23
- package/dest/services/tx_collector.d.ts.map +0 -1
- package/dest/services/tx_collector.js +0 -95
- package/src/services/tx_collector.ts +0 -134
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type ConfigMapping, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
|
|
2
2
|
|
|
3
|
-
export const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS =
|
|
4
|
-
export const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS =
|
|
5
|
-
export const DEFAULT_REQRESP_DIAL_TIMEOUT_MS =
|
|
3
|
+
export const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS = 10_000;
|
|
4
|
+
export const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS = 10_000; // Not currently used
|
|
5
|
+
export const DEFAULT_REQRESP_DIAL_TIMEOUT_MS = 5_000;
|
|
6
6
|
export const DEFAULT_OPTIMISTIC_NEGOTIATION = false;
|
|
7
7
|
|
|
8
8
|
// For use in tests.
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { AbortError
|
|
1
|
+
import { AbortError } from '@aztec/foundation/error';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import { SerialQueue } from '@aztec/foundation/queue';
|
|
4
3
|
|
|
5
4
|
import type { Libp2p, PeerId, Stream } from '@libp2p/interface';
|
|
6
5
|
|
|
@@ -21,13 +20,14 @@ export class RandomSampler {
|
|
|
21
20
|
*/
|
|
22
21
|
export class ConnectionSampler {
|
|
23
22
|
private cleanupInterval: NodeJS.Timeout;
|
|
24
|
-
private dialAttempts: AbortController[] = [];
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
// Map from stringified peer id to number of active connections
|
|
25
|
+
protected readonly activeConnectionsCount: Map<string, number> = new Map();
|
|
28
26
|
|
|
29
|
-
//
|
|
30
|
-
|
|
27
|
+
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
28
|
+
protected readonly streams: Set<Stream> = new Set();
|
|
29
|
+
|
|
30
|
+
private abortOnStop: AbortController = new AbortController();
|
|
31
31
|
|
|
32
32
|
constructor(
|
|
33
33
|
private readonly libp2p: Libp2p,
|
|
@@ -39,8 +39,6 @@ export class ConnectionSampler {
|
|
|
39
39
|
() => void this.cleanupStaleConnections(),
|
|
40
40
|
this.opts.cleanupIntervalMs ?? 60_000,
|
|
41
41
|
);
|
|
42
|
-
|
|
43
|
-
this.dialQueue.start();
|
|
44
42
|
}
|
|
45
43
|
|
|
46
44
|
/**
|
|
@@ -48,14 +46,9 @@ export class ConnectionSampler {
|
|
|
48
46
|
*/
|
|
49
47
|
async stop() {
|
|
50
48
|
this.logger.info('Stopping connection sampler');
|
|
49
|
+
this.abortOnStop.abort(new AbortError('Connection sampler stopped'));
|
|
51
50
|
clearInterval(this.cleanupInterval);
|
|
52
51
|
|
|
53
|
-
for (const attempt of this.dialAttempts) {
|
|
54
|
-
attempt.abort(new AbortError('Connection sampler stopped'));
|
|
55
|
-
}
|
|
56
|
-
this.dialAttempts = [];
|
|
57
|
-
await this.dialQueue.end();
|
|
58
|
-
|
|
59
52
|
// Close all active streams
|
|
60
53
|
const closePromises = Array.from(this.streams.values()).map(stream => this.close(stream));
|
|
61
54
|
await Promise.all(closePromises);
|
|
@@ -103,7 +96,7 @@ export class ConnectionSampler {
|
|
|
103
96
|
for (let attempts = 0; attempts < MAX_SAMPLE_ATTEMPTS && peers.length > 0; attempts++) {
|
|
104
97
|
const randomIndex = this.sampler.random(peers.length);
|
|
105
98
|
const peer = peers[randomIndex];
|
|
106
|
-
const hasActiveConnections = (this.activeConnectionsCount.get(peer) ?? 0) > 0;
|
|
99
|
+
const hasActiveConnections = (this.activeConnectionsCount.get(peer.toString()) ?? 0) > 0;
|
|
107
100
|
const isExcluded = excluding?.get(peer.toString()) ?? false;
|
|
108
101
|
|
|
109
102
|
// Remove this peer from consideration
|
|
@@ -147,6 +140,7 @@ export class ConnectionSampler {
|
|
|
147
140
|
numberToSample = Math.min(numberToSample, peers.length);
|
|
148
141
|
|
|
149
142
|
const batch: PeerId[] = [];
|
|
143
|
+
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
150
144
|
const withActiveConnections: Set<PeerId> = new Set();
|
|
151
145
|
for (let i = 0; i < numberToSample; i++) {
|
|
152
146
|
const { peer, sampledPeers } = this.getPeerFromList(peers, excluding);
|
|
@@ -189,54 +183,33 @@ export class ConnectionSampler {
|
|
|
189
183
|
* @returns The stream
|
|
190
184
|
*/
|
|
191
185
|
async dialProtocol(peerId: PeerId, protocol: string, timeout?: number): Promise<Stream> {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const updatedActiveConnectionsCount = (this.activeConnectionsCount.get(peerId) ?? 0) + 1;
|
|
214
|
-
this.activeConnectionsCount.set(peerId, updatedActiveConnectionsCount);
|
|
215
|
-
|
|
216
|
-
this.logger.trace('Dialed protocol', {
|
|
217
|
-
streamId: stream.id,
|
|
218
|
-
protocol,
|
|
219
|
-
peerId: peerId.toString(),
|
|
220
|
-
activeConnectionsCount: updatedActiveConnectionsCount,
|
|
221
|
-
});
|
|
222
|
-
return stream;
|
|
223
|
-
} finally {
|
|
224
|
-
if (timeoutHandle) {
|
|
225
|
-
clearTimeout(timeoutHandle);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const idx = this.dialAttempts.indexOf(abortController);
|
|
229
|
-
if (idx > -1) {
|
|
230
|
-
this.dialAttempts.splice(idx, 1);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
186
|
+
const stream = await this.libp2p.dialProtocol(peerId, protocol, {
|
|
187
|
+
signal: AbortSignal.any(
|
|
188
|
+
timeout ? [this.abortOnStop.signal, AbortSignal.timeout(timeout!)] : [this.abortOnStop.signal],
|
|
189
|
+
),
|
|
190
|
+
negotiateFully: !this.opts.p2pOptimisticNegotiation,
|
|
191
|
+
});
|
|
192
|
+
stream.metadata.peerId = peerId;
|
|
193
|
+
this.streams.add(stream);
|
|
194
|
+
|
|
195
|
+
const peerIdString = peerId.toString();
|
|
196
|
+
const updatedActiveConnectionsCount = (this.activeConnectionsCount.get(peerIdString) ?? 0) + 1;
|
|
197
|
+
this.activeConnectionsCount.set(peerIdString, updatedActiveConnectionsCount);
|
|
198
|
+
|
|
199
|
+
this.logger.trace('Dialed protocol', {
|
|
200
|
+
streamId: stream.id,
|
|
201
|
+
protocol,
|
|
202
|
+
peerId: peerIdString,
|
|
203
|
+
activeConnectionsCount: updatedActiveConnectionsCount,
|
|
204
|
+
});
|
|
205
|
+
return stream;
|
|
233
206
|
}
|
|
234
207
|
|
|
235
208
|
/**
|
|
236
209
|
* Closes a stream and updates the active connections count
|
|
237
210
|
*/
|
|
238
211
|
async close(stream: Stream): Promise<void> {
|
|
239
|
-
let peerId = undefined;
|
|
212
|
+
let peerId: PeerId | undefined = undefined;
|
|
240
213
|
|
|
241
214
|
try {
|
|
242
215
|
peerId = stream.metadata.peerId;
|
|
@@ -245,13 +218,13 @@ export class ConnectionSampler {
|
|
|
245
218
|
if (!peerId) {
|
|
246
219
|
this.logger.warn(`Stream ${stream.id} does not have a peerId set`);
|
|
247
220
|
} else {
|
|
248
|
-
updatedActiveConnectionsCount = (this.activeConnectionsCount.get(peerId) ?? 1) - 1;
|
|
249
|
-
this.activeConnectionsCount.set(peerId, updatedActiveConnectionsCount);
|
|
221
|
+
updatedActiveConnectionsCount = (this.activeConnectionsCount.get(peerId.toString()) ?? 1) - 1;
|
|
222
|
+
this.activeConnectionsCount.set(peerId.toString(), updatedActiveConnectionsCount);
|
|
250
223
|
}
|
|
251
224
|
|
|
252
225
|
this.logger.trace('Closing connection', {
|
|
253
226
|
streamId: stream.id,
|
|
254
|
-
peerId: peerId
|
|
227
|
+
peerId: peerId?.toString(),
|
|
255
228
|
protocol: stream.protocol,
|
|
256
229
|
activeConnectionsCount: updatedActiveConnectionsCount,
|
|
257
230
|
});
|
|
@@ -263,6 +236,8 @@ export class ConnectionSampler {
|
|
|
263
236
|
await stream.close();
|
|
264
237
|
} catch (error) {
|
|
265
238
|
this.logger.error(`Failed to close connection to peer ${peerId ?? 'unknown'} with stream id ${stream.id}`, error);
|
|
239
|
+
// graceful close failed, abort the stream
|
|
240
|
+
stream.abort(new AbortError('Failed to close stream gracefully'));
|
|
266
241
|
} finally {
|
|
267
242
|
this.streams.delete(stream);
|
|
268
243
|
}
|
|
@@ -277,10 +252,10 @@ export class ConnectionSampler {
|
|
|
277
252
|
for (const stream of this.streams.values()) {
|
|
278
253
|
try {
|
|
279
254
|
// Check if we have lost track of accounting
|
|
280
|
-
const peerId = stream.metadata.peerId;
|
|
255
|
+
const peerId: PeerId = stream.metadata.peerId;
|
|
281
256
|
if (!peerId) {
|
|
282
257
|
this.logger.warn(`Stream ${stream.id} does not have a peerId set`);
|
|
283
|
-
} else if (this.activeConnectionsCount.get(peerId) === 0) {
|
|
258
|
+
} else if (this.activeConnectionsCount.get(peerId.toString()) === 0) {
|
|
284
259
|
await this.close(stream);
|
|
285
260
|
this.logger.debug('Cleaned up stale connection', { streamId: stream.id, peerId: peerId.toString() });
|
|
286
261
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import { L2Block } from '@aztec/stdlib/block';
|
|
3
|
-
import {
|
|
3
|
+
import { TxArray, TxHashArray } from '@aztec/stdlib/tx';
|
|
4
4
|
|
|
5
5
|
import type { PeerId } from '@libp2p/interface';
|
|
6
6
|
|
|
7
7
|
import type { P2PReqRespConfig } from './config.js';
|
|
8
|
+
import { AuthRequest, AuthResponse } from './protocols/auth.js';
|
|
9
|
+
import { BlockTxsRequest, BlockTxsResponse } from './protocols/block_txs/block_txs_reqresp.js';
|
|
8
10
|
import { StatusMessage } from './protocols/status.js';
|
|
9
11
|
import type { ReqRespStatus } from './status.js';
|
|
10
12
|
|
|
@@ -16,6 +18,8 @@ export const STATUS_PROTOCOL = '/aztec/req/status/0.1.0';
|
|
|
16
18
|
export const GOODBYE_PROTOCOL = '/aztec/req/goodbye/0.1.0';
|
|
17
19
|
export const TX_REQ_PROTOCOL = '/aztec/req/tx/0.1.0';
|
|
18
20
|
export const BLOCK_REQ_PROTOCOL = '/aztec/req/block/0.1.0';
|
|
21
|
+
export const AUTH_PROTOCOL = '/aztec/req/auth/0.1.0';
|
|
22
|
+
export const BLOCK_TXS_REQ_PROTOCOL = '/aztec/req/block_txs/0.1.0';
|
|
19
23
|
|
|
20
24
|
export enum ReqRespSubProtocol {
|
|
21
25
|
PING = PING_PROTOCOL,
|
|
@@ -23,6 +27,8 @@ export enum ReqRespSubProtocol {
|
|
|
23
27
|
GOODBYE = GOODBYE_PROTOCOL,
|
|
24
28
|
TX = TX_REQ_PROTOCOL,
|
|
25
29
|
BLOCK = BLOCK_REQ_PROTOCOL,
|
|
30
|
+
AUTH = AUTH_PROTOCOL,
|
|
31
|
+
BLOCK_TXS = BLOCK_TXS_REQ_PROTOCOL,
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
/**
|
|
@@ -38,12 +44,12 @@ export type ReqRespSubProtocolRateLimits = Record<ReqRespSubProtocol, ProtocolRa
|
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
46
|
* The response from the ReqResp protocol
|
|
41
|
-
* Consists of a status
|
|
47
|
+
* Consists of a status
|
|
48
|
+
* And, optionally, a data buffer (in case status is SUCCESS)
|
|
42
49
|
*/
|
|
43
|
-
export
|
|
44
|
-
status: ReqRespStatus;
|
|
45
|
-
|
|
46
|
-
}
|
|
50
|
+
export type ReqRespResponse =
|
|
51
|
+
| { status: ReqRespStatus.SUCCESS; data: Buffer }
|
|
52
|
+
| { status: Exclude<ReqRespStatus, ReqRespStatus.SUCCESS> };
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
55
|
* A rate limit quota
|
|
@@ -93,21 +99,34 @@ export const DEFAULT_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
|
|
|
93
99
|
[ReqRespSubProtocol.TX]: noopValidator,
|
|
94
100
|
[ReqRespSubProtocol.GOODBYE]: noopValidator,
|
|
95
101
|
[ReqRespSubProtocol.BLOCK]: noopValidator,
|
|
102
|
+
[ReqRespSubProtocol.AUTH]: noopValidator,
|
|
103
|
+
[ReqRespSubProtocol.BLOCK_TXS]: noopValidator,
|
|
96
104
|
};
|
|
97
105
|
|
|
106
|
+
/*
|
|
107
|
+
* Helper class to sub-protocol validation error*/
|
|
108
|
+
export class ValidationError extends Error {
|
|
109
|
+
constructor(message: string) {
|
|
110
|
+
super(message);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
98
114
|
/**
|
|
99
115
|
* Sub protocol map determines the request and response types for each
|
|
100
116
|
* Req Resp protocol
|
|
101
117
|
*/
|
|
102
118
|
export type SubProtocolMap = {
|
|
103
|
-
[S in ReqRespSubProtocol]: RequestResponsePair<
|
|
119
|
+
[S in ReqRespSubProtocol]: RequestResponsePair<
|
|
120
|
+
InstanceType<(typeof subProtocolMap)[S]['request']>,
|
|
121
|
+
InstanceType<(typeof subProtocolMap)[S]['response']>
|
|
122
|
+
>;
|
|
104
123
|
};
|
|
105
124
|
|
|
106
125
|
/**
|
|
107
126
|
* Default handler for unimplemented sub protocols, this SHOULD be overwritten
|
|
108
127
|
* by the service, but is provided as a fallback
|
|
109
128
|
*/
|
|
110
|
-
const defaultHandler = (_msg: any): Promise<Buffer> => {
|
|
129
|
+
export const defaultHandler = (_msg: any): Promise<Buffer> => {
|
|
111
130
|
return Promise.resolve(Buffer.from('unimplemented'));
|
|
112
131
|
};
|
|
113
132
|
|
|
@@ -120,6 +139,8 @@ export const DEFAULT_SUB_PROTOCOL_HANDLERS: ReqRespSubProtocolHandlers = {
|
|
|
120
139
|
[ReqRespSubProtocol.TX]: defaultHandler,
|
|
121
140
|
[ReqRespSubProtocol.GOODBYE]: defaultHandler,
|
|
122
141
|
[ReqRespSubProtocol.BLOCK]: defaultHandler,
|
|
142
|
+
[ReqRespSubProtocol.AUTH]: defaultHandler,
|
|
143
|
+
[ReqRespSubProtocol.BLOCK_TXS]: defaultHandler,
|
|
123
144
|
};
|
|
124
145
|
|
|
125
146
|
/**
|
|
@@ -140,6 +161,22 @@ interface RequestResponsePair<Req extends { toBuffer(): Buffer }, Res> {
|
|
|
140
161
|
};
|
|
141
162
|
}
|
|
142
163
|
|
|
164
|
+
/*
|
|
165
|
+
* Small helper function which parses buffer into specific response type
|
|
166
|
+
* It is needed to make TypeScript happy, as it cannot infer the type from the buffer
|
|
167
|
+
*
|
|
168
|
+
* @param proto - The sub protocol to parse the response for
|
|
169
|
+
* @param buffer - The buffer to parse
|
|
170
|
+
*
|
|
171
|
+
* @returns - The parsed response object
|
|
172
|
+
* */
|
|
173
|
+
export function responseFromBuffer<P extends ReqRespSubProtocol>(
|
|
174
|
+
proto: P,
|
|
175
|
+
buffer: Buffer,
|
|
176
|
+
): InstanceType<(typeof subProtocolMap)[P]['response']> {
|
|
177
|
+
return subProtocolMap[proto].response.fromBuffer(buffer) as InstanceType<(typeof subProtocolMap)[P]['response']>;
|
|
178
|
+
}
|
|
179
|
+
|
|
143
180
|
/**
|
|
144
181
|
* RequestableBuffer is a wrapper around a buffer that allows it to be
|
|
145
182
|
* used in generic request response protocols
|
|
@@ -163,7 +200,7 @@ export class RequestableBuffer {
|
|
|
163
200
|
* This defines the request and response types for each sub protocol, used primarily
|
|
164
201
|
* as a type rather than an object
|
|
165
202
|
*/
|
|
166
|
-
export const subProtocolMap
|
|
203
|
+
export const subProtocolMap = {
|
|
167
204
|
[ReqRespSubProtocol.PING]: {
|
|
168
205
|
request: RequestableBuffer,
|
|
169
206
|
response: RequestableBuffer,
|
|
@@ -173,8 +210,8 @@ export const subProtocolMap: SubProtocolMap = {
|
|
|
173
210
|
response: StatusMessage,
|
|
174
211
|
},
|
|
175
212
|
[ReqRespSubProtocol.TX]: {
|
|
176
|
-
request:
|
|
177
|
-
response:
|
|
213
|
+
request: TxHashArray,
|
|
214
|
+
response: TxArray,
|
|
178
215
|
},
|
|
179
216
|
[ReqRespSubProtocol.GOODBYE]: {
|
|
180
217
|
request: RequestableBuffer,
|
|
@@ -184,18 +221,27 @@ export const subProtocolMap: SubProtocolMap = {
|
|
|
184
221
|
request: Fr, // block number
|
|
185
222
|
response: L2Block,
|
|
186
223
|
},
|
|
224
|
+
[ReqRespSubProtocol.AUTH]: {
|
|
225
|
+
request: AuthRequest,
|
|
226
|
+
response: AuthResponse,
|
|
227
|
+
},
|
|
228
|
+
[ReqRespSubProtocol.BLOCK_TXS]: {
|
|
229
|
+
request: BlockTxsRequest,
|
|
230
|
+
response: BlockTxsResponse,
|
|
231
|
+
},
|
|
187
232
|
};
|
|
188
233
|
|
|
189
234
|
export interface ReqRespInterface {
|
|
190
235
|
start(
|
|
191
|
-
subProtocolHandlers: ReqRespSubProtocolHandlers
|
|
236
|
+
subProtocolHandlers: Partial<ReqRespSubProtocolHandlers>,
|
|
192
237
|
subProtocolValidators: ReqRespSubProtocolValidators,
|
|
193
238
|
): Promise<void>;
|
|
239
|
+
addSubProtocol(
|
|
240
|
+
subProtocol: ReqRespSubProtocol,
|
|
241
|
+
handler: ReqRespSubProtocolHandler,
|
|
242
|
+
validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
|
|
243
|
+
): Promise<void>;
|
|
194
244
|
stop(): Promise<void>;
|
|
195
|
-
sendRequest<SubProtocol extends ReqRespSubProtocol>(
|
|
196
|
-
subProtocol: SubProtocol,
|
|
197
|
-
request: InstanceType<SubProtocolMap[SubProtocol]['request']>,
|
|
198
|
-
): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined>;
|
|
199
245
|
sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
|
|
200
246
|
subProtocol: SubProtocol,
|
|
201
247
|
requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
|
|
@@ -203,7 +249,7 @@ export interface ReqRespInterface {
|
|
|
203
249
|
timeoutMs?: number,
|
|
204
250
|
maxPeers?: number,
|
|
205
251
|
maxRetryAttempts?: number,
|
|
206
|
-
): Promise<
|
|
252
|
+
): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]>;
|
|
207
253
|
sendRequestToPeer(
|
|
208
254
|
peerId: PeerId,
|
|
209
255
|
subProtocol: ReqRespSubProtocol,
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
2
|
+
import { keccak256 } from '@aztec/foundation/crypto';
|
|
3
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
4
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
+
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
6
|
+
|
|
7
|
+
import { StatusMessage } from './status.js';
|
|
8
|
+
|
|
9
|
+
export const VALIDATOR_AUTH_DOMAIN_SEPARATOR = 'Aztec Validator Challenge:';
|
|
10
|
+
export const VALIDATOR_AUTH_FULL_CHALLENGE_ENCODED_LENGTH =
|
|
11
|
+
VALIDATOR_AUTH_DOMAIN_SEPARATOR.length + Fr.random().toString().length;
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* P2P Auth Message
|
|
15
|
+
* Superset of the StatusMessage, used to establish a handshake between peers and authenticate them.
|
|
16
|
+
*/
|
|
17
|
+
export class AuthRequest {
|
|
18
|
+
constructor(
|
|
19
|
+
readonly status: StatusMessage,
|
|
20
|
+
readonly challenge: Fr,
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Deserializes the AuthRequest object from a Buffer.
|
|
25
|
+
* @param buffer - Buffer or BufferReader object to deserialize.
|
|
26
|
+
* @returns An instance of StatusMessage.
|
|
27
|
+
*/
|
|
28
|
+
static fromBuffer(buffer: Buffer | BufferReader): AuthRequest {
|
|
29
|
+
const reader = BufferReader.asReader(buffer);
|
|
30
|
+
return new AuthRequest(
|
|
31
|
+
StatusMessage.fromBuffer(reader), // Deserialize StatusMessage
|
|
32
|
+
Fr.fromBuffer(reader), // challenge
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Serializes the AuthRequest object into a Buffer.
|
|
38
|
+
* @returns Buffer representation of the StatusMessage object.
|
|
39
|
+
*/
|
|
40
|
+
toBuffer() {
|
|
41
|
+
return serializeToBuffer([this.status, this.challenge]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getPayloadToSign(): Buffer32 {
|
|
45
|
+
const fullChallenge = VALIDATOR_AUTH_DOMAIN_SEPARATOR + this.challenge.toString();
|
|
46
|
+
return Buffer32.fromBuffer(keccak256(Buffer.from(fullChallenge, 'utf-8')));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static random(): AuthRequest {
|
|
50
|
+
return new AuthRequest(StatusMessage.random(), Fr.random());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class AuthResponse {
|
|
55
|
+
constructor(
|
|
56
|
+
readonly status: StatusMessage,
|
|
57
|
+
readonly signature: Signature,
|
|
58
|
+
) {}
|
|
59
|
+
/**
|
|
60
|
+
* Deserializes the AuthResponse object from a Buffer.
|
|
61
|
+
* @param buffer - Buffer or BufferReader object to deserialize.
|
|
62
|
+
* @returns An instance of StatusMessage.
|
|
63
|
+
*/
|
|
64
|
+
static fromBuffer(buffer: Buffer | BufferReader): AuthResponse {
|
|
65
|
+
const reader = BufferReader.asReader(buffer);
|
|
66
|
+
return new AuthResponse(
|
|
67
|
+
StatusMessage.fromBuffer(reader), // Deserialize StatusMessage
|
|
68
|
+
Signature.fromBuffer(reader), // response
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Serializes the AuthRequest object into a Buffer.
|
|
74
|
+
* @returns Buffer representation of the StatusMessage object.
|
|
75
|
+
*/
|
|
76
|
+
toBuffer() {
|
|
77
|
+
return serializeToBuffer([this.status, this.signature]);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static random(): AuthResponse {
|
|
81
|
+
return new AuthResponse(StatusMessage.random(), Signature.random());
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -4,12 +4,33 @@ import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
|
4
4
|
import type { PeerId } from '@libp2p/interface';
|
|
5
5
|
|
|
6
6
|
import type { ReqRespSubProtocolHandler } from '../interface.js';
|
|
7
|
+
import { ReqRespStatus, ReqRespStatusError } from '../status.js';
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Handler for L2 Block requests
|
|
11
|
+
* @param l2BlockSource - source for L2 blocks
|
|
12
|
+
* @returns the Block request handler
|
|
13
|
+
* */
|
|
8
14
|
export function reqRespBlockHandler(l2BlockSource: L2BlockSource): ReqRespSubProtocolHandler {
|
|
15
|
+
/**
|
|
16
|
+
* @param peerId - the peer ID of the requester
|
|
17
|
+
* @param msg - the block request message, which is expected to contain valid block number as a Buffer
|
|
18
|
+
* @returns a Buffer containing the requested block data, or an empty Buffer if the block is not found
|
|
19
|
+
* @throws ReqRespStatusError if the input msg is not a valid block number
|
|
20
|
+
* */
|
|
9
21
|
return async (_peerId: PeerId, msg: Buffer) => {
|
|
10
|
-
|
|
22
|
+
let blockNumber: Fr;
|
|
23
|
+
try {
|
|
24
|
+
blockNumber = Fr.fromBuffer(msg);
|
|
25
|
+
} catch (err: any) {
|
|
26
|
+
throw new ReqRespStatusError(ReqRespStatus.BADLY_FORMED_REQUEST, { cause: err });
|
|
27
|
+
}
|
|
11
28
|
|
|
12
|
-
|
|
13
|
-
|
|
29
|
+
try {
|
|
30
|
+
const foundBlock = await l2BlockSource.getBlock(Number(blockNumber));
|
|
31
|
+
return foundBlock ? foundBlock.toBuffer() : Buffer.alloc(0);
|
|
32
|
+
} catch (err: any) {
|
|
33
|
+
throw new ReqRespStatusError(ReqRespStatus.INTERNAL_ERROR, { cause: err });
|
|
34
|
+
}
|
|
14
35
|
};
|
|
15
36
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* BitVector helper class for representing and serializing bit vectors
|
|
5
|
+
*/
|
|
6
|
+
export class BitVector {
|
|
7
|
+
private buffer: Buffer;
|
|
8
|
+
private length: number;
|
|
9
|
+
|
|
10
|
+
constructor(buffer: Buffer, length: number) {
|
|
11
|
+
this.buffer = buffer;
|
|
12
|
+
this.length = length;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* Creates new BitVector instance
|
|
17
|
+
* @param length - Length of the bit vector
|
|
18
|
+
* @param indices - Array of indices to set to 1 in the bit vector
|
|
19
|
+
*
|
|
20
|
+
* @returns A new BitVector instance with specified length and set indices
|
|
21
|
+
* */
|
|
22
|
+
static init(length: number, indices: number[]): BitVector {
|
|
23
|
+
if (indices.length > length) {
|
|
24
|
+
throw new Error('Indices length exceeds specified length');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const buffer = Buffer.alloc(BitVector.byteLength(length));
|
|
28
|
+
|
|
29
|
+
indices.forEach(idx => {
|
|
30
|
+
const invalidIndex = idx < 0 || idx >= length;
|
|
31
|
+
if (invalidIndex) {
|
|
32
|
+
throw new Error(`Index ${idx} is out of bounds for BitVector of length ${length}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const byteIndex = Math.floor(idx / 8);
|
|
36
|
+
const bitIndex = idx % 8;
|
|
37
|
+
buffer[byteIndex] |= 1 << bitIndex;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return new BitVector(buffer, length);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getLength(): number {
|
|
44
|
+
return this.length;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* Checks if element at index is set to true
|
|
49
|
+
*
|
|
50
|
+
* @param index - Index of the bit to check
|
|
51
|
+
*
|
|
52
|
+
* @returns True if the bit at index is set, false otherwise
|
|
53
|
+
* */
|
|
54
|
+
isSet(index: number): boolean {
|
|
55
|
+
return index >= 0 && index < this.length && !!(this.buffer[Math.floor(index / 8)] & (1 << index % 8));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Returns all indices which are set to true
|
|
60
|
+
* */
|
|
61
|
+
getTrueIndices(): number[] {
|
|
62
|
+
return Array.from({ length: this.length }, (_, i) => i).filter(i => this.isSet(i));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Serializes the BitVector object into a Buffer
|
|
67
|
+
*
|
|
68
|
+
* @returns Buffer representation of the BitVector object
|
|
69
|
+
* */
|
|
70
|
+
toBuffer(): Buffer {
|
|
71
|
+
return serializeToBuffer([this.length, this.buffer]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Deserializes buffer into new BitVector
|
|
76
|
+
*
|
|
77
|
+
* @returns A new BitVector instance
|
|
78
|
+
* */
|
|
79
|
+
static fromBuffer(buffer: Buffer | BufferReader): BitVector {
|
|
80
|
+
const reader = BufferReader.asReader(buffer);
|
|
81
|
+
const length = reader.readNumber();
|
|
82
|
+
|
|
83
|
+
const bitBuffer = reader.readBytes(BitVector.byteLength(length));
|
|
84
|
+
return new BitVector(bitBuffer, length);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static byteLength(length: number) {
|
|
88
|
+
return Math.ceil(length / 8);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { TxArray } from '@aztec/stdlib/tx';
|
|
2
|
+
|
|
3
|
+
import type { PeerId } from '@libp2p/interface';
|
|
4
|
+
|
|
5
|
+
import type { AttestationPool } from '../../../../mem_pools/attestation_pool/attestation_pool.js';
|
|
6
|
+
import type { TxPool } from '../../../../mem_pools/index.js';
|
|
7
|
+
import type { ReqRespSubProtocolHandler } from '../../interface.js';
|
|
8
|
+
import { ReqRespStatus, ReqRespStatusError } from '../../status.js';
|
|
9
|
+
import { BitVector } from './bitvector.js';
|
|
10
|
+
import { BlockTxsRequest, BlockTxsResponse } from './block_txs_reqresp.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Handler for block txs requests
|
|
14
|
+
* @param attestationPool - the attestation pool to check for block proposals
|
|
15
|
+
* @param mempools - the mempools containing the tx pool
|
|
16
|
+
* @returns the BlockTxs request handler
|
|
17
|
+
*/
|
|
18
|
+
export function reqRespBlockTxsHandler(attestationPool: AttestationPool, txPool: TxPool): ReqRespSubProtocolHandler {
|
|
19
|
+
/**
|
|
20
|
+
* Handler for block txs requests
|
|
21
|
+
* @param msg - the block txs request message
|
|
22
|
+
* @returns the block txs response message
|
|
23
|
+
* @throws if msg is not a valid block txs request
|
|
24
|
+
*/
|
|
25
|
+
return async (_peerId: PeerId, msg: Buffer) => {
|
|
26
|
+
let request: BlockTxsRequest;
|
|
27
|
+
try {
|
|
28
|
+
request = BlockTxsRequest.fromBuffer(msg);
|
|
29
|
+
} catch (err: any) {
|
|
30
|
+
throw new ReqRespStatusError(ReqRespStatus.BADLY_FORMED_REQUEST, { cause: err });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const blockProposal = await attestationPool.getBlockProposal(request.blockHash.toString());
|
|
34
|
+
|
|
35
|
+
if (!blockProposal) {
|
|
36
|
+
throw new ReqRespStatusError(ReqRespStatus.NOT_FOUND);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const txsAvailableInPool = await txPool.hasTxs(blockProposal.txHashes);
|
|
40
|
+
//Map txs in the pool to their indices in the block proposal
|
|
41
|
+
const availableIndices = txsAvailableInPool.map((hasTx, idx) => (hasTx ? idx : -1)).filter(idx => idx !== -1);
|
|
42
|
+
const responseBitVector = BitVector.init(blockProposal.txHashes.length, availableIndices);
|
|
43
|
+
|
|
44
|
+
const requestedIndices = new Set(request.txIndices.getTrueIndices());
|
|
45
|
+
const requestedTxsHashes = blockProposal.txHashes.filter((_, idx) => requestedIndices.has(idx));
|
|
46
|
+
|
|
47
|
+
const responseTxs = (await txPool.getTxsByHash(requestedTxsHashes)).filter(tx => !!tx);
|
|
48
|
+
|
|
49
|
+
const response = new BlockTxsResponse(request.blockHash, new TxArray(...responseTxs), responseBitVector);
|
|
50
|
+
|
|
51
|
+
return response.toBuffer();
|
|
52
|
+
};
|
|
53
|
+
}
|