@aztec/p2p 0.0.1-commit.9ef841308 → 0.0.1-commit.a89ec08
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 +2 -2
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +1 -2
- package/dest/client/p2p_client.d.ts +1 -1
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +4 -6
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -17
- package/dest/config.d.ts +6 -6
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +6 -6
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -4
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +4 -8
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
- package/dest/mem_pools/index.d.ts +2 -1
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.d.ts +2 -4
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +14 -16
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +125 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +596 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +123 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
- package/dest/mem_pools/tx_pool/index.d.ts +3 -0
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/index.js +2 -0
- package/dest/mem_pools/tx_pool/priority.d.ts +12 -0
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/priority.js +15 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +127 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool.js +3 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +7 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +402 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +5 -7
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +0 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +6 -5
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +1 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +43 -26
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +0 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +1 -18
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +4 -5
- package/dest/msg_validators/clock_tolerance.d.ts +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +3 -4
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +5 -5
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
- package/dest/services/discv5/discV5_service.d.ts +1 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +2 -4
- package/dest/services/libp2p/libp2p_service.d.ts +9 -7
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +59 -137
- package/dest/services/peer-manager/metrics.d.ts +1 -3
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +0 -6
- package/dest/services/peer-manager/peer_manager.d.ts +2 -6
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +9 -24
- package/dest/services/peer-manager/peer_scoring.d.ts +2 -5
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +10 -28
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +8 -11
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +101 -82
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -3
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +4 -5
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +7 -13
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +11 -19
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +15 -52
- package/dest/services/reqresp/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +3 -4
- package/dest/services/service.d.ts +1 -7
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +73 -57
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
- package/dest/services/tx_collection/slow_tx_collection.js +1 -1
- package/dest/services/tx_collection/tx_collection.d.ts +6 -3
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +1 -6
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +1 -9
- package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.d.ts +1 -1
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +2 -20
- package/dest/testbench/p2p_client_testbench_worker.js +15 -44
- package/dest/testbench/worker_client_manager.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +2 -2
- package/dest/util.d.ts +4 -9
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +9 -2
- package/package.json +14 -14
- package/src/client/factory.ts +2 -3
- package/src/client/p2p_client.ts +4 -6
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +9 -19
- package/src/config.ts +10 -10
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +7 -8
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
- package/src/mem_pools/index.ts +3 -0
- package/src/mem_pools/instrumentation.ts +13 -17
- package/src/mem_pools/tx_pool/README.md +270 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +746 -0
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +163 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
- package/src/mem_pools/tx_pool/index.ts +2 -0
- package/src/mem_pools/tx_pool/priority.ts +20 -0
- package/src/mem_pools/tx_pool/tx_pool.ts +141 -0
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +321 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +4 -7
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +5 -11
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +43 -29
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +0 -3
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1 -19
- package/src/msg_validators/attestation_validator/README.md +1 -1
- package/src/msg_validators/attestation_validator/attestation_validator.ts +4 -5
- package/src/msg_validators/clock_tolerance.ts +3 -4
- package/src/msg_validators/proposal_validator/README.md +4 -4
- package/src/msg_validators/proposal_validator/proposal_validator.ts +5 -6
- package/src/msg_validators/tx_validator/metadata_validator.ts +4 -12
- package/src/services/discv5/discV5_service.ts +2 -4
- package/src/services/libp2p/libp2p_service.ts +71 -135
- package/src/services/peer-manager/metrics.ts +0 -7
- package/src/services/peer-manager/peer_manager.ts +9 -28
- package/src/services/peer-manager/peer_scoring.ts +5 -21
- package/src/services/reqresp/batch-tx-requester/README.md +7 -46
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +111 -78
- package/src/services/reqresp/batch-tx-requester/interface.ts +1 -2
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +6 -13
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +24 -68
- package/src/services/reqresp/reqresp.ts +3 -5
- package/src/services/service.ts +0 -7
- package/src/services/tx_collection/fast_tx_collection.ts +83 -57
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +13 -8
- package/src/services/tx_collection/slow_tx_collection.ts +1 -1
- package/src/services/tx_collection/tx_collection.ts +5 -3
- package/src/test-helpers/make-test-p2p-clients.ts +1 -1
- package/src/test-helpers/mock-pubsub.ts +0 -9
- package/src/test-helpers/reqresp-nodes.ts +1 -1
- package/src/test-helpers/testbench-utils.ts +3 -28
- package/src/testbench/p2p_client_testbench_worker.ts +15 -44
- package/src/testbench/worker_client_manager.ts +2 -2
- package/src/util.ts +13 -9
- package/dest/services/tx_collection/request_tracker.d.ts +0 -53
- package/dest/services/tx_collection/request_tracker.d.ts.map +0 -1
- package/dest/services/tx_collection/request_tracker.js +0 -84
- package/src/services/tx_collection/request_tracker.ts +0 -127
|
@@ -2,23 +2,18 @@ import type { DateProvider } from '@aztec/foundation/timer';
|
|
|
2
2
|
import type { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
3
3
|
|
|
4
4
|
import type { PeerId } from '@libp2p/interface';
|
|
5
|
-
import { peerIdFromString } from '@libp2p/peer-id';
|
|
6
5
|
|
|
7
|
-
import type { ConnectionSampler } from '../connection-sampler/connection_sampler.js';
|
|
8
6
|
import { DEFAULT_BATCH_TX_REQUESTER_BAD_PEER_THRESHOLD } from './config.js';
|
|
9
7
|
import type { IPeerPenalizer } from './interface.js';
|
|
10
8
|
|
|
11
9
|
export const RATE_LIMIT_EXCEEDED_PEER_CACHE_TTL = 1000; // 1s
|
|
12
10
|
|
|
13
11
|
export interface IPeerCollection {
|
|
12
|
+
getAllPeers(): Set<string>;
|
|
13
|
+
getSmartPeers(): Set<string>;
|
|
14
14
|
markPeerSmart(peerId: PeerId): void;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/** Sample next peer in round-robin fashion. No smart peers if returns undefined */
|
|
18
|
-
nextSmartPeerToQuery(): PeerId | undefined;
|
|
19
|
-
/** Sample next peer in round-robin fashion. No dumb peers if returns undefined */
|
|
20
|
-
nextDumbPeerToQuery(): PeerId | undefined;
|
|
21
|
-
|
|
15
|
+
getSmartPeersToQuery(): Array<string>;
|
|
16
|
+
getDumbPeersToQuery(): Array<string>;
|
|
22
17
|
thereAreSomeDumbRatelimitExceededPeers(): boolean;
|
|
23
18
|
penalisePeer(peerId: PeerId, severity: PeerErrorSeverity): void;
|
|
24
19
|
unMarkPeerAsBad(peerId: PeerId): void;
|
|
@@ -33,6 +28,8 @@ export interface IPeerCollection {
|
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
export class PeerCollection implements IPeerCollection {
|
|
31
|
+
private readonly peers;
|
|
32
|
+
|
|
36
33
|
private readonly smartPeers = new Set<string>();
|
|
37
34
|
private readonly inFlightPeers = new Set<string>();
|
|
38
35
|
private readonly rateLimitExceededPeers = new Map<string, number>();
|
|
@@ -40,64 +37,46 @@ export class PeerCollection implements IPeerCollection {
|
|
|
40
37
|
private readonly badPeers = new Set<string>();
|
|
41
38
|
|
|
42
39
|
constructor(
|
|
43
|
-
|
|
40
|
+
initialPeers: PeerId[],
|
|
44
41
|
private readonly pinnedPeerId: PeerId | undefined,
|
|
45
42
|
private readonly dateProvider: DateProvider,
|
|
46
43
|
private readonly badPeerThreshold: number = DEFAULT_BATCH_TX_REQUESTER_BAD_PEER_THRESHOLD,
|
|
47
44
|
private readonly peerPenalizer?: IPeerPenalizer,
|
|
48
45
|
) {
|
|
49
|
-
|
|
46
|
+
this.peers = new Set(initialPeers.map(peer => peer.toString()));
|
|
47
|
+
|
|
48
|
+
// Pinned peer is treaded specially, always mark it as in-flight
|
|
50
49
|
// and never return it as part of smart/dumb peers
|
|
51
50
|
if (this.pinnedPeerId) {
|
|
52
51
|
const peerIdStr = this.pinnedPeerId.toString();
|
|
53
52
|
this.inFlightPeers.add(peerIdStr);
|
|
53
|
+
this.peers.delete(peerIdStr);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
public
|
|
58
|
-
this.
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public markPeerDumb(peerId: PeerId): void {
|
|
62
|
-
this.smartPeers.delete(peerId.toString());
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// We keep track of all peers that are queried for peer sampling algorithm
|
|
66
|
-
private queriedSmartPeers: Set<string> = new Set<string>();
|
|
67
|
-
private queriedDumbPeers: Set<string> = new Set<string>();
|
|
68
|
-
|
|
69
|
-
private static nextPeer(allPeers: Set<string>, queried: Set<string>): PeerId | undefined {
|
|
70
|
-
if (allPeers.size === 0) {
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
const availablePeers = allPeers.difference(queried);
|
|
74
|
-
let [first] = availablePeers;
|
|
75
|
-
if (first === undefined) {
|
|
76
|
-
// We queried all peers. Start over
|
|
77
|
-
[first] = allPeers;
|
|
78
|
-
queried.clear();
|
|
79
|
-
}
|
|
80
|
-
queried.add(first);
|
|
81
|
-
return peerIdFromString(first);
|
|
57
|
+
public getAllPeers(): Set<string> {
|
|
58
|
+
return this.peers;
|
|
82
59
|
}
|
|
83
60
|
|
|
84
|
-
public
|
|
85
|
-
return
|
|
61
|
+
public getSmartPeers(): Set<string> {
|
|
62
|
+
return this.smartPeers;
|
|
86
63
|
}
|
|
87
64
|
|
|
88
|
-
public
|
|
89
|
-
|
|
65
|
+
public markPeerSmart(peerId: PeerId): void {
|
|
66
|
+
this.smartPeers.add(peerId.toString());
|
|
90
67
|
}
|
|
91
68
|
|
|
92
|
-
|
|
93
|
-
return
|
|
69
|
+
public getSmartPeersToQuery(): Array<string> {
|
|
70
|
+
return Array.from(
|
|
94
71
|
this.smartPeers.difference(this.getBadPeers().union(this.inFlightPeers).union(this.getRateLimitExceededPeers())),
|
|
95
72
|
);
|
|
96
73
|
}
|
|
97
74
|
|
|
98
|
-
|
|
99
|
-
return
|
|
100
|
-
this.
|
|
75
|
+
public getDumbPeersToQuery(): Array<string> {
|
|
76
|
+
return Array.from(
|
|
77
|
+
this.peers.difference(
|
|
78
|
+
this.smartPeers.union(this.getBadPeers()).union(this.inFlightPeers).union(this.getRateLimitExceededPeers()),
|
|
79
|
+
),
|
|
101
80
|
);
|
|
102
81
|
}
|
|
103
82
|
|
|
@@ -223,27 +202,4 @@ export class PeerCollection implements IPeerCollection {
|
|
|
223
202
|
|
|
224
203
|
return minExpiry! - now;
|
|
225
204
|
}
|
|
226
|
-
|
|
227
|
-
private orderedPeers: Set<string> = new Set();
|
|
228
|
-
|
|
229
|
-
private get peers(): Set<string> {
|
|
230
|
-
const pinnedStr = this.pinnedPeerId?.toString();
|
|
231
|
-
const currentlyConnected = new Set(
|
|
232
|
-
this.connectionSampler
|
|
233
|
-
.getPeerListSortedByConnectionCountAsc()
|
|
234
|
-
.map(p => p.toString())
|
|
235
|
-
.filter(p => p !== pinnedStr),
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
// Remove disconnected peers, preserving order of the rest.
|
|
239
|
-
this.orderedPeers = this.orderedPeers.intersection(currentlyConnected);
|
|
240
|
-
|
|
241
|
-
// Append newly connected peers at the end (lowest priority).
|
|
242
|
-
for (const peer of currentlyConnected) {
|
|
243
|
-
if (!this.orderedPeers.has(peer)) {
|
|
244
|
-
this.orderedPeers.add(peer);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return this.orderedPeers;
|
|
248
|
-
}
|
|
249
205
|
}
|
|
@@ -320,7 +320,7 @@ export class ReqResp implements ReqRespInterface {
|
|
|
320
320
|
};
|
|
321
321
|
|
|
322
322
|
for (const index of indices) {
|
|
323
|
-
this.logger.
|
|
323
|
+
this.logger.info(`Sending request ${index} to peer ${peerAsString}`);
|
|
324
324
|
const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffers[index]);
|
|
325
325
|
|
|
326
326
|
// Check the status of the response buffer
|
|
@@ -462,7 +462,7 @@ export class ReqResp implements ReqRespInterface {
|
|
|
462
462
|
);
|
|
463
463
|
return resp;
|
|
464
464
|
} catch (e: any) {
|
|
465
|
-
this.logger.
|
|
465
|
+
this.logger.debug(`SUBPROTOCOL: ${subProtocol}\n`, e);
|
|
466
466
|
// On error we immediately abort the stream, this is preferred way,
|
|
467
467
|
// because it signals to the sender that error happened, whereas
|
|
468
468
|
// closing the stream only closes our side and is much slower
|
|
@@ -621,9 +621,7 @@ export class ReqResp implements ReqRespInterface {
|
|
|
621
621
|
// and that this stream should be dropped
|
|
622
622
|
const isMessageToNotWarn =
|
|
623
623
|
err instanceof Error &&
|
|
624
|
-
['stream reset', 'Cannot push value onto an ended pushable'
|
|
625
|
-
err.message.includes(msg),
|
|
626
|
-
);
|
|
624
|
+
['stream reset', 'Cannot push value onto an ended pushable'].some(msg => err.message.includes(msg));
|
|
627
625
|
const level = isMessageToNotWarn ? 'debug' : 'warn';
|
|
628
626
|
this.logger[level]('Unknown stream error while handling the stream, aborting', {
|
|
629
627
|
protocol,
|
package/src/services/service.ts
CHANGED
|
@@ -196,13 +196,6 @@ export interface PeerDiscoveryService extends EventEmitter {
|
|
|
196
196
|
on(event: 'peer:discovered', listener: (enr: ENR) => void): this;
|
|
197
197
|
emit(event: 'peer:discovered', enr: ENR): boolean;
|
|
198
198
|
|
|
199
|
-
/**
|
|
200
|
-
* Event emitted when our public IP is discovered or changes via discv5 peer interactions.
|
|
201
|
-
* Only emitted when enrUpdate is enabled (i.e. queryForIp=true and no static p2pIp).
|
|
202
|
-
*/
|
|
203
|
-
on(event: 'ip:changed', listener: (ip: string) => void): this;
|
|
204
|
-
emit(event: 'ip:changed', ip: string): boolean;
|
|
205
|
-
|
|
206
199
|
getStatus(): PeerDiscoveryState;
|
|
207
200
|
|
|
208
201
|
getEnr(): ENR | undefined;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { times } from '@aztec/foundation/collection';
|
|
3
|
+
import { AbortError, TimeoutError } from '@aztec/foundation/error';
|
|
3
4
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
4
6
|
import { sleep } from '@aztec/foundation/sleep';
|
|
5
7
|
import { DateProvider, elapsed } from '@aztec/foundation/timer';
|
|
6
8
|
import type { L2BlockInfo } from '@aztec/stdlib/block';
|
|
9
|
+
import type { BlockProposal } from '@aztec/stdlib/p2p';
|
|
7
10
|
import { type Tx, TxHash } from '@aztec/stdlib/tx';
|
|
8
11
|
|
|
9
12
|
import type { PeerId } from '@libp2p/interface';
|
|
@@ -11,12 +14,12 @@ import type { PeerId } from '@libp2p/interface';
|
|
|
11
14
|
import type { BatchTxRequesterConfig } from '../reqresp/batch-tx-requester/config.js';
|
|
12
15
|
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
13
16
|
import type { TxCollectionConfig } from './config.js';
|
|
17
|
+
import { MissingTxsTracker } from './missing_txs_tracker.js';
|
|
14
18
|
import {
|
|
15
19
|
BatchTxRequesterCollector,
|
|
16
20
|
type MissingTxsCollector,
|
|
17
21
|
SendBatchRequestCollector,
|
|
18
22
|
} from './proposal_tx_collector.js';
|
|
19
|
-
import { RequestTracker } from './request_tracker.js';
|
|
20
23
|
import type { FastCollectionRequest, FastCollectionRequestInput } from './tx_collection.js';
|
|
21
24
|
import type { TxAddContext, TxCollectionSink } from './tx_collection_sink.js';
|
|
22
25
|
import type { TxSource } from './tx_source.js';
|
|
@@ -45,9 +48,7 @@ export class FastTxCollection {
|
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
public async stop() {
|
|
48
|
-
this.requests.forEach(request =>
|
|
49
|
-
request.requestTracker.cancel();
|
|
50
|
-
});
|
|
51
|
+
this.requests.forEach(request => request.promise.reject(new AbortError(`Stopped collection service`)));
|
|
51
52
|
await Promise.resolve();
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -74,65 +75,81 @@ export class FastTxCollection {
|
|
|
74
75
|
? { ...input.blockProposal.toBlockInfo(), blockNumber: input.blockNumber }
|
|
75
76
|
: { ...input.block.toBlockInfo() };
|
|
76
77
|
|
|
78
|
+
// This promise is used to await for the collection to finish during the main collectFast method.
|
|
79
|
+
// It gets resolved in `foundTxs` when all txs have been collected, or rejected if the request is aborted or hits the deadline.
|
|
80
|
+
const promise = promiseWithResolvers<void>();
|
|
81
|
+
const timeoutTimer = setTimeout(() => promise.reject(new TimeoutError(`Timed out while collecting txs`)), timeout);
|
|
82
|
+
|
|
77
83
|
const request: FastCollectionRequest = {
|
|
78
84
|
...input,
|
|
79
85
|
blockInfo,
|
|
80
|
-
|
|
86
|
+
promise,
|
|
87
|
+
missingTxTracker: MissingTxsTracker.fromArray(txHashes),
|
|
88
|
+
deadline: opts.deadline,
|
|
81
89
|
};
|
|
82
90
|
|
|
83
91
|
const [duration] = await elapsed(() => this.collectFast(request, { ...opts }));
|
|
92
|
+
clearTimeout(timeoutTimer);
|
|
84
93
|
|
|
85
94
|
this.log.verbose(
|
|
86
|
-
`Collected ${request.
|
|
95
|
+
`Collected ${request.missingTxTracker.collectedTxs.length} txs out of ${txHashes.length} for ${input.type} at slot ${blockInfo.slotNumber}`,
|
|
87
96
|
{
|
|
88
97
|
...blockInfo,
|
|
89
98
|
duration,
|
|
90
99
|
requestType: input.type,
|
|
91
|
-
missingTxs: [...request.
|
|
100
|
+
missingTxs: [...request.missingTxTracker.missingTxHashes],
|
|
92
101
|
},
|
|
93
102
|
);
|
|
94
|
-
return request.
|
|
103
|
+
return request.missingTxTracker.collectedTxs;
|
|
95
104
|
}
|
|
96
105
|
|
|
97
|
-
protected async collectFast(
|
|
106
|
+
protected async collectFast(
|
|
107
|
+
request: FastCollectionRequest,
|
|
108
|
+
opts: { proposal?: BlockProposal; deadline: Date; pinnedPeer?: PeerId },
|
|
109
|
+
) {
|
|
98
110
|
this.requests.add(request);
|
|
99
111
|
const { blockInfo } = request;
|
|
100
112
|
|
|
101
113
|
this.log.debug(
|
|
102
|
-
`Starting fast collection of ${request.
|
|
103
|
-
{ ...blockInfo, requestType: request.type, deadline:
|
|
114
|
+
`Starting fast collection of ${request.missingTxTracker.numberOfMissingTxs} txs for ${request.type} at slot ${blockInfo.slotNumber}`,
|
|
115
|
+
{ ...blockInfo, requestType: request.type, deadline: opts.deadline },
|
|
104
116
|
);
|
|
105
117
|
|
|
106
118
|
try {
|
|
107
119
|
// Start blasting all nodes for the txs. We give them a little time to respond before we start reqresp.
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
const nodeCollectionPromise = this.collectFastFromNodes(request);
|
|
120
|
+
// And keep an eye on the request promise to ensure we don't wait longer than the deadline or return as soon
|
|
121
|
+
// as we have collected all txs, whatever the source.
|
|
122
|
+
const nodeCollectionPromise = this.collectFastFromNodes(request, opts);
|
|
111
123
|
const waitBeforeReqResp = sleep(this.config.txCollectionFastNodesTimeoutBeforeReqRespMs);
|
|
112
|
-
await Promise.race([request.
|
|
124
|
+
await Promise.race([request.promise.promise, waitBeforeReqResp]);
|
|
113
125
|
|
|
114
|
-
// If we have collected all txs
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (request.requestTracker.allFetched()) {
|
|
118
|
-
this.log.debug(`All txs collected for slot ${blockInfo.slotNumber} without reqresp`, blockInfo);
|
|
119
|
-
}
|
|
120
|
-
await nodeCollectionPromise;
|
|
126
|
+
// If we have collected all txs, we can stop here
|
|
127
|
+
if (request.missingTxTracker.allFetched()) {
|
|
128
|
+
this.log.debug(`All txs collected for slot ${blockInfo.slotNumber} without reqresp`, blockInfo);
|
|
121
129
|
return;
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
// Start blasting reqresp for the remaining txs. Note that node collection keeps running in parallel.
|
|
125
133
|
// We stop when we have collected all txs, timed out, or both node collection and reqresp have given up.
|
|
126
|
-
|
|
127
|
-
await Promise.
|
|
134
|
+
const collectionPromise = Promise.allSettled([this.collectFastViaReqResp(request, opts), nodeCollectionPromise]);
|
|
135
|
+
await Promise.race([collectionPromise, request.promise.promise]);
|
|
128
136
|
} catch (err) {
|
|
129
|
-
|
|
137
|
+
// Log and swallow all errors
|
|
138
|
+
const logCtx = {
|
|
130
139
|
...blockInfo,
|
|
131
|
-
|
|
132
|
-
|
|
140
|
+
errorMessage: err instanceof Error ? err.message : undefined,
|
|
141
|
+
missingTxs: request.missingTxTracker.missingTxHashes.values().map(txHash => txHash.toString()),
|
|
142
|
+
};
|
|
143
|
+
if (err instanceof Error && err.name === 'TimeoutError') {
|
|
144
|
+
this.log.warn(`Timed out collecting txs for ${request.type} at slot ${blockInfo.slotNumber}`, logCtx);
|
|
145
|
+
} else if (err instanceof Error && err.name === 'AbortError') {
|
|
146
|
+
this.log.warn(`Aborted collecting txs for ${request.type} at slot ${blockInfo.slotNumber}`, logCtx);
|
|
147
|
+
} else {
|
|
148
|
+
this.log.error(`Error collecting txs for ${request.type} for slot ${blockInfo.slotNumber}`, err, logCtx);
|
|
149
|
+
}
|
|
133
150
|
} finally {
|
|
134
151
|
// Ensure no unresolved promises and remove the request from the set
|
|
135
|
-
request.
|
|
152
|
+
request.promise.resolve();
|
|
136
153
|
this.requests.delete(request);
|
|
137
154
|
}
|
|
138
155
|
}
|
|
@@ -143,28 +160,30 @@ export class FastTxCollection {
|
|
|
143
160
|
* the txs that have been requested less often whenever we need to send a new batch of requests. We ensure that no
|
|
144
161
|
* tx is requested more than once at the same time to the same node.
|
|
145
162
|
*/
|
|
146
|
-
private async collectFastFromNodes(request: FastCollectionRequest): Promise<void> {
|
|
163
|
+
private async collectFastFromNodes(request: FastCollectionRequest, opts: { deadline: Date }): Promise<void> {
|
|
147
164
|
if (this.nodes.length === 0) {
|
|
148
165
|
return;
|
|
149
166
|
}
|
|
150
167
|
|
|
151
168
|
// Keep a shared priority queue of all txs pending to be requested, sorted by the number of attempts made to collect them.
|
|
152
|
-
const attemptsPerTx = [...request.
|
|
169
|
+
const attemptsPerTx = [...request.missingTxTracker.missingTxHashes].map(txHash => ({
|
|
153
170
|
txHash,
|
|
154
171
|
attempts: 0,
|
|
155
172
|
found: false,
|
|
156
173
|
}));
|
|
157
174
|
|
|
158
175
|
// Returns once we have finished all node loops. Each loop finishes when the deadline is hit, or all txs have been collected.
|
|
159
|
-
await Promise.allSettled(this.nodes.map(node => this.collectFastFromNode(request, node, attemptsPerTx)));
|
|
176
|
+
await Promise.allSettled(this.nodes.map(node => this.collectFastFromNode(request, node, attemptsPerTx, opts)));
|
|
160
177
|
}
|
|
161
178
|
|
|
162
179
|
private async collectFastFromNode(
|
|
163
180
|
request: FastCollectionRequest,
|
|
164
181
|
node: TxSource,
|
|
165
182
|
attemptsPerTx: { txHash: string; attempts: number; found: boolean }[],
|
|
183
|
+
opts: { deadline: Date },
|
|
166
184
|
) {
|
|
167
|
-
const notFinished = () =>
|
|
185
|
+
const notFinished = () =>
|
|
186
|
+
this.dateProvider.now() <= +opts.deadline && !request.missingTxTracker.allFetched() && this.requests.has(request);
|
|
168
187
|
|
|
169
188
|
const maxParallelRequests = this.config.txCollectionFastMaxParallelRequestsPerNode;
|
|
170
189
|
const maxBatchSize = this.config.txCollectionNodeRpcMaxBatchSize;
|
|
@@ -181,7 +200,7 @@ export class FastTxCollection {
|
|
|
181
200
|
if (!txToRequest) {
|
|
182
201
|
// No more txs to process
|
|
183
202
|
break;
|
|
184
|
-
} else if (!request.
|
|
203
|
+
} else if (!request.missingTxTracker.isMissing(txToRequest.txHash)) {
|
|
185
204
|
// Mark as found if it was found somewhere else, we'll then remove it from the array.
|
|
186
205
|
// We don't delete it now since 'array.splice' is pretty expensive, so we do it after sorting.
|
|
187
206
|
txToRequest.found = true;
|
|
@@ -216,7 +235,7 @@ export class FastTxCollection {
|
|
|
216
235
|
async () => {
|
|
217
236
|
const result = await node.getTxsByHash(txHashes.map(TxHash.fromString));
|
|
218
237
|
for (const tx of result.validTxs) {
|
|
219
|
-
request.
|
|
238
|
+
request.missingTxTracker.markFetched(tx);
|
|
220
239
|
}
|
|
221
240
|
return result;
|
|
222
241
|
},
|
|
@@ -235,12 +254,9 @@ export class FastTxCollection {
|
|
|
235
254
|
activeRequestsToThisNode.delete(requestedTx.txHash);
|
|
236
255
|
}
|
|
237
256
|
|
|
238
|
-
// Sleep a bit until hitting the node again
|
|
257
|
+
// Sleep a bit until hitting the node again (or not, depending on config)
|
|
239
258
|
if (notFinished()) {
|
|
240
|
-
await
|
|
241
|
-
sleep(this.config.txCollectionFastNodeIntervalMs),
|
|
242
|
-
request.requestTracker.cancellationToken,
|
|
243
|
-
]);
|
|
259
|
+
await sleep(this.config.txCollectionFastNodeIntervalMs);
|
|
244
260
|
}
|
|
245
261
|
}
|
|
246
262
|
};
|
|
@@ -250,20 +266,21 @@ export class FastTxCollection {
|
|
|
250
266
|
}
|
|
251
267
|
|
|
252
268
|
private async collectFastViaReqResp(request: FastCollectionRequest, opts: { pinnedPeer?: PeerId }) {
|
|
269
|
+
const timeoutMs = +request.deadline - this.dateProvider.now();
|
|
253
270
|
const pinnedPeer = opts.pinnedPeer;
|
|
254
271
|
const blockInfo = request.blockInfo;
|
|
255
272
|
const slotNumber = blockInfo.slotNumber;
|
|
256
|
-
if (
|
|
273
|
+
if (timeoutMs < 100) {
|
|
257
274
|
this.log.warn(
|
|
258
275
|
`Not initiating fast reqresp for txs for ${request.type} at slot ${blockInfo.slotNumber} due to timeout`,
|
|
259
|
-
{ timeoutMs
|
|
276
|
+
{ timeoutMs, ...blockInfo },
|
|
260
277
|
);
|
|
261
278
|
return;
|
|
262
279
|
}
|
|
263
280
|
|
|
264
281
|
this.log.debug(
|
|
265
|
-
`Starting fast reqresp for ${request.
|
|
266
|
-
{ ...blockInfo, timeoutMs
|
|
282
|
+
`Starting fast reqresp for ${request.missingTxTracker.numberOfMissingTxs} txs for ${request.type} at slot ${blockInfo.slotNumber}`,
|
|
283
|
+
{ ...blockInfo, timeoutMs, pinnedPeer },
|
|
267
284
|
);
|
|
268
285
|
|
|
269
286
|
try {
|
|
@@ -272,28 +289,34 @@ export class FastTxCollection {
|
|
|
272
289
|
let result: Tx[];
|
|
273
290
|
if (request.type === 'proposal') {
|
|
274
291
|
result = await this.missingTxsCollector.collectTxs(
|
|
275
|
-
request.
|
|
292
|
+
request.missingTxTracker,
|
|
276
293
|
request.blockProposal,
|
|
277
294
|
pinnedPeer,
|
|
295
|
+
timeoutMs,
|
|
278
296
|
);
|
|
279
297
|
} else if (request.type === 'block') {
|
|
280
298
|
const blockTxsSource = {
|
|
281
299
|
txHashes: request.block.body.txEffects.map(e => e.txHash),
|
|
282
300
|
archive: request.block.archive.root,
|
|
283
301
|
};
|
|
284
|
-
result = await this.missingTxsCollector.collectTxs(
|
|
302
|
+
result = await this.missingTxsCollector.collectTxs(
|
|
303
|
+
request.missingTxTracker,
|
|
304
|
+
blockTxsSource,
|
|
305
|
+
pinnedPeer,
|
|
306
|
+
timeoutMs,
|
|
307
|
+
);
|
|
285
308
|
} else {
|
|
286
309
|
throw new Error(`Unknown request type: ${(request as any).type}`);
|
|
287
310
|
}
|
|
288
311
|
return { validTxs: result, invalidTxHashes: [] };
|
|
289
312
|
},
|
|
290
|
-
Array.from(request.
|
|
313
|
+
Array.from(request.missingTxTracker.missingTxHashes),
|
|
291
314
|
{ description: `reqresp for slot ${slotNumber}`, method: 'fast-req-resp', ...opts, ...request.blockInfo },
|
|
292
315
|
this.getAddContext(request),
|
|
293
316
|
);
|
|
294
317
|
} catch (err) {
|
|
295
318
|
this.log.error(`Error sending fast reqresp request for txs`, err, {
|
|
296
|
-
txs: [...request.
|
|
319
|
+
txs: [...request.missingTxTracker.missingTxHashes],
|
|
297
320
|
...blockInfo,
|
|
298
321
|
});
|
|
299
322
|
}
|
|
@@ -317,19 +340,20 @@ export class FastTxCollection {
|
|
|
317
340
|
for (const tx of txs) {
|
|
318
341
|
const txHash = tx.txHash.toString();
|
|
319
342
|
// Remove the tx hash from the missing set, and add it to the found set.
|
|
320
|
-
if (request.
|
|
343
|
+
if (request.missingTxTracker.markFetched(tx)) {
|
|
321
344
|
this.log.trace(`Found tx ${txHash} for fast collection request`, {
|
|
322
345
|
...request.blockInfo,
|
|
323
346
|
txHash: tx.txHash.toString(),
|
|
324
347
|
type: request.type,
|
|
325
348
|
});
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
349
|
+
}
|
|
350
|
+
// If we found all txs for this request, we resolve the promise
|
|
351
|
+
if (request.missingTxTracker.allFetched()) {
|
|
352
|
+
this.log.trace(`All txs found for fast collection request`, {
|
|
353
|
+
...request.blockInfo,
|
|
354
|
+
type: request.type,
|
|
355
|
+
});
|
|
356
|
+
request.promise.resolve();
|
|
333
357
|
}
|
|
334
358
|
}
|
|
335
359
|
}
|
|
@@ -342,7 +366,8 @@ export class FastTxCollection {
|
|
|
342
366
|
public stopCollectingForBlocksUpTo(blockNumber: BlockNumber): void {
|
|
343
367
|
for (const request of this.requests) {
|
|
344
368
|
if (request.blockInfo.blockNumber <= blockNumber) {
|
|
345
|
-
request.
|
|
369
|
+
request.promise.reject(new AbortError(`Stopped collecting txs up to block ${blockNumber}`));
|
|
370
|
+
this.requests.delete(request);
|
|
346
371
|
}
|
|
347
372
|
}
|
|
348
373
|
}
|
|
@@ -354,7 +379,8 @@ export class FastTxCollection {
|
|
|
354
379
|
public stopCollectingForBlocksAfter(blockNumber: BlockNumber): void {
|
|
355
380
|
for (const request of this.requests) {
|
|
356
381
|
if (request.blockInfo.blockNumber > blockNumber) {
|
|
357
|
-
request.
|
|
382
|
+
request.promise.reject(new AbortError(`Stopped collecting txs after block ${blockNumber}`));
|
|
383
|
+
this.requests.delete(request);
|
|
358
384
|
}
|
|
359
385
|
}
|
|
360
386
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { TxHash } from '@aztec/stdlib/tx';
|
|
2
|
+
import type { Tx } from '@aztec/stdlib/tx';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tracks which transactions are still missing and need to be fetched.
|
|
6
|
+
* Allows external code to mark transactions as fetched, enabling coordination
|
|
7
|
+
* between multiple fetching mechanisms (e.g., BatchTxRequester and Rpc Node requests).
|
|
8
|
+
*/
|
|
9
|
+
export interface IMissingTxsTracker {
|
|
10
|
+
/** Returns the set of transaction hashes that are still missing. */
|
|
11
|
+
get missingTxHashes(): Set<string>;
|
|
12
|
+
/** Size of this.missingTxHashes */
|
|
13
|
+
get numberOfMissingTxs(): number;
|
|
14
|
+
/** Are all requested txs are fetched */
|
|
15
|
+
allFetched(): boolean;
|
|
16
|
+
/** Checks that transaction is still missing */
|
|
17
|
+
isMissing(txHash: string): boolean;
|
|
18
|
+
/** Marks a transaction as fetched. Returns true if it was previously missing. */
|
|
19
|
+
markFetched(tx: Tx): boolean;
|
|
20
|
+
/** Get list of collected txs */
|
|
21
|
+
get collectedTxs(): Tx[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class MissingTxsTracker implements IMissingTxsTracker {
|
|
25
|
+
public readonly collectedTxs: Tx[] = [];
|
|
26
|
+
|
|
27
|
+
private constructor(public readonly missingTxHashes: Set<string>) {}
|
|
28
|
+
|
|
29
|
+
public static fromArray(hashes: TxHash[] | string[]) {
|
|
30
|
+
return new MissingTxsTracker(new Set(hashes.map(hash => hash.toString())));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
markFetched(tx: Tx): boolean {
|
|
34
|
+
if (this.missingTxHashes.delete(tx.txHash.toString())) {
|
|
35
|
+
this.collectedTxs.push(tx);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get numberOfMissingTxs(): number {
|
|
42
|
+
return this.missingTxHashes.size;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
allFetched(): boolean {
|
|
46
|
+
return this.numberOfMissingTxs === 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
isMissing(txHash: string): boolean {
|
|
50
|
+
return this.missingTxHashes.has(txHash.toString());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -9,7 +9,7 @@ import type { BatchTxRequesterConfig } from '../reqresp/batch-tx-requester/confi
|
|
|
9
9
|
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
10
10
|
import type { IBatchRequestTxValidator } from '../reqresp/batch-tx-requester/tx_validator.js';
|
|
11
11
|
import { type BlockTxsSource, ReqRespSubProtocol, chunkTxHashesRequest } from '../reqresp/index.js';
|
|
12
|
-
import type {
|
|
12
|
+
import type { IMissingTxsTracker } from './missing_txs_tracker.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Strategy interface for collecting missing transactions for a block or proposal.
|
|
@@ -18,15 +18,17 @@ import type { IRequestTracker } from './request_tracker.js';
|
|
|
18
18
|
export interface MissingTxsCollector {
|
|
19
19
|
/**
|
|
20
20
|
* Collect missing transactions for a block or proposal.
|
|
21
|
-
* @param
|
|
21
|
+
* @param missingTxsTracker - The missing transactions tracker
|
|
22
22
|
* @param blockTxsSource - The block or proposal containing the transactions
|
|
23
23
|
* @param pinnedPeer - Optional peer expected to have the transactions
|
|
24
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
24
25
|
* @returns The collected transactions
|
|
25
26
|
*/
|
|
26
27
|
collectTxs(
|
|
27
|
-
|
|
28
|
+
missingTxsTracker: IMissingTxsTracker,
|
|
28
29
|
blockTxsSource: BlockTxsSource,
|
|
29
30
|
pinnedPeer: PeerId | undefined,
|
|
31
|
+
timeoutMs: number,
|
|
30
32
|
): Promise<Tx[]>;
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -44,9 +46,10 @@ export class BatchTxRequesterCollector implements MissingTxsCollector {
|
|
|
44
46
|
) {}
|
|
45
47
|
|
|
46
48
|
async collectTxs(
|
|
47
|
-
|
|
49
|
+
missingTxsTracker: IMissingTxsTracker,
|
|
48
50
|
blockTxsSource: BlockTxsSource,
|
|
49
51
|
pinnedPeer: PeerId | undefined,
|
|
52
|
+
timeoutMs: number,
|
|
50
53
|
): Promise<Tx[]> {
|
|
51
54
|
const {
|
|
52
55
|
batchTxRequesterSmartParallelWorkerCount: smartParallelWorkerCount,
|
|
@@ -56,9 +59,10 @@ export class BatchTxRequesterCollector implements MissingTxsCollector {
|
|
|
56
59
|
} = this.batchTxRequesterConfig ?? {};
|
|
57
60
|
|
|
58
61
|
const batchRequester = new BatchTxRequester(
|
|
59
|
-
|
|
62
|
+
missingTxsTracker,
|
|
60
63
|
blockTxsSource,
|
|
61
64
|
pinnedPeer,
|
|
65
|
+
timeoutMs,
|
|
62
66
|
this.p2pService,
|
|
63
67
|
this.log,
|
|
64
68
|
this.dateProvider,
|
|
@@ -90,15 +94,16 @@ export class SendBatchRequestCollector implements MissingTxsCollector {
|
|
|
90
94
|
) {}
|
|
91
95
|
|
|
92
96
|
async collectTxs(
|
|
93
|
-
|
|
97
|
+
missingTxsTracker: IMissingTxsTracker,
|
|
94
98
|
_blockTxsSource: BlockTxsSource,
|
|
95
99
|
pinnedPeer: PeerId | undefined,
|
|
100
|
+
timeoutMs: number,
|
|
96
101
|
): Promise<Tx[]> {
|
|
97
102
|
const txs = await this.p2pService.reqResp.sendBatchRequest<ReqRespSubProtocol.TX>(
|
|
98
103
|
ReqRespSubProtocol.TX,
|
|
99
|
-
chunkTxHashesRequest(Array.from(
|
|
104
|
+
chunkTxHashesRequest(Array.from(missingTxsTracker.missingTxHashes).map(TxHash.fromString)),
|
|
100
105
|
pinnedPeer,
|
|
101
|
-
|
|
106
|
+
timeoutMs,
|
|
102
107
|
this.maxPeers,
|
|
103
108
|
this.maxRetryAttempts,
|
|
104
109
|
);
|
|
@@ -196,7 +196,7 @@ export class SlowTxCollection {
|
|
|
196
196
|
// from mined unproven blocks it has seen in the past.
|
|
197
197
|
const fastRequests = this.fastCollection.getFastCollectionRequests();
|
|
198
198
|
const fastCollectionTxs: Set<string> = new Set(
|
|
199
|
-
fastRequests.values().flatMap(r => Array.from(r.
|
|
199
|
+
fastRequests.values().flatMap(r => Array.from(r.missingTxTracker.missingTxHashes)),
|
|
200
200
|
);
|
|
201
201
|
|
|
202
202
|
// Return all missing txs that are not in fastCollectionTxs and are ready for reqresp if requested
|