@aztec/p2p 0.0.1-fake-c83136db25 → 0.0.2-commit.217f559981
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bootstrap/bootstrap.d.ts +4 -3
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +4 -4
- package/dest/client/factory.d.ts +7 -6
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +53 -15
- package/dest/client/index.d.ts +1 -1
- package/dest/client/interface.d.ts +58 -23
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +51 -74
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +613 -264
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
- package/dest/config.d.ts +95 -64
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +42 -21
- package/dest/enr/generate-enr.d.ts +1 -1
- package/dest/enr/index.d.ts +1 -1
- package/dest/errors/attestation-pool.error.d.ts +7 -0
- package/dest/errors/attestation-pool.error.d.ts.map +1 -0
- package/dest/errors/attestation-pool.error.js +12 -0
- package/dest/errors/reqresp.error.d.ts +1 -1
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/tx-pool.error.d.ts +8 -0
- package/dest/errors/tx-pool.error.d.ts.map +1 -0
- package/dest/errors/tx-pool.error.js +9 -0
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +117 -45
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +441 -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 +530 -257
- 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 +234 -10
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +17 -13
- package/dest/mem_pools/index.d.ts +3 -2
- 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 +9 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +37 -10
- package/dest/mem_pools/interface.d.ts +6 -7
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +34 -58
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +320 -335
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
- package/dest/mem_pools/tx_pool/index.d.ts +1 -2
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/index.js +0 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +6 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +17 -6
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +30 -24
- 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 +93 -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 +95 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +10 -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 +11 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +174 -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_v2/eviction/invalid_txs_after_mining_rule.js +65 -0
- 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 +73 -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 +211 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.js +9 -0
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +97 -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 +152 -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 +355 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +60 -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 +161 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +77 -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 +896 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +7 -6
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +57 -24
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +76 -0
- package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
- package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/index.js +1 -0
- package/dest/msg_validators/clock_tolerance.d.ts +21 -0
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
- package/dest/msg_validators/clock_tolerance.js +37 -0
- package/dest/msg_validators/index.d.ts +2 -2
- package/dest/msg_validators/index.d.ts.map +1 -1
- package/dest/msg_validators/index.js +1 -1
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
- package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/index.js +3 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.js +104 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +212 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +3 -3
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
- 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/archive_cache.js +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/data_validator.d.ts +3 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +4 -1
- 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 +10 -4
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +22 -12
- 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 +20 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +11 -16
- package/dest/msg_validators/tx_validator/index.d.ts +2 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +1 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +4 -3
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +2 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +6 -4
- 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/test_utils.d.ts +2 -2
- package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +23 -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 +3 -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 +2 -2
- 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 +10 -6
- package/dest/services/discv5/discV5_service.d.ts +1 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +1 -1
- package/dest/services/dummy_service.d.ts +28 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +51 -0
- package/dest/services/encoding.d.ts +25 -4
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +76 -6
- package/dest/services/gossipsub/index.d.ts +3 -0
- package/dest/services/gossipsub/index.d.ts.map +1 -0
- package/dest/services/gossipsub/index.js +2 -0
- package/dest/services/gossipsub/scoring.d.ts +21 -3
- package/dest/services/gossipsub/scoring.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.js +24 -7
- package/dest/services/gossipsub/topic_score_params.d.ts +173 -0
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
- package/dest/services/gossipsub/topic_score_params.js +346 -0
- package/dest/services/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 +36 -71
- package/dest/services/libp2p/libp2p_service.d.ts +116 -92
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +1153 -267
- package/dest/services/peer-manager/interface.d.ts +1 -1
- package/dest/services/peer-manager/metrics.d.ts +9 -2
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +39 -16
- package/dest/services/peer-manager/peer_manager.d.ts +2 -33
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +6 -12
- 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 +68 -4
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +48 -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 +562 -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 +46 -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 +34 -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 +130 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -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 +139 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -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 +21 -0
- package/dest/services/reqresp/config.d.ts +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +22 -3
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +63 -4
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +2 -4
- 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/index.d.ts +1 -1
- package/dest/services/reqresp/interface.d.ts +13 -2
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +16 -2
- 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 +17 -21
- package/dest/services/reqresp/protocols/auth.d.ts +2 -2
- package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/auth.js +2 -2
- package/dest/services/reqresp/protocols/block.d.ts +1 -1
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.js +3 -2
- 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 +27 -9
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +30 -9
- 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 +60 -14
- package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
- package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.d.ts +1 -1
- package/dest/services/reqresp/protocols/ping.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts +6 -5
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +7 -3
- package/dest/services/reqresp/protocols/tx.d.ts +8 -3
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts +6 -41
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +472 -51
- package/dest/services/reqresp/status.d.ts +2 -2
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/service.d.ts +55 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +22 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +56 -2
- package/dest/services/tx_collection/fast_tx_collection.d.ts +10 -12
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +71 -44
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_collection.js +167 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts +37 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_source.js +90 -0
- package/dest/services/tx_collection/index.d.ts +3 -1
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +2 -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 +11 -13
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +49 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
- package/dest/services/tx_collection/proposal_tx_collector.js +50 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +9 -6
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +61 -26
- package/dest/services/tx_collection/tx_collection.d.ts +31 -18
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +79 -7
- 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 +26 -29
- package/dest/services/tx_collection/tx_source.d.ts +8 -3
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +19 -2
- package/dest/services/tx_file_store/config.d.ts +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 +48 -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 +152 -0
- 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 +16 -6
- package/dest/services/tx_provider_instrumentation.d.ts +5 -2
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.js +14 -14
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
- package/dest/test-helpers/get-ports.d.ts +1 -1
- package/dest/test-helpers/get-ports.d.ts.map +1 -1
- 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-enrs.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts +4 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +31 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +103 -2
- package/dest/test-helpers/mock-tx-helpers.d.ts +2 -2
- package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -1
- package/dest/test-helpers/mock-tx-helpers.js +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -2
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -1
- package/dest/test-helpers/test_tx_provider.d.ts +40 -0
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
- package/dest/test-helpers/test_tx_provider.js +41 -0
- package/dest/test-helpers/testbench-utils.d.ts +163 -0
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
- package/dest/test-helpers/testbench-utils.js +366 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +221 -120
- package/dest/testbench/parse_log_file.d.ts +1 -1
- package/dest/testbench/testbench.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts +51 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +226 -39
- package/dest/types/index.d.ts +1 -1
- package/dest/util.d.ts +3 -2
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +11 -2
- package/dest/versioning.d.ts +1 -1
- package/package.json +19 -18
- package/src/bootstrap/bootstrap.ts +7 -4
- package/src/client/factory.ts +98 -31
- package/src/client/interface.ts +77 -23
- package/src/client/p2p_client.ts +291 -309
- package/src/client/test/tx_proposal_collector/README.md +227 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +346 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
- package/src/config.ts +77 -30
- package/src/errors/attestation-pool.error.ts +13 -0
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +518 -45
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +618 -276
- package/src/mem_pools/attestation_pool/index.ts +9 -2
- package/src/mem_pools/attestation_pool/mocks.ts +22 -15
- package/src/mem_pools/index.ts +4 -1
- package/src/mem_pools/instrumentation.ts +48 -10
- package/src/mem_pools/interface.ts +5 -7
- package/src/mem_pools/tx_pool/README.md +270 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +372 -371
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
- package/src/mem_pools/tx_pool/index.ts +0 -1
- package/src/mem_pools/tx_pool/priority.ts +8 -1
- package/src/mem_pools/tx_pool/tx_pool.ts +18 -5
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +23 -17
- package/src/mem_pools/tx_pool_v2/README.md +275 -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 +121 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +122 -0
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +27 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +209 -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 +90 -0
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +31 -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 +242 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +242 -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 +444 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +223 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1069 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +45 -32
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +94 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/clock_tolerance.ts +51 -0
- package/src/msg_validators/index.ts +1 -1
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
- package/src/msg_validators/proposal_validator/index.ts +3 -0
- package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +2 -2
- package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
- package/src/msg_validators/tx_validator/block_header_validator.ts +21 -8
- package/src/msg_validators/tx_validator/data_validator.ts +18 -6
- package/src/msg_validators/tx_validator/double_spend_validator.ts +15 -9
- package/src/msg_validators/tx_validator/factory.ts +67 -25
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +17 -28
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +19 -8
- package/src/msg_validators/tx_validator/phases_validator.ts +8 -4
- package/src/msg_validators/tx_validator/size_validator.ts +22 -0
- package/src/msg_validators/tx_validator/test_utils.ts +1 -1
- package/src/msg_validators/tx_validator/timestamp_validator.ts +30 -19
- package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +8 -3
- package/src/services/data_store.ts +10 -7
- package/src/services/discv5/discV5_service.ts +1 -1
- package/src/services/dummy_service.ts +68 -1
- package/src/services/encoding.ts +83 -6
- package/src/services/gossipsub/README.md +641 -0
- package/src/services/gossipsub/index.ts +2 -0
- package/src/services/gossipsub/scoring.ts +29 -5
- package/src/services/gossipsub/topic_score_params.ts +487 -0
- package/src/services/index.ts +1 -0
- package/src/services/libp2p/instrumentation.ts +39 -71
- package/src/services/libp2p/libp2p_service.ts +865 -277
- package/src/services/peer-manager/metrics.ts +44 -16
- package/src/services/peer-manager/peer_manager.ts +7 -4
- package/src/services/peer-manager/peer_scoring.ts +70 -3
- package/src/services/reqresp/batch-tx-requester/README.md +305 -0
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
- package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
- package/src/services/reqresp/batch-tx-requester/interface.ts +53 -0
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +161 -0
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +19 -1
- package/src/services/reqresp/constants.ts +14 -0
- package/src/services/reqresp/interface.ts +30 -2
- package/src/services/reqresp/metrics.ts +36 -27
- package/src/services/reqresp/protocols/auth.ts +2 -2
- package/src/services/reqresp/protocols/block.ts +3 -2
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +16 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +35 -12
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +75 -10
- package/src/services/reqresp/protocols/status.ts +16 -12
- package/src/services/reqresp/protocols/tx.ts +23 -2
- package/src/services/reqresp/reqresp.ts +80 -23
- package/src/services/service.ts +72 -4
- package/src/services/tx_collection/config.ts +84 -2
- package/src/services/tx_collection/fast_tx_collection.ts +96 -49
- package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
- package/src/services/tx_collection/file_store_tx_source.ts +117 -0
- package/src/services/tx_collection/index.ts +6 -0
- package/src/services/tx_collection/instrumentation.ts +11 -13
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +113 -0
- package/src/services/tx_collection/slow_tx_collection.ts +70 -36
- package/src/services/tx_collection/tx_collection.ts +122 -24
- package/src/services/tx_collection/tx_collection_sink.ts +30 -34
- package/src/services/tx_collection/tx_source.ts +22 -3
- package/src/services/tx_file_store/config.ts +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 +175 -0
- package/src/services/tx_provider.ts +27 -10
- package/src/services/tx_provider_instrumentation.ts +24 -14
- package/src/test-helpers/index.ts +2 -0
- package/src/test-helpers/make-test-p2p-clients.ts +3 -3
- package/src/test-helpers/mock-pubsub.ts +144 -4
- package/src/test-helpers/mock-tx-helpers.ts +1 -1
- package/src/test-helpers/reqresp-nodes.ts +3 -2
- package/src/test-helpers/test_tx_provider.ts +64 -0
- package/src/test-helpers/testbench-utils.ts +430 -0
- package/src/testbench/p2p_client_testbench_worker.ts +349 -117
- package/src/testbench/worker_client_manager.ts +304 -42
- package/src/util.ts +19 -3
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -28
- 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 -174
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -23
- 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 -175
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -79
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -232
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -70
- package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.js +0 -1
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -235
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -225
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -278
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -81
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import {
|
|
3
|
-
import { Fr } from '@aztec/foundation/
|
|
2
|
+
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
4
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
5
|
-
import { SerialQueue } from '@aztec/foundation/queue';
|
|
6
5
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
7
6
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
7
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
9
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
10
8
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
11
|
-
import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
|
|
9
|
+
import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
12
10
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
13
11
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
14
12
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
15
13
|
import {
|
|
16
|
-
BlockAttestation,
|
|
17
14
|
BlockProposal,
|
|
15
|
+
CheckpointAttestation,
|
|
16
|
+
CheckpointProposal,
|
|
17
|
+
type CheckpointProposalCore,
|
|
18
18
|
type Gossipable,
|
|
19
19
|
P2PClientType,
|
|
20
20
|
P2PMessage,
|
|
21
|
+
type ValidationResult as P2PValidationResult,
|
|
21
22
|
PeerErrorSeverity,
|
|
22
23
|
TopicType,
|
|
23
24
|
createTopicString,
|
|
@@ -28,7 +29,14 @@ import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
|
28
29
|
import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
29
30
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
30
31
|
import { compressComponentVersions } from '@aztec/stdlib/versioning';
|
|
31
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
Attributes,
|
|
34
|
+
OtelMetricsAdapter,
|
|
35
|
+
SpanStatusCode,
|
|
36
|
+
type TelemetryClient,
|
|
37
|
+
WithTracer,
|
|
38
|
+
trackSpan,
|
|
39
|
+
} from '@aztec/telemetry-client';
|
|
32
40
|
|
|
33
41
|
import {
|
|
34
42
|
type GossipSub,
|
|
@@ -36,7 +44,7 @@ import {
|
|
|
36
44
|
type GossipsubMessage,
|
|
37
45
|
gossipsub,
|
|
38
46
|
} from '@chainsafe/libp2p-gossipsub';
|
|
39
|
-
import { createPeerScoreParams
|
|
47
|
+
import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
40
48
|
import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
|
|
41
49
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
42
50
|
import { yamux } from '@chainsafe/libp2p-yamux';
|
|
@@ -51,52 +59,64 @@ import { createLibp2p } from 'libp2p';
|
|
|
51
59
|
|
|
52
60
|
import type { P2PConfig } from '../../config.js';
|
|
53
61
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
54
|
-
import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
|
|
55
|
-
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
56
|
-
import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
|
|
57
|
-
import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
|
|
58
62
|
import {
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
BlockProposalValidator,
|
|
64
|
+
CheckpointAttestationValidator,
|
|
65
|
+
CheckpointProposalValidator,
|
|
61
66
|
DoubleSpendTxValidator,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
} from '../../msg_validators/
|
|
67
|
+
FishermanAttestationValidator,
|
|
68
|
+
getDefaultAllowedSetupFunctions,
|
|
69
|
+
} from '../../msg_validators/index.js';
|
|
70
|
+
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
71
|
+
import {
|
|
72
|
+
type MessageValidator,
|
|
73
|
+
createTxMessageValidators,
|
|
74
|
+
createTxReqRespValidator,
|
|
75
|
+
} from '../../msg_validators/tx_validator/factory.js';
|
|
65
76
|
import { GossipSubEvent } from '../../types/index.js';
|
|
66
77
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
67
78
|
import { getVersions } from '../../versioning.js';
|
|
68
79
|
import { AztecDatastore } from '../data_store.js';
|
|
69
80
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
70
81
|
import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
71
|
-
import { gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
82
|
+
import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
83
|
+
import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
|
|
72
84
|
import type { PeerManagerInterface } from '../peer-manager/interface.js';
|
|
73
85
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
74
86
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
87
|
+
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
75
88
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
76
89
|
import {
|
|
77
90
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
78
91
|
type ReqRespInterface,
|
|
92
|
+
type ReqRespResponse,
|
|
79
93
|
ReqRespSubProtocol,
|
|
80
94
|
type ReqRespSubProtocolHandler,
|
|
81
95
|
type ReqRespSubProtocolHandlers,
|
|
82
96
|
type ReqRespSubProtocolValidators,
|
|
83
97
|
type SubProtocolMap,
|
|
84
98
|
ValidationError,
|
|
85
|
-
} from '../reqresp/
|
|
86
|
-
import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
|
|
87
|
-
import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
99
|
+
} from '../reqresp/index.js';
|
|
88
100
|
import {
|
|
89
101
|
AuthRequest,
|
|
90
102
|
BlockTxsRequest,
|
|
91
103
|
BlockTxsResponse,
|
|
92
104
|
StatusMessage,
|
|
93
105
|
pingHandler,
|
|
106
|
+
reqGoodbyeHandler,
|
|
94
107
|
reqRespBlockHandler,
|
|
108
|
+
reqRespBlockTxsHandler,
|
|
95
109
|
reqRespStatusHandler,
|
|
96
110
|
reqRespTxHandler,
|
|
97
|
-
} from '../reqresp/
|
|
111
|
+
} from '../reqresp/index.js';
|
|
98
112
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
99
|
-
import type {
|
|
113
|
+
import type {
|
|
114
|
+
P2PBlockReceivedCallback,
|
|
115
|
+
P2PCheckpointReceivedCallback,
|
|
116
|
+
P2PDuplicateAttestationCallback,
|
|
117
|
+
P2PService,
|
|
118
|
+
PeerDiscoveryService,
|
|
119
|
+
} from '../service.js';
|
|
100
120
|
import { P2PInstrumentation } from './instrumentation.js';
|
|
101
121
|
|
|
102
122
|
interface ValidationResult {
|
|
@@ -107,22 +127,37 @@ interface ValidationResult {
|
|
|
107
127
|
|
|
108
128
|
type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
|
|
109
129
|
|
|
130
|
+
// REFACTOR: Unify with the type above
|
|
131
|
+
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
132
|
+
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
133
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
134
|
+
|
|
110
135
|
/**
|
|
111
136
|
* Lib P2P implementation of the P2PService interface.
|
|
112
137
|
*/
|
|
113
138
|
export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
|
|
114
|
-
private jobQueue: SerialQueue = new SerialQueue();
|
|
115
139
|
private discoveryRunningPromise?: RunningPromise;
|
|
116
140
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
117
141
|
|
|
118
142
|
// Message validators
|
|
119
|
-
private attestationValidator: AttestationValidator;
|
|
120
143
|
private blockProposalValidator: BlockProposalValidator;
|
|
144
|
+
private checkpointProposalValidator: CheckpointProposalValidator;
|
|
145
|
+
private checkpointAttestationValidator: CheckpointAttestationValidator;
|
|
121
146
|
|
|
122
147
|
private protocolVersion = '';
|
|
123
148
|
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
|
|
124
149
|
|
|
125
|
-
private feesCache: { blockNumber:
|
|
150
|
+
private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
|
|
151
|
+
|
|
152
|
+
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */
|
|
153
|
+
private duplicateProposalCallback?: (info: {
|
|
154
|
+
slot: SlotNumber;
|
|
155
|
+
proposer: EthAddress;
|
|
156
|
+
type: 'checkpoint' | 'block';
|
|
157
|
+
}) => void;
|
|
158
|
+
|
|
159
|
+
/** Callback invoked when a duplicate attestation is detected (triggers slashing). */
|
|
160
|
+
private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
|
|
126
161
|
|
|
127
162
|
/**
|
|
128
163
|
* Callback for when a block is received from a peer.
|
|
@@ -131,32 +166,48 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
131
166
|
*/
|
|
132
167
|
private blockReceivedCallback: P2PBlockReceivedCallback;
|
|
133
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Callback for when a checkpoint proposal is received from a peer.
|
|
171
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
172
|
+
* @returns The attestations for the checkpoint, if any.
|
|
173
|
+
*/
|
|
174
|
+
private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
175
|
+
|
|
134
176
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
135
177
|
|
|
136
178
|
private instrumentation: P2PInstrumentation;
|
|
137
179
|
|
|
180
|
+
private telemetry: TelemetryClient;
|
|
181
|
+
|
|
182
|
+
protected logger: Logger;
|
|
183
|
+
|
|
138
184
|
constructor(
|
|
139
185
|
private clientType: T,
|
|
140
186
|
private config: P2PConfig,
|
|
141
187
|
protected node: PubSubLibp2p,
|
|
142
188
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
143
189
|
private reqresp: ReqRespInterface,
|
|
144
|
-
|
|
145
|
-
protected mempools: MemPools
|
|
146
|
-
|
|
190
|
+
protected peerManager: PeerManagerInterface,
|
|
191
|
+
protected mempools: MemPools,
|
|
192
|
+
protected archiver: L2BlockSource & ContractDataSource,
|
|
147
193
|
private epochCache: EpochCacheInterface,
|
|
148
194
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
149
195
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
150
196
|
telemetry: TelemetryClient,
|
|
151
|
-
|
|
197
|
+
logger: Logger = createLogger('p2p:libp2p_service'),
|
|
152
198
|
) {
|
|
153
199
|
super(telemetry, 'LibP2PService');
|
|
200
|
+
this.telemetry = telemetry;
|
|
201
|
+
|
|
202
|
+
// Create child logger with fisherman prefix if in fisherman mode
|
|
203
|
+
this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
|
|
154
204
|
|
|
155
205
|
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
|
|
156
206
|
|
|
157
207
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
158
208
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
159
|
-
this.msgIdSeenValidators[TopicType.
|
|
209
|
+
this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
210
|
+
this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
160
211
|
|
|
161
212
|
const versions = getVersions(config);
|
|
162
213
|
this.protocolVersion = compressComponentVersions(versions);
|
|
@@ -164,22 +215,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
164
215
|
|
|
165
216
|
this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
|
|
166
217
|
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
167
|
-
this.topicStrings[TopicType.
|
|
168
|
-
TopicType.
|
|
218
|
+
this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(
|
|
219
|
+
TopicType.checkpoint_proposal,
|
|
220
|
+
this.protocolVersion,
|
|
221
|
+
);
|
|
222
|
+
this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(
|
|
223
|
+
TopicType.checkpoint_attestation,
|
|
169
224
|
this.protocolVersion,
|
|
170
225
|
);
|
|
171
226
|
|
|
172
|
-
this.attestationValidator = new AttestationValidator(epochCache);
|
|
173
227
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
|
|
228
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
229
|
+
txsPermitted: !config.disableTransactions,
|
|
230
|
+
});
|
|
231
|
+
this.checkpointAttestationValidator = config.fishermanMode
|
|
232
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
233
|
+
: new CheckpointAttestationValidator(epochCache);
|
|
174
234
|
|
|
175
235
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
176
236
|
|
|
177
|
-
this.blockReceivedCallback = async (block: BlockProposal): Promise<
|
|
237
|
+
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
178
238
|
this.logger.debug(
|
|
179
|
-
`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber
|
|
180
|
-
{ p2pMessageIdentifier: await block.
|
|
239
|
+
`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
|
|
240
|
+
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
181
241
|
);
|
|
182
|
-
return
|
|
242
|
+
return false;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
this.checkpointReceivedCallback = (
|
|
246
|
+
checkpoint: CheckpointProposalCore,
|
|
247
|
+
): Promise<CheckpointAttestation[] | undefined> => {
|
|
248
|
+
this.logger.debug(
|
|
249
|
+
`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
|
|
250
|
+
);
|
|
251
|
+
return Promise.resolve(undefined);
|
|
183
252
|
};
|
|
184
253
|
}
|
|
185
254
|
|
|
@@ -198,7 +267,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
198
267
|
config: P2PConfig,
|
|
199
268
|
peerId: PeerId,
|
|
200
269
|
deps: {
|
|
201
|
-
mempools: MemPools
|
|
270
|
+
mempools: MemPools;
|
|
202
271
|
l2BlockSource: L2BlockSource & ContractDataSource;
|
|
203
272
|
epochCache: EpochCacheInterface;
|
|
204
273
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
@@ -225,14 +294,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
225
294
|
|
|
226
295
|
const datastore = new AztecDatastore(peerStore);
|
|
227
296
|
|
|
228
|
-
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
|
|
297
|
+
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
|
|
229
298
|
|
|
230
299
|
const peerDiscoveryService = new DiscV5Service(
|
|
231
300
|
peerId,
|
|
232
301
|
config,
|
|
233
302
|
packageVersion,
|
|
234
303
|
telemetry,
|
|
235
|
-
createLogger(`${logger.module}:discv5_service
|
|
304
|
+
createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
|
|
236
305
|
);
|
|
237
306
|
|
|
238
307
|
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
@@ -246,10 +315,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
246
315
|
const versions = getVersions(config);
|
|
247
316
|
const protocolVersion = compressComponentVersions(versions);
|
|
248
317
|
|
|
249
|
-
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
250
|
-
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
251
|
-
const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
|
|
252
|
-
|
|
253
318
|
const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
|
|
254
319
|
const directPeers = (
|
|
255
320
|
await Promise.all(
|
|
@@ -269,6 +334,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
269
334
|
|
|
270
335
|
const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
|
|
271
336
|
|
|
337
|
+
// Create dynamic topic score params based on network configuration
|
|
338
|
+
const l1Constants = epochCache.getL1Constants();
|
|
339
|
+
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
340
|
+
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
341
|
+
heartbeatIntervalMs: config.gossipsubInterval,
|
|
342
|
+
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
343
|
+
blockDurationMs: config.blockDurationMs,
|
|
344
|
+
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
|
|
345
|
+
});
|
|
346
|
+
|
|
272
347
|
const node = await createLibp2p({
|
|
273
348
|
start: false,
|
|
274
349
|
peerId,
|
|
@@ -364,33 +439,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
364
439
|
scoreParams: createPeerScoreParams({
|
|
365
440
|
// IPColocation factor can be disabled for local testing - default to -5
|
|
366
441
|
IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
|
|
367
|
-
topics:
|
|
368
|
-
[txTopic]: createTopicScoreParams({
|
|
369
|
-
topicWeight: 1,
|
|
370
|
-
invalidMessageDeliveriesWeight: -20,
|
|
371
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
372
|
-
}),
|
|
373
|
-
[blockAttestationTopic]: createTopicScoreParams({
|
|
374
|
-
topicWeight: 1,
|
|
375
|
-
invalidMessageDeliveriesWeight: -20,
|
|
376
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
377
|
-
}),
|
|
378
|
-
[blockProposalTopic]: createTopicScoreParams({
|
|
379
|
-
topicWeight: 1,
|
|
380
|
-
invalidMessageDeliveriesWeight: -20,
|
|
381
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
382
|
-
}),
|
|
383
|
-
},
|
|
442
|
+
topics: topicScoreParams,
|
|
384
443
|
}),
|
|
385
444
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
386
445
|
components: (components: { connectionManager: ConnectionManager }) => ({
|
|
387
446
|
connectionManager: components.connectionManager,
|
|
388
447
|
}),
|
|
389
448
|
},
|
|
390
|
-
logger: createLibp2pComponentLogger(logger.module),
|
|
449
|
+
logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
|
|
391
450
|
});
|
|
392
451
|
|
|
393
|
-
const peerScoring = new PeerScoring(config);
|
|
452
|
+
const peerScoring = new PeerScoring(config, telemetry);
|
|
394
453
|
const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
|
|
395
454
|
|
|
396
455
|
const peerManager = new PeerManager(
|
|
@@ -406,8 +465,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
406
465
|
epochCache,
|
|
407
466
|
);
|
|
408
467
|
|
|
409
|
-
//
|
|
410
|
-
|
|
468
|
+
// Configure application-specific scoring for gossipsub.
|
|
469
|
+
// The weight scales app score to align with gossipsub thresholds:
|
|
470
|
+
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
471
|
+
// - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
|
|
472
|
+
// Note: positive topic scores can offset penalties, so alignment is best-effort.
|
|
473
|
+
node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
|
|
411
474
|
node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
|
|
412
475
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
413
476
|
|
|
@@ -445,20 +508,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
445
508
|
}
|
|
446
509
|
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
447
510
|
|
|
448
|
-
// Start job queue, peer discovery service and libp2p node
|
|
449
|
-
this.jobQueue.start();
|
|
450
|
-
|
|
451
|
-
await this.peerManager.initializePeers();
|
|
452
|
-
if (!this.config.p2pDiscoveryDisabled) {
|
|
453
|
-
await this.peerDiscoveryService.start();
|
|
454
|
-
}
|
|
455
|
-
await this.node.start();
|
|
456
|
-
|
|
457
|
-
// Subscribe to standard GossipSub topics by default
|
|
458
|
-
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
|
|
459
|
-
this.subscribeToTopic(this.topicStrings[topic]);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
511
|
// Create request response protocol handlers
|
|
463
512
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
464
513
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
@@ -472,9 +521,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
472
521
|
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
|
|
473
522
|
};
|
|
474
523
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
524
|
+
if (!this.config.disableTransactions) {
|
|
525
|
+
const blockTxsHandler = reqRespBlockTxsHandler(
|
|
526
|
+
this.mempools.attestationPool,
|
|
527
|
+
this.archiver,
|
|
528
|
+
this.mempools.txPool,
|
|
529
|
+
);
|
|
478
530
|
requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
|
|
479
531
|
}
|
|
480
532
|
|
|
@@ -482,25 +534,41 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
482
534
|
requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
|
|
483
535
|
}
|
|
484
536
|
|
|
537
|
+
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
538
|
+
const reqrespSubProtocolValidators = {
|
|
539
|
+
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
540
|
+
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
541
|
+
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
542
|
+
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
await this.peerManager.initializePeers();
|
|
546
|
+
|
|
547
|
+
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
548
|
+
|
|
549
|
+
await this.node.start();
|
|
550
|
+
|
|
551
|
+
// Subscribe to standard GossipSub topics by default
|
|
552
|
+
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
|
|
553
|
+
this.subscribeToTopic(this.topicStrings[topic]);
|
|
554
|
+
}
|
|
555
|
+
|
|
485
556
|
// add GossipSub listener
|
|
486
557
|
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
487
558
|
|
|
488
|
-
// Start running promise for peer discovery
|
|
559
|
+
// Start running promise for peer discovery and metrics collection
|
|
560
|
+
if (!this.config.p2pDiscoveryDisabled) {
|
|
561
|
+
await this.peerDiscoveryService.start();
|
|
562
|
+
}
|
|
489
563
|
this.discoveryRunningPromise = new RunningPromise(
|
|
490
|
-
() =>
|
|
564
|
+
async () => {
|
|
565
|
+
await this.peerManager.heartbeat();
|
|
566
|
+
},
|
|
491
567
|
this.logger,
|
|
492
568
|
this.config.peerCheckIntervalMS,
|
|
493
569
|
);
|
|
494
570
|
this.discoveryRunningPromise.start();
|
|
495
571
|
|
|
496
|
-
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
497
|
-
const reqrespSubProtocolValidators = {
|
|
498
|
-
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
499
|
-
// TODO(#11336): A request validator for blocks
|
|
500
|
-
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
501
|
-
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
502
|
-
};
|
|
503
|
-
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
504
572
|
this.logger.info(`Started P2P service`, {
|
|
505
573
|
listen: this.config.listenAddress,
|
|
506
574
|
port: this.config.p2pPort,
|
|
@@ -520,9 +588,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
520
588
|
// Stop peer manager
|
|
521
589
|
this.logger.debug('Stopping peer manager...');
|
|
522
590
|
await this.peerManager.stop();
|
|
523
|
-
|
|
524
|
-
this.logger.debug('Stopping job queue...');
|
|
525
|
-
await this.jobQueue.end();
|
|
526
591
|
this.logger.debug('Stopping running promise...');
|
|
527
592
|
await this.discoveryRunningPromise?.stop();
|
|
528
593
|
this.logger.debug('Stopping peer discovery service...');
|
|
@@ -550,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
550
615
|
return this.peerManager.getPeers(includePending);
|
|
551
616
|
}
|
|
552
617
|
|
|
618
|
+
public getGossipMeshPeerCount(topicType: TopicType): number {
|
|
619
|
+
return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
|
|
620
|
+
}
|
|
621
|
+
|
|
553
622
|
private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
|
|
554
623
|
this.logger.trace(`Received PUBSUB message.`);
|
|
555
624
|
|
|
@@ -577,6 +646,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
577
646
|
return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
|
|
578
647
|
}
|
|
579
648
|
|
|
649
|
+
public sendRequestToPeer(
|
|
650
|
+
peerId: PeerId,
|
|
651
|
+
subProtocol: ReqRespSubProtocol,
|
|
652
|
+
payload: Buffer,
|
|
653
|
+
dialTimeout?: number,
|
|
654
|
+
): Promise<ReqRespResponse> {
|
|
655
|
+
return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
|
|
656
|
+
}
|
|
657
|
+
|
|
580
658
|
/**
|
|
581
659
|
* Get the ENR of the node
|
|
582
660
|
* @returns The ENR of the node
|
|
@@ -589,6 +667,29 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
589
667
|
this.blockReceivedCallback = callback;
|
|
590
668
|
}
|
|
591
669
|
|
|
670
|
+
public registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
671
|
+
this.checkpointReceivedCallback = callback;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Registers a callback to be invoked when a duplicate proposal is detected.
|
|
676
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
677
|
+
*/
|
|
678
|
+
public registerDuplicateProposalCallback(
|
|
679
|
+
callback: (info: { slot: SlotNumber; proposer: EthAddress; type: 'checkpoint' | 'block' }) => void,
|
|
680
|
+
): void {
|
|
681
|
+
this.duplicateProposalCallback = callback;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Registers a callback to be invoked when a duplicate attestation is detected.
|
|
686
|
+
* A validator signing attestations for different proposals at the same slot.
|
|
687
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
688
|
+
*/
|
|
689
|
+
public registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void {
|
|
690
|
+
this.duplicateAttestationCallback = callback;
|
|
691
|
+
}
|
|
692
|
+
|
|
592
693
|
/**
|
|
593
694
|
* Subscribes to a topic.
|
|
594
695
|
* @param topic - The topic to subscribe to.
|
|
@@ -610,11 +711,19 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
610
711
|
if (!this.node.services.pubsub) {
|
|
611
712
|
throw new Error('Pubsub service not available.');
|
|
612
713
|
}
|
|
613
|
-
const
|
|
714
|
+
const isBlockProposal = topic === this.topicStrings[TopicType.block_proposal];
|
|
715
|
+
const traceContext =
|
|
716
|
+
this.config.debugP2PInstrumentMessages && isBlockProposal ? this.telemetry.getTraceContext() : undefined;
|
|
717
|
+
const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages, traceContext);
|
|
614
718
|
const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
|
|
615
719
|
return result.recipients.length;
|
|
616
720
|
}
|
|
617
721
|
|
|
722
|
+
/**
|
|
723
|
+
* Checks if this message has already been seen, based on its msgId computed from hashing the message data.
|
|
724
|
+
* Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
|
|
725
|
+
* messages to avoid tx echoes across the network.
|
|
726
|
+
*/
|
|
618
727
|
protected preValidateReceivedMessage(
|
|
619
728
|
msg: Message,
|
|
620
729
|
msgId: string,
|
|
@@ -626,12 +735,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
626
735
|
case this.topicStrings[TopicType.tx]:
|
|
627
736
|
topicType = TopicType.tx;
|
|
628
737
|
break;
|
|
629
|
-
case this.topicStrings[TopicType.block_attestation]:
|
|
630
|
-
topicType = TopicType.block_attestation;
|
|
631
|
-
break;
|
|
632
738
|
case this.topicStrings[TopicType.block_proposal]:
|
|
633
739
|
topicType = TopicType.block_proposal;
|
|
634
740
|
break;
|
|
741
|
+
case this.topicStrings[TopicType.checkpoint_proposal]:
|
|
742
|
+
topicType = TopicType.checkpoint_proposal;
|
|
743
|
+
break;
|
|
744
|
+
case this.topicStrings[TopicType.checkpoint_attestation]:
|
|
745
|
+
topicType = TopicType.checkpoint_attestation;
|
|
746
|
+
break;
|
|
635
747
|
default:
|
|
636
748
|
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
637
749
|
break;
|
|
@@ -650,13 +762,39 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
650
762
|
return { result: true, topicType };
|
|
651
763
|
}
|
|
652
764
|
|
|
765
|
+
/**
|
|
766
|
+
* Safely deserializes a P2PMessage from raw message data.
|
|
767
|
+
* @param msgId - The message ID.
|
|
768
|
+
* @param source - The peer ID of the message source.
|
|
769
|
+
* @param data - The raw message data.
|
|
770
|
+
* @returns The deserialized P2PMessage or undefined if deserialization fails.
|
|
771
|
+
*/
|
|
772
|
+
private safelyDeserializeP2PMessage(msgId: string, source: PeerId, data: Uint8Array): P2PMessage | undefined {
|
|
773
|
+
try {
|
|
774
|
+
return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
|
|
775
|
+
} catch (err) {
|
|
776
|
+
this.logger.error(`Error deserializing P2PMessage`, err, {
|
|
777
|
+
msgId,
|
|
778
|
+
source: source.toString(),
|
|
779
|
+
});
|
|
780
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
|
|
781
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
|
|
782
|
+
return undefined;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
653
786
|
/**
|
|
654
787
|
* Handles a new gossip message that was received by the client.
|
|
655
788
|
* @param topic - The message's topic.
|
|
656
789
|
* @param data - The message data
|
|
657
790
|
*/
|
|
658
791
|
protected async handleNewGossipMessage(msg: Message, msgId: string, source: PeerId) {
|
|
659
|
-
const
|
|
792
|
+
const msgReceivedTime = Date.now();
|
|
793
|
+
let topicType: TopicType | undefined;
|
|
794
|
+
const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
|
|
795
|
+
if (!p2pMessage) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
660
798
|
|
|
661
799
|
const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
|
|
662
800
|
|
|
@@ -664,56 +802,147 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
664
802
|
return;
|
|
665
803
|
}
|
|
666
804
|
|
|
805
|
+
// Determine topic type for attributes
|
|
667
806
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
668
|
-
|
|
807
|
+
topicType = TopicType.tx;
|
|
808
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
809
|
+
topicType = TopicType.checkpoint_attestation;
|
|
810
|
+
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
811
|
+
topicType = TopicType.block_proposal;
|
|
812
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
813
|
+
topicType = TopicType.checkpoint_proposal;
|
|
669
814
|
}
|
|
670
|
-
|
|
671
|
-
|
|
815
|
+
|
|
816
|
+
// Process the message, optionally within a linked span for trace propagation
|
|
817
|
+
const processMessage = async () => {
|
|
818
|
+
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
819
|
+
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
820
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
821
|
+
if (this.clientType === P2PClientType.Full) {
|
|
822
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
823
|
+
}
|
|
824
|
+
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
825
|
+
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
826
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
827
|
+
await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
|
|
828
|
+
} else {
|
|
829
|
+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
const latency = p2pMessage.timestamp !== undefined ? msgReceivedTime - p2pMessage.timestamp.getTime() : undefined;
|
|
834
|
+
const propagatedContext = p2pMessage.traceContext
|
|
835
|
+
? this.telemetry.extractPropagatedContext(p2pMessage.traceContext)
|
|
836
|
+
: undefined;
|
|
837
|
+
|
|
838
|
+
if (propagatedContext) {
|
|
839
|
+
await this.tracer.startActiveSpan(
|
|
840
|
+
'LibP2PService.processMessage',
|
|
841
|
+
{
|
|
842
|
+
attributes: {
|
|
843
|
+
[Attributes.TOPIC_NAME]: topicType!,
|
|
844
|
+
[Attributes.PEER_ID]: source.toString(),
|
|
845
|
+
},
|
|
846
|
+
},
|
|
847
|
+
propagatedContext,
|
|
848
|
+
async span => {
|
|
849
|
+
try {
|
|
850
|
+
await processMessage();
|
|
851
|
+
span.setStatus({
|
|
852
|
+
code: SpanStatusCode.OK,
|
|
853
|
+
});
|
|
854
|
+
} catch (err) {
|
|
855
|
+
span.setStatus({
|
|
856
|
+
code: SpanStatusCode.ERROR,
|
|
857
|
+
message: String(err),
|
|
858
|
+
});
|
|
859
|
+
if (typeof err === 'string' || (err && err instanceof Error)) {
|
|
860
|
+
span.recordException(err);
|
|
861
|
+
}
|
|
862
|
+
throw err;
|
|
863
|
+
} finally {
|
|
864
|
+
span.end();
|
|
865
|
+
}
|
|
866
|
+
},
|
|
867
|
+
);
|
|
868
|
+
} else {
|
|
869
|
+
await processMessage();
|
|
672
870
|
}
|
|
673
|
-
|
|
674
|
-
|
|
871
|
+
|
|
872
|
+
if (latency !== undefined && topicType !== undefined) {
|
|
873
|
+
this.instrumentation.recordMessageLatency(topicType, latency);
|
|
675
874
|
}
|
|
676
875
|
|
|
677
876
|
return;
|
|
678
877
|
}
|
|
679
878
|
|
|
680
|
-
protected async validateReceivedMessage<T>(
|
|
681
|
-
validationFunc: () => Promise<
|
|
879
|
+
protected async validateReceivedMessage<T, M = undefined>(
|
|
880
|
+
validationFunc: () => Promise<ReceivedMessageValidationResult<T, M>>,
|
|
682
881
|
msgId: string,
|
|
683
882
|
source: PeerId,
|
|
684
883
|
topicType: TopicType,
|
|
685
|
-
): Promise<
|
|
686
|
-
let resultAndObj:
|
|
884
|
+
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
885
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
|
|
687
886
|
const timer = new Timer();
|
|
688
887
|
try {
|
|
689
888
|
resultAndObj = await validationFunc();
|
|
690
889
|
} catch (err) {
|
|
691
|
-
this.
|
|
890
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
|
|
891
|
+
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
892
|
+
msgId,
|
|
893
|
+
source: source.toString(),
|
|
894
|
+
topicType,
|
|
895
|
+
});
|
|
692
896
|
}
|
|
693
897
|
|
|
694
|
-
if (resultAndObj.result) {
|
|
898
|
+
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
695
899
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
696
900
|
}
|
|
697
901
|
|
|
698
|
-
this.node.services.pubsub.reportMessageValidationResult(
|
|
699
|
-
msgId,
|
|
700
|
-
source.toString(),
|
|
701
|
-
resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject,
|
|
702
|
-
);
|
|
902
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
|
|
703
903
|
return resultAndObj;
|
|
704
904
|
}
|
|
705
905
|
|
|
706
906
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
707
|
-
const validationFunc = async () => {
|
|
907
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
708
908
|
const tx = Tx.fromBuffer(payloadData);
|
|
709
|
-
const
|
|
710
|
-
|
|
909
|
+
const isValid = await this.validatePropagatedTx(tx, source);
|
|
910
|
+
if (!isValid) {
|
|
911
|
+
this.logger.trace(`Rejecting invalid propagated tx`, {
|
|
912
|
+
[Attributes.P2P_ID]: source.toString(),
|
|
913
|
+
});
|
|
914
|
+
return { result: TopicValidatorResult.Reject };
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// Propagate only on pool acceptance
|
|
918
|
+
const txHash = tx.getTxHash();
|
|
919
|
+
const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
|
|
920
|
+
|
|
921
|
+
const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
|
|
922
|
+
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
923
|
+
|
|
924
|
+
this.logger.trace(`Validate propagated tx`, {
|
|
925
|
+
isValid,
|
|
926
|
+
wasAccepted,
|
|
927
|
+
wasIgnored,
|
|
928
|
+
[Attributes.P2P_ID]: source.toString(),
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
if (wasAccepted) {
|
|
932
|
+
return { result: TopicValidatorResult.Accept, obj: tx };
|
|
933
|
+
} else if (wasIgnored) {
|
|
934
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
935
|
+
} else {
|
|
936
|
+
return { result: TopicValidatorResult.Reject };
|
|
937
|
+
}
|
|
711
938
|
};
|
|
712
939
|
|
|
713
940
|
const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source, TopicType.tx);
|
|
714
|
-
if (
|
|
941
|
+
if (result !== TopicValidatorResult.Accept || !tx) {
|
|
715
942
|
return;
|
|
716
943
|
}
|
|
944
|
+
|
|
945
|
+
// Tx was accepted into pool and will be propagated - just log and record metrics
|
|
717
946
|
const txHash = tx.getTxHash();
|
|
718
947
|
const txHashString = txHash.toString();
|
|
719
948
|
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
@@ -721,126 +950,386 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
721
950
|
txHash: txHashString,
|
|
722
951
|
});
|
|
723
952
|
|
|
724
|
-
|
|
725
|
-
this.logger.debug(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
await this.mempools.txPool.addTxs([tx]);
|
|
953
|
+
this.instrumentation.incrementTxReceived(1);
|
|
730
954
|
}
|
|
731
955
|
|
|
732
956
|
/**
|
|
733
|
-
* Process
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
* @param attestation - The attestation to process.
|
|
957
|
+
* Process a checkpoint attestation from a peer.
|
|
958
|
+
* Validates the attestation and adds it to the pool.
|
|
737
959
|
*/
|
|
738
|
-
private async
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
});
|
|
746
|
-
return { result, obj: attestation };
|
|
747
|
-
};
|
|
748
|
-
|
|
749
|
-
const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
|
|
750
|
-
validationFunc,
|
|
960
|
+
private async processCheckpointAttestationFromPeer(
|
|
961
|
+
payloadData: Buffer,
|
|
962
|
+
msgId: string,
|
|
963
|
+
source: PeerId,
|
|
964
|
+
): Promise<void> {
|
|
965
|
+
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
966
|
+
() => this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)),
|
|
751
967
|
msgId,
|
|
752
968
|
source,
|
|
753
|
-
TopicType.
|
|
969
|
+
TopicType.checkpoint_attestation,
|
|
754
970
|
);
|
|
755
|
-
|
|
971
|
+
|
|
972
|
+
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
756
973
|
return;
|
|
757
974
|
}
|
|
758
|
-
|
|
759
|
-
|
|
975
|
+
|
|
976
|
+
this.logger.verbose(
|
|
977
|
+
`Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
760
978
|
{
|
|
761
|
-
p2pMessageIdentifier: await attestation.
|
|
762
|
-
slot: attestation.slotNumber
|
|
979
|
+
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
980
|
+
slot: attestation.slotNumber,
|
|
763
981
|
archive: attestation.archive.toString(),
|
|
764
982
|
source: source.toString(),
|
|
765
983
|
},
|
|
766
984
|
);
|
|
767
|
-
await this.mempools.attestationPool!.addAttestations([attestation]);
|
|
768
985
|
}
|
|
769
986
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
987
|
+
/** Validates a checkpoint attestation and adds it to the pool. Penalizes the peer if validation fails. */
|
|
988
|
+
@trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation) => ({
|
|
989
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
990
|
+
}))
|
|
991
|
+
protected async validateAndStoreCheckpointAttestation(
|
|
992
|
+
peerId: PeerId,
|
|
993
|
+
attestation: CheckpointAttestation,
|
|
994
|
+
): Promise<ReceivedMessageValidationResult<CheckpointAttestation>> {
|
|
995
|
+
const validationResult = await this.checkpointAttestationValidator.validate(attestation);
|
|
996
|
+
|
|
997
|
+
if (validationResult.result === 'reject') {
|
|
998
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
999
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1000
|
+
return { result: TopicValidatorResult.Reject };
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
if (validationResult.result === 'ignore') {
|
|
1004
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// Try to add the attestation: this handles existence check, cap check, and adding in one call
|
|
1008
|
+
// count is the number of attestations by this signer for this slot (for duplicate detection)
|
|
1009
|
+
const slot = attestation.payload.header.slotNumber;
|
|
1010
|
+
const { added, alreadyExists, count } =
|
|
1011
|
+
await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
|
|
1012
|
+
|
|
1013
|
+
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
1014
|
+
added,
|
|
1015
|
+
alreadyExists,
|
|
1016
|
+
count,
|
|
1017
|
+
[Attributes.SLOT_NUMBER]: slot.toString(),
|
|
1018
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
// Exact same attestation received, no need to re-broadcast
|
|
1022
|
+
if (alreadyExists) {
|
|
1023
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// Could not add (cap reached for signer), no need to re-broadcast
|
|
1027
|
+
if (!added) {
|
|
1028
|
+
this.logger.warn(`Dropping checkpoint attestation due to cap`, {
|
|
1029
|
+
slot: slot.toString(),
|
|
1030
|
+
archive: attestation.archive.toString(),
|
|
1031
|
+
source: peerId.toString(),
|
|
1032
|
+
attester: attestation.getSender()?.toString(),
|
|
1033
|
+
count,
|
|
777
1034
|
});
|
|
778
|
-
return { result, obj:
|
|
779
|
-
}
|
|
1035
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1036
|
+
}
|
|
780
1037
|
|
|
781
|
-
|
|
782
|
-
|
|
1038
|
+
// Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
|
|
1039
|
+
// count is the number of attestations by this signer for this slot
|
|
1040
|
+
if (count === 2) {
|
|
1041
|
+
const attester = attestation.getSender();
|
|
1042
|
+
if (attester) {
|
|
1043
|
+
this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
|
|
1044
|
+
slot: slot.toString(),
|
|
1045
|
+
archive: attestation.archive.toString(),
|
|
1046
|
+
source: peerId.toString(),
|
|
1047
|
+
attester: attester.toString(),
|
|
1048
|
+
});
|
|
1049
|
+
this.duplicateAttestationCallback?.({ slot, attester });
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// Attestation was added successfully - accept it so other nodes can also detect the equivocation
|
|
1054
|
+
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
protected async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1058
|
+
const {
|
|
1059
|
+
result,
|
|
1060
|
+
obj: block,
|
|
1061
|
+
metadata: { isEquivocated } = {},
|
|
1062
|
+
} = await this.validateReceivedMessage<BlockProposal, { isEquivocated: boolean }>(
|
|
1063
|
+
() => this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)),
|
|
783
1064
|
msgId,
|
|
784
1065
|
source,
|
|
785
1066
|
TopicType.block_proposal,
|
|
786
1067
|
);
|
|
787
|
-
|
|
1068
|
+
|
|
1069
|
+
// If not accepted or equivocated, return
|
|
1070
|
+
if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
|
|
788
1071
|
return;
|
|
789
1072
|
}
|
|
790
1073
|
|
|
791
1074
|
await this.processValidBlockProposal(block, source);
|
|
792
1075
|
}
|
|
793
1076
|
|
|
794
|
-
|
|
1077
|
+
/** Validates a block proposal. Triggers a penalization to the peer that sent it if invalid. Adds to the mempool if valid. */
|
|
1078
|
+
@trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block) => ({
|
|
1079
|
+
[Attributes.BLOCK_NUMBER]: block.blockNumber.toString(),
|
|
1080
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1081
|
+
}))
|
|
1082
|
+
protected async validateAndStoreBlockProposal(
|
|
1083
|
+
peerId: PeerId,
|
|
1084
|
+
block: BlockProposal,
|
|
1085
|
+
): Promise<ReceivedMessageValidationResult<BlockProposal, { isEquivocated: boolean }>> {
|
|
1086
|
+
const validationResult = await this.blockProposalValidator.validate(block);
|
|
1087
|
+
|
|
1088
|
+
if (validationResult.result === 'reject') {
|
|
1089
|
+
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1090
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1091
|
+
return { result: TopicValidatorResult.Reject };
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
if (validationResult.result === 'ignore') {
|
|
1095
|
+
return { result: TopicValidatorResult.Ignore, obj: block };
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1099
|
+
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1100
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1101
|
+
|
|
1102
|
+
// Duplicate proposal received, no need to re-broadcast
|
|
1103
|
+
if (alreadyExists) {
|
|
1104
|
+
this.logger.debug(`Ignoring duplicate block proposal received`, {
|
|
1105
|
+
...block.toBlockInfo(),
|
|
1106
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1107
|
+
proposer: block.getSender()?.toString(),
|
|
1108
|
+
source: peerId.toString(),
|
|
1109
|
+
});
|
|
1110
|
+
return { result: TopicValidatorResult.Ignore, obj: block, metadata: { isEquivocated } };
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1114
|
+
if (!added) {
|
|
1115
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1116
|
+
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1117
|
+
...block.toBlockInfo(),
|
|
1118
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1119
|
+
count,
|
|
1120
|
+
proposer: block.getSender()?.toString(),
|
|
1121
|
+
source: peerId.toString(),
|
|
1122
|
+
});
|
|
1123
|
+
return { result: TopicValidatorResult.Reject, metadata: { isEquivocated } };
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1127
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1128
|
+
if (isEquivocated) {
|
|
1129
|
+
const proposer = block.getSender();
|
|
1130
|
+
this.logger.warn(`Detected duplicate block proposal (equivocation) at slot ${block.slotNumber}`, {
|
|
1131
|
+
...block.toBlockInfo(),
|
|
1132
|
+
source: peerId.toString(),
|
|
1133
|
+
proposer: proposer?.toString(),
|
|
1134
|
+
});
|
|
1135
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1136
|
+
if (proposer && count === 2) {
|
|
1137
|
+
this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
|
|
1138
|
+
}
|
|
1139
|
+
return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// Otherwise, we're good to go!
|
|
1143
|
+
return { result: TopicValidatorResult.Accept, obj: block };
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
1147
|
+
// should not be here as it does not deal with p2p networking.
|
|
795
1148
|
@trackSpan('Libp2pService.processValidBlockProposal', async block => ({
|
|
796
|
-
[Attributes.SLOT_NUMBER]: block.slotNumber
|
|
1149
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber,
|
|
797
1150
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
798
|
-
[Attributes.P2P_ID]: await block.
|
|
1151
|
+
[Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
799
1152
|
}))
|
|
800
|
-
|
|
801
|
-
const slot = block.slotNumber
|
|
802
|
-
const previousSlot = slot - 1n;
|
|
1153
|
+
protected async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
|
|
1154
|
+
const slot = block.slotNumber;
|
|
803
1155
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
804
|
-
p2pMessageIdentifier: await block.
|
|
805
|
-
slot: block.slotNumber.toNumber(),
|
|
806
|
-
archive: block.archive.toString(),
|
|
1156
|
+
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
807
1157
|
source: sender.toString(),
|
|
1158
|
+
...block.toBlockInfo(),
|
|
808
1159
|
});
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
1160
|
+
|
|
1161
|
+
// Mark the txs in this proposal as protected
|
|
1162
|
+
await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
|
|
1163
|
+
|
|
1164
|
+
// Call the block received callback to validate the proposal.
|
|
1165
|
+
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1166
|
+
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1167
|
+
if (!isValid) {
|
|
1168
|
+
this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
/**
|
|
1173
|
+
* Handle a gossiped checkpoint proposal.
|
|
1174
|
+
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1175
|
+
*/
|
|
1176
|
+
protected async handleGossipedCheckpointProposal(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1177
|
+
const {
|
|
1178
|
+
result,
|
|
1179
|
+
obj: checkpoint,
|
|
1180
|
+
metadata: { isEquivocated, processBlock } = {},
|
|
1181
|
+
} = await this.validateReceivedMessage<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>(
|
|
1182
|
+
() => this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)),
|
|
1183
|
+
msgId,
|
|
1184
|
+
source,
|
|
1185
|
+
TopicType.checkpoint_proposal,
|
|
1186
|
+
);
|
|
1187
|
+
|
|
1188
|
+
// If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
|
|
1189
|
+
// TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
|
|
1190
|
+
if (processBlock && checkpoint?.getBlockProposal()) {
|
|
1191
|
+
await this.processValidBlockProposal(checkpoint.getBlockProposal()!, source);
|
|
812
1192
|
}
|
|
813
1193
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
const attestations = await this.blockReceivedCallback(block, sender);
|
|
1194
|
+
if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
818
1197
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
1198
|
+
await this.processValidCheckpointProposal(checkpoint.toCore(), source);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
|
|
1203
|
+
* its last block (if present) to the mempool if valid. Triggers equivocation detection on both.
|
|
1204
|
+
*/
|
|
1205
|
+
@trackSpan('Libp2pService.validateAndStoreCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1206
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1207
|
+
}))
|
|
1208
|
+
protected async validateAndStoreCheckpointProposal(
|
|
1209
|
+
peerId: PeerId,
|
|
1210
|
+
checkpoint: CheckpointProposal,
|
|
1211
|
+
): Promise<ReceivedMessageValidationResult<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>> {
|
|
1212
|
+
const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1213
|
+
|
|
1214
|
+
if (validationResult.result === 'reject') {
|
|
1215
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1216
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1217
|
+
return { result: TopicValidatorResult.Reject };
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
if (validationResult.result === 'ignore') {
|
|
1221
|
+
return { result: TopicValidatorResult.Ignore, obj: checkpoint };
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// Extract and try to add the block proposal first if present
|
|
1225
|
+
const blockProposal = checkpoint.getBlockProposal();
|
|
1226
|
+
let processBlock = false;
|
|
1227
|
+
if (blockProposal) {
|
|
1228
|
+
this.logger.debug(`Validating block proposal from propagated checkpoint`, {
|
|
1229
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1230
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1231
|
+
});
|
|
1232
|
+
const {
|
|
1233
|
+
result,
|
|
1234
|
+
obj,
|
|
1235
|
+
metadata: { isEquivocated } = {},
|
|
1236
|
+
} = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1237
|
+
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1238
|
+
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1239
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1240
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1241
|
+
isEquivocated,
|
|
1242
|
+
result,
|
|
827
1243
|
});
|
|
828
|
-
|
|
1244
|
+
return { result: TopicValidatorResult.Reject };
|
|
1245
|
+
} else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1246
|
+
processBlock = true;
|
|
829
1247
|
}
|
|
830
1248
|
}
|
|
1249
|
+
|
|
1250
|
+
// Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
|
|
1251
|
+
const checkpointCore = checkpoint.toCore();
|
|
1252
|
+
const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
|
|
1253
|
+
const { added, alreadyExists, count } = tryAddResult;
|
|
1254
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1255
|
+
|
|
1256
|
+
// Duplicate proposal received, do not re-broadcast
|
|
1257
|
+
if (alreadyExists) {
|
|
1258
|
+
this.logger.debug(`Ignoring duplicate checkpoint proposal received`, {
|
|
1259
|
+
...checkpoint.toCheckpointInfo(),
|
|
1260
|
+
source: peerId.toString(),
|
|
1261
|
+
});
|
|
1262
|
+
return {
|
|
1263
|
+
result: TopicValidatorResult.Ignore,
|
|
1264
|
+
obj: checkpoint,
|
|
1265
|
+
metadata: { isEquivocated, processBlock },
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1270
|
+
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1271
|
+
if (!added) {
|
|
1272
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1273
|
+
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1274
|
+
...checkpoint.toCheckpointInfo(),
|
|
1275
|
+
count,
|
|
1276
|
+
source: peerId.toString(),
|
|
1277
|
+
});
|
|
1278
|
+
return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1282
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1283
|
+
if (isEquivocated) {
|
|
1284
|
+
const proposer = checkpoint.getSender();
|
|
1285
|
+
this.logger.warn(`Detected duplicate checkpoint proposal (equivocation) at slot ${checkpoint.slotNumber}`, {
|
|
1286
|
+
...checkpoint.toCheckpointInfo(),
|
|
1287
|
+
source: peerId.toString(),
|
|
1288
|
+
proposer: proposer?.toString(),
|
|
1289
|
+
});
|
|
1290
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1291
|
+
if (proposer && count === 2) {
|
|
1292
|
+
this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
|
|
1293
|
+
}
|
|
1294
|
+
return {
|
|
1295
|
+
result: TopicValidatorResult.Accept,
|
|
1296
|
+
obj: checkpoint,
|
|
1297
|
+
metadata: { isEquivocated, processBlock },
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// Otherwise, we're good to go!
|
|
1302
|
+
return { result: TopicValidatorResult.Accept, obj: checkpoint, metadata: { processBlock, isEquivocated } };
|
|
831
1303
|
}
|
|
832
1304
|
|
|
833
1305
|
/**
|
|
834
|
-
*
|
|
835
|
-
*
|
|
1306
|
+
* Process a validated checkpoint proposal.
|
|
1307
|
+
* Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
|
|
836
1308
|
*/
|
|
837
|
-
@trackSpan('Libp2pService.
|
|
838
|
-
[Attributes.SLOT_NUMBER]:
|
|
839
|
-
[Attributes.BLOCK_ARCHIVE]:
|
|
840
|
-
[Attributes.P2P_ID]: await
|
|
1309
|
+
@trackSpan('Libp2pService.processValidCheckpointProposal', async checkpoint => ({
|
|
1310
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
|
|
1311
|
+
[Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
|
|
1312
|
+
[Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
841
1313
|
}))
|
|
842
|
-
|
|
843
|
-
|
|
1314
|
+
protected async processValidCheckpointProposal(checkpoint: CheckpointProposalCore, sender: PeerId) {
|
|
1315
|
+
const slot = checkpoint.slotNumber;
|
|
1316
|
+
this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1317
|
+
p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
|
|
1318
|
+
slot: checkpoint.slotNumber,
|
|
1319
|
+
archive: checkpoint.archive.toString(),
|
|
1320
|
+
source: sender.toString(),
|
|
1321
|
+
});
|
|
1322
|
+
|
|
1323
|
+
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1324
|
+
// to validate and potentially generate attestations
|
|
1325
|
+
const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
|
|
1326
|
+
if (attestations && attestations.length > 0) {
|
|
1327
|
+
// If the callback returned attestations, add them to the pool and propagate them
|
|
1328
|
+
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
1329
|
+
for (const attestation of attestations) {
|
|
1330
|
+
await this.propagate(attestation);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
844
1333
|
}
|
|
845
1334
|
|
|
846
1335
|
/**
|
|
@@ -848,36 +1337,89 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
848
1337
|
* @param message - The message to propagate.
|
|
849
1338
|
*/
|
|
850
1339
|
public async propagate<T extends Gossipable>(message: T) {
|
|
851
|
-
const p2pMessageIdentifier = await message.
|
|
1340
|
+
const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
|
|
852
1341
|
this.logger.trace(`Message ${p2pMessageIdentifier} queued`, { p2pMessageIdentifier });
|
|
853
|
-
void this.
|
|
854
|
-
.
|
|
855
|
-
|
|
856
|
-
})
|
|
857
|
-
.catch(error => {
|
|
858
|
-
this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
|
|
859
|
-
});
|
|
1342
|
+
void this.sendToPeers(message).catch(error => {
|
|
1343
|
+
this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
|
|
1344
|
+
});
|
|
860
1345
|
}
|
|
861
1346
|
|
|
862
1347
|
/**
|
|
863
|
-
* Validate the requested block transactions.
|
|
1348
|
+
* Validate the requested block transactions. Allow partial returns.
|
|
864
1349
|
* @param request - The block transactions request.
|
|
865
1350
|
* @param response - The block transactions response.
|
|
866
1351
|
* @param peerId - The ID of the peer that made the request.
|
|
867
1352
|
* @returns True if the requested block transactions are valid, false otherwise.
|
|
868
1353
|
*/
|
|
869
1354
|
@trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
|
|
870
|
-
[Attributes.
|
|
1355
|
+
[Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
|
|
871
1356
|
}))
|
|
872
|
-
|
|
873
|
-
|
|
1357
|
+
protected async validateRequestedBlockTxs(
|
|
1358
|
+
request: BlockTxsRequest,
|
|
874
1359
|
response: BlockTxsResponse,
|
|
875
1360
|
peerId: PeerId,
|
|
876
1361
|
): Promise<boolean> {
|
|
877
1362
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
878
1363
|
|
|
879
1364
|
try {
|
|
880
|
-
|
|
1365
|
+
if (!response.archiveRoot.equals(request.archiveRoot)) {
|
|
1366
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1367
|
+
throw new ValidationError(
|
|
1368
|
+
`Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`,
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
if (response.txIndices.getLength() !== request.txIndices.getLength()) {
|
|
1373
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1374
|
+
throw new ValidationError(
|
|
1375
|
+
`Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`,
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// Check no duplicates and not exceeding returnable count
|
|
1380
|
+
const requestedIndices = new Set(request.txIndices.getTrueIndices());
|
|
1381
|
+
const availableIndices = new Set(response.txIndices.getTrueIndices());
|
|
1382
|
+
const maxReturnable = [...requestedIndices].filter(i => availableIndices.has(i)).length;
|
|
1383
|
+
|
|
1384
|
+
const returnedHashes = await Promise.all(response.txs.map(tx => tx.getTxHash().toString()));
|
|
1385
|
+
const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
|
|
1386
|
+
if (uniqueReturned.size !== returnedHashes.length) {
|
|
1387
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1388
|
+
throw new ValidationError(`Received duplicate txs in block txs response`);
|
|
1389
|
+
}
|
|
1390
|
+
if (response.txs.length > maxReturnable) {
|
|
1391
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1392
|
+
throw new ValidationError(
|
|
1393
|
+
`Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`,
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
// Given proposal (should have locally), ensure returned txs are valid subset and match request indices
|
|
1398
|
+
const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
|
|
1399
|
+
if (proposal) {
|
|
1400
|
+
// Build intersected indices
|
|
1401
|
+
const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
|
|
1402
|
+
|
|
1403
|
+
// Enforce subset membership and preserve increasing order by index.
|
|
1404
|
+
const hashToIndexInProposal = new Map<string, number>(
|
|
1405
|
+
proposal.txHashes.map((h, i) => [h.toString(), i] as [string, number]),
|
|
1406
|
+
);
|
|
1407
|
+
const allowedIndexSet = new Set(intersectIdx);
|
|
1408
|
+
const indices = returnedHashes.map(h => hashToIndexInProposal.get(h));
|
|
1409
|
+
const allAllowed = indices.every(idx => idx !== undefined && allowedIndexSet.has(idx));
|
|
1410
|
+
const strictlyIncreasing = indices.every((idx, i) => (i === 0 ? idx !== undefined : idx! > indices[i - 1]!));
|
|
1411
|
+
if (!allAllowed || !strictlyIncreasing) {
|
|
1412
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1413
|
+
throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
|
|
1414
|
+
}
|
|
1415
|
+
} else {
|
|
1416
|
+
// No local proposal, cannot check the membership/order of the returned txs
|
|
1417
|
+
this.logger.warn(
|
|
1418
|
+
`Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`,
|
|
1419
|
+
);
|
|
1420
|
+
return false;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
881
1423
|
await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
|
|
882
1424
|
return true;
|
|
883
1425
|
} catch (e: any) {
|
|
@@ -901,7 +1443,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
901
1443
|
* ReqRespSubProtocol.TX subprotocol validation.
|
|
902
1444
|
*
|
|
903
1445
|
* @param requestedTxHash - The collection of the txs that was requested.
|
|
904
|
-
* @param responseTx - The
|
|
1446
|
+
* @param responseTx - The collection of txs that was received as a response to the request.
|
|
905
1447
|
* @param peerId - The peer ID of the peer that sent the tx.
|
|
906
1448
|
* @returns True if the whole collection of txs is valid, false otherwise.
|
|
907
1449
|
*/
|
|
@@ -912,7 +1454,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
912
1454
|
const requested = new Set(requestedTxHash.map(h => h.toString()));
|
|
913
1455
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
914
1456
|
|
|
915
|
-
//TODO: (mralj) - this is somewhat naive implementation, if single tx is
|
|
1457
|
+
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
|
|
916
1458
|
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
917
1459
|
try {
|
|
918
1460
|
await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
|
|
@@ -928,44 +1470,86 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
928
1470
|
}
|
|
929
1471
|
}
|
|
930
1472
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1473
|
+
/**
|
|
1474
|
+
* Validates a BLOCK response.
|
|
1475
|
+
*
|
|
1476
|
+
* If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
|
|
1477
|
+
* Penalizes on block number mismatch or hash mismatch.
|
|
1478
|
+
*
|
|
1479
|
+
* @param requestedBlockNumber - The requested block number.
|
|
1480
|
+
* @param responseBlock - The block returned by the peer.
|
|
1481
|
+
* @param peerId - The peer that returned the block.
|
|
1482
|
+
* @returns True if the response is valid, false otherwise.
|
|
1483
|
+
*/
|
|
1484
|
+
@trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
|
|
1485
|
+
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
|
|
1486
|
+
}))
|
|
1487
|
+
protected async validateRequestedBlock(
|
|
1488
|
+
requestedBlockNumber: Fr,
|
|
1489
|
+
responseBlock: L2Block,
|
|
1490
|
+
peerId: PeerId,
|
|
1491
|
+
): Promise<boolean> {
|
|
1492
|
+
try {
|
|
1493
|
+
const reqNum = Number(requestedBlockNumber.toString());
|
|
1494
|
+
if (responseBlock.number !== reqNum) {
|
|
1495
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
943
1498
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1499
|
+
const local = await this.archiver.getBlock(BlockNumber(reqNum));
|
|
1500
|
+
if (!local) {
|
|
1501
|
+
// We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
|
|
1502
|
+
// TODO: Consider extending this validator to accept an expected hash or
|
|
1503
|
+
// performing quorum-based checks when using P2P syncing prior to L1 sync.
|
|
1504
|
+
this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
|
|
1505
|
+
return false;
|
|
1506
|
+
}
|
|
1507
|
+
const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
|
|
1508
|
+
if (!localHash.equals(respHash)) {
|
|
1509
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1510
|
+
return false;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
return true;
|
|
1514
|
+
} catch (e) {
|
|
1515
|
+
this.logger.warn(`Error validating requested block`, e);
|
|
1516
|
+
return false;
|
|
948
1517
|
}
|
|
1518
|
+
}
|
|
949
1519
|
|
|
1520
|
+
protected async validateRequestedTx(
|
|
1521
|
+
tx: Tx,
|
|
1522
|
+
peerId: PeerId,
|
|
1523
|
+
txValidator: TxValidator,
|
|
1524
|
+
requested?: Set<`0x${string}`>,
|
|
1525
|
+
) {
|
|
1526
|
+
const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
|
|
950
1527
|
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
951
|
-
|
|
1528
|
+
penalize(PeerErrorSeverity.MidToleranceError);
|
|
952
1529
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
953
1530
|
}
|
|
954
1531
|
|
|
955
1532
|
const { result } = await txValidator.validateTx(tx);
|
|
956
1533
|
if (result === 'invalid') {
|
|
957
|
-
|
|
1534
|
+
penalize(PeerErrorSeverity.LowToleranceError);
|
|
958
1535
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
|
|
959
1536
|
}
|
|
960
1537
|
}
|
|
961
1538
|
|
|
1539
|
+
protected createRequestedTxValidator(): TxValidator {
|
|
1540
|
+
return createTxReqRespValidator(this.proofVerifier, {
|
|
1541
|
+
l1ChainId: this.config.l1ChainId,
|
|
1542
|
+
rollupVersion: this.config.rollupVersion,
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
|
|
962
1546
|
@trackSpan('Libp2pService.validatePropagatedTx', tx => ({
|
|
963
1547
|
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
964
1548
|
}))
|
|
965
|
-
|
|
1549
|
+
protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
|
|
966
1550
|
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
967
1551
|
|
|
968
|
-
// We accept transactions if they are not expired by the next slot (checked based on the
|
|
1552
|
+
// We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
|
|
969
1553
|
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
970
1554
|
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
971
1555
|
|
|
@@ -980,7 +1564,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
980
1564
|
|
|
981
1565
|
// Double spend validator has a special case handler
|
|
982
1566
|
if (name === 'doubleSpendValidator') {
|
|
983
|
-
const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
|
|
1567
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
|
|
984
1568
|
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
985
1569
|
}
|
|
986
1570
|
|
|
@@ -990,7 +1574,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
990
1574
|
return true;
|
|
991
1575
|
}
|
|
992
1576
|
|
|
993
|
-
private async getGasFees(blockNumber:
|
|
1577
|
+
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
994
1578
|
if (blockNumber === this.feesCache?.blockNumber) {
|
|
995
1579
|
return this.feesCache.gasFees;
|
|
996
1580
|
}
|
|
@@ -1001,10 +1585,26 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1001
1585
|
return gasFees;
|
|
1002
1586
|
}
|
|
1003
1587
|
|
|
1588
|
+
/**
|
|
1589
|
+
* Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
|
|
1590
|
+
*/
|
|
1591
|
+
public getBatchTxRequesterService(): BatchTxRequesterLibP2PService {
|
|
1592
|
+
return {
|
|
1593
|
+
reqResp: this.reqresp,
|
|
1594
|
+
connectionSampler: this.reqresp.getConnectionSampler(),
|
|
1595
|
+
txValidatorConfig: {
|
|
1596
|
+
l1ChainId: this.config.l1ChainId,
|
|
1597
|
+
rollupVersion: this.config.rollupVersion,
|
|
1598
|
+
proofVerifier: this.proofVerifier,
|
|
1599
|
+
},
|
|
1600
|
+
peerScoring: this.peerManager,
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1004
1604
|
public async validate(txs: Tx[]): Promise<void> {
|
|
1005
1605
|
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1006
1606
|
|
|
1007
|
-
// We accept transactions if they are not expired by the next slot (checked based on the
|
|
1607
|
+
// We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
|
|
1008
1608
|
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1009
1609
|
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1010
1610
|
|
|
@@ -1031,13 +1631,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1031
1631
|
* @returns The message validators.
|
|
1032
1632
|
*/
|
|
1033
1633
|
private async createMessageValidators(
|
|
1034
|
-
currentBlockNumber:
|
|
1634
|
+
currentBlockNumber: BlockNumber,
|
|
1035
1635
|
nextSlotTimestamp: UInt64,
|
|
1036
1636
|
): Promise<Record<string, MessageValidator>[]> {
|
|
1037
1637
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
1038
1638
|
const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
|
|
1039
1639
|
|
|
1040
|
-
const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
|
|
1640
|
+
const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
|
|
1041
1641
|
|
|
1042
1642
|
return createTxMessageValidators(
|
|
1043
1643
|
nextSlotTimestamp,
|
|
@@ -1051,6 +1651,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1051
1651
|
this.proofVerifier,
|
|
1052
1652
|
!this.config.disableTransactions,
|
|
1053
1653
|
allowedInSetup,
|
|
1654
|
+
this.logger.getBindings(),
|
|
1054
1655
|
);
|
|
1055
1656
|
}
|
|
1056
1657
|
|
|
@@ -1099,20 +1700,23 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1099
1700
|
* @param peerId - The peer ID of the peer that sent the tx.
|
|
1100
1701
|
* @returns Severity
|
|
1101
1702
|
*/
|
|
1102
|
-
private async handleDoubleSpendFailure(tx: Tx, blockNumber:
|
|
1703
|
+
private async handleDoubleSpendFailure(tx: Tx, blockNumber: BlockNumber): Promise<PeerErrorSeverity> {
|
|
1103
1704
|
if (blockNumber <= this.config.doubleSpendSeverePeerPenaltyWindow) {
|
|
1104
1705
|
return PeerErrorSeverity.HighToleranceError;
|
|
1105
1706
|
}
|
|
1106
1707
|
|
|
1107
|
-
const snapshotValidator = new DoubleSpendTxValidator(
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1708
|
+
const snapshotValidator = new DoubleSpendTxValidator(
|
|
1709
|
+
{
|
|
1710
|
+
nullifiersExist: async (nullifiers: Buffer[]) => {
|
|
1711
|
+
const merkleTree = this.worldStateSynchronizer.getSnapshot(
|
|
1712
|
+
BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
|
|
1713
|
+
);
|
|
1714
|
+
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
1715
|
+
return indices.map(index => index !== undefined);
|
|
1716
|
+
},
|
|
1114
1717
|
},
|
|
1115
|
-
|
|
1718
|
+
this.logger.getBindings(),
|
|
1719
|
+
);
|
|
1116
1720
|
|
|
1117
1721
|
const validSnapshot = await snapshotValidator.validateTx(tx);
|
|
1118
1722
|
if (validSnapshot.result !== 'valid') {
|
|
@@ -1123,44 +1727,28 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1123
1727
|
}
|
|
1124
1728
|
|
|
1125
1729
|
/**
|
|
1126
|
-
* Validate
|
|
1730
|
+
* Validate a checkpoint attestation.
|
|
1127
1731
|
*
|
|
1128
|
-
* @param attestation - The attestation to validate.
|
|
1129
|
-
* @returns True if the attestation is valid, false otherwise.
|
|
1732
|
+
* @param attestation - The checkpoint attestation to validate.
|
|
1733
|
+
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1130
1734
|
*/
|
|
1131
|
-
@trackSpan('Libp2pService.
|
|
1132
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber
|
|
1735
|
+
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1736
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1133
1737
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1134
|
-
[Attributes.P2P_ID]: await attestation.
|
|
1738
|
+
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1135
1739
|
}))
|
|
1136
|
-
public async
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
return true;
|
|
1144
|
-
}
|
|
1740
|
+
public async validateCheckpointAttestation(
|
|
1741
|
+
peerId: PeerId,
|
|
1742
|
+
attestation: CheckpointAttestation,
|
|
1743
|
+
): Promise<P2PValidationResult> {
|
|
1744
|
+
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1145
1745
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
* @param block - The block proposal to validate.
|
|
1150
|
-
* @returns True if the block proposal is valid, false otherwise.
|
|
1151
|
-
*/
|
|
1152
|
-
@trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
|
|
1153
|
-
[Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
|
|
1154
|
-
}))
|
|
1155
|
-
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
|
|
1156
|
-
const severity = await this.blockProposalValidator.validate(block);
|
|
1157
|
-
if (severity) {
|
|
1158
|
-
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1159
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1160
|
-
return false;
|
|
1746
|
+
if (result.result === 'reject') {
|
|
1747
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1748
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1161
1749
|
}
|
|
1162
1750
|
|
|
1163
|
-
return
|
|
1751
|
+
return result;
|
|
1164
1752
|
}
|
|
1165
1753
|
|
|
1166
1754
|
public getPeerScore(peerId: PeerId): number {
|
|
@@ -1174,7 +1762,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1174
1762
|
private async sendToPeers<T extends Gossipable>(message: T) {
|
|
1175
1763
|
const parent = message.constructor as typeof Gossipable;
|
|
1176
1764
|
|
|
1177
|
-
const identifier = await message.
|
|
1765
|
+
const identifier = await message.p2pMessageLoggingIdentifier().then(i => i.toString());
|
|
1178
1766
|
this.logger.trace(`Sending message ${identifier}`, { p2pMessageIdentifier: identifier });
|
|
1179
1767
|
|
|
1180
1768
|
const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);
|