@aztec/p2p 0.0.1-fake-ceab37513c → 0.0.6-commit.a2d1860fe9
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 +52 -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 -61
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +42 -16
- 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 +114 -57
- 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 +529 -288
- 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 +33 -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 +316 -337
- 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 +11 -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 +74 -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 +209 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.js +8 -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 +878 -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 +5 -4
- 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 +30 -14
- 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 +3 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +2 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +5 -7
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +8 -26
- 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 +30 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
- 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 +2 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +10 -8
- 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 +111 -84
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +1160 -284
- 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 +471 -50
- 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 +47 -20
- 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 +21 -4
- 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 +12 -0
- package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
- package/dest/test-helpers/mock-tx-helpers.js +19 -0
- 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 -123
- package/dest/testbench/parse_log_file.d.ts +1 -1
- package/dest/testbench/testbench.d.ts +1 -1
- package/dest/testbench/testbench.js +2 -2
- 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/dest/versioning.js +2 -2
- package/package.json +19 -18
- package/src/bootstrap/bootstrap.ts +7 -4
- package/src/client/factory.ts +97 -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 +76 -21
- 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 +514 -58
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +614 -309
- 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 +369 -373
- 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 +11 -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 +87 -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 +239 -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 +1052 -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 +22 -9
- 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 +72 -24
- 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 +2 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +25 -48
- 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 +57 -0
- 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 +9 -7
- 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 +883 -286
- 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 +79 -22
- 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 +48 -21
- package/src/services/tx_collection/tx_source.ts +24 -5
- 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 +24 -0
- 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 -120
- package/src/testbench/testbench.ts +2 -2
- package/src/testbench/worker_client_manager.ts +304 -42
- package/src/util.ts +19 -3
- package/src/versioning.ts +2 -2
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -30
- 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 -190
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -25
- 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 -197
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -80
- 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 -238
- 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 -62
- 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 -256
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -253
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -283
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -72
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import {
|
|
2
|
+
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
4
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
4
|
-
import { SerialQueue } from '@aztec/foundation/queue';
|
|
5
5
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
6
6
|
import { Timer } from '@aztec/foundation/timer';
|
|
7
7
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
8
|
-
import {
|
|
9
|
-
import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
|
|
8
|
+
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
9
|
+
import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
10
10
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
11
11
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
12
12
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
13
13
|
import {
|
|
14
|
-
BlockAttestation,
|
|
15
14
|
BlockProposal,
|
|
15
|
+
CheckpointAttestation,
|
|
16
|
+
CheckpointProposal,
|
|
17
|
+
type CheckpointProposalCore,
|
|
16
18
|
type Gossipable,
|
|
17
19
|
P2PClientType,
|
|
18
20
|
P2PMessage,
|
|
21
|
+
type ValidationResult as P2PValidationResult,
|
|
19
22
|
PeerErrorSeverity,
|
|
20
23
|
TopicType,
|
|
21
24
|
createTopicString,
|
|
@@ -23,10 +26,17 @@ import {
|
|
|
23
26
|
metricsTopicStrToLabels,
|
|
24
27
|
} from '@aztec/stdlib/p2p';
|
|
25
28
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
26
|
-
import { Tx, type TxHash, type TxValidationResult } from '@aztec/stdlib/tx';
|
|
29
|
+
import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
27
30
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
28
31
|
import { compressComponentVersions } from '@aztec/stdlib/versioning';
|
|
29
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
Attributes,
|
|
34
|
+
OtelMetricsAdapter,
|
|
35
|
+
SpanStatusCode,
|
|
36
|
+
type TelemetryClient,
|
|
37
|
+
WithTracer,
|
|
38
|
+
trackSpan,
|
|
39
|
+
} from '@aztec/telemetry-client';
|
|
30
40
|
|
|
31
41
|
import {
|
|
32
42
|
type GossipSub,
|
|
@@ -34,7 +44,7 @@ import {
|
|
|
34
44
|
type GossipsubMessage,
|
|
35
45
|
gossipsub,
|
|
36
46
|
} from '@chainsafe/libp2p-gossipsub';
|
|
37
|
-
import { createPeerScoreParams
|
|
47
|
+
import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
38
48
|
import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
|
|
39
49
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
40
50
|
import { yamux } from '@chainsafe/libp2p-yamux';
|
|
@@ -49,44 +59,64 @@ import { createLibp2p } from 'libp2p';
|
|
|
49
59
|
|
|
50
60
|
import type { P2PConfig } from '../../config.js';
|
|
51
61
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
52
|
-
import {
|
|
62
|
+
import {
|
|
63
|
+
BlockProposalValidator,
|
|
64
|
+
CheckpointAttestationValidator,
|
|
65
|
+
CheckpointProposalValidator,
|
|
66
|
+
DoubleSpendTxValidator,
|
|
67
|
+
FishermanAttestationValidator,
|
|
68
|
+
getDefaultAllowedSetupFunctions,
|
|
69
|
+
} from '../../msg_validators/index.js';
|
|
53
70
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
54
|
-
import {
|
|
55
|
-
|
|
56
|
-
|
|
71
|
+
import {
|
|
72
|
+
type MessageValidator,
|
|
73
|
+
createTxMessageValidators,
|
|
74
|
+
createTxReqRespValidator,
|
|
75
|
+
} from '../../msg_validators/tx_validator/factory.js';
|
|
57
76
|
import { GossipSubEvent } from '../../types/index.js';
|
|
58
77
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
59
78
|
import { getVersions } from '../../versioning.js';
|
|
60
79
|
import { AztecDatastore } from '../data_store.js';
|
|
61
80
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
62
81
|
import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
63
|
-
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';
|
|
64
84
|
import type { PeerManagerInterface } from '../peer-manager/interface.js';
|
|
65
85
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
66
86
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
87
|
+
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
67
88
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
68
89
|
import {
|
|
69
90
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
70
91
|
type ReqRespInterface,
|
|
92
|
+
type ReqRespResponse,
|
|
71
93
|
ReqRespSubProtocol,
|
|
72
94
|
type ReqRespSubProtocolHandler,
|
|
73
95
|
type ReqRespSubProtocolHandlers,
|
|
74
96
|
type ReqRespSubProtocolValidators,
|
|
75
97
|
type SubProtocolMap,
|
|
76
98
|
ValidationError,
|
|
77
|
-
} from '../reqresp/
|
|
78
|
-
import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
|
|
79
|
-
import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
99
|
+
} from '../reqresp/index.js';
|
|
80
100
|
import {
|
|
81
101
|
AuthRequest,
|
|
102
|
+
BlockTxsRequest,
|
|
103
|
+
BlockTxsResponse,
|
|
82
104
|
StatusMessage,
|
|
83
105
|
pingHandler,
|
|
106
|
+
reqGoodbyeHandler,
|
|
84
107
|
reqRespBlockHandler,
|
|
108
|
+
reqRespBlockTxsHandler,
|
|
85
109
|
reqRespStatusHandler,
|
|
86
110
|
reqRespTxHandler,
|
|
87
|
-
} from '../reqresp/
|
|
111
|
+
} from '../reqresp/index.js';
|
|
88
112
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
89
|
-
import type {
|
|
113
|
+
import type {
|
|
114
|
+
P2PBlockReceivedCallback,
|
|
115
|
+
P2PCheckpointReceivedCallback,
|
|
116
|
+
P2PDuplicateAttestationCallback,
|
|
117
|
+
P2PService,
|
|
118
|
+
PeerDiscoveryService,
|
|
119
|
+
} from '../service.js';
|
|
90
120
|
import { P2PInstrumentation } from './instrumentation.js';
|
|
91
121
|
|
|
92
122
|
interface ValidationResult {
|
|
@@ -98,26 +128,36 @@ interface ValidationResult {
|
|
|
98
128
|
type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
|
|
99
129
|
|
|
100
130
|
// REFACTOR: Unify with the type above
|
|
101
|
-
type ReceivedMessageValidationResult<T> =
|
|
102
|
-
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject
|
|
103
|
-
| { obj?:
|
|
131
|
+
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
132
|
+
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
133
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
104
134
|
|
|
105
135
|
/**
|
|
106
136
|
* Lib P2P implementation of the P2PService interface.
|
|
107
137
|
*/
|
|
108
138
|
export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
|
|
109
|
-
private jobQueue: SerialQueue = new SerialQueue();
|
|
110
139
|
private discoveryRunningPromise?: RunningPromise;
|
|
111
140
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
112
141
|
|
|
113
142
|
// Message validators
|
|
114
|
-
private attestationValidator: AttestationValidator;
|
|
115
143
|
private blockProposalValidator: BlockProposalValidator;
|
|
144
|
+
private checkpointProposalValidator: CheckpointProposalValidator;
|
|
145
|
+
private checkpointAttestationValidator: CheckpointAttestationValidator;
|
|
116
146
|
|
|
117
147
|
private protocolVersion = '';
|
|
118
148
|
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
|
|
119
149
|
|
|
120
|
-
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;
|
|
121
161
|
|
|
122
162
|
/**
|
|
123
163
|
* Callback for when a block is received from a peer.
|
|
@@ -126,32 +166,48 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
126
166
|
*/
|
|
127
167
|
private blockReceivedCallback: P2PBlockReceivedCallback;
|
|
128
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
|
+
|
|
129
176
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
130
177
|
|
|
131
178
|
private instrumentation: P2PInstrumentation;
|
|
132
179
|
|
|
180
|
+
private telemetry: TelemetryClient;
|
|
181
|
+
|
|
182
|
+
protected logger: Logger;
|
|
183
|
+
|
|
133
184
|
constructor(
|
|
134
185
|
private clientType: T,
|
|
135
186
|
private config: P2PConfig,
|
|
136
187
|
protected node: PubSubLibp2p,
|
|
137
188
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
138
189
|
private reqresp: ReqRespInterface,
|
|
139
|
-
|
|
140
|
-
protected mempools: MemPools
|
|
141
|
-
|
|
190
|
+
protected peerManager: PeerManagerInterface,
|
|
191
|
+
protected mempools: MemPools,
|
|
192
|
+
protected archiver: L2BlockSource & ContractDataSource,
|
|
142
193
|
private epochCache: EpochCacheInterface,
|
|
143
194
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
144
195
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
145
196
|
telemetry: TelemetryClient,
|
|
146
|
-
|
|
197
|
+
logger: Logger = createLogger('p2p:libp2p_service'),
|
|
147
198
|
) {
|
|
148
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;
|
|
149
204
|
|
|
150
205
|
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
|
|
151
206
|
|
|
152
207
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
153
208
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
154
|
-
this.msgIdSeenValidators[TopicType.
|
|
209
|
+
this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
210
|
+
this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
155
211
|
|
|
156
212
|
const versions = getVersions(config);
|
|
157
213
|
this.protocolVersion = compressComponentVersions(versions);
|
|
@@ -159,22 +215,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
159
215
|
|
|
160
216
|
this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
|
|
161
217
|
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
162
|
-
this.topicStrings[TopicType.
|
|
163
|
-
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,
|
|
164
224
|
this.protocolVersion,
|
|
165
225
|
);
|
|
166
226
|
|
|
167
|
-
this.attestationValidator = new AttestationValidator(epochCache);
|
|
168
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);
|
|
169
234
|
|
|
170
235
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
171
236
|
|
|
172
|
-
this.blockReceivedCallback = async (block: BlockProposal): Promise<
|
|
237
|
+
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
173
238
|
this.logger.debug(
|
|
174
|
-
`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber
|
|
175
|
-
{ 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() },
|
|
176
241
|
);
|
|
177
|
-
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);
|
|
178
252
|
};
|
|
179
253
|
}
|
|
180
254
|
|
|
@@ -193,7 +267,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
193
267
|
config: P2PConfig,
|
|
194
268
|
peerId: PeerId,
|
|
195
269
|
deps: {
|
|
196
|
-
mempools: MemPools
|
|
270
|
+
mempools: MemPools;
|
|
197
271
|
l2BlockSource: L2BlockSource & ContractDataSource;
|
|
198
272
|
epochCache: EpochCacheInterface;
|
|
199
273
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
@@ -220,14 +294,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
220
294
|
|
|
221
295
|
const datastore = new AztecDatastore(peerStore);
|
|
222
296
|
|
|
223
|
-
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
|
|
297
|
+
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
|
|
224
298
|
|
|
225
299
|
const peerDiscoveryService = new DiscV5Service(
|
|
226
300
|
peerId,
|
|
227
301
|
config,
|
|
228
302
|
packageVersion,
|
|
229
303
|
telemetry,
|
|
230
|
-
createLogger(`${logger.module}:discv5_service
|
|
304
|
+
createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
|
|
231
305
|
);
|
|
232
306
|
|
|
233
307
|
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
@@ -241,10 +315,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
241
315
|
const versions = getVersions(config);
|
|
242
316
|
const protocolVersion = compressComponentVersions(versions);
|
|
243
317
|
|
|
244
|
-
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
245
|
-
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
246
|
-
const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
|
|
247
|
-
|
|
248
318
|
const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
|
|
249
319
|
const directPeers = (
|
|
250
320
|
await Promise.all(
|
|
@@ -264,6 +334,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
264
334
|
|
|
265
335
|
const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
|
|
266
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
|
+
|
|
267
347
|
const node = await createLibp2p({
|
|
268
348
|
start: false,
|
|
269
349
|
peerId,
|
|
@@ -359,33 +439,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
359
439
|
scoreParams: createPeerScoreParams({
|
|
360
440
|
// IPColocation factor can be disabled for local testing - default to -5
|
|
361
441
|
IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
|
|
362
|
-
topics:
|
|
363
|
-
[txTopic]: createTopicScoreParams({
|
|
364
|
-
topicWeight: 1,
|
|
365
|
-
invalidMessageDeliveriesWeight: -20,
|
|
366
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
367
|
-
}),
|
|
368
|
-
[blockAttestationTopic]: createTopicScoreParams({
|
|
369
|
-
topicWeight: 1,
|
|
370
|
-
invalidMessageDeliveriesWeight: -20,
|
|
371
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
372
|
-
}),
|
|
373
|
-
[blockProposalTopic]: createTopicScoreParams({
|
|
374
|
-
topicWeight: 1,
|
|
375
|
-
invalidMessageDeliveriesWeight: -20,
|
|
376
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
377
|
-
}),
|
|
378
|
-
},
|
|
442
|
+
topics: topicScoreParams,
|
|
379
443
|
}),
|
|
380
444
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
381
445
|
components: (components: { connectionManager: ConnectionManager }) => ({
|
|
382
446
|
connectionManager: components.connectionManager,
|
|
383
447
|
}),
|
|
384
448
|
},
|
|
385
|
-
logger: createLibp2pComponentLogger(logger.module),
|
|
449
|
+
logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
|
|
386
450
|
});
|
|
387
451
|
|
|
388
|
-
const peerScoring = new PeerScoring(config);
|
|
452
|
+
const peerScoring = new PeerScoring(config, telemetry);
|
|
389
453
|
const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
|
|
390
454
|
|
|
391
455
|
const peerManager = new PeerManager(
|
|
@@ -401,8 +465,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
401
465
|
epochCache,
|
|
402
466
|
);
|
|
403
467
|
|
|
404
|
-
//
|
|
405
|
-
|
|
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;
|
|
406
474
|
node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
|
|
407
475
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
408
476
|
|
|
@@ -440,20 +508,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
440
508
|
}
|
|
441
509
|
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
442
510
|
|
|
443
|
-
// Start job queue, peer discovery service and libp2p node
|
|
444
|
-
this.jobQueue.start();
|
|
445
|
-
|
|
446
|
-
await this.peerManager.initializePeers();
|
|
447
|
-
if (!this.config.p2pDiscoveryDisabled) {
|
|
448
|
-
await this.peerDiscoveryService.start();
|
|
449
|
-
}
|
|
450
|
-
await this.node.start();
|
|
451
|
-
|
|
452
|
-
// Subscribe to standard GossipSub topics by default
|
|
453
|
-
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
|
|
454
|
-
this.subscribeToTopic(this.topicStrings[topic]);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
511
|
// Create request response protocol handlers
|
|
458
512
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
459
513
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
@@ -467,9 +521,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
467
521
|
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
|
|
468
522
|
};
|
|
469
523
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
524
|
+
if (!this.config.disableTransactions) {
|
|
525
|
+
const blockTxsHandler = reqRespBlockTxsHandler(
|
|
526
|
+
this.mempools.attestationPool,
|
|
527
|
+
this.archiver,
|
|
528
|
+
this.mempools.txPool,
|
|
529
|
+
);
|
|
473
530
|
requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
|
|
474
531
|
}
|
|
475
532
|
|
|
@@ -477,24 +534,41 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
477
534
|
requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
|
|
478
535
|
}
|
|
479
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
|
+
|
|
480
556
|
// add GossipSub listener
|
|
481
557
|
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
482
558
|
|
|
483
|
-
// 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
|
+
}
|
|
484
563
|
this.discoveryRunningPromise = new RunningPromise(
|
|
485
|
-
() =>
|
|
564
|
+
async () => {
|
|
565
|
+
await this.peerManager.heartbeat();
|
|
566
|
+
},
|
|
486
567
|
this.logger,
|
|
487
568
|
this.config.peerCheckIntervalMS,
|
|
488
569
|
);
|
|
489
570
|
this.discoveryRunningPromise.start();
|
|
490
571
|
|
|
491
|
-
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
492
|
-
const reqrespSubProtocolValidators = {
|
|
493
|
-
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
494
|
-
// TODO(#11336): A request validator for blocks
|
|
495
|
-
[ReqRespSubProtocol.TX]: this.validateRequestedTx.bind(this),
|
|
496
|
-
};
|
|
497
|
-
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
498
572
|
this.logger.info(`Started P2P service`, {
|
|
499
573
|
listen: this.config.listenAddress,
|
|
500
574
|
port: this.config.p2pPort,
|
|
@@ -514,9 +588,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
514
588
|
// Stop peer manager
|
|
515
589
|
this.logger.debug('Stopping peer manager...');
|
|
516
590
|
await this.peerManager.stop();
|
|
517
|
-
|
|
518
|
-
this.logger.debug('Stopping job queue...');
|
|
519
|
-
await this.jobQueue.end();
|
|
520
591
|
this.logger.debug('Stopping running promise...');
|
|
521
592
|
await this.discoveryRunningPromise?.stop();
|
|
522
593
|
this.logger.debug('Stopping peer discovery service...');
|
|
@@ -544,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
544
615
|
return this.peerManager.getPeers(includePending);
|
|
545
616
|
}
|
|
546
617
|
|
|
618
|
+
public getGossipMeshPeerCount(topicType: TopicType): number {
|
|
619
|
+
return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
|
|
620
|
+
}
|
|
621
|
+
|
|
547
622
|
private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
|
|
548
623
|
this.logger.trace(`Received PUBSUB message.`);
|
|
549
624
|
|
|
@@ -571,6 +646,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
571
646
|
return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
|
|
572
647
|
}
|
|
573
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
|
+
|
|
574
658
|
/**
|
|
575
659
|
* Get the ENR of the node
|
|
576
660
|
* @returns The ENR of the node
|
|
@@ -583,6 +667,29 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
583
667
|
this.blockReceivedCallback = callback;
|
|
584
668
|
}
|
|
585
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
|
+
|
|
586
693
|
/**
|
|
587
694
|
* Subscribes to a topic.
|
|
588
695
|
* @param topic - The topic to subscribe to.
|
|
@@ -604,7 +711,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
604
711
|
if (!this.node.services.pubsub) {
|
|
605
712
|
throw new Error('Pubsub service not available.');
|
|
606
713
|
}
|
|
607
|
-
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);
|
|
608
718
|
const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
|
|
609
719
|
return result.recipients.length;
|
|
610
720
|
}
|
|
@@ -625,12 +735,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
625
735
|
case this.topicStrings[TopicType.tx]:
|
|
626
736
|
topicType = TopicType.tx;
|
|
627
737
|
break;
|
|
628
|
-
case this.topicStrings[TopicType.block_attestation]:
|
|
629
|
-
topicType = TopicType.block_attestation;
|
|
630
|
-
break;
|
|
631
738
|
case this.topicStrings[TopicType.block_proposal]:
|
|
632
739
|
topicType = TopicType.block_proposal;
|
|
633
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;
|
|
634
747
|
default:
|
|
635
748
|
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
636
749
|
break;
|
|
@@ -649,13 +762,39 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
649
762
|
return { result: true, topicType };
|
|
650
763
|
}
|
|
651
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
|
+
|
|
652
786
|
/**
|
|
653
787
|
* Handles a new gossip message that was received by the client.
|
|
654
788
|
* @param topic - The message's topic.
|
|
655
789
|
* @param data - The message data
|
|
656
790
|
*/
|
|
657
791
|
protected async handleNewGossipMessage(msg: Message, msgId: string, source: PeerId) {
|
|
658
|
-
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
|
+
}
|
|
659
798
|
|
|
660
799
|
const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
|
|
661
800
|
|
|
@@ -663,30 +802,92 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
663
802
|
return;
|
|
664
803
|
}
|
|
665
804
|
|
|
805
|
+
// Determine topic type for attributes
|
|
666
806
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
667
|
-
|
|
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;
|
|
668
814
|
}
|
|
669
|
-
|
|
670
|
-
|
|
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();
|
|
671
870
|
}
|
|
672
|
-
|
|
673
|
-
|
|
871
|
+
|
|
872
|
+
if (latency !== undefined && topicType !== undefined) {
|
|
873
|
+
this.instrumentation.recordMessageLatency(topicType, latency);
|
|
674
874
|
}
|
|
675
875
|
|
|
676
876
|
return;
|
|
677
877
|
}
|
|
678
878
|
|
|
679
|
-
protected async validateReceivedMessage<T>(
|
|
680
|
-
validationFunc: () => Promise<ReceivedMessageValidationResult<T>>,
|
|
879
|
+
protected async validateReceivedMessage<T, M = undefined>(
|
|
880
|
+
validationFunc: () => Promise<ReceivedMessageValidationResult<T, M>>,
|
|
681
881
|
msgId: string,
|
|
682
882
|
source: PeerId,
|
|
683
883
|
topicType: TopicType,
|
|
684
|
-
): Promise<ReceivedMessageValidationResult<T>> {
|
|
685
|
-
let resultAndObj: ReceivedMessageValidationResult<T> = { result: TopicValidatorResult.Reject };
|
|
884
|
+
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
885
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
|
|
686
886
|
const timer = new Timer();
|
|
687
887
|
try {
|
|
688
888
|
resultAndObj = await validationFunc();
|
|
689
889
|
} catch (err) {
|
|
890
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
|
|
690
891
|
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
691
892
|
msgId,
|
|
692
893
|
source: source.toString(),
|
|
@@ -706,20 +907,33 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
706
907
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
707
908
|
const tx = Tx.fromBuffer(payloadData);
|
|
708
909
|
const isValid = await this.validatePropagatedTx(tx, source);
|
|
709
|
-
|
|
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));
|
|
710
923
|
|
|
711
924
|
this.logger.trace(`Validate propagated tx`, {
|
|
712
925
|
isValid,
|
|
713
|
-
|
|
926
|
+
wasAccepted,
|
|
927
|
+
wasIgnored,
|
|
714
928
|
[Attributes.P2P_ID]: source.toString(),
|
|
715
929
|
});
|
|
716
930
|
|
|
717
|
-
if (
|
|
718
|
-
return { result: TopicValidatorResult.
|
|
719
|
-
} else if (
|
|
931
|
+
if (wasAccepted) {
|
|
932
|
+
return { result: TopicValidatorResult.Accept, obj: tx };
|
|
933
|
+
} else if (wasIgnored) {
|
|
720
934
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
721
935
|
} else {
|
|
722
|
-
return { result: TopicValidatorResult.
|
|
936
|
+
return { result: TopicValidatorResult.Reject };
|
|
723
937
|
}
|
|
724
938
|
};
|
|
725
939
|
|
|
@@ -728,6 +942,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
728
942
|
return;
|
|
729
943
|
}
|
|
730
944
|
|
|
945
|
+
// Tx was accepted into pool and will be propagated - just log and record metrics
|
|
731
946
|
const txHash = tx.getTxHash();
|
|
732
947
|
const txHashString = txHash.toString();
|
|
733
948
|
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
@@ -735,152 +950,386 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
735
950
|
txHash: txHashString,
|
|
736
951
|
});
|
|
737
952
|
|
|
738
|
-
|
|
739
|
-
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
740
|
-
return;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
await this.mempools.txPool.addTxs([tx]);
|
|
953
|
+
this.instrumentation.incrementTxReceived(1);
|
|
744
954
|
}
|
|
745
955
|
|
|
746
956
|
/**
|
|
747
|
-
* Process
|
|
748
|
-
*
|
|
749
|
-
*
|
|
750
|
-
* @param attestation - The attestation to process.
|
|
957
|
+
* Process a checkpoint attestation from a peer.
|
|
958
|
+
* Validates the attestation and adds it to the pool.
|
|
751
959
|
*/
|
|
752
|
-
private async
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
this.
|
|
759
|
-
isValid,
|
|
760
|
-
exists,
|
|
761
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
762
|
-
[Attributes.P2P_ID]: source.toString(),
|
|
763
|
-
});
|
|
764
|
-
|
|
765
|
-
if (!isValid) {
|
|
766
|
-
return { result: TopicValidatorResult.Reject };
|
|
767
|
-
} else if (exists) {
|
|
768
|
-
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
769
|
-
} else {
|
|
770
|
-
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
771
|
-
}
|
|
772
|
-
};
|
|
773
|
-
|
|
774
|
-
const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
|
|
775
|
-
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)),
|
|
776
967
|
msgId,
|
|
777
968
|
source,
|
|
778
|
-
TopicType.
|
|
969
|
+
TopicType.checkpoint_attestation,
|
|
779
970
|
);
|
|
780
971
|
|
|
781
972
|
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
782
973
|
return;
|
|
783
974
|
}
|
|
784
975
|
|
|
785
|
-
this.logger.
|
|
786
|
-
`Received attestation for slot ${attestation.slotNumber
|
|
976
|
+
this.logger.verbose(
|
|
977
|
+
`Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
787
978
|
{
|
|
788
|
-
p2pMessageIdentifier: await attestation.
|
|
789
|
-
slot: attestation.slotNumber
|
|
979
|
+
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
980
|
+
slot: attestation.slotNumber,
|
|
790
981
|
archive: attestation.archive.toString(),
|
|
791
982
|
source: source.toString(),
|
|
792
983
|
},
|
|
793
984
|
);
|
|
794
|
-
|
|
795
|
-
await this.mempools.attestationPool!.addAttestations([attestation]);
|
|
796
985
|
}
|
|
797
986
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
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
|
+
}
|
|
803
1002
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
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,
|
|
809
1034
|
});
|
|
1035
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1036
|
+
}
|
|
810
1037
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
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 });
|
|
817
1050
|
}
|
|
818
|
-
}
|
|
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
|
+
}
|
|
819
1056
|
|
|
820
|
-
|
|
821
|
-
|
|
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)),
|
|
822
1064
|
msgId,
|
|
823
1065
|
source,
|
|
824
1066
|
TopicType.block_proposal,
|
|
825
1067
|
);
|
|
826
1068
|
|
|
827
|
-
|
|
1069
|
+
// If not accepted or equivocated, return
|
|
1070
|
+
if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
|
|
828
1071
|
return;
|
|
829
1072
|
}
|
|
830
1073
|
|
|
831
1074
|
await this.processValidBlockProposal(block, source);
|
|
832
1075
|
}
|
|
833
1076
|
|
|
834
|
-
|
|
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.
|
|
835
1148
|
@trackSpan('Libp2pService.processValidBlockProposal', async block => ({
|
|
836
|
-
[Attributes.SLOT_NUMBER]: block.slotNumber
|
|
1149
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber,
|
|
837
1150
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
838
|
-
[Attributes.P2P_ID]: await block.
|
|
1151
|
+
[Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
839
1152
|
}))
|
|
840
|
-
|
|
841
|
-
const slot = block.slotNumber
|
|
842
|
-
const previousSlot = slot - 1n;
|
|
1153
|
+
protected async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
|
|
1154
|
+
const slot = block.slotNumber;
|
|
843
1155
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
844
|
-
p2pMessageIdentifier: await block.
|
|
845
|
-
slot: block.slotNumber.toNumber(),
|
|
846
|
-
archive: block.archive.toString(),
|
|
1156
|
+
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
847
1157
|
source: sender.toString(),
|
|
1158
|
+
...block.toBlockInfo(),
|
|
848
1159
|
});
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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());
|
|
852
1169
|
}
|
|
1170
|
+
}
|
|
853
1171
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
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
|
+
);
|
|
858
1187
|
|
|
859
|
-
//
|
|
860
|
-
//
|
|
861
|
-
if (
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
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,
|
|
867
1243
|
});
|
|
868
|
-
|
|
1244
|
+
return { result: TopicValidatorResult.Reject };
|
|
1245
|
+
} else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1246
|
+
processBlock = true;
|
|
869
1247
|
}
|
|
870
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 } };
|
|
871
1303
|
}
|
|
872
1304
|
|
|
873
1305
|
/**
|
|
874
|
-
*
|
|
875
|
-
*
|
|
1306
|
+
* Process a validated checkpoint proposal.
|
|
1307
|
+
* Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
|
|
876
1308
|
*/
|
|
877
|
-
@trackSpan('Libp2pService.
|
|
878
|
-
[Attributes.SLOT_NUMBER]:
|
|
879
|
-
[Attributes.BLOCK_ARCHIVE]:
|
|
880
|
-
[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()),
|
|
881
1313
|
}))
|
|
882
|
-
|
|
883
|
-
|
|
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
|
+
}
|
|
884
1333
|
}
|
|
885
1334
|
|
|
886
1335
|
/**
|
|
@@ -888,15 +1337,100 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
888
1337
|
* @param message - The message to propagate.
|
|
889
1338
|
*/
|
|
890
1339
|
public async propagate<T extends Gossipable>(message: T) {
|
|
891
|
-
const p2pMessageIdentifier = await message.
|
|
1340
|
+
const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
|
|
892
1341
|
this.logger.trace(`Message ${p2pMessageIdentifier} queued`, { p2pMessageIdentifier });
|
|
893
|
-
void this.
|
|
894
|
-
.
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1342
|
+
void this.sendToPeers(message).catch(error => {
|
|
1343
|
+
this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Validate the requested block transactions. Allow partial returns.
|
|
1349
|
+
* @param request - The block transactions request.
|
|
1350
|
+
* @param response - The block transactions response.
|
|
1351
|
+
* @param peerId - The ID of the peer that made the request.
|
|
1352
|
+
* @returns True if the requested block transactions are valid, false otherwise.
|
|
1353
|
+
*/
|
|
1354
|
+
@trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
|
|
1355
|
+
[Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
|
|
1356
|
+
}))
|
|
1357
|
+
protected async validateRequestedBlockTxs(
|
|
1358
|
+
request: BlockTxsRequest,
|
|
1359
|
+
response: BlockTxsResponse,
|
|
1360
|
+
peerId: PeerId,
|
|
1361
|
+
): Promise<boolean> {
|
|
1362
|
+
const requestedTxValidator = this.createRequestedTxValidator();
|
|
1363
|
+
|
|
1364
|
+
try {
|
|
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
|
+
|
|
1423
|
+
await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
|
|
1424
|
+
return true;
|
|
1425
|
+
} catch (e: any) {
|
|
1426
|
+
if (e instanceof ValidationError) {
|
|
1427
|
+
this.logger.warn(`Failed validation for requested block txs from peer ${peerId.toString()}`);
|
|
1428
|
+
} else {
|
|
1429
|
+
this.logger.error(`Error during validation of requested block txs`, e);
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
900
1434
|
}
|
|
901
1435
|
|
|
902
1436
|
/**
|
|
@@ -909,54 +1443,113 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
909
1443
|
* ReqRespSubProtocol.TX subprotocol validation.
|
|
910
1444
|
*
|
|
911
1445
|
* @param requestedTxHash - The collection of the txs that was requested.
|
|
912
|
-
* @param responseTx - The
|
|
1446
|
+
* @param responseTx - The collection of txs that was received as a response to the request.
|
|
913
1447
|
* @param peerId - The peer ID of the peer that sent the tx.
|
|
914
1448
|
* @returns True if the whole collection of txs is valid, false otherwise.
|
|
915
1449
|
*/
|
|
916
|
-
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
|
|
917
|
-
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
918
1450
|
@trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx) => ({
|
|
919
1451
|
[Attributes.TX_HASH]: requestedTxHash.toString(),
|
|
920
1452
|
}))
|
|
921
|
-
private async
|
|
1453
|
+
private async validateRequestedTxs(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
|
|
922
1454
|
const requested = new Set(requestedTxHash.map(h => h.toString()));
|
|
1455
|
+
const requestedTxValidator = this.createRequestedTxValidator();
|
|
923
1456
|
|
|
924
|
-
|
|
925
|
-
|
|
1457
|
+
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
|
|
1458
|
+
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
926
1459
|
try {
|
|
927
|
-
await Promise.all(
|
|
928
|
-
responseTx.map(async tx => {
|
|
929
|
-
if (!requested.has(tx.getTxHash().toString())) {
|
|
930
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
931
|
-
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
const { result } = await proofValidator.validateTx(tx);
|
|
935
|
-
if (result === 'invalid') {
|
|
936
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
937
|
-
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
|
|
938
|
-
}
|
|
939
|
-
}),
|
|
940
|
-
);
|
|
1460
|
+
await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
|
|
941
1461
|
return true;
|
|
942
1462
|
} catch (e: any) {
|
|
943
1463
|
if (e instanceof ValidationError) {
|
|
944
|
-
this.logger.
|
|
1464
|
+
this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
|
|
945
1465
|
} else {
|
|
946
|
-
this.logger.
|
|
1466
|
+
this.logger.error(`Error during validation of requested txs`, e);
|
|
947
1467
|
}
|
|
948
1468
|
|
|
949
1469
|
return false;
|
|
950
1470
|
}
|
|
951
1471
|
}
|
|
952
1472
|
|
|
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
|
+
}
|
|
1498
|
+
|
|
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;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
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);
|
|
1527
|
+
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
1528
|
+
penalize(PeerErrorSeverity.MidToleranceError);
|
|
1529
|
+
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
const { result } = await txValidator.validateTx(tx);
|
|
1533
|
+
if (result === 'invalid') {
|
|
1534
|
+
penalize(PeerErrorSeverity.LowToleranceError);
|
|
1535
|
+
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
protected createRequestedTxValidator(): TxValidator {
|
|
1540
|
+
return createTxReqRespValidator(this.proofVerifier, {
|
|
1541
|
+
l1ChainId: this.config.l1ChainId,
|
|
1542
|
+
rollupVersion: this.config.rollupVersion,
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
|
|
953
1546
|
@trackSpan('Libp2pService.validatePropagatedTx', tx => ({
|
|
954
1547
|
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
955
1548
|
}))
|
|
956
|
-
|
|
1549
|
+
protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
|
|
957
1550
|
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
958
1551
|
|
|
959
|
-
// 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)
|
|
960
1553
|
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
961
1554
|
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
962
1555
|
|
|
@@ -971,7 +1564,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
971
1564
|
|
|
972
1565
|
// Double spend validator has a special case handler
|
|
973
1566
|
if (name === 'doubleSpendValidator') {
|
|
974
|
-
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
|
|
975
1568
|
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
976
1569
|
}
|
|
977
1570
|
|
|
@@ -981,7 +1574,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
981
1574
|
return true;
|
|
982
1575
|
}
|
|
983
1576
|
|
|
984
|
-
private async getGasFees(blockNumber:
|
|
1577
|
+
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
985
1578
|
if (blockNumber === this.feesCache?.blockNumber) {
|
|
986
1579
|
return this.feesCache.gasFees;
|
|
987
1580
|
}
|
|
@@ -992,10 +1585,26 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
992
1585
|
return gasFees;
|
|
993
1586
|
}
|
|
994
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
|
+
|
|
995
1604
|
public async validate(txs: Tx[]): Promise<void> {
|
|
996
1605
|
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
997
1606
|
|
|
998
|
-
// 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)
|
|
999
1608
|
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1000
1609
|
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1001
1610
|
|
|
@@ -1022,13 +1631,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1022
1631
|
* @returns The message validators.
|
|
1023
1632
|
*/
|
|
1024
1633
|
private async createMessageValidators(
|
|
1025
|
-
currentBlockNumber:
|
|
1634
|
+
currentBlockNumber: BlockNumber,
|
|
1026
1635
|
nextSlotTimestamp: UInt64,
|
|
1027
1636
|
): Promise<Record<string, MessageValidator>[]> {
|
|
1028
1637
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
1029
1638
|
const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
|
|
1030
1639
|
|
|
1031
|
-
const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
|
|
1640
|
+
const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
|
|
1032
1641
|
|
|
1033
1642
|
return createTxMessageValidators(
|
|
1034
1643
|
nextSlotTimestamp,
|
|
@@ -1037,11 +1646,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1037
1646
|
gasFees,
|
|
1038
1647
|
this.config.l1ChainId,
|
|
1039
1648
|
this.config.rollupVersion,
|
|
1040
|
-
|
|
1649
|
+
protocolContractsHash,
|
|
1041
1650
|
this.archiver,
|
|
1042
1651
|
this.proofVerifier,
|
|
1043
1652
|
!this.config.disableTransactions,
|
|
1044
1653
|
allowedInSetup,
|
|
1654
|
+
this.logger.getBindings(),
|
|
1045
1655
|
);
|
|
1046
1656
|
}
|
|
1047
1657
|
|
|
@@ -1090,20 +1700,23 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1090
1700
|
* @param peerId - The peer ID of the peer that sent the tx.
|
|
1091
1701
|
* @returns Severity
|
|
1092
1702
|
*/
|
|
1093
|
-
private async handleDoubleSpendFailure(tx: Tx, blockNumber:
|
|
1703
|
+
private async handleDoubleSpendFailure(tx: Tx, blockNumber: BlockNumber): Promise<PeerErrorSeverity> {
|
|
1094
1704
|
if (blockNumber <= this.config.doubleSpendSeverePeerPenaltyWindow) {
|
|
1095
1705
|
return PeerErrorSeverity.HighToleranceError;
|
|
1096
1706
|
}
|
|
1097
1707
|
|
|
1098
|
-
const snapshotValidator = new DoubleSpendTxValidator(
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
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
|
+
},
|
|
1105
1717
|
},
|
|
1106
|
-
|
|
1718
|
+
this.logger.getBindings(),
|
|
1719
|
+
);
|
|
1107
1720
|
|
|
1108
1721
|
const validSnapshot = await snapshotValidator.validateTx(tx);
|
|
1109
1722
|
if (validSnapshot.result !== 'valid') {
|
|
@@ -1114,44 +1727,28 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1114
1727
|
}
|
|
1115
1728
|
|
|
1116
1729
|
/**
|
|
1117
|
-
* Validate
|
|
1730
|
+
* Validate a checkpoint attestation.
|
|
1118
1731
|
*
|
|
1119
|
-
* @param attestation - The attestation to validate.
|
|
1120
|
-
* @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.
|
|
1121
1734
|
*/
|
|
1122
|
-
@trackSpan('Libp2pService.
|
|
1123
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber
|
|
1735
|
+
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1736
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1124
1737
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1125
|
-
[Attributes.P2P_ID]: await attestation.
|
|
1738
|
+
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1126
1739
|
}))
|
|
1127
|
-
public async
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
return true;
|
|
1135
|
-
}
|
|
1740
|
+
public async validateCheckpointAttestation(
|
|
1741
|
+
peerId: PeerId,
|
|
1742
|
+
attestation: CheckpointAttestation,
|
|
1743
|
+
): Promise<P2PValidationResult> {
|
|
1744
|
+
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1136
1745
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
* @param block - The block proposal to validate.
|
|
1141
|
-
* @returns True if the block proposal is valid, false otherwise.
|
|
1142
|
-
*/
|
|
1143
|
-
@trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
|
|
1144
|
-
[Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
|
|
1145
|
-
}))
|
|
1146
|
-
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
|
|
1147
|
-
const severity = await this.blockProposalValidator.validate(block);
|
|
1148
|
-
if (severity) {
|
|
1149
|
-
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1150
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1151
|
-
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);
|
|
1152
1749
|
}
|
|
1153
1750
|
|
|
1154
|
-
return
|
|
1751
|
+
return result;
|
|
1155
1752
|
}
|
|
1156
1753
|
|
|
1157
1754
|
public getPeerScore(peerId: PeerId): number {
|
|
@@ -1165,7 +1762,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1165
1762
|
private async sendToPeers<T extends Gossipable>(message: T) {
|
|
1166
1763
|
const parent = message.constructor as typeof Gossipable;
|
|
1167
1764
|
|
|
1168
|
-
const identifier = await message.
|
|
1765
|
+
const identifier = await message.p2pMessageLoggingIdentifier().then(i => i.toString());
|
|
1169
1766
|
this.logger.trace(`Sending message ${identifier}`, { p2pMessageIdentifier: identifier });
|
|
1170
1767
|
|
|
1171
1768
|
const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);
|