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