@aztec/p2p 0.0.1-commit.4d79d1f2d → 0.0.1-commit.5358163d3
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 +6 -6
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +23 -30
- package/dest/client/interface.d.ts +14 -19
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +9 -18
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +52 -72
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -7
- package/dest/config.d.ts +20 -14
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +30 -35
- package/dest/errors/tx-pool.error.d.ts +8 -0
- package/dest/errors/tx-pool.error.d.ts.map +1 -0
- package/dest/errors/tx-pool.error.js +9 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -2
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +10 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +2 -2
- package/dest/mem_pools/instrumentation.d.ts +4 -2
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +16 -14
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +30 -13
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +91 -20
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
- 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 +5 -2
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +12 -4
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +48 -5
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
- 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 +14 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +14 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +20 -6
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +4 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +34 -8
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +76 -10
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
- 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 +36 -14
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -4
- 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 +14 -6
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +14 -5
- 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 +299 -142
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +2 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +2 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +3 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +10 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +2 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +166 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +25 -10
- package/dest/msg_validators/tx_validator/factory.d.ts +114 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +219 -58
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +58 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +73 -36
- package/dest/msg_validators/tx_validator/index.d.ts +2 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +25 -24
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- package/dest/services/dummy_service.d.ts +4 -4
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +4 -4
- package/dest/services/encoding.d.ts +2 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +9 -8
- package/dest/services/gossipsub/topic_score_params.d.ts +18 -6
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +32 -10
- package/dest/services/libp2p/libp2p_service.d.ts +16 -13
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +77 -84
- package/dest/services/peer-manager/metrics.d.ts +3 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +6 -0
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +2 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -3
- 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 +19 -46
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -6
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +10 -13
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +25 -46
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +17 -11
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +49 -15
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- 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 +2 -1
- package/dest/services/service.d.ts +5 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +13 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +30 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +39 -33
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +38 -29
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +126 -77
- package/dest/services/tx_collection/file_store_tx_source.d.ts +16 -6
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +49 -16
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +2 -1
- 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 +5 -4
- package/dest/services/tx_collection/slow_tx_collection.d.ts +5 -3
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +17 -12
- package/dest/services/tx_collection/tx_collection.d.ts +9 -6
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +26 -10
- package/dest/services/tx_collection/tx_collection_sink.d.ts +6 -5
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +13 -22
- package/dest/services/tx_collection/tx_source.d.ts +8 -3
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +19 -2
- package/dest/services/tx_file_store/tx_file_store.d.ts +3 -2
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +9 -6
- 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 +4 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +1 -2
- package/dest/test-helpers/mock-pubsub.d.ts +4 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +8 -2
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -2
- package/dest/test-helpers/testbench-utils.d.ts +8 -3
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +7 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +13 -13
- package/dest/util.d.ts +2 -2
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +39 -48
- package/src/client/interface.ts +17 -20
- package/src/client/p2p_client.ts +60 -104
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +19 -10
- package/src/config.ts +44 -42
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +13 -4
- package/src/mem_pools/attestation_pool/mocks.ts +2 -1
- package/src/mem_pools/instrumentation.ts +17 -13
- package/src/mem_pools/tx_pool/README.md +1 -1
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/README.md +43 -27
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +109 -22
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +5 -2
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -4
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +49 -4
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +24 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +21 -6
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +107 -17
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +43 -16
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +21 -7
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +331 -138
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +1 -1
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +1 -1
- package/src/msg_validators/proposal_validator/proposal_validator.ts +15 -1
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +144 -1
- package/src/msg_validators/tx_validator/README.md +115 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +27 -13
- package/src/msg_validators/tx_validator/factory.ts +353 -77
- package/src/msg_validators/tx_validator/gas_validator.ts +90 -27
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +25 -29
- package/src/msg_validators/tx_validator/timestamp_validator.ts +7 -7
- package/src/services/dummy_service.ts +6 -6
- package/src/services/encoding.ts +7 -7
- package/src/services/gossipsub/README.md +29 -14
- package/src/services/gossipsub/topic_score_params.ts +49 -13
- package/src/services/libp2p/libp2p_service.ts +89 -92
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +2 -1
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +20 -48
- package/src/services/reqresp/batch-tx-requester/interface.ts +1 -5
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +23 -71
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +63 -24
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/reqresp.ts +3 -1
- package/src/services/service.ts +11 -2
- package/src/services/tx_collection/config.ts +42 -0
- package/src/services/tx_collection/fast_tx_collection.ts +51 -30
- package/src/services/tx_collection/file_store_tx_collection.ts +143 -93
- package/src/services/tx_collection/file_store_tx_source.ts +64 -17
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
- package/src/services/tx_collection/slow_tx_collection.ts +17 -13
- package/src/services/tx_collection/tx_collection.ts +45 -14
- package/src/services/tx_collection/tx_collection_sink.ts +15 -29
- package/src/services/tx_collection/tx_source.ts +22 -3
- package/src/services/tx_file_store/tx_file_store.ts +6 -4
- package/src/services/tx_provider.ts +2 -2
- package/src/test-helpers/make-test-p2p-clients.ts +0 -2
- package/src/test-helpers/mock-pubsub.ts +13 -6
- package/src/test-helpers/reqresp-nodes.ts +2 -5
- package/src/test-helpers/testbench-utils.ts +11 -3
- package/src/testbench/p2p_client_testbench_worker.ts +22 -19
- package/src/util.ts +7 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
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';
|
|
@@ -8,6 +9,7 @@ import type { L2Block, L2BlockId, L2BlockSource } from '@aztec/stdlib/block';
|
|
|
8
9
|
import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
9
10
|
import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
|
|
10
11
|
import { BlockHeader, Tx, TxHash, type TxValidator } from '@aztec/stdlib/tx';
|
|
12
|
+
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
11
13
|
|
|
12
14
|
import { TxArchive } from './archive/index.js';
|
|
13
15
|
import { DeletedPool } from './deleted_pool.js';
|
|
@@ -21,8 +23,12 @@ import {
|
|
|
21
23
|
LowPriorityPreAddRule,
|
|
22
24
|
NullifierConflictRule,
|
|
23
25
|
type PoolOperations,
|
|
26
|
+
type PreAddContext,
|
|
24
27
|
type PreAddPoolAccess,
|
|
28
|
+
TxPoolRejectionCode,
|
|
29
|
+
type TxPoolRejectionError,
|
|
25
30
|
} from './eviction/index.js';
|
|
31
|
+
import { TxPoolV2Instrumentation } from './instrumentation.js';
|
|
26
32
|
import {
|
|
27
33
|
type AddTxsResult,
|
|
28
34
|
DEFAULT_TX_POOL_V2_CONFIG,
|
|
@@ -39,6 +45,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
|
|
|
39
45
|
export interface TxPoolV2Callbacks {
|
|
40
46
|
onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
|
|
41
47
|
onTxsRemoved: (txHashes: string[] | bigint[]) => void;
|
|
48
|
+
onTxsMined: (txHashes: string[]) => void;
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
/**
|
|
@@ -64,6 +71,9 @@ export class TxPoolV2Impl {
|
|
|
64
71
|
#archive: TxArchive;
|
|
65
72
|
#deletedPool: DeletedPool;
|
|
66
73
|
#evictionManager: EvictionManager;
|
|
74
|
+
#dateProvider: DateProvider;
|
|
75
|
+
#instrumentation: TxPoolV2Instrumentation;
|
|
76
|
+
#evictedTxHashes: Set<string> = new Set();
|
|
67
77
|
#log: Logger;
|
|
68
78
|
#callbacks: TxPoolV2Callbacks;
|
|
69
79
|
|
|
@@ -72,7 +82,9 @@ export class TxPoolV2Impl {
|
|
|
72
82
|
archiveStore: AztecAsyncKVStore,
|
|
73
83
|
deps: TxPoolV2Dependencies,
|
|
74
84
|
callbacks: TxPoolV2Callbacks,
|
|
85
|
+
telemetry: TelemetryClient,
|
|
75
86
|
config: Partial<TxPoolV2Config> = {},
|
|
87
|
+
dateProvider: DateProvider,
|
|
76
88
|
log: Logger,
|
|
77
89
|
) {
|
|
78
90
|
this.#store = store;
|
|
@@ -85,6 +97,8 @@ export class TxPoolV2Impl {
|
|
|
85
97
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
86
98
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
87
99
|
this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
|
|
100
|
+
this.#dateProvider = dateProvider;
|
|
101
|
+
this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
|
|
88
102
|
this.#log = log;
|
|
89
103
|
this.#callbacks = callbacks;
|
|
90
104
|
|
|
@@ -164,16 +178,43 @@ export class TxPoolV2Impl {
|
|
|
164
178
|
await this.#txsDB.delete(txHashStr);
|
|
165
179
|
}
|
|
166
180
|
});
|
|
167
|
-
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup
|
|
181
|
+
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
|
|
168
182
|
}
|
|
169
183
|
|
|
170
|
-
async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
|
|
184
|
+
async addPendingTxs(txs: Tx[], opts: { source?: string; feeComparisonOnly?: boolean }): Promise<AddTxsResult> {
|
|
171
185
|
const accepted: TxHash[] = [];
|
|
172
186
|
const ignored: TxHash[] = [];
|
|
173
187
|
const rejected: TxHash[] = [];
|
|
188
|
+
const errors = new Map<string, TxPoolRejectionError>();
|
|
174
189
|
const acceptedPending = new Set<string>();
|
|
175
190
|
|
|
191
|
+
// Phase 1: Pre-compute all throwable I/O outside the transaction.
|
|
192
|
+
// If any pre-computation throws, the entire call fails before mutations happen.
|
|
193
|
+
const precomputed = new Map<string, { meta: TxMetaData; minedBlockId: L2BlockId | undefined; isValid: boolean }>();
|
|
194
|
+
|
|
195
|
+
const validator = await this.#createTxValidator();
|
|
196
|
+
|
|
197
|
+
for (const tx of txs) {
|
|
198
|
+
const txHash = tx.getTxHash();
|
|
199
|
+
const txHashStr = txHash.toString();
|
|
200
|
+
|
|
201
|
+
const meta = await buildTxMetaData(tx);
|
|
202
|
+
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
203
|
+
|
|
204
|
+
// Validate non-mined txs (mined and pre-protected txs bypass validation inside the transaction)
|
|
205
|
+
let isValid = true;
|
|
206
|
+
if (!minedBlockId) {
|
|
207
|
+
isValid = await this.#validateMeta(meta, validator);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
precomputed.set(txHashStr, { meta, minedBlockId, isValid });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Phase 2: Apply mutations inside the transaction using only pre-computed results,
|
|
214
|
+
// in-memory reads, and buffered DB writes. Nothing here can throw an unhandled exception.
|
|
176
215
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
216
|
+
const preAddContext: PreAddContext | undefined =
|
|
217
|
+
opts.feeComparisonOnly !== undefined ? { feeComparisonOnly: opts.feeComparisonOnly } : undefined;
|
|
177
218
|
|
|
178
219
|
await this.#store.transactionAsync(async () => {
|
|
179
220
|
for (const tx of txs) {
|
|
@@ -186,30 +227,46 @@ export class TxPoolV2Impl {
|
|
|
186
227
|
continue;
|
|
187
228
|
}
|
|
188
229
|
|
|
189
|
-
|
|
190
|
-
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
230
|
+
const { meta, minedBlockId, isValid } = precomputed.get(txHashStr)!;
|
|
191
231
|
const preProtectedSlot = this.#indices.getProtectionSlot(txHashStr);
|
|
192
232
|
|
|
193
233
|
if (minedBlockId) {
|
|
194
234
|
// Already mined - add directly (protection already set if pre-protected)
|
|
195
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
235
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
196
236
|
accepted.push(txHash);
|
|
197
237
|
} else if (preProtectedSlot !== undefined) {
|
|
198
238
|
// Pre-protected and not mined - add as protected (bypass validation)
|
|
199
|
-
await this.#addTx(tx, { protected: preProtectedSlot }, opts);
|
|
239
|
+
await this.#addTx(tx, { protected: preProtectedSlot }, opts, meta);
|
|
200
240
|
accepted.push(txHash);
|
|
241
|
+
} else if (!isValid) {
|
|
242
|
+
// Failed pre-computed validation
|
|
243
|
+
rejected.push(txHash);
|
|
201
244
|
} else {
|
|
202
|
-
// Regular pending tx -
|
|
203
|
-
const result = await this.#tryAddRegularPendingTx(
|
|
245
|
+
// Regular pending tx - run pre-add rules using pre-computed metadata
|
|
246
|
+
const result = await this.#tryAddRegularPendingTx(
|
|
247
|
+
tx,
|
|
248
|
+
meta,
|
|
249
|
+
opts,
|
|
250
|
+
poolAccess,
|
|
251
|
+
acceptedPending,
|
|
252
|
+
ignored,
|
|
253
|
+
errors,
|
|
254
|
+
preAddContext,
|
|
255
|
+
);
|
|
204
256
|
if (result.status === 'accepted') {
|
|
205
257
|
acceptedPending.add(txHashStr);
|
|
206
|
-
} else if (result.status === 'rejected') {
|
|
207
|
-
rejected.push(txHash);
|
|
208
258
|
} else {
|
|
209
259
|
ignored.push(txHash);
|
|
210
260
|
}
|
|
211
261
|
}
|
|
212
262
|
}
|
|
263
|
+
|
|
264
|
+
// Run post-add eviction rules for pending txs (inside transaction for atomicity)
|
|
265
|
+
if (acceptedPending.size > 0) {
|
|
266
|
+
const feePayers = Array.from(acceptedPending).map(txHash => this.#indices.getMetadata(txHash)!.feePayer);
|
|
267
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
268
|
+
await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
|
|
269
|
+
}
|
|
213
270
|
});
|
|
214
271
|
|
|
215
272
|
// Build final accepted list for pending txs (excludes intra-batch evictions)
|
|
@@ -217,58 +274,80 @@ export class TxPoolV2Impl {
|
|
|
217
274
|
accepted.push(TxHash.fromString(txHashStr));
|
|
218
275
|
}
|
|
219
276
|
|
|
220
|
-
//
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
277
|
+
// Record metrics
|
|
278
|
+
if (ignored.length > 0) {
|
|
279
|
+
this.#instrumentation.recordIgnored(ignored.length);
|
|
280
|
+
}
|
|
281
|
+
if (rejected.length > 0) {
|
|
282
|
+
this.#instrumentation.recordRejected(rejected.length);
|
|
225
283
|
}
|
|
226
284
|
|
|
227
|
-
return { accepted, ignored, rejected };
|
|
285
|
+
return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
|
|
228
286
|
}
|
|
229
287
|
|
|
230
|
-
/**
|
|
288
|
+
/** Adds a validated pending tx, running pre-add rules and evicting conflicts. */
|
|
231
289
|
async #tryAddRegularPendingTx(
|
|
232
290
|
tx: Tx,
|
|
291
|
+
precomputedMeta: TxMetaData,
|
|
233
292
|
opts: { source?: string },
|
|
234
293
|
poolAccess: PreAddPoolAccess,
|
|
235
294
|
acceptedPending: Set<string>,
|
|
236
295
|
ignored: TxHash[],
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// Build metadata and validate using metadata
|
|
242
|
-
const meta = await buildTxMetaData(tx);
|
|
243
|
-
if (!(await this.#validateMeta(meta))) {
|
|
244
|
-
return { status: 'rejected' };
|
|
245
|
-
}
|
|
296
|
+
errors: Map<string, TxPoolRejectionError>,
|
|
297
|
+
preAddContext?: PreAddContext,
|
|
298
|
+
): Promise<{ status: 'accepted' | 'ignored' }> {
|
|
299
|
+
const txHashStr = tx.getTxHash().toString();
|
|
246
300
|
|
|
247
301
|
// Run pre-add rules
|
|
248
|
-
const preAddResult = await this.#evictionManager.runPreAddRules(
|
|
302
|
+
const preAddResult = await this.#evictionManager.runPreAddRules(precomputedMeta, poolAccess, preAddContext);
|
|
249
303
|
|
|
250
304
|
if (preAddResult.shouldIgnore) {
|
|
251
|
-
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason}`);
|
|
305
|
+
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
|
|
306
|
+
if (preAddResult.reason && preAddResult.reason.code !== TxPoolRejectionCode.INTERNAL_ERROR) {
|
|
307
|
+
errors.set(txHashStr, preAddResult.reason);
|
|
308
|
+
}
|
|
252
309
|
return { status: 'ignored' };
|
|
253
310
|
}
|
|
254
311
|
|
|
255
|
-
// Evict conflicts
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
312
|
+
// Evict conflicts, grouped by rule name for metrics
|
|
313
|
+
if (preAddResult.evictions && preAddResult.evictions.length > 0) {
|
|
314
|
+
const byReason = new Map<string, string[]>();
|
|
315
|
+
for (const { txHash: evictHash, reason } of preAddResult.evictions) {
|
|
316
|
+
const group = byReason.get(reason);
|
|
317
|
+
if (group) {
|
|
318
|
+
group.push(evictHash);
|
|
319
|
+
} else {
|
|
320
|
+
byReason.set(reason, [evictHash]);
|
|
321
|
+
}
|
|
263
322
|
}
|
|
323
|
+
for (const [reason, hashes] of byReason) {
|
|
324
|
+
await this.#evictTxs(hashes, reason);
|
|
325
|
+
}
|
|
326
|
+
for (const evictHashStr of preAddResult.txHashesToEvict) {
|
|
327
|
+
this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
|
|
328
|
+
evictedTxHash: evictHashStr,
|
|
329
|
+
replacementTxHash: txHashStr,
|
|
330
|
+
});
|
|
331
|
+
if (acceptedPending.has(evictHashStr)) {
|
|
332
|
+
// Evicted tx was from this batch - mark as ignored in result
|
|
333
|
+
acceptedPending.delete(evictHashStr);
|
|
334
|
+
ignored.push(TxHash.fromString(evictHashStr));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Randomly drop the transaction for testing purposes (report as accepted so it propagates)
|
|
340
|
+
if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
|
|
341
|
+
this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
|
|
342
|
+
return { status: 'accepted' };
|
|
264
343
|
}
|
|
265
344
|
|
|
266
345
|
// Add the transaction
|
|
267
|
-
await this.#addTx(tx, 'pending', opts);
|
|
346
|
+
await this.#addTx(tx, 'pending', opts, precomputedMeta);
|
|
268
347
|
return { status: 'accepted' };
|
|
269
348
|
}
|
|
270
349
|
|
|
271
|
-
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'
|
|
350
|
+
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
|
|
272
351
|
const txHashStr = tx.getTxHash().toString();
|
|
273
352
|
|
|
274
353
|
// Check if already in pool
|
|
@@ -276,14 +355,8 @@ export class TxPoolV2Impl {
|
|
|
276
355
|
return 'ignored';
|
|
277
356
|
}
|
|
278
357
|
|
|
279
|
-
// Build metadata and
|
|
358
|
+
// Build metadata and check pre-add rules
|
|
280
359
|
const meta = await buildTxMetaData(tx);
|
|
281
|
-
const validationResult = await this.#validateMeta(meta, undefined, 'can add pending');
|
|
282
|
-
if (validationResult !== true) {
|
|
283
|
-
return 'rejected';
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Use pre-add rules
|
|
287
360
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
288
361
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
289
362
|
|
|
@@ -320,23 +393,58 @@ export class TxPoolV2Impl {
|
|
|
320
393
|
});
|
|
321
394
|
}
|
|
322
395
|
|
|
323
|
-
protectTxs(txHashes: TxHash[], block: BlockHeader): TxHash[] {
|
|
396
|
+
async protectTxs(txHashes: TxHash[], block: BlockHeader): Promise<TxHash[]> {
|
|
324
397
|
const slotNumber = block.globalVariables.slotNumber;
|
|
325
398
|
const missing: TxHash[] = [];
|
|
399
|
+
let softDeletedHits = 0;
|
|
400
|
+
let missingPreviouslyEvicted = 0;
|
|
326
401
|
|
|
327
|
-
|
|
328
|
-
const
|
|
402
|
+
await this.#store.transactionAsync(async () => {
|
|
403
|
+
for (const txHash of txHashes) {
|
|
404
|
+
const txHashStr = txHash.toString();
|
|
329
405
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
406
|
+
if (this.#indices.has(txHashStr)) {
|
|
407
|
+
// Update protection for existing tx
|
|
408
|
+
this.#indices.updateProtection(txHashStr, slotNumber);
|
|
409
|
+
} else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
410
|
+
// Resurrect soft-deleted tx as protected
|
|
411
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
412
|
+
if (buffer) {
|
|
413
|
+
const tx = Tx.fromBuffer(buffer);
|
|
414
|
+
await this.#addTx(tx, { protected: slotNumber });
|
|
415
|
+
softDeletedHits++;
|
|
416
|
+
} else {
|
|
417
|
+
// Data missing despite soft-delete flag — treat as truly missing
|
|
418
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
419
|
+
missing.push(txHash);
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
// Truly missing — pre-record protection for tx we don't have yet
|
|
423
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
424
|
+
missing.push(txHash);
|
|
425
|
+
if (this.#evictedTxHashes.has(txHashStr)) {
|
|
426
|
+
missingPreviouslyEvicted++;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
337
429
|
}
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// Record metrics
|
|
433
|
+
if (softDeletedHits > 0) {
|
|
434
|
+
this.#instrumentation.recordSoftDeletedHits(softDeletedHits);
|
|
435
|
+
}
|
|
436
|
+
if (missing.length > 0) {
|
|
437
|
+
this.#log.debug(`protectTxs missing tx hashes: ${missing.map(h => h.toString()).join(', ')}`);
|
|
438
|
+
this.#instrumentation.recordMissingOnProtect(missing.length);
|
|
439
|
+
}
|
|
440
|
+
if (missingPreviouslyEvicted > 0) {
|
|
441
|
+
this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
|
|
338
442
|
}
|
|
339
443
|
|
|
444
|
+
this.#log.info(
|
|
445
|
+
`Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`,
|
|
446
|
+
);
|
|
447
|
+
|
|
340
448
|
return missing;
|
|
341
449
|
}
|
|
342
450
|
|
|
@@ -380,54 +488,67 @@ export class TxPoolV2Impl {
|
|
|
380
488
|
}
|
|
381
489
|
}
|
|
382
490
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
491
|
+
await this.#store.transactionAsync(async () => {
|
|
492
|
+
// Step 4: Mark txs as mined (only those we have in the pool)
|
|
493
|
+
for (const meta of found) {
|
|
494
|
+
this.#indices.markAsMined(meta, blockId);
|
|
495
|
+
await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
|
|
496
|
+
}
|
|
388
497
|
|
|
389
|
-
|
|
390
|
-
|
|
498
|
+
// Step 5: Run post-event eviction rules (inside transaction for atomicity)
|
|
499
|
+
await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
if (found.length > 0) {
|
|
503
|
+
this.#callbacks.onTxsMined(found.map(m => m.txHash));
|
|
504
|
+
}
|
|
391
505
|
|
|
392
506
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
393
507
|
}
|
|
394
508
|
|
|
395
509
|
async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
|
|
396
|
-
|
|
397
|
-
|
|
510
|
+
await this.#store.transactionAsync(async () => {
|
|
511
|
+
// Step 0: Clean up slot-deleted txs from previous slots
|
|
512
|
+
await this.#deletedPool.cleanupSlotDeleted(slotNumber);
|
|
398
513
|
|
|
399
|
-
|
|
400
|
-
|
|
514
|
+
// Step 1: Find expired protected txs
|
|
515
|
+
const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
|
|
401
516
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
if (txsToRestore.length === 0) {
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
517
|
+
// Step 2: Clear protection for all expired entries (including those without metadata)
|
|
518
|
+
this.#indices.clearProtection(expiredProtected);
|
|
407
519
|
|
|
408
|
-
|
|
520
|
+
// Step 3: Filter to only txs that have metadata and are not mined
|
|
521
|
+
const txsToRestore = this.#indices.filterRestorable(expiredProtected);
|
|
522
|
+
if (txsToRestore.length === 0) {
|
|
523
|
+
this.#log.debug(`Preparing for slot ${slotNumber}, no txs to unprotect`);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
409
526
|
|
|
410
|
-
|
|
411
|
-
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
|
|
527
|
+
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
412
528
|
|
|
413
|
-
|
|
414
|
-
|
|
529
|
+
// Step 4: Validate for pending pool
|
|
530
|
+
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
|
|
415
531
|
|
|
416
|
-
|
|
417
|
-
|
|
532
|
+
// Step 5: Resolve nullifier conflicts and add winners to pending indices
|
|
533
|
+
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
418
534
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
535
|
+
// Step 6: Delete invalid txs and evict conflict losers
|
|
536
|
+
await this.#deleteTxsBatch(invalid);
|
|
537
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
538
|
+
|
|
539
|
+
// Step 7: Run eviction rules (enforce pool size limit)
|
|
540
|
+
if (added.length > 0) {
|
|
541
|
+
const feePayers = added.map(meta => meta.feePayer);
|
|
542
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
543
|
+
await this.#evictionManager.evictAfterNewTxs(
|
|
544
|
+
added.map(m => m.txHash),
|
|
545
|
+
[...uniqueFeePayers],
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
428
549
|
}
|
|
429
550
|
|
|
430
|
-
async handlePrunedBlocks(latestBlock: L2BlockId): Promise<void> {
|
|
551
|
+
async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
|
|
431
552
|
// Step 1: Find transactions mined after the prune point
|
|
432
553
|
const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
|
|
433
554
|
if (txsToUnmine.length === 0) {
|
|
@@ -437,43 +558,62 @@ export class TxPoolV2Impl {
|
|
|
437
558
|
|
|
438
559
|
this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
|
|
439
560
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
561
|
+
await this.#store.transactionAsync(async () => {
|
|
562
|
+
// Step 2: Mark ALL un-mined txs with their original mined block number
|
|
563
|
+
// This ensures they get soft-deleted if removed later, and only hard-deleted
|
|
564
|
+
// when their original mined block is finalized
|
|
565
|
+
await this.#deletedPool.markFromPrunedBlock(
|
|
566
|
+
txsToUnmine.map(m => ({
|
|
567
|
+
txHash: m.txHash,
|
|
568
|
+
minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
|
|
569
|
+
})),
|
|
570
|
+
);
|
|
449
571
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
572
|
+
// Step 3: Unmine - clear mined status from metadata
|
|
573
|
+
for (const meta of txsToUnmine) {
|
|
574
|
+
this.#indices.markAsUnmined(meta);
|
|
575
|
+
}
|
|
454
576
|
|
|
455
|
-
|
|
456
|
-
|
|
577
|
+
// If deleteAllTxs is set (epoch prune), delete all un-mined txs and return early
|
|
578
|
+
if (options?.deleteAllTxs) {
|
|
579
|
+
const allTxHashes = txsToUnmine.map(m => m.txHash);
|
|
580
|
+
await this.#deleteTxsBatch(allTxHashes);
|
|
581
|
+
this.#log.info(
|
|
582
|
+
`Handled prune to block ${latestBlock.number} with deleteAllTxs: deleted ${allTxHashes.length} txs`,
|
|
583
|
+
);
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
|
|
588
|
+
const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
|
|
457
589
|
|
|
458
|
-
|
|
459
|
-
|
|
590
|
+
// Step 5: Validate for pending pool
|
|
591
|
+
const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
|
|
460
592
|
|
|
461
|
-
|
|
462
|
-
|
|
593
|
+
// Step 6: Resolve nullifier conflicts and add winners to pending indices
|
|
594
|
+
const { toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
463
595
|
|
|
464
|
-
|
|
465
|
-
|
|
596
|
+
// Step 7: Delete invalid txs and evict conflict losers
|
|
597
|
+
await this.#deleteTxsBatch(invalid);
|
|
598
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
466
599
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
600
|
+
this.#log.info(
|
|
601
|
+
`Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`,
|
|
602
|
+
{ txHashesRestored: valid.map(m => m.txHash), txHashesInvalid: invalid, txHashesEvicted: toEvict },
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
// Step 8: Run eviction rules for ALL pending txs (not just restored ones)
|
|
606
|
+
// This handles cases like existing pending txs with invalid fee payer balances
|
|
607
|
+
await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
|
|
608
|
+
});
|
|
470
609
|
}
|
|
471
610
|
|
|
472
611
|
async handleFailedExecution(txHashes: TxHash[]): Promise<void> {
|
|
473
|
-
|
|
474
|
-
|
|
612
|
+
await this.#store.transactionAsync(async () => {
|
|
613
|
+
await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
|
|
614
|
+
});
|
|
475
615
|
|
|
476
|
-
this.#log.info(`Deleted ${txHashes.length} failed txs
|
|
616
|
+
this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
|
|
477
617
|
}
|
|
478
618
|
|
|
479
619
|
async handleFinalizedBlock(block: BlockHeader): Promise<void> {
|
|
@@ -482,30 +622,34 @@ export class TxPoolV2Impl {
|
|
|
482
622
|
// Step 1: Find mined txs at or before finalized block
|
|
483
623
|
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
|
|
484
624
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
625
|
+
await this.#store.transactionAsync(async () => {
|
|
626
|
+
// Step 2: Collect mined txs for archiving (before deletion)
|
|
627
|
+
const txsToArchive: Tx[] = [];
|
|
628
|
+
if (this.#archive.isEnabled()) {
|
|
629
|
+
for (const txHashStr of minedTxsToFinalize) {
|
|
630
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
631
|
+
if (buffer) {
|
|
632
|
+
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
633
|
+
}
|
|
492
634
|
}
|
|
493
635
|
}
|
|
494
|
-
}
|
|
495
636
|
|
|
496
|
-
|
|
497
|
-
|
|
637
|
+
// Step 3: Delete mined txs from active pool
|
|
638
|
+
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
498
639
|
|
|
499
|
-
|
|
500
|
-
|
|
640
|
+
// Step 4: Finalize soft-deleted txs
|
|
641
|
+
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
501
642
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
643
|
+
// Step 5: Archive mined txs
|
|
644
|
+
if (txsToArchive.length > 0) {
|
|
645
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
646
|
+
}
|
|
647
|
+
});
|
|
506
648
|
|
|
507
649
|
if (minedTxsToFinalize.length > 0) {
|
|
508
|
-
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}
|
|
650
|
+
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
|
|
651
|
+
txHashes: minedTxsToFinalize,
|
|
652
|
+
});
|
|
509
653
|
}
|
|
510
654
|
}
|
|
511
655
|
|
|
@@ -549,6 +693,13 @@ export class TxPoolV2Impl {
|
|
|
549
693
|
return [...this.#indices.iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
|
|
550
694
|
}
|
|
551
695
|
|
|
696
|
+
getEligiblePendingTxHashes(): TxHash[] {
|
|
697
|
+
const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
|
|
698
|
+
return [...this.#indices.iterateEligiblePendingByPriority('desc', maxReceivedAt)].map(hash =>
|
|
699
|
+
TxHash.fromString(hash),
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
|
|
552
703
|
getPendingTxCount(): number {
|
|
553
704
|
return this.#indices.getPendingTxCount();
|
|
554
705
|
}
|
|
@@ -593,6 +744,9 @@ export class TxPoolV2Impl {
|
|
|
593
744
|
this.#config.archivedTxLimit = config.archivedTxLimit;
|
|
594
745
|
this.#archive.updateLimit(config.archivedTxLimit);
|
|
595
746
|
}
|
|
747
|
+
if (config.minTxPoolAgeMs !== undefined) {
|
|
748
|
+
this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
|
|
749
|
+
}
|
|
596
750
|
// Update eviction rules with new config
|
|
597
751
|
this.#evictionManager.updateConfig(config);
|
|
598
752
|
}
|
|
@@ -610,8 +764,17 @@ export class TxPoolV2Impl {
|
|
|
610
764
|
|
|
611
765
|
// === Metrics ===
|
|
612
766
|
|
|
613
|
-
countTxs(): {
|
|
614
|
-
|
|
767
|
+
countTxs(): {
|
|
768
|
+
pending: number;
|
|
769
|
+
protected: number;
|
|
770
|
+
mined: number;
|
|
771
|
+
softDeleted: number;
|
|
772
|
+
totalMetadataBytes: number;
|
|
773
|
+
} {
|
|
774
|
+
return {
|
|
775
|
+
...this.#indices.countTxs(),
|
|
776
|
+
softDeleted: this.#deletedPool.getSoftDeletedCount(),
|
|
777
|
+
};
|
|
615
778
|
}
|
|
616
779
|
|
|
617
780
|
// ============================================================================
|
|
@@ -626,11 +789,14 @@ export class TxPoolV2Impl {
|
|
|
626
789
|
tx: Tx,
|
|
627
790
|
state: 'pending' | { protected: SlotNumber } | { mined: L2BlockId },
|
|
628
791
|
opts: { source?: string } = {},
|
|
792
|
+
precomputedMeta?: TxMetaData,
|
|
629
793
|
): Promise<TxMetaData> {
|
|
630
794
|
const txHashStr = tx.getTxHash().toString();
|
|
631
|
-
const meta = await buildTxMetaData(tx);
|
|
795
|
+
const meta = precomputedMeta ?? (await buildTxMetaData(tx));
|
|
796
|
+
meta.receivedAt = this.#dateProvider.now();
|
|
632
797
|
|
|
633
798
|
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
799
|
+
await this.#deletedPool.clearSoftDeleted(txHashStr);
|
|
634
800
|
this.#callbacks.onTxsAdded([tx], opts);
|
|
635
801
|
|
|
636
802
|
if (state === 'pending') {
|
|
@@ -643,9 +809,11 @@ export class TxPoolV2Impl {
|
|
|
643
809
|
}
|
|
644
810
|
|
|
645
811
|
const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
|
|
646
|
-
this.#log.
|
|
812
|
+
this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
|
|
647
813
|
eventName: 'tx-added-to-pool',
|
|
814
|
+
txHash: txHashStr,
|
|
648
815
|
state: stateStr,
|
|
816
|
+
source: opts.source,
|
|
649
817
|
});
|
|
650
818
|
|
|
651
819
|
return meta;
|
|
@@ -673,6 +841,29 @@ export class TxPoolV2Impl {
|
|
|
673
841
|
}
|
|
674
842
|
}
|
|
675
843
|
|
|
844
|
+
/** Evicts transactions: records eviction metric with reason, caches hashes, then deletes. */
|
|
845
|
+
async #evictTxs(txHashes: string[], reason: string): Promise<void> {
|
|
846
|
+
if (txHashes.length === 0) {
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
this.#instrumentation.recordEvictions(txHashes.length, reason);
|
|
850
|
+
for (const txHashStr of txHashes) {
|
|
851
|
+
this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
|
|
852
|
+
this.#addToEvictedCache(txHashStr);
|
|
853
|
+
}
|
|
854
|
+
await this.#deleteTxsBatch(txHashes);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */
|
|
858
|
+
#addToEvictedCache(txHashStr: string): void {
|
|
859
|
+
if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
|
|
860
|
+
// FIFO eviction: remove the first (oldest) entry
|
|
861
|
+
const oldest = this.#evictedTxHashes.values().next().value!;
|
|
862
|
+
this.#evictedTxHashes.delete(oldest);
|
|
863
|
+
}
|
|
864
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
865
|
+
}
|
|
866
|
+
|
|
676
867
|
// ============================================================================
|
|
677
868
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
678
869
|
// ============================================================================
|
|
@@ -828,7 +1019,9 @@ export class TxPoolV2Impl {
|
|
|
828
1019
|
if (preAddResult.shouldIgnore) {
|
|
829
1020
|
// Transaction rejected - mark for deletion from DB
|
|
830
1021
|
rejected.push(meta.txHash);
|
|
831
|
-
this.#log.debug(
|
|
1022
|
+
this.#log.debug(
|
|
1023
|
+
`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`,
|
|
1024
|
+
);
|
|
832
1025
|
continue;
|
|
833
1026
|
}
|
|
834
1027
|
|
|
@@ -864,7 +1057,7 @@ export class TxPoolV2Impl {
|
|
|
864
1057
|
getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
|
|
865
1058
|
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
866
1059
|
getLowestPriorityPending: (limit: number) => this.#indices.getLowestPriorityPending(limit),
|
|
867
|
-
deleteTxs: (txHashes: string[]) => this.#
|
|
1060
|
+
deleteTxs: (txHashes: string[], reason?: string) => this.#evictTxs(txHashes, reason ?? 'unknown'),
|
|
868
1061
|
};
|
|
869
1062
|
}
|
|
870
1063
|
|