@aztec/p2p 0.0.1-commit.96bb3f7 → 0.0.1-commit.993d240
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 +129 -3
- package/dest/bootstrap/bootstrap.d.ts +4 -3
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +13 -5
- package/dest/client/factory.d.ts +13 -12
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +65 -20
- package/dest/client/interface.d.ts +58 -36
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +52 -58
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +236 -236
- package/dest/config.d.ts +163 -84
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +156 -43
- 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 +1 -20
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +0 -21
- 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 +162 -106
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +511 -3
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
- 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 +525 -132
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts +4 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +13 -8
- package/dest/mem_pools/index.d.ts +3 -3
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/index.js +1 -1
- package/dest/mem_pools/instrumentation.d.ts +4 -2
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +35 -17
- package/dest/mem_pools/interface.d.ts +5 -5
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
- package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +43 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +103 -0
- 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 +47 -0
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +128 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +94 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +97 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +11 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +12 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +180 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +25 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/{tx_pool → tx_pool_v2}/eviction/invalid_txs_after_mining_rule.js +16 -35
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +93 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +78 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +20 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +75 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts +6 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/index.js +5 -0
- 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 +218 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.js +10 -0
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +137 -0
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +223 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts +26 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.js +70 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +108 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +337 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +62 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +167 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +78 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +914 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -4
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +69 -13
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +9 -5
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +22 -11
- package/dest/msg_validators/clock_tolerance.d.ts +32 -0
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
- package/dest/msg_validators/clock_tolerance.js +95 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +10 -4
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +10 -4
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +21 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +123 -53
- 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.d.ts +3 -3
- package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +20 -6
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +4 -3
- 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 +4 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +40 -3
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +15 -4
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +7 -6
- package/dest/msg_validators/tx_validator/factory.d.ts +138 -5
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +259 -58
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +24 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +100 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +146 -67
- package/dest/msg_validators/tx_validator/index.d.ts +6 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +5 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +6 -6
- 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 +24 -3
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +75 -27
- package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
- package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/size_validator.js +23 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +22 -5
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +8 -8
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +4 -2
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +4 -2
- 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 +69 -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 +14 -10
- package/dest/services/discv5/discV5_service.d.ts +2 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +36 -9
- package/dest/services/dummy_service.d.ts +33 -17
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +56 -15
- package/dest/services/encoding.d.ts +7 -3
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +20 -14
- package/dest/services/gossipsub/index.d.ts +3 -0
- package/dest/services/gossipsub/index.d.ts.map +1 -0
- package/dest/services/gossipsub/index.js +2 -0
- package/dest/services/gossipsub/scoring.d.ts +21 -3
- package/dest/services/gossipsub/scoring.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.js +24 -7
- package/dest/services/gossipsub/topic_score_params.d.ts +184 -0
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
- package/dest/services/gossipsub/topic_score_params.js +363 -0
- package/dest/services/index.d.ts +2 -1
- package/dest/services/index.d.ts.map +1 -1
- package/dest/services/index.js +1 -0
- 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 +33 -8
- package/dest/services/libp2p/libp2p_service.d.ts +107 -59
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +683 -539
- package/dest/services/peer-manager/metrics.d.ts +4 -2
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +26 -5
- package/dest/services/peer-manager/peer_manager.d.ts +6 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +40 -11
- package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +65 -14
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +51 -0
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +552 -0
- package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
- package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +35 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +136 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +62 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +176 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +11 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +7 -0
- package/dest/services/reqresp/config.d.ts +3 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +2 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +12 -0
- package/dest/services/reqresp/constants.d.ts +12 -0
- package/dest/services/reqresp/constants.d.ts.map +1 -0
- package/dest/services/reqresp/constants.js +7 -0
- package/dest/services/reqresp/interface.d.ts +27 -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 +6 -5
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +16 -5
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +5 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +12 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +7 -5
- 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 +29 -9
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +29 -6
- 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 +59 -13
- 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/status.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +2 -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 +0 -10
- package/dest/services/reqresp/reqresp.d.ts +12 -29
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +58 -187
- package/dest/services/service.d.ts +49 -13
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +11 -11
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +27 -26
- 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 -2
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +1 -0
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +8 -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 +50 -56
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +298 -70
- 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 +26 -7
- package/dest/services/tx_file_store/config.d.ts +16 -0
- package/dest/services/tx_file_store/config.d.ts.map +1 -0
- package/dest/services/tx_file_store/config.js +22 -0
- package/dest/services/tx_file_store/index.d.ts +4 -0
- package/dest/services/tx_file_store/index.d.ts.map +1 -0
- package/dest/services/tx_file_store/index.js +3 -0
- package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
- package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
- package/dest/services/tx_file_store/instrumentation.js +29 -0
- package/dest/services/tx_file_store/tx_file_store.d.ts +46 -0
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
- package/dest/services/tx_file_store/tx_file_store.js +142 -0
- package/dest/services/tx_provider.d.ts +8 -6
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +12 -8
- package/dest/services/tx_provider_instrumentation.d.ts +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.js +5 -5
- package/dest/test-helpers/index.d.ts +3 -1
- package/dest/test-helpers/index.d.ts.map +1 -1
- package/dest/test-helpers/index.js +2 -0
- 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 +46 -6
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +115 -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 +19 -20
- package/dest/test-helpers/test_tx_provider.d.ts +42 -0
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
- package/dest/test-helpers/test_tx_provider.js +44 -0
- package/dest/test-helpers/testbench-utils.d.ts +161 -0
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
- package/dest/test-helpers/testbench-utils.js +393 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +26 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +270 -144
- package/dest/testbench/worker_client_manager.d.ts +57 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +277 -49
- 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 -16
- package/src/bootstrap/bootstrap.ts +16 -5
- package/src/client/factory.ts +135 -39
- package/src/client/interface.ts +70 -44
- package/src/client/p2p_client.ts +283 -302
- package/src/client/test/p2p_client.batch_tx_requester.bench.README.md +197 -0
- package/src/config.ts +274 -48
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/errors/reqresp.error.ts +0 -25
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +1 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +575 -94
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +633 -149
- package/src/mem_pools/attestation_pool/index.ts +9 -2
- package/src/mem_pools/attestation_pool/mocks.ts +19 -11
- package/src/mem_pools/index.ts +2 -2
- package/src/mem_pools/instrumentation.ts +24 -15
- package/src/mem_pools/interface.ts +4 -4
- package/src/mem_pools/tx_pool_v2/README.md +283 -0
- package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +120 -0
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +160 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +122 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +125 -0
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +28 -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 +219 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +91 -0
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +99 -0
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +32 -0
- package/src/mem_pools/tx_pool_v2/index.ts +12 -0
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +250 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +349 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +430 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +238 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1090 -0
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +60 -16
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +29 -16
- package/src/msg_validators/clock_tolerance.ts +127 -0
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +24 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +35 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +129 -62
- package/src/msg_validators/tx_validator/README.md +127 -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 +2 -2
- package/src/msg_validators/tx_validator/block_header_validator.ts +21 -8
- 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 +50 -3
- package/src/msg_validators/tx_validator/double_spend_validator.ts +15 -9
- package/src/msg_validators/tx_validator/factory.ts +424 -56
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +44 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +211 -77
- package/src/msg_validators/tx_validator/index.ts +5 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +18 -7
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +87 -30
- package/src/msg_validators/tx_validator/size_validator.ts +22 -0
- package/src/msg_validators/tx_validator/timestamp_validator.ts +29 -21
- package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +10 -3
- package/src/msg_validators/tx_validator/tx_validation_cache.ts +102 -0
- package/src/services/data_store.ts +14 -19
- package/src/services/discv5/discV5_service.ts +39 -6
- package/src/services/dummy_service.ts +71 -39
- package/src/services/encoding.ts +20 -13
- package/src/services/gossipsub/README.md +641 -0
- package/src/services/gossipsub/index.ts +2 -0
- package/src/services/gossipsub/scoring.ts +29 -5
- package/src/services/gossipsub/topic_score_params.ts +519 -0
- package/src/services/index.ts +1 -0
- package/src/services/libp2p/instrumentation.ts +34 -7
- package/src/services/libp2p/libp2p_service.ts +753 -597
- package/src/services/peer-manager/metrics.ts +28 -4
- package/src/services/peer-manager/peer_manager.ts +46 -11
- package/src/services/peer-manager/peer_scoring.ts +56 -6
- package/src/services/reqresp/README.md +215 -0
- package/src/services/reqresp/batch-tx-requester/README.md +344 -0
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +684 -0
- package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
- package/src/services/reqresp/batch-tx-requester/interface.ts +61 -0
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +168 -0
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +249 -0
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +24 -0
- package/src/services/reqresp/config.ts +2 -2
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +16 -0
- package/src/services/reqresp/constants.ts +14 -0
- package/src/services/reqresp/interface.ts +48 -46
- package/src/services/reqresp/metrics.ts +33 -9
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +16 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +37 -12
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +74 -9
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/status.ts +5 -3
- 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 +0 -10
- package/src/services/reqresp/reqresp.ts +68 -224
- package/src/services/service.ts +66 -29
- package/src/services/tx_collection/config.ts +41 -36
- 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 -1
- package/src/services/tx_collection/instrumentation.ts +11 -2
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/tx_collection.ts +367 -115
- package/src/services/tx_collection/tx_collection_sink.ts +32 -36
- package/src/services/tx_collection/tx_source.ts +28 -8
- package/src/services/tx_file_store/config.ts +37 -0
- package/src/services/tx_file_store/index.ts +3 -0
- package/src/services/tx_file_store/instrumentation.ts +36 -0
- package/src/services/tx_file_store/tx_file_store.ts +163 -0
- package/src/services/tx_provider.ts +17 -11
- package/src/services/tx_provider_instrumentation.ts +11 -5
- package/src/test-helpers/index.ts +2 -0
- package/src/test-helpers/make-test-p2p-clients.ts +7 -6
- package/src/test-helpers/mock-pubsub.ts +137 -14
- package/src/test-helpers/reqresp-nodes.ts +17 -29
- package/src/test-helpers/test_tx_provider.ts +69 -0
- package/src/test-helpers/testbench-utils.ts +455 -0
- package/src/testbench/p2p_client_testbench_worker.ts +370 -138
- package/src/testbench/worker_client_manager.ts +355 -51
- package/src/util.ts +40 -19
- package/src/versioning.ts +3 -33
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -40
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -218
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -31
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -180
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -120
- 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 -555
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -18
- 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 -56
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -83
- 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 -5
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +0 -15
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +0 -88
- 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_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 -76
- 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/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/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 -183
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -45
- 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 -92
- 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 -51
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/fast_tx_collection.js +0 -300
- 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/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -320
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -264
- package/src/mem_pools/tx_pool/README.md +0 -255
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -691
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -71
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -93
- package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +0 -108
- 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 -91
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
- 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/proposal_validator/proposal_validator_test_suite.ts +0 -206
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -100
- package/src/services/reqresp/protocols/block.ts +0 -37
- package/src/services/tx_collection/fast_tx_collection.ts +0 -341
- package/src/services/tx_collection/slow_tx_collection.ts +0 -233
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
|
+
import { IndexWithinCheckpoint, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { Secp256k1Signer } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
|
-
import type { BlockProposal, CheckpointAttestation,
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import type { BlockProposal, CheckpointAttestation, CheckpointProposalCore } from '@aztec/stdlib/p2p';
|
|
5
|
+
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
6
|
+
import {
|
|
7
|
+
makeBlockHeader,
|
|
8
|
+
makeBlockProposal,
|
|
9
|
+
makeCheckpointHeader,
|
|
10
|
+
makeCheckpointProposal,
|
|
11
|
+
} from '@aztec/stdlib/testing';
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
type AttestationPool,
|
|
15
|
+
MAX_BLOCK_PROPOSALS_PER_POSITION,
|
|
16
|
+
MAX_CHECKPOINT_PROPOSALS_PER_SLOT,
|
|
17
|
+
} from './attestation_pool.js';
|
|
9
18
|
import { mockCheckpointAttestation } from './mocks.js';
|
|
10
19
|
|
|
11
20
|
const NUMBER_OF_SIGNERS_PER_TEST = 4;
|
|
@@ -19,9 +28,16 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
19
28
|
signers = Array.from({ length: NUMBER_OF_SIGNERS_PER_TEST }, () => Secp256k1Signer.random());
|
|
20
29
|
});
|
|
21
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Build attestations from each signer over the *same* signed payload (same header,
|
|
33
|
+
* archive, feeAssetPriceModifier). Required by the new pool, which deduplicates by
|
|
34
|
+
* payload hash and treats attestations from different signers as distinct entries
|
|
35
|
+
* only when the payload itself matches.
|
|
36
|
+
*/
|
|
22
37
|
const createCheckpointAttestationsForSlot = (slotNumber: number, archive?: Fr) => {
|
|
23
38
|
const archiveToUse = archive ?? Fr.random();
|
|
24
|
-
|
|
39
|
+
const sharedHeader = CheckpointHeader.random({ slotNumber: SlotNumber(slotNumber) });
|
|
40
|
+
return signers.map(signer => mockCheckpointAttestation(signer, slotNumber, archiveToUse, sharedHeader));
|
|
25
41
|
};
|
|
26
42
|
|
|
27
43
|
const mockBlockProposalForPool = (
|
|
@@ -29,7 +45,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
29
45
|
slotNumber: number,
|
|
30
46
|
archive: Fr = Fr.random(),
|
|
31
47
|
): Promise<BlockProposal> => {
|
|
32
|
-
const header =
|
|
48
|
+
const header = makeBlockHeader(1, { slotNumber: SlotNumber(slotNumber) });
|
|
33
49
|
return makeBlockProposal({
|
|
34
50
|
signer,
|
|
35
51
|
blockHeader: header,
|
|
@@ -50,95 +66,93 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
50
66
|
it('should add attestations to pool', async () => {
|
|
51
67
|
const slotNumber = 420;
|
|
52
68
|
const archive = Fr.random();
|
|
53
|
-
const
|
|
69
|
+
const sharedHeader = CheckpointHeader.random({ slotNumber: SlotNumber(slotNumber) });
|
|
70
|
+
const attestations = signers
|
|
71
|
+
.slice(0, -1)
|
|
72
|
+
.map(signer => mockCheckpointAttestation(signer, slotNumber, archive, sharedHeader));
|
|
73
|
+
const payloadHash = attestations[0].getPayloadHash();
|
|
54
74
|
|
|
55
|
-
await ap.
|
|
75
|
+
await ap.addOwnCheckpointAttestations(attestations);
|
|
56
76
|
|
|
57
77
|
const retrievedAttestations = await ap.getCheckpointAttestationsForSlotAndProposal(
|
|
58
78
|
SlotNumber(slotNumber),
|
|
59
|
-
|
|
79
|
+
payloadHash,
|
|
60
80
|
);
|
|
61
81
|
expect(retrievedAttestations.length).toBe(attestations.length);
|
|
62
82
|
compareCheckpointAttestations(retrievedAttestations, attestations);
|
|
63
83
|
|
|
64
|
-
// Check hasCheckpointAttestation for added attestations
|
|
65
|
-
for (const attestation of attestations) {
|
|
66
|
-
expect(await ap.hasCheckpointAttestation(attestation)).toBe(true);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
84
|
const retrievedAttestationsForSlot = await ap.getCheckpointAttestationsForSlot(SlotNumber(slotNumber));
|
|
70
85
|
expect(retrievedAttestationsForSlot.length).toBe(attestations.length);
|
|
71
86
|
compareCheckpointAttestations(retrievedAttestationsForSlot, attestations);
|
|
72
87
|
|
|
73
88
|
// Add another one
|
|
74
|
-
const newAttestation = mockCheckpointAttestation(
|
|
75
|
-
|
|
89
|
+
const newAttestation = mockCheckpointAttestation(
|
|
90
|
+
signers[NUMBER_OF_SIGNERS_PER_TEST - 1],
|
|
91
|
+
slotNumber,
|
|
92
|
+
archive,
|
|
93
|
+
sharedHeader,
|
|
94
|
+
);
|
|
95
|
+
await ap.addOwnCheckpointAttestations([newAttestation]);
|
|
76
96
|
const retrievedAttestationsAfterAdd = await ap.getCheckpointAttestationsForSlotAndProposal(
|
|
77
97
|
SlotNumber(slotNumber),
|
|
78
|
-
|
|
98
|
+
payloadHash,
|
|
79
99
|
);
|
|
80
100
|
expect(retrievedAttestationsAfterAdd.length).toBe(attestations.length + 1);
|
|
81
101
|
compareCheckpointAttestations(retrievedAttestationsAfterAdd, [...attestations, newAttestation]);
|
|
82
|
-
expect(await ap.hasCheckpointAttestation(newAttestation)).toBe(true);
|
|
83
102
|
const retrievedAttestationsForSlotAfterAdd = await ap.getCheckpointAttestationsForSlot(SlotNumber(slotNumber));
|
|
84
103
|
expect(retrievedAttestationsForSlotAfterAdd.length).toBe(attestations.length + 1);
|
|
85
104
|
compareCheckpointAttestations(retrievedAttestationsForSlotAfterAdd, [...attestations, newAttestation]);
|
|
86
105
|
|
|
87
106
|
// Delete by slot
|
|
88
|
-
await ap.
|
|
107
|
+
await ap.deleteOlderThan(SlotNumber(slotNumber + 1));
|
|
89
108
|
|
|
90
109
|
const retreivedAttestationsAfterDelete = await ap.getCheckpointAttestationsForSlotAndProposal(
|
|
91
110
|
SlotNumber(slotNumber),
|
|
92
|
-
|
|
111
|
+
payloadHash,
|
|
93
112
|
);
|
|
94
113
|
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
95
|
-
// Check hasCheckpointAttestation after deletion
|
|
96
|
-
for (const attestation of attestations) {
|
|
97
|
-
expect(await ap.hasCheckpointAttestation(attestation)).toBe(false);
|
|
98
|
-
}
|
|
99
|
-
expect(await ap.hasCheckpointAttestation(newAttestation)).toBe(false);
|
|
100
114
|
});
|
|
101
115
|
|
|
102
116
|
it('should handle duplicate proposals in a slot', async () => {
|
|
103
117
|
const slotNumber = 420;
|
|
104
118
|
const archive = Fr.random();
|
|
119
|
+
const header = CheckpointHeader.random({ slotNumber: SlotNumber(slotNumber) });
|
|
105
120
|
|
|
106
|
-
// Use the same signer for all attestations
|
|
121
|
+
// Use the same signer and header for all attestations
|
|
107
122
|
const attestations: CheckpointAttestation[] = [];
|
|
108
123
|
const signer = signers[0];
|
|
109
124
|
for (let i = 0; i < NUMBER_OF_SIGNERS_PER_TEST; i++) {
|
|
110
|
-
attestations.push(mockCheckpointAttestation(signer, slotNumber, archive));
|
|
125
|
+
attestations.push(mockCheckpointAttestation(signer, slotNumber, archive, header));
|
|
111
126
|
}
|
|
127
|
+
const payloadHash = attestations[0].getPayloadHash();
|
|
112
128
|
|
|
113
129
|
// Add them to store and check we end up with only one
|
|
114
|
-
await ap.
|
|
130
|
+
await ap.addOwnCheckpointAttestations(attestations);
|
|
115
131
|
|
|
116
132
|
const retreivedAttestations = await ap.getCheckpointAttestationsForSlotAndProposal(
|
|
117
133
|
SlotNumber(slotNumber),
|
|
118
|
-
|
|
134
|
+
payloadHash,
|
|
119
135
|
);
|
|
120
136
|
expect(retreivedAttestations.length).toBe(1);
|
|
121
137
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
|
|
122
138
|
expect(retreivedAttestations[0].getSender()?.toString()).toEqual(signer.address.toString());
|
|
123
139
|
|
|
124
140
|
// Try adding them on another operation and check they are still not duplicated
|
|
125
|
-
await ap.
|
|
126
|
-
expect(
|
|
127
|
-
await ap.getCheckpointAttestationsForSlotAndProposal(SlotNumber(slotNumber), archive.toString()),
|
|
128
|
-
).toHaveLength(1);
|
|
141
|
+
await ap.addOwnCheckpointAttestations([attestations[0]]);
|
|
142
|
+
expect(await ap.getCheckpointAttestationsForSlotAndProposal(SlotNumber(slotNumber), payloadHash)).toHaveLength(1);
|
|
129
143
|
});
|
|
130
144
|
|
|
131
145
|
it('should store attestations by differing slot', async () => {
|
|
132
146
|
const slotNumbers = [1, 2, 3, 4];
|
|
133
147
|
const attestations = signers.map((signer, i) => mockCheckpointAttestation(signer, slotNumbers[i]));
|
|
134
148
|
|
|
135
|
-
await ap.
|
|
149
|
+
await ap.addOwnCheckpointAttestations(attestations);
|
|
136
150
|
|
|
137
151
|
for (const attestation of attestations) {
|
|
138
152
|
const slot = attestation.payload.header.slotNumber;
|
|
139
|
-
const
|
|
153
|
+
const payloadHash = attestation.getPayloadHash();
|
|
140
154
|
|
|
141
|
-
const retreivedAttestations = await ap.getCheckpointAttestationsForSlotAndProposal(slot,
|
|
155
|
+
const retreivedAttestations = await ap.getCheckpointAttestationsForSlotAndProposal(slot, payloadHash);
|
|
142
156
|
expect(retreivedAttestations.length).toBe(1);
|
|
143
157
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
144
158
|
expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
|
|
@@ -150,13 +164,13 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
150
164
|
const archives = [Fr.random(), Fr.random(), Fr.random(), Fr.random()];
|
|
151
165
|
const attestations = signers.map((signer, i) => mockCheckpointAttestation(signer, slotNumbers[i], archives[i]));
|
|
152
166
|
|
|
153
|
-
await ap.
|
|
167
|
+
await ap.addOwnCheckpointAttestations(attestations);
|
|
154
168
|
|
|
155
169
|
for (const attestation of attestations) {
|
|
156
170
|
const slot = attestation.payload.header.slotNumber;
|
|
157
|
-
const
|
|
171
|
+
const payloadHash = attestation.getPayloadHash();
|
|
158
172
|
|
|
159
|
-
const retreivedAttestations = await ap.getCheckpointAttestationsForSlotAndProposal(slot,
|
|
173
|
+
const retreivedAttestations = await ap.getCheckpointAttestationsForSlotAndProposal(slot, payloadHash);
|
|
160
174
|
expect(retreivedAttestations.length).toBe(1);
|
|
161
175
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
162
176
|
expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
|
|
@@ -165,21 +179,25 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
165
179
|
|
|
166
180
|
it('should delete attestations older than a given slot', async () => {
|
|
167
181
|
const slotNumbers = [1, 2, 3, 69, 72, 74, 88, 420];
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
)
|
|
171
|
-
const
|
|
182
|
+
const attestationsPerSlot = await Promise.all(
|
|
183
|
+
slotNumbers.map(slotNumber => createCheckpointAttestationsForSlot(slotNumber)),
|
|
184
|
+
);
|
|
185
|
+
const attestations = attestationsPerSlot.flat();
|
|
186
|
+
const payloadHashForSlot1 = attestationsPerSlot[0][0].getPayloadHash();
|
|
172
187
|
|
|
173
|
-
await ap.
|
|
188
|
+
await ap.addOwnCheckpointAttestations(attestations);
|
|
174
189
|
|
|
175
|
-
const attestationsForSlot1 = await ap.getCheckpointAttestationsForSlotAndProposal(
|
|
190
|
+
const attestationsForSlot1 = await ap.getCheckpointAttestationsForSlotAndProposal(
|
|
191
|
+
SlotNumber(1),
|
|
192
|
+
payloadHashForSlot1,
|
|
193
|
+
);
|
|
176
194
|
expect(attestationsForSlot1.length).toBe(signers.length);
|
|
177
195
|
|
|
178
|
-
await ap.
|
|
196
|
+
await ap.deleteOlderThan(SlotNumber(73));
|
|
179
197
|
|
|
180
198
|
const attestationsForSlot1AfterDelete = await ap.getCheckpointAttestationsForSlotAndProposal(
|
|
181
199
|
SlotNumber(1),
|
|
182
|
-
|
|
200
|
+
payloadHashForSlot1,
|
|
183
201
|
);
|
|
184
202
|
expect(attestationsForSlot1AfterDelete.length).toBe(0);
|
|
185
203
|
});
|
|
@@ -190,184 +208,650 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
190
208
|
const slotNumber = 420;
|
|
191
209
|
const archive = Fr.random();
|
|
192
210
|
const proposal = await mockBlockProposalForPool(signers[0], slotNumber, archive);
|
|
193
|
-
const proposalId = proposal.archive.toString();
|
|
194
211
|
|
|
195
|
-
await ap.
|
|
212
|
+
const result = await ap.tryAddBlockProposal(proposal);
|
|
213
|
+
|
|
214
|
+
expect(result.added).toBe(true);
|
|
215
|
+
expect(result.alreadyExists).toBe(false);
|
|
216
|
+
expect(result.count).toBe(1);
|
|
196
217
|
|
|
197
|
-
const retrievedProposal = await ap.
|
|
218
|
+
const retrievedProposal = await ap.getBlockProposalByArchive(proposal.archive.toString());
|
|
198
219
|
|
|
199
220
|
expect(retrievedProposal).toBeDefined();
|
|
200
221
|
expect(retrievedProposal!).toEqual(proposal);
|
|
201
|
-
|
|
202
|
-
// Check hasBlockProposal with both id and object
|
|
203
|
-
expect(await ap.hasBlockProposal(proposalId)).toBe(true);
|
|
204
|
-
expect(await ap.hasBlockProposal(proposal)).toBe(true);
|
|
205
222
|
});
|
|
206
223
|
|
|
207
224
|
it('should return undefined for non-existent block proposal', async () => {
|
|
208
225
|
const nonExistentId = Fr.random().toString();
|
|
209
|
-
const retrievedProposal = await ap.
|
|
226
|
+
const retrievedProposal = await ap.getBlockProposalByArchive(nonExistentId);
|
|
210
227
|
expect(retrievedProposal).toBeUndefined();
|
|
211
|
-
|
|
212
|
-
// Check hasBlockProposal returns false for non-existent proposal
|
|
213
|
-
expect(await ap.hasBlockProposal(nonExistentId)).toBe(false);
|
|
214
228
|
});
|
|
215
229
|
|
|
216
|
-
it('should
|
|
230
|
+
it('should return alreadyExists when re-adding the same signed payload', async () => {
|
|
217
231
|
const slotNumber = 420;
|
|
218
232
|
const archive = Fr.random();
|
|
219
|
-
const
|
|
220
|
-
const proposalId = proposal1.archive.toString();
|
|
221
|
-
|
|
222
|
-
await ap.addBlockProposal(proposal1);
|
|
233
|
+
const proposal = await mockBlockProposalForPool(signers[0], slotNumber, archive);
|
|
223
234
|
|
|
224
|
-
|
|
225
|
-
|
|
235
|
+
const result1 = await ap.tryAddBlockProposal(proposal);
|
|
236
|
+
expect(result1.added).toBe(true);
|
|
237
|
+
expect(result1.alreadyExists).toBe(false);
|
|
226
238
|
|
|
227
|
-
|
|
239
|
+
// Re-broadcasting the exact same proposal yields alreadyExists.
|
|
240
|
+
const result2 = await ap.tryAddBlockProposal(proposal);
|
|
241
|
+
expect(result2.added).toBe(false);
|
|
242
|
+
expect(result2.alreadyExists).toBe(true);
|
|
228
243
|
|
|
229
|
-
const retrievedProposal = await ap.
|
|
244
|
+
const retrievedProposal = await ap.getBlockProposalByArchive(proposal.archive.toString());
|
|
230
245
|
expect(retrievedProposal).toBeDefined();
|
|
231
|
-
|
|
232
|
-
expect(retrievedProposal!.
|
|
233
|
-
expect(retrievedProposal!.getSender()?.toString()).toBe(signers[1].address.toString());
|
|
246
|
+
expect(retrievedProposal!.toBuffer()).toEqual(proposal.toBuffer());
|
|
247
|
+
expect(retrievedProposal!.getSender()?.toString()).toBe(signers[0].address.toString());
|
|
234
248
|
});
|
|
235
249
|
|
|
236
|
-
it('should
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
const proposal2 = await mockBlockProposalForPool(signers[1], 200, archive);
|
|
240
|
-
const proposalId = archive.toString();
|
|
250
|
+
it('should retain an exact duplicate block proposal only once', async () => {
|
|
251
|
+
const slotNumber = 420;
|
|
252
|
+
const proposal = await mockBlockProposalForPool(signers[0], slotNumber);
|
|
241
253
|
|
|
242
|
-
await ap.
|
|
243
|
-
await ap.
|
|
254
|
+
await ap.tryAddBlockProposal(proposal);
|
|
255
|
+
await ap.tryAddBlockProposal(proposal);
|
|
244
256
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
257
|
+
const proposals = await ap.getProposalsForSlot(SlotNumber(slotNumber));
|
|
258
|
+
expect(proposals.blockProposals.map(proposal => proposal.toBuffer())).toEqual([
|
|
259
|
+
proposal.withoutSignedTxs().toBuffer(),
|
|
260
|
+
]);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should retain all accepted block proposals at a position', async () => {
|
|
264
|
+
const slotNumber = 420;
|
|
265
|
+
const blockHeader = makeBlockHeader(1, { slotNumber: SlotNumber(slotNumber) });
|
|
266
|
+
const proposal1 = await makeBlockProposal({
|
|
267
|
+
signer: signers[0],
|
|
268
|
+
blockHeader,
|
|
269
|
+
archiveRoot: Fr.random(),
|
|
270
|
+
indexWithinCheckpoint: IndexWithinCheckpoint(1),
|
|
271
|
+
});
|
|
272
|
+
const proposal2 = await makeBlockProposal({
|
|
273
|
+
signer: signers[0],
|
|
274
|
+
blockHeader,
|
|
275
|
+
archiveRoot: Fr.random(),
|
|
276
|
+
indexWithinCheckpoint: IndexWithinCheckpoint(1),
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await ap.tryAddBlockProposal(proposal1);
|
|
280
|
+
await ap.tryAddBlockProposal(proposal2);
|
|
281
|
+
|
|
282
|
+
const proposals = await ap.getProposalsForSlot(SlotNumber(slotNumber));
|
|
283
|
+
expect(proposals.blockProposals.map(proposal => proposal.toBuffer())).toEqual(
|
|
284
|
+
expect.arrayContaining([proposal1.withoutSignedTxs().toBuffer(), proposal2.withoutSignedTxs().toBuffer()]),
|
|
285
|
+
);
|
|
286
|
+
expect(await ap.getBlockProposalByArchive(proposal2.archive.toString())).toBeDefined();
|
|
250
287
|
});
|
|
251
288
|
});
|
|
252
289
|
|
|
253
290
|
describe('CheckpointProposal in attestation pool', () => {
|
|
254
|
-
const mockCheckpointProposalForPool = (
|
|
291
|
+
const mockCheckpointProposalForPool = async (
|
|
255
292
|
signer: Secp256k1Signer,
|
|
256
293
|
slotNumber: number,
|
|
257
294
|
archive: Fr = Fr.random(),
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
295
|
+
checkpointHeader?: CheckpointHeader,
|
|
296
|
+
): Promise<CheckpointProposalCore> => {
|
|
297
|
+
const headerToUse = checkpointHeader ?? makeCheckpointHeader(1, { slotNumber: SlotNumber(slotNumber) });
|
|
298
|
+
const blockHeader = makeBlockHeader(1);
|
|
299
|
+
const proposal = await makeCheckpointProposal({
|
|
261
300
|
signer,
|
|
262
|
-
checkpointHeader:
|
|
301
|
+
checkpointHeader: headerToUse,
|
|
263
302
|
archiveRoot: archive,
|
|
264
|
-
lastBlock: { blockHeader
|
|
303
|
+
lastBlock: { blockHeader },
|
|
265
304
|
});
|
|
305
|
+
// Return the core version since tryAddCheckpointProposal now takes CheckpointProposalCore
|
|
306
|
+
return proposal.toCore();
|
|
266
307
|
};
|
|
267
308
|
|
|
268
|
-
it('should add and retrieve checkpoint proposal
|
|
309
|
+
it('should add and retrieve checkpoint proposal', async () => {
|
|
269
310
|
const slotNumber = 420;
|
|
270
311
|
const archive = Fr.random();
|
|
271
312
|
const proposal = await mockCheckpointProposalForPool(signers[0], slotNumber, archive);
|
|
272
|
-
const proposalId = proposal.archive.toString();
|
|
273
|
-
|
|
274
|
-
await ap.addCheckpointProposal(proposal);
|
|
275
|
-
|
|
276
|
-
const retrievedProposal = await ap.getCheckpointProposal(proposalId);
|
|
277
313
|
|
|
278
|
-
|
|
279
|
-
// Should return core version (without lastBlock)
|
|
280
|
-
expect(retrievedProposal!.toBuffer()).toEqual(proposal.toCore().toBuffer());
|
|
281
|
-
|
|
282
|
-
// Check hasCheckpointProposal with both id and object
|
|
283
|
-
expect(await ap.hasCheckpointProposal(proposalId)).toBe(true);
|
|
284
|
-
expect(await ap.hasCheckpointProposal(proposal)).toBe(true);
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('should extract and store block proposal when adding checkpoint proposal with lastBlock', async () => {
|
|
288
|
-
const slotNumber = 420;
|
|
289
|
-
const archive = Fr.random();
|
|
290
|
-
const proposal = await mockCheckpointProposalForPool(signers[0], slotNumber, archive);
|
|
291
|
-
const proposalId = proposal.archive.toString();
|
|
314
|
+
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
292
315
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
expect(
|
|
316
|
+
expect(result.added).toBe(true);
|
|
317
|
+
expect(result.alreadyExists).toBe(false);
|
|
318
|
+
expect(result.count).toBe(1);
|
|
296
319
|
|
|
297
|
-
await ap.
|
|
320
|
+
const retrievedProposal = await ap.getCheckpointProposal(SlotNumber(slotNumber));
|
|
298
321
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
expect(retrievedBlockProposal).toBeDefined();
|
|
302
|
-
expect(retrievedBlockProposal!.archive.toString()).toBe(archive.toString());
|
|
303
|
-
expect(retrievedBlockProposal!.blockHeader.toBuffer()).toEqual(expectedBlockProposal!.blockHeader.toBuffer());
|
|
322
|
+
expect(retrievedProposal).toBeDefined();
|
|
323
|
+
expect(retrievedProposal!.toBuffer()).toEqual(proposal.toBuffer());
|
|
304
324
|
});
|
|
305
325
|
|
|
306
|
-
it('should
|
|
326
|
+
it('should handle checkpoint proposal without lastBlock (caller extracts and adds block separately)', async () => {
|
|
307
327
|
const slotNumber = 420;
|
|
308
328
|
const archive = Fr.random();
|
|
309
|
-
const
|
|
329
|
+
const checkpointHeader = makeCheckpointHeader(1, { slotNumber: SlotNumber(slotNumber) });
|
|
310
330
|
// Create a checkpoint proposal WITHOUT lastBlock
|
|
311
331
|
const proposal = await makeCheckpointProposal({
|
|
312
332
|
signer: signers[0],
|
|
313
|
-
checkpointHeader
|
|
333
|
+
checkpointHeader,
|
|
314
334
|
archiveRoot: archive,
|
|
315
335
|
// No lastBlock
|
|
316
336
|
});
|
|
317
|
-
const proposalId = proposal.archive.toString();
|
|
318
337
|
|
|
319
|
-
|
|
338
|
+
// Add the checkpoint core - block extraction is now caller responsibility
|
|
339
|
+
await ap.tryAddCheckpointProposal(proposal.toCore());
|
|
320
340
|
|
|
321
341
|
// The checkpoint proposal should be stored
|
|
322
|
-
const retrievedCheckpointProposal = await ap.getCheckpointProposal(
|
|
342
|
+
const retrievedCheckpointProposal = await ap.getCheckpointProposal(SlotNumber(slotNumber));
|
|
323
343
|
expect(retrievedCheckpointProposal).toBeDefined();
|
|
324
344
|
|
|
325
|
-
//
|
|
326
|
-
const retrievedBlockProposal = await ap.
|
|
345
|
+
// No block proposal was extracted (it had none anyway)
|
|
346
|
+
const retrievedBlockProposal = await ap.getBlockProposalByArchive(proposal.archive.toString());
|
|
327
347
|
expect(retrievedBlockProposal).toBeUndefined();
|
|
328
348
|
});
|
|
329
349
|
|
|
330
350
|
it('should return undefined for non-existent checkpoint proposal', async () => {
|
|
331
|
-
const
|
|
332
|
-
const retrievedProposal = await ap.getCheckpointProposal(nonExistentId);
|
|
351
|
+
const retrievedProposal = await ap.getCheckpointProposal(SlotNumber(99999));
|
|
333
352
|
expect(retrievedProposal).toBeUndefined();
|
|
353
|
+
});
|
|
334
354
|
|
|
335
|
-
|
|
336
|
-
|
|
355
|
+
it('should return alreadyExists when re-adding the same signed payload', async () => {
|
|
356
|
+
const slotNumber = 420;
|
|
357
|
+
const archive = Fr.random();
|
|
358
|
+
const proposal = await mockCheckpointProposalForPool(signers[0], slotNumber, archive);
|
|
359
|
+
|
|
360
|
+
const result1 = await ap.tryAddCheckpointProposal(proposal);
|
|
361
|
+
expect(result1.added).toBe(true);
|
|
362
|
+
expect(result1.alreadyExists).toBe(false);
|
|
363
|
+
|
|
364
|
+
// Re-broadcasting the exact same signed payload yields alreadyExists.
|
|
365
|
+
const result2 = await ap.tryAddCheckpointProposal(proposal);
|
|
366
|
+
expect(result2.added).toBe(false);
|
|
367
|
+
expect(result2.alreadyExists).toBe(true);
|
|
368
|
+
|
|
369
|
+
// Should still have the first proposal stored at the slot
|
|
370
|
+
const retrievedProposal = await ap.getCheckpointProposal(SlotNumber(slotNumber));
|
|
371
|
+
expect(retrievedProposal).toBeDefined();
|
|
372
|
+
expect(retrievedProposal!.toBuffer()).toEqual(proposal.toBuffer());
|
|
373
|
+
expect(retrievedProposal!.getSender()?.toString()).toBe(signers[0].address.toString());
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('should treat distinct payloads at the same slot as equivocations (count = 2)', async () => {
|
|
377
|
+
const slotNumber = 420;
|
|
378
|
+
// Two proposals at the same slot but with different headers (distinct payloads).
|
|
379
|
+
const proposal1 = await mockCheckpointProposalForPool(signers[0], slotNumber, Fr.random());
|
|
380
|
+
const proposal2 = await mockCheckpointProposalForPool(signers[0], slotNumber, Fr.random());
|
|
381
|
+
|
|
382
|
+
const result1 = await ap.tryAddCheckpointProposal(proposal1);
|
|
383
|
+
expect(result1.added).toBe(true);
|
|
384
|
+
expect(result1.count).toBe(1);
|
|
385
|
+
|
|
386
|
+
const result2 = await ap.tryAddCheckpointProposal(proposal2);
|
|
387
|
+
// The second distinct payload is tracked as an equivocation, count goes to 2,
|
|
388
|
+
// and both accepted payloads are retained by payload hash.
|
|
389
|
+
expect(result2.added).toBe(true);
|
|
390
|
+
expect(result2.alreadyExists).toBe(false);
|
|
391
|
+
expect(result2.count).toBe(2);
|
|
392
|
+
|
|
393
|
+
const retrievedProposal = await ap.getCheckpointProposal(SlotNumber(slotNumber));
|
|
394
|
+
const expectedProposal = [proposal1, proposal2].sort((a, b) =>
|
|
395
|
+
a.getPayloadHash().localeCompare(b.getPayloadHash()),
|
|
396
|
+
)[0];
|
|
397
|
+
expect(retrievedProposal!.toBuffer()).toEqual(expectedProposal.toBuffer());
|
|
398
|
+
|
|
399
|
+
const proposals = await ap.getProposalsForSlot(SlotNumber(slotNumber));
|
|
400
|
+
expect(proposals.checkpointProposals.map(proposal => proposal.toBuffer())).toEqual(
|
|
401
|
+
expect.arrayContaining([proposal1.toBuffer(), proposal2.toBuffer()]),
|
|
402
|
+
);
|
|
337
403
|
});
|
|
338
404
|
|
|
339
|
-
it('should
|
|
405
|
+
it('should detect equivocation when only feeAssetPriceModifier differs', async () => {
|
|
340
406
|
const slotNumber = 420;
|
|
341
407
|
const archive = Fr.random();
|
|
342
|
-
|
|
343
|
-
|
|
408
|
+
// Same checkpoint header + archive, but two different feeAssetPriceModifier values.
|
|
409
|
+
// This is the audit-finding scenario: archive collides but the signed payload differs.
|
|
410
|
+
const sharedHeader = makeCheckpointHeader(1, { slotNumber: SlotNumber(slotNumber) });
|
|
411
|
+
const proposalA = await makeCheckpointProposal({
|
|
412
|
+
signer: signers[0],
|
|
413
|
+
checkpointHeader: sharedHeader,
|
|
414
|
+
archiveRoot: archive,
|
|
415
|
+
feeAssetPriceModifier: 50n,
|
|
416
|
+
});
|
|
417
|
+
const proposalB = await makeCheckpointProposal({
|
|
418
|
+
signer: signers[0],
|
|
419
|
+
checkpointHeader: sharedHeader,
|
|
420
|
+
archiveRoot: archive,
|
|
421
|
+
feeAssetPriceModifier: -50n,
|
|
422
|
+
});
|
|
344
423
|
|
|
345
|
-
await ap.
|
|
424
|
+
const result1 = await ap.tryAddCheckpointProposal(proposalA.toCore());
|
|
425
|
+
expect(result1.count).toBe(1);
|
|
346
426
|
|
|
347
|
-
|
|
348
|
-
|
|
427
|
+
const result2 = await ap.tryAddCheckpointProposal(proposalB.toCore());
|
|
428
|
+
// The fix: archive collision no longer hides the equivocation; payload-hash dedup
|
|
429
|
+
// sees the distinct feeMod and bumps `count` to 2 so libp2p can fire the slash callback.
|
|
430
|
+
expect(result2.added).toBe(true);
|
|
431
|
+
expect(result2.alreadyExists).toBe(false);
|
|
432
|
+
expect(result2.count).toBe(2);
|
|
433
|
+
});
|
|
349
434
|
|
|
350
|
-
|
|
435
|
+
it('should delete retained proposals older than a given slot', async () => {
|
|
436
|
+
const oldSlot = 100;
|
|
437
|
+
const newSlot = 200;
|
|
438
|
+
const oldBlock = await mockBlockProposalForPool(signers[0], oldSlot);
|
|
439
|
+
const newBlock = await mockBlockProposalForPool(signers[1], newSlot);
|
|
440
|
+
const oldCheckpoint = await mockCheckpointProposalForPool(signers[0], oldSlot);
|
|
441
|
+
const newCheckpoint = await mockCheckpointProposalForPool(signers[1], newSlot);
|
|
351
442
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
443
|
+
await ap.tryAddBlockProposal(oldBlock);
|
|
444
|
+
await ap.tryAddBlockProposal(newBlock);
|
|
445
|
+
await ap.tryAddCheckpointProposal(oldCheckpoint);
|
|
446
|
+
await ap.tryAddCheckpointProposal(newCheckpoint);
|
|
447
|
+
|
|
448
|
+
await ap.deleteOlderThan(SlotNumber(newSlot));
|
|
449
|
+
|
|
450
|
+
expect(await ap.getProposalsForSlot(SlotNumber(oldSlot))).toEqual({
|
|
451
|
+
blockProposals: [],
|
|
452
|
+
checkpointProposals: [],
|
|
453
|
+
});
|
|
454
|
+
const newProposals = await ap.getProposalsForSlot(SlotNumber(newSlot));
|
|
455
|
+
expect(newProposals.blockProposals.map(proposal => proposal.toBuffer())).toContainEqual(
|
|
456
|
+
newBlock.withoutSignedTxs().toBuffer(),
|
|
457
|
+
);
|
|
458
|
+
expect(newProposals.checkpointProposals.map(proposal => proposal.toBuffer())).toContainEqual(
|
|
459
|
+
newCheckpoint.toBuffer(),
|
|
460
|
+
);
|
|
357
461
|
});
|
|
358
462
|
|
|
359
|
-
it('should
|
|
463
|
+
it('should return added=false when exceeding capacity', async () => {
|
|
360
464
|
const slotNumber = 420;
|
|
361
465
|
|
|
362
|
-
// Add
|
|
363
|
-
for (let i = 0; i <
|
|
466
|
+
// Add MAX_CHECKPOINT_PROPOSALS_PER_SLOT distinct proposals.
|
|
467
|
+
for (let i = 0; i < MAX_CHECKPOINT_PROPOSALS_PER_SLOT; i++) {
|
|
364
468
|
const proposal = await mockCheckpointProposalForPool(signers[i % NUMBER_OF_SIGNERS_PER_TEST], slotNumber);
|
|
365
|
-
await ap.
|
|
469
|
+
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
470
|
+
expect(result.added).toBe(true);
|
|
471
|
+
expect(result.count).toBe(i + 1);
|
|
366
472
|
}
|
|
367
473
|
|
|
368
|
-
// The next proposal should
|
|
474
|
+
// The next proposal should not be added.
|
|
369
475
|
const extraProposal = await mockCheckpointProposalForPool(signers[0], slotNumber);
|
|
370
|
-
await
|
|
476
|
+
const result = await ap.tryAddCheckpointProposal(extraProposal);
|
|
477
|
+
expect(result.added).toBe(false);
|
|
478
|
+
expect(result.alreadyExists).toBe(false);
|
|
479
|
+
expect(result.count).toBe(MAX_CHECKPOINT_PROPOSALS_PER_SLOT);
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
describe('Duplicate proposal detection', () => {
|
|
484
|
+
const mockBlockProposalWithIndex = (
|
|
485
|
+
signer: Secp256k1Signer,
|
|
486
|
+
slotNumber: number,
|
|
487
|
+
indexWithinCheckpoint: number,
|
|
488
|
+
archive: Fr = Fr.random(),
|
|
489
|
+
): Promise<BlockProposal> => {
|
|
490
|
+
const header = makeBlockHeader(1, { slotNumber: SlotNumber(slotNumber) });
|
|
491
|
+
return makeBlockProposal({
|
|
492
|
+
signer,
|
|
493
|
+
blockHeader: header,
|
|
494
|
+
archiveRoot: archive,
|
|
495
|
+
indexWithinCheckpoint: IndexWithinCheckpoint(indexWithinCheckpoint),
|
|
496
|
+
});
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
describe('tryAddBlockProposal duplicate detection', () => {
|
|
500
|
+
it('should return count=1 when pool is empty', async () => {
|
|
501
|
+
const proposal = await mockBlockProposalWithIndex(signers[0], 100, 0);
|
|
502
|
+
const result = await ap.tryAddBlockProposal(proposal);
|
|
503
|
+
|
|
504
|
+
expect(result.added).toBe(true);
|
|
505
|
+
expect(result.alreadyExists).toBe(false);
|
|
506
|
+
expect(result.count).toBe(1);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
it('should return alreadyExists when same proposal exists', async () => {
|
|
510
|
+
const proposal = await mockBlockProposalWithIndex(signers[0], 100, 0);
|
|
511
|
+
await ap.tryAddBlockProposal(proposal);
|
|
512
|
+
|
|
513
|
+
const result = await ap.tryAddBlockProposal(proposal);
|
|
514
|
+
|
|
515
|
+
expect(result.added).toBe(false);
|
|
516
|
+
expect(result.alreadyExists).toBe(true);
|
|
517
|
+
expect(result.count).toBe(1);
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
it('should detect duplicate via count when different proposal exists at same position', async () => {
|
|
521
|
+
const slotNumber = 100;
|
|
522
|
+
const indexWithinCheckpoint = 2;
|
|
523
|
+
|
|
524
|
+
// Add first proposal
|
|
525
|
+
const proposal1 = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
526
|
+
const result1 = await ap.tryAddBlockProposal(proposal1);
|
|
527
|
+
expect(result1.count).toBe(1);
|
|
528
|
+
|
|
529
|
+
// Add a different proposal at same position - this is a duplicate (equivocation)
|
|
530
|
+
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, indexWithinCheckpoint);
|
|
531
|
+
const result2 = await ap.tryAddBlockProposal(proposal2);
|
|
532
|
+
|
|
533
|
+
expect(result2.added).toBe(true);
|
|
534
|
+
expect(result2.alreadyExists).toBe(false);
|
|
535
|
+
// count >= 2 indicates duplicate detection
|
|
536
|
+
expect(result2.count).toBe(2);
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
it('should not detect duplicate for different positions in same slot', async () => {
|
|
540
|
+
const slotNumber = 100;
|
|
541
|
+
|
|
542
|
+
// Add proposal at index 0
|
|
543
|
+
const proposal1 = await mockBlockProposalWithIndex(signers[0], slotNumber, 0);
|
|
544
|
+
await ap.tryAddBlockProposal(proposal1);
|
|
545
|
+
|
|
546
|
+
// Add proposal at index 1 (different position)
|
|
547
|
+
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, 1);
|
|
548
|
+
const result = await ap.tryAddBlockProposal(proposal2);
|
|
549
|
+
|
|
550
|
+
expect(result.added).toBe(true);
|
|
551
|
+
// count = 1 means no duplicate for this position
|
|
552
|
+
expect(result.count).toBe(1);
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it('should not detect duplicate for same position in different slots', async () => {
|
|
556
|
+
const indexWithinCheckpoint = 0;
|
|
557
|
+
|
|
558
|
+
// Add proposal at slot 100
|
|
559
|
+
const proposal1 = await mockBlockProposalWithIndex(signers[0], 100, indexWithinCheckpoint);
|
|
560
|
+
await ap.tryAddBlockProposal(proposal1);
|
|
561
|
+
|
|
562
|
+
// Add proposal at slot 200 (different slot)
|
|
563
|
+
const proposal2 = await mockBlockProposalWithIndex(signers[1], 200, indexWithinCheckpoint);
|
|
564
|
+
const result = await ap.tryAddBlockProposal(proposal2);
|
|
565
|
+
|
|
566
|
+
expect(result.added).toBe(true);
|
|
567
|
+
// count = 1 means no duplicate for this position
|
|
568
|
+
expect(result.count).toBe(1);
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
it('should track multiple duplicates correctly via count', async () => {
|
|
572
|
+
const slotNumber = 100;
|
|
573
|
+
const indexWithinCheckpoint = 0;
|
|
574
|
+
|
|
575
|
+
// Add multiple proposals for same position
|
|
576
|
+
const proposal1 = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
577
|
+
const result1 = await ap.tryAddBlockProposal(proposal1);
|
|
578
|
+
expect(result1.count).toBe(1);
|
|
579
|
+
|
|
580
|
+
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, indexWithinCheckpoint);
|
|
581
|
+
const result2 = await ap.tryAddBlockProposal(proposal2);
|
|
582
|
+
expect(result2.count).toBe(2);
|
|
583
|
+
|
|
584
|
+
// Third proposal for same position should be rejected (cap is 2)
|
|
585
|
+
const proposal3 = await mockBlockProposalWithIndex(signers[2], slotNumber, indexWithinCheckpoint);
|
|
586
|
+
const result3 = await ap.tryAddBlockProposal(proposal3);
|
|
587
|
+
|
|
588
|
+
expect(result3.added).toBe(false);
|
|
589
|
+
expect(result3.count).toBe(2);
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it('should return added=false when exceeding capacity', async () => {
|
|
593
|
+
const slotNumber = 100;
|
|
594
|
+
const indexWithinCheckpoint = 0;
|
|
595
|
+
|
|
596
|
+
// Add MAX_BLOCK_PROPOSALS_PER_POSITION proposals
|
|
597
|
+
for (let i = 0; i < MAX_BLOCK_PROPOSALS_PER_POSITION; i++) {
|
|
598
|
+
const proposal = await mockBlockProposalWithIndex(
|
|
599
|
+
signers[i % NUMBER_OF_SIGNERS_PER_TEST],
|
|
600
|
+
slotNumber,
|
|
601
|
+
indexWithinCheckpoint,
|
|
602
|
+
);
|
|
603
|
+
const result = await ap.tryAddBlockProposal(proposal);
|
|
604
|
+
expect(result.added).toBe(true);
|
|
605
|
+
expect(result.count).toBe(i + 1);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// The next proposal should not be added
|
|
609
|
+
const extraProposal = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
610
|
+
const result = await ap.tryAddBlockProposal(extraProposal);
|
|
611
|
+
expect(result.added).toBe(false);
|
|
612
|
+
expect(result.alreadyExists).toBe(false);
|
|
613
|
+
expect(result.count).toBe(MAX_BLOCK_PROPOSALS_PER_POSITION);
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it('should clean up block position index when deleting old data', async () => {
|
|
617
|
+
const slotNumber = 100;
|
|
618
|
+
const indexWithinCheckpoint = 0;
|
|
619
|
+
|
|
620
|
+
// Add proposal
|
|
621
|
+
const proposal1 = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
622
|
+
await ap.tryAddBlockProposal(proposal1);
|
|
623
|
+
|
|
624
|
+
// Verify it's tracked (adding another should show count = 2)
|
|
625
|
+
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, indexWithinCheckpoint);
|
|
626
|
+
let result = await ap.tryAddBlockProposal(proposal2);
|
|
627
|
+
expect(result.count).toBe(2);
|
|
628
|
+
|
|
629
|
+
// Delete old data
|
|
630
|
+
await ap.deleteOlderThan(SlotNumber(slotNumber + 1));
|
|
631
|
+
|
|
632
|
+
// Verify position index is cleaned up (count should be 1 now)
|
|
633
|
+
const proposal3 = await mockBlockProposalWithIndex(signers[2], slotNumber, indexWithinCheckpoint);
|
|
634
|
+
result = await ap.tryAddBlockProposal(proposal3);
|
|
635
|
+
expect(result.count).toBe(1);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
it('should correctly delete block proposals at slot boundary', async () => {
|
|
639
|
+
// Add proposals at slots 99, 100, and 101 with various indices
|
|
640
|
+
const proposalSlot99Idx0 = await mockBlockProposalWithIndex(signers[0], 99, 0);
|
|
641
|
+
const proposalSlot99Idx1 = await mockBlockProposalWithIndex(signers[1], 99, 1);
|
|
642
|
+
const proposalSlot100Idx0 = await mockBlockProposalWithIndex(signers[2], 100, 0);
|
|
643
|
+
const proposalSlot101Idx0 = await mockBlockProposalWithIndex(signers[3], 101, 0);
|
|
644
|
+
|
|
645
|
+
await ap.tryAddBlockProposal(proposalSlot99Idx0);
|
|
646
|
+
await ap.tryAddBlockProposal(proposalSlot99Idx1);
|
|
647
|
+
await ap.tryAddBlockProposal(proposalSlot100Idx0);
|
|
648
|
+
await ap.tryAddBlockProposal(proposalSlot101Idx0);
|
|
649
|
+
|
|
650
|
+
// Delete slots older than 100 (should delete slot 99 only)
|
|
651
|
+
await ap.deleteOlderThan(SlotNumber(100));
|
|
652
|
+
|
|
653
|
+
// Slot 99 proposals should have their index cleaned up
|
|
654
|
+
const newProposal99 = await mockBlockProposalWithIndex(signers[0], 99, 0);
|
|
655
|
+
const result99 = await ap.tryAddBlockProposal(newProposal99);
|
|
656
|
+
expect(result99.count).toBe(1); // Index was cleaned up
|
|
657
|
+
|
|
658
|
+
// Slot 100 and 101 should still be tracked
|
|
659
|
+
const newProposal100 = await mockBlockProposalWithIndex(signers[1], 100, 0);
|
|
660
|
+
const result100 = await ap.tryAddBlockProposal(newProposal100);
|
|
661
|
+
expect(result100.count).toBe(2); // Still has the original
|
|
662
|
+
|
|
663
|
+
const newProposal101 = await mockBlockProposalWithIndex(signers[2], 101, 0);
|
|
664
|
+
const result101 = await ap.tryAddBlockProposal(newProposal101);
|
|
665
|
+
expect(result101.count).toBe(2); // Still has the original
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
it('should delete all indices for a given slot', async () => {
|
|
669
|
+
const slotNumber = 50;
|
|
670
|
+
|
|
671
|
+
// Add proposals at multiple indices for the same slot
|
|
672
|
+
const proposal0 = await mockBlockProposalWithIndex(signers[0], slotNumber, 0);
|
|
673
|
+
const proposal1 = await mockBlockProposalWithIndex(signers[1], slotNumber, 1);
|
|
674
|
+
const proposal2 = await mockBlockProposalWithIndex(signers[2], slotNumber, 2);
|
|
675
|
+
|
|
676
|
+
await ap.tryAddBlockProposal(proposal0);
|
|
677
|
+
await ap.tryAddBlockProposal(proposal1);
|
|
678
|
+
await ap.tryAddBlockProposal(proposal2);
|
|
679
|
+
|
|
680
|
+
// Delete slots older than slotNumber + 1
|
|
681
|
+
await ap.deleteOlderThan(SlotNumber(slotNumber + 1));
|
|
682
|
+
|
|
683
|
+
// All indices should be cleaned up
|
|
684
|
+
const newProposal0 = await mockBlockProposalWithIndex(signers[0], slotNumber, 0);
|
|
685
|
+
const result0 = await ap.tryAddBlockProposal(newProposal0);
|
|
686
|
+
expect(result0.count).toBe(1);
|
|
687
|
+
|
|
688
|
+
const newProposal1 = await mockBlockProposalWithIndex(signers[1], slotNumber, 1);
|
|
689
|
+
const result1 = await ap.tryAddBlockProposal(newProposal1);
|
|
690
|
+
expect(result1.count).toBe(1);
|
|
691
|
+
|
|
692
|
+
const newProposal2 = await mockBlockProposalWithIndex(signers[2], slotNumber, 2);
|
|
693
|
+
const result2 = await ap.tryAddBlockProposal(newProposal2);
|
|
694
|
+
expect(result2.count).toBe(1);
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
it('should delete block proposals from storage when deleting old data', async () => {
|
|
698
|
+
const oldSlot = 50;
|
|
699
|
+
const newSlot = 100;
|
|
700
|
+
|
|
701
|
+
// Add proposals at old and new slots
|
|
702
|
+
const oldProposal = await mockBlockProposalWithIndex(signers[0], oldSlot, 0);
|
|
703
|
+
const newProposal = await mockBlockProposalWithIndex(signers[1], newSlot, 0);
|
|
704
|
+
|
|
705
|
+
await ap.tryAddBlockProposal(oldProposal);
|
|
706
|
+
await ap.tryAddBlockProposal(newProposal);
|
|
707
|
+
|
|
708
|
+
// Verify both proposals exist
|
|
709
|
+
expect(await ap.getBlockProposalByArchive(oldProposal.archive.toString())).toBeDefined();
|
|
710
|
+
expect(await ap.getBlockProposalByArchive(newProposal.archive.toString())).toBeDefined();
|
|
711
|
+
|
|
712
|
+
// Delete slots older than newSlot (should delete oldSlot)
|
|
713
|
+
await ap.deleteOlderThan(SlotNumber(newSlot));
|
|
714
|
+
|
|
715
|
+
// Old proposal should be deleted from storage
|
|
716
|
+
expect(await ap.getBlockProposalByArchive(oldProposal.archive.toString())).toBeUndefined();
|
|
717
|
+
|
|
718
|
+
// New proposal should still exist
|
|
719
|
+
expect(await ap.getBlockProposalByArchive(newProposal.archive.toString())).toBeDefined();
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
describe('tryAddCheckpointProposal duplicate detection', () => {
|
|
724
|
+
const mockCheckpointProposalCoreForPool = async (
|
|
725
|
+
signer: Secp256k1Signer,
|
|
726
|
+
slotNumber: number,
|
|
727
|
+
archive: Fr = Fr.random(),
|
|
728
|
+
checkpointHeader?: CheckpointHeader,
|
|
729
|
+
): Promise<CheckpointProposalCore> => {
|
|
730
|
+
const headerToUse = checkpointHeader ?? makeCheckpointHeader(1, { slotNumber: SlotNumber(slotNumber) });
|
|
731
|
+
const blockHeader = makeBlockHeader(1);
|
|
732
|
+
const proposal = await makeCheckpointProposal({
|
|
733
|
+
signer,
|
|
734
|
+
checkpointHeader: headerToUse,
|
|
735
|
+
archiveRoot: archive,
|
|
736
|
+
lastBlock: { blockHeader },
|
|
737
|
+
});
|
|
738
|
+
return proposal.toCore();
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
it('should return count=1 when pool is empty', async () => {
|
|
742
|
+
const proposal = await mockCheckpointProposalCoreForPool(signers[0], 100);
|
|
743
|
+
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
744
|
+
|
|
745
|
+
expect(result.added).toBe(true);
|
|
746
|
+
expect(result.alreadyExists).toBe(false);
|
|
747
|
+
expect(result.count).toBe(1);
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
it('should return alreadyExists when same proposal exists', async () => {
|
|
751
|
+
const proposal = await mockCheckpointProposalCoreForPool(signers[0], 100);
|
|
752
|
+
await ap.tryAddCheckpointProposal(proposal);
|
|
753
|
+
|
|
754
|
+
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
755
|
+
|
|
756
|
+
expect(result.added).toBe(false);
|
|
757
|
+
expect(result.alreadyExists).toBe(true);
|
|
758
|
+
expect(result.count).toBe(1);
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
it('should detect duplicate via count when different proposal exists for same slot', async () => {
|
|
762
|
+
const slotNumber = 100;
|
|
763
|
+
|
|
764
|
+
// Add first proposal
|
|
765
|
+
const proposal1 = await mockCheckpointProposalCoreForPool(signers[0], slotNumber);
|
|
766
|
+
const result1 = await ap.tryAddCheckpointProposal(proposal1);
|
|
767
|
+
expect(result1.count).toBe(1);
|
|
768
|
+
|
|
769
|
+
// Add a different proposal for same slot - this is a duplicate (equivocation)
|
|
770
|
+
const proposal2 = await mockCheckpointProposalCoreForPool(signers[1], slotNumber);
|
|
771
|
+
const result2 = await ap.tryAddCheckpointProposal(proposal2);
|
|
772
|
+
|
|
773
|
+
expect(result2.added).toBe(true);
|
|
774
|
+
expect(result2.alreadyExists).toBe(false);
|
|
775
|
+
// count >= 2 indicates duplicate detection
|
|
776
|
+
expect(result2.count).toBe(2);
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
it('should not detect duplicate for different slots', async () => {
|
|
780
|
+
// Add proposal at slot 100
|
|
781
|
+
const proposal1 = await mockCheckpointProposalCoreForPool(signers[0], 100);
|
|
782
|
+
await ap.tryAddCheckpointProposal(proposal1);
|
|
783
|
+
|
|
784
|
+
// Add proposal at slot 200 (different slot)
|
|
785
|
+
const proposal2 = await mockCheckpointProposalCoreForPool(signers[1], 200);
|
|
786
|
+
const result = await ap.tryAddCheckpointProposal(proposal2);
|
|
787
|
+
|
|
788
|
+
expect(result.added).toBe(true);
|
|
789
|
+
// count = 1 means no duplicate for this slot
|
|
790
|
+
expect(result.count).toBe(1);
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
it('should track multiple duplicates correctly via count', async () => {
|
|
794
|
+
const slotNumber = 100;
|
|
795
|
+
|
|
796
|
+
// Add multiple proposals for same slot
|
|
797
|
+
const proposal1 = await mockCheckpointProposalCoreForPool(signers[0], slotNumber);
|
|
798
|
+
const result1 = await ap.tryAddCheckpointProposal(proposal1);
|
|
799
|
+
expect(result1.count).toBe(1);
|
|
800
|
+
|
|
801
|
+
const proposal2 = await mockCheckpointProposalCoreForPool(signers[1], slotNumber);
|
|
802
|
+
const result2 = await ap.tryAddCheckpointProposal(proposal2);
|
|
803
|
+
expect(result2.count).toBe(2);
|
|
804
|
+
|
|
805
|
+
// Third proposal for same slot should be rejected (cap is 2)
|
|
806
|
+
const proposal3 = await mockCheckpointProposalCoreForPool(signers[2], slotNumber);
|
|
807
|
+
const result3 = await ap.tryAddCheckpointProposal(proposal3);
|
|
808
|
+
|
|
809
|
+
expect(result3.added).toBe(false);
|
|
810
|
+
expect(result3.count).toBe(2);
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
it('should not count attestations as proposals for duplicate detection', async () => {
|
|
814
|
+
const slotNumber = 100;
|
|
815
|
+
const archive = Fr.random();
|
|
816
|
+
|
|
817
|
+
// Attestation arrives BEFORE the checkpoint proposal (race condition in p2p)
|
|
818
|
+
const attestation = mockCheckpointAttestation(signers[0], slotNumber, archive);
|
|
819
|
+
await ap.addOwnCheckpointAttestations([attestation]);
|
|
820
|
+
|
|
821
|
+
// Now the checkpoint proposal arrives - this should NOT be detected as a duplicate
|
|
822
|
+
const proposal = await mockCheckpointProposalCoreForPool(signers[1], slotNumber, archive);
|
|
823
|
+
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
824
|
+
|
|
825
|
+
expect(result.added).toBe(true);
|
|
826
|
+
expect(result.alreadyExists).toBe(false);
|
|
827
|
+
// count should be 1, NOT 2 - attestations should not count as proposals
|
|
828
|
+
expect(result.count).toBe(1);
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
it('should not count attestations for different proposals as duplicates', async () => {
|
|
832
|
+
const slotNumber = 100;
|
|
833
|
+
const archive1 = Fr.random();
|
|
834
|
+
const archive2 = Fr.random();
|
|
835
|
+
|
|
836
|
+
// Add attestations for two different proposals in the same slot
|
|
837
|
+
const attestation1 = mockCheckpointAttestation(signers[0], slotNumber, archive1);
|
|
838
|
+
const attestation2 = mockCheckpointAttestation(signers[1], slotNumber, archive2);
|
|
839
|
+
await ap.addOwnCheckpointAttestations([attestation1, attestation2]);
|
|
840
|
+
|
|
841
|
+
// Add the first checkpoint proposal - should not be affected by attestations
|
|
842
|
+
const proposal1 = await mockCheckpointProposalCoreForPool(signers[2], slotNumber, archive1);
|
|
843
|
+
const result1 = await ap.tryAddCheckpointProposal(proposal1);
|
|
844
|
+
|
|
845
|
+
expect(result1.added).toBe(true);
|
|
846
|
+
expect(result1.count).toBe(1);
|
|
847
|
+
|
|
848
|
+
// Add the second checkpoint proposal - this IS a duplicate (different archive, same slot)
|
|
849
|
+
const proposal2 = await mockCheckpointProposalCoreForPool(signers[3], slotNumber, archive2);
|
|
850
|
+
const result2 = await ap.tryAddCheckpointProposal(proposal2);
|
|
851
|
+
|
|
852
|
+
expect(result2.added).toBe(true);
|
|
853
|
+
expect(result2.count).toBe(2);
|
|
854
|
+
});
|
|
371
855
|
});
|
|
372
856
|
});
|
|
373
857
|
}
|