@aztec/p2p 0.0.1-commit.f2ce05ee → 0.0.1-commit.f5d02921e
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 +9 -9
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +52 -14
- package/dest/client/interface.d.ts +47 -34
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +39 -51
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +164 -224
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +20 -10
- package/dest/config.d.ts +52 -16
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +100 -37
- 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 +21 -12
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +75 -40
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- 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 +57 -57
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +2 -2
- package/dest/mem_pools/index.d.ts +2 -2
- package/dest/mem_pools/index.d.ts.map +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 +3 -3
- 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 +30 -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 -19
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +50 -45
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +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 +17 -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 +364 -189
- 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/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/dummy_service.d.ts +12 -6
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +12 -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/topic_score_params.d.ts +18 -6
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +32 -10
- package/dest/services/libp2p/libp2p_service.d.ts +37 -23
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +274 -173
- 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 +28 -10
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +12 -8
- 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 +83 -106
- 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 +3 -3
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +7 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +15 -0
- package/dest/services/reqresp/protocols/tx.d.ts +7 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/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 +26 -4
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +19 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +46 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +3 -4
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +80 -76
- 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 +2 -1
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +1 -0
- package/dest/services/tx_collection/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 +7 -7
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
- package/dest/services/tx_collection/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 +30 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +105 -4
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -2
- package/dest/test-helpers/testbench-utils.d.ts +35 -24
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +115 -38
- 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 +57 -27
- 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 +3 -3
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +102 -25
- package/src/client/interface.ts +52 -34
- package/src/client/p2p_client.ts +190 -266
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +33 -14
- package/src/config.ts +149 -43
- 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 +104 -50
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +61 -57
- package/src/mem_pools/attestation_pool/index.ts +3 -3
- package/src/mem_pools/attestation_pool/mocks.ts +2 -1
- package/src/mem_pools/index.ts +1 -1
- package/src/mem_pools/instrumentation.ts +17 -13
- package/src/mem_pools/interface.ts +2 -2
- package/src/mem_pools/tx_pool_v2/README.md +85 -11
- 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 +32 -12
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +209 -27
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +58 -45
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +34 -8
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +410 -187
- 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/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/dummy_service.ts +18 -7
- package/src/services/encoding.ts +18 -10
- package/src/services/gossipsub/README.md +29 -14
- package/src/services/gossipsub/topic_score_params.ts +49 -13
- package/src/services/libp2p/libp2p_service.ts +288 -198
- 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 +21 -5
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/README.md +46 -7
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +79 -112
- 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 +2 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +17 -0
- package/src/services/reqresp/protocols/tx.ts +22 -0
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/reqresp.ts +35 -15
- package/src/services/service.ts +37 -3
- package/src/services/tx_collection/config.ts +68 -0
- package/src/services/tx_collection/fast_tx_collection.ts +83 -76
- 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 +1 -0
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/proposal_tx_collector.ts +9 -13
- 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 +146 -9
- package/src/test-helpers/reqresp-nodes.ts +3 -6
- package/src/test-helpers/testbench-utils.ts +137 -43
- package/src/testbench/p2p_client_testbench_worker.ts +63 -30
- package/src/testbench/worker_client_manager.ts +13 -6
- package/src/util.ts +8 -2
- 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/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,
|
|
@@ -38,6 +45,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
|
|
|
38
45
|
export interface TxPoolV2Callbacks {
|
|
39
46
|
onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
|
|
40
47
|
onTxsRemoved: (txHashes: string[] | bigint[]) => void;
|
|
48
|
+
onTxsMined: (txHashes: string[]) => void;
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
/**
|
|
@@ -53,7 +61,8 @@ export class TxPoolV2Impl {
|
|
|
53
61
|
// === Dependencies ===
|
|
54
62
|
#l2BlockSource: L2BlockSource;
|
|
55
63
|
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
56
|
-
#
|
|
64
|
+
#createTxValidator: TxPoolV2Dependencies['createTxValidator'];
|
|
65
|
+
#checkAllowedSetupCalls: TxPoolV2Dependencies['checkAllowedSetupCalls'];
|
|
57
66
|
|
|
58
67
|
// === In-Memory Indices ===
|
|
59
68
|
#indices: TxPoolIndices = new TxPoolIndices();
|
|
@@ -61,7 +70,11 @@ export class TxPoolV2Impl {
|
|
|
61
70
|
// === Config & Services ===
|
|
62
71
|
#config: TxPoolV2Config;
|
|
63
72
|
#archive: TxArchive;
|
|
73
|
+
#deletedPool: DeletedPool;
|
|
64
74
|
#evictionManager: EvictionManager;
|
|
75
|
+
#dateProvider: DateProvider;
|
|
76
|
+
#instrumentation: TxPoolV2Instrumentation;
|
|
77
|
+
#evictedTxHashes: Set<string> = new Set();
|
|
65
78
|
#log: Logger;
|
|
66
79
|
#callbacks: TxPoolV2Callbacks;
|
|
67
80
|
|
|
@@ -70,7 +83,9 @@ export class TxPoolV2Impl {
|
|
|
70
83
|
archiveStore: AztecAsyncKVStore,
|
|
71
84
|
deps: TxPoolV2Dependencies,
|
|
72
85
|
callbacks: TxPoolV2Callbacks,
|
|
86
|
+
telemetry: TelemetryClient,
|
|
73
87
|
config: Partial<TxPoolV2Config> = {},
|
|
88
|
+
dateProvider: DateProvider,
|
|
74
89
|
log: Logger,
|
|
75
90
|
) {
|
|
76
91
|
this.#store = store;
|
|
@@ -78,10 +93,14 @@ export class TxPoolV2Impl {
|
|
|
78
93
|
|
|
79
94
|
this.#l2BlockSource = deps.l2BlockSource;
|
|
80
95
|
this.#worldStateSynchronizer = deps.worldStateSynchronizer;
|
|
81
|
-
this.#
|
|
96
|
+
this.#createTxValidator = deps.createTxValidator;
|
|
97
|
+
this.#checkAllowedSetupCalls = deps.checkAllowedSetupCalls;
|
|
82
98
|
|
|
83
99
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
84
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());
|
|
85
104
|
this.#log = log;
|
|
86
105
|
this.#callbacks = callbacks;
|
|
87
106
|
|
|
@@ -116,7 +135,10 @@ export class TxPoolV2Impl {
|
|
|
116
135
|
* by running pre-add rules to resolve nullifier conflicts, balance checks, and pool size limits.
|
|
117
136
|
*/
|
|
118
137
|
async hydrateFromDatabase(): Promise<void> {
|
|
119
|
-
// 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)
|
|
120
142
|
const { loaded, errors: deserializationErrors } = await this.#loadAllTxsFromDb();
|
|
121
143
|
|
|
122
144
|
// Step 2: Check mined status for each tx
|
|
@@ -134,7 +156,10 @@ export class TxPoolV2Impl {
|
|
|
134
156
|
}
|
|
135
157
|
|
|
136
158
|
// Step 4: Validate non-mined transactions
|
|
137
|
-
const { valid, invalid } = await this.#
|
|
159
|
+
const { valid, invalid } = await this.#revalidateMetadata(
|
|
160
|
+
nonMined.map(e => e.meta),
|
|
161
|
+
'on startup',
|
|
162
|
+
);
|
|
138
163
|
|
|
139
164
|
// Step 5: Populate mined indices (these don't need conflict resolution)
|
|
140
165
|
for (const meta of mined) {
|
|
@@ -155,16 +180,45 @@ export class TxPoolV2Impl {
|
|
|
155
180
|
await this.#txsDB.delete(txHashStr);
|
|
156
181
|
}
|
|
157
182
|
});
|
|
158
|
-
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 });
|
|
159
184
|
}
|
|
160
185
|
|
|
161
|
-
async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
|
|
186
|
+
async addPendingTxs(txs: Tx[], opts: { source?: string; feeComparisonOnly?: boolean }): Promise<AddTxsResult> {
|
|
162
187
|
const accepted: TxHash[] = [];
|
|
163
188
|
const ignored: TxHash[] = [];
|
|
164
189
|
const rejected: TxHash[] = [];
|
|
190
|
+
const errors = new Map<string, TxPoolRejectionError>();
|
|
165
191
|
const acceptedPending = new Set<string>();
|
|
166
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.
|
|
167
217
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
218
|
+
const preAddContext: PreAddContext | undefined =
|
|
219
|
+
opts.feeComparisonOnly !== undefined
|
|
220
|
+
? { feeComparisonOnly: opts.feeComparisonOnly, priceBumpPercentage: this.#config.priceBumpPercentage }
|
|
221
|
+
: undefined;
|
|
168
222
|
|
|
169
223
|
await this.#store.transactionAsync(async () => {
|
|
170
224
|
for (const tx of txs) {
|
|
@@ -177,30 +231,46 @@ export class TxPoolV2Impl {
|
|
|
177
231
|
continue;
|
|
178
232
|
}
|
|
179
233
|
|
|
180
|
-
|
|
181
|
-
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
234
|
+
const { meta, minedBlockId, isValid } = precomputed.get(txHashStr)!;
|
|
182
235
|
const preProtectedSlot = this.#indices.getProtectionSlot(txHashStr);
|
|
183
236
|
|
|
184
237
|
if (minedBlockId) {
|
|
185
238
|
// Already mined - add directly (protection already set if pre-protected)
|
|
186
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
239
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
187
240
|
accepted.push(txHash);
|
|
188
241
|
} else if (preProtectedSlot !== undefined) {
|
|
189
242
|
// Pre-protected and not mined - add as protected (bypass validation)
|
|
190
|
-
await this.#addTx(tx, { protected: preProtectedSlot }, opts);
|
|
243
|
+
await this.#addTx(tx, { protected: preProtectedSlot }, opts, meta);
|
|
191
244
|
accepted.push(txHash);
|
|
245
|
+
} else if (!isValid) {
|
|
246
|
+
// Failed pre-computed validation
|
|
247
|
+
rejected.push(txHash);
|
|
192
248
|
} else {
|
|
193
|
-
// Regular pending tx -
|
|
194
|
-
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
|
+
);
|
|
195
260
|
if (result.status === 'accepted') {
|
|
196
261
|
acceptedPending.add(txHashStr);
|
|
197
|
-
} else if (result.status === 'rejected') {
|
|
198
|
-
rejected.push(txHash);
|
|
199
262
|
} else {
|
|
200
263
|
ignored.push(txHash);
|
|
201
264
|
}
|
|
202
265
|
}
|
|
203
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
|
+
}
|
|
204
274
|
});
|
|
205
275
|
|
|
206
276
|
// Build final accepted list for pending txs (excludes intra-batch evictions)
|
|
@@ -208,96 +278,124 @@ export class TxPoolV2Impl {
|
|
|
208
278
|
accepted.push(TxHash.fromString(txHashStr));
|
|
209
279
|
}
|
|
210
280
|
|
|
211
|
-
//
|
|
212
|
-
if (
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
281
|
+
// Record metrics
|
|
282
|
+
if (ignored.length > 0) {
|
|
283
|
+
this.#instrumentation.recordIgnored(ignored.length);
|
|
284
|
+
}
|
|
285
|
+
if (rejected.length > 0) {
|
|
286
|
+
this.#instrumentation.recordRejected(rejected.length);
|
|
216
287
|
}
|
|
217
288
|
|
|
218
|
-
return { accepted, ignored, rejected };
|
|
289
|
+
return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
|
|
219
290
|
}
|
|
220
291
|
|
|
221
|
-
/**
|
|
292
|
+
/** Adds a validated pending tx, running pre-add rules and evicting conflicts. */
|
|
222
293
|
async #tryAddRegularPendingTx(
|
|
223
294
|
tx: Tx,
|
|
295
|
+
precomputedMeta: TxMetaData,
|
|
224
296
|
opts: { source?: string },
|
|
225
297
|
poolAccess: PreAddPoolAccess,
|
|
226
298
|
acceptedPending: Set<string>,
|
|
227
299
|
ignored: TxHash[],
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
// Validate transaction
|
|
233
|
-
if (!(await this.#validateTx(tx))) {
|
|
234
|
-
return { status: 'rejected' };
|
|
235
|
-
}
|
|
300
|
+
errors: Map<string, TxPoolRejectionError>,
|
|
301
|
+
preAddContext?: PreAddContext,
|
|
302
|
+
): Promise<{ status: 'accepted' | 'ignored' }> {
|
|
303
|
+
const txHashStr = tx.getTxHash().toString();
|
|
236
304
|
|
|
237
|
-
//
|
|
238
|
-
const
|
|
239
|
-
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
305
|
+
// Run pre-add rules
|
|
306
|
+
const preAddResult = await this.#evictionManager.runPreAddRules(precomputedMeta, poolAccess, preAddContext);
|
|
240
307
|
|
|
241
308
|
if (preAddResult.shouldIgnore) {
|
|
242
|
-
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
|
+
}
|
|
243
313
|
return { status: 'ignored' };
|
|
244
314
|
}
|
|
245
315
|
|
|
246
|
-
// Evict conflicts
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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);
|
|
254
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' };
|
|
255
347
|
}
|
|
256
348
|
|
|
257
349
|
// Add the transaction
|
|
258
|
-
await this.#addTx(tx, 'pending', opts);
|
|
350
|
+
await this.#addTx(tx, 'pending', opts, precomputedMeta);
|
|
259
351
|
return { status: 'accepted' };
|
|
260
352
|
}
|
|
261
353
|
|
|
262
|
-
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'
|
|
354
|
+
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
|
|
263
355
|
const txHashStr = tx.getTxHash().toString();
|
|
264
356
|
|
|
265
357
|
// Check if already in pool
|
|
266
358
|
if (this.#indices.has(txHashStr)) {
|
|
359
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} already in pool`);
|
|
267
360
|
return 'ignored';
|
|
268
361
|
}
|
|
269
362
|
|
|
270
|
-
//
|
|
271
|
-
const validationResult = await this.#pendingTxValidator.validateTx(tx);
|
|
272
|
-
if (validationResult.result !== 'valid') {
|
|
273
|
-
return 'rejected';
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Build metadata and use pre-add rules
|
|
363
|
+
// Build metadata and check pre-add rules
|
|
277
364
|
const meta = await buildTxMetaData(tx);
|
|
278
365
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
279
366
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
280
367
|
|
|
281
|
-
|
|
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';
|
|
282
375
|
}
|
|
283
376
|
|
|
284
377
|
async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
|
|
285
378
|
const slotNumber = block.globalVariables.slotNumber;
|
|
286
379
|
|
|
380
|
+
// Precompute setup-call allow-list flags outside the store transaction
|
|
381
|
+
const allowedFlags = await Promise.all(txs.map(tx => this.#checkAllowedSetupCalls(tx)));
|
|
382
|
+
|
|
287
383
|
await this.#store.transactionAsync(async () => {
|
|
288
|
-
for (
|
|
384
|
+
for (let i = 0; i < txs.length; i++) {
|
|
385
|
+
const tx = txs[i];
|
|
289
386
|
const txHash = tx.getTxHash();
|
|
290
387
|
const txHashStr = txHash.toString();
|
|
291
388
|
const isNew = !this.#indices.has(txHashStr);
|
|
292
389
|
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
293
390
|
|
|
294
391
|
if (isNew) {
|
|
392
|
+
const meta = await buildTxMetaData(tx, allowedFlags[i]);
|
|
295
393
|
// New tx - add as mined or protected (callback emitted by #addTx)
|
|
296
394
|
if (minedBlockId) {
|
|
297
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
395
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
298
396
|
this.#indices.setProtection(txHashStr, slotNumber);
|
|
299
397
|
} else {
|
|
300
|
-
await this.#addTx(tx, { protected: slotNumber }, opts);
|
|
398
|
+
await this.#addTx(tx, { protected: slotNumber }, opts, meta);
|
|
301
399
|
}
|
|
302
400
|
} else {
|
|
303
401
|
// Existing tx - update protection and mined status
|
|
@@ -311,22 +409,57 @@ export class TxPoolV2Impl {
|
|
|
311
409
|
});
|
|
312
410
|
}
|
|
313
411
|
|
|
314
|
-
protectTxs(txHashes: TxHash[], block: BlockHeader): TxHash[] {
|
|
412
|
+
async protectTxs(txHashes: TxHash[], block: BlockHeader): Promise<TxHash[]> {
|
|
315
413
|
const slotNumber = block.globalVariables.slotNumber;
|
|
316
414
|
const missing: TxHash[] = [];
|
|
415
|
+
let softDeletedHits = 0;
|
|
416
|
+
let missingPreviouslyEvicted = 0;
|
|
317
417
|
|
|
318
|
-
|
|
319
|
-
const
|
|
418
|
+
await this.#store.transactionAsync(async () => {
|
|
419
|
+
for (const txHash of txHashes) {
|
|
420
|
+
const txHashStr = txHash.toString();
|
|
320
421
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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
|
+
}
|
|
328
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);
|
|
329
455
|
}
|
|
456
|
+
if (missingPreviouslyEvicted > 0) {
|
|
457
|
+
this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
this.#log.info(
|
|
461
|
+
`Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`,
|
|
462
|
+
);
|
|
330
463
|
|
|
331
464
|
return missing;
|
|
332
465
|
}
|
|
@@ -347,6 +480,7 @@ export class TxPoolV2Impl {
|
|
|
347
480
|
// Add new mined tx (callback emitted by #addTx)
|
|
348
481
|
await this.#addTx(tx, { mined: blockId }, opts);
|
|
349
482
|
}
|
|
483
|
+
await this.#deletedPool.clearIfMinedHigher(txHashStr, blockId.number);
|
|
350
484
|
}
|
|
351
485
|
});
|
|
352
486
|
}
|
|
@@ -370,53 +504,67 @@ export class TxPoolV2Impl {
|
|
|
370
504
|
}
|
|
371
505
|
}
|
|
372
506
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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
|
+
}
|
|
513
|
+
|
|
514
|
+
// Step 5: Run post-event eviction rules (inside transaction for atomicity)
|
|
515
|
+
await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
|
|
516
|
+
});
|
|
377
517
|
|
|
378
|
-
|
|
379
|
-
|
|
518
|
+
if (found.length > 0) {
|
|
519
|
+
this.#callbacks.onTxsMined(found.map(m => m.txHash));
|
|
520
|
+
}
|
|
380
521
|
|
|
381
522
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
382
523
|
}
|
|
383
524
|
|
|
384
525
|
async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
|
|
385
|
-
|
|
386
|
-
|
|
526
|
+
await this.#store.transactionAsync(async () => {
|
|
527
|
+
// Step 0: Clean up slot-deleted txs from previous slots
|
|
528
|
+
await this.#deletedPool.cleanupSlotDeleted(slotNumber);
|
|
387
529
|
|
|
388
|
-
|
|
389
|
-
|
|
530
|
+
// Step 1: Find expired protected txs
|
|
531
|
+
const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
|
|
390
532
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
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
|
+
}
|
|
396
542
|
|
|
397
|
-
|
|
543
|
+
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
398
544
|
|
|
399
|
-
|
|
400
|
-
|
|
545
|
+
// Step 4: Validate for pending pool
|
|
546
|
+
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
|
|
401
547
|
|
|
402
|
-
|
|
403
|
-
|
|
548
|
+
// Step 5: Resolve nullifier conflicts and add winners to pending indices
|
|
549
|
+
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
404
550
|
|
|
405
|
-
|
|
406
|
-
|
|
551
|
+
// Step 6: Delete invalid txs and evict conflict losers
|
|
552
|
+
await this.#deleteTxsBatch(invalid);
|
|
553
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
407
554
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
+
});
|
|
417
565
|
}
|
|
418
566
|
|
|
419
|
-
async handlePrunedBlocks(latestBlock: L2BlockId): Promise<void> {
|
|
567
|
+
async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
|
|
420
568
|
// Step 1: Find transactions mined after the prune point
|
|
421
569
|
const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
|
|
422
570
|
if (txsToUnmine.length === 0) {
|
|
@@ -426,64 +574,99 @@ export class TxPoolV2Impl {
|
|
|
426
574
|
|
|
427
575
|
this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
|
|
428
576
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
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
|
+
);
|
|
587
|
+
|
|
588
|
+
// Step 3: Unmine - clear mined status from metadata
|
|
589
|
+
for (const meta of txsToUnmine) {
|
|
590
|
+
this.#indices.markAsUnmined(meta);
|
|
591
|
+
}
|
|
592
|
+
|
|
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
|
+
}
|
|
602
|
+
|
|
603
|
+
// Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
|
|
604
|
+
const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
|
|
433
605
|
|
|
434
|
-
|
|
435
|
-
|
|
606
|
+
// Step 5: Validate for pending pool
|
|
607
|
+
const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
|
|
436
608
|
|
|
437
|
-
|
|
438
|
-
|
|
609
|
+
// Step 6: Resolve nullifier conflicts and add winners to pending indices
|
|
610
|
+
const { toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
439
611
|
|
|
440
|
-
|
|
441
|
-
|
|
612
|
+
// Step 7: Delete invalid txs and evict conflict losers
|
|
613
|
+
await this.#deleteTxsBatch(invalid);
|
|
614
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
442
615
|
|
|
443
|
-
|
|
444
|
-
|
|
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
|
+
);
|
|
445
620
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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
|
+
});
|
|
449
625
|
}
|
|
450
626
|
|
|
451
627
|
async handleFailedExecution(txHashes: TxHash[]): Promise<void> {
|
|
452
|
-
|
|
453
|
-
|
|
628
|
+
await this.#store.transactionAsync(async () => {
|
|
629
|
+
await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
|
|
630
|
+
});
|
|
454
631
|
|
|
455
|
-
this.#log.info(`Deleted ${txHashes.length} failed txs
|
|
632
|
+
this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
|
|
456
633
|
}
|
|
457
634
|
|
|
458
635
|
async handleFinalizedBlock(block: BlockHeader): Promise<void> {
|
|
459
636
|
const blockNumber = block.globalVariables.blockNumber;
|
|
460
637
|
|
|
461
|
-
// Step 1: Find txs
|
|
462
|
-
const
|
|
463
|
-
if (txsToFinalize.length === 0) {
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
638
|
+
// Step 1: Find mined txs at or before finalized block
|
|
639
|
+
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
|
|
466
640
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
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
|
+
}
|
|
474
650
|
}
|
|
475
651
|
}
|
|
476
|
-
}
|
|
477
652
|
|
|
478
|
-
|
|
479
|
-
|
|
653
|
+
// Step 3: Delete mined txs from active pool
|
|
654
|
+
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
480
655
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
await this.#archive.archiveTxs(txsToArchive);
|
|
484
|
-
}
|
|
656
|
+
// Step 4: Finalize soft-deleted txs
|
|
657
|
+
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
485
658
|
|
|
486
|
-
|
|
659
|
+
// Step 5: Archive mined txs
|
|
660
|
+
if (txsToArchive.length > 0) {
|
|
661
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
if (minedTxsToFinalize.length > 0) {
|
|
666
|
+
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
|
|
667
|
+
txHashes: minedTxsToFinalize,
|
|
668
|
+
});
|
|
669
|
+
}
|
|
487
670
|
}
|
|
488
671
|
|
|
489
672
|
// === Query Methods ===
|
|
@@ -503,21 +686,36 @@ export class TxPoolV2Impl {
|
|
|
503
686
|
}
|
|
504
687
|
|
|
505
688
|
hasTxs(txHashes: TxHash[]): boolean[] {
|
|
506
|
-
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
|
+
});
|
|
507
693
|
}
|
|
508
694
|
|
|
509
695
|
getTxStatus(txHash: TxHash): TxState | undefined {
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
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';
|
|
513
704
|
}
|
|
514
|
-
return
|
|
705
|
+
return undefined;
|
|
515
706
|
}
|
|
516
707
|
|
|
517
708
|
getPendingTxHashes(): TxHash[] {
|
|
518
709
|
return [...this.#indices.iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
|
|
519
710
|
}
|
|
520
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
|
+
);
|
|
717
|
+
}
|
|
718
|
+
|
|
521
719
|
getPendingTxCount(): number {
|
|
522
720
|
return this.#indices.getPendingTxCount();
|
|
523
721
|
}
|
|
@@ -562,6 +760,9 @@ export class TxPoolV2Impl {
|
|
|
562
760
|
this.#config.archivedTxLimit = config.archivedTxLimit;
|
|
563
761
|
this.#archive.updateLimit(config.archivedTxLimit);
|
|
564
762
|
}
|
|
763
|
+
if (config.minTxPoolAgeMs !== undefined) {
|
|
764
|
+
this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
|
|
765
|
+
}
|
|
565
766
|
// Update eviction rules with new config
|
|
566
767
|
this.#evictionManager.updateConfig(config);
|
|
567
768
|
}
|
|
@@ -579,8 +780,17 @@ export class TxPoolV2Impl {
|
|
|
579
780
|
|
|
580
781
|
// === Metrics ===
|
|
581
782
|
|
|
582
|
-
countTxs(): {
|
|
583
|
-
|
|
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
|
+
};
|
|
584
794
|
}
|
|
585
795
|
|
|
586
796
|
// ============================================================================
|
|
@@ -595,11 +805,14 @@ export class TxPoolV2Impl {
|
|
|
595
805
|
tx: Tx,
|
|
596
806
|
state: 'pending' | { protected: SlotNumber } | { mined: L2BlockId },
|
|
597
807
|
opts: { source?: string } = {},
|
|
808
|
+
precomputedMeta?: TxMetaData,
|
|
598
809
|
): Promise<TxMetaData> {
|
|
599
810
|
const txHashStr = tx.getTxHash().toString();
|
|
600
|
-
const meta = await buildTxMetaData(tx);
|
|
811
|
+
const meta = precomputedMeta ?? (await buildTxMetaData(tx));
|
|
812
|
+
meta.receivedAt = this.#dateProvider.now();
|
|
601
813
|
|
|
602
814
|
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
815
|
+
await this.#deletedPool.clearSoftDeleted(txHashStr);
|
|
603
816
|
this.#callbacks.onTxsAdded([tx], opts);
|
|
604
817
|
|
|
605
818
|
if (state === 'pending') {
|
|
@@ -612,9 +825,11 @@ export class TxPoolV2Impl {
|
|
|
612
825
|
}
|
|
613
826
|
|
|
614
827
|
const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
|
|
615
|
-
this.#log.
|
|
828
|
+
this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
|
|
616
829
|
eventName: 'tx-added-to-pool',
|
|
830
|
+
txHash: txHashStr,
|
|
617
831
|
state: stateStr,
|
|
832
|
+
source: opts.source,
|
|
618
833
|
});
|
|
619
834
|
|
|
620
835
|
return meta;
|
|
@@ -624,10 +839,15 @@ export class TxPoolV2Impl {
|
|
|
624
839
|
* Deletes a transaction from both indices and DB.
|
|
625
840
|
* Emits onTxsRemoved callback immediately after DB delete.
|
|
626
841
|
*/
|
|
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
|
+
*/
|
|
627
847
|
async #deleteTx(txHashStr: string): Promise<void> {
|
|
628
848
|
this.#indices.remove(txHashStr);
|
|
629
|
-
await this.#txsDB.delete(txHashStr);
|
|
630
849
|
this.#callbacks.onTxsRemoved([txHashStr]);
|
|
850
|
+
await this.#deletedPool.deleteTx(txHashStr);
|
|
631
851
|
}
|
|
632
852
|
|
|
633
853
|
/** Deletes a batch of transactions, emitting callbacks individually for each. */
|
|
@@ -637,68 +857,63 @@ export class TxPoolV2Impl {
|
|
|
637
857
|
}
|
|
638
858
|
}
|
|
639
859
|
|
|
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);
|
|
869
|
+
}
|
|
870
|
+
await this.#deleteTxsBatch(txHashes);
|
|
871
|
+
}
|
|
872
|
+
|
|
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);
|
|
879
|
+
}
|
|
880
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
881
|
+
}
|
|
882
|
+
|
|
640
883
|
// ============================================================================
|
|
641
884
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
642
885
|
// ============================================================================
|
|
643
886
|
|
|
644
|
-
/** Validates
|
|
645
|
-
async #
|
|
646
|
-
const
|
|
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);
|
|
647
891
|
if (result.result !== 'valid') {
|
|
648
892
|
const contextStr = context ? ` ${context}` : '';
|
|
649
|
-
this.#log.info(`Tx ${
|
|
893
|
+
this.#log.info(`Tx ${meta.txHash}${contextStr} failed validation: ${result.reason?.join(', ')}`);
|
|
650
894
|
return false;
|
|
651
895
|
}
|
|
652
896
|
return true;
|
|
653
897
|
}
|
|
654
898
|
|
|
655
|
-
/**
|
|
656
|
-
async #
|
|
657
|
-
|
|
658
|
-
const missing: string[] = [];
|
|
659
|
-
|
|
660
|
-
for (const meta of metas) {
|
|
661
|
-
const buffer = await this.#txsDB.getAsync(meta.txHash);
|
|
662
|
-
if (!buffer) {
|
|
663
|
-
this.#log.warn(`Tx ${meta.txHash} not found in DB`);
|
|
664
|
-
missing.push(meta.txHash);
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
loaded.push({ tx: Tx.fromBuffer(buffer), meta });
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
return { loaded, missing };
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
/** Validates a batch of transactions, returning valid and invalid groups */
|
|
674
|
-
async #validateTxBatch(
|
|
675
|
-
txs: { tx: Tx; meta: TxMetaData }[],
|
|
899
|
+
/** Validates metadata directly */
|
|
900
|
+
async #revalidateMetadata(
|
|
901
|
+
metas: TxMetaData[],
|
|
676
902
|
context?: string,
|
|
677
903
|
): Promise<{ valid: TxMetaData[]; invalid: string[] }> {
|
|
678
904
|
const valid: TxMetaData[] = [];
|
|
679
905
|
const invalid: string[] = [];
|
|
680
|
-
|
|
681
|
-
for (const
|
|
682
|
-
if (await this.#
|
|
906
|
+
const validator = await this.#createTxValidator();
|
|
907
|
+
for (const meta of metas) {
|
|
908
|
+
if (await this.#validateMeta(meta, validator, context)) {
|
|
683
909
|
valid.push(meta);
|
|
684
910
|
} else {
|
|
685
911
|
invalid.push(meta.txHash);
|
|
686
912
|
}
|
|
687
913
|
}
|
|
688
|
-
|
|
689
914
|
return { valid, invalid };
|
|
690
915
|
}
|
|
691
916
|
|
|
692
|
-
/** Loads transactions from DB and validates them */
|
|
693
|
-
async #loadAndValidateTxs(
|
|
694
|
-
metas: TxMetaData[],
|
|
695
|
-
context?: string,
|
|
696
|
-
): Promise<{ valid: TxMetaData[]; invalid: string[] }> {
|
|
697
|
-
const { loaded, missing } = await this.#loadTxsFromDb(metas);
|
|
698
|
-
const { valid, invalid } = await this.#validateTxBatch(loaded, context);
|
|
699
|
-
return { valid, invalid: [...missing, ...invalid] };
|
|
700
|
-
}
|
|
701
|
-
|
|
702
917
|
/**
|
|
703
918
|
* Resolves nullifier conflicts between incoming txs and existing pending txs.
|
|
704
919
|
* Modifies the pending indices during iteration to maintain consistent state
|
|
@@ -768,9 +983,15 @@ export class TxPoolV2Impl {
|
|
|
768
983
|
const errors: string[] = [];
|
|
769
984
|
|
|
770
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
|
+
|
|
771
991
|
try {
|
|
772
992
|
const tx = Tx.fromBuffer(buffer);
|
|
773
|
-
const
|
|
993
|
+
const allowedSetupCalls = await this.#checkAllowedSetupCalls(tx);
|
|
994
|
+
const meta = await buildTxMetaData(tx, allowedSetupCalls);
|
|
774
995
|
loaded.push({ tx, meta });
|
|
775
996
|
} catch (err) {
|
|
776
997
|
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
@@ -815,7 +1036,9 @@ export class TxPoolV2Impl {
|
|
|
815
1036
|
if (preAddResult.shouldIgnore) {
|
|
816
1037
|
// Transaction rejected - mark for deletion from DB
|
|
817
1038
|
rejected.push(meta.txHash);
|
|
818
|
-
this.#log.debug(
|
|
1039
|
+
this.#log.debug(
|
|
1040
|
+
`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`,
|
|
1041
|
+
);
|
|
819
1042
|
continue;
|
|
820
1043
|
}
|
|
821
1044
|
|
|
@@ -851,7 +1074,7 @@ export class TxPoolV2Impl {
|
|
|
851
1074
|
getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
|
|
852
1075
|
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
853
1076
|
getLowestPriorityPending: (limit: number) => this.#indices.getLowestPriorityPending(limit),
|
|
854
|
-
deleteTxs: (txHashes: string[]) => this.#
|
|
1077
|
+
deleteTxs: (txHashes: string[], reason?: string) => this.#evictTxs(txHashes, reason ?? 'unknown'),
|
|
855
1078
|
};
|
|
856
1079
|
}
|
|
857
1080
|
|