@aztec/p2p 0.0.1-commit.2eb6648a → 0.0.1-commit.343b43af6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/client/factory.d.ts +9 -9
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +43 -13
- package/dest/client/interface.d.ts +39 -33
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +37 -50
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +144 -223
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -7
- package/dest/config.d.ts +48 -17
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +92 -38
- 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 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- 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 +72 -38
- 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 +53 -53
- 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 -1
- 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/eviction/invalid_txs_after_mining_rule.js +3 -3
- package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +4 -3
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -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 +5 -2
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +12 -4
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +54 -5
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/index.d.ts +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 +24 -8
- 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 +70 -14
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +132 -17
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +50 -45
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -4
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +14 -6
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +14 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +353 -185
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +48 -36
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +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/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 +125 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +226 -58
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +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 +2 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +44 -23
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +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 +9 -5
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +7 -4
- package/dest/services/encoding.d.ts +3 -3
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +11 -10
- package/dest/services/gossipsub/index.d.ts +3 -0
- package/dest/services/gossipsub/index.d.ts.map +1 -0
- package/dest/services/gossipsub/index.js +2 -0
- package/dest/services/gossipsub/scoring.d.ts +21 -3
- package/dest/services/gossipsub/scoring.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.js +24 -7
- package/dest/services/gossipsub/topic_score_params.d.ts +173 -0
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
- package/dest/services/gossipsub/topic_score_params.js +346 -0
- package/dest/services/libp2p/libp2p_service.d.ts +25 -14
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +195 -153
- package/dest/services/peer-manager/metrics.d.ts +3 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +6 -0
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +2 -1
- package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +25 -2
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -3
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +19 -46
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -6
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +10 -13
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +25 -46
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +17 -11
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +49 -15
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- package/dest/services/reqresp/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/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +13 -5
- package/dest/services/service.d.ts +22 -3
- 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 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +56 -36
- 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 +37 -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 +90 -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/missing_txs_tracker.d.ts +32 -0
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
- package/dest/services/tx_collection/slow_tx_collection.d.ts +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 -10
- 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 +8 -3
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +19 -2
- package/dest/services/tx_file_store/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 +4 -3
- 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 +104 -36
- 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 +16 -15
- package/dest/testbench/worker_client_manager.d.ts +3 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +6 -2
- package/dest/util.d.ts +3 -3
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +79 -24
- package/src/client/interface.ts +43 -33
- package/src/client/p2p_client.ts +165 -265
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +20 -11
- package/src/config.ts +141 -44
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +100 -48
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +57 -53
- 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 +3 -0
- package/src/mem_pools/instrumentation.ts +17 -13
- package/src/mem_pools/interface.ts +2 -2
- package/src/mem_pools/tx_pool/README.md +1 -1
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
- package/src/mem_pools/tx_pool/priority.ts +6 -3
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
- 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 +5 -2
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -4
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +59 -4
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
- package/src/mem_pools/tx_pool_v2/index.ts +2 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +26 -8
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +191 -25
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +58 -45
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +21 -7
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +398 -183
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +63 -40
- package/src/msg_validators/tx_validator/README.md +115 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +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/double_spend_validator.ts +11 -6
- package/src/msg_validators/tx_validator/factory.ts +366 -77
- 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 +51 -26
- package/src/msg_validators/tx_validator/timestamp_validator.ts +23 -18
- package/src/services/dummy_service.ts +12 -6
- package/src/services/encoding.ts +9 -9
- package/src/services/gossipsub/README.md +641 -0
- package/src/services/gossipsub/index.ts +2 -0
- package/src/services/gossipsub/scoring.ts +29 -5
- package/src/services/gossipsub/topic_score_params.ts +487 -0
- package/src/services/libp2p/libp2p_service.ts +206 -164
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +2 -1
- package/src/services/peer-manager/peer_scoring.ts +25 -0
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +20 -48
- package/src/services/reqresp/batch-tx-requester/interface.ts +1 -5
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +23 -71
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +63 -24
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/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/reqresp.ts +16 -4
- package/src/services/service.ts +31 -2
- package/src/services/tx_collection/config.ts +68 -0
- package/src/services/tx_collection/fast_tx_collection.ts +65 -32
- package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
- package/src/services/tx_collection/file_store_tx_source.ts +117 -0
- package/src/services/tx_collection/index.ts +1 -0
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
- package/src/services/tx_collection/slow_tx_collection.ts +66 -33
- package/src/services/tx_collection/tx_collection.ts +113 -16
- package/src/services/tx_collection/tx_collection_sink.ts +30 -34
- package/src/services/tx_collection/tx_source.ts +22 -3
- 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 +5 -7
- package/src/test-helpers/testbench-utils.ts +118 -40
- package/src/testbench/p2p_client_testbench_worker.ts +25 -21
- package/src/testbench/worker_client_manager.ts +13 -5
- package/src/util.ts +8 -2
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
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,7 @@ export class TxPoolV2Impl {
|
|
|
53
61
|
// === Dependencies ===
|
|
54
62
|
#l2BlockSource: L2BlockSource;
|
|
55
63
|
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
56
|
-
#
|
|
64
|
+
#createTxValidator: TxPoolV2Dependencies['createTxValidator'];
|
|
57
65
|
|
|
58
66
|
// === In-Memory Indices ===
|
|
59
67
|
#indices: TxPoolIndices = new TxPoolIndices();
|
|
@@ -61,7 +69,11 @@ export class TxPoolV2Impl {
|
|
|
61
69
|
// === Config & Services ===
|
|
62
70
|
#config: TxPoolV2Config;
|
|
63
71
|
#archive: TxArchive;
|
|
72
|
+
#deletedPool: DeletedPool;
|
|
64
73
|
#evictionManager: EvictionManager;
|
|
74
|
+
#dateProvider: DateProvider;
|
|
75
|
+
#instrumentation: TxPoolV2Instrumentation;
|
|
76
|
+
#evictedTxHashes: Set<string> = new Set();
|
|
65
77
|
#log: Logger;
|
|
66
78
|
#callbacks: TxPoolV2Callbacks;
|
|
67
79
|
|
|
@@ -70,7 +82,9 @@ export class TxPoolV2Impl {
|
|
|
70
82
|
archiveStore: AztecAsyncKVStore,
|
|
71
83
|
deps: TxPoolV2Dependencies,
|
|
72
84
|
callbacks: TxPoolV2Callbacks,
|
|
85
|
+
telemetry: TelemetryClient,
|
|
73
86
|
config: Partial<TxPoolV2Config> = {},
|
|
87
|
+
dateProvider: DateProvider,
|
|
74
88
|
log: Logger,
|
|
75
89
|
) {
|
|
76
90
|
this.#store = store;
|
|
@@ -78,10 +92,13 @@ export class TxPoolV2Impl {
|
|
|
78
92
|
|
|
79
93
|
this.#l2BlockSource = deps.l2BlockSource;
|
|
80
94
|
this.#worldStateSynchronizer = deps.worldStateSynchronizer;
|
|
81
|
-
this.#
|
|
95
|
+
this.#createTxValidator = deps.createTxValidator;
|
|
82
96
|
|
|
83
97
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
84
98
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
99
|
+
this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
|
|
100
|
+
this.#dateProvider = dateProvider;
|
|
101
|
+
this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
|
|
85
102
|
this.#log = log;
|
|
86
103
|
this.#callbacks = callbacks;
|
|
87
104
|
|
|
@@ -116,7 +133,10 @@ export class TxPoolV2Impl {
|
|
|
116
133
|
* by running pre-add rules to resolve nullifier conflicts, balance checks, and pool size limits.
|
|
117
134
|
*/
|
|
118
135
|
async hydrateFromDatabase(): Promise<void> {
|
|
119
|
-
// Step
|
|
136
|
+
// Step 0: Hydrate deleted pool state
|
|
137
|
+
await this.#deletedPool.hydrateFromDatabase();
|
|
138
|
+
|
|
139
|
+
// Step 1: Load all transactions from DB (excluding soft-deleted)
|
|
120
140
|
const { loaded, errors: deserializationErrors } = await this.#loadAllTxsFromDb();
|
|
121
141
|
|
|
122
142
|
// Step 2: Check mined status for each tx
|
|
@@ -134,7 +154,10 @@ export class TxPoolV2Impl {
|
|
|
134
154
|
}
|
|
135
155
|
|
|
136
156
|
// Step 4: Validate non-mined transactions
|
|
137
|
-
const { valid, invalid } = await this.#
|
|
157
|
+
const { valid, invalid } = await this.#revalidateMetadata(
|
|
158
|
+
nonMined.map(e => e.meta),
|
|
159
|
+
'on startup',
|
|
160
|
+
);
|
|
138
161
|
|
|
139
162
|
// Step 5: Populate mined indices (these don't need conflict resolution)
|
|
140
163
|
for (const meta of mined) {
|
|
@@ -155,16 +178,45 @@ export class TxPoolV2Impl {
|
|
|
155
178
|
await this.#txsDB.delete(txHashStr);
|
|
156
179
|
}
|
|
157
180
|
});
|
|
158
|
-
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup
|
|
181
|
+
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
|
|
159
182
|
}
|
|
160
183
|
|
|
161
|
-
async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
|
|
184
|
+
async addPendingTxs(txs: Tx[], opts: { source?: string; feeComparisonOnly?: boolean }): Promise<AddTxsResult> {
|
|
162
185
|
const accepted: TxHash[] = [];
|
|
163
186
|
const ignored: TxHash[] = [];
|
|
164
187
|
const rejected: TxHash[] = [];
|
|
188
|
+
const errors = new Map<string, TxPoolRejectionError>();
|
|
165
189
|
const acceptedPending = new Set<string>();
|
|
166
190
|
|
|
191
|
+
// Phase 1: Pre-compute all throwable I/O outside the transaction.
|
|
192
|
+
// If any pre-computation throws, the entire call fails before mutations happen.
|
|
193
|
+
const precomputed = new Map<string, { meta: TxMetaData; minedBlockId: L2BlockId | undefined; isValid: boolean }>();
|
|
194
|
+
|
|
195
|
+
const validator = await this.#createTxValidator();
|
|
196
|
+
|
|
197
|
+
for (const tx of txs) {
|
|
198
|
+
const txHash = tx.getTxHash();
|
|
199
|
+
const txHashStr = txHash.toString();
|
|
200
|
+
|
|
201
|
+
const meta = await buildTxMetaData(tx);
|
|
202
|
+
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
203
|
+
|
|
204
|
+
// Validate non-mined txs (mined and pre-protected txs bypass validation inside the transaction)
|
|
205
|
+
let isValid = true;
|
|
206
|
+
if (!minedBlockId) {
|
|
207
|
+
isValid = await this.#validateMeta(meta, validator);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
precomputed.set(txHashStr, { meta, minedBlockId, isValid });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Phase 2: Apply mutations inside the transaction using only pre-computed results,
|
|
214
|
+
// in-memory reads, and buffered DB writes. Nothing here can throw an unhandled exception.
|
|
167
215
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
216
|
+
const preAddContext: PreAddContext | undefined =
|
|
217
|
+
opts.feeComparisonOnly !== undefined
|
|
218
|
+
? { feeComparisonOnly: opts.feeComparisonOnly, priceBumpPercentage: this.#config.priceBumpPercentage }
|
|
219
|
+
: undefined;
|
|
168
220
|
|
|
169
221
|
await this.#store.transactionAsync(async () => {
|
|
170
222
|
for (const tx of txs) {
|
|
@@ -177,30 +229,46 @@ export class TxPoolV2Impl {
|
|
|
177
229
|
continue;
|
|
178
230
|
}
|
|
179
231
|
|
|
180
|
-
|
|
181
|
-
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
232
|
+
const { meta, minedBlockId, isValid } = precomputed.get(txHashStr)!;
|
|
182
233
|
const preProtectedSlot = this.#indices.getProtectionSlot(txHashStr);
|
|
183
234
|
|
|
184
235
|
if (minedBlockId) {
|
|
185
236
|
// Already mined - add directly (protection already set if pre-protected)
|
|
186
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
237
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
187
238
|
accepted.push(txHash);
|
|
188
239
|
} else if (preProtectedSlot !== undefined) {
|
|
189
240
|
// Pre-protected and not mined - add as protected (bypass validation)
|
|
190
|
-
await this.#addTx(tx, { protected: preProtectedSlot }, opts);
|
|
241
|
+
await this.#addTx(tx, { protected: preProtectedSlot }, opts, meta);
|
|
191
242
|
accepted.push(txHash);
|
|
243
|
+
} else if (!isValid) {
|
|
244
|
+
// Failed pre-computed validation
|
|
245
|
+
rejected.push(txHash);
|
|
192
246
|
} else {
|
|
193
|
-
// Regular pending tx -
|
|
194
|
-
const result = await this.#tryAddRegularPendingTx(
|
|
247
|
+
// Regular pending tx - run pre-add rules using pre-computed metadata
|
|
248
|
+
const result = await this.#tryAddRegularPendingTx(
|
|
249
|
+
tx,
|
|
250
|
+
meta,
|
|
251
|
+
opts,
|
|
252
|
+
poolAccess,
|
|
253
|
+
acceptedPending,
|
|
254
|
+
ignored,
|
|
255
|
+
errors,
|
|
256
|
+
preAddContext,
|
|
257
|
+
);
|
|
195
258
|
if (result.status === 'accepted') {
|
|
196
259
|
acceptedPending.add(txHashStr);
|
|
197
|
-
} else if (result.status === 'rejected') {
|
|
198
|
-
rejected.push(txHash);
|
|
199
260
|
} else {
|
|
200
261
|
ignored.push(txHash);
|
|
201
262
|
}
|
|
202
263
|
}
|
|
203
264
|
}
|
|
265
|
+
|
|
266
|
+
// Run post-add eviction rules for pending txs (inside transaction for atomicity)
|
|
267
|
+
if (acceptedPending.size > 0) {
|
|
268
|
+
const feePayers = Array.from(acceptedPending).map(txHash => this.#indices.getMetadata(txHash)!.feePayer);
|
|
269
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
270
|
+
await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
|
|
271
|
+
}
|
|
204
272
|
});
|
|
205
273
|
|
|
206
274
|
// Build final accepted list for pending txs (excludes intra-batch evictions)
|
|
@@ -208,77 +276,100 @@ export class TxPoolV2Impl {
|
|
|
208
276
|
accepted.push(TxHash.fromString(txHashStr));
|
|
209
277
|
}
|
|
210
278
|
|
|
211
|
-
//
|
|
212
|
-
if (
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
279
|
+
// Record metrics
|
|
280
|
+
if (ignored.length > 0) {
|
|
281
|
+
this.#instrumentation.recordIgnored(ignored.length);
|
|
282
|
+
}
|
|
283
|
+
if (rejected.length > 0) {
|
|
284
|
+
this.#instrumentation.recordRejected(rejected.length);
|
|
216
285
|
}
|
|
217
286
|
|
|
218
|
-
return { accepted, ignored, rejected };
|
|
287
|
+
return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
|
|
219
288
|
}
|
|
220
289
|
|
|
221
|
-
/**
|
|
290
|
+
/** Adds a validated pending tx, running pre-add rules and evicting conflicts. */
|
|
222
291
|
async #tryAddRegularPendingTx(
|
|
223
292
|
tx: Tx,
|
|
293
|
+
precomputedMeta: TxMetaData,
|
|
224
294
|
opts: { source?: string },
|
|
225
295
|
poolAccess: PreAddPoolAccess,
|
|
226
296
|
acceptedPending: Set<string>,
|
|
227
297
|
ignored: TxHash[],
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
// Validate transaction
|
|
233
|
-
if (!(await this.#validateTx(tx))) {
|
|
234
|
-
return { status: 'rejected' };
|
|
235
|
-
}
|
|
298
|
+
errors: Map<string, TxPoolRejectionError>,
|
|
299
|
+
preAddContext?: PreAddContext,
|
|
300
|
+
): Promise<{ status: 'accepted' | 'ignored' }> {
|
|
301
|
+
const txHashStr = tx.getTxHash().toString();
|
|
236
302
|
|
|
237
|
-
//
|
|
238
|
-
const
|
|
239
|
-
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
303
|
+
// Run pre-add rules
|
|
304
|
+
const preAddResult = await this.#evictionManager.runPreAddRules(precomputedMeta, poolAccess, preAddContext);
|
|
240
305
|
|
|
241
306
|
if (preAddResult.shouldIgnore) {
|
|
242
|
-
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason}`);
|
|
307
|
+
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
|
|
308
|
+
if (preAddResult.reason && preAddResult.reason.code !== TxPoolRejectionCode.INTERNAL_ERROR) {
|
|
309
|
+
errors.set(txHashStr, preAddResult.reason);
|
|
310
|
+
}
|
|
243
311
|
return { status: 'ignored' };
|
|
244
312
|
}
|
|
245
313
|
|
|
246
|
-
// Evict conflicts
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
314
|
+
// Evict conflicts, grouped by rule name for metrics
|
|
315
|
+
if (preAddResult.evictions && preAddResult.evictions.length > 0) {
|
|
316
|
+
const byReason = new Map<string, string[]>();
|
|
317
|
+
for (const { txHash: evictHash, reason } of preAddResult.evictions) {
|
|
318
|
+
const group = byReason.get(reason);
|
|
319
|
+
if (group) {
|
|
320
|
+
group.push(evictHash);
|
|
321
|
+
} else {
|
|
322
|
+
byReason.set(reason, [evictHash]);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
for (const [reason, hashes] of byReason) {
|
|
326
|
+
await this.#evictTxs(hashes, reason);
|
|
254
327
|
}
|
|
328
|
+
for (const evictHashStr of preAddResult.txHashesToEvict) {
|
|
329
|
+
this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
|
|
330
|
+
evictedTxHash: evictHashStr,
|
|
331
|
+
replacementTxHash: txHashStr,
|
|
332
|
+
});
|
|
333
|
+
if (acceptedPending.has(evictHashStr)) {
|
|
334
|
+
// Evicted tx was from this batch - mark as ignored in result
|
|
335
|
+
acceptedPending.delete(evictHashStr);
|
|
336
|
+
ignored.push(TxHash.fromString(evictHashStr));
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Randomly drop the transaction for testing purposes (report as accepted so it propagates)
|
|
342
|
+
if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
|
|
343
|
+
this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
|
|
344
|
+
return { status: 'accepted' };
|
|
255
345
|
}
|
|
256
346
|
|
|
257
347
|
// Add the transaction
|
|
258
|
-
await this.#addTx(tx, 'pending', opts);
|
|
348
|
+
await this.#addTx(tx, 'pending', opts, precomputedMeta);
|
|
259
349
|
return { status: 'accepted' };
|
|
260
350
|
}
|
|
261
351
|
|
|
262
|
-
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'
|
|
352
|
+
async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
|
|
263
353
|
const txHashStr = tx.getTxHash().toString();
|
|
264
354
|
|
|
265
355
|
// Check if already in pool
|
|
266
356
|
if (this.#indices.has(txHashStr)) {
|
|
357
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} already in pool`);
|
|
267
358
|
return 'ignored';
|
|
268
359
|
}
|
|
269
360
|
|
|
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
|
|
361
|
+
// Build metadata and check pre-add rules
|
|
277
362
|
const meta = await buildTxMetaData(tx);
|
|
278
363
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
279
364
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
280
365
|
|
|
281
|
-
|
|
366
|
+
if (preAddResult.shouldIgnore) {
|
|
367
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} ignored by pre-add rule`, {
|
|
368
|
+
reason: preAddResult.reason?.message ?? 'no reason provided',
|
|
369
|
+
});
|
|
370
|
+
return 'ignored';
|
|
371
|
+
}
|
|
372
|
+
return 'accepted';
|
|
282
373
|
}
|
|
283
374
|
|
|
284
375
|
async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
|
|
@@ -311,23 +402,58 @@ export class TxPoolV2Impl {
|
|
|
311
402
|
});
|
|
312
403
|
}
|
|
313
404
|
|
|
314
|
-
protectTxs(txHashes: TxHash[], block: BlockHeader): TxHash[] {
|
|
405
|
+
async protectTxs(txHashes: TxHash[], block: BlockHeader): Promise<TxHash[]> {
|
|
315
406
|
const slotNumber = block.globalVariables.slotNumber;
|
|
316
407
|
const missing: TxHash[] = [];
|
|
408
|
+
let softDeletedHits = 0;
|
|
409
|
+
let missingPreviouslyEvicted = 0;
|
|
317
410
|
|
|
318
|
-
|
|
319
|
-
const
|
|
411
|
+
await this.#store.transactionAsync(async () => {
|
|
412
|
+
for (const txHash of txHashes) {
|
|
413
|
+
const txHashStr = txHash.toString();
|
|
320
414
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
415
|
+
if (this.#indices.has(txHashStr)) {
|
|
416
|
+
// Update protection for existing tx
|
|
417
|
+
this.#indices.updateProtection(txHashStr, slotNumber);
|
|
418
|
+
} else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
419
|
+
// Resurrect soft-deleted tx as protected
|
|
420
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
421
|
+
if (buffer) {
|
|
422
|
+
const tx = Tx.fromBuffer(buffer);
|
|
423
|
+
await this.#addTx(tx, { protected: slotNumber });
|
|
424
|
+
softDeletedHits++;
|
|
425
|
+
} else {
|
|
426
|
+
// Data missing despite soft-delete flag — treat as truly missing
|
|
427
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
428
|
+
missing.push(txHash);
|
|
429
|
+
}
|
|
430
|
+
} else {
|
|
431
|
+
// Truly missing — pre-record protection for tx we don't have yet
|
|
432
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
433
|
+
missing.push(txHash);
|
|
434
|
+
if (this.#evictedTxHashes.has(txHashStr)) {
|
|
435
|
+
missingPreviouslyEvicted++;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
328
438
|
}
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Record metrics
|
|
442
|
+
if (softDeletedHits > 0) {
|
|
443
|
+
this.#instrumentation.recordSoftDeletedHits(softDeletedHits);
|
|
444
|
+
}
|
|
445
|
+
if (missing.length > 0) {
|
|
446
|
+
this.#log.debug(`protectTxs missing tx hashes: ${missing.map(h => h.toString()).join(', ')}`);
|
|
447
|
+
this.#instrumentation.recordMissingOnProtect(missing.length);
|
|
448
|
+
}
|
|
449
|
+
if (missingPreviouslyEvicted > 0) {
|
|
450
|
+
this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
|
|
329
451
|
}
|
|
330
452
|
|
|
453
|
+
this.#log.info(
|
|
454
|
+
`Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`,
|
|
455
|
+
);
|
|
456
|
+
|
|
331
457
|
return missing;
|
|
332
458
|
}
|
|
333
459
|
|
|
@@ -347,6 +473,7 @@ export class TxPoolV2Impl {
|
|
|
347
473
|
// Add new mined tx (callback emitted by #addTx)
|
|
348
474
|
await this.#addTx(tx, { mined: blockId }, opts);
|
|
349
475
|
}
|
|
476
|
+
await this.#deletedPool.clearIfMinedHigher(txHashStr, blockId.number);
|
|
350
477
|
}
|
|
351
478
|
});
|
|
352
479
|
}
|
|
@@ -370,53 +497,67 @@ export class TxPoolV2Impl {
|
|
|
370
497
|
}
|
|
371
498
|
}
|
|
372
499
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
500
|
+
await this.#store.transactionAsync(async () => {
|
|
501
|
+
// Step 4: Mark txs as mined (only those we have in the pool)
|
|
502
|
+
for (const meta of found) {
|
|
503
|
+
this.#indices.markAsMined(meta, blockId);
|
|
504
|
+
await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
|
|
505
|
+
}
|
|
377
506
|
|
|
378
|
-
|
|
379
|
-
|
|
507
|
+
// Step 5: Run post-event eviction rules (inside transaction for atomicity)
|
|
508
|
+
await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
if (found.length > 0) {
|
|
512
|
+
this.#callbacks.onTxsMined(found.map(m => m.txHash));
|
|
513
|
+
}
|
|
380
514
|
|
|
381
515
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
382
516
|
}
|
|
383
517
|
|
|
384
518
|
async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
|
|
385
|
-
|
|
386
|
-
|
|
519
|
+
await this.#store.transactionAsync(async () => {
|
|
520
|
+
// Step 0: Clean up slot-deleted txs from previous slots
|
|
521
|
+
await this.#deletedPool.cleanupSlotDeleted(slotNumber);
|
|
387
522
|
|
|
388
|
-
|
|
389
|
-
|
|
523
|
+
// Step 1: Find expired protected txs
|
|
524
|
+
const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
|
|
390
525
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if (txsToRestore.length === 0) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
526
|
+
// Step 2: Clear protection for all expired entries (including those without metadata)
|
|
527
|
+
this.#indices.clearProtection(expiredProtected);
|
|
396
528
|
|
|
397
|
-
|
|
529
|
+
// Step 3: Filter to only txs that have metadata and are not mined
|
|
530
|
+
const txsToRestore = this.#indices.filterRestorable(expiredProtected);
|
|
531
|
+
if (txsToRestore.length === 0) {
|
|
532
|
+
this.#log.debug(`Preparing for slot ${slotNumber}, no txs to unprotect`);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
398
535
|
|
|
399
|
-
|
|
400
|
-
const { valid, invalid } = await this.#loadAndValidateTxs(txsToRestore, 'during prepareForSlot');
|
|
536
|
+
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
401
537
|
|
|
402
|
-
|
|
403
|
-
|
|
538
|
+
// Step 4: Validate for pending pool
|
|
539
|
+
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
|
|
404
540
|
|
|
405
|
-
|
|
406
|
-
|
|
541
|
+
// Step 5: Resolve nullifier conflicts and add winners to pending indices
|
|
542
|
+
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
407
543
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
544
|
+
// Step 6: Delete invalid txs and evict conflict losers
|
|
545
|
+
await this.#deleteTxsBatch(invalid);
|
|
546
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
547
|
+
|
|
548
|
+
// Step 7: Run eviction rules (enforce pool size limit)
|
|
549
|
+
if (added.length > 0) {
|
|
550
|
+
const feePayers = added.map(meta => meta.feePayer);
|
|
551
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
552
|
+
await this.#evictionManager.evictAfterNewTxs(
|
|
553
|
+
added.map(m => m.txHash),
|
|
554
|
+
[...uniqueFeePayers],
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
417
558
|
}
|
|
418
559
|
|
|
419
|
-
async handlePrunedBlocks(latestBlock: L2BlockId): Promise<void> {
|
|
560
|
+
async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
|
|
420
561
|
// Step 1: Find transactions mined after the prune point
|
|
421
562
|
const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
|
|
422
563
|
if (txsToUnmine.length === 0) {
|
|
@@ -426,64 +567,99 @@ export class TxPoolV2Impl {
|
|
|
426
567
|
|
|
427
568
|
this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
|
|
428
569
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
570
|
+
await this.#store.transactionAsync(async () => {
|
|
571
|
+
// Step 2: Mark ALL un-mined txs with their original mined block number
|
|
572
|
+
// This ensures they get soft-deleted if removed later, and only hard-deleted
|
|
573
|
+
// when their original mined block is finalized
|
|
574
|
+
await this.#deletedPool.markFromPrunedBlock(
|
|
575
|
+
txsToUnmine.map(m => ({
|
|
576
|
+
txHash: m.txHash,
|
|
577
|
+
minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
|
|
578
|
+
})),
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
// Step 3: Unmine - clear mined status from metadata
|
|
582
|
+
for (const meta of txsToUnmine) {
|
|
583
|
+
this.#indices.markAsUnmined(meta);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// If deleteAllTxs is set (epoch prune), delete all un-mined txs and return early
|
|
587
|
+
if (options?.deleteAllTxs) {
|
|
588
|
+
const allTxHashes = txsToUnmine.map(m => m.txHash);
|
|
589
|
+
await this.#deleteTxsBatch(allTxHashes);
|
|
590
|
+
this.#log.info(
|
|
591
|
+
`Handled prune to block ${latestBlock.number} with deleteAllTxs: deleted ${allTxHashes.length} txs`,
|
|
592
|
+
);
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
433
595
|
|
|
434
|
-
|
|
435
|
-
|
|
596
|
+
// Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
|
|
597
|
+
const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
|
|
436
598
|
|
|
437
|
-
|
|
438
|
-
|
|
599
|
+
// Step 5: Validate for pending pool
|
|
600
|
+
const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
|
|
439
601
|
|
|
440
|
-
|
|
441
|
-
|
|
602
|
+
// Step 6: Resolve nullifier conflicts and add winners to pending indices
|
|
603
|
+
const { toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
442
604
|
|
|
443
|
-
|
|
444
|
-
|
|
605
|
+
// Step 7: Delete invalid txs and evict conflict losers
|
|
606
|
+
await this.#deleteTxsBatch(invalid);
|
|
607
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
445
608
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
609
|
+
this.#log.info(
|
|
610
|
+
`Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`,
|
|
611
|
+
{ txHashesRestored: valid.map(m => m.txHash), txHashesInvalid: invalid, txHashesEvicted: toEvict },
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
// Step 8: Run eviction rules for ALL pending txs (not just restored ones)
|
|
615
|
+
// This handles cases like existing pending txs with invalid fee payer balances
|
|
616
|
+
await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
|
|
617
|
+
});
|
|
449
618
|
}
|
|
450
619
|
|
|
451
620
|
async handleFailedExecution(txHashes: TxHash[]): Promise<void> {
|
|
452
|
-
|
|
453
|
-
|
|
621
|
+
await this.#store.transactionAsync(async () => {
|
|
622
|
+
await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
|
|
623
|
+
});
|
|
454
624
|
|
|
455
|
-
this.#log.info(`Deleted ${txHashes.length} failed txs
|
|
625
|
+
this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
|
|
456
626
|
}
|
|
457
627
|
|
|
458
628
|
async handleFinalizedBlock(block: BlockHeader): Promise<void> {
|
|
459
629
|
const blockNumber = block.globalVariables.blockNumber;
|
|
460
630
|
|
|
461
|
-
// Step 1: Find txs
|
|
462
|
-
const
|
|
463
|
-
if (txsToFinalize.length === 0) {
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
631
|
+
// Step 1: Find mined txs at or before finalized block
|
|
632
|
+
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
|
|
466
633
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
634
|
+
await this.#store.transactionAsync(async () => {
|
|
635
|
+
// Step 2: Collect mined txs for archiving (before deletion)
|
|
636
|
+
const txsToArchive: Tx[] = [];
|
|
637
|
+
if (this.#archive.isEnabled()) {
|
|
638
|
+
for (const txHashStr of minedTxsToFinalize) {
|
|
639
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
640
|
+
if (buffer) {
|
|
641
|
+
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
642
|
+
}
|
|
474
643
|
}
|
|
475
644
|
}
|
|
476
|
-
}
|
|
477
645
|
|
|
478
|
-
|
|
479
|
-
|
|
646
|
+
// Step 3: Delete mined txs from active pool
|
|
647
|
+
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
480
648
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
await this.#archive.archiveTxs(txsToArchive);
|
|
484
|
-
}
|
|
649
|
+
// Step 4: Finalize soft-deleted txs
|
|
650
|
+
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
485
651
|
|
|
486
|
-
|
|
652
|
+
// Step 5: Archive mined txs
|
|
653
|
+
if (txsToArchive.length > 0) {
|
|
654
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
if (minedTxsToFinalize.length > 0) {
|
|
659
|
+
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
|
|
660
|
+
txHashes: minedTxsToFinalize,
|
|
661
|
+
});
|
|
662
|
+
}
|
|
487
663
|
}
|
|
488
664
|
|
|
489
665
|
// === Query Methods ===
|
|
@@ -503,21 +679,36 @@ export class TxPoolV2Impl {
|
|
|
503
679
|
}
|
|
504
680
|
|
|
505
681
|
hasTxs(txHashes: TxHash[]): boolean[] {
|
|
506
|
-
return txHashes.map(h =>
|
|
682
|
+
return txHashes.map(h => {
|
|
683
|
+
const hashStr = h.toString();
|
|
684
|
+
return this.#indices.has(hashStr) || this.#deletedPool.isSoftDeleted(hashStr);
|
|
685
|
+
});
|
|
507
686
|
}
|
|
508
687
|
|
|
509
688
|
getTxStatus(txHash: TxHash): TxState | undefined {
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
689
|
+
const txHashStr = txHash.toString();
|
|
690
|
+
const meta = this.#indices.getMetadata(txHashStr);
|
|
691
|
+
if (meta) {
|
|
692
|
+
return this.#indices.getTxState(meta);
|
|
693
|
+
}
|
|
694
|
+
// Check if soft-deleted
|
|
695
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
696
|
+
return 'deleted';
|
|
513
697
|
}
|
|
514
|
-
return
|
|
698
|
+
return undefined;
|
|
515
699
|
}
|
|
516
700
|
|
|
517
701
|
getPendingTxHashes(): TxHash[] {
|
|
518
702
|
return [...this.#indices.iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
|
|
519
703
|
}
|
|
520
704
|
|
|
705
|
+
getEligiblePendingTxHashes(): TxHash[] {
|
|
706
|
+
const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
|
|
707
|
+
return [...this.#indices.iterateEligiblePendingByPriority('desc', maxReceivedAt)].map(hash =>
|
|
708
|
+
TxHash.fromString(hash),
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
521
712
|
getPendingTxCount(): number {
|
|
522
713
|
return this.#indices.getPendingTxCount();
|
|
523
714
|
}
|
|
@@ -562,6 +753,9 @@ export class TxPoolV2Impl {
|
|
|
562
753
|
this.#config.archivedTxLimit = config.archivedTxLimit;
|
|
563
754
|
this.#archive.updateLimit(config.archivedTxLimit);
|
|
564
755
|
}
|
|
756
|
+
if (config.minTxPoolAgeMs !== undefined) {
|
|
757
|
+
this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
|
|
758
|
+
}
|
|
565
759
|
// Update eviction rules with new config
|
|
566
760
|
this.#evictionManager.updateConfig(config);
|
|
567
761
|
}
|
|
@@ -579,8 +773,17 @@ export class TxPoolV2Impl {
|
|
|
579
773
|
|
|
580
774
|
// === Metrics ===
|
|
581
775
|
|
|
582
|
-
countTxs(): {
|
|
583
|
-
|
|
776
|
+
countTxs(): {
|
|
777
|
+
pending: number;
|
|
778
|
+
protected: number;
|
|
779
|
+
mined: number;
|
|
780
|
+
softDeleted: number;
|
|
781
|
+
totalMetadataBytes: number;
|
|
782
|
+
} {
|
|
783
|
+
return {
|
|
784
|
+
...this.#indices.countTxs(),
|
|
785
|
+
softDeleted: this.#deletedPool.getSoftDeletedCount(),
|
|
786
|
+
};
|
|
584
787
|
}
|
|
585
788
|
|
|
586
789
|
// ============================================================================
|
|
@@ -595,11 +798,14 @@ export class TxPoolV2Impl {
|
|
|
595
798
|
tx: Tx,
|
|
596
799
|
state: 'pending' | { protected: SlotNumber } | { mined: L2BlockId },
|
|
597
800
|
opts: { source?: string } = {},
|
|
801
|
+
precomputedMeta?: TxMetaData,
|
|
598
802
|
): Promise<TxMetaData> {
|
|
599
803
|
const txHashStr = tx.getTxHash().toString();
|
|
600
|
-
const meta = await buildTxMetaData(tx);
|
|
804
|
+
const meta = precomputedMeta ?? (await buildTxMetaData(tx));
|
|
805
|
+
meta.receivedAt = this.#dateProvider.now();
|
|
601
806
|
|
|
602
807
|
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
808
|
+
await this.#deletedPool.clearSoftDeleted(txHashStr);
|
|
603
809
|
this.#callbacks.onTxsAdded([tx], opts);
|
|
604
810
|
|
|
605
811
|
if (state === 'pending') {
|
|
@@ -612,9 +818,11 @@ export class TxPoolV2Impl {
|
|
|
612
818
|
}
|
|
613
819
|
|
|
614
820
|
const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
|
|
615
|
-
this.#log.
|
|
821
|
+
this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
|
|
616
822
|
eventName: 'tx-added-to-pool',
|
|
823
|
+
txHash: txHashStr,
|
|
617
824
|
state: stateStr,
|
|
825
|
+
source: opts.source,
|
|
618
826
|
});
|
|
619
827
|
|
|
620
828
|
return meta;
|
|
@@ -624,10 +832,15 @@ export class TxPoolV2Impl {
|
|
|
624
832
|
* Deletes a transaction from both indices and DB.
|
|
625
833
|
* Emits onTxsRemoved callback immediately after DB delete.
|
|
626
834
|
*/
|
|
835
|
+
/**
|
|
836
|
+
* Deletes a transaction from the pool.
|
|
837
|
+
* Delegates to DeletedPool which decides soft vs hard delete based on whether
|
|
838
|
+
* the tx is from a pruned block.
|
|
839
|
+
*/
|
|
627
840
|
async #deleteTx(txHashStr: string): Promise<void> {
|
|
628
841
|
this.#indices.remove(txHashStr);
|
|
629
|
-
await this.#txsDB.delete(txHashStr);
|
|
630
842
|
this.#callbacks.onTxsRemoved([txHashStr]);
|
|
843
|
+
await this.#deletedPool.deleteTx(txHashStr);
|
|
631
844
|
}
|
|
632
845
|
|
|
633
846
|
/** Deletes a batch of transactions, emitting callbacks individually for each. */
|
|
@@ -637,68 +850,63 @@ export class TxPoolV2Impl {
|
|
|
637
850
|
}
|
|
638
851
|
}
|
|
639
852
|
|
|
853
|
+
/** Evicts transactions: records eviction metric with reason, caches hashes, then deletes. */
|
|
854
|
+
async #evictTxs(txHashes: string[], reason: string): Promise<void> {
|
|
855
|
+
if (txHashes.length === 0) {
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
this.#instrumentation.recordEvictions(txHashes.length, reason);
|
|
859
|
+
for (const txHashStr of txHashes) {
|
|
860
|
+
this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
|
|
861
|
+
this.#addToEvictedCache(txHashStr);
|
|
862
|
+
}
|
|
863
|
+
await this.#deleteTxsBatch(txHashes);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */
|
|
867
|
+
#addToEvictedCache(txHashStr: string): void {
|
|
868
|
+
if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
|
|
869
|
+
// FIFO eviction: remove the first (oldest) entry
|
|
870
|
+
const oldest = this.#evictedTxHashes.values().next().value!;
|
|
871
|
+
this.#evictedTxHashes.delete(oldest);
|
|
872
|
+
}
|
|
873
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
874
|
+
}
|
|
875
|
+
|
|
640
876
|
// ============================================================================
|
|
641
877
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
642
878
|
// ============================================================================
|
|
643
879
|
|
|
644
|
-
/** Validates
|
|
645
|
-
async #
|
|
646
|
-
const
|
|
880
|
+
/** Validates transaction metadata, returning true if valid */
|
|
881
|
+
async #validateMeta(meta: TxMetaData, validator?: TxValidator<TxMetaData>, context?: string): Promise<boolean> {
|
|
882
|
+
const txValidator = validator ?? (await this.#createTxValidator());
|
|
883
|
+
const result = await txValidator.validateTx(meta);
|
|
647
884
|
if (result.result !== 'valid') {
|
|
648
885
|
const contextStr = context ? ` ${context}` : '';
|
|
649
|
-
this.#log.info(`Tx ${
|
|
886
|
+
this.#log.info(`Tx ${meta.txHash}${contextStr} failed validation: ${result.reason?.join(', ')}`);
|
|
650
887
|
return false;
|
|
651
888
|
}
|
|
652
889
|
return true;
|
|
653
890
|
}
|
|
654
891
|
|
|
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 }[],
|
|
892
|
+
/** Validates metadata directly */
|
|
893
|
+
async #revalidateMetadata(
|
|
894
|
+
metas: TxMetaData[],
|
|
676
895
|
context?: string,
|
|
677
896
|
): Promise<{ valid: TxMetaData[]; invalid: string[] }> {
|
|
678
897
|
const valid: TxMetaData[] = [];
|
|
679
898
|
const invalid: string[] = [];
|
|
680
|
-
|
|
681
|
-
for (const
|
|
682
|
-
if (await this.#
|
|
899
|
+
const validator = await this.#createTxValidator();
|
|
900
|
+
for (const meta of metas) {
|
|
901
|
+
if (await this.#validateMeta(meta, validator, context)) {
|
|
683
902
|
valid.push(meta);
|
|
684
903
|
} else {
|
|
685
904
|
invalid.push(meta.txHash);
|
|
686
905
|
}
|
|
687
906
|
}
|
|
688
|
-
|
|
689
907
|
return { valid, invalid };
|
|
690
908
|
}
|
|
691
909
|
|
|
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
910
|
/**
|
|
703
911
|
* Resolves nullifier conflicts between incoming txs and existing pending txs.
|
|
704
912
|
* Modifies the pending indices during iteration to maintain consistent state
|
|
@@ -768,6 +976,11 @@ export class TxPoolV2Impl {
|
|
|
768
976
|
const errors: string[] = [];
|
|
769
977
|
|
|
770
978
|
for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
|
|
979
|
+
// Skip soft-deleted transactions - they stay in DB but not in indices
|
|
980
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
|
|
771
984
|
try {
|
|
772
985
|
const tx = Tx.fromBuffer(buffer);
|
|
773
986
|
const meta = await buildTxMetaData(tx);
|
|
@@ -815,7 +1028,9 @@ export class TxPoolV2Impl {
|
|
|
815
1028
|
if (preAddResult.shouldIgnore) {
|
|
816
1029
|
// Transaction rejected - mark for deletion from DB
|
|
817
1030
|
rejected.push(meta.txHash);
|
|
818
|
-
this.#log.debug(
|
|
1031
|
+
this.#log.debug(
|
|
1032
|
+
`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`,
|
|
1033
|
+
);
|
|
819
1034
|
continue;
|
|
820
1035
|
}
|
|
821
1036
|
|
|
@@ -851,7 +1066,7 @@ export class TxPoolV2Impl {
|
|
|
851
1066
|
getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
|
|
852
1067
|
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
853
1068
|
getLowestPriorityPending: (limit: number) => this.#indices.getLowestPriorityPending(limit),
|
|
854
|
-
deleteTxs: (txHashes: string[]) => this.#
|
|
1069
|
+
deleteTxs: (txHashes: string[], reason?: string) => this.#evictTxs(txHashes, reason ?? 'unknown'),
|
|
855
1070
|
};
|
|
856
1071
|
}
|
|
857
1072
|
|