@aztec/p2p 0.0.1-commit.6d63667d → 0.0.1-commit.7cf39cb55
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 -5
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +44 -10
- package/dest/client/interface.d.ts +37 -15
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +35 -36
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +114 -138
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +1 -1
- package/dest/config.d.ts +22 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +16 -1
- 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 +104 -88
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +441 -3
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
- 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 +353 -87
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -2
- package/dest/mem_pools/index.d.ts +3 -2
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/index.js +1 -1
- package/dest/mem_pools/interface.d.ts +5 -5
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +102 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +242 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +3 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +3 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +3 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +3 -1
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -1
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +7 -3
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +27 -3
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +37 -4
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +8 -2
- 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 +15 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +4 -2
- 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 +6 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +4 -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 +110 -78
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +3 -3
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +16 -3
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +13 -3
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +20 -4
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +2 -2
- package/dest/services/dummy_service.d.ts +10 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +6 -0
- package/dest/services/encoding.d.ts +2 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +2 -2
- package/dest/services/gossipsub/index.d.ts +3 -0
- package/dest/services/gossipsub/index.d.ts.map +1 -0
- package/dest/services/gossipsub/index.js +2 -0
- package/dest/services/gossipsub/scoring.d.ts +21 -3
- package/dest/services/gossipsub/scoring.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.js +24 -7
- package/dest/services/gossipsub/topic_score_params.d.ts +161 -0
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
- package/dest/services/gossipsub/topic_score_params.js +324 -0
- package/dest/services/libp2p/libp2p_service.d.ts +84 -35
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +364 -265
- package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +25 -2
- package/dest/services/reqresp/interface.d.ts +10 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +15 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +4 -3
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +7 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +15 -0
- package/dest/services/reqresp/protocols/tx.d.ts +7 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +20 -0
- 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 +11 -4
- package/dest/services/service.d.ts +35 -1
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +19 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +46 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +3 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +17 -3
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_collection.js +165 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts +28 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_source.js +59 -0
- package/dest/services/tx_collection/index.d.ts +2 -1
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +1 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +6 -2
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +55 -23
- package/dest/services/tx_collection/tx_collection.d.ts +19 -7
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +75 -3
- package/dest/services/tx_collection/tx_collection_sink.d.ts +15 -6
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +13 -7
- package/dest/services/tx_file_store/config.d.ts +1 -3
- package/dest/services/tx_file_store/config.d.ts.map +1 -1
- package/dest/services/tx_file_store/config.js +0 -4
- package/dest/services/tx_file_store/tx_file_store.d.ts +4 -3
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +8 -5
- package/dest/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +5 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +3 -3
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +27 -1
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +97 -2
- 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/reqresp-nodes.js +2 -1
- package/dest/test-helpers/testbench-utils.d.ts +40 -38
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +128 -59
- package/dest/testbench/p2p_client_testbench_worker.js +2 -2
- package/package.json +14 -14
- package/src/client/factory.ts +81 -13
- package/src/client/interface.ts +45 -14
- package/src/client/p2p_client.ts +151 -161
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +1 -1
- package/src/config.ts +34 -2
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +496 -91
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +442 -102
- package/src/mem_pools/attestation_pool/index.ts +9 -2
- package/src/mem_pools/index.ts +4 -1
- package/src/mem_pools/interface.ts +4 -4
- package/src/mem_pools/tx_pool_v2/README.md +75 -9
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +310 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +3 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +1 -1
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +1 -1
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +3 -1
- package/src/mem_pools/tx_pool_v2/index.ts +1 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +8 -2
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +55 -5
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +18 -2
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +7 -1
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +122 -80
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +2 -2
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +2 -2
- package/src/msg_validators/tx_validator/block_header_validator.ts +15 -3
- package/src/msg_validators/tx_validator/double_spend_validator.ts +11 -6
- package/src/msg_validators/tx_validator/timestamp_validator.ts +19 -14
- package/src/services/dummy_service.ts +12 -0
- package/src/services/encoding.ts +2 -2
- package/src/services/gossipsub/README.md +626 -0
- package/src/services/gossipsub/index.ts +2 -0
- package/src/services/gossipsub/scoring.ts +29 -5
- package/src/services/gossipsub/topic_score_params.ts +451 -0
- package/src/services/libp2p/libp2p_service.ts +360 -269
- package/src/services/peer-manager/peer_scoring.ts +25 -0
- package/src/services/reqresp/interface.ts +26 -1
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +4 -3
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +17 -0
- package/src/services/reqresp/protocols/tx.ts +22 -0
- package/src/services/reqresp/reqresp.ts +13 -3
- package/src/services/service.ts +40 -0
- package/src/services/tx_collection/config.ts +68 -0
- package/src/services/tx_collection/fast_tx_collection.ts +14 -2
- package/src/services/tx_collection/file_store_tx_collection.ts +198 -0
- package/src/services/tx_collection/file_store_tx_source.ts +73 -0
- package/src/services/tx_collection/index.ts +1 -0
- package/src/services/tx_collection/slow_tx_collection.ts +64 -30
- package/src/services/tx_collection/tx_collection.ts +109 -13
- package/src/services/tx_collection/tx_collection_sink.ts +17 -7
- package/src/services/tx_file_store/config.ts +0 -6
- package/src/services/tx_file_store/tx_file_store.ts +9 -7
- package/src/services/tx_provider.ts +8 -7
- package/src/test-helpers/make-test-p2p-clients.ts +3 -3
- package/src/test-helpers/mock-pubsub.ts +133 -3
- package/src/test-helpers/reqresp-nodes.ts +2 -1
- package/src/test-helpers/testbench-utils.ts +127 -71
- package/src/testbench/p2p_client_testbench_worker.ts +2 -2
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -40
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -218
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -31
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -180
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -320
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -264
|
@@ -72,7 +72,7 @@ export class TxPoolIndices {
|
|
|
72
72
|
* Iterates pending transaction hashes in priority order.
|
|
73
73
|
* @param order - 'desc' for highest priority first, 'asc' for lowest priority first
|
|
74
74
|
*/
|
|
75
|
-
*iteratePendingByPriority(order: 'asc' | 'desc'): Generator<string> {
|
|
75
|
+
*iteratePendingByPriority(order: 'asc' | 'desc', filter?: (hash: string) => boolean): Generator<string> {
|
|
76
76
|
// Use compareFee from tx_metadata, swap args for descending order
|
|
77
77
|
const feeCompareFn = order === 'desc' ? (a: bigint, b: bigint) => compareFee(b, a) : compareFee;
|
|
78
78
|
const hashCompareFn = order === 'desc' ? (a: string, b: string) => compareTxHash(b, a) : compareTxHash;
|
|
@@ -84,11 +84,27 @@ export class TxPoolIndices {
|
|
|
84
84
|
// Use compareTxHash from tx_metadata, swap args for descending order
|
|
85
85
|
const sortedHashes = [...hashesAtFee].sort(hashCompareFn);
|
|
86
86
|
for (const hash of sortedHashes) {
|
|
87
|
-
|
|
87
|
+
if (filter === undefined || filter(hash)) {
|
|
88
|
+
yield hash;
|
|
89
|
+
}
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Iterates pending transaction hashes in priority order, skipping txs received after maxReceivedAt.
|
|
96
|
+
* @param order - 'desc' for highest priority first, 'asc' for lowest priority first
|
|
97
|
+
* @param maxReceivedAt - Only yield txs with receivedAt <= this value
|
|
98
|
+
*/
|
|
99
|
+
*iterateEligiblePendingByPriority(order: 'asc' | 'desc', maxReceivedAt: number): Generator<string> {
|
|
100
|
+
const filter = (hash: string) => {
|
|
101
|
+
const meta = this.#metadata.get(hash);
|
|
102
|
+
return meta !== undefined && meta.receivedAt <= maxReceivedAt;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
yield* this.iteratePendingByPriority(order, filter);
|
|
106
|
+
}
|
|
107
|
+
|
|
92
108
|
/** Iterates all metadata entries */
|
|
93
109
|
*iterateMetadata(): Generator<[string, TxMetaData]> {
|
|
94
110
|
yield* this.#metadata;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
4
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
4
5
|
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
5
6
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
6
7
|
import type { L2Block, L2BlockId } from '@aztec/stdlib/block';
|
|
@@ -35,6 +36,7 @@ export class AztecKVTxPoolV2 extends (EventEmitter as new () => TypedEventEmitte
|
|
|
35
36
|
deps: TxPoolV2Dependencies,
|
|
36
37
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
37
38
|
config: Partial<TxPoolV2Config> = {},
|
|
39
|
+
dateProvider: DateProvider = new DateProvider(),
|
|
38
40
|
log = createLogger('p2p:tx_pool_v2'),
|
|
39
41
|
) {
|
|
40
42
|
super();
|
|
@@ -59,7 +61,7 @@ export class AztecKVTxPoolV2 extends (EventEmitter as new () => TypedEventEmitte
|
|
|
59
61
|
};
|
|
60
62
|
|
|
61
63
|
// Create the implementation
|
|
62
|
-
this.#impl = new TxPoolV2Impl(store, archiveStore, deps, callbacks, config, log);
|
|
64
|
+
this.#impl = new TxPoolV2Impl(store, archiveStore, deps, callbacks, config, dateProvider, log);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
// ============================================================================
|
|
@@ -132,6 +134,10 @@ export class AztecKVTxPoolV2 extends (EventEmitter as new () => TypedEventEmitte
|
|
|
132
134
|
return this.#queue.put(() => Promise.resolve(this.#impl.getPendingTxHashes()));
|
|
133
135
|
}
|
|
134
136
|
|
|
137
|
+
getEligiblePendingTxHashes(): Promise<TxHash[]> {
|
|
138
|
+
return this.#queue.put(() => Promise.resolve(this.#impl.getEligiblePendingTxHashes()));
|
|
139
|
+
}
|
|
140
|
+
|
|
135
141
|
getPendingTxCount(): Promise<number> {
|
|
136
142
|
return this.#queue.put(() => Promise.resolve(this.#impl.getPendingTxCount()));
|
|
137
143
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
|
+
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
|
+
import type { DateProvider } from '@aztec/foundation/timer';
|
|
3
4
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
4
5
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
6
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
@@ -10,6 +11,7 @@ import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
|
|
|
10
11
|
import { BlockHeader, Tx, TxHash, type TxValidator } from '@aztec/stdlib/tx';
|
|
11
12
|
|
|
12
13
|
import { TxArchive } from './archive/index.js';
|
|
14
|
+
import { DeletedPool } from './deleted_pool.js';
|
|
13
15
|
import {
|
|
14
16
|
EvictionManager,
|
|
15
17
|
FeePayerBalanceEvictionRule,
|
|
@@ -53,7 +55,7 @@ export class TxPoolV2Impl {
|
|
|
53
55
|
// === Dependencies ===
|
|
54
56
|
#l2BlockSource: L2BlockSource;
|
|
55
57
|
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
56
|
-
#
|
|
58
|
+
#createTxValidator: TxPoolV2Dependencies['createTxValidator'];
|
|
57
59
|
|
|
58
60
|
// === In-Memory Indices ===
|
|
59
61
|
#indices: TxPoolIndices = new TxPoolIndices();
|
|
@@ -61,7 +63,9 @@ export class TxPoolV2Impl {
|
|
|
61
63
|
// === Config & Services ===
|
|
62
64
|
#config: TxPoolV2Config;
|
|
63
65
|
#archive: TxArchive;
|
|
66
|
+
#deletedPool: DeletedPool;
|
|
64
67
|
#evictionManager: EvictionManager;
|
|
68
|
+
#dateProvider: DateProvider;
|
|
65
69
|
#log: Logger;
|
|
66
70
|
#callbacks: TxPoolV2Callbacks;
|
|
67
71
|
|
|
@@ -71,6 +75,7 @@ export class TxPoolV2Impl {
|
|
|
71
75
|
deps: TxPoolV2Dependencies,
|
|
72
76
|
callbacks: TxPoolV2Callbacks,
|
|
73
77
|
config: Partial<TxPoolV2Config> = {},
|
|
78
|
+
dateProvider: DateProvider,
|
|
74
79
|
log: Logger,
|
|
75
80
|
) {
|
|
76
81
|
this.#store = store;
|
|
@@ -78,10 +83,12 @@ export class TxPoolV2Impl {
|
|
|
78
83
|
|
|
79
84
|
this.#l2BlockSource = deps.l2BlockSource;
|
|
80
85
|
this.#worldStateSynchronizer = deps.worldStateSynchronizer;
|
|
81
|
-
this.#
|
|
86
|
+
this.#createTxValidator = deps.createTxValidator;
|
|
82
87
|
|
|
83
88
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
84
89
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
90
|
+
this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
|
|
91
|
+
this.#dateProvider = dateProvider;
|
|
85
92
|
this.#log = log;
|
|
86
93
|
this.#callbacks = callbacks;
|
|
87
94
|
|
|
@@ -116,7 +123,10 @@ export class TxPoolV2Impl {
|
|
|
116
123
|
* by running pre-add rules to resolve nullifier conflicts, balance checks, and pool size limits.
|
|
117
124
|
*/
|
|
118
125
|
async hydrateFromDatabase(): Promise<void> {
|
|
119
|
-
// Step
|
|
126
|
+
// Step 0: Hydrate deleted pool state
|
|
127
|
+
await this.#deletedPool.hydrateFromDatabase();
|
|
128
|
+
|
|
129
|
+
// Step 1: Load all transactions from DB (excluding soft-deleted)
|
|
120
130
|
const { loaded, errors: deserializationErrors } = await this.#loadAllTxsFromDb();
|
|
121
131
|
|
|
122
132
|
// Step 2: Check mined status for each tx
|
|
@@ -134,7 +144,10 @@ export class TxPoolV2Impl {
|
|
|
134
144
|
}
|
|
135
145
|
|
|
136
146
|
// Step 4: Validate non-mined transactions
|
|
137
|
-
const { valid, invalid } = await this.#
|
|
147
|
+
const { valid, invalid } = await this.#revalidateMetadata(
|
|
148
|
+
nonMined.map(e => e.meta),
|
|
149
|
+
'on startup',
|
|
150
|
+
);
|
|
138
151
|
|
|
139
152
|
// Step 5: Populate mined indices (these don't need conflict resolution)
|
|
140
153
|
for (const meta of mined) {
|
|
@@ -155,7 +168,7 @@ export class TxPoolV2Impl {
|
|
|
155
168
|
await this.#txsDB.delete(txHashStr);
|
|
156
169
|
}
|
|
157
170
|
});
|
|
158
|
-
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup
|
|
171
|
+
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
|
|
159
172
|
}
|
|
160
173
|
|
|
161
174
|
async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
|
|
@@ -229,13 +242,13 @@ export class TxPoolV2Impl {
|
|
|
229
242
|
const txHash = tx.getTxHash();
|
|
230
243
|
const txHashStr = txHash.toString();
|
|
231
244
|
|
|
232
|
-
//
|
|
233
|
-
|
|
245
|
+
// Build metadata and validate using metadata
|
|
246
|
+
const meta = await buildTxMetaData(tx);
|
|
247
|
+
if (!(await this.#validateMeta(meta))) {
|
|
234
248
|
return { status: 'rejected' };
|
|
235
249
|
}
|
|
236
250
|
|
|
237
|
-
//
|
|
238
|
-
const meta = await buildTxMetaData(tx);
|
|
251
|
+
// Run pre-add rules
|
|
239
252
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
240
253
|
|
|
241
254
|
if (preAddResult.shouldIgnore) {
|
|
@@ -246,7 +259,10 @@ export class TxPoolV2Impl {
|
|
|
246
259
|
// Evict conflicts
|
|
247
260
|
for (const evictHashStr of preAddResult.txHashesToEvict) {
|
|
248
261
|
await this.#deleteTx(evictHashStr);
|
|
249
|
-
this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}
|
|
262
|
+
this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
|
|
263
|
+
evictedTxHash: evictHashStr,
|
|
264
|
+
replacementTxHash: txHashStr,
|
|
265
|
+
});
|
|
250
266
|
if (acceptedPending.has(evictHashStr)) {
|
|
251
267
|
// Evicted tx was from this batch - mark as ignored in result
|
|
252
268
|
acceptedPending.delete(evictHashStr);
|
|
@@ -267,14 +283,14 @@ export class TxPoolV2Impl {
|
|
|
267
283
|
return 'ignored';
|
|
268
284
|
}
|
|
269
285
|
|
|
270
|
-
//
|
|
271
|
-
const
|
|
272
|
-
|
|
286
|
+
// Build metadata and validate using metadata
|
|
287
|
+
const meta = await buildTxMetaData(tx);
|
|
288
|
+
const validationResult = await this.#validateMeta(meta, undefined, 'can add pending');
|
|
289
|
+
if (validationResult !== true) {
|
|
273
290
|
return 'rejected';
|
|
274
291
|
}
|
|
275
292
|
|
|
276
|
-
//
|
|
277
|
-
const meta = await buildTxMetaData(tx);
|
|
293
|
+
// Use pre-add rules
|
|
278
294
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
279
295
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
280
296
|
|
|
@@ -347,6 +363,7 @@ export class TxPoolV2Impl {
|
|
|
347
363
|
// Add new mined tx (callback emitted by #addTx)
|
|
348
364
|
await this.#addTx(tx, { mined: blockId }, opts);
|
|
349
365
|
}
|
|
366
|
+
await this.#deletedPool.clearIfMinedHigher(txHashStr, blockId.number);
|
|
350
367
|
}
|
|
351
368
|
});
|
|
352
369
|
}
|
|
@@ -373,6 +390,7 @@ export class TxPoolV2Impl {
|
|
|
373
390
|
// Step 4: Mark txs as mined (only those we have in the pool)
|
|
374
391
|
for (const meta of found) {
|
|
375
392
|
this.#indices.markAsMined(meta, blockId);
|
|
393
|
+
await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
|
|
376
394
|
}
|
|
377
395
|
|
|
378
396
|
// Step 5: Run eviction rules (remove pending txs with conflicting nullifiers/expired timestamps)
|
|
@@ -382,6 +400,9 @@ export class TxPoolV2Impl {
|
|
|
382
400
|
}
|
|
383
401
|
|
|
384
402
|
async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
|
|
403
|
+
// Step 0: Clean up slot-deleted txs from previous slots
|
|
404
|
+
await this.#deletedPool.cleanupSlotDeleted(slotNumber);
|
|
405
|
+
|
|
385
406
|
// Step 1: Find expired protected txs
|
|
386
407
|
const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
|
|
387
408
|
|
|
@@ -397,7 +418,7 @@ export class TxPoolV2Impl {
|
|
|
397
418
|
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
398
419
|
|
|
399
420
|
// Step 4: Validate for pending pool
|
|
400
|
-
const { valid, invalid } = await this.#
|
|
421
|
+
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
|
|
401
422
|
|
|
402
423
|
// Step 5: Resolve nullifier conflicts and add winners to pending indices
|
|
403
424
|
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
@@ -426,24 +447,39 @@ export class TxPoolV2Impl {
|
|
|
426
447
|
|
|
427
448
|
this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
|
|
428
449
|
|
|
429
|
-
// Step 2:
|
|
450
|
+
// Step 2: Mark ALL un-mined txs with their original mined block number
|
|
451
|
+
// This ensures they get soft-deleted if removed later, and only hard-deleted
|
|
452
|
+
// when their original mined block is finalized
|
|
453
|
+
await this.#deletedPool.markFromPrunedBlock(
|
|
454
|
+
txsToUnmine.map(m => ({
|
|
455
|
+
txHash: m.txHash,
|
|
456
|
+
minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
|
|
457
|
+
})),
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
// Step 3: Unmine - clear mined status from metadata
|
|
430
461
|
for (const meta of txsToUnmine) {
|
|
431
462
|
this.#indices.markAsUnmined(meta);
|
|
432
463
|
}
|
|
433
464
|
|
|
434
|
-
// Step
|
|
465
|
+
// Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
|
|
435
466
|
const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
|
|
436
467
|
|
|
437
468
|
// Step 4: Validate for pending pool
|
|
438
|
-
const { valid, invalid } = await this.#
|
|
469
|
+
const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
|
|
439
470
|
|
|
440
|
-
// Step
|
|
471
|
+
// Step 6: Resolve nullifier conflicts and add winners to pending indices
|
|
441
472
|
const { toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
442
473
|
|
|
443
|
-
// Step
|
|
474
|
+
// Step 7: Delete invalid and evicted txs
|
|
444
475
|
await this.#deleteTxsBatch([...invalid, ...toEvict]);
|
|
445
476
|
|
|
446
|
-
|
|
477
|
+
this.#log.info(
|
|
478
|
+
`Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`,
|
|
479
|
+
{ txHashesRestored: valid.map(m => m.txHash), txHashesInvalid: invalid, txHashesEvicted: toEvict },
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
// Step 8: Run eviction rules for ALL pending txs (not just restored ones)
|
|
447
483
|
// This handles cases like existing pending txs with invalid fee payer balances
|
|
448
484
|
await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
|
|
449
485
|
}
|
|
@@ -452,22 +488,19 @@ export class TxPoolV2Impl {
|
|
|
452
488
|
// Delete failed txs
|
|
453
489
|
await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
|
|
454
490
|
|
|
455
|
-
this.#log.info(`Deleted ${txHashes.length} failed txs
|
|
491
|
+
this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
|
|
456
492
|
}
|
|
457
493
|
|
|
458
494
|
async handleFinalizedBlock(block: BlockHeader): Promise<void> {
|
|
459
495
|
const blockNumber = block.globalVariables.blockNumber;
|
|
460
496
|
|
|
461
|
-
// Step 1: Find txs
|
|
462
|
-
const
|
|
463
|
-
if (txsToFinalize.length === 0) {
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
497
|
+
// Step 1: Find mined txs at or before finalized block
|
|
498
|
+
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
|
|
466
499
|
|
|
467
|
-
// Step 2: Collect txs for archiving (before deletion)
|
|
500
|
+
// Step 2: Collect mined txs for archiving (before deletion)
|
|
468
501
|
const txsToArchive: Tx[] = [];
|
|
469
502
|
if (this.#archive.isEnabled()) {
|
|
470
|
-
for (const txHashStr of
|
|
503
|
+
for (const txHashStr of minedTxsToFinalize) {
|
|
471
504
|
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
472
505
|
if (buffer) {
|
|
473
506
|
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
@@ -475,15 +508,22 @@ export class TxPoolV2Impl {
|
|
|
475
508
|
}
|
|
476
509
|
}
|
|
477
510
|
|
|
478
|
-
// Step 3: Delete from active pool
|
|
479
|
-
await this.#deleteTxsBatch(
|
|
511
|
+
// Step 3: Delete mined txs from active pool
|
|
512
|
+
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
480
513
|
|
|
481
|
-
// Step 4:
|
|
514
|
+
// Step 4: Finalize soft-deleted txs
|
|
515
|
+
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
516
|
+
|
|
517
|
+
// Step 5: Archive mined txs
|
|
482
518
|
if (txsToArchive.length > 0) {
|
|
483
519
|
await this.#archive.archiveTxs(txsToArchive);
|
|
484
520
|
}
|
|
485
521
|
|
|
486
|
-
|
|
522
|
+
if (minedTxsToFinalize.length > 0) {
|
|
523
|
+
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
|
|
524
|
+
txHashes: minedTxsToFinalize,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
487
527
|
}
|
|
488
528
|
|
|
489
529
|
// === Query Methods ===
|
|
@@ -503,21 +543,36 @@ export class TxPoolV2Impl {
|
|
|
503
543
|
}
|
|
504
544
|
|
|
505
545
|
hasTxs(txHashes: TxHash[]): boolean[] {
|
|
506
|
-
return txHashes.map(h =>
|
|
546
|
+
return txHashes.map(h => {
|
|
547
|
+
const hashStr = h.toString();
|
|
548
|
+
return this.#indices.has(hashStr) || this.#deletedPool.isSoftDeleted(hashStr);
|
|
549
|
+
});
|
|
507
550
|
}
|
|
508
551
|
|
|
509
552
|
getTxStatus(txHash: TxHash): TxState | undefined {
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
553
|
+
const txHashStr = txHash.toString();
|
|
554
|
+
const meta = this.#indices.getMetadata(txHashStr);
|
|
555
|
+
if (meta) {
|
|
556
|
+
return this.#indices.getTxState(meta);
|
|
557
|
+
}
|
|
558
|
+
// Check if soft-deleted
|
|
559
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
560
|
+
return 'deleted';
|
|
513
561
|
}
|
|
514
|
-
return
|
|
562
|
+
return undefined;
|
|
515
563
|
}
|
|
516
564
|
|
|
517
565
|
getPendingTxHashes(): TxHash[] {
|
|
518
566
|
return [...this.#indices.iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
|
|
519
567
|
}
|
|
520
568
|
|
|
569
|
+
getEligiblePendingTxHashes(): TxHash[] {
|
|
570
|
+
const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
|
|
571
|
+
return [...this.#indices.iterateEligiblePendingByPriority('desc', maxReceivedAt)].map(hash =>
|
|
572
|
+
TxHash.fromString(hash),
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
|
|
521
576
|
getPendingTxCount(): number {
|
|
522
577
|
return this.#indices.getPendingTxCount();
|
|
523
578
|
}
|
|
@@ -562,6 +617,9 @@ export class TxPoolV2Impl {
|
|
|
562
617
|
this.#config.archivedTxLimit = config.archivedTxLimit;
|
|
563
618
|
this.#archive.updateLimit(config.archivedTxLimit);
|
|
564
619
|
}
|
|
620
|
+
if (config.minTxPoolAgeMs !== undefined) {
|
|
621
|
+
this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
|
|
622
|
+
}
|
|
565
623
|
// Update eviction rules with new config
|
|
566
624
|
this.#evictionManager.updateConfig(config);
|
|
567
625
|
}
|
|
@@ -598,8 +656,10 @@ export class TxPoolV2Impl {
|
|
|
598
656
|
): Promise<TxMetaData> {
|
|
599
657
|
const txHashStr = tx.getTxHash().toString();
|
|
600
658
|
const meta = await buildTxMetaData(tx);
|
|
659
|
+
meta.receivedAt = this.#dateProvider.now();
|
|
601
660
|
|
|
602
661
|
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
662
|
+
await this.#deletedPool.clearSoftDeleted(txHashStr);
|
|
603
663
|
this.#callbacks.onTxsAdded([tx], opts);
|
|
604
664
|
|
|
605
665
|
if (state === 'pending') {
|
|
@@ -624,10 +684,15 @@ export class TxPoolV2Impl {
|
|
|
624
684
|
* Deletes a transaction from both indices and DB.
|
|
625
685
|
* Emits onTxsRemoved callback immediately after DB delete.
|
|
626
686
|
*/
|
|
687
|
+
/**
|
|
688
|
+
* Deletes a transaction from the pool.
|
|
689
|
+
* Delegates to DeletedPool which decides soft vs hard delete based on whether
|
|
690
|
+
* the tx is from a pruned block.
|
|
691
|
+
*/
|
|
627
692
|
async #deleteTx(txHashStr: string): Promise<void> {
|
|
628
693
|
this.#indices.remove(txHashStr);
|
|
629
|
-
await this.#txsDB.delete(txHashStr);
|
|
630
694
|
this.#callbacks.onTxsRemoved([txHashStr]);
|
|
695
|
+
await this.#deletedPool.deleteTx(txHashStr);
|
|
631
696
|
}
|
|
632
697
|
|
|
633
698
|
/** Deletes a batch of transactions, emitting callbacks individually for each. */
|
|
@@ -641,64 +706,36 @@ export class TxPoolV2Impl {
|
|
|
641
706
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
642
707
|
// ============================================================================
|
|
643
708
|
|
|
644
|
-
/** Validates
|
|
645
|
-
async #
|
|
646
|
-
const
|
|
709
|
+
/** Validates transaction metadata, returning true if valid */
|
|
710
|
+
async #validateMeta(meta: TxMetaData, validator?: TxValidator<TxMetaData>, context?: string): Promise<boolean> {
|
|
711
|
+
const txValidator = validator ?? (await this.#createTxValidator());
|
|
712
|
+
const result = await txValidator.validateTx(meta);
|
|
647
713
|
if (result.result !== 'valid') {
|
|
648
714
|
const contextStr = context ? ` ${context}` : '';
|
|
649
|
-
this.#log.info(`Tx ${
|
|
715
|
+
this.#log.info(`Tx ${meta.txHash}${contextStr} failed validation: ${result.reason?.join(', ')}`);
|
|
650
716
|
return false;
|
|
651
717
|
}
|
|
652
718
|
return true;
|
|
653
719
|
}
|
|
654
720
|
|
|
655
|
-
/**
|
|
656
|
-
async #
|
|
657
|
-
|
|
658
|
-
const missing: string[] = [];
|
|
659
|
-
|
|
660
|
-
for (const meta of metas) {
|
|
661
|
-
const buffer = await this.#txsDB.getAsync(meta.txHash);
|
|
662
|
-
if (!buffer) {
|
|
663
|
-
this.#log.warn(`Tx ${meta.txHash} not found in DB`);
|
|
664
|
-
missing.push(meta.txHash);
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
loaded.push({ tx: Tx.fromBuffer(buffer), meta });
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
return { loaded, missing };
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
/** Validates a batch of transactions, returning valid and invalid groups */
|
|
674
|
-
async #validateTxBatch(
|
|
675
|
-
txs: { tx: Tx; meta: TxMetaData }[],
|
|
721
|
+
/** Validates metadata directly */
|
|
722
|
+
async #revalidateMetadata(
|
|
723
|
+
metas: TxMetaData[],
|
|
676
724
|
context?: string,
|
|
677
725
|
): Promise<{ valid: TxMetaData[]; invalid: string[] }> {
|
|
678
726
|
const valid: TxMetaData[] = [];
|
|
679
727
|
const invalid: string[] = [];
|
|
680
|
-
|
|
681
|
-
for (const
|
|
682
|
-
if (await this.#
|
|
728
|
+
const validator = await this.#createTxValidator();
|
|
729
|
+
for (const meta of metas) {
|
|
730
|
+
if (await this.#validateMeta(meta, validator, context)) {
|
|
683
731
|
valid.push(meta);
|
|
684
732
|
} else {
|
|
685
733
|
invalid.push(meta.txHash);
|
|
686
734
|
}
|
|
687
735
|
}
|
|
688
|
-
|
|
689
736
|
return { valid, invalid };
|
|
690
737
|
}
|
|
691
738
|
|
|
692
|
-
/** Loads transactions from DB and validates them */
|
|
693
|
-
async #loadAndValidateTxs(
|
|
694
|
-
metas: TxMetaData[],
|
|
695
|
-
context?: string,
|
|
696
|
-
): Promise<{ valid: TxMetaData[]; invalid: string[] }> {
|
|
697
|
-
const { loaded, missing } = await this.#loadTxsFromDb(metas);
|
|
698
|
-
const { valid, invalid } = await this.#validateTxBatch(loaded, context);
|
|
699
|
-
return { valid, invalid: [...missing, ...invalid] };
|
|
700
|
-
}
|
|
701
|
-
|
|
702
739
|
/**
|
|
703
740
|
* Resolves nullifier conflicts between incoming txs and existing pending txs.
|
|
704
741
|
* Modifies the pending indices during iteration to maintain consistent state
|
|
@@ -768,6 +805,11 @@ export class TxPoolV2Impl {
|
|
|
768
805
|
const errors: string[] = [];
|
|
769
806
|
|
|
770
807
|
for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
|
|
808
|
+
// Skip soft-deleted transactions - they stay in DB but not in indices
|
|
809
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
|
|
771
813
|
try {
|
|
772
814
|
const tx = Tx.fromBuffer(buffer);
|
|
773
815
|
const meta = await buildTxMetaData(tx);
|
|
@@ -2,7 +2,7 @@ import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
|
2
2
|
import { type CheckpointAttestation, PeerErrorSeverity, type ValidationResult } from '@aztec/stdlib/p2p';
|
|
3
3
|
import { Attributes, Metrics, type TelemetryClient, createUpDownCounterWithDefault } from '@aztec/telemetry-client';
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type { AttestationPoolApi } from '../../mem_pools/attestation_pool/attestation_pool.js';
|
|
6
6
|
import { CheckpointAttestationValidator } from './attestation_validator.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -18,7 +18,7 @@ export class FishermanAttestationValidator extends CheckpointAttestationValidato
|
|
|
18
18
|
|
|
19
19
|
constructor(
|
|
20
20
|
epochCache: EpochCacheInterface,
|
|
21
|
-
private attestationPool:
|
|
21
|
+
private attestationPool: AttestationPoolApi,
|
|
22
22
|
telemetryClient: TelemetryClient,
|
|
23
23
|
) {
|
|
24
24
|
super(epochCache);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TxValidationResult, TxValidator } from '@aztec/stdlib/tx';
|
|
2
2
|
|
|
3
|
-
export class AggregateTxValidator<T
|
|
3
|
+
export class AggregateTxValidator<T> implements TxValidator<T> {
|
|
4
4
|
#validators: TxValidator<T>[];
|
|
5
5
|
constructor(...validators: TxValidator<T>[]) {
|
|
6
6
|
if (validators.length === 0) {
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
2
2
|
import type { BlockHash } from '@aztec/stdlib/block';
|
|
3
|
-
import {
|
|
3
|
+
import { TX_ERROR_BLOCK_HEADER, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
4
4
|
|
|
5
5
|
export interface ArchiveSource {
|
|
6
6
|
getArchiveIndices: (archives: BlockHash[]) => Promise<(bigint | undefined)[]>;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/** Structural interface for block header validation. */
|
|
10
|
+
export interface HasBlockHeaderData {
|
|
11
|
+
txHash: { toString(): string };
|
|
12
|
+
data: {
|
|
13
|
+
constants: {
|
|
14
|
+
anchorBlockHeader: {
|
|
15
|
+
hash(): Promise<BlockHash>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class BlockHeaderTxValidator<T extends HasBlockHeaderData> implements TxValidator<T> {
|
|
10
22
|
#log: Logger;
|
|
11
23
|
#archiveSource: ArchiveSource;
|
|
12
24
|
|
|
@@ -18,7 +30,7 @@ export class BlockHeaderTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
|
18
30
|
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
19
31
|
const [index] = await this.#archiveSource.getArchiveIndices([await tx.data.constants.anchorBlockHeader.hash()]);
|
|
20
32
|
if (index === undefined) {
|
|
21
|
-
this.#log.verbose(`Rejecting tx ${
|
|
33
|
+
this.#log.verbose(`Rejecting tx ${tx.txHash} for referencing an unknown block header`);
|
|
22
34
|
return { result: 'invalid', reason: [TX_ERROR_BLOCK_HEADER] };
|
|
23
35
|
}
|
|
24
36
|
return { result: 'valid' };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
1
2
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
2
3
|
import {
|
|
3
|
-
type AnyTx,
|
|
4
4
|
TX_ERROR_DUPLICATE_NULLIFIER_IN_TX,
|
|
5
5
|
TX_ERROR_EXISTING_NULLIFIER,
|
|
6
|
-
Tx,
|
|
7
6
|
type TxValidationResult,
|
|
8
7
|
type TxValidator,
|
|
9
8
|
} from '@aztec/stdlib/tx';
|
|
@@ -12,7 +11,13 @@ export interface NullifierSource {
|
|
|
12
11
|
nullifiersExist: (nullifiers: Buffer[]) => Promise<boolean[]>;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
/** Structural interface for double-spend validation. */
|
|
15
|
+
export interface HasNullifierData {
|
|
16
|
+
txHash: { toString(): string };
|
|
17
|
+
data: { getNonEmptyNullifiers(): Fr[] };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class DoubleSpendTxValidator<T extends HasNullifierData> implements TxValidator<T> {
|
|
16
21
|
#log: Logger;
|
|
17
22
|
#nullifierSource: NullifierSource;
|
|
18
23
|
|
|
@@ -22,17 +27,17 @@ export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
25
|
-
const nullifiers = tx
|
|
30
|
+
const nullifiers = tx.data.getNonEmptyNullifiers();
|
|
26
31
|
|
|
27
32
|
// Ditch this tx if it has repeated nullifiers
|
|
28
33
|
const uniqueNullifiers = new Set(nullifiers.map(n => n.toBigInt()));
|
|
29
34
|
if (uniqueNullifiers.size !== nullifiers.length) {
|
|
30
|
-
this.#log.verbose(`Rejecting tx ${
|
|
35
|
+
this.#log.verbose(`Rejecting tx ${tx.txHash} for emitting duplicate nullifiers`);
|
|
31
36
|
return { result: 'invalid', reason: [TX_ERROR_DUPLICATE_NULLIFIER_IN_TX] };
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
if ((await this.#nullifierSource.nullifiersExist(nullifiers.map(n => n.toBuffer()))).some(Boolean)) {
|
|
35
|
-
this.#log.verbose(`Rejecting tx ${
|
|
40
|
+
this.#log.verbose(`Rejecting tx ${tx.txHash} for repeating a nullifier`);
|
|
36
41
|
return { result: 'invalid', reason: [TX_ERROR_EXISTING_NULLIFIER] };
|
|
37
42
|
}
|
|
38
43
|
|
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
1
|
+
import type { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import {
|
|
4
|
-
type AnyTx,
|
|
5
|
-
TX_ERROR_INVALID_INCLUDE_BY_TIMESTAMP,
|
|
6
|
-
type TxValidationResult,
|
|
7
|
-
type TxValidator,
|
|
8
|
-
getTxHash,
|
|
9
|
-
} from '@aztec/stdlib/tx';
|
|
3
|
+
import { TX_ERROR_INVALID_INCLUDE_BY_TIMESTAMP, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
10
4
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
11
5
|
|
|
12
|
-
|
|
6
|
+
/** Structural interface for timestamp validation. */
|
|
7
|
+
export interface HasTimestampData {
|
|
8
|
+
txHash: { toString(): string };
|
|
9
|
+
data: {
|
|
10
|
+
includeByTimestamp: bigint;
|
|
11
|
+
constants: {
|
|
12
|
+
anchorBlockHeader: {
|
|
13
|
+
globalVariables: {
|
|
14
|
+
blockNumber: BlockNumber;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class TimestampTxValidator<T extends HasTimestampData> implements TxValidator<T> {
|
|
13
22
|
#log: Logger;
|
|
14
23
|
|
|
15
24
|
constructor(
|
|
@@ -38,11 +47,7 @@ export class TimestampTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
|
38
47
|
);
|
|
39
48
|
}
|
|
40
49
|
this.#log.verbose(
|
|
41
|
-
`Rejecting tx ${
|
|
42
|
-
tx,
|
|
43
|
-
)} for low expiration timestamp. Tx expiration timestamp: ${includeByTimestamp}, timestamp: ${
|
|
44
|
-
this.values.timestamp
|
|
45
|
-
}.`,
|
|
50
|
+
`Rejecting tx ${tx.txHash} for low expiration timestamp. Tx expiration timestamp: ${includeByTimestamp}, timestamp: ${this.values.timestamp}.`,
|
|
46
51
|
);
|
|
47
52
|
return Promise.resolve({ result: 'invalid', reason: [TX_ERROR_INVALID_INCLUDE_BY_TIMESTAMP] });
|
|
48
53
|
} else {
|