@aztec/p2p 0.0.1-commit.4d79d1f2d → 0.0.1-commit.4d9804df
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 +130 -3
- package/dest/bootstrap/bootstrap.d.ts +1 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +22 -6
- package/dest/client/factory.d.ts +9 -8
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +50 -34
- package/dest/client/interface.d.ts +59 -27
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +40 -34
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +162 -135
- package/dest/config.d.ts +164 -100
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +149 -49
- 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/reqresp.error.d.ts +9 -16
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +10 -17
- 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 +1 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +0 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +103 -59
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +278 -196
- 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 +224 -65
- 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 +7 -5
- package/dest/mem_pools/index.d.ts +1 -2
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.d.ts +12 -5
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +38 -17
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -5
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +1 -7
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +32 -15
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +95 -24
- 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 +8 -4
- 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 +3 -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 +2 -1
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
- 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 +9 -7
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +60 -14
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +6 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +59 -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 +116 -20
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +26 -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 +79 -43
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +20 -7
- 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 +34 -12
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +29 -7
- 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 +473 -211
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +38 -15
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +4 -5
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +12 -5
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +11 -3
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +12 -5
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +23 -3
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +36 -9
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +130 -48
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +11 -18
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +25 -21
- 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/archive_cache.js +1 -1
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
- 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 +2 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +36 -2
- package/dest/msg_validators/tx_validator/factory.d.ts +133 -7
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +261 -61
- 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 +104 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +137 -53
- package/dest/msg_validators/tx_validator/index.d.ts +5 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +4 -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 +2 -2
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +5 -5
- package/dest/services/discv5/discV5_service.d.ts +13 -2
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +119 -23
- package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
- package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
- package/dest/services/discv5/persisted_enr_store.js +145 -0
- package/dest/services/dummy_service.d.ts +18 -18
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +19 -20
- package/dest/services/encoding.d.ts +23 -6
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +41 -24
- package/dest/services/gossipsub/topic_score_params.d.ts +23 -17
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +36 -24
- package/dest/services/libp2p/instrumentation.d.ts +3 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +14 -0
- package/dest/services/libp2p/libp2p_service.d.ts +57 -56
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +483 -373
- 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 +20 -3
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +83 -26
- package/dest/services/peer-manager/peer_scoring.d.ts +34 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +102 -13
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +5 -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 +95 -127
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +11 -11
- 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.d.ts +5 -14
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
- package/dest/services/reqresp/config.d.ts +15 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/config.js +11 -0
- package/dest/services/reqresp/interface.d.ts +16 -18
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +10 -20
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +0 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
- 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 +31 -28
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
- 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 +42 -24
- package/dest/services/reqresp/protocols/index.d.ts +1 -2
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +0 -1
- package/dest/services/reqresp/protocols/tx.d.ts +1 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +1 -3
- 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/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -13
- package/dest/services/reqresp/reqresp.d.ts +7 -29
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +75 -216
- package/dest/services/service.d.ts +29 -14
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +8 -17
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +17 -40
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +25 -32
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +96 -87
- package/dest/services/tx_collection/file_store_tx_source.d.ts +17 -6
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +53 -10
- package/dest/services/tx_collection/index.d.ts +2 -3
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +0 -1
- package/dest/services/tx_collection/instrumentation.js +1 -2
- 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/tx_collection.d.ts +39 -55
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +280 -108
- package/dest/services/tx_collection/tx_collection_sink.d.ts +7 -6
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +15 -24
- 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 +29 -7
- package/dest/services/tx_file_store/tx_file_store.d.ts +3 -4
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +13 -20
- package/dest/services/tx_provider.d.ts +5 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +7 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +5 -3
- package/dest/test-helpers/mock-pubsub.d.ts +26 -12
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +51 -45
- package/dest/test-helpers/reqresp-nodes.d.ts +5 -7
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +17 -19
- package/dest/test-helpers/test_tx_provider.d.ts +3 -1
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
- package/dest/test-helpers/test_tx_provider.js +3 -0
- package/dest/test-helpers/testbench-utils.d.ts +22 -16
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +56 -16
- package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +111 -48
- package/dest/testbench/worker_client_manager.d.ts +12 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +57 -11
- package/dest/util.d.ts +13 -8
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +35 -14
- package/dest/versioning.d.ts +3 -6
- package/dest/versioning.d.ts.map +1 -1
- package/dest/versioning.js +3 -24
- package/package.json +16 -16
- package/src/bootstrap/bootstrap.ts +17 -3
- package/src/client/factory.ts +95 -51
- package/src/client/interface.ts +59 -35
- package/src/client/p2p_client.ts +186 -196
- package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
- package/src/config.ts +259 -57
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/errors/reqresp.error.ts +13 -19
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +0 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +336 -242
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +244 -69
- package/src/mem_pools/attestation_pool/mocks.ts +14 -8
- package/src/mem_pools/index.ts +0 -3
- package/src/mem_pools/instrumentation.ts +27 -17
- package/src/mem_pools/tx_pool_v2/README.md +52 -28
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +114 -27
- 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 +8 -4
- 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 +5 -0
- package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -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 +8 -8
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
- package/src/mem_pools/tx_pool_v2/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +61 -14
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +170 -28
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +91 -43
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +54 -14
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +527 -207
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +46 -14
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +15 -7
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +26 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +43 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +155 -49
- package/src/msg_validators/tx_validator/README.md +129 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +6 -15
- 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/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +44 -1
- package/src/msg_validators/tx_validator/factory.ts +413 -80
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +195 -54
- package/src/msg_validators/tx_validator/index.ts +4 -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 +7 -7
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
- package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
- package/src/services/data_store.ts +5 -13
- package/src/services/discv5/discV5_service.ts +126 -14
- package/src/services/discv5/persisted_enr_store.ts +158 -0
- package/src/services/dummy_service.ts +26 -45
- package/src/services/encoding.ts +40 -24
- package/src/services/gossipsub/README.md +59 -22
- package/src/services/gossipsub/topic_score_params.ts +58 -31
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +554 -428
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +91 -25
- package/src/services/peer-manager/peer_scoring.ts +102 -8
- package/src/services/reqresp/README.md +194 -0
- package/src/services/reqresp/batch-tx-requester/README.md +46 -7
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +92 -138
- package/src/services/reqresp/batch-tx-requester/interface.ts +14 -10
- 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 +12 -25
- package/src/services/reqresp/config.ts +19 -2
- package/src/services/reqresp/interface.ts +21 -47
- package/src/services/reqresp/metrics.ts +0 -1
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +1 -3
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -13
- package/src/services/reqresp/reqresp.ts +87 -260
- package/src/services/service.ts +42 -30
- package/src/services/tx_collection/config.ts +24 -59
- package/src/services/tx_collection/file_store_tx_collection.ts +108 -107
- package/src/services/tx_collection/file_store_tx_source.ts +69 -10
- package/src/services/tx_collection/index.ts +1 -6
- package/src/services/tx_collection/instrumentation.ts +1 -1
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/tx_collection.ts +342 -156
- package/src/services/tx_collection/tx_collection_sink.ts +17 -31
- package/src/services/tx_collection/tx_source.ts +29 -8
- package/src/services/tx_file_store/tx_file_store.ts +11 -21
- package/src/services/tx_provider.ts +7 -2
- package/src/test-helpers/make-test-p2p-clients.ts +4 -3
- package/src/test-helpers/mock-pubsub.ts +59 -66
- package/src/test-helpers/reqresp-nodes.ts +15 -28
- package/src/test-helpers/test_tx_provider.ts +5 -0
- package/src/test-helpers/testbench-utils.ts +74 -31
- package/src/testbench/p2p_client_testbench_worker.ts +120 -63
- package/src/testbench/worker_client_manager.ts +72 -25
- package/src/util.ts +40 -19
- package/src/versioning.ts +3 -33
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -305
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
- 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/clock_tolerance.d.ts +0 -21
- package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
- package/dest/msg_validators/clock_tolerance.js +0 -37
- 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/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
- package/dest/services/reqresp/protocols/block.d.ts +0 -9
- package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
- package/dest/services/reqresp/protocols/block.js +0 -32
- package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -54
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/fast_tx_collection.js +0 -321
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -48
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +0 -49
- package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -55
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/slow_tx_collection.js +0 -206
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -336
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
- 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/clock_tolerance.ts +0 -51
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
- package/src/services/reqresp/protocols/block.ts +0 -37
- package/src/services/tx_collection/fast_tx_collection.ts +0 -366
- package/src/services/tx_collection/proposal_tx_collector.ts +0 -112
- package/src/services/tx_collection/slow_tx_collection.ts +0 -262
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { FifoSet } from '@aztec/foundation/fifo-set';
|
|
2
3
|
import type { Logger } from '@aztec/foundation/log';
|
|
4
|
+
import type { DateProvider } from '@aztec/foundation/timer';
|
|
3
5
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
4
6
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
7
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
@@ -8,6 +10,7 @@ import type { L2Block, L2BlockId, L2BlockSource } from '@aztec/stdlib/block';
|
|
|
8
10
|
import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
9
11
|
import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
|
|
10
12
|
import { BlockHeader, Tx, TxHash, type TxValidator } from '@aztec/stdlib/tx';
|
|
13
|
+
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
11
14
|
|
|
12
15
|
import { TxArchive } from './archive/index.js';
|
|
13
16
|
import { DeletedPool } from './deleted_pool.js';
|
|
@@ -15,14 +18,19 @@ import {
|
|
|
15
18
|
EvictionManager,
|
|
16
19
|
FeePayerBalanceEvictionRule,
|
|
17
20
|
FeePayerBalancePreAddRule,
|
|
21
|
+
InsufficientFeePerGasEvictionRule,
|
|
18
22
|
InvalidTxsAfterMiningRule,
|
|
19
23
|
InvalidTxsAfterReorgRule,
|
|
20
24
|
LowPriorityEvictionRule,
|
|
21
25
|
LowPriorityPreAddRule,
|
|
22
26
|
NullifierConflictRule,
|
|
23
27
|
type PoolOperations,
|
|
28
|
+
type PreAddContext,
|
|
24
29
|
type PreAddPoolAccess,
|
|
30
|
+
TxPoolRejectionCode,
|
|
31
|
+
type TxPoolRejectionError,
|
|
25
32
|
} from './eviction/index.js';
|
|
33
|
+
import { TxPoolV2Instrumentation } from './instrumentation.js';
|
|
26
34
|
import {
|
|
27
35
|
type AddTxsResult,
|
|
28
36
|
DEFAULT_TX_POOL_V2_CONFIG,
|
|
@@ -33,12 +41,28 @@ import {
|
|
|
33
41
|
import { type TxMetaData, type TxState, buildTxMetaData, checkNullifierConflict } from './tx_metadata.js';
|
|
34
42
|
import { TxPoolIndices } from './tx_pool_indices.js';
|
|
35
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Maximum number of full transactions to load into memory at once when finalizing a block.
|
|
46
|
+
* Bounds peak memory while archiving and hard-deleting mined txs (~23k txs/epoch at 10 TPS would
|
|
47
|
+
* otherwise OOM the node).
|
|
48
|
+
*/
|
|
49
|
+
const FINALIZE_BLOCK_CHUNK_SIZE = 100;
|
|
50
|
+
|
|
36
51
|
/**
|
|
37
52
|
* Callbacks for the implementation to notify the outer class about events and metrics.
|
|
38
53
|
*/
|
|
54
|
+
/** A tx that has just transitioned to mined, with the time it spent in the pool. */
|
|
55
|
+
export interface MinedTxInfo {
|
|
56
|
+
txHash: string;
|
|
57
|
+
/** Wall-clock ms from receipt into the pool to being marked mined. Undefined when the
|
|
58
|
+
* receive time is unknown (e.g. a tx hydrated from the DB on restart, receivedAt === 0). */
|
|
59
|
+
minedDelayMs?: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
39
62
|
export interface TxPoolV2Callbacks {
|
|
40
63
|
onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
|
|
41
64
|
onTxsRemoved: (txHashes: string[] | bigint[]) => void;
|
|
65
|
+
onTxsMined: (minedTxs: MinedTxInfo[]) => void;
|
|
42
66
|
}
|
|
43
67
|
|
|
44
68
|
/**
|
|
@@ -49,12 +73,16 @@ export interface TxPoolV2Callbacks {
|
|
|
49
73
|
export class TxPoolV2Impl {
|
|
50
74
|
// === Persistence ===
|
|
51
75
|
#store: AztecAsyncKVStore;
|
|
76
|
+
/** Tx data without its proof. Proofs live in #proofsDB so a tx can be read without loading its proof. */
|
|
52
77
|
#txsDB: AztecAsyncMap<string, Buffer>;
|
|
78
|
+
/** Tx proofs, keyed by tx hash. Written and deleted in lockstep with #txsDB. */
|
|
79
|
+
#proofsDB: AztecAsyncMap<string, Buffer>;
|
|
53
80
|
|
|
54
81
|
// === Dependencies ===
|
|
55
82
|
#l2BlockSource: L2BlockSource;
|
|
56
83
|
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
57
84
|
#createTxValidator: TxPoolV2Dependencies['createTxValidator'];
|
|
85
|
+
#checkAllowedSetupCalls: TxPoolV2Dependencies['checkAllowedSetupCalls'];
|
|
58
86
|
|
|
59
87
|
// === In-Memory Indices ===
|
|
60
88
|
#indices: TxPoolIndices = new TxPoolIndices();
|
|
@@ -64,6 +92,9 @@ export class TxPoolV2Impl {
|
|
|
64
92
|
#archive: TxArchive;
|
|
65
93
|
#deletedPool: DeletedPool;
|
|
66
94
|
#evictionManager: EvictionManager;
|
|
95
|
+
#dateProvider: DateProvider;
|
|
96
|
+
#instrumentation: TxPoolV2Instrumentation;
|
|
97
|
+
#evictedTxHashes: FifoSet<string>;
|
|
67
98
|
#log: Logger;
|
|
68
99
|
#callbacks: TxPoolV2Callbacks;
|
|
69
100
|
|
|
@@ -72,19 +103,26 @@ export class TxPoolV2Impl {
|
|
|
72
103
|
archiveStore: AztecAsyncKVStore,
|
|
73
104
|
deps: TxPoolV2Dependencies,
|
|
74
105
|
callbacks: TxPoolV2Callbacks,
|
|
106
|
+
telemetry: TelemetryClient,
|
|
75
107
|
config: Partial<TxPoolV2Config> = {},
|
|
108
|
+
dateProvider: DateProvider,
|
|
76
109
|
log: Logger,
|
|
77
110
|
) {
|
|
78
111
|
this.#store = store;
|
|
79
112
|
this.#txsDB = store.openMap('txs');
|
|
113
|
+
this.#proofsDB = store.openMap('tx_proofs');
|
|
80
114
|
|
|
81
115
|
this.#l2BlockSource = deps.l2BlockSource;
|
|
82
116
|
this.#worldStateSynchronizer = deps.worldStateSynchronizer;
|
|
83
117
|
this.#createTxValidator = deps.createTxValidator;
|
|
118
|
+
this.#checkAllowedSetupCalls = deps.checkAllowedSetupCalls;
|
|
84
119
|
|
|
85
120
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
121
|
+
this.#evictedTxHashes = FifoSet.withLimit<string>(this.#config.evictedTxCacheSize);
|
|
86
122
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
87
|
-
this.#deletedPool = new DeletedPool(store, this.#
|
|
123
|
+
this.#deletedPool = new DeletedPool(store, txHashStr => this.#deleteTxData(txHashStr), log);
|
|
124
|
+
this.#dateProvider = dateProvider;
|
|
125
|
+
this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
|
|
88
126
|
this.#log = log;
|
|
89
127
|
this.#callbacks = callbacks;
|
|
90
128
|
|
|
@@ -100,6 +138,7 @@ export class TxPoolV2Impl {
|
|
|
100
138
|
|
|
101
139
|
// Post-event eviction rules (run after events to check ALL pending txs)
|
|
102
140
|
this.#evictionManager.registerRule(new InvalidTxsAfterMiningRule());
|
|
141
|
+
this.#evictionManager.registerRule(new InsufficientFeePerGasEvictionRule(deps.blockMinFeesProvider));
|
|
103
142
|
this.#evictionManager.registerRule(new InvalidTxsAfterReorgRule(deps.worldStateSynchronizer));
|
|
104
143
|
this.#evictionManager.registerRule(new FeePayerBalanceEvictionRule(deps.worldStateSynchronizer));
|
|
105
144
|
// LowPriorityEvictionRule handles cases where txs become pending via prepareForSlot (unprotect)
|
|
@@ -122,58 +161,115 @@ export class TxPoolV2Impl {
|
|
|
122
161
|
// Step 0: Hydrate deleted pool state
|
|
123
162
|
await this.#deletedPool.hydrateFromDatabase();
|
|
124
163
|
|
|
125
|
-
// Step 1:
|
|
126
|
-
const
|
|
164
|
+
// Step 1: Stream txs from DB, building metadata and mined status one at a time.
|
|
165
|
+
const minedMetas: TxMetaData[] = [];
|
|
166
|
+
const pendingMetas: TxMetaData[] = [];
|
|
167
|
+
const deserializationErrors: string[] = [];
|
|
127
168
|
|
|
128
|
-
|
|
129
|
-
|
|
169
|
+
for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
|
|
170
|
+
// Skip soft-deleted transactions - they stay in DB but not in indices
|
|
171
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
130
174
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
mined
|
|
175
|
+
let meta: TxMetaData;
|
|
176
|
+
let txEffect: Awaited<ReturnType<L2BlockSource['getTxEffect']>>;
|
|
177
|
+
try {
|
|
178
|
+
const tx = Tx.fromBuffer(buffer);
|
|
179
|
+
// Resolve allowed-setup-calls and the tx effect concurrently
|
|
180
|
+
// getTxEffect failures are non-fatal (we just treat the tx as not-yet-mined), so
|
|
181
|
+
// its rejection is swallowed before the Promise.all so it can't fail-fast the batch.
|
|
182
|
+
const txEffectPromise = this.#l2BlockSource.getTxEffect(tx.getTxHash()).catch(err => {
|
|
183
|
+
this.#log.warn(`Failed to check mined status for tx ${txHashStr}`, { err });
|
|
184
|
+
return undefined;
|
|
185
|
+
});
|
|
186
|
+
const [allowedSetupCalls, fetchedTxEffect] = await Promise.all([
|
|
187
|
+
this.#checkAllowedSetupCalls(tx),
|
|
188
|
+
txEffectPromise,
|
|
189
|
+
]);
|
|
190
|
+
meta = await buildTxMetaData(tx, allowedSetupCalls);
|
|
191
|
+
txEffect = fetchedTxEffect;
|
|
192
|
+
} catch (err) {
|
|
193
|
+
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
194
|
+
deserializationErrors.push(txHashStr);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (txEffect) {
|
|
199
|
+
meta.minedL2BlockId = {
|
|
200
|
+
number: txEffect.l2BlockNumber,
|
|
201
|
+
hash: txEffect.l2BlockHash.toString(),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (meta.minedL2BlockId !== undefined) {
|
|
206
|
+
minedMetas.push(meta);
|
|
137
207
|
} else {
|
|
138
|
-
|
|
208
|
+
pendingMetas.push(meta);
|
|
139
209
|
}
|
|
140
210
|
}
|
|
141
211
|
|
|
142
|
-
// Step
|
|
143
|
-
const { valid, invalid } = await this.#revalidateMetadata(
|
|
144
|
-
nonMined.map(e => e.meta),
|
|
145
|
-
'on startup',
|
|
146
|
-
);
|
|
212
|
+
// Step 2: Validate non-mined transactions
|
|
213
|
+
const { valid, invalid } = await this.#revalidateMetadata(pendingMetas, 'on startup');
|
|
147
214
|
|
|
148
|
-
// Step
|
|
149
|
-
for (const meta of
|
|
215
|
+
// Step 3: Populate mined indices (these don't need conflict resolution)
|
|
216
|
+
for (const meta of minedMetas) {
|
|
150
217
|
this.#indices.addMined(meta);
|
|
151
218
|
}
|
|
152
219
|
|
|
153
|
-
// Step
|
|
220
|
+
// Step 4: Rebuild pending pool by running pre-add rules for each tx
|
|
154
221
|
// This resolves nullifier conflicts, fee payer balance issues, and pool size limits
|
|
155
222
|
const { rejected } = await this.#rebuildPendingPool(valid);
|
|
156
223
|
|
|
157
|
-
// Step
|
|
224
|
+
// Step 5: Delete invalid and rejected txs from DB only (indices were never populated for these)
|
|
158
225
|
const toDelete = [...deserializationErrors, ...invalid, ...rejected];
|
|
159
226
|
if (toDelete.length === 0) {
|
|
160
227
|
return;
|
|
161
228
|
}
|
|
162
229
|
await this.#store.transactionAsync(async () => {
|
|
163
230
|
for (const txHashStr of toDelete) {
|
|
164
|
-
await this.#
|
|
231
|
+
await this.#deleteTxData(txHashStr);
|
|
165
232
|
}
|
|
166
233
|
});
|
|
167
|
-
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup
|
|
234
|
+
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
|
|
168
235
|
}
|
|
169
236
|
|
|
170
|
-
async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
|
|
237
|
+
async addPendingTxs(txs: Tx[], opts: { source?: string; feeComparisonOnly?: boolean }): Promise<AddTxsResult> {
|
|
171
238
|
const accepted: TxHash[] = [];
|
|
172
239
|
const ignored: TxHash[] = [];
|
|
173
240
|
const rejected: TxHash[] = [];
|
|
241
|
+
const errors = new Map<string, TxPoolRejectionError>();
|
|
174
242
|
const acceptedPending = new Set<string>();
|
|
175
243
|
|
|
244
|
+
// Phase 1: Pre-compute all throwable I/O outside the transaction.
|
|
245
|
+
// If any pre-computation throws, the entire call fails before mutations happen.
|
|
246
|
+
const precomputed = new Map<string, { meta: TxMetaData; minedBlockId: L2BlockId | undefined; isValid: boolean }>();
|
|
247
|
+
|
|
248
|
+
const validator = await this.#createTxValidator();
|
|
249
|
+
|
|
250
|
+
for (const tx of txs) {
|
|
251
|
+
const txHash = tx.getTxHash();
|
|
252
|
+
const txHashStr = txHash.toString();
|
|
253
|
+
|
|
254
|
+
const meta = await buildTxMetaData(tx);
|
|
255
|
+
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
256
|
+
|
|
257
|
+
// Validate non-mined txs (mined and pre-protected txs bypass validation inside the transaction)
|
|
258
|
+
let isValid = true;
|
|
259
|
+
if (!minedBlockId) {
|
|
260
|
+
isValid = await this.#validateMeta(meta, validator);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
precomputed.set(txHashStr, { meta, minedBlockId, isValid });
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Phase 2: Apply mutations inside the transaction using only pre-computed results,
|
|
267
|
+
// in-memory reads, and buffered DB writes. Nothing here can throw an unhandled exception.
|
|
176
268
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
269
|
+
const preAddContext: PreAddContext | undefined =
|
|
270
|
+
opts.feeComparisonOnly !== undefined
|
|
271
|
+
? { feeComparisonOnly: opts.feeComparisonOnly, priceBumpPercentage: this.#config.priceBumpPercentage }
|
|
272
|
+
: undefined;
|
|
177
273
|
|
|
178
274
|
await this.#store.transactionAsync(async () => {
|
|
179
275
|
for (const tx of txs) {
|
|
@@ -186,30 +282,46 @@ export class TxPoolV2Impl {
|
|
|
186
282
|
continue;
|
|
187
283
|
}
|
|
188
284
|
|
|
189
|
-
|
|
190
|
-
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
285
|
+
const { meta, minedBlockId, isValid } = precomputed.get(txHashStr)!;
|
|
191
286
|
const preProtectedSlot = this.#indices.getProtectionSlot(txHashStr);
|
|
192
287
|
|
|
193
288
|
if (minedBlockId) {
|
|
194
289
|
// Already mined - add directly (protection already set if pre-protected)
|
|
195
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
290
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
196
291
|
accepted.push(txHash);
|
|
197
292
|
} else if (preProtectedSlot !== undefined) {
|
|
198
293
|
// Pre-protected and not mined - add as protected (bypass validation)
|
|
199
|
-
await this.#addTx(tx, { protected: preProtectedSlot }, opts);
|
|
294
|
+
await this.#addTx(tx, { protected: preProtectedSlot }, opts, meta);
|
|
200
295
|
accepted.push(txHash);
|
|
296
|
+
} else if (!isValid) {
|
|
297
|
+
// Failed pre-computed validation
|
|
298
|
+
rejected.push(txHash);
|
|
201
299
|
} else {
|
|
202
|
-
// Regular pending tx -
|
|
203
|
-
const result = await this.#tryAddRegularPendingTx(
|
|
300
|
+
// Regular pending tx - run pre-add rules using pre-computed metadata
|
|
301
|
+
const result = await this.#tryAddRegularPendingTx(
|
|
302
|
+
tx,
|
|
303
|
+
meta,
|
|
304
|
+
opts,
|
|
305
|
+
poolAccess,
|
|
306
|
+
acceptedPending,
|
|
307
|
+
ignored,
|
|
308
|
+
errors,
|
|
309
|
+
preAddContext,
|
|
310
|
+
);
|
|
204
311
|
if (result.status === 'accepted') {
|
|
205
312
|
acceptedPending.add(txHashStr);
|
|
206
|
-
} else if (result.status === 'rejected') {
|
|
207
|
-
rejected.push(txHash);
|
|
208
313
|
} else {
|
|
209
314
|
ignored.push(txHash);
|
|
210
315
|
}
|
|
211
316
|
}
|
|
212
317
|
}
|
|
318
|
+
|
|
319
|
+
// Run post-add eviction rules for pending txs (inside transaction for atomicity)
|
|
320
|
+
if (acceptedPending.size > 0) {
|
|
321
|
+
const feePayers = Array.from(acceptedPending).map(txHash => this.#indices.getMetadata(txHash)!.feePayer);
|
|
322
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
323
|
+
await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
|
|
324
|
+
}
|
|
213
325
|
});
|
|
214
326
|
|
|
215
327
|
// Build final accepted list for pending txs (excludes intra-batch evictions)
|
|
@@ -217,96 +329,124 @@ export class TxPoolV2Impl {
|
|
|
217
329
|
accepted.push(TxHash.fromString(txHashStr));
|
|
218
330
|
}
|
|
219
331
|
|
|
220
|
-
//
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
332
|
+
// Record metrics
|
|
333
|
+
if (ignored.length > 0) {
|
|
334
|
+
this.#instrumentation.recordIgnored(ignored.length);
|
|
335
|
+
}
|
|
336
|
+
if (rejected.length > 0) {
|
|
337
|
+
this.#instrumentation.recordRejected(rejected.length);
|
|
225
338
|
}
|
|
226
339
|
|
|
227
|
-
return { accepted, ignored, rejected };
|
|
340
|
+
return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
|
|
228
341
|
}
|
|
229
342
|
|
|
230
|
-
/**
|
|
343
|
+
/** Adds a validated pending tx, running pre-add rules and evicting conflicts. */
|
|
231
344
|
async #tryAddRegularPendingTx(
|
|
232
345
|
tx: Tx,
|
|
346
|
+
precomputedMeta: TxMetaData,
|
|
233
347
|
opts: { source?: string },
|
|
234
348
|
poolAccess: PreAddPoolAccess,
|
|
235
349
|
acceptedPending: Set<string>,
|
|
236
350
|
ignored: TxHash[],
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// Build metadata and validate using metadata
|
|
242
|
-
const meta = await buildTxMetaData(tx);
|
|
243
|
-
if (!(await this.#validateMeta(meta))) {
|
|
244
|
-
return { status: 'rejected' };
|
|
245
|
-
}
|
|
351
|
+
errors: Map<string, TxPoolRejectionError>,
|
|
352
|
+
preAddContext?: PreAddContext,
|
|
353
|
+
): Promise<{ status: 'accepted' | 'ignored' }> {
|
|
354
|
+
const txHashStr = tx.getTxHash().toString();
|
|
246
355
|
|
|
247
356
|
// Run pre-add rules
|
|
248
|
-
const preAddResult = await this.#evictionManager.runPreAddRules(
|
|
357
|
+
const preAddResult = await this.#evictionManager.runPreAddRules(precomputedMeta, poolAccess, preAddContext);
|
|
249
358
|
|
|
250
359
|
if (preAddResult.shouldIgnore) {
|
|
251
|
-
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason}`);
|
|
360
|
+
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
|
|
361
|
+
if (preAddResult.reason && preAddResult.reason.code !== TxPoolRejectionCode.INTERNAL_ERROR) {
|
|
362
|
+
errors.set(txHashStr, preAddResult.reason);
|
|
363
|
+
}
|
|
252
364
|
return { status: 'ignored' };
|
|
253
365
|
}
|
|
254
366
|
|
|
255
|
-
// Evict conflicts
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
367
|
+
// Evict conflicts, grouped by rule name for metrics
|
|
368
|
+
if (preAddResult.evictions && preAddResult.evictions.length > 0) {
|
|
369
|
+
const byReason = new Map<string, string[]>();
|
|
370
|
+
for (const { txHash: evictHash, reason } of preAddResult.evictions) {
|
|
371
|
+
const group = byReason.get(reason);
|
|
372
|
+
if (group) {
|
|
373
|
+
group.push(evictHash);
|
|
374
|
+
} else {
|
|
375
|
+
byReason.set(reason, [evictHash]);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
for (const [reason, hashes] of byReason) {
|
|
379
|
+
await this.#evictTxs(hashes, reason);
|
|
380
|
+
}
|
|
381
|
+
for (const evictHashStr of preAddResult.txHashesToEvict) {
|
|
382
|
+
this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
|
|
383
|
+
evictedTxHash: evictHashStr,
|
|
384
|
+
replacementTxHash: txHashStr,
|
|
385
|
+
});
|
|
386
|
+
if (acceptedPending.has(evictHashStr)) {
|
|
387
|
+
// Evicted tx was from this batch - mark as ignored in result
|
|
388
|
+
acceptedPending.delete(evictHashStr);
|
|
389
|
+
ignored.push(TxHash.fromString(evictHashStr));
|
|
390
|
+
}
|
|
263
391
|
}
|
|
264
392
|
}
|
|
265
393
|
|
|
394
|
+
// Randomly drop the transaction for testing purposes (report as accepted so it propagates)
|
|
395
|
+
if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
|
|
396
|
+
this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
|
|
397
|
+
return { status: 'accepted' };
|
|
398
|
+
}
|
|
399
|
+
|
|
266
400
|
// Add the transaction
|
|
267
|
-
await this.#addTx(tx, 'pending', opts);
|
|
401
|
+
await this.#addTx(tx, 'pending', opts, precomputedMeta);
|
|
268
402
|
return { status: 'accepted' };
|
|
269
403
|
}
|
|
270
404
|
|
|
271
|
-
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'
|
|
405
|
+
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
|
|
272
406
|
const txHashStr = tx.getTxHash().toString();
|
|
273
407
|
|
|
274
408
|
// Check if already in pool
|
|
275
409
|
if (this.#indices.has(txHashStr)) {
|
|
410
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} already in pool`);
|
|
276
411
|
return 'ignored';
|
|
277
412
|
}
|
|
278
413
|
|
|
279
|
-
// Build metadata and
|
|
414
|
+
// Build metadata and check pre-add rules
|
|
280
415
|
const meta = await buildTxMetaData(tx);
|
|
281
|
-
const validationResult = await this.#validateMeta(meta, undefined, 'can add pending');
|
|
282
|
-
if (validationResult !== true) {
|
|
283
|
-
return 'rejected';
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Use pre-add rules
|
|
287
416
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
288
417
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
289
418
|
|
|
290
|
-
|
|
419
|
+
if (preAddResult.shouldIgnore) {
|
|
420
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} ignored by pre-add rule`, {
|
|
421
|
+
reason: preAddResult.reason?.message ?? 'no reason provided',
|
|
422
|
+
});
|
|
423
|
+
return 'ignored';
|
|
424
|
+
}
|
|
425
|
+
return 'accepted';
|
|
291
426
|
}
|
|
292
427
|
|
|
293
428
|
async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
|
|
294
429
|
const slotNumber = block.globalVariables.slotNumber;
|
|
295
430
|
|
|
431
|
+
// Precompute setup-call allow-list flags outside the store transaction
|
|
432
|
+
const allowedFlags = await Promise.all(txs.map(tx => this.#checkAllowedSetupCalls(tx)));
|
|
433
|
+
|
|
296
434
|
await this.#store.transactionAsync(async () => {
|
|
297
|
-
for (
|
|
435
|
+
for (let i = 0; i < txs.length; i++) {
|
|
436
|
+
const tx = txs[i];
|
|
298
437
|
const txHash = tx.getTxHash();
|
|
299
438
|
const txHashStr = txHash.toString();
|
|
300
439
|
const isNew = !this.#indices.has(txHashStr);
|
|
301
440
|
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
302
441
|
|
|
303
442
|
if (isNew) {
|
|
443
|
+
const meta = await buildTxMetaData(tx, allowedFlags[i]);
|
|
304
444
|
// New tx - add as mined or protected (callback emitted by #addTx)
|
|
305
445
|
if (minedBlockId) {
|
|
306
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
446
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
307
447
|
this.#indices.setProtection(txHashStr, slotNumber);
|
|
308
448
|
} else {
|
|
309
|
-
await this.#addTx(tx, { protected: slotNumber }, opts);
|
|
449
|
+
await this.#addTx(tx, { protected: slotNumber }, opts, meta);
|
|
310
450
|
}
|
|
311
451
|
} else {
|
|
312
452
|
// Existing tx - update protection and mined status
|
|
@@ -320,23 +460,59 @@ export class TxPoolV2Impl {
|
|
|
320
460
|
});
|
|
321
461
|
}
|
|
322
462
|
|
|
323
|
-
protectTxs(txHashes: TxHash[], block: BlockHeader): TxHash[] {
|
|
463
|
+
async protectTxs(txHashes: TxHash[], block: BlockHeader): Promise<TxHash[]> {
|
|
324
464
|
const slotNumber = block.globalVariables.slotNumber;
|
|
325
465
|
const missing: TxHash[] = [];
|
|
466
|
+
let softDeletedHits = 0;
|
|
467
|
+
let missingPreviouslyEvicted = 0;
|
|
326
468
|
|
|
327
|
-
|
|
328
|
-
const
|
|
469
|
+
await this.#store.transactionAsync(async () => {
|
|
470
|
+
for (const txHash of txHashes) {
|
|
471
|
+
const txHashStr = txHash.toString();
|
|
329
472
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
473
|
+
if (this.#indices.has(txHashStr)) {
|
|
474
|
+
// Update protection for existing tx
|
|
475
|
+
this.#indices.updateProtection(txHashStr, slotNumber);
|
|
476
|
+
} else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
477
|
+
// Resurrect soft-deleted tx as protected. Load the proof too: #addTx rewrites both entries, so re-adding
|
|
478
|
+
// a proofless tx would wipe the stored proof.
|
|
479
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
480
|
+
if (buffer) {
|
|
481
|
+
const tx = await this.#loadTxWithProof(txHashStr, buffer);
|
|
482
|
+
await this.#addTx(tx, { protected: slotNumber });
|
|
483
|
+
softDeletedHits++;
|
|
484
|
+
} else {
|
|
485
|
+
// Data missing despite soft-delete flag — treat as truly missing
|
|
486
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
487
|
+
missing.push(txHash);
|
|
488
|
+
}
|
|
489
|
+
} else {
|
|
490
|
+
// Truly missing — pre-record protection for tx we don't have yet
|
|
491
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
492
|
+
missing.push(txHash);
|
|
493
|
+
if (this.#evictedTxHashes.has(txHashStr)) {
|
|
494
|
+
missingPreviouslyEvicted++;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
337
497
|
}
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
// Record metrics
|
|
501
|
+
if (softDeletedHits > 0) {
|
|
502
|
+
this.#instrumentation.recordSoftDeletedHits(softDeletedHits);
|
|
503
|
+
}
|
|
504
|
+
if (missing.length > 0) {
|
|
505
|
+
this.#log.debug(`protectTxs missing tx hashes: ${missing.map(h => h.toString()).join(', ')}`);
|
|
506
|
+
this.#instrumentation.recordMissingOnProtect(missing.length);
|
|
507
|
+
}
|
|
508
|
+
if (missingPreviouslyEvicted > 0) {
|
|
509
|
+
this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
|
|
338
510
|
}
|
|
339
511
|
|
|
512
|
+
this.#log.info(
|
|
513
|
+
`Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`,
|
|
514
|
+
);
|
|
515
|
+
|
|
340
516
|
return missing;
|
|
341
517
|
}
|
|
342
518
|
|
|
@@ -380,43 +556,97 @@ export class TxPoolV2Impl {
|
|
|
380
556
|
}
|
|
381
557
|
}
|
|
382
558
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
559
|
+
await this.#store.transactionAsync(async () => {
|
|
560
|
+
// Step 4: Mark txs as mined (only those we have in the pool)
|
|
561
|
+
for (const meta of found) {
|
|
562
|
+
this.#indices.markAsMined(meta, blockId);
|
|
563
|
+
await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Step 5: Run post-event eviction rules (inside transaction for atomicity)
|
|
567
|
+
await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
|
|
568
|
+
});
|
|
388
569
|
|
|
389
|
-
|
|
390
|
-
|
|
570
|
+
if (found.length > 0) {
|
|
571
|
+
// receivedAt is 0 for txs hydrated from the DB on restart (true receive time lost) — leave
|
|
572
|
+
// their delay undefined so the metric isn't polluted by epoch-sized values.
|
|
573
|
+
const now = this.#dateProvider.now();
|
|
574
|
+
this.#callbacks.onTxsMined(
|
|
575
|
+
found.map(m => ({
|
|
576
|
+
txHash: m.txHash,
|
|
577
|
+
minedDelayMs: m.receivedAt > 0 ? now - m.receivedAt : undefined,
|
|
578
|
+
})),
|
|
579
|
+
);
|
|
580
|
+
}
|
|
391
581
|
|
|
392
582
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
393
583
|
}
|
|
394
584
|
|
|
395
585
|
async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
|
|
396
|
-
|
|
397
|
-
|
|
586
|
+
await this.#store.transactionAsync(async () => {
|
|
587
|
+
// Step 0: Clean up slot-deleted txs from previous slots
|
|
588
|
+
await this.#deletedPool.cleanupSlotDeleted(slotNumber);
|
|
398
589
|
|
|
399
|
-
|
|
400
|
-
|
|
590
|
+
// Step 1: Find expired protected txs
|
|
591
|
+
const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
|
|
401
592
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
if (txsToRestore.length === 0) {
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
593
|
+
// Step 2: Clear protection for all expired entries (including those without metadata)
|
|
594
|
+
this.#indices.clearProtection(expiredProtected);
|
|
407
595
|
|
|
408
|
-
|
|
596
|
+
// Step 3: Filter to only txs that have metadata and are not mined
|
|
597
|
+
const txsToRestore = this.#indices.filterRestorable(expiredProtected);
|
|
598
|
+
if (txsToRestore.length === 0) {
|
|
599
|
+
this.#log.debug(`Preparing for slot ${slotNumber}, no txs to unprotect`);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
409
602
|
|
|
410
|
-
|
|
411
|
-
|
|
603
|
+
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
604
|
+
await this.#restoreUnprotectedToPending(txsToRestore, 'during prepareForSlot');
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
async unprotectTxs(txHashes: TxHash[], slotNumber: SlotNumber): Promise<void> {
|
|
609
|
+
const hashStrs = txHashes.map(h => h.toString());
|
|
610
|
+
|
|
611
|
+
await this.#store.transactionAsync(async () => {
|
|
612
|
+
// Only release entries still recorded at this exact slot. A tx that another, still-live proposal
|
|
613
|
+
// raised to a higher slot via updateProtection must keep that protection. Mined txs have no
|
|
614
|
+
// protection entry and so are never matched here.
|
|
615
|
+
const matching = this.#indices.findProtectedTxsAtSlot(hashStrs, slotNumber);
|
|
616
|
+
if (matching.length === 0) {
|
|
617
|
+
this.#log.debug(`Unprotecting txs for slot ${slotNumber}: no matching protections to release`);
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
this.#indices.clearProtection(matching);
|
|
412
622
|
|
|
413
|
-
|
|
623
|
+
const txsToRestore = this.#indices.filterRestorable(matching);
|
|
624
|
+
if (txsToRestore.length === 0) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
this.#log.info(`Unprotecting ${txsToRestore.length} txs from failed proposal at slot ${slotNumber}`);
|
|
629
|
+
await this.#restoreUnprotectedToPending(txsToRestore, 'during unprotectTxs');
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Returns just-unprotected txs to the pending pool: revalidates them, resolves nullifier
|
|
635
|
+
* conflicts, deletes losers, then enforces the pool size limit. Must run inside a store
|
|
636
|
+
* transaction; callers clear the protection entries before invoking.
|
|
637
|
+
*/
|
|
638
|
+
async #restoreUnprotectedToPending(txsToRestore: TxMetaData[], context: string): Promise<void> {
|
|
639
|
+
// Step 1: Validate for pending pool
|
|
640
|
+
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, context);
|
|
641
|
+
|
|
642
|
+
// Step 2: Resolve nullifier conflicts and add winners to pending indices
|
|
414
643
|
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
415
644
|
|
|
416
|
-
// Step
|
|
417
|
-
await this.#deleteTxsBatch(
|
|
645
|
+
// Step 3: Delete invalid txs and evict conflict losers
|
|
646
|
+
await this.#deleteTxsBatch(invalid);
|
|
647
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
418
648
|
|
|
419
|
-
// Step
|
|
649
|
+
// Step 4: Run eviction rules (enforce pool size limit)
|
|
420
650
|
if (added.length > 0) {
|
|
421
651
|
const feePayers = added.map(meta => meta.feePayer);
|
|
422
652
|
const uniqueFeePayers = new Set<string>(feePayers);
|
|
@@ -427,7 +657,7 @@ export class TxPoolV2Impl {
|
|
|
427
657
|
}
|
|
428
658
|
}
|
|
429
659
|
|
|
430
|
-
async handlePrunedBlocks(latestBlock: L2BlockId): Promise<void> {
|
|
660
|
+
async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
|
|
431
661
|
// Step 1: Find transactions mined after the prune point
|
|
432
662
|
const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
|
|
433
663
|
if (txsToUnmine.length === 0) {
|
|
@@ -437,94 +667,174 @@ export class TxPoolV2Impl {
|
|
|
437
667
|
|
|
438
668
|
this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
|
|
439
669
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
670
|
+
await this.#store.transactionAsync(async () => {
|
|
671
|
+
// Step 2: Mark ALL un-mined txs with their original mined block number
|
|
672
|
+
// This ensures they get soft-deleted if removed later, and only hard-deleted
|
|
673
|
+
// when their original mined block is finalized
|
|
674
|
+
await this.#deletedPool.markFromPrunedBlock(
|
|
675
|
+
txsToUnmine.map(m => ({
|
|
676
|
+
txHash: m.txHash,
|
|
677
|
+
minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
|
|
678
|
+
})),
|
|
679
|
+
);
|
|
449
680
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
681
|
+
// Step 3: Unmine - clear mined status from metadata
|
|
682
|
+
for (const meta of txsToUnmine) {
|
|
683
|
+
this.#indices.markAsUnmined(meta);
|
|
684
|
+
}
|
|
454
685
|
|
|
455
|
-
|
|
456
|
-
|
|
686
|
+
// If deleteAllTxs is set (epoch prune), delete all un-mined txs and return early
|
|
687
|
+
if (options?.deleteAllTxs) {
|
|
688
|
+
const allTxHashes = txsToUnmine.map(m => m.txHash);
|
|
689
|
+
await this.#deleteTxsBatch(allTxHashes);
|
|
690
|
+
this.#log.info(
|
|
691
|
+
`Handled prune to block ${latestBlock.number} with deleteAllTxs: deleted ${allTxHashes.length} txs`,
|
|
692
|
+
);
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
457
695
|
|
|
458
|
-
|
|
459
|
-
|
|
696
|
+
// Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
|
|
697
|
+
const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
|
|
460
698
|
|
|
461
|
-
|
|
462
|
-
|
|
699
|
+
// Step 5: Validate for pending pool
|
|
700
|
+
const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
|
|
463
701
|
|
|
464
|
-
|
|
465
|
-
|
|
702
|
+
// Step 6: Resolve nullifier conflicts and add winners to pending indices
|
|
703
|
+
const { toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
466
704
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
705
|
+
// Step 7: Delete invalid txs and evict conflict losers
|
|
706
|
+
await this.#deleteTxsBatch(invalid);
|
|
707
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
708
|
+
|
|
709
|
+
this.#log.info(
|
|
710
|
+
`Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`,
|
|
711
|
+
{ txHashesRestored: valid.map(m => m.txHash), txHashesInvalid: invalid, txHashesEvicted: toEvict },
|
|
712
|
+
);
|
|
713
|
+
|
|
714
|
+
// Step 8: Run eviction rules for ALL pending txs (not just restored ones)
|
|
715
|
+
// This handles cases like existing pending txs with invalid fee payer balances
|
|
716
|
+
await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
|
|
717
|
+
});
|
|
470
718
|
}
|
|
471
719
|
|
|
472
720
|
async handleFailedExecution(txHashes: TxHash[]): Promise<void> {
|
|
473
|
-
|
|
474
|
-
|
|
721
|
+
await this.#store.transactionAsync(async () => {
|
|
722
|
+
await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
|
|
723
|
+
});
|
|
475
724
|
|
|
476
|
-
this.#log.info(`Deleted ${txHashes.length} failed txs
|
|
725
|
+
this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
|
|
477
726
|
}
|
|
478
727
|
|
|
479
728
|
async handleFinalizedBlock(block: BlockHeader): Promise<void> {
|
|
480
729
|
const blockNumber = block.globalVariables.blockNumber;
|
|
481
730
|
|
|
482
|
-
//
|
|
483
|
-
|
|
731
|
+
// Hold finalized txs for a configurable margin behind the finalized tip so a prover still
|
|
732
|
+
// proving an epoch with already-finalized blocks isn't starved of its txs. 0 deletes at the finalized tip.
|
|
733
|
+
const cutoffBlock = await this.#finalizationCutoffBlock(block);
|
|
734
|
+
|
|
735
|
+
// Step 1: Find mined txs at or before the cutoff block
|
|
736
|
+
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(cutoffBlock);
|
|
484
737
|
|
|
485
|
-
// Step 2:
|
|
486
|
-
|
|
738
|
+
// Step 2: Archive in chunks if archiving is enabled. Hydrating an entire epoch's worth of
|
|
739
|
+
// mined txs at once would OOM under load. When archiving is disabled there is no need to hydrate the txs at all.
|
|
487
740
|
if (this.#archive.isEnabled()) {
|
|
488
|
-
for (
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
741
|
+
for (let i = 0; i < minedTxsToFinalize.length; i += FINALIZE_BLOCK_CHUNK_SIZE) {
|
|
742
|
+
const chunk = minedTxsToFinalize.slice(i, i + FINALIZE_BLOCK_CHUNK_SIZE);
|
|
743
|
+
const txsToArchive: Tx[] = [];
|
|
744
|
+
for (const txHashStr of chunk) {
|
|
745
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
746
|
+
if (buffer) {
|
|
747
|
+
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
if (txsToArchive.length > 0) {
|
|
751
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
492
752
|
}
|
|
493
753
|
}
|
|
494
754
|
}
|
|
495
755
|
|
|
496
|
-
// Step 3: Delete mined txs from active pool
|
|
497
|
-
|
|
756
|
+
// Step 3: Delete mined txs from the active pool and finalize soft-deleted txs in one
|
|
757
|
+
// transaction. Only tx hashes are touched here, so memory is bounded and atomicity is preserved.
|
|
758
|
+
await this.#store.transactionAsync(async () => {
|
|
759
|
+
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
760
|
+
await this.#deletedPool.finalizeBlock(cutoffBlock);
|
|
761
|
+
});
|
|
498
762
|
|
|
499
|
-
|
|
500
|
-
|
|
763
|
+
if (minedTxsToFinalize.length > 0) {
|
|
764
|
+
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${cutoffBlock}`, {
|
|
765
|
+
txHashes: minedTxsToFinalize,
|
|
766
|
+
finalizedBlockNumber: blockNumber,
|
|
767
|
+
cutoffBlock,
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
}
|
|
501
771
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
772
|
+
/**
|
|
773
|
+
* Resolves the block up to which finalized txs may be deleted, given `keepFinalizedTxsForSlots`.
|
|
774
|
+
* With a margin of 0 this is just the finalized block. Otherwise we keep txs whose block is within
|
|
775
|
+
* the margin (in slots) of the finalized tip: take the target slot `finalizedSlot - margin`, find the
|
|
776
|
+
* latest checkpoint at or before it with a single reverse range query (`limit: 1`), and use that
|
|
777
|
+
* checkpoint's last block as the cutoff. This rounds to a checkpoint boundary, so it can retain slightly
|
|
778
|
+
* more than the configured margin but never less, and never deletes past the finalized block.
|
|
779
|
+
*/
|
|
780
|
+
async #finalizationCutoffBlock(block: BlockHeader): Promise<BlockNumber> {
|
|
781
|
+
const keepSlots = this.#config.keepFinalizedTxsForSlots;
|
|
782
|
+
if (keepSlots <= 0) {
|
|
783
|
+
return block.globalVariables.blockNumber;
|
|
505
784
|
}
|
|
506
785
|
|
|
507
|
-
|
|
508
|
-
|
|
786
|
+
// The goal here really is to ensure we keep transactions long enough for them to be proven.
|
|
787
|
+
// So we could be smart and calculate the number of slots until the end of the proof submission window.
|
|
788
|
+
// Our approach here is a lot simpler however and we just keep transactions for the configured number
|
|
789
|
+
// of slots past L1 finalisation. This means we may keep transactions in the mined pool for longer
|
|
790
|
+
// than strictly necessary.
|
|
791
|
+
const targetSlot = block.getSlot() - keepSlots;
|
|
792
|
+
if (targetSlot < 0) {
|
|
793
|
+
// The margin reaches past genesis: keep everything.
|
|
794
|
+
return BlockNumber(0);
|
|
509
795
|
}
|
|
796
|
+
|
|
797
|
+
const [checkpoint] = await this.#l2BlockSource.getCheckpointsData({
|
|
798
|
+
fromSlot: SlotNumber(targetSlot),
|
|
799
|
+
limit: 1,
|
|
800
|
+
reverse: true,
|
|
801
|
+
});
|
|
802
|
+
// No checkpoint at or before the target slot (e.g. early chain): keep everything.
|
|
803
|
+
return checkpoint ? BlockNumber(checkpoint.startBlock + checkpoint.blockCount - 1) : BlockNumber(0);
|
|
510
804
|
}
|
|
511
805
|
|
|
512
806
|
// === Query Methods ===
|
|
513
807
|
|
|
514
|
-
async getTxByHash(txHash: TxHash): Promise<Tx | undefined> {
|
|
515
|
-
const
|
|
516
|
-
|
|
808
|
+
async getTxByHash(txHash: TxHash, opts: { includeProof?: boolean } = {}): Promise<Tx | undefined> {
|
|
809
|
+
const txHashStr = txHash.toString();
|
|
810
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
811
|
+
if (!buffer) {
|
|
812
|
+
return undefined;
|
|
813
|
+
}
|
|
814
|
+
return opts.includeProof === false ? Tx.fromBuffer(buffer) : this.#loadTxWithProof(txHashStr, buffer);
|
|
517
815
|
}
|
|
518
816
|
|
|
519
|
-
async getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
817
|
+
async getTxsByHash(txHashes: TxHash[], opts: { includeProof?: boolean } = {}): Promise<(Tx | undefined)[]> {
|
|
520
818
|
const results: (Tx | undefined)[] = [];
|
|
521
819
|
for (const h of txHashes) {
|
|
522
|
-
|
|
523
|
-
results.push(buffer ? Tx.fromBuffer(buffer) : undefined);
|
|
820
|
+
results.push(await this.getTxByHash(h, opts));
|
|
524
821
|
}
|
|
525
822
|
return results;
|
|
526
823
|
}
|
|
527
824
|
|
|
825
|
+
/** Deserializes a tx blob loaded from #txsDB together with its separately-stored proof. */
|
|
826
|
+
async #loadTxWithProof(txHashStr: string, buffer: Buffer): Promise<Tx> {
|
|
827
|
+
const proofBuffer = await this.#proofsDB.getAsync(txHashStr);
|
|
828
|
+
if (!proofBuffer) {
|
|
829
|
+
// #addTx always writes a proof entry (an empty proof serializes to a 4-byte sentinel), so a missing entry
|
|
830
|
+
// means the blob/proof invariant is broken. Return the proofless tx but flag it, since a consumer that needs
|
|
831
|
+
// the proof (eg serving peers) would otherwise fail far away from the root cause.
|
|
832
|
+
this.#log.warn(`Missing stored proof for tx ${txHashStr}`, { txHash: txHashStr });
|
|
833
|
+
return Tx.fromBuffer(buffer);
|
|
834
|
+
}
|
|
835
|
+
return Tx.fromBuffers(buffer, proofBuffer);
|
|
836
|
+
}
|
|
837
|
+
|
|
528
838
|
hasTxs(txHashes: TxHash[]): boolean[] {
|
|
529
839
|
return txHashes.map(h => {
|
|
530
840
|
const hashStr = h.toString();
|
|
@@ -549,10 +859,22 @@ export class TxPoolV2Impl {
|
|
|
549
859
|
return [...this.#indices.iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
|
|
550
860
|
}
|
|
551
861
|
|
|
862
|
+
getEligiblePendingTxHashes(): TxHash[] {
|
|
863
|
+
const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
|
|
864
|
+
return [...this.#indices.iterateEligiblePendingByPriority('desc', maxReceivedAt)].map(hash =>
|
|
865
|
+
TxHash.fromString(hash),
|
|
866
|
+
);
|
|
867
|
+
}
|
|
868
|
+
|
|
552
869
|
getPendingTxCount(): number {
|
|
553
870
|
return this.#indices.getPendingTxCount();
|
|
554
871
|
}
|
|
555
872
|
|
|
873
|
+
hasEligiblePendingTxs(minCount: number): boolean {
|
|
874
|
+
const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
|
|
875
|
+
return this.#indices.hasEligiblePendingTxs(maxReceivedAt, minCount);
|
|
876
|
+
}
|
|
877
|
+
|
|
556
878
|
getMinedTxHashes(): [TxHash, L2BlockId][] {
|
|
557
879
|
return this.#indices.getMinedTxs().map(([hash, blockId]) => [TxHash.fromString(hash), blockId]);
|
|
558
880
|
}
|
|
@@ -593,6 +915,12 @@ export class TxPoolV2Impl {
|
|
|
593
915
|
this.#config.archivedTxLimit = config.archivedTxLimit;
|
|
594
916
|
this.#archive.updateLimit(config.archivedTxLimit);
|
|
595
917
|
}
|
|
918
|
+
if (config.minTxPoolAgeMs !== undefined) {
|
|
919
|
+
this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
|
|
920
|
+
}
|
|
921
|
+
if (config.keepFinalizedTxsForSlots !== undefined) {
|
|
922
|
+
this.#config.keepFinalizedTxsForSlots = config.keepFinalizedTxsForSlots;
|
|
923
|
+
}
|
|
596
924
|
// Update eviction rules with new config
|
|
597
925
|
this.#evictionManager.updateConfig(config);
|
|
598
926
|
}
|
|
@@ -610,8 +938,17 @@ export class TxPoolV2Impl {
|
|
|
610
938
|
|
|
611
939
|
// === Metrics ===
|
|
612
940
|
|
|
613
|
-
countTxs(): {
|
|
614
|
-
|
|
941
|
+
countTxs(): {
|
|
942
|
+
pending: number;
|
|
943
|
+
protected: number;
|
|
944
|
+
mined: number;
|
|
945
|
+
softDeleted: number;
|
|
946
|
+
totalMetadataBytes: number;
|
|
947
|
+
} {
|
|
948
|
+
return {
|
|
949
|
+
...this.#indices.countTxs(),
|
|
950
|
+
softDeleted: this.#deletedPool.getSoftDeletedCount(),
|
|
951
|
+
};
|
|
615
952
|
}
|
|
616
953
|
|
|
617
954
|
// ============================================================================
|
|
@@ -626,11 +963,15 @@ export class TxPoolV2Impl {
|
|
|
626
963
|
tx: Tx,
|
|
627
964
|
state: 'pending' | { protected: SlotNumber } | { mined: L2BlockId },
|
|
628
965
|
opts: { source?: string } = {},
|
|
966
|
+
precomputedMeta?: TxMetaData,
|
|
629
967
|
): Promise<TxMetaData> {
|
|
630
968
|
const txHashStr = tx.getTxHash().toString();
|
|
631
|
-
const meta = await buildTxMetaData(tx);
|
|
969
|
+
const meta = precomputedMeta ?? (await buildTxMetaData(tx));
|
|
970
|
+
meta.receivedAt = this.#dateProvider.now();
|
|
632
971
|
|
|
633
|
-
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
972
|
+
await this.#txsDB.set(txHashStr, tx.withoutProof().toBuffer());
|
|
973
|
+
await this.#proofsDB.set(txHashStr, tx.chonkProof.toBuffer());
|
|
974
|
+
await this.#deletedPool.clearSoftDeleted(txHashStr);
|
|
634
975
|
this.#callbacks.onTxsAdded([tx], opts);
|
|
635
976
|
|
|
636
977
|
if (state === 'pending') {
|
|
@@ -643,9 +984,11 @@ export class TxPoolV2Impl {
|
|
|
643
984
|
}
|
|
644
985
|
|
|
645
986
|
const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
|
|
646
|
-
this.#log.
|
|
987
|
+
this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
|
|
647
988
|
eventName: 'tx-added-to-pool',
|
|
989
|
+
txHash: txHashStr,
|
|
648
990
|
state: stateStr,
|
|
991
|
+
source: opts.source,
|
|
649
992
|
});
|
|
650
993
|
|
|
651
994
|
return meta;
|
|
@@ -666,6 +1009,12 @@ export class TxPoolV2Impl {
|
|
|
666
1009
|
await this.#deletedPool.deleteTx(txHashStr);
|
|
667
1010
|
}
|
|
668
1011
|
|
|
1012
|
+
/** Hard-deletes a tx's stored data (tx blob and proof) from the DB. */
|
|
1013
|
+
async #deleteTxData(txHashStr: string): Promise<void> {
|
|
1014
|
+
await this.#txsDB.delete(txHashStr);
|
|
1015
|
+
await this.#proofsDB.delete(txHashStr);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
669
1018
|
/** Deletes a batch of transactions, emitting callbacks individually for each. */
|
|
670
1019
|
async #deleteTxsBatch(txHashes: string[]): Promise<void> {
|
|
671
1020
|
for (const txHashStr of txHashes) {
|
|
@@ -673,6 +1022,19 @@ export class TxPoolV2Impl {
|
|
|
673
1022
|
}
|
|
674
1023
|
}
|
|
675
1024
|
|
|
1025
|
+
/** Evicts transactions: records eviction metric with reason, caches hashes, then deletes. */
|
|
1026
|
+
async #evictTxs(txHashes: string[], reason: string): Promise<void> {
|
|
1027
|
+
if (txHashes.length === 0) {
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
this.#instrumentation.recordEvictions(txHashes.length, reason);
|
|
1031
|
+
for (const txHashStr of txHashes) {
|
|
1032
|
+
this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
|
|
1033
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
1034
|
+
}
|
|
1035
|
+
await this.#deleteTxsBatch(txHashes);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
676
1038
|
// ============================================================================
|
|
677
1039
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
678
1040
|
// ============================================================================
|
|
@@ -767,50 +1129,6 @@ export class TxPoolV2Impl {
|
|
|
767
1129
|
};
|
|
768
1130
|
}
|
|
769
1131
|
|
|
770
|
-
/** Loads all transactions from the database, returning loaded txs and deserialization errors */
|
|
771
|
-
async #loadAllTxsFromDb(): Promise<{
|
|
772
|
-
loaded: { tx: Tx; meta: TxMetaData }[];
|
|
773
|
-
errors: string[];
|
|
774
|
-
}> {
|
|
775
|
-
const loaded: { tx: Tx; meta: TxMetaData }[] = [];
|
|
776
|
-
const errors: string[] = [];
|
|
777
|
-
|
|
778
|
-
for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
|
|
779
|
-
// Skip soft-deleted transactions - they stay in DB but not in indices
|
|
780
|
-
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
781
|
-
continue;
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
try {
|
|
785
|
-
const tx = Tx.fromBuffer(buffer);
|
|
786
|
-
const meta = await buildTxMetaData(tx);
|
|
787
|
-
loaded.push({ tx, meta });
|
|
788
|
-
} catch (err) {
|
|
789
|
-
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
790
|
-
errors.push(txHashStr);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
return { loaded, errors };
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
/** Queries block source and marks mined status on transaction metadata */
|
|
798
|
-
async #markMinedStatusBatch(metas: TxMetaData[]): Promise<void> {
|
|
799
|
-
for (const meta of metas) {
|
|
800
|
-
try {
|
|
801
|
-
const txEffect = await this.#l2BlockSource.getTxEffect(TxHash.fromString(meta.txHash));
|
|
802
|
-
if (txEffect) {
|
|
803
|
-
meta.minedL2BlockId = {
|
|
804
|
-
number: txEffect.l2BlockNumber,
|
|
805
|
-
hash: txEffect.l2BlockHash.toString(),
|
|
806
|
-
};
|
|
807
|
-
}
|
|
808
|
-
} catch (err) {
|
|
809
|
-
this.#log.warn(`Failed to check mined status for tx ${meta.txHash}`, { err });
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
|
|
814
1132
|
/**
|
|
815
1133
|
* Rebuilds the pending pool by processing each tx through pre-add rules.
|
|
816
1134
|
* Starts with an empty pending pool and adds txs one by one, resolving conflicts.
|
|
@@ -828,7 +1146,9 @@ export class TxPoolV2Impl {
|
|
|
828
1146
|
if (preAddResult.shouldIgnore) {
|
|
829
1147
|
// Transaction rejected - mark for deletion from DB
|
|
830
1148
|
rejected.push(meta.txHash);
|
|
831
|
-
this.#log.debug(
|
|
1149
|
+
this.#log.debug(
|
|
1150
|
+
`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`,
|
|
1151
|
+
);
|
|
832
1152
|
continue;
|
|
833
1153
|
}
|
|
834
1154
|
|
|
@@ -864,7 +1184,7 @@ export class TxPoolV2Impl {
|
|
|
864
1184
|
getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
|
|
865
1185
|
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
866
1186
|
getLowestPriorityPending: (limit: number) => this.#indices.getLowestPriorityPending(limit),
|
|
867
|
-
deleteTxs: (txHashes: string[]) => this.#
|
|
1187
|
+
deleteTxs: (txHashes: string[], reason?: string) => this.#evictTxs(txHashes, reason ?? 'unknown'),
|
|
868
1188
|
};
|
|
869
1189
|
}
|
|
870
1190
|
|
|
@@ -883,7 +1203,7 @@ export class TxPoolV2Impl {
|
|
|
883
1203
|
const publicStateSource = new DatabasePublicStateSource(db);
|
|
884
1204
|
const balance = await publicStateSource.storageRead(
|
|
885
1205
|
ProtocolContractAddress.FeeJuice,
|
|
886
|
-
await computeFeePayerBalanceStorageSlot(AztecAddress.
|
|
1206
|
+
await computeFeePayerBalanceStorageSlot(AztecAddress.fromStringUnsafe(feePayer)),
|
|
887
1207
|
);
|
|
888
1208
|
return balance.toBigInt();
|
|
889
1209
|
},
|