@aztec/p2p 0.0.1-commit.343b43af6 → 0.0.1-commit.350e0a4d
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 +4 -3
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +36 -19
- package/dest/client/interface.d.ts +48 -11
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +34 -19
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +115 -50
- package/dest/config.d.ts +147 -105
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +80 -24
- 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/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 +101 -59
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +272 -199
- 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 +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +6 -4
- 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 +9 -4
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +28 -9
- 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 +3 -3
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +6 -6
- 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 +3 -2
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
- 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 -0
- 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/invalid_txs_after_reorg_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +39 -9
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +13 -3
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +20 -7
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +15 -1
- 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 +31 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +12 -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 +22 -8
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +17 -4
- 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 +217 -120
- 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 +8 -3
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +2 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +8 -3
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +8 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +25 -3
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +85 -15
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +3 -3
- 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 +22 -15
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +51 -19
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +47 -10
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +65 -48
- 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/phases_validator.d.ts +21 -1
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +30 -3
- 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 +15 -15
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +15 -16
- package/dest/services/encoding.d.ts +23 -6
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +32 -16
- package/dest/services/gossipsub/topic_score_params.d.ts +6 -12
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +4 -14
- 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 +45 -47
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +392 -300
- 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 +81 -25
- 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 +4 -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 +81 -86
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +10 -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 +5 -4
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
- 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 +73 -215
- package/dest/services/service.d.ts +25 -12
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +2 -23
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +2 -55
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
- package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +39 -29
- 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.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +0 -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 +36 -55
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +275 -119
- package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +2 -2
- package/dest/services/tx_collection/tx_source.d.ts +6 -5
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +13 -8
- package/dest/services/tx_file_store/tx_file_store.d.ts +1 -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 +4 -14
- package/dest/services/tx_provider.d.ts +3 -1
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +3 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +5 -2
- package/dest/test-helpers/mock-pubsub.d.ts +23 -9
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +44 -44
- package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +16 -18
- 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 +15 -14
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +47 -14
- 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 +102 -40
- package/dest/testbench/worker_client_manager.d.ts +10 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +51 -9
- package/dest/util.d.ts +11 -6
- 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 +57 -11
- package/src/client/interface.ts +44 -17
- package/src/client/p2p_client.ts +138 -83
- package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
- package/src/config.ts +160 -31
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/errors/reqresp.error.ts +13 -19
- package/src/index.ts +0 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +327 -242
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +244 -69
- package/src/mem_pools/attestation_pool/mocks.ts +13 -8
- package/src/mem_pools/index.ts +0 -3
- package/src/mem_pools/instrumentation.ts +18 -12
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +7 -7
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +3 -2
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -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/invalid_txs_after_reorg_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/interfaces.ts +37 -8
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +31 -9
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +35 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +35 -9
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +243 -125
- 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 +15 -3
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +26 -3
- package/src/msg_validators/proposal_validator/proposal_validator.ts +95 -12
- package/src/msg_validators/tx_validator/README.md +17 -3
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +3 -3
- 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 +65 -21
- package/src/msg_validators/tx_validator/gas_validator.ts +99 -54
- package/src/msg_validators/tx_validator/index.ts +2 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +33 -3
- 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 +20 -39
- package/src/services/encoding.ts +35 -19
- package/src/services/gossipsub/README.md +33 -11
- package/src/services/gossipsub/topic_score_params.ts +9 -18
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +444 -339
- package/src/services/peer-manager/peer_manager.ts +89 -24
- 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 +77 -95
- package/src/services/reqresp/batch-tx-requester/interface.ts +13 -5
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
- 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 +84 -259
- package/src/services/service.ts +31 -28
- package/src/services/tx_collection/config.ts +3 -80
- package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
- package/src/services/tx_collection/file_store_tx_source.ts +43 -31
- package/src/services/tx_collection/index.ts +1 -6
- package/src/services/tx_collection/instrumentation.ts +1 -7
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/tx_collection.ts +331 -176
- package/src/services/tx_collection/tx_collection_sink.ts +2 -2
- package/src/services/tx_collection/tx_source.ts +10 -8
- package/src/services/tx_file_store/tx_file_store.ts +5 -17
- package/src/services/tx_provider.ts +5 -0
- package/src/test-helpers/make-test-p2p-clients.ts +3 -0
- package/src/test-helpers/mock-pubsub.ts +46 -60
- package/src/test-helpers/reqresp-nodes.ts +12 -22
- package/src/test-helpers/test_tx_provider.ts +5 -0
- package/src/test-helpers/testbench-utils.ts +62 -28
- package/src/testbench/p2p_client_testbench_worker.ts +109 -56
- package/src/testbench/worker_client_manager.ts +59 -20
- package/src/util.ts +32 -17
- 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 -304
- 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 -16
- 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 -402
- 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/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 -327
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
- package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -49
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
- package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/slow_tx_collection.js +0 -211
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -345
- 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 -23
- package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -321
- package/src/msg_validators/clock_tolerance.ts +0 -51
- 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 -387
- package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
- package/src/services/tx_collection/proposal_tx_collector.ts +0 -113
- package/src/services/tx_collection/slow_tx_collection.ts +0 -266
|
@@ -1,4 +1,5 @@
|
|
|
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';
|
|
3
4
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
4
5
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
EvictionManager,
|
|
18
19
|
FeePayerBalanceEvictionRule,
|
|
19
20
|
FeePayerBalancePreAddRule,
|
|
21
|
+
InsufficientFeePerGasEvictionRule,
|
|
20
22
|
InvalidTxsAfterMiningRule,
|
|
21
23
|
InvalidTxsAfterReorgRule,
|
|
22
24
|
LowPriorityEvictionRule,
|
|
@@ -39,13 +41,28 @@ import {
|
|
|
39
41
|
import { type TxMetaData, type TxState, buildTxMetaData, checkNullifierConflict } from './tx_metadata.js';
|
|
40
42
|
import { TxPoolIndices } from './tx_pool_indices.js';
|
|
41
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
|
+
|
|
42
51
|
/**
|
|
43
52
|
* Callbacks for the implementation to notify the outer class about events and metrics.
|
|
44
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
|
+
|
|
45
62
|
export interface TxPoolV2Callbacks {
|
|
46
63
|
onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
|
|
47
64
|
onTxsRemoved: (txHashes: string[] | bigint[]) => void;
|
|
48
|
-
onTxsMined: (
|
|
65
|
+
onTxsMined: (minedTxs: MinedTxInfo[]) => void;
|
|
49
66
|
}
|
|
50
67
|
|
|
51
68
|
/**
|
|
@@ -56,12 +73,16 @@ export interface TxPoolV2Callbacks {
|
|
|
56
73
|
export class TxPoolV2Impl {
|
|
57
74
|
// === Persistence ===
|
|
58
75
|
#store: AztecAsyncKVStore;
|
|
76
|
+
/** Tx data without its proof. Proofs live in #proofsDB so a tx can be read without loading its proof. */
|
|
59
77
|
#txsDB: AztecAsyncMap<string, Buffer>;
|
|
78
|
+
/** Tx proofs, keyed by tx hash. Written and deleted in lockstep with #txsDB. */
|
|
79
|
+
#proofsDB: AztecAsyncMap<string, Buffer>;
|
|
60
80
|
|
|
61
81
|
// === Dependencies ===
|
|
62
82
|
#l2BlockSource: L2BlockSource;
|
|
63
83
|
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
64
84
|
#createTxValidator: TxPoolV2Dependencies['createTxValidator'];
|
|
85
|
+
#checkAllowedSetupCalls: TxPoolV2Dependencies['checkAllowedSetupCalls'];
|
|
65
86
|
|
|
66
87
|
// === In-Memory Indices ===
|
|
67
88
|
#indices: TxPoolIndices = new TxPoolIndices();
|
|
@@ -73,7 +94,7 @@ export class TxPoolV2Impl {
|
|
|
73
94
|
#evictionManager: EvictionManager;
|
|
74
95
|
#dateProvider: DateProvider;
|
|
75
96
|
#instrumentation: TxPoolV2Instrumentation;
|
|
76
|
-
#evictedTxHashes:
|
|
97
|
+
#evictedTxHashes: FifoSet<string>;
|
|
77
98
|
#log: Logger;
|
|
78
99
|
#callbacks: TxPoolV2Callbacks;
|
|
79
100
|
|
|
@@ -89,14 +110,17 @@ export class TxPoolV2Impl {
|
|
|
89
110
|
) {
|
|
90
111
|
this.#store = store;
|
|
91
112
|
this.#txsDB = store.openMap('txs');
|
|
113
|
+
this.#proofsDB = store.openMap('tx_proofs');
|
|
92
114
|
|
|
93
115
|
this.#l2BlockSource = deps.l2BlockSource;
|
|
94
116
|
this.#worldStateSynchronizer = deps.worldStateSynchronizer;
|
|
95
117
|
this.#createTxValidator = deps.createTxValidator;
|
|
118
|
+
this.#checkAllowedSetupCalls = deps.checkAllowedSetupCalls;
|
|
96
119
|
|
|
97
120
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
121
|
+
this.#evictedTxHashes = FifoSet.withLimit<string>(this.#config.evictedTxCacheSize);
|
|
98
122
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
99
|
-
this.#deletedPool = new DeletedPool(store, this.#
|
|
123
|
+
this.#deletedPool = new DeletedPool(store, txHashStr => this.#deleteTxData(txHashStr), log);
|
|
100
124
|
this.#dateProvider = dateProvider;
|
|
101
125
|
this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
|
|
102
126
|
this.#log = log;
|
|
@@ -114,6 +138,7 @@ export class TxPoolV2Impl {
|
|
|
114
138
|
|
|
115
139
|
// Post-event eviction rules (run after events to check ALL pending txs)
|
|
116
140
|
this.#evictionManager.registerRule(new InvalidTxsAfterMiningRule());
|
|
141
|
+
this.#evictionManager.registerRule(new InsufficientFeePerGasEvictionRule(deps.blockMinFeesProvider));
|
|
117
142
|
this.#evictionManager.registerRule(new InvalidTxsAfterReorgRule(deps.worldStateSynchronizer));
|
|
118
143
|
this.#evictionManager.registerRule(new FeePayerBalanceEvictionRule(deps.worldStateSynchronizer));
|
|
119
144
|
// LowPriorityEvictionRule handles cases where txs become pending via prepareForSlot (unprotect)
|
|
@@ -136,46 +161,74 @@ export class TxPoolV2Impl {
|
|
|
136
161
|
// Step 0: Hydrate deleted pool state
|
|
137
162
|
await this.#deletedPool.hydrateFromDatabase();
|
|
138
163
|
|
|
139
|
-
// Step 1:
|
|
140
|
-
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[] = [];
|
|
168
|
+
|
|
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
|
+
}
|
|
174
|
+
|
|
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
|
+
}
|
|
141
197
|
|
|
142
|
-
|
|
143
|
-
|
|
198
|
+
if (txEffect) {
|
|
199
|
+
meta.minedL2BlockId = {
|
|
200
|
+
number: txEffect.l2BlockNumber,
|
|
201
|
+
hash: txEffect.l2BlockHash.toString(),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
144
204
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const nonMined: { tx: Tx; meta: TxMetaData }[] = [];
|
|
148
|
-
for (const entry of loaded) {
|
|
149
|
-
if (entry.meta.minedL2BlockId !== undefined) {
|
|
150
|
-
mined.push(entry.meta);
|
|
205
|
+
if (meta.minedL2BlockId !== undefined) {
|
|
206
|
+
minedMetas.push(meta);
|
|
151
207
|
} else {
|
|
152
|
-
|
|
208
|
+
pendingMetas.push(meta);
|
|
153
209
|
}
|
|
154
210
|
}
|
|
155
211
|
|
|
156
|
-
// Step
|
|
157
|
-
const { valid, invalid } = await this.#revalidateMetadata(
|
|
158
|
-
nonMined.map(e => e.meta),
|
|
159
|
-
'on startup',
|
|
160
|
-
);
|
|
212
|
+
// Step 2: Validate non-mined transactions
|
|
213
|
+
const { valid, invalid } = await this.#revalidateMetadata(pendingMetas, 'on startup');
|
|
161
214
|
|
|
162
|
-
// Step
|
|
163
|
-
for (const meta of
|
|
215
|
+
// Step 3: Populate mined indices (these don't need conflict resolution)
|
|
216
|
+
for (const meta of minedMetas) {
|
|
164
217
|
this.#indices.addMined(meta);
|
|
165
218
|
}
|
|
166
219
|
|
|
167
|
-
// Step
|
|
220
|
+
// Step 4: Rebuild pending pool by running pre-add rules for each tx
|
|
168
221
|
// This resolves nullifier conflicts, fee payer balance issues, and pool size limits
|
|
169
222
|
const { rejected } = await this.#rebuildPendingPool(valid);
|
|
170
223
|
|
|
171
|
-
// Step
|
|
224
|
+
// Step 5: Delete invalid and rejected txs from DB only (indices were never populated for these)
|
|
172
225
|
const toDelete = [...deserializationErrors, ...invalid, ...rejected];
|
|
173
226
|
if (toDelete.length === 0) {
|
|
174
227
|
return;
|
|
175
228
|
}
|
|
176
229
|
await this.#store.transactionAsync(async () => {
|
|
177
230
|
for (const txHashStr of toDelete) {
|
|
178
|
-
await this.#
|
|
231
|
+
await this.#deleteTxData(txHashStr);
|
|
179
232
|
}
|
|
180
233
|
});
|
|
181
234
|
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
|
|
@@ -375,20 +428,25 @@ export class TxPoolV2Impl {
|
|
|
375
428
|
async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
|
|
376
429
|
const slotNumber = block.globalVariables.slotNumber;
|
|
377
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
|
+
|
|
378
434
|
await this.#store.transactionAsync(async () => {
|
|
379
|
-
for (
|
|
435
|
+
for (let i = 0; i < txs.length; i++) {
|
|
436
|
+
const tx = txs[i];
|
|
380
437
|
const txHash = tx.getTxHash();
|
|
381
438
|
const txHashStr = txHash.toString();
|
|
382
439
|
const isNew = !this.#indices.has(txHashStr);
|
|
383
440
|
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
384
441
|
|
|
385
442
|
if (isNew) {
|
|
443
|
+
const meta = await buildTxMetaData(tx, allowedFlags[i]);
|
|
386
444
|
// New tx - add as mined or protected (callback emitted by #addTx)
|
|
387
445
|
if (minedBlockId) {
|
|
388
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
446
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
389
447
|
this.#indices.setProtection(txHashStr, slotNumber);
|
|
390
448
|
} else {
|
|
391
|
-
await this.#addTx(tx, { protected: slotNumber }, opts);
|
|
449
|
+
await this.#addTx(tx, { protected: slotNumber }, opts, meta);
|
|
392
450
|
}
|
|
393
451
|
} else {
|
|
394
452
|
// Existing tx - update protection and mined status
|
|
@@ -416,10 +474,11 @@ export class TxPoolV2Impl {
|
|
|
416
474
|
// Update protection for existing tx
|
|
417
475
|
this.#indices.updateProtection(txHashStr, slotNumber);
|
|
418
476
|
} else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
419
|
-
// Resurrect soft-deleted tx as protected
|
|
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.
|
|
420
479
|
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
421
480
|
if (buffer) {
|
|
422
|
-
const tx =
|
|
481
|
+
const tx = await this.#loadTxWithProof(txHashStr, buffer);
|
|
423
482
|
await this.#addTx(tx, { protected: slotNumber });
|
|
424
483
|
softDeletedHits++;
|
|
425
484
|
} else {
|
|
@@ -509,7 +568,15 @@ export class TxPoolV2Impl {
|
|
|
509
568
|
});
|
|
510
569
|
|
|
511
570
|
if (found.length > 0) {
|
|
512
|
-
|
|
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
|
+
);
|
|
513
580
|
}
|
|
514
581
|
|
|
515
582
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
@@ -534,29 +601,62 @@ export class TxPoolV2Impl {
|
|
|
534
601
|
}
|
|
535
602
|
|
|
536
603
|
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
604
|
+
await this.#restoreUnprotectedToPending(txsToRestore, 'during prepareForSlot');
|
|
605
|
+
});
|
|
606
|
+
}
|
|
537
607
|
|
|
538
|
-
|
|
539
|
-
|
|
608
|
+
async unprotectTxs(txHashes: TxHash[], slotNumber: SlotNumber): Promise<void> {
|
|
609
|
+
const hashStrs = txHashes.map(h => h.toString());
|
|
540
610
|
|
|
541
|
-
|
|
542
|
-
|
|
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
|
+
}
|
|
543
620
|
|
|
544
|
-
|
|
545
|
-
await this.#deleteTxsBatch(invalid);
|
|
546
|
-
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
621
|
+
this.#indices.clearProtection(matching);
|
|
547
622
|
|
|
548
|
-
|
|
549
|
-
if (
|
|
550
|
-
|
|
551
|
-
const uniqueFeePayers = new Set<string>(feePayers);
|
|
552
|
-
await this.#evictionManager.evictAfterNewTxs(
|
|
553
|
-
added.map(m => m.txHash),
|
|
554
|
-
[...uniqueFeePayers],
|
|
555
|
-
);
|
|
623
|
+
const txsToRestore = this.#indices.filterRestorable(matching);
|
|
624
|
+
if (txsToRestore.length === 0) {
|
|
625
|
+
return;
|
|
556
626
|
}
|
|
627
|
+
|
|
628
|
+
this.#log.info(`Unprotecting ${txsToRestore.length} txs from failed proposal at slot ${slotNumber}`);
|
|
629
|
+
await this.#restoreUnprotectedToPending(txsToRestore, 'during unprotectTxs');
|
|
557
630
|
});
|
|
558
631
|
}
|
|
559
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
|
|
643
|
+
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
644
|
+
|
|
645
|
+
// Step 3: Delete invalid txs and evict conflict losers
|
|
646
|
+
await this.#deleteTxsBatch(invalid);
|
|
647
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
648
|
+
|
|
649
|
+
// Step 4: Run eviction rules (enforce pool size limit)
|
|
650
|
+
if (added.length > 0) {
|
|
651
|
+
const feePayers = added.map(meta => meta.feePayer);
|
|
652
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
653
|
+
await this.#evictionManager.evictAfterNewTxs(
|
|
654
|
+
added.map(m => m.txHash),
|
|
655
|
+
[...uniqueFeePayers],
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
560
660
|
async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
|
|
561
661
|
// Step 1: Find transactions mined after the prune point
|
|
562
662
|
const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
|
|
@@ -628,56 +728,113 @@ export class TxPoolV2Impl {
|
|
|
628
728
|
async handleFinalizedBlock(block: BlockHeader): Promise<void> {
|
|
629
729
|
const blockNumber = block.globalVariables.blockNumber;
|
|
630
730
|
|
|
631
|
-
//
|
|
632
|
-
|
|
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);
|
|
633
734
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
735
|
+
// Step 1: Find mined txs at or before the cutoff block
|
|
736
|
+
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(cutoffBlock);
|
|
737
|
+
|
|
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.
|
|
740
|
+
if (this.#archive.isEnabled()) {
|
|
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) {
|
|
639
745
|
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
640
746
|
if (buffer) {
|
|
641
747
|
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
642
748
|
}
|
|
643
749
|
}
|
|
750
|
+
if (txsToArchive.length > 0) {
|
|
751
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
752
|
+
}
|
|
644
753
|
}
|
|
754
|
+
}
|
|
645
755
|
|
|
646
|
-
|
|
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 () => {
|
|
647
759
|
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
648
|
-
|
|
649
|
-
// Step 4: Finalize soft-deleted txs
|
|
650
|
-
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
651
|
-
|
|
652
|
-
// Step 5: Archive mined txs
|
|
653
|
-
if (txsToArchive.length > 0) {
|
|
654
|
-
await this.#archive.archiveTxs(txsToArchive);
|
|
655
|
-
}
|
|
760
|
+
await this.#deletedPool.finalizeBlock(cutoffBlock);
|
|
656
761
|
});
|
|
657
762
|
|
|
658
763
|
if (minedTxsToFinalize.length > 0) {
|
|
659
|
-
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${
|
|
764
|
+
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${cutoffBlock}`, {
|
|
660
765
|
txHashes: minedTxsToFinalize,
|
|
766
|
+
finalizedBlockNumber: blockNumber,
|
|
767
|
+
cutoffBlock,
|
|
661
768
|
});
|
|
662
769
|
}
|
|
663
770
|
}
|
|
664
771
|
|
|
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;
|
|
784
|
+
}
|
|
785
|
+
|
|
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);
|
|
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);
|
|
804
|
+
}
|
|
805
|
+
|
|
665
806
|
// === Query Methods ===
|
|
666
807
|
|
|
667
|
-
async getTxByHash(txHash: TxHash): Promise<Tx | undefined> {
|
|
668
|
-
const
|
|
669
|
-
|
|
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);
|
|
670
815
|
}
|
|
671
816
|
|
|
672
|
-
async getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
817
|
+
async getTxsByHash(txHashes: TxHash[], opts: { includeProof?: boolean } = {}): Promise<(Tx | undefined)[]> {
|
|
673
818
|
const results: (Tx | undefined)[] = [];
|
|
674
819
|
for (const h of txHashes) {
|
|
675
|
-
|
|
676
|
-
results.push(buffer ? Tx.fromBuffer(buffer) : undefined);
|
|
820
|
+
results.push(await this.getTxByHash(h, opts));
|
|
677
821
|
}
|
|
678
822
|
return results;
|
|
679
823
|
}
|
|
680
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
|
+
|
|
681
838
|
hasTxs(txHashes: TxHash[]): boolean[] {
|
|
682
839
|
return txHashes.map(h => {
|
|
683
840
|
const hashStr = h.toString();
|
|
@@ -713,6 +870,11 @@ export class TxPoolV2Impl {
|
|
|
713
870
|
return this.#indices.getPendingTxCount();
|
|
714
871
|
}
|
|
715
872
|
|
|
873
|
+
hasEligiblePendingTxs(minCount: number): boolean {
|
|
874
|
+
const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
|
|
875
|
+
return this.#indices.hasEligiblePendingTxs(maxReceivedAt, minCount);
|
|
876
|
+
}
|
|
877
|
+
|
|
716
878
|
getMinedTxHashes(): [TxHash, L2BlockId][] {
|
|
717
879
|
return this.#indices.getMinedTxs().map(([hash, blockId]) => [TxHash.fromString(hash), blockId]);
|
|
718
880
|
}
|
|
@@ -756,6 +918,9 @@ export class TxPoolV2Impl {
|
|
|
756
918
|
if (config.minTxPoolAgeMs !== undefined) {
|
|
757
919
|
this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
|
|
758
920
|
}
|
|
921
|
+
if (config.keepFinalizedTxsForSlots !== undefined) {
|
|
922
|
+
this.#config.keepFinalizedTxsForSlots = config.keepFinalizedTxsForSlots;
|
|
923
|
+
}
|
|
759
924
|
// Update eviction rules with new config
|
|
760
925
|
this.#evictionManager.updateConfig(config);
|
|
761
926
|
}
|
|
@@ -804,7 +969,8 @@ export class TxPoolV2Impl {
|
|
|
804
969
|
const meta = precomputedMeta ?? (await buildTxMetaData(tx));
|
|
805
970
|
meta.receivedAt = this.#dateProvider.now();
|
|
806
971
|
|
|
807
|
-
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());
|
|
808
974
|
await this.#deletedPool.clearSoftDeleted(txHashStr);
|
|
809
975
|
this.#callbacks.onTxsAdded([tx], opts);
|
|
810
976
|
|
|
@@ -843,6 +1009,12 @@ export class TxPoolV2Impl {
|
|
|
843
1009
|
await this.#deletedPool.deleteTx(txHashStr);
|
|
844
1010
|
}
|
|
845
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
|
+
|
|
846
1018
|
/** Deletes a batch of transactions, emitting callbacks individually for each. */
|
|
847
1019
|
async #deleteTxsBatch(txHashes: string[]): Promise<void> {
|
|
848
1020
|
for (const txHashStr of txHashes) {
|
|
@@ -858,21 +1030,11 @@ export class TxPoolV2Impl {
|
|
|
858
1030
|
this.#instrumentation.recordEvictions(txHashes.length, reason);
|
|
859
1031
|
for (const txHashStr of txHashes) {
|
|
860
1032
|
this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
|
|
861
|
-
this.#
|
|
1033
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
862
1034
|
}
|
|
863
1035
|
await this.#deleteTxsBatch(txHashes);
|
|
864
1036
|
}
|
|
865
1037
|
|
|
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
|
-
|
|
876
1038
|
// ============================================================================
|
|
877
1039
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
878
1040
|
// ============================================================================
|
|
@@ -967,50 +1129,6 @@ export class TxPoolV2Impl {
|
|
|
967
1129
|
};
|
|
968
1130
|
}
|
|
969
1131
|
|
|
970
|
-
/** Loads all transactions from the database, returning loaded txs and deserialization errors */
|
|
971
|
-
async #loadAllTxsFromDb(): Promise<{
|
|
972
|
-
loaded: { tx: Tx; meta: TxMetaData }[];
|
|
973
|
-
errors: string[];
|
|
974
|
-
}> {
|
|
975
|
-
const loaded: { tx: Tx; meta: TxMetaData }[] = [];
|
|
976
|
-
const errors: string[] = [];
|
|
977
|
-
|
|
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
|
-
|
|
984
|
-
try {
|
|
985
|
-
const tx = Tx.fromBuffer(buffer);
|
|
986
|
-
const meta = await buildTxMetaData(tx);
|
|
987
|
-
loaded.push({ tx, meta });
|
|
988
|
-
} catch (err) {
|
|
989
|
-
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
990
|
-
errors.push(txHashStr);
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
return { loaded, errors };
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
/** Queries block source and marks mined status on transaction metadata */
|
|
998
|
-
async #markMinedStatusBatch(metas: TxMetaData[]): Promise<void> {
|
|
999
|
-
for (const meta of metas) {
|
|
1000
|
-
try {
|
|
1001
|
-
const txEffect = await this.#l2BlockSource.getTxEffect(TxHash.fromString(meta.txHash));
|
|
1002
|
-
if (txEffect) {
|
|
1003
|
-
meta.minedL2BlockId = {
|
|
1004
|
-
number: txEffect.l2BlockNumber,
|
|
1005
|
-
hash: txEffect.l2BlockHash.toString(),
|
|
1006
|
-
};
|
|
1007
|
-
}
|
|
1008
|
-
} catch (err) {
|
|
1009
|
-
this.#log.warn(`Failed to check mined status for tx ${meta.txHash}`, { err });
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
1132
|
/**
|
|
1015
1133
|
* Rebuilds the pending pool by processing each tx through pre-add rules.
|
|
1016
1134
|
* Starts with an empty pending pool and adds txs one by one, resolving conflicts.
|
|
@@ -1085,7 +1203,7 @@ export class TxPoolV2Impl {
|
|
|
1085
1203
|
const publicStateSource = new DatabasePublicStateSource(db);
|
|
1086
1204
|
const balance = await publicStateSource.storageRead(
|
|
1087
1205
|
ProtocolContractAddress.FeeJuice,
|
|
1088
|
-
await computeFeePayerBalanceStorageSlot(AztecAddress.
|
|
1206
|
+
await computeFeePayerBalanceStorageSlot(AztecAddress.fromStringUnsafe(feePayer)),
|
|
1089
1207
|
);
|
|
1090
1208
|
return balance.toBigInt();
|
|
1091
1209
|
},
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Attestation Validation
|
|
2
|
+
|
|
3
|
+
This module validates `CheckpointAttestation` gossipsub messages. Attestations are signatures from committee members endorsing a checkpoint proposal.
|
|
4
|
+
|
|
5
|
+
**Topic**: `checkpoint_attestation` | **Snappy size limit**: 5 KB
|
|
6
|
+
|
|
7
|
+
## Stage 1: AttestationValidator (Gossipsub Validation)
|
|
8
|
+
|
|
9
|
+
| # | Rule | Consequence | Severity | File |
|
|
10
|
+
|---|------|-------------|----------|------|
|
|
11
|
+
| 1 | **Slot timeliness**: `currentSlot` or `nextSlot`. Previous slot within 500ms: IGNORE. Older: REJECT. | REJECT or IGNORE | HighToleranceError | `attestation_validator.ts` |
|
|
12
|
+
| 2 | **Attester signature**: `getSender()` must recover valid address | REJECT | LowToleranceError | same |
|
|
13
|
+
| 3 | **Attester in committee**: recovered address in committee for slot | REJECT | HighToleranceError | same |
|
|
14
|
+
| 4 | **Proposer exists**: `getProposerAttesterAddressInSlot` must return defined | REJECT | HighToleranceError | same |
|
|
15
|
+
| 5 | **Proposer signature**: `getProposer()` must recover valid address | REJECT | LowToleranceError | same |
|
|
16
|
+
| 6 | **Proposer matches expected**: recovered proposer = expected for slot | REJECT | HighToleranceError | same |
|
|
17
|
+
| 7 | **NoCommitteeError**: committee unavailable | REJECT | LowToleranceError | same |
|
|
18
|
+
|
|
19
|
+
**Fisherman mode extension** (`FishermanAttestationValidator`): if a checkpoint proposal for the same archive exists in pool, the attestation's `ConsensusPayload` must `.equals()` the stored proposal's payload. On mismatch: REJECT + LowToleranceError.
|
|
20
|
+
|
|
21
|
+
## Stage 2: Pool Admission
|
|
22
|
+
|
|
23
|
+
| # | Rule | Consequence |
|
|
24
|
+
|---|------|-------------|
|
|
25
|
+
| 8 | Sender recoverable (pool-side) | Silent drop |
|
|
26
|
+
| 9 | Not a duplicate (same slot + proposalId + signer) | IGNORE |
|
|
27
|
+
| 10 | Per-signer cap: `MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER` = 2 | IGNORE |
|
|
28
|
+
|
|
29
|
+
Own attestations added via `addOwnCheckpointAttestations` bypass the per-signer cap.
|
|
30
|
+
|
|
31
|
+
## Stage 3: Equivocation Detection
|
|
32
|
+
|
|
33
|
+
When a signer's attestation count for a slot reaches exactly 2 (different proposals): `duplicateAttestationCallback` fires -> `WANT_TO_SLASH_EVENT` with `OffenseType.DUPLICATE_ATTESTATION`. Attestation still ACCEPTED and rebroadcast. Callback fires once (not again at count 3+).
|
|
34
|
+
|
|
35
|
+
## Validation at L1 Checkpoint Submission (Archiver)
|
|
36
|
+
|
|
37
|
+
| Rule | Consequence | File |
|
|
38
|
+
|------|-------------|------|
|
|
39
|
+
| Each attestation must have recoverable signature (or address-only is allowed but does not count toward quorum) | Checkpoint rejected as invalid | `archiver/src/modules/validation.ts` |
|
|
40
|
+
| Attestation at index `i` must correspond to committee member at index `i` | Checkpoint rejected as invalid | same |
|
|
41
|
+
| Valid attestation count >= floor(committee * 2/3) + 1 | Checkpoint rejected as invalid | same |
|
|
42
|
+
| No committee / escape hatch open | Accepted unconditionally | same |
|
|
43
|
+
|
|
44
|
+
Note: `skipValidateCheckpointAttestations` config flag bypasses all archiver attestation validation.
|
|
45
|
+
|
|
46
|
+
## Gossipsub Topic Scoring
|
|
47
|
+
|
|
48
|
+
P3 enabled with expected messages per slot = `targetCommitteeSize`. Conservative threshold (30% of convergence value). Max P3 penalty = -34 per topic.
|
|
49
|
+
|