@aztec/p2p 0.0.1-commit.4d79d1f2d → 0.0.1-commit.4d9804df
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -3
- package/dest/bootstrap/bootstrap.d.ts +1 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +22 -6
- package/dest/client/factory.d.ts +9 -8
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +50 -34
- package/dest/client/interface.d.ts +59 -27
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +40 -34
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +162 -135
- package/dest/config.d.ts +164 -100
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +149 -49
- package/dest/errors/p2p-service.error.d.ts +9 -0
- package/dest/errors/p2p-service.error.d.ts.map +1 -0
- package/dest/errors/p2p-service.error.js +10 -0
- package/dest/errors/reqresp.error.d.ts +9 -16
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +10 -17
- package/dest/errors/tx-pool.error.d.ts +8 -0
- package/dest/errors/tx-pool.error.d.ts.map +1 -0
- package/dest/errors/tx-pool.error.js +9 -0
- package/dest/index.d.ts +1 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +0 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +103 -59
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +278 -196
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +224 -65
- package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +7 -5
- package/dest/mem_pools/index.d.ts +1 -2
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.d.ts +12 -5
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +38 -17
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -5
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +1 -7
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +32 -15
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +95 -24
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +8 -4
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +12 -4
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +3 -2
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +2 -1
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +54 -5
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +9 -7
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +60 -14
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +6 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +59 -15
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +116 -20
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +26 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +79 -43
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +20 -7
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +34 -12
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +29 -7
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +473 -211
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +38 -15
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +4 -5
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +12 -5
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +11 -3
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +12 -5
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +23 -3
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +36 -9
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +130 -48
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +11 -18
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +25 -21
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
- package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +36 -2
- package/dest/msg_validators/tx_validator/factory.d.ts +133 -7
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +261 -61
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +104 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +137 -53
- package/dest/msg_validators/tx_validator/index.d.ts +5 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +4 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +5 -5
- package/dest/services/discv5/discV5_service.d.ts +13 -2
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +119 -23
- package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
- package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
- package/dest/services/discv5/persisted_enr_store.js +145 -0
- package/dest/services/dummy_service.d.ts +18 -18
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +19 -20
- package/dest/services/encoding.d.ts +23 -6
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +41 -24
- package/dest/services/gossipsub/topic_score_params.d.ts +23 -17
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +36 -24
- package/dest/services/libp2p/instrumentation.d.ts +3 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +14 -0
- package/dest/services/libp2p/libp2p_service.d.ts +57 -56
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +483 -373
- package/dest/services/peer-manager/metrics.d.ts +3 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +6 -0
- package/dest/services/peer-manager/peer_manager.d.ts +20 -3
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +83 -26
- package/dest/services/peer-manager/peer_scoring.d.ts +34 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +102 -13
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +5 -8
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +95 -127
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +11 -11
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +11 -13
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +31 -46
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -11
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +52 -15
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
- package/dest/services/reqresp/config.d.ts +15 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/config.js +11 -0
- package/dest/services/reqresp/interface.d.ts +16 -18
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +10 -20
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +0 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +42 -24
- package/dest/services/reqresp/protocols/index.d.ts +1 -2
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +0 -1
- package/dest/services/reqresp/protocols/tx.d.ts +1 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +1 -3
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -13
- package/dest/services/reqresp/reqresp.d.ts +7 -29
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +75 -216
- package/dest/services/service.d.ts +29 -14
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +8 -17
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +17 -40
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +25 -32
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +96 -87
- package/dest/services/tx_collection/file_store_tx_source.d.ts +17 -6
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +53 -10
- package/dest/services/tx_collection/index.d.ts +2 -3
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +0 -1
- package/dest/services/tx_collection/instrumentation.js +1 -2
- package/dest/services/tx_collection/request_tracker.d.ts +53 -0
- package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/request_tracker.js +84 -0
- package/dest/services/tx_collection/tx_collection.d.ts +39 -55
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +280 -108
- package/dest/services/tx_collection/tx_collection_sink.d.ts +7 -6
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +15 -24
- package/dest/services/tx_collection/tx_source.d.ts +13 -7
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +29 -7
- package/dest/services/tx_file_store/tx_file_store.d.ts +3 -4
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +13 -20
- package/dest/services/tx_provider.d.ts +5 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +7 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +5 -3
- package/dest/test-helpers/mock-pubsub.d.ts +26 -12
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +51 -45
- package/dest/test-helpers/reqresp-nodes.d.ts +5 -7
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +17 -19
- package/dest/test-helpers/test_tx_provider.d.ts +3 -1
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
- package/dest/test-helpers/test_tx_provider.js +3 -0
- package/dest/test-helpers/testbench-utils.d.ts +22 -16
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +56 -16
- package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +111 -48
- package/dest/testbench/worker_client_manager.d.ts +12 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +57 -11
- package/dest/util.d.ts +13 -8
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +35 -14
- package/dest/versioning.d.ts +3 -6
- package/dest/versioning.d.ts.map +1 -1
- package/dest/versioning.js +3 -24
- package/package.json +16 -16
- package/src/bootstrap/bootstrap.ts +17 -3
- package/src/client/factory.ts +95 -51
- package/src/client/interface.ts +59 -35
- package/src/client/p2p_client.ts +186 -196
- package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
- package/src/config.ts +259 -57
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/errors/reqresp.error.ts +13 -19
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +0 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +336 -242
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +244 -69
- package/src/mem_pools/attestation_pool/mocks.ts +14 -8
- package/src/mem_pools/index.ts +0 -3
- package/src/mem_pools/instrumentation.ts +27 -17
- package/src/mem_pools/tx_pool_v2/README.md +52 -28
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +114 -27
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +8 -4
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -4
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +5 -0
- package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +59 -4
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +8 -8
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
- package/src/mem_pools/tx_pool_v2/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +61 -14
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +170 -28
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +91 -43
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +54 -14
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +527 -207
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +46 -14
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +15 -7
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +26 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +43 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +155 -49
- package/src/msg_validators/tx_validator/README.md +129 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +6 -15
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
- package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
- package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +44 -1
- package/src/msg_validators/tx_validator/factory.ts +413 -80
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +195 -54
- package/src/msg_validators/tx_validator/index.ts +4 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
- package/src/msg_validators/tx_validator/timestamp_validator.ts +7 -7
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
- package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
- package/src/services/data_store.ts +5 -13
- package/src/services/discv5/discV5_service.ts +126 -14
- package/src/services/discv5/persisted_enr_store.ts +158 -0
- package/src/services/dummy_service.ts +26 -45
- package/src/services/encoding.ts +40 -24
- package/src/services/gossipsub/README.md +59 -22
- package/src/services/gossipsub/topic_score_params.ts +58 -31
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +554 -428
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +91 -25
- package/src/services/peer-manager/peer_scoring.ts +102 -8
- package/src/services/reqresp/README.md +194 -0
- package/src/services/reqresp/batch-tx-requester/README.md +46 -7
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +92 -138
- package/src/services/reqresp/batch-tx-requester/interface.ts +14 -10
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +30 -71
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
- package/src/services/reqresp/config.ts +19 -2
- package/src/services/reqresp/interface.ts +21 -47
- package/src/services/reqresp/metrics.ts +0 -1
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +1 -3
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -13
- package/src/services/reqresp/reqresp.ts +87 -260
- package/src/services/service.ts +42 -30
- package/src/services/tx_collection/config.ts +24 -59
- package/src/services/tx_collection/file_store_tx_collection.ts +108 -107
- package/src/services/tx_collection/file_store_tx_source.ts +69 -10
- package/src/services/tx_collection/index.ts +1 -6
- package/src/services/tx_collection/instrumentation.ts +1 -1
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/tx_collection.ts +342 -156
- package/src/services/tx_collection/tx_collection_sink.ts +17 -31
- package/src/services/tx_collection/tx_source.ts +29 -8
- package/src/services/tx_file_store/tx_file_store.ts +11 -21
- package/src/services/tx_provider.ts +7 -2
- package/src/test-helpers/make-test-p2p-clients.ts +4 -3
- package/src/test-helpers/mock-pubsub.ts +59 -66
- package/src/test-helpers/reqresp-nodes.ts +15 -28
- package/src/test-helpers/test_tx_provider.ts +5 -0
- package/src/test-helpers/testbench-utils.ts +74 -31
- package/src/testbench/p2p_client_testbench_worker.ts +120 -63
- package/src/testbench/worker_client_manager.ts +72 -25
- package/src/util.ts +40 -19
- package/src/versioning.ts +3 -33
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -305
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
- package/dest/mem_pools/tx_pool/index.d.ts +0 -3
- package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/index.js +0 -2
- package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
- package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/priority.js +0 -15
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
- package/dest/msg_validators/clock_tolerance.d.ts +0 -21
- package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
- package/dest/msg_validators/clock_tolerance.js +0 -37
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
- package/dest/services/reqresp/protocols/block.d.ts +0 -9
- package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
- package/dest/services/reqresp/protocols/block.js +0 -32
- package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -54
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/fast_tx_collection.js +0 -321
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -48
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +0 -49
- package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -55
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/slow_tx_collection.js +0 -206
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -336
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
- package/src/mem_pools/tx_pool/README.md +0 -270
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
- package/src/mem_pools/tx_pool/index.ts +0 -2
- package/src/mem_pools/tx_pool/priority.ts +0 -20
- package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
- package/src/msg_validators/clock_tolerance.ts +0 -51
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
- package/src/services/reqresp/protocols/block.ts +0 -37
- package/src/services/tx_collection/fast_tx_collection.ts +0 -366
- package/src/services/tx_collection/proposal_tx_collector.ts +0 -112
- package/src/services/tx_collection/slow_tx_collection.ts +0 -262
|
@@ -1,125 +1,156 @@
|
|
|
1
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
1
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
3
|
import { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
|
|
5
4
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
6
5
|
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
7
|
-
export const MAX_CHECKPOINT_PROPOSALS_PER_SLOT =
|
|
8
|
-
export const MAX_BLOCK_PROPOSALS_PER_POSITION =
|
|
9
|
-
/** Maximum attestations a single signer can make per slot before being rejected. */ export const MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER =
|
|
6
|
+
export const MAX_CHECKPOINT_PROPOSALS_PER_SLOT = 2;
|
|
7
|
+
export const MAX_BLOCK_PROPOSALS_PER_POSITION = 2;
|
|
8
|
+
/** Maximum attestations a single signer can make per slot before being rejected. */ export const MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER = 2;
|
|
10
9
|
/**
|
|
11
10
|
* Pool for storing attestations and proposals collected by a validator.
|
|
12
11
|
*
|
|
13
12
|
* Attestations and proposals observed via the p2p network are stored for requests
|
|
14
13
|
* from the validator to produce a block, or to serve to other peers.
|
|
14
|
+
*
|
|
15
|
+
* Equivocation detection: distinct *signed payload hashes* arriving at the same
|
|
16
|
+
* position are tracked in the matching index multimap so the equivocation count
|
|
17
|
+
* reaches 2 even when archive collides on `feeAssetPriceModifier` variants.
|
|
18
|
+
* Proposal bytes are retained per accepted payload hash, up to the same equivocation
|
|
19
|
+
* caps, for slashing watchers that need signed P2P proposals.
|
|
15
20
|
*/ export class AttestationPool {
|
|
16
21
|
store;
|
|
17
22
|
log;
|
|
18
23
|
metrics;
|
|
19
|
-
// Checkpoint attestations from
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
// Key:
|
|
26
|
-
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
// Checkpoint attestations from `${paddedSlot}-${signer}` to serialized CheckpointAttestation.
|
|
25
|
+
// Stores the first attestation seen per (slot, signer); subsequent distinct payload
|
|
26
|
+
// hashes from the same signer are tracked only in `attestationHashesPerSlotAndSigner`
|
|
27
|
+
// for equivocation detection.
|
|
28
|
+
attestationPerSlotAndSigner;
|
|
29
|
+
// Distinct payload hashes seen per (slot, signer) for tracking attestation equivocations.
|
|
30
|
+
// Key: `${paddedSlot}-${signerAddress}`, Value: CheckpointProposalHash (`0x`-prefixed hex)
|
|
31
|
+
attestationHashesPerSlotAndSigner;
|
|
32
|
+
// Checkpoint proposals from `${paddedSlot}-${payloadHash}` to serialized CheckpointProposalCore.
|
|
33
|
+
// Stores every accepted distinct payload up to MAX_CHECKPOINT_PROPOSALS_PER_SLOT.
|
|
34
|
+
checkpointProposalsPerSlotAndHash;
|
|
35
|
+
// Distinct payload hashes seen per slot. Hash collision = duplicate.
|
|
36
|
+
// Hash count reaching 2 = equivocation.
|
|
37
|
+
// Key: slot number, Value: CheckpointProposalHash (`0x`-prefixed hex)
|
|
38
|
+
checkpointProposalHashesPerSlot;
|
|
39
|
+
// Block proposals from `${paddedSlot}-${paddedIndex}-${payloadHash}` to serialized BlockProposal.
|
|
40
|
+
// Stores every accepted distinct payload up to MAX_BLOCK_PROPOSALS_PER_POSITION.
|
|
41
|
+
blockProposalsPerSlotIndexAndHash;
|
|
42
|
+
// Distinct payload hashes seen per (slot, indexWithinCheckpoint).
|
|
43
|
+
// Key: slot * (1 << INDEX_BITS) + indexWithinCheckpoint, Value: BlockProposalHash (`0x`-prefixed hex)
|
|
44
|
+
blockProposalHashesPerSlotAndIndex;
|
|
45
|
+
// Secondary index from archive root to all retained block proposal keys.
|
|
46
|
+
blockProposalKeysPerArchive;
|
|
35
47
|
constructor(store, telemetry = getTelemetryClient(), log = createLogger('aztec:attestation_pool')){
|
|
36
48
|
this.store = store;
|
|
37
49
|
this.log = log;
|
|
38
50
|
this.poolStats = async ()=>{
|
|
39
51
|
return {
|
|
40
|
-
itemCount: await this.
|
|
52
|
+
itemCount: await this.attestationPerSlotAndSigner.sizeAsync()
|
|
41
53
|
};
|
|
42
54
|
};
|
|
43
55
|
// Initialize block proposal storage
|
|
44
|
-
this.
|
|
45
|
-
this.
|
|
56
|
+
this.blockProposalsPerSlotIndexAndHash = store.openMap('block_proposals_by_slot_index_and_hash');
|
|
57
|
+
this.blockProposalHashesPerSlotAndIndex = store.openMultiMap('block_proposals_for_slot_and_index');
|
|
58
|
+
this.blockProposalKeysPerArchive = store.openMultiMap('block_proposals_by_archive');
|
|
46
59
|
// Initialize checkpoint attestations storage
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
60
|
+
this.attestationPerSlotAndSigner = store.openMap('checkpoint_attestations');
|
|
61
|
+
this.attestationHashesPerSlotAndSigner = store.openMultiMap('checkpoint_attestations_per_slot_and_signer');
|
|
49
62
|
// Initialize checkpoint proposal storage
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
63
|
+
this.checkpointProposalsPerSlotAndHash = store.openMap('checkpoint_proposals_by_slot_and_hash');
|
|
64
|
+
this.checkpointProposalHashesPerSlot = store.openMultiMap('checkpoint_proposals_for_slot');
|
|
52
65
|
this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL, this.poolStats);
|
|
53
66
|
}
|
|
54
67
|
poolStats;
|
|
55
68
|
/** Returns whether the pool is empty. */ async isEmpty() {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
const [attestationCount, blockProposalCount, checkpointProposalCount] = await Promise.all([
|
|
70
|
+
this.attestationPerSlotAndSigner.sizeAsync(),
|
|
71
|
+
this.blockProposalsPerSlotIndexAndHash.sizeAsync(),
|
|
72
|
+
this.checkpointProposalsPerSlotAndHash.sizeAsync()
|
|
73
|
+
]);
|
|
74
|
+
return attestationCount === 0 && blockProposalCount === 0 && checkpointProposalCount === 0;
|
|
75
|
+
}
|
|
76
|
+
/** Number of bits reserved for indexWithinCheckpoint in position keys. */ static INDEX_BITS = 10;
|
|
77
|
+
/** Maximum indexWithinCheckpoint value (2^10 - 1 = 1023). */ static MAX_INDEX = (1 << AttestationPool.INDEX_BITS) - 1;
|
|
78
|
+
/** Decimal digits used to left-pad slot numbers in string keys.
|
|
79
|
+
* 10 digits ≈ 3500 years at 36 s/slot, leaving ample headroom. */ static SLOT_PAD_DIGITS = 10;
|
|
80
|
+
/** Fixed-width decimal slot string for use in composite string keys. */ slotPaddedKey(slot) {
|
|
81
|
+
return slot.toString().padStart(AttestationPool.SLOT_PAD_DIGITS, '0');
|
|
63
82
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const proposalIdStr = typeof proposalId === 'string' ? proposalId : Buffer.isBuffer(proposalId) ? Fr.fromBuffer(proposalId).toString() : proposalId.toString();
|
|
67
|
-
return `${slotStr}-${proposalIdStr}`;
|
|
83
|
+
/** Fixed-width decimal index string for use in composite string keys. */ indexPaddedKey(indexWithinCheckpoint) {
|
|
84
|
+
return indexWithinCheckpoint.toString().padStart(4, '0');
|
|
68
85
|
}
|
|
69
|
-
|
|
70
|
-
return `${this.
|
|
86
|
+
/** Key for retained block proposals. */ getBlockProposalKey(slot, indexWithinCheckpoint, payloadHash) {
|
|
87
|
+
return `${this.slotPaddedKey(slot)}-${this.indexPaddedKey(indexWithinCheckpoint)}-${payloadHash}`;
|
|
71
88
|
}
|
|
72
|
-
/**
|
|
73
|
-
const slotStr = new Fr(slot).toString();
|
|
89
|
+
/** Range bounds for all retained block proposals in a slot. */ getBlockProposalKeyRangeForSlot(slot) {
|
|
74
90
|
return {
|
|
75
|
-
start: `${
|
|
76
|
-
end: `${
|
|
77
|
-
};
|
|
91
|
+
start: `${this.slotPaddedKey(slot)}-`,
|
|
92
|
+
end: `${this.slotPaddedKey(slot + 1)}-`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** Key for retained checkpoint proposals. */ getCheckpointProposalKey(slot, payloadHash) {
|
|
96
|
+
return `${this.slotPaddedKey(slot)}-${payloadHash}`;
|
|
78
97
|
}
|
|
79
|
-
/**
|
|
80
|
-
const proposalKey = this.getProposalKey(slot, proposalId);
|
|
98
|
+
/** Range bounds for all retained checkpoint proposals in a slot. */ getCheckpointProposalKeyRangeForSlot(slot) {
|
|
81
99
|
return {
|
|
82
|
-
start: `${
|
|
83
|
-
end: `${
|
|
100
|
+
start: `${this.slotPaddedKey(slot)}-`,
|
|
101
|
+
end: `${this.slotPaddedKey(slot + 1)}-`
|
|
84
102
|
};
|
|
85
103
|
}
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
return `${slotStr}-${signerAddress}`;
|
|
104
|
+
/** Key for the per-(slot, signer) attestation main store and equivocation index. */ getSlotSignerKey(slot, signerAddress) {
|
|
105
|
+
return `${this.slotPaddedKey(slot)}-${signerAddress}`;
|
|
89
106
|
}
|
|
90
|
-
/**
|
|
91
|
-
|
|
92
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Returns range bounds for querying all attestations for a given slot.
|
|
109
|
+
* Fixed-width padding ensures the slot prefix sorts cleanly, so using the next
|
|
110
|
+
* slot's prefix as the upper bound captures exactly the current slot's entries.
|
|
111
|
+
*/ getAttestationKeyRangeForSlot(slot) {
|
|
112
|
+
return {
|
|
113
|
+
start: `${this.slotPaddedKey(slot)}-`,
|
|
114
|
+
end: `${this.slotPaddedKey(slot + 1)}-`
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Creates a position key for block proposals: slot * 1024 + indexWithinCheckpoint.
|
|
118
|
+
* Uses multiplication instead of bit-shift to avoid 32-bit signed integer overflow
|
|
119
|
+
* (bit-shift overflows after slot ~2^21, roughly 278 days of uptime). */ getBlockPositionKey(slot, indexWithinCheckpoint) {
|
|
93
120
|
if (indexWithinCheckpoint > AttestationPool.MAX_INDEX) {
|
|
94
121
|
throw new Error(`Value for indexWithinCheckpoint ${indexWithinCheckpoint} exceeds maximum ${AttestationPool.MAX_INDEX}`);
|
|
95
122
|
}
|
|
96
|
-
return slot << AttestationPool.INDEX_BITS
|
|
123
|
+
return slot * (1 << AttestationPool.INDEX_BITS) + indexWithinCheckpoint;
|
|
124
|
+
}
|
|
125
|
+
/** Returns true if the multimap already contains the given value for the given key. */ async multimapHasValue(map, key, value) {
|
|
126
|
+
const values = await toArray(map.getValuesAsync(key));
|
|
127
|
+
return values.includes(value);
|
|
97
128
|
}
|
|
98
129
|
/**
|
|
99
130
|
* Attempts to add a block proposal to the pool.
|
|
100
131
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* -
|
|
104
|
-
*
|
|
132
|
+
* - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
|
|
133
|
+
* exact same signed payload returns `alreadyExists: true`.
|
|
134
|
+
* - Distinct payload hashes at the same `(slot, indexWithinCheckpoint)` are tracked
|
|
135
|
+
* in the equivocation index and retained up to the cap.
|
|
105
136
|
*
|
|
106
137
|
* @param blockProposal - The block proposal to add
|
|
107
138
|
* @returns Result indicating whether the proposal was added and duplicate detection info
|
|
108
139
|
*/ async tryAddBlockProposal(blockProposal) {
|
|
109
140
|
return await this.store.transactionAsync(async ()=>{
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
const count = await this.
|
|
141
|
+
const positionKey = this.getBlockPositionKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
|
|
142
|
+
const payloadHash = blockProposal.getPayloadHash();
|
|
143
|
+
// Hash already tracked => exact same signed payload was already received.
|
|
144
|
+
if (await this.multimapHasValue(this.blockProposalHashesPerSlotAndIndex, positionKey, payloadHash)) {
|
|
145
|
+
const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
|
|
115
146
|
return {
|
|
116
147
|
added: false,
|
|
117
148
|
alreadyExists: true,
|
|
118
149
|
count
|
|
119
150
|
};
|
|
120
151
|
}
|
|
121
|
-
//
|
|
122
|
-
const count = await this.
|
|
152
|
+
// Cap reached for this position (no more new payload hashes accepted).
|
|
153
|
+
const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
|
|
123
154
|
if (count >= MAX_BLOCK_PROPOSALS_PER_POSITION) {
|
|
124
155
|
return {
|
|
125
156
|
added: false,
|
|
@@ -127,10 +158,14 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
127
158
|
count
|
|
128
159
|
};
|
|
129
160
|
}
|
|
130
|
-
//
|
|
131
|
-
await this.
|
|
161
|
+
// Track the new payload hash for equivocation detection.
|
|
162
|
+
await this.blockProposalHashesPerSlotAndIndex.set(positionKey, payloadHash);
|
|
163
|
+
const proposalKey = this.getBlockProposalKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint, payloadHash);
|
|
164
|
+
await this.blockProposalsPerSlotIndexAndHash.set(proposalKey, blockProposal.withoutSignedTxs().toBuffer());
|
|
165
|
+
await this.blockProposalKeysPerArchive.set(blockProposal.archive.toString(), proposalKey);
|
|
132
166
|
this.log.debug(`Added block proposal for slot ${blockProposal.slotNumber} and index ${blockProposal.indexWithinCheckpoint}`, {
|
|
133
|
-
|
|
167
|
+
archive: blockProposal.archive.toString(),
|
|
168
|
+
payloadHash,
|
|
134
169
|
slotNumber: blockProposal.slotNumber,
|
|
135
170
|
indexWithinCheckpoint: blockProposal.indexWithinCheckpoint
|
|
136
171
|
});
|
|
@@ -141,42 +176,67 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
141
176
|
};
|
|
142
177
|
});
|
|
143
178
|
}
|
|
144
|
-
/** Gets the count of block proposals for a given position (slot, indexWithinCheckpoint). */ getBlockProposalCountForPosition(slot, indexWithinCheckpoint) {
|
|
145
|
-
const positionKey = this.getBlockPositionKey(slot, indexWithinCheckpoint);
|
|
146
|
-
return this.blockProposalsForSlotAndIndex.getValueCountAsync(positionKey);
|
|
147
|
-
}
|
|
148
|
-
/** Internal method - must be called within a transaction. */ async addBlockProposal(blockProposal) {
|
|
149
|
-
const proposalId = blockProposal.archive.toString();
|
|
150
|
-
// Strip signedTxs before storing to avoid persisting full tx data
|
|
151
|
-
await this.blockProposals.set(proposalId, blockProposal.withoutSignedTxs().toBuffer());
|
|
152
|
-
// Index by slot and position for duplicate detection
|
|
153
|
-
const positionKey = this.getBlockPositionKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
|
|
154
|
-
await this.blockProposalsForSlotAndIndex.set(positionKey, proposalId);
|
|
155
|
-
}
|
|
156
179
|
/**
|
|
157
|
-
* Get block proposal by
|
|
180
|
+
* Get block proposal by archive root.
|
|
158
181
|
*
|
|
159
|
-
*
|
|
182
|
+
* Resolves the archive root through the archive index and returns the first
|
|
183
|
+
* retained proposal for that archive. This lookup is used by block-txs req/resp,
|
|
184
|
+
* where any retained proposal for the requested archive gives the tx hash list.
|
|
160
185
|
*
|
|
161
|
-
* @
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
186
|
+
* @param archiveRoot - The archive root to look up
|
|
187
|
+
* @return The block proposal if it exists and its archive matches, otherwise undefined.
|
|
188
|
+
*/ async getBlockProposalByArchive(archiveRoot) {
|
|
189
|
+
for await (const proposalKey of this.blockProposalKeysPerArchive.getValuesAsync(archiveRoot)){
|
|
190
|
+
const buffer = await this.blockProposalsPerSlotIndexAndHash.getAsync(proposalKey);
|
|
191
|
+
if (!buffer || buffer.length === 0) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const proposal = BlockProposal.fromBuffer(buffer);
|
|
196
|
+
if (proposal.archive.toString() === archiveRoot) {
|
|
197
|
+
return proposal;
|
|
198
|
+
}
|
|
199
|
+
} catch {
|
|
200
|
+
continue;
|
|
167
201
|
}
|
|
168
|
-
} catch {
|
|
169
|
-
return undefined;
|
|
170
202
|
}
|
|
171
203
|
return undefined;
|
|
172
204
|
}
|
|
205
|
+
/** Returns retained signed proposals for a slot. */ async getProposalsForSlot(slot) {
|
|
206
|
+
const blockProposals = [];
|
|
207
|
+
const checkpointProposals = [];
|
|
208
|
+
for await (const [_, buffer] of this.blockProposalsPerSlotIndexAndHash.entriesAsync(this.getBlockProposalKeyRangeForSlot(slot))){
|
|
209
|
+
try {
|
|
210
|
+
blockProposals.push(BlockProposal.fromBuffer(buffer));
|
|
211
|
+
} catch {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
for await (const [_, buffer] of this.checkpointProposalsPerSlotAndHash.entriesAsync(this.getCheckpointProposalKeyRangeForSlot(slot))){
|
|
216
|
+
try {
|
|
217
|
+
checkpointProposals.push(CheckpointProposal.fromBuffer(buffer));
|
|
218
|
+
} catch {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
blockProposals,
|
|
224
|
+
checkpointProposals
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/** Checks if any block proposals exist for a given slot (at index 0). */ async hasBlockProposalsForSlot(slot) {
|
|
228
|
+
const positionKey = this.getBlockPositionKey(slot, 0);
|
|
229
|
+
const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
|
|
230
|
+
return count > 0;
|
|
231
|
+
}
|
|
173
232
|
/**
|
|
174
233
|
* Attempts to add a checkpoint proposal to the pool.
|
|
175
234
|
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
* -
|
|
179
|
-
*
|
|
235
|
+
* - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
|
|
236
|
+
* exact same signed payload returns `alreadyExists: true`.
|
|
237
|
+
* - Distinct payload hashes at the same slot are tracked in the equivocation index.
|
|
238
|
+
* Distinct payload bytes are retained up to the same cap so slashing watchers
|
|
239
|
+
* can recover signed proposals.
|
|
180
240
|
*
|
|
181
241
|
* Note: This method only handles the CheckpointProposalCore. If the original
|
|
182
242
|
* CheckpointProposal contains a lastBlock, the caller should extract it via
|
|
@@ -186,19 +246,17 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
186
246
|
* @returns Result indicating whether the proposal was added and duplicate detection info
|
|
187
247
|
*/ async tryAddCheckpointProposal(proposal) {
|
|
188
248
|
return await this.store.transactionAsync(async ()=>{
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const count = await this.checkpointProposalsForSlot.getValueCountAsync(proposal.slotNumber);
|
|
249
|
+
const slot = proposal.slotNumber;
|
|
250
|
+
const payloadHash = proposal.getPayloadHash();
|
|
251
|
+
if (await this.multimapHasValue(this.checkpointProposalHashesPerSlot, slot, payloadHash)) {
|
|
252
|
+
const count = await this.checkpointProposalHashesPerSlot.getValueCountAsync(slot);
|
|
194
253
|
return {
|
|
195
254
|
added: false,
|
|
196
255
|
alreadyExists: true,
|
|
197
256
|
count
|
|
198
257
|
};
|
|
199
258
|
}
|
|
200
|
-
|
|
201
|
-
const count = await this.checkpointProposalsForSlot.getValueCountAsync(proposal.slotNumber);
|
|
259
|
+
const count = await this.checkpointProposalHashesPerSlot.getValueCountAsync(slot);
|
|
202
260
|
if (count >= MAX_CHECKPOINT_PROPOSALS_PER_SLOT) {
|
|
203
261
|
return {
|
|
204
262
|
added: false,
|
|
@@ -206,11 +264,13 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
206
264
|
count
|
|
207
265
|
};
|
|
208
266
|
}
|
|
209
|
-
//
|
|
210
|
-
await this.
|
|
211
|
-
this.
|
|
212
|
-
|
|
213
|
-
|
|
267
|
+
// Track the new payload hash for equivocation detection.
|
|
268
|
+
await this.checkpointProposalHashesPerSlot.set(slot, payloadHash);
|
|
269
|
+
await this.checkpointProposalsPerSlotAndHash.set(this.getCheckpointProposalKey(slot, payloadHash), proposal.toBuffer());
|
|
270
|
+
this.log.debug(`Added checkpoint proposal for slot ${slot}`, {
|
|
271
|
+
archive: proposal.archive.toString(),
|
|
272
|
+
payloadHash,
|
|
273
|
+
slotNumber: slot
|
|
214
274
|
});
|
|
215
275
|
return {
|
|
216
276
|
added: true,
|
|
@@ -219,56 +279,66 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
219
279
|
};
|
|
220
280
|
});
|
|
221
281
|
}
|
|
222
|
-
/** Internal method - must be called within a transaction. */ async addCheckpointProposal(proposal) {
|
|
223
|
-
const slotKey = proposal.slotNumber;
|
|
224
|
-
const proposalId = proposal.archive.toString();
|
|
225
|
-
await this.checkpointProposalsForSlot.set(slotKey, proposalId);
|
|
226
|
-
await this.checkpointProposals.set(proposalId, proposal.toBuffer());
|
|
227
|
-
}
|
|
228
282
|
/**
|
|
229
|
-
* Get checkpoint proposal
|
|
283
|
+
* Get a retained checkpoint proposal stored for the given slot.
|
|
284
|
+
* If multiple proposals were retained for an equivocation, returns the lowest
|
|
285
|
+
* payload hash deterministically.
|
|
230
286
|
*
|
|
231
287
|
* Returns a CheckpointProposalCore (without lastBlock info) since the lastBlock
|
|
232
288
|
* is extracted and stored separately as a BlockProposal when added.
|
|
233
289
|
*
|
|
234
|
-
* @param
|
|
235
|
-
* @return The checkpoint proposal core if
|
|
236
|
-
*/ async getCheckpointProposal(
|
|
237
|
-
const buffer
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
290
|
+
* @param slot - The slot to look up
|
|
291
|
+
* @return The checkpoint proposal core if one is stored, otherwise undefined.
|
|
292
|
+
*/ async getCheckpointProposal(slot) {
|
|
293
|
+
for await (const [_, buffer] of this.checkpointProposalsPerSlotAndHash.entriesAsync(this.getCheckpointProposalKeyRangeForSlot(slot))){
|
|
294
|
+
try {
|
|
295
|
+
if (buffer && buffer.length > 0) {
|
|
296
|
+
return CheckpointProposal.fromBuffer(buffer);
|
|
297
|
+
}
|
|
298
|
+
} catch {
|
|
299
|
+
continue;
|
|
241
300
|
}
|
|
242
|
-
} catch {
|
|
243
|
-
return undefined;
|
|
244
301
|
}
|
|
245
302
|
return undefined;
|
|
246
303
|
}
|
|
304
|
+
/** Returns whether any checkpoint proposal is retained for the given slot. */ async hasCheckpointProposalForSlot(slot) {
|
|
305
|
+
return await this.getCheckpointProposal(slot) !== undefined;
|
|
306
|
+
}
|
|
247
307
|
/**
|
|
248
308
|
* Adds own checkpoint attestations to the pool.
|
|
249
|
-
* Skips
|
|
309
|
+
* Skips per-signer cap and equivocation tracking; the caller is trusted.
|
|
310
|
+
* Each (slot, signer) gets a single stored attestation; later additions overwrite.
|
|
250
311
|
*/ async addOwnCheckpointAttestations(attestations) {
|
|
251
312
|
await this.store.transactionAsync(async ()=>{
|
|
252
313
|
for (const attestation of attestations){
|
|
253
314
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
254
|
-
const proposalId = attestation.archive;
|
|
255
315
|
const sender = attestation.getSender();
|
|
256
316
|
// Skip attestations with invalid signatures
|
|
257
317
|
if (!sender) {
|
|
258
318
|
this.log.warn(`Skipping own checkpoint attestation with invalid signature for slot ${slotNumber}`, {
|
|
259
319
|
signature: attestation.signature.toString(),
|
|
260
320
|
slotNumber,
|
|
261
|
-
|
|
321
|
+
archive: attestation.archive.toString()
|
|
262
322
|
});
|
|
263
323
|
continue;
|
|
264
324
|
}
|
|
265
325
|
const address = sender.toString();
|
|
266
|
-
|
|
326
|
+
const ownKey = this.getSlotSignerKey(slotNumber, address);
|
|
327
|
+
const payloadHash = attestation.getPayloadHash();
|
|
328
|
+
// Store the signature in canonical (v ∈ {27, 28}) form; see tryAddCheckpointAttestation.
|
|
329
|
+
await this.attestationPerSlotAndSigner.set(ownKey, attestation.withNormalizedSignature().toBuffer());
|
|
330
|
+
this.metrics.trackMempoolItemAdded(ownKey);
|
|
331
|
+
// Track our own payload hash so that an equivocating attestation from another
|
|
332
|
+
// peer at the same (slot, signer) is detected as a duplicate.
|
|
333
|
+
if (!await this.multimapHasValue(this.attestationHashesPerSlotAndSigner, ownKey, payloadHash)) {
|
|
334
|
+
await this.attestationHashesPerSlotAndSigner.set(ownKey, payloadHash);
|
|
335
|
+
}
|
|
267
336
|
this.log.debug(`Added own checkpoint attestation for slot ${slotNumber} from ${address}`, {
|
|
268
337
|
signature: attestation.signature.toString(),
|
|
269
338
|
slotNumber,
|
|
270
339
|
address,
|
|
271
|
-
|
|
340
|
+
archive: attestation.archive.toString(),
|
|
341
|
+
payloadHash
|
|
272
342
|
});
|
|
273
343
|
}
|
|
274
344
|
});
|
|
@@ -276,29 +346,30 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
276
346
|
/**
|
|
277
347
|
* Get all checkpoint attestations for a given slot.
|
|
278
348
|
*
|
|
349
|
+
* Returns one attestation per (slot, signer) — the first seen for each signer.
|
|
350
|
+
* Later equivocating attestations from the same signer are tracked in the index
|
|
351
|
+
* but their bytes are not retained.
|
|
352
|
+
*
|
|
279
353
|
* @param slot - The slot to query
|
|
280
354
|
* @return CheckpointAttestations
|
|
281
355
|
*/ async getCheckpointAttestationsForSlot(slot) {
|
|
282
356
|
const range = this.getAttestationKeyRangeForSlot(slot);
|
|
283
357
|
const attestations = [];
|
|
284
|
-
for await (const [_, buf] of this.
|
|
358
|
+
for await (const [_, buf] of this.attestationPerSlotAndSigner.entriesAsync(range)){
|
|
285
359
|
attestations.push(CheckpointAttestation.fromBuffer(buf));
|
|
286
360
|
}
|
|
287
361
|
return attestations;
|
|
288
362
|
}
|
|
289
363
|
/**
|
|
290
|
-
* Get checkpoint attestations for slot
|
|
364
|
+
* Get checkpoint attestations for a slot whose signed payload matches the given
|
|
365
|
+
* proposal payload hash.
|
|
291
366
|
*
|
|
292
367
|
* @param slot - The slot to query
|
|
293
|
-
* @param
|
|
294
|
-
* @return CheckpointAttestations
|
|
295
|
-
*/ async getCheckpointAttestationsForSlotAndProposal(slot,
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
for await (const [_, buf] of this.checkpointAttestations.entriesAsync(range)){
|
|
299
|
-
attestations.push(CheckpointAttestation.fromBuffer(buf));
|
|
300
|
-
}
|
|
301
|
-
return attestations;
|
|
368
|
+
* @param proposalPayloadHash - Hex-encoded keccak256 of the target proposal's signed payload
|
|
369
|
+
* @return CheckpointAttestations whose `getPayloadHash()` matches `proposalPayloadHash`
|
|
370
|
+
*/ async getCheckpointAttestationsForSlotAndProposal(slot, proposalPayloadHash) {
|
|
371
|
+
const all = await this.getCheckpointAttestationsForSlot(slot);
|
|
372
|
+
return all.filter((att)=>att.getPayloadHash() === proposalPayloadHash);
|
|
302
373
|
}
|
|
303
374
|
/**
|
|
304
375
|
* Delete all pool data (attestations, proposals) older than the given slot.
|
|
@@ -309,47 +380,53 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
309
380
|
let numberOfCheckpointProposals = 0;
|
|
310
381
|
let numberOfBlockProposals = 0;
|
|
311
382
|
await this.store.transactionAsync(async ()=>{
|
|
312
|
-
|
|
313
|
-
//
|
|
314
|
-
|
|
315
|
-
for await (const key of this.
|
|
316
|
-
end:
|
|
383
|
+
const oldestSlotPadded = this.slotPaddedKey(oldestSlot);
|
|
384
|
+
// Delete checkpoint attestations whose key < `${oldestSlotPadded}-`. Fixed-width
|
|
385
|
+
// decimal padding means the slot prefix sorts strictly before any key at that slot.
|
|
386
|
+
for await (const key of this.attestationPerSlotAndSigner.keysAsync({
|
|
387
|
+
end: `${oldestSlotPadded}-`
|
|
317
388
|
})){
|
|
318
|
-
await this.
|
|
389
|
+
await this.attestationPerSlotAndSigner.delete(key);
|
|
390
|
+
this.metrics.trackMempoolItemRemoved(key);
|
|
319
391
|
numberOfAttestations++;
|
|
320
392
|
}
|
|
321
|
-
// Clean up per-signer-per-slot index
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const slotSignerEndKey = new Fr(oldestSlot).toString();
|
|
325
|
-
for await (const key of this.checkpointAttestationsPerSlotAndSigner.keysAsync({
|
|
326
|
-
end: slotSignerEndKey
|
|
393
|
+
// Clean up per-signer-per-slot index using the same end bound.
|
|
394
|
+
for await (const key of this.attestationHashesPerSlotAndSigner.keysAsync({
|
|
395
|
+
end: `${oldestSlotPadded}-`
|
|
327
396
|
})){
|
|
328
|
-
await this.
|
|
397
|
+
await this.attestationHashesPerSlotAndSigner.delete(key);
|
|
329
398
|
}
|
|
330
|
-
// Delete checkpoint proposals for slots < oldestSlot
|
|
331
|
-
for await (const slot of this.
|
|
399
|
+
// Delete checkpoint proposals for slots < oldestSlot.
|
|
400
|
+
for await (const slot of this.checkpointProposalHashesPerSlot.keysAsync({
|
|
332
401
|
end: oldestSlot
|
|
333
402
|
})){
|
|
334
|
-
|
|
335
|
-
for (const proposalId of proposalIds){
|
|
336
|
-
await this.checkpointProposals.delete(proposalId);
|
|
337
|
-
numberOfCheckpointProposals++;
|
|
338
|
-
}
|
|
339
|
-
await this.checkpointProposalsForSlot.delete(slot);
|
|
403
|
+
await this.checkpointProposalHashesPerSlot.delete(slot);
|
|
340
404
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
405
|
+
for await (const key of this.checkpointProposalsPerSlotAndHash.keysAsync({
|
|
406
|
+
end: `${oldestSlotPadded}-`
|
|
407
|
+
})){
|
|
408
|
+
await this.checkpointProposalsPerSlotAndHash.delete(key);
|
|
409
|
+
numberOfCheckpointProposals++;
|
|
410
|
+
}
|
|
411
|
+
// Delete block proposals for slots < oldestSlot, using blockProposalHashesPerSlotAndIndex as index.
|
|
412
|
+
// Key format: slot * (1 << INDEX_BITS) + indexWithinCheckpoint
|
|
413
|
+
const blockPositionEndKey = oldestSlot * (1 << AttestationPool.INDEX_BITS);
|
|
414
|
+
for await (const positionKey of this.blockProposalHashesPerSlotAndIndex.keysAsync({
|
|
345
415
|
end: blockPositionEndKey
|
|
346
416
|
})){
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
417
|
+
await this.blockProposalHashesPerSlotAndIndex.delete(positionKey);
|
|
418
|
+
}
|
|
419
|
+
for await (const [key, buffer] of this.blockProposalsPerSlotIndexAndHash.entriesAsync({
|
|
420
|
+
end: `${oldestSlotPadded}-`
|
|
421
|
+
})){
|
|
422
|
+
try {
|
|
423
|
+
const proposal = BlockProposal.fromBuffer(buffer);
|
|
424
|
+
await this.blockProposalKeysPerArchive.deleteValue(proposal.archive.toString(), key);
|
|
425
|
+
} catch {
|
|
426
|
+
// ignore decode errors when cleaning up
|
|
351
427
|
}
|
|
352
|
-
await this.
|
|
428
|
+
await this.blockProposalsPerSlotIndexAndHash.delete(key);
|
|
429
|
+
numberOfBlockProposals++;
|
|
353
430
|
}
|
|
354
431
|
});
|
|
355
432
|
this.log.verbose(`Deleted old pool data`, {
|
|
@@ -362,17 +439,18 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
362
439
|
/**
|
|
363
440
|
* Attempts to add a checkpoint attestation to the pool.
|
|
364
441
|
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
* -
|
|
368
|
-
*
|
|
442
|
+
* - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
|
|
443
|
+
* exact same signed payload from the same signer returns `alreadyExists: true`.
|
|
444
|
+
* - Distinct payload hashes from the same (slot, signer) are tracked in the
|
|
445
|
+
* equivocation index. The first one's bytes are stored; later distinct hashes
|
|
446
|
+
* bump `count` so libp2p can fire its duplicate callback.
|
|
369
447
|
*
|
|
370
448
|
* @param attestation - The checkpoint attestation to add
|
|
371
|
-
* @returns Result indicating whether the attestation was added, existence info,
|
|
372
|
-
*
|
|
449
|
+
* @returns Result indicating whether the attestation was added, existence info,
|
|
450
|
+
* and number of distinct payload hashes by this signer for this slot
|
|
451
|
+
* (for equivocation detection).
|
|
373
452
|
*/ async tryAddCheckpointAttestation(attestation) {
|
|
374
453
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
375
|
-
const proposalId = attestation.archive.toString();
|
|
376
454
|
const sender = attestation.getSender();
|
|
377
455
|
if (!sender) {
|
|
378
456
|
return {
|
|
@@ -382,24 +460,24 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
382
460
|
};
|
|
383
461
|
}
|
|
384
462
|
const signerAddress = sender.toString();
|
|
463
|
+
const slotSignerKey = this.getSlotSignerKey(slotNumber, signerAddress);
|
|
464
|
+
const payloadHash = attestation.getPayloadHash();
|
|
385
465
|
return await this.store.transactionAsync(async ()=>{
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
// Get count of attestations by this signer for this slot (for duplicate detection)
|
|
389
|
-
const signerAttestationCount = await this.getSignerAttestationCountForSlot(slotNumber, signerAddress);
|
|
390
|
-
if (alreadyExists) {
|
|
466
|
+
if (await this.multimapHasValue(this.attestationHashesPerSlotAndSigner, slotSignerKey, payloadHash)) {
|
|
467
|
+
const count = await this.attestationHashesPerSlotAndSigner.getValueCountAsync(slotSignerKey);
|
|
391
468
|
return {
|
|
392
469
|
added: false,
|
|
393
470
|
alreadyExists: true,
|
|
394
|
-
count
|
|
471
|
+
count
|
|
395
472
|
};
|
|
396
473
|
}
|
|
397
|
-
|
|
474
|
+
const signerAttestationCount = await this.attestationHashesPerSlotAndSigner.getValueCountAsync(slotSignerKey);
|
|
398
475
|
if (signerAttestationCount >= MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER) {
|
|
399
476
|
this.log.debug(`Rejecting attestation: signer ${signerAddress} exceeded per-slot cap for slot ${slotNumber}`, {
|
|
400
477
|
slotNumber,
|
|
401
478
|
signerAddress,
|
|
402
|
-
|
|
479
|
+
archive: attestation.archive.toString(),
|
|
480
|
+
payloadHash,
|
|
403
481
|
signerAttestationCount
|
|
404
482
|
});
|
|
405
483
|
return {
|
|
@@ -408,18 +486,26 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
408
486
|
count: signerAttestationCount
|
|
409
487
|
};
|
|
410
488
|
}
|
|
411
|
-
//
|
|
412
|
-
await this.
|
|
413
|
-
//
|
|
414
|
-
|
|
415
|
-
await this.
|
|
489
|
+
// Track the new payload hash for equivocation detection.
|
|
490
|
+
await this.attestationHashesPerSlotAndSigner.set(slotSignerKey, payloadHash);
|
|
491
|
+
// Only the first distinct payload at (slot, signer) is stored; later
|
|
492
|
+
// equivocations are detected via the multimap but their bytes are not retained.
|
|
493
|
+
const alreadyHasStored = await this.attestationPerSlotAndSigner.hasAsync(slotSignerKey);
|
|
494
|
+
if (!alreadyHasStored) {
|
|
495
|
+
// Store the signature in canonical (v ∈ {27, 28}) form. `sender` recovered above, so the
|
|
496
|
+
// signature is non-empty and safe to normalize; this keeps a yParity-encoded (v = 0/1) variant
|
|
497
|
+
// from a malicious peer or an in-flight byte mutation out of the L1 bundle downstream.
|
|
498
|
+
await this.attestationPerSlotAndSigner.set(slotSignerKey, attestation.withNormalizedSignature().toBuffer());
|
|
499
|
+
this.metrics.trackMempoolItemAdded(slotSignerKey);
|
|
500
|
+
}
|
|
416
501
|
this.log.debug(`Added checkpoint attestation for slot ${slotNumber} from ${signerAddress}`, {
|
|
417
502
|
signature: attestation.signature.toString(),
|
|
418
503
|
slotNumber,
|
|
419
504
|
address: signerAddress,
|
|
420
|
-
|
|
505
|
+
archive: attestation.archive.toString(),
|
|
506
|
+
payloadHash,
|
|
507
|
+
stored: !alreadyHasStored
|
|
421
508
|
});
|
|
422
|
-
// Return the new count
|
|
423
509
|
return {
|
|
424
510
|
added: true,
|
|
425
511
|
alreadyExists: false,
|
|
@@ -427,10 +513,6 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
|
427
513
|
};
|
|
428
514
|
});
|
|
429
515
|
}
|
|
430
|
-
/** Gets the count of attestations by a specific signer for a given slot. */ async getSignerAttestationCountForSlot(slot, signerAddress) {
|
|
431
|
-
const slotSignerKey = this.getSlotSignerKey(slot, signerAddress);
|
|
432
|
-
return await this.checkpointAttestationsPerSlotAndSigner.getValueCountAsync(slotSignerKey);
|
|
433
|
-
}
|
|
434
516
|
}
|
|
435
517
|
/** Creates an AttestationPool backed by a temporary store for testing. */ export async function createTestAttestationPool(telemetry) {
|
|
436
518
|
const { openTmpStore } = await import('@aztec/kv-store/lmdb-v2');
|