@aztec/p2p 0.0.1-commit.f2ce05ee → 0.0.1-commit.f5a9928
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 +11 -10
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +64 -17
- package/dest/client/interface.d.ts +86 -40
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +67 -64
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +251 -251
- package/dest/config.d.ts +173 -94
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +158 -44
- 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 +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +106 -55
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +302 -195
- 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 +274 -115
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +7 -5
- package/dest/mem_pools/index.d.ts +2 -2
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.d.ts +12 -5
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +38 -17
- package/dest/mem_pools/interface.d.ts +3 -3
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +10 -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 +29 -20
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +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 +15 -5
- 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 +64 -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.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +6 -5
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +9 -8
- 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 +15 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/index.d.ts +3 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +2 -1
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +25 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +67 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +62 -16
- 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 +81 -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 +147 -19
- 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 +27 -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 +94 -32
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +62 -9
- 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 +537 -246
- 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 +4 -4
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +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/block_header_validator.d.ts +16 -3
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
- package/dest/msg_validators/tx_validator/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/double_spend_validator.d.ts +13 -3
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
- package/dest/msg_validators/tx_validator/factory.d.ts +133 -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 +20 -4
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- package/dest/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 +25 -19
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +28 -20
- package/dest/services/encoding.d.ts +24 -7
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +43 -26
- 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 +6 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +21 -0
- package/dest/services/libp2p/libp2p_service.d.ts +71 -60
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +602 -407
- 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 +31 -3
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +127 -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 +25 -18
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +23 -19
- 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 +3 -3
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +18 -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 +57 -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 +7 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +21 -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 +85 -219
- package/dest/services/service.d.ts +63 -19
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +11 -14
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +26 -33
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +37 -0
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_collection.js +127 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts +38 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_source.js +100 -0
- package/dest/services/tx_collection/index.d.ts +3 -3
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +1 -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 +45 -51
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +296 -68
- package/dest/services/tx_collection/tx_collection_sink.d.ts +19 -9
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +28 -31
- 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/config.d.ts +1 -3
- package/dest/services/tx_file_store/config.d.ts.map +1 -1
- package/dest/services/tx_file_store/config.js +0 -4
- package/dest/services/tx_file_store/tx_file_store.d.ts +4 -5
- 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 +6 -4
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +12 -8
- package/dest/test-helpers/make-test-p2p-clients.d.ts +7 -8
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +5 -3
- package/dest/test-helpers/mock-pubsub.d.ts +56 -6
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +128 -14
- 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 +49 -37
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +142 -50
- 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 +112 -49
- 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 +17 -17
- package/src/bootstrap/bootstrap.ts +17 -3
- package/src/client/factory.ts +129 -28
- package/src/client/interface.ts +88 -48
- package/src/client/p2p_client.ts +284 -317
- package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
- package/src/config.ts +280 -49
- 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 +1 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +373 -236
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +298 -119
- package/src/mem_pools/attestation_pool/index.ts +3 -3
- package/src/mem_pools/attestation_pool/mocks.ts +14 -8
- package/src/mem_pools/index.ts +1 -1
- package/src/mem_pools/instrumentation.ts +27 -17
- package/src/mem_pools/interface.ts +2 -2
- package/src/mem_pools/tx_pool_v2/README.md +85 -11
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +30 -20
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +6 -4
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +21 -6
- 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 +67 -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 +4 -6
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +8 -10
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -10
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
- package/src/mem_pools/tx_pool_v2/index.ts +2 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +96 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +63 -16
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +215 -27
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +91 -43
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +122 -33
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +602 -242
- 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 +8 -17
- 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/block_header_validator.ts +15 -3
- 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/double_spend_validator.ts +11 -6
- 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 +23 -18
- 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 +38 -46
- package/src/services/encoding.ts +42 -26
- package/src/services/gossipsub/README.md +59 -22
- package/src/services/gossipsub/topic_score_params.ts +58 -31
- package/src/services/libp2p/instrumentation.ts +22 -0
- package/src/services/libp2p/libp2p_service.ts +687 -466
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +140 -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 +45 -46
- 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 +36 -32
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +64 -20
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +23 -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 +100 -263
- package/src/services/service.ts +80 -35
- package/src/services/tx_collection/config.ts +40 -49
- package/src/services/tx_collection/file_store_tx_collection.ts +153 -0
- package/src/services/tx_collection/file_store_tx_source.ts +129 -0
- package/src/services/tx_collection/index.ts +2 -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 +362 -110
- package/src/services/tx_collection/tx_collection_sink.ts +32 -36
- package/src/services/tx_collection/tx_source.ts +29 -8
- package/src/services/tx_file_store/config.ts +0 -6
- package/src/services/tx_file_store/tx_file_store.ts +15 -25
- package/src/services/tx_provider.ts +15 -9
- package/src/test-helpers/make-test-p2p-clients.ts +7 -6
- package/src/test-helpers/mock-pubsub.ts +152 -14
- 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 +171 -68
- package/src/testbench/p2p_client_testbench_worker.ts +121 -64
- 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 -52
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/fast_tx_collection.js +0 -307
- 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 -53
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/slow_tx_collection.js +0 -177
- 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 -354
- package/src/services/tx_collection/proposal_tx_collector.ts +0 -112
- package/src/services/tx_collection/slow_tx_collection.ts +0 -233
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
1
|
+
import type { BlockProposalHash, CheckpointProposalHash, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
4
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
5
4
|
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
|
|
@@ -15,30 +14,42 @@ import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instru
|
|
|
15
14
|
|
|
16
15
|
/** Result of trying to add an item (proposal or attestation) to the pool */
|
|
17
16
|
export type TryAddResult = {
|
|
18
|
-
/** Whether the item was
|
|
17
|
+
/** Whether the item was accepted into pool state. False when it already existed, was invalid, or hit a cap. */
|
|
19
18
|
added: boolean;
|
|
20
|
-
/** Whether the exact
|
|
19
|
+
/** Whether the exact signed payload (matched by payload hash) already existed in the pool. */
|
|
21
20
|
alreadyExists: boolean;
|
|
22
|
-
/**
|
|
23
|
-
|
|
21
|
+
/** Number of distinct signed-payload hashes seen for the position. Meaning varies by method:
|
|
22
|
+
* - tryAddBlockProposal: distinct payload hashes at (slot, indexWithinCheckpoint)
|
|
23
|
+
* - tryAddCheckpointProposal: distinct payload hashes at slot
|
|
24
|
+
* - tryAddCheckpointAttestation: distinct payload hashes by this signer for this slot */
|
|
25
|
+
count: number;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
|
-
export
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
export type ProposalsForSlot = {
|
|
29
|
+
blockProposals: BlockProposal[];
|
|
30
|
+
checkpointProposals: CheckpointProposalCore[];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const MAX_CHECKPOINT_PROPOSALS_PER_SLOT = 2;
|
|
34
|
+
export const MAX_BLOCK_PROPOSALS_PER_POSITION = 2;
|
|
35
|
+
/** Maximum attestations a single signer can make per slot before being rejected. */
|
|
36
|
+
export const MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER = 2;
|
|
29
37
|
|
|
30
38
|
/** Public API interface for attestation pools. Used for typing mocks and test implementations. */
|
|
31
39
|
export type AttestationPoolApi = Pick<
|
|
32
40
|
AttestationPool,
|
|
33
41
|
| 'tryAddBlockProposal'
|
|
34
|
-
| '
|
|
42
|
+
| 'getBlockProposalByArchive'
|
|
43
|
+
| 'getProposalsForSlot'
|
|
35
44
|
| 'tryAddCheckpointProposal'
|
|
36
45
|
| 'getCheckpointProposal'
|
|
46
|
+
| 'hasCheckpointProposalForSlot'
|
|
37
47
|
| 'addOwnCheckpointAttestations'
|
|
38
48
|
| 'tryAddCheckpointAttestation'
|
|
39
49
|
| 'deleteOlderThan'
|
|
40
50
|
| 'getCheckpointAttestationsForSlot'
|
|
41
51
|
| 'getCheckpointAttestationsForSlotAndProposal'
|
|
52
|
+
| 'hasBlockProposalsForSlot'
|
|
42
53
|
| 'isEmpty'
|
|
43
54
|
>;
|
|
44
55
|
|
|
@@ -47,27 +58,45 @@ export type AttestationPoolApi = Pick<
|
|
|
47
58
|
*
|
|
48
59
|
* Attestations and proposals observed via the p2p network are stored for requests
|
|
49
60
|
* from the validator to produce a block, or to serve to other peers.
|
|
61
|
+
*
|
|
62
|
+
* Equivocation detection: distinct *signed payload hashes* arriving at the same
|
|
63
|
+
* position are tracked in the matching index multimap so the equivocation count
|
|
64
|
+
* reaches 2 even when archive collides on `feeAssetPriceModifier` variants.
|
|
65
|
+
* Proposal bytes are retained per accepted payload hash, up to the same equivocation
|
|
66
|
+
* caps, for slashing watchers that need signed P2P proposals.
|
|
50
67
|
*/
|
|
51
68
|
export class AttestationPool {
|
|
52
69
|
private metrics: PoolInstrumentation<CheckpointAttestation>;
|
|
53
70
|
|
|
54
|
-
// Checkpoint attestations from
|
|
55
|
-
//
|
|
56
|
-
|
|
71
|
+
// Checkpoint attestations from `${paddedSlot}-${signer}` to serialized CheckpointAttestation.
|
|
72
|
+
// Stores the first attestation seen per (slot, signer); subsequent distinct payload
|
|
73
|
+
// hashes from the same signer are tracked only in `attestationHashesPerSlotAndSigner`
|
|
74
|
+
// for equivocation detection.
|
|
75
|
+
private attestationPerSlotAndSigner: AztecAsyncMap<string, Buffer>;
|
|
57
76
|
|
|
58
|
-
//
|
|
59
|
-
|
|
77
|
+
// Distinct payload hashes seen per (slot, signer) for tracking attestation equivocations.
|
|
78
|
+
// Key: `${paddedSlot}-${signerAddress}`, Value: CheckpointProposalHash (`0x`-prefixed hex)
|
|
79
|
+
private attestationHashesPerSlotAndSigner: AztecAsyncMultiMap<string, CheckpointProposalHash>;
|
|
60
80
|
|
|
61
|
-
// Checkpoint proposals
|
|
62
|
-
//
|
|
63
|
-
private
|
|
81
|
+
// Checkpoint proposals from `${paddedSlot}-${payloadHash}` to serialized CheckpointProposalCore.
|
|
82
|
+
// Stores every accepted distinct payload up to MAX_CHECKPOINT_PROPOSALS_PER_SLOT.
|
|
83
|
+
private checkpointProposalsPerSlotAndHash: AztecAsyncMap<string, Buffer>;
|
|
64
84
|
|
|
65
|
-
//
|
|
66
|
-
|
|
85
|
+
// Distinct payload hashes seen per slot. Hash collision = duplicate.
|
|
86
|
+
// Hash count reaching 2 = equivocation.
|
|
87
|
+
// Key: slot number, Value: CheckpointProposalHash (`0x`-prefixed hex)
|
|
88
|
+
private checkpointProposalHashesPerSlot: AztecAsyncMultiMap<number, CheckpointProposalHash>;
|
|
67
89
|
|
|
68
|
-
// Block proposals
|
|
69
|
-
//
|
|
70
|
-
private
|
|
90
|
+
// Block proposals from `${paddedSlot}-${paddedIndex}-${payloadHash}` to serialized BlockProposal.
|
|
91
|
+
// Stores every accepted distinct payload up to MAX_BLOCK_PROPOSALS_PER_POSITION.
|
|
92
|
+
private blockProposalsPerSlotIndexAndHash: AztecAsyncMap<string, Buffer>;
|
|
93
|
+
|
|
94
|
+
// Distinct payload hashes seen per (slot, indexWithinCheckpoint).
|
|
95
|
+
// Key: slot * (1 << INDEX_BITS) + indexWithinCheckpoint, Value: BlockProposalHash (`0x`-prefixed hex)
|
|
96
|
+
private blockProposalHashesPerSlotAndIndex: AztecAsyncMultiMap<number, BlockProposalHash>;
|
|
97
|
+
|
|
98
|
+
// Secondary index from archive root to all retained block proposal keys.
|
|
99
|
+
private blockProposalKeysPerArchive: AztecAsyncMultiMap<string, string>;
|
|
71
100
|
|
|
72
101
|
constructor(
|
|
73
102
|
private store: AztecAsyncKVStore,
|
|
@@ -75,177 +104,239 @@ export class AttestationPool {
|
|
|
75
104
|
private log = createLogger('aztec:attestation_pool'),
|
|
76
105
|
) {
|
|
77
106
|
// Initialize block proposal storage
|
|
78
|
-
this.
|
|
79
|
-
this.
|
|
107
|
+
this.blockProposalsPerSlotIndexAndHash = store.openMap('block_proposals_by_slot_index_and_hash');
|
|
108
|
+
this.blockProposalHashesPerSlotAndIndex = store.openMultiMap('block_proposals_for_slot_and_index');
|
|
109
|
+
this.blockProposalKeysPerArchive = store.openMultiMap('block_proposals_by_archive');
|
|
80
110
|
|
|
81
111
|
// Initialize checkpoint attestations storage
|
|
82
|
-
this.
|
|
112
|
+
this.attestationPerSlotAndSigner = store.openMap('checkpoint_attestations');
|
|
113
|
+
this.attestationHashesPerSlotAndSigner = store.openMultiMap('checkpoint_attestations_per_slot_and_signer');
|
|
83
114
|
|
|
84
115
|
// Initialize checkpoint proposal storage
|
|
85
|
-
this.
|
|
86
|
-
this.
|
|
116
|
+
this.checkpointProposalsPerSlotAndHash = store.openMap('checkpoint_proposals_by_slot_and_hash');
|
|
117
|
+
this.checkpointProposalHashesPerSlot = store.openMultiMap('checkpoint_proposals_for_slot');
|
|
87
118
|
|
|
88
119
|
this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL, this.poolStats);
|
|
89
120
|
}
|
|
90
121
|
|
|
91
122
|
private poolStats: PoolStatsCallback = async () => {
|
|
92
123
|
return {
|
|
93
|
-
itemCount: await this.
|
|
124
|
+
itemCount: await this.attestationPerSlotAndSigner.sizeAsync(),
|
|
94
125
|
};
|
|
95
126
|
};
|
|
96
127
|
|
|
97
128
|
/** Returns whether the pool is empty. */
|
|
98
129
|
public async isEmpty(): Promise<boolean> {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return
|
|
130
|
+
const [attestationCount, blockProposalCount, checkpointProposalCount] = await Promise.all([
|
|
131
|
+
this.attestationPerSlotAndSigner.sizeAsync(),
|
|
132
|
+
this.blockProposalsPerSlotIndexAndHash.sizeAsync(),
|
|
133
|
+
this.checkpointProposalsPerSlotAndHash.sizeAsync(),
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
return attestationCount === 0 && blockProposalCount === 0 && checkpointProposalCount === 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Number of bits reserved for indexWithinCheckpoint in position keys. */
|
|
140
|
+
private static readonly INDEX_BITS = 10;
|
|
141
|
+
/** Maximum indexWithinCheckpoint value (2^10 - 1 = 1023). */
|
|
142
|
+
private static readonly MAX_INDEX = (1 << AttestationPool.INDEX_BITS) - 1;
|
|
143
|
+
/** Decimal digits used to left-pad slot numbers in string keys.
|
|
144
|
+
* 10 digits ≈ 3500 years at 36 s/slot, leaving ample headroom. */
|
|
145
|
+
private static readonly SLOT_PAD_DIGITS = 10;
|
|
146
|
+
|
|
147
|
+
/** Fixed-width decimal slot string for use in composite string keys. */
|
|
148
|
+
private slotPaddedKey(slot: SlotNumber | number): string {
|
|
149
|
+
return slot.toString().padStart(AttestationPool.SLOT_PAD_DIGITS, '0');
|
|
106
150
|
}
|
|
107
151
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
? proposalId
|
|
113
|
-
: Buffer.isBuffer(proposalId)
|
|
114
|
-
? Fr.fromBuffer(proposalId).toString()
|
|
115
|
-
: proposalId.toString();
|
|
152
|
+
/** Fixed-width decimal index string for use in composite string keys. */
|
|
153
|
+
private indexPaddedKey(indexWithinCheckpoint: number): string {
|
|
154
|
+
return indexWithinCheckpoint.toString().padStart(4, '0');
|
|
155
|
+
}
|
|
116
156
|
|
|
117
|
-
|
|
157
|
+
/** Key for retained block proposals. */
|
|
158
|
+
private getBlockProposalKey(
|
|
159
|
+
slot: SlotNumber | number,
|
|
160
|
+
indexWithinCheckpoint: number,
|
|
161
|
+
payloadHash: BlockProposalHash,
|
|
162
|
+
): string {
|
|
163
|
+
return `${this.slotPaddedKey(slot)}-${this.indexPaddedKey(indexWithinCheckpoint)}-${payloadHash}`;
|
|
118
164
|
}
|
|
119
165
|
|
|
120
|
-
|
|
121
|
-
|
|
166
|
+
/** Range bounds for all retained block proposals in a slot. */
|
|
167
|
+
private getBlockProposalKeyRangeForSlot(slot: SlotNumber): { start: string; end: string } {
|
|
168
|
+
return { start: `${this.slotPaddedKey(slot)}-`, end: `${this.slotPaddedKey(slot + 1)}-` };
|
|
122
169
|
}
|
|
123
170
|
|
|
124
|
-
/**
|
|
125
|
-
private
|
|
126
|
-
|
|
127
|
-
return { start: `${slotStr}-`, end: `${slotStr}-Z` }; // 'Z' sorts after any hex character
|
|
171
|
+
/** Key for retained checkpoint proposals. */
|
|
172
|
+
private getCheckpointProposalKey(slot: SlotNumber | number, payloadHash: CheckpointProposalHash): string {
|
|
173
|
+
return `${this.slotPaddedKey(slot)}-${payloadHash}`;
|
|
128
174
|
}
|
|
129
175
|
|
|
130
|
-
/**
|
|
131
|
-
private
|
|
132
|
-
|
|
133
|
-
return { start: `${proposalKey}-`, end: `${proposalKey}-Z` };
|
|
176
|
+
/** Range bounds for all retained checkpoint proposals in a slot. */
|
|
177
|
+
private getCheckpointProposalKeyRangeForSlot(slot: SlotNumber): { start: string; end: string } {
|
|
178
|
+
return { start: `${this.slotPaddedKey(slot)}-`, end: `${this.slotPaddedKey(slot + 1)}-` };
|
|
134
179
|
}
|
|
135
180
|
|
|
136
|
-
/**
|
|
137
|
-
private
|
|
138
|
-
|
|
139
|
-
|
|
181
|
+
/** Key for the per-(slot, signer) attestation main store and equivocation index. */
|
|
182
|
+
private getSlotSignerKey(slot: SlotNumber, signerAddress: string): string {
|
|
183
|
+
return `${this.slotPaddedKey(slot)}-${signerAddress}`;
|
|
184
|
+
}
|
|
140
185
|
|
|
141
|
-
/**
|
|
186
|
+
/**
|
|
187
|
+
* Returns range bounds for querying all attestations for a given slot.
|
|
188
|
+
* Fixed-width padding ensures the slot prefix sorts cleanly, so using the next
|
|
189
|
+
* slot's prefix as the upper bound captures exactly the current slot's entries.
|
|
190
|
+
*/
|
|
191
|
+
private getAttestationKeyRangeForSlot(slot: SlotNumber): { start: string; end: string } {
|
|
192
|
+
return { start: `${this.slotPaddedKey(slot)}-`, end: `${this.slotPaddedKey(slot + 1)}-` };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Creates a position key for block proposals: slot * 1024 + indexWithinCheckpoint.
|
|
196
|
+
* Uses multiplication instead of bit-shift to avoid 32-bit signed integer overflow
|
|
197
|
+
* (bit-shift overflows after slot ~2^21, roughly 278 days of uptime). */
|
|
142
198
|
private getBlockPositionKey(slot: number, indexWithinCheckpoint: number): number {
|
|
143
199
|
if (indexWithinCheckpoint > AttestationPool.MAX_INDEX) {
|
|
144
200
|
throw new Error(
|
|
145
201
|
`Value for indexWithinCheckpoint ${indexWithinCheckpoint} exceeds maximum ${AttestationPool.MAX_INDEX}`,
|
|
146
202
|
);
|
|
147
203
|
}
|
|
148
|
-
return
|
|
204
|
+
return slot * (1 << AttestationPool.INDEX_BITS) + indexWithinCheckpoint;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Returns true if the multimap already contains the given value for the given key. */
|
|
208
|
+
private async multimapHasValue<TKey extends number | string, TValue extends string>(
|
|
209
|
+
map: AztecAsyncMultiMap<TKey, TValue>,
|
|
210
|
+
key: TKey,
|
|
211
|
+
value: TValue,
|
|
212
|
+
): Promise<boolean> {
|
|
213
|
+
const values = await toArray(map.getValuesAsync(key));
|
|
214
|
+
return values.includes(value);
|
|
149
215
|
}
|
|
150
216
|
|
|
151
217
|
/**
|
|
152
218
|
* Attempts to add a block proposal to the pool.
|
|
153
219
|
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* -
|
|
157
|
-
*
|
|
220
|
+
* - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
|
|
221
|
+
* exact same signed payload returns `alreadyExists: true`.
|
|
222
|
+
* - Distinct payload hashes at the same `(slot, indexWithinCheckpoint)` are tracked
|
|
223
|
+
* in the equivocation index and retained up to the cap.
|
|
158
224
|
*
|
|
159
225
|
* @param blockProposal - The block proposal to add
|
|
160
226
|
* @returns Result indicating whether the proposal was added and duplicate detection info
|
|
161
227
|
*/
|
|
162
228
|
public async tryAddBlockProposal(blockProposal: BlockProposal): Promise<TryAddResult> {
|
|
163
229
|
return await this.store.transactionAsync(async () => {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
blockProposal.indexWithinCheckpoint,
|
|
172
|
-
);
|
|
173
|
-
return { added: false, alreadyExists: true, totalForPosition };
|
|
230
|
+
const positionKey = this.getBlockPositionKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
|
|
231
|
+
const payloadHash = blockProposal.getPayloadHash();
|
|
232
|
+
|
|
233
|
+
// Hash already tracked => exact same signed payload was already received.
|
|
234
|
+
if (await this.multimapHasValue(this.blockProposalHashesPerSlotAndIndex, positionKey, payloadHash)) {
|
|
235
|
+
const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
|
|
236
|
+
return { added: false, alreadyExists: true, count };
|
|
174
237
|
}
|
|
175
238
|
|
|
176
|
-
//
|
|
177
|
-
const
|
|
239
|
+
// Cap reached for this position (no more new payload hashes accepted).
|
|
240
|
+
const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
|
|
241
|
+
if (count >= MAX_BLOCK_PROPOSALS_PER_POSITION) {
|
|
242
|
+
return { added: false, alreadyExists: false, count };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Track the new payload hash for equivocation detection.
|
|
246
|
+
await this.blockProposalHashesPerSlotAndIndex.set(positionKey, payloadHash);
|
|
247
|
+
const proposalKey = this.getBlockProposalKey(
|
|
178
248
|
blockProposal.slotNumber,
|
|
179
249
|
blockProposal.indexWithinCheckpoint,
|
|
250
|
+
payloadHash,
|
|
180
251
|
);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return { added: false, alreadyExists: false, totalForPosition };
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Add the proposal
|
|
187
|
-
await this.addBlockProposal(blockProposal);
|
|
252
|
+
await this.blockProposalsPerSlotIndexAndHash.set(proposalKey, blockProposal.withoutSignedTxs().toBuffer());
|
|
253
|
+
await this.blockProposalKeysPerArchive.set(blockProposal.archive.toString(), proposalKey);
|
|
188
254
|
|
|
189
255
|
this.log.debug(
|
|
190
256
|
`Added block proposal for slot ${blockProposal.slotNumber} and index ${blockProposal.indexWithinCheckpoint}`,
|
|
191
257
|
{
|
|
192
|
-
|
|
258
|
+
archive: blockProposal.archive.toString(),
|
|
259
|
+
payloadHash,
|
|
193
260
|
slotNumber: blockProposal.slotNumber,
|
|
194
261
|
indexWithinCheckpoint: blockProposal.indexWithinCheckpoint,
|
|
195
262
|
},
|
|
196
263
|
);
|
|
197
264
|
|
|
198
|
-
return { added: true, alreadyExists: false,
|
|
265
|
+
return { added: true, alreadyExists: false, count: count + 1 };
|
|
199
266
|
});
|
|
200
267
|
}
|
|
201
268
|
|
|
202
|
-
/** Gets the count of block proposals for a given position (slot, indexWithinCheckpoint). */
|
|
203
|
-
private getBlockProposalCountForPosition(
|
|
204
|
-
slot: SlotNumber,
|
|
205
|
-
indexWithinCheckpoint: IndexWithinCheckpoint,
|
|
206
|
-
): Promise<number> {
|
|
207
|
-
const positionKey = this.getBlockPositionKey(slot, indexWithinCheckpoint);
|
|
208
|
-
return this.blockProposalsForSlotAndIndex.getValueCountAsync(positionKey);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** Internal method - must be called within a transaction. */
|
|
212
|
-
private async addBlockProposal(blockProposal: BlockProposal): Promise<void> {
|
|
213
|
-
const proposalId = blockProposal.archive.toString();
|
|
214
|
-
// Strip signedTxs before storing to avoid persisting full tx data
|
|
215
|
-
await this.blockProposals.set(proposalId, blockProposal.withoutSignedTxs().toBuffer());
|
|
216
|
-
|
|
217
|
-
// Index by slot and position for duplicate detection
|
|
218
|
-
const positionKey = this.getBlockPositionKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
|
|
219
|
-
await this.blockProposalsForSlotAndIndex.set(positionKey, proposalId);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
269
|
/**
|
|
223
|
-
* Get block proposal by
|
|
270
|
+
* Get block proposal by archive root.
|
|
224
271
|
*
|
|
225
|
-
*
|
|
272
|
+
* Resolves the archive root through the archive index and returns the first
|
|
273
|
+
* retained proposal for that archive. This lookup is used by block-txs req/resp,
|
|
274
|
+
* where any retained proposal for the requested archive gives the tx hash list.
|
|
226
275
|
*
|
|
227
|
-
* @
|
|
276
|
+
* @param archiveRoot - The archive root to look up
|
|
277
|
+
* @return The block proposal if it exists and its archive matches, otherwise undefined.
|
|
228
278
|
*/
|
|
229
|
-
public async
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
if (buffer
|
|
233
|
-
|
|
279
|
+
public async getBlockProposalByArchive(archiveRoot: string): Promise<BlockProposal | undefined> {
|
|
280
|
+
for await (const proposalKey of this.blockProposalKeysPerArchive.getValuesAsync(archiveRoot)) {
|
|
281
|
+
const buffer = await this.blockProposalsPerSlotIndexAndHash.getAsync(proposalKey);
|
|
282
|
+
if (!buffer || buffer.length === 0) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
const proposal = BlockProposal.fromBuffer(buffer);
|
|
287
|
+
if (proposal.archive.toString() === archiveRoot) {
|
|
288
|
+
return proposal;
|
|
289
|
+
}
|
|
290
|
+
} catch {
|
|
291
|
+
continue;
|
|
234
292
|
}
|
|
235
|
-
} catch {
|
|
236
|
-
return undefined;
|
|
237
293
|
}
|
|
238
|
-
|
|
239
294
|
return undefined;
|
|
240
295
|
}
|
|
241
296
|
|
|
297
|
+
/** Returns retained signed proposals for a slot. */
|
|
298
|
+
public async getProposalsForSlot(slot: SlotNumber): Promise<ProposalsForSlot> {
|
|
299
|
+
const blockProposals: BlockProposal[] = [];
|
|
300
|
+
const checkpointProposals: CheckpointProposalCore[] = [];
|
|
301
|
+
|
|
302
|
+
for await (const [_, buffer] of this.blockProposalsPerSlotIndexAndHash.entriesAsync(
|
|
303
|
+
this.getBlockProposalKeyRangeForSlot(slot),
|
|
304
|
+
)) {
|
|
305
|
+
try {
|
|
306
|
+
blockProposals.push(BlockProposal.fromBuffer(buffer));
|
|
307
|
+
} catch {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
for await (const [_, buffer] of this.checkpointProposalsPerSlotAndHash.entriesAsync(
|
|
313
|
+
this.getCheckpointProposalKeyRangeForSlot(slot),
|
|
314
|
+
)) {
|
|
315
|
+
try {
|
|
316
|
+
checkpointProposals.push(CheckpointProposal.fromBuffer(buffer));
|
|
317
|
+
} catch {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return { blockProposals, checkpointProposals };
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** Checks if any block proposals exist for a given slot (at index 0). */
|
|
326
|
+
public async hasBlockProposalsForSlot(slot: SlotNumber): Promise<boolean> {
|
|
327
|
+
const positionKey = this.getBlockPositionKey(slot, 0);
|
|
328
|
+
const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
|
|
329
|
+
return count > 0;
|
|
330
|
+
}
|
|
331
|
+
|
|
242
332
|
/**
|
|
243
333
|
* Attempts to add a checkpoint proposal to the pool.
|
|
244
334
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* -
|
|
248
|
-
*
|
|
335
|
+
* - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
|
|
336
|
+
* exact same signed payload returns `alreadyExists: true`.
|
|
337
|
+
* - Distinct payload hashes at the same slot are tracked in the equivocation index.
|
|
338
|
+
* Distinct payload bytes are retained up to the same cap so slashing watchers
|
|
339
|
+
* can recover signed proposals.
|
|
249
340
|
*
|
|
250
341
|
* Note: This method only handles the CheckpointProposalCore. If the original
|
|
251
342
|
* CheckpointProposal contains a lastBlock, the caller should extract it via
|
|
@@ -256,73 +347,77 @@ export class AttestationPool {
|
|
|
256
347
|
*/
|
|
257
348
|
public async tryAddCheckpointProposal(proposal: CheckpointProposalCore): Promise<TryAddResult> {
|
|
258
349
|
return await this.store.transactionAsync(async () => {
|
|
259
|
-
const
|
|
350
|
+
const slot = proposal.slotNumber;
|
|
351
|
+
const payloadHash = proposal.getPayloadHash();
|
|
260
352
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const totalForPosition = await this.checkpointProposalsForSlot.getValueCountAsync(proposal.slotNumber);
|
|
265
|
-
return { added: false, alreadyExists: true, totalForPosition };
|
|
353
|
+
if (await this.multimapHasValue(this.checkpointProposalHashesPerSlot, slot, payloadHash)) {
|
|
354
|
+
const count = await this.checkpointProposalHashesPerSlot.getValueCountAsync(slot);
|
|
355
|
+
return { added: false, alreadyExists: true, count };
|
|
266
356
|
}
|
|
267
357
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return { added: false, alreadyExists: false, totalForPosition };
|
|
358
|
+
const count = await this.checkpointProposalHashesPerSlot.getValueCountAsync(slot);
|
|
359
|
+
if (count >= MAX_CHECKPOINT_PROPOSALS_PER_SLOT) {
|
|
360
|
+
return { added: false, alreadyExists: false, count };
|
|
272
361
|
}
|
|
273
362
|
|
|
274
|
-
//
|
|
275
|
-
await this.
|
|
363
|
+
// Track the new payload hash for equivocation detection.
|
|
364
|
+
await this.checkpointProposalHashesPerSlot.set(slot, payloadHash);
|
|
365
|
+
await this.checkpointProposalsPerSlotAndHash.set(
|
|
366
|
+
this.getCheckpointProposalKey(slot, payloadHash),
|
|
367
|
+
proposal.toBuffer(),
|
|
368
|
+
);
|
|
276
369
|
|
|
277
|
-
this.log.debug(`Added checkpoint proposal for slot ${
|
|
278
|
-
|
|
279
|
-
|
|
370
|
+
this.log.debug(`Added checkpoint proposal for slot ${slot}`, {
|
|
371
|
+
archive: proposal.archive.toString(),
|
|
372
|
+
payloadHash,
|
|
373
|
+
slotNumber: slot,
|
|
280
374
|
});
|
|
281
375
|
|
|
282
|
-
return { added: true, alreadyExists: false,
|
|
376
|
+
return { added: true, alreadyExists: false, count: count + 1 };
|
|
283
377
|
});
|
|
284
378
|
}
|
|
285
379
|
|
|
286
|
-
/** Internal method - must be called within a transaction. */
|
|
287
|
-
private async addCheckpointProposal(proposal: CheckpointProposalCore): Promise<void> {
|
|
288
|
-
const slotKey = proposal.slotNumber;
|
|
289
|
-
const proposalId = proposal.archive.toString();
|
|
290
|
-
|
|
291
|
-
await this.checkpointProposalsForSlot.set(slotKey, proposalId);
|
|
292
|
-
await this.checkpointProposals.set(proposalId, proposal.toBuffer());
|
|
293
|
-
}
|
|
294
|
-
|
|
295
380
|
/**
|
|
296
|
-
* Get checkpoint proposal
|
|
381
|
+
* Get a retained checkpoint proposal stored for the given slot.
|
|
382
|
+
* If multiple proposals were retained for an equivocation, returns the lowest
|
|
383
|
+
* payload hash deterministically.
|
|
297
384
|
*
|
|
298
385
|
* Returns a CheckpointProposalCore (without lastBlock info) since the lastBlock
|
|
299
386
|
* is extracted and stored separately as a BlockProposal when added.
|
|
300
387
|
*
|
|
301
|
-
* @param
|
|
302
|
-
* @return The checkpoint proposal core if
|
|
388
|
+
* @param slot - The slot to look up
|
|
389
|
+
* @return The checkpoint proposal core if one is stored, otherwise undefined.
|
|
303
390
|
*/
|
|
304
|
-
public async getCheckpointProposal(
|
|
305
|
-
const buffer
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
391
|
+
public async getCheckpointProposal(slot: SlotNumber): Promise<CheckpointProposalCore | undefined> {
|
|
392
|
+
for await (const [_, buffer] of this.checkpointProposalsPerSlotAndHash.entriesAsync(
|
|
393
|
+
this.getCheckpointProposalKeyRangeForSlot(slot),
|
|
394
|
+
)) {
|
|
395
|
+
try {
|
|
396
|
+
if (buffer && buffer.length > 0) {
|
|
397
|
+
return CheckpointProposal.fromBuffer(buffer);
|
|
398
|
+
}
|
|
399
|
+
} catch {
|
|
400
|
+
continue;
|
|
309
401
|
}
|
|
310
|
-
} catch {
|
|
311
|
-
return undefined;
|
|
312
402
|
}
|
|
313
403
|
|
|
314
404
|
return undefined;
|
|
315
405
|
}
|
|
316
406
|
|
|
407
|
+
/** Returns whether any checkpoint proposal is retained for the given slot. */
|
|
408
|
+
public async hasCheckpointProposalForSlot(slot: SlotNumber): Promise<boolean> {
|
|
409
|
+
return (await this.getCheckpointProposal(slot)) !== undefined;
|
|
410
|
+
}
|
|
411
|
+
|
|
317
412
|
/**
|
|
318
413
|
* Adds own checkpoint attestations to the pool.
|
|
319
|
-
* Skips
|
|
414
|
+
* Skips per-signer cap and equivocation tracking; the caller is trusted.
|
|
415
|
+
* Each (slot, signer) gets a single stored attestation; later additions overwrite.
|
|
320
416
|
*/
|
|
321
417
|
public async addOwnCheckpointAttestations(attestations: CheckpointAttestation[]): Promise<void> {
|
|
322
418
|
await this.store.transactionAsync(async () => {
|
|
323
419
|
for (const attestation of attestations) {
|
|
324
420
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
325
|
-
const proposalId = attestation.archive;
|
|
326
421
|
const sender = attestation.getSender();
|
|
327
422
|
|
|
328
423
|
// Skip attestations with invalid signatures
|
|
@@ -330,23 +425,31 @@ export class AttestationPool {
|
|
|
330
425
|
this.log.warn(`Skipping own checkpoint attestation with invalid signature for slot ${slotNumber}`, {
|
|
331
426
|
signature: attestation.signature.toString(),
|
|
332
427
|
slotNumber,
|
|
333
|
-
|
|
428
|
+
archive: attestation.archive.toString(),
|
|
334
429
|
});
|
|
335
430
|
continue;
|
|
336
431
|
}
|
|
337
432
|
|
|
338
433
|
const address = sender.toString();
|
|
434
|
+
const ownKey = this.getSlotSignerKey(slotNumber, address);
|
|
435
|
+
const payloadHash = attestation.getPayloadHash();
|
|
339
436
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
437
|
+
// Store the signature in canonical (v ∈ {27, 28}) form; see tryAddCheckpointAttestation.
|
|
438
|
+
await this.attestationPerSlotAndSigner.set(ownKey, attestation.withNormalizedSignature().toBuffer());
|
|
439
|
+
this.metrics.trackMempoolItemAdded(ownKey);
|
|
440
|
+
|
|
441
|
+
// Track our own payload hash so that an equivocating attestation from another
|
|
442
|
+
// peer at the same (slot, signer) is detected as a duplicate.
|
|
443
|
+
if (!(await this.multimapHasValue(this.attestationHashesPerSlotAndSigner, ownKey, payloadHash))) {
|
|
444
|
+
await this.attestationHashesPerSlotAndSigner.set(ownKey, payloadHash);
|
|
445
|
+
}
|
|
344
446
|
|
|
345
447
|
this.log.debug(`Added own checkpoint attestation for slot ${slotNumber} from ${address}`, {
|
|
346
448
|
signature: attestation.signature.toString(),
|
|
347
449
|
slotNumber,
|
|
348
450
|
address,
|
|
349
|
-
|
|
451
|
+
archive: attestation.archive.toString(),
|
|
452
|
+
payloadHash,
|
|
350
453
|
});
|
|
351
454
|
}
|
|
352
455
|
});
|
|
@@ -355,6 +458,10 @@ export class AttestationPool {
|
|
|
355
458
|
/**
|
|
356
459
|
* Get all checkpoint attestations for a given slot.
|
|
357
460
|
*
|
|
461
|
+
* Returns one attestation per (slot, signer) — the first seen for each signer.
|
|
462
|
+
* Later equivocating attestations from the same signer are tracked in the index
|
|
463
|
+
* but their bytes are not retained.
|
|
464
|
+
*
|
|
358
465
|
* @param slot - The slot to query
|
|
359
466
|
* @return CheckpointAttestations
|
|
360
467
|
*/
|
|
@@ -362,7 +469,7 @@ export class AttestationPool {
|
|
|
362
469
|
const range = this.getAttestationKeyRangeForSlot(slot);
|
|
363
470
|
const attestations: CheckpointAttestation[] = [];
|
|
364
471
|
|
|
365
|
-
for await (const [_, buf] of this.
|
|
472
|
+
for await (const [_, buf] of this.attestationPerSlotAndSigner.entriesAsync(range)) {
|
|
366
473
|
attestations.push(CheckpointAttestation.fromBuffer(buf));
|
|
367
474
|
}
|
|
368
475
|
|
|
@@ -370,24 +477,19 @@ export class AttestationPool {
|
|
|
370
477
|
}
|
|
371
478
|
|
|
372
479
|
/**
|
|
373
|
-
* Get checkpoint attestations for slot
|
|
480
|
+
* Get checkpoint attestations for a slot whose signed payload matches the given
|
|
481
|
+
* proposal payload hash.
|
|
374
482
|
*
|
|
375
483
|
* @param slot - The slot to query
|
|
376
|
-
* @param
|
|
377
|
-
* @return CheckpointAttestations
|
|
484
|
+
* @param proposalPayloadHash - Hex-encoded keccak256 of the target proposal's signed payload
|
|
485
|
+
* @return CheckpointAttestations whose `getPayloadHash()` matches `proposalPayloadHash`
|
|
378
486
|
*/
|
|
379
487
|
public async getCheckpointAttestationsForSlotAndProposal(
|
|
380
488
|
slot: SlotNumber,
|
|
381
|
-
|
|
489
|
+
proposalPayloadHash: CheckpointProposalHash,
|
|
382
490
|
): Promise<CheckpointAttestation[]> {
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
for await (const [_, buf] of this.checkpointAttestations.entriesAsync(range)) {
|
|
387
|
-
attestations.push(CheckpointAttestation.fromBuffer(buf));
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return attestations;
|
|
491
|
+
const all = await this.getCheckpointAttestationsForSlot(slot);
|
|
492
|
+
return all.filter(att => att.getPayloadHash() === proposalPayloadHash);
|
|
391
493
|
}
|
|
392
494
|
|
|
393
495
|
/**
|
|
@@ -401,34 +503,51 @@ export class AttestationPool {
|
|
|
401
503
|
let numberOfBlockProposals = 0;
|
|
402
504
|
|
|
403
505
|
await this.store.transactionAsync(async () => {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
506
|
+
const oldestSlotPadded = this.slotPaddedKey(oldestSlot);
|
|
507
|
+
|
|
508
|
+
// Delete checkpoint attestations whose key < `${oldestSlotPadded}-`. Fixed-width
|
|
509
|
+
// decimal padding means the slot prefix sorts strictly before any key at that slot.
|
|
510
|
+
for await (const key of this.attestationPerSlotAndSigner.keysAsync({ end: `${oldestSlotPadded}-` })) {
|
|
511
|
+
await this.attestationPerSlotAndSigner.delete(key);
|
|
512
|
+
this.metrics.trackMempoolItemRemoved(key);
|
|
409
513
|
numberOfAttestations++;
|
|
410
514
|
}
|
|
411
515
|
|
|
412
|
-
//
|
|
413
|
-
for await (const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
await this.
|
|
516
|
+
// Clean up per-signer-per-slot index using the same end bound.
|
|
517
|
+
for await (const key of this.attestationHashesPerSlotAndSigner.keysAsync({ end: `${oldestSlotPadded}-` })) {
|
|
518
|
+
await this.attestationHashesPerSlotAndSigner.delete(key);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Delete checkpoint proposals for slots < oldestSlot.
|
|
522
|
+
for await (const slot of this.checkpointProposalHashesPerSlot.keysAsync({ end: oldestSlot })) {
|
|
523
|
+
await this.checkpointProposalHashesPerSlot.delete(slot);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
for await (const key of this.checkpointProposalsPerSlotAndHash.keysAsync({
|
|
527
|
+
end: `${oldestSlotPadded}-`,
|
|
528
|
+
})) {
|
|
529
|
+
await this.checkpointProposalsPerSlotAndHash.delete(key);
|
|
530
|
+
numberOfCheckpointProposals++;
|
|
420
531
|
}
|
|
421
532
|
|
|
422
|
-
// Delete block proposals for slots < oldestSlot, using
|
|
423
|
-
// Key format:
|
|
424
|
-
const blockPositionEndKey = oldestSlot << AttestationPool.INDEX_BITS;
|
|
425
|
-
for await (const positionKey of this.
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
533
|
+
// Delete block proposals for slots < oldestSlot, using blockProposalHashesPerSlotAndIndex as index.
|
|
534
|
+
// Key format: slot * (1 << INDEX_BITS) + indexWithinCheckpoint
|
|
535
|
+
const blockPositionEndKey = oldestSlot * (1 << AttestationPool.INDEX_BITS);
|
|
536
|
+
for await (const positionKey of this.blockProposalHashesPerSlotAndIndex.keysAsync({ end: blockPositionEndKey })) {
|
|
537
|
+
await this.blockProposalHashesPerSlotAndIndex.delete(positionKey);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
for await (const [key, buffer] of this.blockProposalsPerSlotIndexAndHash.entriesAsync({
|
|
541
|
+
end: `${oldestSlotPadded}-`,
|
|
542
|
+
})) {
|
|
543
|
+
try {
|
|
544
|
+
const proposal = BlockProposal.fromBuffer(buffer);
|
|
545
|
+
await this.blockProposalKeysPerArchive.deleteValue(proposal.archive.toString(), key);
|
|
546
|
+
} catch {
|
|
547
|
+
// ignore decode errors when cleaning up
|
|
430
548
|
}
|
|
431
|
-
await this.
|
|
549
|
+
await this.blockProposalsPerSlotIndexAndHash.delete(key);
|
|
550
|
+
numberOfBlockProposals++;
|
|
432
551
|
}
|
|
433
552
|
});
|
|
434
553
|
|
|
@@ -443,63 +562,81 @@ export class AttestationPool {
|
|
|
443
562
|
/**
|
|
444
563
|
* Attempts to add a checkpoint attestation to the pool.
|
|
445
564
|
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
* -
|
|
449
|
-
*
|
|
565
|
+
* - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
|
|
566
|
+
* exact same signed payload from the same signer returns `alreadyExists: true`.
|
|
567
|
+
* - Distinct payload hashes from the same (slot, signer) are tracked in the
|
|
568
|
+
* equivocation index. The first one's bytes are stored; later distinct hashes
|
|
569
|
+
* bump `count` so libp2p can fire its duplicate callback.
|
|
450
570
|
*
|
|
451
571
|
* @param attestation - The checkpoint attestation to add
|
|
452
|
-
* @
|
|
453
|
-
*
|
|
572
|
+
* @returns Result indicating whether the attestation was added, existence info,
|
|
573
|
+
* and number of distinct payload hashes by this signer for this slot
|
|
574
|
+
* (for equivocation detection).
|
|
454
575
|
*/
|
|
455
|
-
public async tryAddCheckpointAttestation(
|
|
456
|
-
attestation: CheckpointAttestation,
|
|
457
|
-
committeeSize: number,
|
|
458
|
-
): Promise<TryAddResult> {
|
|
576
|
+
public async tryAddCheckpointAttestation(attestation: CheckpointAttestation): Promise<TryAddResult> {
|
|
459
577
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
460
|
-
const proposalId = attestation.archive.toString();
|
|
461
578
|
const sender = attestation.getSender();
|
|
462
579
|
|
|
463
580
|
if (!sender) {
|
|
464
|
-
return { added: false, alreadyExists: false,
|
|
581
|
+
return { added: false, alreadyExists: false, count: 0 };
|
|
465
582
|
}
|
|
466
583
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
584
|
+
const signerAddress = sender.toString();
|
|
585
|
+
const slotSignerKey = this.getSlotSignerKey(slotNumber, signerAddress);
|
|
586
|
+
const payloadHash = attestation.getPayloadHash();
|
|
470
587
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
588
|
+
return await this.store.transactionAsync(async () => {
|
|
589
|
+
if (await this.multimapHasValue(this.attestationHashesPerSlotAndSigner, slotSignerKey, payloadHash)) {
|
|
590
|
+
const count = await this.attestationHashesPerSlotAndSigner.getValueCountAsync(slotSignerKey);
|
|
591
|
+
return { added: false, alreadyExists: true, count };
|
|
474
592
|
}
|
|
475
593
|
|
|
476
|
-
const
|
|
477
|
-
const currentCount = await this.getAttestationCount(slotNumber, proposalId);
|
|
594
|
+
const signerAttestationCount = await this.attestationHashesPerSlotAndSigner.getValueCountAsync(slotSignerKey);
|
|
478
595
|
|
|
479
|
-
if (
|
|
480
|
-
|
|
596
|
+
if (signerAttestationCount >= MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER) {
|
|
597
|
+
this.log.debug(`Rejecting attestation: signer ${signerAddress} exceeded per-slot cap for slot ${slotNumber}`, {
|
|
598
|
+
slotNumber,
|
|
599
|
+
signerAddress,
|
|
600
|
+
archive: attestation.archive.toString(),
|
|
601
|
+
payloadHash,
|
|
602
|
+
signerAttestationCount,
|
|
603
|
+
});
|
|
604
|
+
return {
|
|
605
|
+
added: false,
|
|
606
|
+
alreadyExists: false,
|
|
607
|
+
count: signerAttestationCount,
|
|
608
|
+
};
|
|
481
609
|
}
|
|
482
610
|
|
|
483
|
-
|
|
611
|
+
// Track the new payload hash for equivocation detection.
|
|
612
|
+
await this.attestationHashesPerSlotAndSigner.set(slotSignerKey, payloadHash);
|
|
613
|
+
|
|
614
|
+
// Only the first distinct payload at (slot, signer) is stored; later
|
|
615
|
+
// equivocations are detected via the multimap but their bytes are not retained.
|
|
616
|
+
const alreadyHasStored = await this.attestationPerSlotAndSigner.hasAsync(slotSignerKey);
|
|
617
|
+
if (!alreadyHasStored) {
|
|
618
|
+
// Store the signature in canonical (v ∈ {27, 28}) form. `sender` recovered above, so the
|
|
619
|
+
// signature is non-empty and safe to normalize; this keeps a yParity-encoded (v = 0/1) variant
|
|
620
|
+
// from a malicious peer or an in-flight byte mutation out of the L1 bundle downstream.
|
|
621
|
+
await this.attestationPerSlotAndSigner.set(slotSignerKey, attestation.withNormalizedSignature().toBuffer());
|
|
622
|
+
this.metrics.trackMempoolItemAdded(slotSignerKey);
|
|
623
|
+
}
|
|
484
624
|
|
|
485
|
-
this.log.debug(`Added checkpoint attestation for slot ${slotNumber} from ${
|
|
625
|
+
this.log.debug(`Added checkpoint attestation for slot ${slotNumber} from ${signerAddress}`, {
|
|
486
626
|
signature: attestation.signature.toString(),
|
|
487
627
|
slotNumber,
|
|
488
|
-
address:
|
|
489
|
-
|
|
628
|
+
address: signerAddress,
|
|
629
|
+
archive: attestation.archive.toString(),
|
|
630
|
+
payloadHash,
|
|
631
|
+
stored: !alreadyHasStored,
|
|
490
632
|
});
|
|
491
|
-
return { added: true, alreadyExists: false, totalForPosition: currentCount + 1 };
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
633
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
}
|
|
502
|
-
return count;
|
|
634
|
+
return {
|
|
635
|
+
added: true,
|
|
636
|
+
alreadyExists: false,
|
|
637
|
+
count: signerAttestationCount + 1,
|
|
638
|
+
};
|
|
639
|
+
});
|
|
503
640
|
}
|
|
504
641
|
}
|
|
505
642
|
|