@aztec/p2p 0.0.1-commit.43c09e3f → 0.0.1-commit.4d3c002
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/README.md +129 -3
- package/dest/client/factory.d.ts +11 -11
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +55 -17
- package/dest/client/interface.d.ts +54 -34
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +41 -52
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +170 -224
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +21 -11
- package/dest/config.d.ts +55 -18
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +102 -38
- package/dest/errors/p2p-service.error.d.ts +9 -0
- package/dest/errors/p2p-service.error.d.ts.map +1 -0
- package/dest/errors/p2p-service.error.js +10 -0
- 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/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +104 -88
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +446 -3
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +353 -87
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -2
- package/dest/mem_pools/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/index.d.ts +3 -3
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/index.js +1 -1
- 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/interface.d.ts +5 -5
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
- 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 +7 -3
- 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 +3 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +2 -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 +34 -12
- 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 +78 -15
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +144 -18
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +108 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +337 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +12 -5
- 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 +23 -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 +476 -594
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +5 -4
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +4 -3
- 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 +53 -41
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +4 -4
- 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/block_header_validator.d.ts +16 -3
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +35 -2
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +13 -3
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
- package/dest/msg_validators/tx_validator/factory.d.ts +133 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +247 -60
- 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 +67 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +104 -37
- 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 +22 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +20 -4
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- package/dest/services/discv5/discV5_service.d.ts +1 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +5 -2
- package/dest/services/dummy_service.d.ts +16 -6
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +15 -5
- package/dest/services/encoding.d.ts +7 -3
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +18 -11
- package/dest/services/gossipsub/index.d.ts +3 -0
- package/dest/services/gossipsub/index.d.ts.map +1 -0
- package/dest/services/gossipsub/index.js +2 -0
- package/dest/services/gossipsub/scoring.d.ts +21 -3
- package/dest/services/gossipsub/scoring.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.js +24 -7
- package/dest/services/gossipsub/topic_score_params.d.ts +173 -0
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
- package/dest/services/gossipsub/topic_score_params.js +346 -0
- package/dest/services/libp2p/libp2p_service.d.ts +108 -51
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +568 -383
- 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 +6 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +24 -9
- package/dest/services/peer-manager/peer_scoring.d.ts +5 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +53 -12
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +14 -10
- 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 +89 -112
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +4 -7
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +11 -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 +31 -46
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -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 +52 -15
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- package/dest/services/reqresp/interface.d.ts +10 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +15 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +7 -5
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +16 -11
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +21 -10
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +27 -11
- package/dest/services/reqresp/protocols/tx.d.ts +7 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
- 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 +30 -14
- package/dest/services/service.d.ts +45 -4
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +22 -4
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +49 -3
- package/dest/services/tx_collection/fast_tx_collection.d.ts +6 -8
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +88 -88
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_collection.js +167 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts +38 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_source.js +100 -0
- package/dest/services/tx_collection/index.d.ts +3 -2
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +1 -0
- package/dest/services/tx_collection/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/proposal_tx_collector.d.ts +15 -15
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +6 -6
- package/dest/services/tx_collection/request_tracker.d.ts +53 -0
- package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/request_tracker.js +84 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +7 -3
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +60 -26
- package/dest/services/tx_collection/tx_collection.d.ts +23 -13
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +75 -3
- package/dest/services/tx_collection/tx_collection_sink.d.ts +18 -8
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +26 -29
- package/dest/services/tx_collection/tx_source.d.ts +13 -7
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +26 -7
- package/dest/services/tx_file_store/config.d.ts +1 -3
- package/dest/services/tx_file_store/config.d.ts.map +1 -1
- package/dest/services/tx_file_store/config.js +0 -4
- package/dest/services/tx_file_store/tx_file_store.d.ts +4 -3
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +9 -6
- package/dest/services/tx_provider.d.ts +4 -4
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +9 -8
- package/dest/test-helpers/make-test-p2p-clients.d.ts +7 -8
- 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 +37 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +113 -5
- 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 +9 -4
- package/dest/test-helpers/testbench-utils.d.ts +43 -38
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +149 -61
- 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 +58 -28
- 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 -3
- package/dest/util.d.ts +9 -5
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +2 -10
- package/package.json +14 -14
- package/src/client/factory.ts +106 -30
- package/src/client/interface.ts +65 -35
- package/src/client/p2p_client.ts +205 -269
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +34 -15
- package/src/config.ts +158 -44
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +1 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +499 -91
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +442 -102
- package/src/mem_pools/attestation_pool/index.ts +9 -2
- package/src/mem_pools/attestation_pool/mocks.ts +2 -1
- package/src/mem_pools/index.ts +2 -2
- package/src/mem_pools/instrumentation.ts +17 -13
- package/src/mem_pools/interface.ts +4 -4
- package/src/mem_pools/tx_pool_v2/README.md +112 -17
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
- 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 +7 -3
- 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 +2 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +34 -12
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +209 -26
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +430 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +37 -8
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +518 -678
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +5 -4
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +2 -2
- package/src/msg_validators/clock_tolerance.ts +4 -3
- package/src/msg_validators/proposal_validator/README.md +123 -0
- 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 +69 -45
- package/src/msg_validators/tx_validator/README.md +119 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +5 -5
- 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/block_header_validator.ts +15 -3
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +42 -1
- package/src/msg_validators/tx_validator/double_spend_validator.ts +11 -6
- package/src/msg_validators/tx_validator/factory.ts +394 -78
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +123 -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 +82 -27
- package/src/msg_validators/tx_validator/timestamp_validator.ts +23 -18
- package/src/services/discv5/discV5_service.ts +5 -2
- package/src/services/dummy_service.ts +24 -7
- package/src/services/encoding.ts +18 -10
- package/src/services/gossipsub/README.md +641 -0
- package/src/services/gossipsub/index.ts +2 -0
- package/src/services/gossipsub/scoring.ts +29 -5
- package/src/services/gossipsub/topic_score_params.ts +487 -0
- package/src/services/libp2p/libp2p_service.ts +599 -418
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +28 -9
- package/src/services/peer-manager/peer_scoring.ts +46 -5
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/README.md +53 -14
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +89 -122
- package/src/services/reqresp/batch-tx-requester/interface.ts +3 -6
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +30 -71
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/interface.ts +26 -1
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +23 -14
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +38 -15
- package/src/services/reqresp/protocols/tx.ts +22 -0
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/reqresp.ts +35 -15
- package/src/services/service.ts +60 -3
- package/src/services/tx_collection/config.ts +74 -6
- package/src/services/tx_collection/fast_tx_collection.ts +94 -97
- package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
- package/src/services/tx_collection/file_store_tx_source.ts +129 -0
- package/src/services/tx_collection/index.ts +2 -1
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/proposal_tx_collector.ts +21 -27
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/slow_tx_collection.ts +66 -33
- package/src/services/tx_collection/tx_collection.ts +114 -19
- package/src/services/tx_collection/tx_collection_sink.ts +30 -34
- package/src/services/tx_collection/tx_source.ts +28 -8
- package/src/services/tx_file_store/config.ts +0 -6
- package/src/services/tx_file_store/tx_file_store.ts +10 -8
- package/src/services/tx_provider.ts +10 -9
- package/src/test-helpers/make-test-p2p-clients.ts +4 -6
- package/src/test-helpers/mock-pubsub.ts +153 -9
- package/src/test-helpers/reqresp-nodes.ts +9 -7
- package/src/test-helpers/testbench-utils.ts +156 -74
- package/src/testbench/p2p_client_testbench_worker.ts +64 -31
- package/src/testbench/worker_client_manager.ts +13 -6
- package/src/util.ts +15 -16
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -40
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -218
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -31
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -180
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
- package/dest/mem_pools/tx_pool/index.d.ts +0 -3
- package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/index.js +0 -2
- package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
- package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/priority.js +0 -15
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
- 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/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -320
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -264
- package/src/mem_pools/tx_pool/README.md +0 -270
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
- package/src/mem_pools/tx_pool/index.ts +0 -2
- package/src/mem_pools/tx_pool/priority.ts +0 -20
- package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
|
+
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
|
+
import type { DateProvider } from '@aztec/foundation/timer';
|
|
3
4
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
4
5
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
6
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
@@ -8,8 +9,10 @@ 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';
|
|
15
|
+
import { DeletedPool } from './deleted_pool.js';
|
|
13
16
|
import {
|
|
14
17
|
EvictionManager,
|
|
15
18
|
FeePayerBalanceEvictionRule,
|
|
@@ -20,8 +23,12 @@ import {
|
|
|
20
23
|
LowPriorityPreAddRule,
|
|
21
24
|
NullifierConflictRule,
|
|
22
25
|
type PoolOperations,
|
|
26
|
+
type PreAddContext,
|
|
23
27
|
type PreAddPoolAccess,
|
|
28
|
+
TxPoolRejectionCode,
|
|
29
|
+
type TxPoolRejectionError,
|
|
24
30
|
} from './eviction/index.js';
|
|
31
|
+
import { TxPoolV2Instrumentation } from './instrumentation.js';
|
|
25
32
|
import {
|
|
26
33
|
type AddTxsResult,
|
|
27
34
|
DEFAULT_TX_POOL_V2_CONFIG,
|
|
@@ -29,14 +36,8 @@ import {
|
|
|
29
36
|
type TxPoolV2Config,
|
|
30
37
|
type TxPoolV2Dependencies,
|
|
31
38
|
} from './interfaces.js';
|
|
32
|
-
import {
|
|
33
|
-
|
|
34
|
-
type TxState,
|
|
35
|
-
buildTxMetaData,
|
|
36
|
-
checkNullifierConflict,
|
|
37
|
-
compareFee,
|
|
38
|
-
compareTxHash,
|
|
39
|
-
} from './tx_metadata.js';
|
|
39
|
+
import { type TxMetaData, type TxState, buildTxMetaData, checkNullifierConflict } from './tx_metadata.js';
|
|
40
|
+
import { TxPoolIndices } from './tx_pool_indices.js';
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
* Callbacks for the implementation to notify the outer class about events and metrics.
|
|
@@ -44,6 +45,7 @@ import {
|
|
|
44
45
|
export interface TxPoolV2Callbacks {
|
|
45
46
|
onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
|
|
46
47
|
onTxsRemoved: (txHashes: string[] | bigint[]) => void;
|
|
48
|
+
onTxsMined: (txHashes: string[]) => void;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
/**
|
|
@@ -59,27 +61,20 @@ export class TxPoolV2Impl {
|
|
|
59
61
|
// === Dependencies ===
|
|
60
62
|
#l2BlockSource: L2BlockSource;
|
|
61
63
|
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
62
|
-
#
|
|
64
|
+
#createTxValidator: TxPoolV2Dependencies['createTxValidator'];
|
|
65
|
+
#checkAllowedSetupCalls: TxPoolV2Dependencies['checkAllowedSetupCalls'];
|
|
63
66
|
|
|
64
67
|
// === In-Memory Indices ===
|
|
65
|
-
|
|
66
|
-
#metadata: Map<string, TxMetaData> = new Map();
|
|
67
|
-
/** Nullifier to txHash index (pending txs only) */
|
|
68
|
-
#nullifierToTxHash: Map<string, string> = new Map();
|
|
69
|
-
/** Fee payer to txHashes index (pending txs only) */
|
|
70
|
-
#feePayerToTxHashes: Map<string, Set<string>> = new Map();
|
|
71
|
-
/**
|
|
72
|
-
* Pending txHashes grouped by priority fee.
|
|
73
|
-
* Outer map: priorityFee -> Set of txHashes at that fee level.
|
|
74
|
-
*/
|
|
75
|
-
#pendingByPriority: Map<bigint, Set<string>> = new Map();
|
|
76
|
-
/** Protected transactions: txHash -> slotNumber. Includes txs we have and txs we expect to receive. */
|
|
77
|
-
#protectedTransactions: Map<string, SlotNumber> = new Map();
|
|
68
|
+
#indices: TxPoolIndices = new TxPoolIndices();
|
|
78
69
|
|
|
79
70
|
// === Config & Services ===
|
|
80
71
|
#config: TxPoolV2Config;
|
|
81
72
|
#archive: TxArchive;
|
|
73
|
+
#deletedPool: DeletedPool;
|
|
82
74
|
#evictionManager: EvictionManager;
|
|
75
|
+
#dateProvider: DateProvider;
|
|
76
|
+
#instrumentation: TxPoolV2Instrumentation;
|
|
77
|
+
#evictedTxHashes: Set<string> = new Set();
|
|
83
78
|
#log: Logger;
|
|
84
79
|
#callbacks: TxPoolV2Callbacks;
|
|
85
80
|
|
|
@@ -88,7 +83,9 @@ export class TxPoolV2Impl {
|
|
|
88
83
|
archiveStore: AztecAsyncKVStore,
|
|
89
84
|
deps: TxPoolV2Dependencies,
|
|
90
85
|
callbacks: TxPoolV2Callbacks,
|
|
86
|
+
telemetry: TelemetryClient,
|
|
91
87
|
config: Partial<TxPoolV2Config> = {},
|
|
88
|
+
dateProvider: DateProvider,
|
|
92
89
|
log: Logger,
|
|
93
90
|
) {
|
|
94
91
|
this.#store = store;
|
|
@@ -96,10 +93,14 @@ export class TxPoolV2Impl {
|
|
|
96
93
|
|
|
97
94
|
this.#l2BlockSource = deps.l2BlockSource;
|
|
98
95
|
this.#worldStateSynchronizer = deps.worldStateSynchronizer;
|
|
99
|
-
this.#
|
|
96
|
+
this.#createTxValidator = deps.createTxValidator;
|
|
97
|
+
this.#checkAllowedSetupCalls = deps.checkAllowedSetupCalls;
|
|
100
98
|
|
|
101
99
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
102
100
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
101
|
+
this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
|
|
102
|
+
this.#dateProvider = dateProvider;
|
|
103
|
+
this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
|
|
103
104
|
this.#log = log;
|
|
104
105
|
this.#callbacks = callbacks;
|
|
105
106
|
|
|
@@ -134,26 +135,42 @@ export class TxPoolV2Impl {
|
|
|
134
135
|
* by running pre-add rules to resolve nullifier conflicts, balance checks, and pool size limits.
|
|
135
136
|
*/
|
|
136
137
|
async hydrateFromDatabase(): Promise<void> {
|
|
137
|
-
// Step
|
|
138
|
+
// Step 0: Hydrate deleted pool state
|
|
139
|
+
await this.#deletedPool.hydrateFromDatabase();
|
|
140
|
+
|
|
141
|
+
// Step 1: Load all transactions from DB (excluding soft-deleted)
|
|
138
142
|
const { loaded, errors: deserializationErrors } = await this.#loadAllTxsFromDb();
|
|
139
143
|
|
|
140
144
|
// Step 2: Check mined status for each tx
|
|
141
145
|
await this.#markMinedStatusBatch(loaded.map(l => l.meta));
|
|
142
146
|
|
|
143
147
|
// Step 3: Partition by mined status
|
|
144
|
-
const
|
|
148
|
+
const mined: TxMetaData[] = [];
|
|
149
|
+
const nonMined: { tx: Tx; meta: TxMetaData }[] = [];
|
|
150
|
+
for (const entry of loaded) {
|
|
151
|
+
if (entry.meta.minedL2BlockId !== undefined) {
|
|
152
|
+
mined.push(entry.meta);
|
|
153
|
+
} else {
|
|
154
|
+
nonMined.push(entry);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
145
157
|
|
|
146
158
|
// Step 4: Validate non-mined transactions
|
|
147
|
-
const { valid, invalid } = await this.#
|
|
159
|
+
const { valid, invalid } = await this.#revalidateMetadata(
|
|
160
|
+
nonMined.map(e => e.meta),
|
|
161
|
+
'on startup',
|
|
162
|
+
);
|
|
148
163
|
|
|
149
164
|
// Step 5: Populate mined indices (these don't need conflict resolution)
|
|
150
|
-
|
|
165
|
+
for (const meta of mined) {
|
|
166
|
+
this.#indices.addMined(meta);
|
|
167
|
+
}
|
|
151
168
|
|
|
152
169
|
// Step 6: Rebuild pending pool by running pre-add rules for each tx
|
|
153
170
|
// This resolves nullifier conflicts, fee payer balance issues, and pool size limits
|
|
154
171
|
const { rejected } = await this.#rebuildPendingPool(valid);
|
|
155
172
|
|
|
156
|
-
// Step 7: Delete invalid and rejected txs from DB
|
|
173
|
+
// Step 7: Delete invalid and rejected txs from DB only (indices were never populated for these)
|
|
157
174
|
const toDelete = [...deserializationErrors, ...invalid, ...rejected];
|
|
158
175
|
if (toDelete.length === 0) {
|
|
159
176
|
return;
|
|
@@ -163,17 +180,45 @@ export class TxPoolV2Impl {
|
|
|
163
180
|
await this.#txsDB.delete(txHashStr);
|
|
164
181
|
}
|
|
165
182
|
});
|
|
166
|
-
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup
|
|
183
|
+
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
|
|
167
184
|
}
|
|
168
185
|
|
|
169
|
-
async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
|
|
186
|
+
async addPendingTxs(txs: Tx[], opts: { source?: string; feeComparisonOnly?: boolean }): Promise<AddTxsResult> {
|
|
170
187
|
const accepted: TxHash[] = [];
|
|
171
188
|
const ignored: TxHash[] = [];
|
|
172
189
|
const rejected: TxHash[] = [];
|
|
173
|
-
const
|
|
190
|
+
const errors = new Map<string, TxPoolRejectionError>();
|
|
174
191
|
const acceptedPending = new Set<string>();
|
|
175
192
|
|
|
193
|
+
// Phase 1: Pre-compute all throwable I/O outside the transaction.
|
|
194
|
+
// If any pre-computation throws, the entire call fails before mutations happen.
|
|
195
|
+
const precomputed = new Map<string, { meta: TxMetaData; minedBlockId: L2BlockId | undefined; isValid: boolean }>();
|
|
196
|
+
|
|
197
|
+
const validator = await this.#createTxValidator();
|
|
198
|
+
|
|
199
|
+
for (const tx of txs) {
|
|
200
|
+
const txHash = tx.getTxHash();
|
|
201
|
+
const txHashStr = txHash.toString();
|
|
202
|
+
|
|
203
|
+
const meta = await buildTxMetaData(tx);
|
|
204
|
+
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
205
|
+
|
|
206
|
+
// Validate non-mined txs (mined and pre-protected txs bypass validation inside the transaction)
|
|
207
|
+
let isValid = true;
|
|
208
|
+
if (!minedBlockId) {
|
|
209
|
+
isValid = await this.#validateMeta(meta, validator);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
precomputed.set(txHashStr, { meta, minedBlockId, isValid });
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Phase 2: Apply mutations inside the transaction using only pre-computed results,
|
|
216
|
+
// in-memory reads, and buffered DB writes. Nothing here can throw an unhandled exception.
|
|
176
217
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
218
|
+
const preAddContext: PreAddContext | undefined =
|
|
219
|
+
opts.feeComparisonOnly !== undefined
|
|
220
|
+
? { feeComparisonOnly: opts.feeComparisonOnly, priceBumpPercentage: this.#config.priceBumpPercentage }
|
|
221
|
+
: undefined;
|
|
177
222
|
|
|
178
223
|
await this.#store.transactionAsync(async () => {
|
|
179
224
|
for (const tx of txs) {
|
|
@@ -181,38 +226,51 @@ export class TxPoolV2Impl {
|
|
|
181
226
|
const txHashStr = txHash.toString();
|
|
182
227
|
|
|
183
228
|
// Skip duplicates
|
|
184
|
-
if (this.#
|
|
229
|
+
if (this.#indices.has(txHashStr)) {
|
|
185
230
|
ignored.push(txHash);
|
|
186
231
|
continue;
|
|
187
232
|
}
|
|
188
233
|
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
const preProtectedSlot = this.#protectedTransactions.get(txHashStr);
|
|
234
|
+
const { meta, minedBlockId, isValid } = precomputed.get(txHashStr)!;
|
|
235
|
+
const preProtectedSlot = this.#indices.getProtectionSlot(txHashStr);
|
|
192
236
|
|
|
193
237
|
if (minedBlockId) {
|
|
194
238
|
// Already mined - add directly (protection already set if pre-protected)
|
|
195
|
-
await this.#
|
|
239
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
196
240
|
accepted.push(txHash);
|
|
197
|
-
newlyAdded.push(tx);
|
|
198
241
|
} else if (preProtectedSlot !== undefined) {
|
|
199
242
|
// Pre-protected and not mined - add as protected (bypass validation)
|
|
200
|
-
await this.#
|
|
243
|
+
await this.#addTx(tx, { protected: preProtectedSlot }, opts, meta);
|
|
201
244
|
accepted.push(txHash);
|
|
202
|
-
|
|
245
|
+
} else if (!isValid) {
|
|
246
|
+
// Failed pre-computed validation
|
|
247
|
+
rejected.push(txHash);
|
|
203
248
|
} else {
|
|
204
|
-
// Regular pending tx -
|
|
205
|
-
const result = await this.#tryAddRegularPendingTx(
|
|
249
|
+
// Regular pending tx - run pre-add rules using pre-computed metadata
|
|
250
|
+
const result = await this.#tryAddRegularPendingTx(
|
|
251
|
+
tx,
|
|
252
|
+
meta,
|
|
253
|
+
opts,
|
|
254
|
+
poolAccess,
|
|
255
|
+
acceptedPending,
|
|
256
|
+
ignored,
|
|
257
|
+
errors,
|
|
258
|
+
preAddContext,
|
|
259
|
+
);
|
|
206
260
|
if (result.status === 'accepted') {
|
|
207
261
|
acceptedPending.add(txHashStr);
|
|
208
|
-
newlyAdded.push(tx);
|
|
209
|
-
} else if (result.status === 'rejected') {
|
|
210
|
-
rejected.push(txHash);
|
|
211
262
|
} else {
|
|
212
263
|
ignored.push(txHash);
|
|
213
264
|
}
|
|
214
265
|
}
|
|
215
266
|
}
|
|
267
|
+
|
|
268
|
+
// Run post-add eviction rules for pending txs (inside transaction for atomicity)
|
|
269
|
+
if (acceptedPending.size > 0) {
|
|
270
|
+
const feePayers = Array.from(acceptedPending).map(txHash => this.#indices.getMetadata(txHash)!.feePayer);
|
|
271
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
272
|
+
await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
|
|
273
|
+
}
|
|
216
274
|
});
|
|
217
275
|
|
|
218
276
|
// Build final accepted list for pending txs (excludes intra-batch evictions)
|
|
@@ -220,164 +278,211 @@ export class TxPoolV2Impl {
|
|
|
220
278
|
accepted.push(TxHash.fromString(txHashStr));
|
|
221
279
|
}
|
|
222
280
|
|
|
223
|
-
//
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
const uniqueFeePayers = new Set<string>(feePayers);
|
|
227
|
-
await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
|
|
281
|
+
// Record metrics
|
|
282
|
+
if (ignored.length > 0) {
|
|
283
|
+
this.#instrumentation.recordIgnored(ignored.length);
|
|
228
284
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (newlyAdded.length > 0) {
|
|
232
|
-
this.#callbacks.onTxsAdded(newlyAdded, opts);
|
|
285
|
+
if (rejected.length > 0) {
|
|
286
|
+
this.#instrumentation.recordRejected(rejected.length);
|
|
233
287
|
}
|
|
234
288
|
|
|
235
|
-
return { accepted, ignored, rejected };
|
|
289
|
+
return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
|
|
236
290
|
}
|
|
237
291
|
|
|
238
|
-
/**
|
|
292
|
+
/** Adds a validated pending tx, running pre-add rules and evicting conflicts. */
|
|
239
293
|
async #tryAddRegularPendingTx(
|
|
240
294
|
tx: Tx,
|
|
295
|
+
precomputedMeta: TxMetaData,
|
|
296
|
+
opts: { source?: string },
|
|
241
297
|
poolAccess: PreAddPoolAccess,
|
|
242
298
|
acceptedPending: Set<string>,
|
|
243
299
|
ignored: TxHash[],
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
300
|
+
errors: Map<string, TxPoolRejectionError>,
|
|
301
|
+
preAddContext?: PreAddContext,
|
|
302
|
+
): Promise<{ status: 'accepted' | 'ignored' }> {
|
|
303
|
+
const txHashStr = tx.getTxHash().toString();
|
|
247
304
|
|
|
248
|
-
//
|
|
249
|
-
const
|
|
250
|
-
if (validationResult.result !== 'valid') {
|
|
251
|
-
this.#log.info(`Rejecting tx ${txHashStr}: ${validationResult.reason?.join(', ')}`);
|
|
252
|
-
return { status: 'rejected' };
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Build metadata and run pre-add rules
|
|
256
|
-
const meta = await buildTxMetaData(tx);
|
|
257
|
-
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
305
|
+
// Run pre-add rules
|
|
306
|
+
const preAddResult = await this.#evictionManager.runPreAddRules(precomputedMeta, poolAccess, preAddContext);
|
|
258
307
|
|
|
259
308
|
if (preAddResult.shouldIgnore) {
|
|
260
|
-
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason}`);
|
|
309
|
+
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
|
|
310
|
+
if (preAddResult.reason && preAddResult.reason.code !== TxPoolRejectionCode.INTERNAL_ERROR) {
|
|
311
|
+
errors.set(txHashStr, preAddResult.reason);
|
|
312
|
+
}
|
|
261
313
|
return { status: 'ignored' };
|
|
262
314
|
}
|
|
263
315
|
|
|
264
|
-
// Evict conflicts
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
316
|
+
// Evict conflicts, grouped by rule name for metrics
|
|
317
|
+
if (preAddResult.evictions && preAddResult.evictions.length > 0) {
|
|
318
|
+
const byReason = new Map<string, string[]>();
|
|
319
|
+
for (const { txHash: evictHash, reason } of preAddResult.evictions) {
|
|
320
|
+
const group = byReason.get(reason);
|
|
321
|
+
if (group) {
|
|
322
|
+
group.push(evictHash);
|
|
323
|
+
} else {
|
|
324
|
+
byReason.set(reason, [evictHash]);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
for (const [reason, hashes] of byReason) {
|
|
328
|
+
await this.#evictTxs(hashes, reason);
|
|
271
329
|
}
|
|
330
|
+
for (const evictHashStr of preAddResult.txHashesToEvict) {
|
|
331
|
+
this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
|
|
332
|
+
evictedTxHash: evictHashStr,
|
|
333
|
+
replacementTxHash: txHashStr,
|
|
334
|
+
});
|
|
335
|
+
if (acceptedPending.has(evictHashStr)) {
|
|
336
|
+
// Evicted tx was from this batch - mark as ignored in result
|
|
337
|
+
acceptedPending.delete(evictHashStr);
|
|
338
|
+
ignored.push(TxHash.fromString(evictHashStr));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Randomly drop the transaction for testing purposes (report as accepted so it propagates)
|
|
344
|
+
if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
|
|
345
|
+
this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
|
|
346
|
+
return { status: 'accepted' };
|
|
272
347
|
}
|
|
273
348
|
|
|
274
349
|
// Add the transaction
|
|
275
|
-
await this.#
|
|
350
|
+
await this.#addTx(tx, 'pending', opts, precomputedMeta);
|
|
276
351
|
return { status: 'accepted' };
|
|
277
352
|
}
|
|
278
353
|
|
|
279
|
-
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'
|
|
354
|
+
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
|
|
280
355
|
const txHashStr = tx.getTxHash().toString();
|
|
281
356
|
|
|
282
357
|
// Check if already in pool
|
|
283
|
-
if (this.#
|
|
358
|
+
if (this.#indices.has(txHashStr)) {
|
|
359
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} already in pool`);
|
|
284
360
|
return 'ignored';
|
|
285
361
|
}
|
|
286
362
|
|
|
287
|
-
//
|
|
288
|
-
const validationResult = await this.#pendingTxValidator.validateTx(tx);
|
|
289
|
-
if (validationResult.result !== 'valid') {
|
|
290
|
-
return 'rejected';
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Build metadata and use pre-add rules
|
|
363
|
+
// Build metadata and check pre-add rules
|
|
294
364
|
const meta = await buildTxMetaData(tx);
|
|
295
365
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
296
366
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
297
367
|
|
|
298
|
-
|
|
368
|
+
if (preAddResult.shouldIgnore) {
|
|
369
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} ignored by pre-add rule`, {
|
|
370
|
+
reason: preAddResult.reason?.message ?? 'no reason provided',
|
|
371
|
+
});
|
|
372
|
+
return 'ignored';
|
|
373
|
+
}
|
|
374
|
+
return 'accepted';
|
|
299
375
|
}
|
|
300
376
|
|
|
301
377
|
async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
|
|
302
378
|
const slotNumber = block.globalVariables.slotNumber;
|
|
303
|
-
|
|
379
|
+
|
|
380
|
+
// Precompute setup-call allow-list flags outside the store transaction
|
|
381
|
+
const allowedFlags = await Promise.all(txs.map(tx => this.#checkAllowedSetupCalls(tx)));
|
|
304
382
|
|
|
305
383
|
await this.#store.transactionAsync(async () => {
|
|
306
|
-
for (
|
|
384
|
+
for (let i = 0; i < txs.length; i++) {
|
|
385
|
+
const tx = txs[i];
|
|
307
386
|
const txHash = tx.getTxHash();
|
|
308
387
|
const txHashStr = txHash.toString();
|
|
309
|
-
const isNew = !this.#
|
|
388
|
+
const isNew = !this.#indices.has(txHashStr);
|
|
310
389
|
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
311
390
|
|
|
312
391
|
if (isNew) {
|
|
313
|
-
|
|
392
|
+
const meta = await buildTxMetaData(tx, allowedFlags[i]);
|
|
393
|
+
// New tx - add as mined or protected (callback emitted by #addTx)
|
|
314
394
|
if (minedBlockId) {
|
|
315
|
-
await this.#
|
|
316
|
-
this.#
|
|
395
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
396
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
317
397
|
} else {
|
|
318
|
-
await this.#
|
|
398
|
+
await this.#addTx(tx, { protected: slotNumber }, opts, meta);
|
|
319
399
|
}
|
|
320
|
-
newlyAdded.push(tx);
|
|
321
400
|
} else {
|
|
322
401
|
// Existing tx - update protection and mined status
|
|
323
|
-
this.#updateProtection(txHashStr, slotNumber);
|
|
402
|
+
this.#indices.updateProtection(txHashStr, slotNumber);
|
|
324
403
|
if (minedBlockId) {
|
|
325
|
-
this.#
|
|
404
|
+
const meta = this.#indices.getMetadata(txHashStr)!;
|
|
405
|
+
this.#indices.markAsMined(meta, minedBlockId);
|
|
326
406
|
}
|
|
327
407
|
}
|
|
328
408
|
}
|
|
329
409
|
});
|
|
330
|
-
|
|
331
|
-
if (newlyAdded.length > 0) {
|
|
332
|
-
this.#callbacks.onTxsAdded(newlyAdded, opts);
|
|
333
|
-
}
|
|
334
410
|
}
|
|
335
411
|
|
|
336
|
-
protectTxs(txHashes: TxHash[], block: BlockHeader): TxHash[] {
|
|
412
|
+
async protectTxs(txHashes: TxHash[], block: BlockHeader): Promise<TxHash[]> {
|
|
337
413
|
const slotNumber = block.globalVariables.slotNumber;
|
|
338
414
|
const missing: TxHash[] = [];
|
|
415
|
+
let softDeletedHits = 0;
|
|
416
|
+
let missingPreviouslyEvicted = 0;
|
|
339
417
|
|
|
340
|
-
|
|
341
|
-
const
|
|
418
|
+
await this.#store.transactionAsync(async () => {
|
|
419
|
+
for (const txHash of txHashes) {
|
|
420
|
+
const txHashStr = txHash.toString();
|
|
342
421
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
422
|
+
if (this.#indices.has(txHashStr)) {
|
|
423
|
+
// Update protection for existing tx
|
|
424
|
+
this.#indices.updateProtection(txHashStr, slotNumber);
|
|
425
|
+
} else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
426
|
+
// Resurrect soft-deleted tx as protected
|
|
427
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
428
|
+
if (buffer) {
|
|
429
|
+
const tx = Tx.fromBuffer(buffer);
|
|
430
|
+
await this.#addTx(tx, { protected: slotNumber });
|
|
431
|
+
softDeletedHits++;
|
|
432
|
+
} else {
|
|
433
|
+
// Data missing despite soft-delete flag — treat as truly missing
|
|
434
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
435
|
+
missing.push(txHash);
|
|
436
|
+
}
|
|
437
|
+
} else {
|
|
438
|
+
// Truly missing — pre-record protection for tx we don't have yet
|
|
439
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
440
|
+
missing.push(txHash);
|
|
441
|
+
if (this.#evictedTxHashes.has(txHashStr)) {
|
|
442
|
+
missingPreviouslyEvicted++;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
350
445
|
}
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// Record metrics
|
|
449
|
+
if (softDeletedHits > 0) {
|
|
450
|
+
this.#instrumentation.recordSoftDeletedHits(softDeletedHits);
|
|
451
|
+
}
|
|
452
|
+
if (missing.length > 0) {
|
|
453
|
+
this.#log.debug(`protectTxs missing tx hashes: ${missing.map(h => h.toString()).join(', ')}`);
|
|
454
|
+
this.#instrumentation.recordMissingOnProtect(missing.length);
|
|
455
|
+
}
|
|
456
|
+
if (missingPreviouslyEvicted > 0) {
|
|
457
|
+
this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
|
|
351
458
|
}
|
|
352
459
|
|
|
460
|
+
this.#log.info(
|
|
461
|
+
`Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`,
|
|
462
|
+
);
|
|
463
|
+
|
|
353
464
|
return missing;
|
|
354
465
|
}
|
|
355
466
|
|
|
356
467
|
async addMinedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
|
|
357
468
|
// Step 1: Build block ID
|
|
358
469
|
const blockId = await this.#buildBlockId(block);
|
|
359
|
-
const newlyAdded: Tx[] = [];
|
|
360
470
|
|
|
361
471
|
await this.#store.transactionAsync(async () => {
|
|
362
472
|
for (const tx of txs) {
|
|
363
473
|
const txHashStr = tx.getTxHash().toString();
|
|
364
|
-
const existingMeta = this.#
|
|
474
|
+
const existingMeta = this.#indices.getMetadata(txHashStr);
|
|
365
475
|
|
|
366
476
|
if (existingMeta) {
|
|
367
|
-
//
|
|
368
|
-
this.#markAsMined(existingMeta, blockId);
|
|
477
|
+
// Mark existing tx as mined
|
|
478
|
+
this.#indices.markAsMined(existingMeta, blockId);
|
|
369
479
|
} else {
|
|
370
|
-
//
|
|
371
|
-
await this.#
|
|
372
|
-
newlyAdded.push(tx);
|
|
480
|
+
// Add new mined tx (callback emitted by #addTx)
|
|
481
|
+
await this.#addTx(tx, { mined: blockId }, opts);
|
|
373
482
|
}
|
|
483
|
+
await this.#deletedPool.clearIfMinedHigher(txHashStr, blockId.number);
|
|
374
484
|
}
|
|
375
485
|
});
|
|
376
|
-
|
|
377
|
-
// Step 3: Emit events for newly added txs
|
|
378
|
-
if (newlyAdded.length > 0) {
|
|
379
|
-
this.#callbacks.onTxsAdded(newlyAdded, opts);
|
|
380
|
-
}
|
|
381
486
|
}
|
|
382
487
|
|
|
383
488
|
async handleMinedBlock(block: L2Block): Promise<void> {
|
|
@@ -392,61 +497,76 @@ export class TxPoolV2Impl {
|
|
|
392
497
|
const feePayers: string[] = [];
|
|
393
498
|
const found: TxMetaData[] = [];
|
|
394
499
|
for (const txHash of txHashes) {
|
|
395
|
-
const meta = this.#
|
|
500
|
+
const meta = this.#indices.getMetadata(txHash.toString());
|
|
396
501
|
if (meta) {
|
|
397
502
|
feePayers.push(meta.feePayer);
|
|
398
503
|
found.push(meta);
|
|
399
504
|
}
|
|
400
505
|
}
|
|
401
506
|
|
|
402
|
-
|
|
403
|
-
|
|
507
|
+
await this.#store.transactionAsync(async () => {
|
|
508
|
+
// Step 4: Mark txs as mined (only those we have in the pool)
|
|
509
|
+
for (const meta of found) {
|
|
510
|
+
this.#indices.markAsMined(meta, blockId);
|
|
511
|
+
await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
|
|
512
|
+
}
|
|
404
513
|
|
|
405
|
-
|
|
406
|
-
|
|
514
|
+
// Step 5: Run post-event eviction rules (inside transaction for atomicity)
|
|
515
|
+
await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
if (found.length > 0) {
|
|
519
|
+
this.#callbacks.onTxsMined(found.map(m => m.txHash));
|
|
520
|
+
}
|
|
407
521
|
|
|
408
|
-
this.#callbacks.onTxsRemoved(txHashes.map(h => h.toBigInt()));
|
|
409
522
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
410
523
|
}
|
|
411
524
|
|
|
412
525
|
async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
|
|
413
|
-
|
|
414
|
-
|
|
526
|
+
await this.#store.transactionAsync(async () => {
|
|
527
|
+
// Step 0: Clean up slot-deleted txs from previous slots
|
|
528
|
+
await this.#deletedPool.cleanupSlotDeleted(slotNumber);
|
|
415
529
|
|
|
416
|
-
|
|
417
|
-
|
|
530
|
+
// Step 1: Find expired protected txs
|
|
531
|
+
const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
|
|
418
532
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
533
|
+
// Step 2: Clear protection for all expired entries (including those without metadata)
|
|
534
|
+
this.#indices.clearProtection(expiredProtected);
|
|
535
|
+
|
|
536
|
+
// Step 3: Filter to only txs that have metadata and are not mined
|
|
537
|
+
const txsToRestore = this.#indices.filterRestorable(expiredProtected);
|
|
538
|
+
if (txsToRestore.length === 0) {
|
|
539
|
+
this.#log.debug(`Preparing for slot ${slotNumber}, no txs to unprotect`);
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
424
542
|
|
|
425
|
-
|
|
543
|
+
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
426
544
|
|
|
427
|
-
|
|
428
|
-
|
|
545
|
+
// Step 4: Validate for pending pool
|
|
546
|
+
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
|
|
429
547
|
|
|
430
|
-
|
|
431
|
-
|
|
548
|
+
// Step 5: Resolve nullifier conflicts and add winners to pending indices
|
|
549
|
+
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
432
550
|
|
|
433
|
-
|
|
434
|
-
|
|
551
|
+
// Step 6: Delete invalid txs and evict conflict losers
|
|
552
|
+
await this.#deleteTxsBatch(invalid);
|
|
553
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
435
554
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
555
|
+
// Step 7: Run eviction rules (enforce pool size limit)
|
|
556
|
+
if (added.length > 0) {
|
|
557
|
+
const feePayers = added.map(meta => meta.feePayer);
|
|
558
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
559
|
+
await this.#evictionManager.evictAfterNewTxs(
|
|
560
|
+
added.map(m => m.txHash),
|
|
561
|
+
[...uniqueFeePayers],
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
});
|
|
445
565
|
}
|
|
446
566
|
|
|
447
|
-
async handlePrunedBlocks(latestBlock: L2BlockId): Promise<void> {
|
|
567
|
+
async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
|
|
448
568
|
// Step 1: Find transactions mined after the prune point
|
|
449
|
-
const txsToUnmine = this.#findTxsMinedAfter(latestBlock.number);
|
|
569
|
+
const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
|
|
450
570
|
if (txsToUnmine.length === 0) {
|
|
451
571
|
this.#log.debug(`No transactions to un-mine for prune to block ${latestBlock.number}`);
|
|
452
572
|
return;
|
|
@@ -454,62 +574,99 @@ export class TxPoolV2Impl {
|
|
|
454
574
|
|
|
455
575
|
this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
|
|
456
576
|
|
|
457
|
-
|
|
458
|
-
|
|
577
|
+
await this.#store.transactionAsync(async () => {
|
|
578
|
+
// Step 2: Mark ALL un-mined txs with their original mined block number
|
|
579
|
+
// This ensures they get soft-deleted if removed later, and only hard-deleted
|
|
580
|
+
// when their original mined block is finalized
|
|
581
|
+
await this.#deletedPool.markFromPrunedBlock(
|
|
582
|
+
txsToUnmine.map(m => ({
|
|
583
|
+
txHash: m.txHash,
|
|
584
|
+
minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
|
|
585
|
+
})),
|
|
586
|
+
);
|
|
459
587
|
|
|
460
|
-
|
|
461
|
-
|
|
588
|
+
// Step 3: Unmine - clear mined status from metadata
|
|
589
|
+
for (const meta of txsToUnmine) {
|
|
590
|
+
this.#indices.markAsUnmined(meta);
|
|
591
|
+
}
|
|
462
592
|
|
|
463
|
-
|
|
464
|
-
|
|
593
|
+
// If deleteAllTxs is set (epoch prune), delete all un-mined txs and return early
|
|
594
|
+
if (options?.deleteAllTxs) {
|
|
595
|
+
const allTxHashes = txsToUnmine.map(m => m.txHash);
|
|
596
|
+
await this.#deleteTxsBatch(allTxHashes);
|
|
597
|
+
this.#log.info(
|
|
598
|
+
`Handled prune to block ${latestBlock.number} with deleteAllTxs: deleted ${allTxHashes.length} txs`,
|
|
599
|
+
);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
465
602
|
|
|
466
|
-
|
|
467
|
-
|
|
603
|
+
// Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
|
|
604
|
+
const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
|
|
468
605
|
|
|
469
|
-
|
|
470
|
-
|
|
606
|
+
// Step 5: Validate for pending pool
|
|
607
|
+
const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
|
|
471
608
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
609
|
+
// Step 6: Resolve nullifier conflicts and add winners to pending indices
|
|
610
|
+
const { toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
611
|
+
|
|
612
|
+
// Step 7: Delete invalid txs and evict conflict losers
|
|
613
|
+
await this.#deleteTxsBatch(invalid);
|
|
614
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
615
|
+
|
|
616
|
+
this.#log.info(
|
|
617
|
+
`Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`,
|
|
618
|
+
{ txHashesRestored: valid.map(m => m.txHash), txHashesInvalid: invalid, txHashesEvicted: toEvict },
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
// Step 8: Run eviction rules for ALL pending txs (not just restored ones)
|
|
622
|
+
// This handles cases like existing pending txs with invalid fee payer balances
|
|
623
|
+
await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
|
|
624
|
+
});
|
|
475
625
|
}
|
|
476
626
|
|
|
477
627
|
async handleFailedExecution(txHashes: TxHash[]): Promise<void> {
|
|
478
|
-
|
|
479
|
-
|
|
628
|
+
await this.#store.transactionAsync(async () => {
|
|
629
|
+
await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
|
|
630
|
+
});
|
|
480
631
|
|
|
481
|
-
this.#log.info(`Deleted ${txHashes.length} failed txs
|
|
632
|
+
this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
|
|
482
633
|
}
|
|
483
634
|
|
|
484
635
|
async handleFinalizedBlock(block: BlockHeader): Promise<void> {
|
|
485
636
|
const blockNumber = block.globalVariables.blockNumber;
|
|
486
637
|
|
|
487
|
-
// Step 1: Find txs
|
|
488
|
-
const
|
|
489
|
-
if (txsToFinalize.length === 0) {
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
638
|
+
// Step 1: Find mined txs at or before finalized block
|
|
639
|
+
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
|
|
492
640
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
641
|
+
await this.#store.transactionAsync(async () => {
|
|
642
|
+
// Step 2: Collect mined txs for archiving (before deletion)
|
|
643
|
+
const txsToArchive: Tx[] = [];
|
|
644
|
+
if (this.#archive.isEnabled()) {
|
|
645
|
+
for (const txHashStr of minedTxsToFinalize) {
|
|
646
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
647
|
+
if (buffer) {
|
|
648
|
+
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
649
|
+
}
|
|
500
650
|
}
|
|
501
651
|
}
|
|
502
|
-
}
|
|
503
652
|
|
|
504
|
-
|
|
505
|
-
|
|
653
|
+
// Step 3: Delete mined txs from active pool
|
|
654
|
+
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
506
655
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
656
|
+
// Step 4: Finalize soft-deleted txs
|
|
657
|
+
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
658
|
+
|
|
659
|
+
// Step 5: Archive mined txs
|
|
660
|
+
if (txsToArchive.length > 0) {
|
|
661
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
662
|
+
}
|
|
663
|
+
});
|
|
511
664
|
|
|
512
|
-
|
|
665
|
+
if (minedTxsToFinalize.length > 0) {
|
|
666
|
+
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
|
|
667
|
+
txHashes: minedTxsToFinalize,
|
|
668
|
+
});
|
|
669
|
+
}
|
|
513
670
|
}
|
|
514
671
|
|
|
515
672
|
// === Query Methods ===
|
|
@@ -529,42 +686,47 @@ export class TxPoolV2Impl {
|
|
|
529
686
|
}
|
|
530
687
|
|
|
531
688
|
hasTxs(txHashes: TxHash[]): boolean[] {
|
|
532
|
-
return txHashes.map(h =>
|
|
689
|
+
return txHashes.map(h => {
|
|
690
|
+
const hashStr = h.toString();
|
|
691
|
+
return this.#indices.has(hashStr) || this.#deletedPool.isSoftDeleted(hashStr);
|
|
692
|
+
});
|
|
533
693
|
}
|
|
534
694
|
|
|
535
695
|
getTxStatus(txHash: TxHash): TxState | undefined {
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
696
|
+
const txHashStr = txHash.toString();
|
|
697
|
+
const meta = this.#indices.getMetadata(txHashStr);
|
|
698
|
+
if (meta) {
|
|
699
|
+
return this.#indices.getTxState(meta);
|
|
700
|
+
}
|
|
701
|
+
// Check if soft-deleted
|
|
702
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
703
|
+
return 'deleted';
|
|
539
704
|
}
|
|
540
|
-
return
|
|
705
|
+
return undefined;
|
|
541
706
|
}
|
|
542
707
|
|
|
543
708
|
getPendingTxHashes(): TxHash[] {
|
|
544
|
-
return [...this.#iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
|
|
709
|
+
return [...this.#indices.iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
getEligiblePendingTxHashes(): TxHash[] {
|
|
713
|
+
const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
|
|
714
|
+
return [...this.#indices.iterateEligiblePendingByPriority('desc', maxReceivedAt)].map(hash =>
|
|
715
|
+
TxHash.fromString(hash),
|
|
716
|
+
);
|
|
545
717
|
}
|
|
546
718
|
|
|
547
719
|
getPendingTxCount(): number {
|
|
548
|
-
|
|
549
|
-
for (const hashes of this.#pendingByPriority.values()) {
|
|
550
|
-
count += hashes.size;
|
|
551
|
-
}
|
|
552
|
-
return count;
|
|
720
|
+
return this.#indices.getPendingTxCount();
|
|
553
721
|
}
|
|
554
722
|
|
|
555
723
|
getMinedTxHashes(): [TxHash, L2BlockId][] {
|
|
556
|
-
|
|
557
|
-
for (const [txHash, meta] of this.#metadata) {
|
|
558
|
-
if (meta.minedL2BlockId !== undefined) {
|
|
559
|
-
result.push([TxHash.fromString(txHash), meta.minedL2BlockId]);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
return result;
|
|
724
|
+
return this.#indices.getMinedTxs().map(([hash, blockId]) => [TxHash.fromString(hash), blockId]);
|
|
563
725
|
}
|
|
564
726
|
|
|
565
727
|
getMinedTxCount(): number {
|
|
566
728
|
let count = 0;
|
|
567
|
-
for (const meta of this.#
|
|
729
|
+
for (const [, meta] of this.#indices.iterateMetadata()) {
|
|
568
730
|
if (meta.minedL2BlockId !== undefined) {
|
|
569
731
|
count++;
|
|
570
732
|
}
|
|
@@ -573,11 +735,11 @@ export class TxPoolV2Impl {
|
|
|
573
735
|
}
|
|
574
736
|
|
|
575
737
|
isEmpty(): boolean {
|
|
576
|
-
return this.#
|
|
738
|
+
return this.#indices.isEmpty();
|
|
577
739
|
}
|
|
578
740
|
|
|
579
741
|
getTxCount(): number {
|
|
580
|
-
return this.#
|
|
742
|
+
return this.#indices.getTxCount();
|
|
581
743
|
}
|
|
582
744
|
|
|
583
745
|
getArchivedTxByHash(txHash: TxHash): Promise<Tx | undefined> {
|
|
@@ -585,18 +747,7 @@ export class TxPoolV2Impl {
|
|
|
585
747
|
}
|
|
586
748
|
|
|
587
749
|
getLowestPriorityPending(limit: number): TxHash[] {
|
|
588
|
-
|
|
589
|
-
return [];
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
const result: TxHash[] = [];
|
|
593
|
-
for (const hash of this.#iteratePendingByPriority('asc')) {
|
|
594
|
-
result.push(TxHash.fromString(hash));
|
|
595
|
-
if (result.length >= limit) {
|
|
596
|
-
break;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
return result;
|
|
750
|
+
return this.#indices.getLowestPriorityPending(limit).map(h => TxHash.fromString(h));
|
|
600
751
|
}
|
|
601
752
|
|
|
602
753
|
// === Configuration ===
|
|
@@ -609,6 +760,9 @@ export class TxPoolV2Impl {
|
|
|
609
760
|
this.#config.archivedTxLimit = config.archivedTxLimit;
|
|
610
761
|
this.#archive.updateLimit(config.archivedTxLimit);
|
|
611
762
|
}
|
|
763
|
+
if (config.minTxPoolAgeMs !== undefined) {
|
|
764
|
+
this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
|
|
765
|
+
}
|
|
612
766
|
// Update eviction rules with new config
|
|
613
767
|
this.#evictionManager.updateConfig(config);
|
|
614
768
|
}
|
|
@@ -617,159 +771,146 @@ export class TxPoolV2Impl {
|
|
|
617
771
|
|
|
618
772
|
getPoolReadAccess(): PoolReadAccess {
|
|
619
773
|
return {
|
|
620
|
-
getMetadata: (txHash: string) => this.#
|
|
621
|
-
getTxHashByNullifier: (nullifier: string) => this.#
|
|
622
|
-
getTxHashesByFeePayer: (feePayer: string) => this.#
|
|
623
|
-
getPendingTxCount: () => this.getPendingTxCount(),
|
|
774
|
+
getMetadata: (txHash: string) => this.#indices.getMetadata(txHash),
|
|
775
|
+
getTxHashByNullifier: (nullifier: string) => this.#indices.getTxHashByNullifier(nullifier),
|
|
776
|
+
getTxHashesByFeePayer: (feePayer: string) => this.#indices.getTxHashesByFeePayer(feePayer),
|
|
777
|
+
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
624
778
|
};
|
|
625
779
|
}
|
|
626
780
|
|
|
627
781
|
// === Metrics ===
|
|
628
782
|
|
|
629
|
-
countTxs(): {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
} else if (state === 'mined') {
|
|
641
|
-
mined++;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
return { pending, protected: protected_, mined };
|
|
783
|
+
countTxs(): {
|
|
784
|
+
pending: number;
|
|
785
|
+
protected: number;
|
|
786
|
+
mined: number;
|
|
787
|
+
softDeleted: number;
|
|
788
|
+
totalMetadataBytes: number;
|
|
789
|
+
} {
|
|
790
|
+
return {
|
|
791
|
+
...this.#indices.countTxs(),
|
|
792
|
+
softDeleted: this.#deletedPool.getSoftDeletedCount(),
|
|
793
|
+
};
|
|
646
794
|
}
|
|
647
795
|
|
|
648
796
|
// ============================================================================
|
|
649
|
-
// PRIVATE
|
|
797
|
+
// PRIVATE HELPERS - Transaction Management
|
|
650
798
|
// ============================================================================
|
|
651
799
|
|
|
652
800
|
/**
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
* - 'mined' if it has a minedL2BlockId
|
|
656
|
-
* - 'protected' if it's in the protectedTransactions map (but not mined)
|
|
657
|
-
* - 'pending' otherwise
|
|
801
|
+
* Adds a new transaction to the pool with the specified state.
|
|
802
|
+
* Emits onTxsAdded callback immediately after DB write.
|
|
658
803
|
*/
|
|
659
|
-
#
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
804
|
+
async #addTx(
|
|
805
|
+
tx: Tx,
|
|
806
|
+
state: 'pending' | { protected: SlotNumber } | { mined: L2BlockId },
|
|
807
|
+
opts: { source?: string } = {},
|
|
808
|
+
precomputedMeta?: TxMetaData,
|
|
809
|
+
): Promise<TxMetaData> {
|
|
810
|
+
const txHashStr = tx.getTxHash().toString();
|
|
811
|
+
const meta = precomputedMeta ?? (await buildTxMetaData(tx));
|
|
812
|
+
meta.receivedAt = this.#dateProvider.now();
|
|
813
|
+
|
|
814
|
+
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
815
|
+
await this.#deletedPool.clearSoftDeleted(txHashStr);
|
|
816
|
+
this.#callbacks.onTxsAdded([tx], opts);
|
|
817
|
+
|
|
818
|
+
if (state === 'pending') {
|
|
819
|
+
this.#indices.addPending(meta);
|
|
820
|
+
} else if ('protected' in state) {
|
|
821
|
+
this.#indices.addProtected(meta, state.protected);
|
|
664
822
|
} else {
|
|
665
|
-
|
|
823
|
+
meta.minedL2BlockId = state.mined;
|
|
824
|
+
this.#indices.addMined(meta);
|
|
666
825
|
}
|
|
826
|
+
|
|
827
|
+
const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
|
|
828
|
+
this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
|
|
829
|
+
eventName: 'tx-added-to-pool',
|
|
830
|
+
txHash: txHashStr,
|
|
831
|
+
state: stateStr,
|
|
832
|
+
source: opts.source,
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
return meta;
|
|
667
836
|
}
|
|
668
837
|
|
|
669
838
|
/**
|
|
670
|
-
*
|
|
671
|
-
*
|
|
839
|
+
* Deletes a transaction from both indices and DB.
|
|
840
|
+
* Emits onTxsRemoved callback immediately after DB delete.
|
|
672
841
|
*/
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
for (const fee of sortedFees) {
|
|
683
|
-
const hashesAtFee = this.#pendingByPriority.get(fee)!;
|
|
684
|
-
const sortedHashes = [...hashesAtFee].sort(hashCompareFn);
|
|
685
|
-
for (const hash of sortedHashes) {
|
|
686
|
-
yield hash;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
842
|
+
/**
|
|
843
|
+
* Deletes a transaction from the pool.
|
|
844
|
+
* Delegates to DeletedPool which decides soft vs hard delete based on whether
|
|
845
|
+
* the tx is from a pruned block.
|
|
846
|
+
*/
|
|
847
|
+
async #deleteTx(txHashStr: string): Promise<void> {
|
|
848
|
+
this.#indices.remove(txHashStr);
|
|
849
|
+
this.#callbacks.onTxsRemoved([txHashStr]);
|
|
850
|
+
await this.#deletedPool.deleteTx(txHashStr);
|
|
689
851
|
}
|
|
690
852
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
// --- Finding & Filtering Steps ---
|
|
696
|
-
|
|
697
|
-
/** Finds all transactions mined in blocks after the given block number */
|
|
698
|
-
#findTxsMinedAfter(blockNumber: number): TxMetaData[] {
|
|
699
|
-
const result: TxMetaData[] = [];
|
|
700
|
-
for (const meta of this.#metadata.values()) {
|
|
701
|
-
if (meta.minedL2BlockId !== undefined && meta.minedL2BlockId.number > blockNumber) {
|
|
702
|
-
result.push(meta);
|
|
703
|
-
}
|
|
853
|
+
/** Deletes a batch of transactions, emitting callbacks individually for each. */
|
|
854
|
+
async #deleteTxsBatch(txHashes: string[]): Promise<void> {
|
|
855
|
+
for (const txHashStr of txHashes) {
|
|
856
|
+
await this.#deleteTx(txHashStr);
|
|
704
857
|
}
|
|
705
|
-
return result;
|
|
706
858
|
}
|
|
707
859
|
|
|
708
|
-
/**
|
|
709
|
-
#
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
860
|
+
/** Evicts transactions: records eviction metric with reason, caches hashes, then deletes. */
|
|
861
|
+
async #evictTxs(txHashes: string[], reason: string): Promise<void> {
|
|
862
|
+
if (txHashes.length === 0) {
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
this.#instrumentation.recordEvictions(txHashes.length, reason);
|
|
866
|
+
for (const txHashStr of txHashes) {
|
|
867
|
+
this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
|
|
868
|
+
this.#addToEvictedCache(txHashStr);
|
|
715
869
|
}
|
|
716
|
-
|
|
870
|
+
await this.#deleteTxsBatch(txHashes);
|
|
717
871
|
}
|
|
718
872
|
|
|
719
|
-
/**
|
|
720
|
-
#
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
}
|
|
873
|
+
/** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */
|
|
874
|
+
#addToEvictedCache(txHashStr: string): void {
|
|
875
|
+
if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
|
|
876
|
+
// FIFO eviction: remove the first (oldest) entry
|
|
877
|
+
const oldest = this.#evictedTxHashes.values().next().value!;
|
|
878
|
+
this.#evictedTxHashes.delete(oldest);
|
|
726
879
|
}
|
|
727
|
-
|
|
880
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
728
881
|
}
|
|
729
882
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
}
|
|
883
|
+
// ============================================================================
|
|
884
|
+
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
885
|
+
// ============================================================================
|
|
734
886
|
|
|
735
|
-
/**
|
|
736
|
-
#
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
887
|
+
/** Validates transaction metadata, returning true if valid */
|
|
888
|
+
async #validateMeta(meta: TxMetaData, validator?: TxValidator<TxMetaData>, context?: string): Promise<boolean> {
|
|
889
|
+
const txValidator = validator ?? (await this.#createTxValidator());
|
|
890
|
+
const result = await txValidator.validateTx(meta);
|
|
891
|
+
if (result.result !== 'valid') {
|
|
892
|
+
const contextStr = context ? ` ${context}` : '';
|
|
893
|
+
this.#log.info(`Tx ${meta.txHash}${contextStr} failed validation: ${result.reason?.join(', ')}`);
|
|
894
|
+
return false;
|
|
743
895
|
}
|
|
744
|
-
return
|
|
896
|
+
return true;
|
|
745
897
|
}
|
|
746
898
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
899
|
+
/** Validates metadata directly */
|
|
900
|
+
async #revalidateMetadata(
|
|
901
|
+
metas: TxMetaData[],
|
|
902
|
+
context?: string,
|
|
903
|
+
): Promise<{ valid: TxMetaData[]; invalid: string[] }> {
|
|
751
904
|
const valid: TxMetaData[] = [];
|
|
752
905
|
const invalid: string[] = [];
|
|
753
|
-
|
|
754
|
-
for (const meta of
|
|
755
|
-
|
|
756
|
-
if (!buffer) {
|
|
757
|
-
this.#log.warn(`Tx ${meta.txHash} not found in DB during validation`);
|
|
758
|
-
invalid.push(meta.txHash);
|
|
759
|
-
continue;
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
const tx = Tx.fromBuffer(buffer);
|
|
763
|
-
const result = await this.#pendingTxValidator.validateTx(tx);
|
|
764
|
-
|
|
765
|
-
if (result.result === 'valid') {
|
|
906
|
+
const validator = await this.#createTxValidator();
|
|
907
|
+
for (const meta of metas) {
|
|
908
|
+
if (await this.#validateMeta(meta, validator, context)) {
|
|
766
909
|
valid.push(meta);
|
|
767
910
|
} else {
|
|
768
|
-
this.#log.info(`Tx ${meta.txHash} failed validation: ${result.reason?.join(', ')}`);
|
|
769
911
|
invalid.push(meta.txHash);
|
|
770
912
|
}
|
|
771
913
|
}
|
|
772
|
-
|
|
773
914
|
return { valid, invalid };
|
|
774
915
|
}
|
|
775
916
|
|
|
@@ -785,8 +926,8 @@ export class TxPoolV2Impl {
|
|
|
785
926
|
for (const meta of txs) {
|
|
786
927
|
const conflict = checkNullifierConflict(
|
|
787
928
|
meta,
|
|
788
|
-
nullifier => this.#
|
|
789
|
-
txHash => this.#
|
|
929
|
+
nullifier => this.#indices.getTxHashByNullifier(nullifier),
|
|
930
|
+
txHash => this.#indices.getMetadata(txHash),
|
|
790
931
|
);
|
|
791
932
|
if (conflict.shouldIgnore) {
|
|
792
933
|
// Lower priority than existing - don't add, mark for deletion
|
|
@@ -796,13 +937,13 @@ export class TxPoolV2Impl {
|
|
|
796
937
|
toEvict.push(...conflict.txHashesToEvict);
|
|
797
938
|
// Remove evicted from indices immediately for subsequent checks
|
|
798
939
|
for (const evictHash of conflict.txHashesToEvict) {
|
|
799
|
-
const evictMeta = this.#
|
|
940
|
+
const evictMeta = this.#indices.getMetadata(evictHash);
|
|
800
941
|
if (evictMeta) {
|
|
801
|
-
this.#removeFromPendingIndices(evictMeta);
|
|
942
|
+
this.#indices.removeFromPendingIndices(evictMeta);
|
|
802
943
|
}
|
|
803
944
|
}
|
|
804
945
|
// Add to pending indices immediately so subsequent txs in the batch see this tx
|
|
805
|
-
this.#addToPendingIndices(meta);
|
|
946
|
+
this.#indices.addToPendingIndices(meta);
|
|
806
947
|
added.push(meta);
|
|
807
948
|
}
|
|
808
949
|
}
|
|
@@ -810,43 +951,10 @@ export class TxPoolV2Impl {
|
|
|
810
951
|
return { added, toEvict };
|
|
811
952
|
}
|
|
812
953
|
|
|
813
|
-
//
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
#unmineTxs(txs: TxMetaData[]): TxMetaData[] {
|
|
817
|
-
for (const meta of txs) {
|
|
818
|
-
meta.minedL2BlockId = undefined;
|
|
819
|
-
}
|
|
820
|
-
return txs;
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
/** Removes protection from tx hashes and clears them from the protected map */
|
|
824
|
-
#clearProtection(txHashes: string[]): void {
|
|
825
|
-
for (const txHashStr of txHashes) {
|
|
826
|
-
this.#protectedTransactions.delete(txHashStr);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
// --- Batch Operation Steps ---
|
|
831
|
-
|
|
832
|
-
/** Deletes a batch of transactions permanently */
|
|
833
|
-
async #deleteTxsBatch(txHashes: string[]): Promise<void> {
|
|
834
|
-
if (txHashes.length === 0) {
|
|
835
|
-
return;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
await this.#store.transactionAsync(async () => {
|
|
839
|
-
for (const txHashStr of txHashes) {
|
|
840
|
-
await this.#deleteTx(txHashStr);
|
|
841
|
-
}
|
|
842
|
-
});
|
|
843
|
-
|
|
844
|
-
this.#callbacks.onTxsRemoved(txHashes);
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
// --- Block & Tx Info Steps ---
|
|
954
|
+
// ============================================================================
|
|
955
|
+
// PRIVATE HELPERS - Block & Hydration
|
|
956
|
+
// ============================================================================
|
|
848
957
|
|
|
849
|
-
/** Builds a block ID from a block header */
|
|
850
958
|
async #buildBlockId(block: BlockHeader): Promise<L2BlockId> {
|
|
851
959
|
return {
|
|
852
960
|
number: block.globalVariables.blockNumber,
|
|
@@ -866,50 +974,6 @@ export class TxPoolV2Impl {
|
|
|
866
974
|
};
|
|
867
975
|
}
|
|
868
976
|
|
|
869
|
-
/** Marks a batch of transactions as mined */
|
|
870
|
-
#markTxsAsMined(metas: TxMetaData[], blockId: L2BlockId): void {
|
|
871
|
-
for (const meta of metas) {
|
|
872
|
-
this.#markAsMined(meta, blockId);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
// --- Add Transaction Steps ---
|
|
877
|
-
|
|
878
|
-
/** Persists a transaction to the database */
|
|
879
|
-
async #persistTx(txHashStr: string, tx: Tx): Promise<void> {
|
|
880
|
-
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
/** Adds a new transaction as protected, returning its metadata */
|
|
884
|
-
async #addNewProtectedTx(tx: Tx, slotNumber: SlotNumber): Promise<TxMetaData> {
|
|
885
|
-
const txHashStr = tx.getTxHash().toString();
|
|
886
|
-
const meta = await buildTxMetaData(tx);
|
|
887
|
-
|
|
888
|
-
this.#protectedTransactions.set(txHashStr, slotNumber);
|
|
889
|
-
await this.#persistTx(txHashStr, tx);
|
|
890
|
-
this.#metadata.set(txHashStr, meta);
|
|
891
|
-
// Don't add to pending indices since it's protected
|
|
892
|
-
|
|
893
|
-
this.#log.verbose(`Added protected tx ${txHashStr} for slot ${slotNumber}`);
|
|
894
|
-
return meta;
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
/** Adds a new transaction as mined, returning its metadata */
|
|
898
|
-
async #addNewMinedTx(tx: Tx, blockId: L2BlockId): Promise<TxMetaData> {
|
|
899
|
-
const txHashStr = tx.getTxHash().toString();
|
|
900
|
-
const meta = await buildTxMetaData(tx);
|
|
901
|
-
meta.minedL2BlockId = blockId;
|
|
902
|
-
|
|
903
|
-
await this.#persistTx(txHashStr, tx);
|
|
904
|
-
this.#metadata.set(txHashStr, meta);
|
|
905
|
-
// Don't add to pending indices since it's mined
|
|
906
|
-
|
|
907
|
-
this.#log.verbose(`Added mined tx ${txHashStr} from block ${blockId.number}`);
|
|
908
|
-
return meta;
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
// --- Hydration Steps ---
|
|
912
|
-
|
|
913
977
|
/** Loads all transactions from the database, returning loaded txs and deserialization errors */
|
|
914
978
|
async #loadAllTxsFromDb(): Promise<{
|
|
915
979
|
loaded: { tx: Tx; meta: TxMetaData }[];
|
|
@@ -919,9 +983,15 @@ export class TxPoolV2Impl {
|
|
|
919
983
|
const errors: string[] = [];
|
|
920
984
|
|
|
921
985
|
for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
|
|
986
|
+
// Skip soft-deleted transactions - they stay in DB but not in indices
|
|
987
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
|
|
922
991
|
try {
|
|
923
992
|
const tx = Tx.fromBuffer(buffer);
|
|
924
|
-
const
|
|
993
|
+
const allowedSetupCalls = await this.#checkAllowedSetupCalls(tx);
|
|
994
|
+
const meta = await buildTxMetaData(tx, allowedSetupCalls);
|
|
925
995
|
loaded.push({ tx, meta });
|
|
926
996
|
} catch (err) {
|
|
927
997
|
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
@@ -949,50 +1019,6 @@ export class TxPoolV2Impl {
|
|
|
949
1019
|
}
|
|
950
1020
|
}
|
|
951
1021
|
|
|
952
|
-
/** Partitions transactions by mined status */
|
|
953
|
-
#partitionByMinedStatus(txs: { tx: Tx; meta: TxMetaData }[]): {
|
|
954
|
-
mined: TxMetaData[];
|
|
955
|
-
nonMined: { tx: Tx; meta: TxMetaData }[];
|
|
956
|
-
} {
|
|
957
|
-
const mined: TxMetaData[] = [];
|
|
958
|
-
const nonMined: { tx: Tx; meta: TxMetaData }[] = [];
|
|
959
|
-
|
|
960
|
-
for (const entry of txs) {
|
|
961
|
-
if (entry.meta.minedL2BlockId !== undefined) {
|
|
962
|
-
mined.push(entry.meta);
|
|
963
|
-
} else {
|
|
964
|
-
nonMined.push(entry);
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
return { mined, nonMined };
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
/** Validates non-mined transactions, returning valid metadata and invalid hashes */
|
|
972
|
-
async #validateNonMinedTxs(txs: { tx: Tx; meta: TxMetaData }[]): Promise<{ valid: TxMetaData[]; invalid: string[] }> {
|
|
973
|
-
const valid: TxMetaData[] = [];
|
|
974
|
-
const invalid: string[] = [];
|
|
975
|
-
|
|
976
|
-
for (const { tx, meta } of txs) {
|
|
977
|
-
const result = await this.#pendingTxValidator.validateTx(tx);
|
|
978
|
-
if (result.result === 'valid') {
|
|
979
|
-
valid.push(meta);
|
|
980
|
-
} else {
|
|
981
|
-
this.#log.info(`Removing invalid tx ${meta.txHash} on startup: ${result.reason?.join(', ')}`);
|
|
982
|
-
invalid.push(meta.txHash);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
return { valid, invalid };
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
/** Populates metadata index for mined transactions */
|
|
990
|
-
#populateMinedIndices(metas: TxMetaData[]): void {
|
|
991
|
-
for (const meta of metas) {
|
|
992
|
-
this.#metadata.set(meta.txHash, meta);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
|
|
996
1022
|
/**
|
|
997
1023
|
* Rebuilds the pending pool by processing each tx through pre-add rules.
|
|
998
1024
|
* Starts with an empty pending pool and adds txs one by one, resolving conflicts.
|
|
@@ -1010,24 +1036,26 @@ export class TxPoolV2Impl {
|
|
|
1010
1036
|
if (preAddResult.shouldIgnore) {
|
|
1011
1037
|
// Transaction rejected - mark for deletion from DB
|
|
1012
1038
|
rejected.push(meta.txHash);
|
|
1013
|
-
this.#log.debug(
|
|
1039
|
+
this.#log.debug(
|
|
1040
|
+
`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`,
|
|
1041
|
+
);
|
|
1014
1042
|
continue;
|
|
1015
1043
|
}
|
|
1016
1044
|
|
|
1017
1045
|
// Evict any conflicting txs identified by pre-add rules
|
|
1018
1046
|
for (const evictHashStr of preAddResult.txHashesToEvict) {
|
|
1019
|
-
const evictMeta = this.#
|
|
1047
|
+
const evictMeta = this.#indices.getMetadata(evictHashStr);
|
|
1020
1048
|
if (evictMeta) {
|
|
1021
|
-
this.#removeFromPendingIndices(evictMeta);
|
|
1022
|
-
this.#
|
|
1049
|
+
this.#indices.removeFromPendingIndices(evictMeta);
|
|
1050
|
+
this.#indices.remove(evictHashStr);
|
|
1023
1051
|
rejected.push(evictHashStr);
|
|
1024
1052
|
accepted.delete(evictHashStr);
|
|
1025
1053
|
this.#log.debug(`Evicted tx ${evictHashStr} during rebuild due to conflict with ${meta.txHash}`);
|
|
1026
1054
|
}
|
|
1027
1055
|
}
|
|
1028
1056
|
|
|
1029
|
-
// Add to
|
|
1030
|
-
this.#
|
|
1057
|
+
// Add to indices
|
|
1058
|
+
this.#indices.addPending(meta);
|
|
1031
1059
|
accepted.add(meta.txHash);
|
|
1032
1060
|
}
|
|
1033
1061
|
|
|
@@ -1035,207 +1063,32 @@ export class TxPoolV2Impl {
|
|
|
1035
1063
|
return { accepted: [...accepted], rejected };
|
|
1036
1064
|
}
|
|
1037
1065
|
|
|
1038
|
-
// --- Add Pending Tx Steps ---
|
|
1039
|
-
|
|
1040
|
-
/** Checks if a tx is a duplicate (already in pool) */
|
|
1041
|
-
#isDuplicateTx(txHashStr: string): boolean {
|
|
1042
|
-
return this.#metadata.has(txHashStr);
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
/** Adds a new pending tx to the pool, returning its metadata */
|
|
1046
|
-
async #addNewPendingTx(tx: Tx): Promise<TxMetaData> {
|
|
1047
|
-
const txHashStr = tx.getTxHash().toString();
|
|
1048
|
-
const meta = await buildTxMetaData(tx);
|
|
1049
|
-
|
|
1050
|
-
await this.#persistTx(txHashStr, tx);
|
|
1051
|
-
this.#addToIndices(meta);
|
|
1052
|
-
|
|
1053
|
-
this.#log.verbose(`Added tx ${txHashStr} to pool`, {
|
|
1054
|
-
eventName: 'tx-added-to-pool',
|
|
1055
|
-
state: this.#getTxState(meta),
|
|
1056
|
-
});
|
|
1057
|
-
|
|
1058
|
-
return meta;
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
1066
|
// ============================================================================
|
|
1062
|
-
//
|
|
1067
|
+
// PRIVATE HELPERS - Pool Access Adapters
|
|
1063
1068
|
// ============================================================================
|
|
1064
1069
|
|
|
1065
|
-
#addToIndices(meta: TxMetaData): void {
|
|
1066
|
-
this.#metadata.set(meta.txHash, meta);
|
|
1067
|
-
|
|
1068
|
-
if (this.#getTxState(meta) === 'pending') {
|
|
1069
|
-
this.#addToPendingIndices(meta);
|
|
1070
|
-
}
|
|
1071
|
-
// Protected and mined txs don't go into pending indices
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
#addToPendingIndices(meta: TxMetaData): void {
|
|
1075
|
-
// Add to nullifier index
|
|
1076
|
-
for (const nullifier of meta.nullifiers) {
|
|
1077
|
-
this.#nullifierToTxHash.set(nullifier, meta.txHash);
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
// Add to fee payer index
|
|
1081
|
-
let feePayerSet = this.#feePayerToTxHashes.get(meta.feePayer);
|
|
1082
|
-
if (!feePayerSet) {
|
|
1083
|
-
feePayerSet = new Set();
|
|
1084
|
-
this.#feePayerToTxHashes.set(meta.feePayer, feePayerSet);
|
|
1085
|
-
}
|
|
1086
|
-
feePayerSet.add(meta.txHash);
|
|
1087
|
-
|
|
1088
|
-
// Add to priority bucket
|
|
1089
|
-
let prioritySet = this.#pendingByPriority.get(meta.priorityFee);
|
|
1090
|
-
if (!prioritySet) {
|
|
1091
|
-
prioritySet = new Set();
|
|
1092
|
-
this.#pendingByPriority.set(meta.priorityFee, prioritySet);
|
|
1093
|
-
}
|
|
1094
|
-
prioritySet.add(meta.txHash);
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
#removeFromPendingIndices(meta: TxMetaData): void {
|
|
1098
|
-
// Remove from nullifier index
|
|
1099
|
-
for (const nullifier of meta.nullifiers) {
|
|
1100
|
-
this.#nullifierToTxHash.delete(nullifier);
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
// Remove from fee payer index
|
|
1104
|
-
const feePayerSet = this.#feePayerToTxHashes.get(meta.feePayer);
|
|
1105
|
-
if (feePayerSet) {
|
|
1106
|
-
feePayerSet.delete(meta.txHash);
|
|
1107
|
-
if (feePayerSet.size === 0) {
|
|
1108
|
-
this.#feePayerToTxHashes.delete(meta.feePayer);
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
// Remove from priority map
|
|
1113
|
-
const hashSet = this.#pendingByPriority.get(meta.priorityFee);
|
|
1114
|
-
if (hashSet) {
|
|
1115
|
-
hashSet.delete(meta.txHash);
|
|
1116
|
-
if (hashSet.size === 0) {
|
|
1117
|
-
this.#pendingByPriority.delete(meta.priorityFee);
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
#updateProtection(txHashStr: string, slotNumber: SlotNumber): void {
|
|
1123
|
-
const currentSlot = this.#protectedTransactions.get(txHashStr);
|
|
1124
|
-
|
|
1125
|
-
// Only update if not already protected at an equal or later slot
|
|
1126
|
-
if (currentSlot !== undefined && currentSlot >= slotNumber) {
|
|
1127
|
-
return;
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
// Remove from pending indices if transitioning from pending to protected
|
|
1131
|
-
if (currentSlot === undefined) {
|
|
1132
|
-
const meta = this.#metadata.get(txHashStr);
|
|
1133
|
-
if (meta) {
|
|
1134
|
-
this.#removeFromPendingIndices(meta);
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
this.#protectedTransactions.set(txHashStr, slotNumber);
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
#markAsMined(meta: TxMetaData, blockId: L2BlockId): void {
|
|
1142
|
-
meta.minedL2BlockId = blockId;
|
|
1143
|
-
// Safe to call unconditionally - removeFromPendingIndices is idempotent
|
|
1144
|
-
this.#removeFromPendingIndices(meta);
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
async #deleteTx(txHashStr: string): Promise<void> {
|
|
1148
|
-
const meta = this.#metadata.get(txHashStr);
|
|
1149
|
-
if (!meta) {
|
|
1150
|
-
return;
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
// Remove from all indices
|
|
1154
|
-
this.#metadata.delete(txHashStr);
|
|
1155
|
-
this.#protectedTransactions.delete(txHashStr);
|
|
1156
|
-
this.#removeFromPendingIndices(meta);
|
|
1157
|
-
|
|
1158
|
-
// Remove from persistence
|
|
1159
|
-
await this.#txsDB.delete(txHashStr);
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
// ============================================================================
|
|
1163
|
-
// HELPER FUNCTIONS - Adapters
|
|
1164
|
-
// ============================================================================
|
|
1165
|
-
|
|
1166
|
-
/** Gets all pending transactions for a given fee payer. */
|
|
1167
|
-
#getFeePayerPendingTxs(feePayer: string): TxMetaData[] {
|
|
1168
|
-
const txHashes = this.#feePayerToTxHashes.get(feePayer);
|
|
1169
|
-
if (!txHashes) {
|
|
1170
|
-
return [];
|
|
1171
|
-
}
|
|
1172
|
-
const result: TxMetaData[] = [];
|
|
1173
|
-
for (const txHashStr of txHashes) {
|
|
1174
|
-
const meta = this.#metadata.get(txHashStr);
|
|
1175
|
-
if (meta && this.#getTxState(meta) === 'pending') {
|
|
1176
|
-
result.push(meta);
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
return result;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
/**
|
|
1183
|
-
* Creates a PoolOperations adapter for use with the eviction manager.
|
|
1184
|
-
*/
|
|
1185
1070
|
#createPoolOperations(): PoolOperations {
|
|
1186
1071
|
return {
|
|
1187
|
-
getPendingTxs: ()
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
result.push(meta);
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
return result;
|
|
1198
|
-
},
|
|
1199
|
-
getPendingFeePayers: (): string[] => {
|
|
1200
|
-
return Array.from(this.#feePayerToTxHashes.keys());
|
|
1201
|
-
},
|
|
1202
|
-
getFeePayerPendingTxs: (feePayer: string): TxMetaData[] => {
|
|
1203
|
-
return this.#getFeePayerPendingTxs(feePayer);
|
|
1204
|
-
},
|
|
1205
|
-
getPendingTxCount: (): number => {
|
|
1206
|
-
return this.getPendingTxCount();
|
|
1207
|
-
},
|
|
1208
|
-
getLowestPriorityPending: (limit: number): string[] => {
|
|
1209
|
-
return this.getLowestPriorityPending(limit).map(h => h.toString());
|
|
1210
|
-
},
|
|
1211
|
-
deleteTxs: async (txHashes: string[]): Promise<void> => {
|
|
1212
|
-
await this.#store.transactionAsync(async () => {
|
|
1213
|
-
for (const txHashStr of txHashes) {
|
|
1214
|
-
await this.#deleteTx(txHashStr);
|
|
1215
|
-
}
|
|
1216
|
-
});
|
|
1217
|
-
this.#callbacks.onTxsRemoved(txHashes);
|
|
1218
|
-
},
|
|
1072
|
+
getPendingTxs: () => this.#indices.getPendingTxs(),
|
|
1073
|
+
getPendingFeePayers: () => this.#indices.getPendingFeePayers(),
|
|
1074
|
+
getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
|
|
1075
|
+
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
1076
|
+
getLowestPriorityPending: (limit: number) => this.#indices.getLowestPriorityPending(limit),
|
|
1077
|
+
deleteTxs: (txHashes: string[], reason?: string) => this.#evictTxs(txHashes, reason ?? 'unknown'),
|
|
1219
1078
|
};
|
|
1220
1079
|
}
|
|
1221
1080
|
|
|
1222
|
-
/**
|
|
1223
|
-
* Creates a PreAddPoolAccess adapter for use with pre-add eviction rules.
|
|
1224
|
-
* All methods work with strings and TxMetaData for efficiency.
|
|
1225
|
-
*/
|
|
1226
1081
|
#createPreAddPoolAccess(): PreAddPoolAccess {
|
|
1227
1082
|
return {
|
|
1228
|
-
getMetadata: (txHashStr: string)
|
|
1229
|
-
const meta = this.#
|
|
1230
|
-
if (!meta || this.#getTxState(meta) !== 'pending') {
|
|
1083
|
+
getMetadata: (txHashStr: string) => {
|
|
1084
|
+
const meta = this.#indices.getMetadata(txHashStr);
|
|
1085
|
+
if (!meta || this.#indices.getTxState(meta) !== 'pending') {
|
|
1231
1086
|
return undefined;
|
|
1232
1087
|
}
|
|
1233
1088
|
return meta;
|
|
1234
1089
|
},
|
|
1235
|
-
getTxHashByNullifier: (nullifier: string)
|
|
1236
|
-
|
|
1237
|
-
},
|
|
1238
|
-
getFeePayerBalance: async (feePayer: string): Promise<bigint> => {
|
|
1090
|
+
getTxHashByNullifier: (nullifier: string) => this.#indices.getTxHashByNullifier(nullifier),
|
|
1091
|
+
getFeePayerBalance: async (feePayer: string) => {
|
|
1239
1092
|
const db = this.#worldStateSynchronizer.getCommitted();
|
|
1240
1093
|
const publicStateSource = new DatabasePublicStateSource(db);
|
|
1241
1094
|
const balance = await publicStateSource.storageRead(
|
|
@@ -1244,22 +1097,9 @@ export class TxPoolV2Impl {
|
|
|
1244
1097
|
);
|
|
1245
1098
|
return balance.toBigInt();
|
|
1246
1099
|
},
|
|
1247
|
-
getFeePayerPendingTxs: (feePayer: string)
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
getPendingTxCount: (): number => {
|
|
1251
|
-
return this.getPendingTxCount();
|
|
1252
|
-
},
|
|
1253
|
-
getLowestPriorityPendingTx: (): TxMetaData | undefined => {
|
|
1254
|
-
// Iterate in ascending order to find the lowest priority
|
|
1255
|
-
for (const txHashStr of this.#iteratePendingByPriority('asc')) {
|
|
1256
|
-
const meta = this.#metadata.get(txHashStr);
|
|
1257
|
-
if (meta) {
|
|
1258
|
-
return meta;
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
return undefined;
|
|
1262
|
-
},
|
|
1100
|
+
getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
|
|
1101
|
+
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
1102
|
+
getLowestPriorityPendingTx: () => this.#indices.getLowestPriorityPendingTx(),
|
|
1263
1103
|
};
|
|
1264
1104
|
}
|
|
1265
1105
|
}
|