@aztec/p2p 0.0.1-commit.b655e406 → 0.0.1-commit.c0b82b2
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 +10 -10
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +45 -19
- package/dest/client/index.d.ts +1 -1
- package/dest/client/interface.d.ts +61 -33
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +52 -83
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +612 -318
- 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 +304 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
- package/dest/config.d.ts +95 -64
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +42 -21
- package/dest/enr/generate-enr.d.ts +1 -1
- package/dest/enr/index.d.ts +1 -1
- package/dest/errors/attestation-pool.error.d.ts +7 -0
- package/dest/errors/attestation-pool.error.d.ts.map +1 -0
- package/dest/errors/attestation-pool.error.js +12 -0
- package/dest/errors/reqresp.error.d.ts +1 -1
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/tx-pool.error.d.ts +8 -0
- package/dest/errors/tx-pool.error.d.ts.map +1 -0
- package/dest/errors/tx-pool.error.js +9 -0
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +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 +314 -335
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
- package/dest/mem_pools/tx_pool/index.d.ts +1 -2
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/index.js +0 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +6 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +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 +97 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +10 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +11 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +174 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +25 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +65 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +93 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +78 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +20 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +73 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts +6 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/index.js +5 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +211 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.js +9 -0
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +119 -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 +193 -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 +354 -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 +905 -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 +4 -4
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
- package/dest/msg_validators/tx_validator/archive_cache.d.ts +3 -3
- package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +20 -6
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +4 -3
- package/dest/msg_validators/tx_validator/data_validator.d.ts +3 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +4 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +15 -4
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +7 -6
- package/dest/msg_validators/tx_validator/factory.d.ts +120 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +228 -57
- 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 +59 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +84 -52
- 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 +4 -3
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +2 -2
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +6 -4
- package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
- package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/size_validator.js +23 -0
- package/dest/msg_validators/tx_validator/test_utils.d.ts +2 -2
- package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +23 -5
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +8 -8
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -2
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +10 -6
- package/dest/services/discv5/discV5_service.d.ts +1 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +1 -1
- package/dest/services/dummy_service.d.ts +28 -4
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +49 -1
- package/dest/services/encoding.d.ts +3 -3
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +16 -14
- package/dest/services/gossipsub/index.d.ts +3 -0
- package/dest/services/gossipsub/index.d.ts.map +1 -0
- package/dest/services/gossipsub/index.js +2 -0
- package/dest/services/gossipsub/scoring.d.ts +21 -3
- package/dest/services/gossipsub/scoring.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.js +24 -7
- package/dest/services/gossipsub/topic_score_params.d.ts +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 +112 -93
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +1158 -342
- 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 +539 -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 +60 -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 +173 -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 +473 -51
- package/dest/services/reqresp/status.d.ts +2 -2
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/service.d.ts +56 -4
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +22 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +56 -2
- package/dest/services/tx_collection/fast_tx_collection.d.ts +10 -12
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +71 -44
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_collection.js +167 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts +37 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_source.js +90 -0
- package/dest/services/tx_collection/index.d.ts +3 -1
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +2 -0
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +11 -13
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +49 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
- package/dest/services/tx_collection/proposal_tx_collector.js +50 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +9 -6
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +61 -26
- package/dest/services/tx_collection/tx_collection.d.ts +31 -18
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +79 -7
- package/dest/services/tx_collection/tx_collection_sink.d.ts +19 -9
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +26 -29
- package/dest/services/tx_collection/tx_source.d.ts +8 -3
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +19 -2
- package/dest/services/tx_file_store/config.d.ts +16 -0
- package/dest/services/tx_file_store/config.d.ts.map +1 -0
- package/dest/services/tx_file_store/config.js +22 -0
- package/dest/services/tx_file_store/index.d.ts +4 -0
- package/dest/services/tx_file_store/index.d.ts.map +1 -0
- package/dest/services/tx_file_store/index.js +3 -0
- package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
- package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
- package/dest/services/tx_file_store/instrumentation.js +29 -0
- package/dest/services/tx_file_store/tx_file_store.d.ts +48 -0
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
- package/dest/services/tx_file_store/tx_file_store.js +152 -0
- package/dest/services/tx_provider.d.ts +7 -5
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +20 -10
- 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 +7 -8
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +1 -2
- package/dest/test-helpers/mock-pubsub.d.ts +32 -6
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +105 -4
- package/dest/test-helpers/mock-tx-helpers.d.ts +2 -2
- package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -1
- package/dest/test-helpers/mock-tx-helpers.js +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +4 -3
- 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 +225 -127
- package/dest/testbench/parse_log_file.d.ts +1 -1
- package/dest/testbench/testbench.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts +51 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +226 -39
- package/dest/types/index.d.ts +1 -1
- package/dest/util.d.ts +3 -2
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +11 -2
- package/dest/versioning.d.ts +1 -1
- package/package.json +19 -18
- package/src/bootstrap/bootstrap.ts +7 -4
- package/src/client/factory.ts +85 -43
- package/src/client/interface.ts +74 -34
- package/src/client/p2p_client.ts +281 -383
- package/src/client/test/tx_proposal_collector/README.md +227 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +345 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
- package/src/config.ts +77 -30
- package/src/errors/attestation-pool.error.ts +13 -0
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +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 +367 -371
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
- package/src/mem_pools/tx_pool/index.ts +0 -1
- package/src/mem_pools/tx_pool/priority.ts +8 -1
- package/src/mem_pools/tx_pool/tx_pool.ts +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 +125 -0
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +27 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +209 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +91 -0
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +90 -0
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +31 -0
- package/src/mem_pools/tx_pool_v2/index.ts +12 -0
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +242 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +297 -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 +1083 -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/README.md +115 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +5 -5
- package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
- package/src/msg_validators/tx_validator/block_header_validator.ts +21 -8
- package/src/msg_validators/tx_validator/data_validator.ts +18 -6
- package/src/msg_validators/tx_validator/double_spend_validator.ts +15 -9
- package/src/msg_validators/tx_validator/factory.ts +375 -57
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +106 -54
- package/src/msg_validators/tx_validator/index.ts +2 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +19 -8
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +8 -4
- package/src/msg_validators/tx_validator/size_validator.ts +22 -0
- package/src/msg_validators/tx_validator/test_utils.ts +1 -1
- package/src/msg_validators/tx_validator/timestamp_validator.ts +30 -19
- package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +8 -3
- package/src/services/data_store.ts +10 -7
- package/src/services/discv5/discV5_service.ts +1 -1
- package/src/services/dummy_service.ts +65 -2
- package/src/services/encoding.ts +13 -12
- 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 -364
- 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 +678 -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 +244 -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 +82 -23
- package/src/services/service.ts +73 -5
- package/src/services/tx_collection/config.ts +84 -2
- package/src/services/tx_collection/fast_tx_collection.ts +96 -49
- package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
- package/src/services/tx_collection/file_store_tx_source.ts +117 -0
- package/src/services/tx_collection/index.ts +6 -0
- package/src/services/tx_collection/instrumentation.ts +11 -13
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +113 -0
- package/src/services/tx_collection/slow_tx_collection.ts +70 -36
- package/src/services/tx_collection/tx_collection.ts +122 -24
- package/src/services/tx_collection/tx_collection_sink.ts +30 -34
- package/src/services/tx_collection/tx_source.ts +22 -3
- package/src/services/tx_file_store/config.ts +37 -0
- package/src/services/tx_file_store/index.ts +3 -0
- package/src/services/tx_file_store/instrumentation.ts +36 -0
- package/src/services/tx_file_store/tx_file_store.ts +175 -0
- package/src/services/tx_provider.ts +29 -12
- 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 -5
- package/src/test-helpers/mock-pubsub.ts +147 -10
- package/src/test-helpers/mock-tx-helpers.ts +1 -1
- package/src/test-helpers/reqresp-nodes.ts +5 -7
- 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 +350 -125
- package/src/testbench/worker_client_manager.ts +304 -42
- package/src/util.ts +19 -3
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -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 -70
- package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.js +0 -1
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -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 -81
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,25 +1,389 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
function applyDecs2203RFactory() {
|
|
2
|
+
function createAddInitializerMethod(initializers, decoratorFinishedRef) {
|
|
3
|
+
return function addInitializer(initializer) {
|
|
4
|
+
assertNotFinished(decoratorFinishedRef, "addInitializer");
|
|
5
|
+
assertCallable(initializer, "An initializer");
|
|
6
|
+
initializers.push(initializer);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
|
|
10
|
+
var kindStr;
|
|
11
|
+
switch(kind){
|
|
12
|
+
case 1:
|
|
13
|
+
kindStr = "accessor";
|
|
14
|
+
break;
|
|
15
|
+
case 2:
|
|
16
|
+
kindStr = "method";
|
|
17
|
+
break;
|
|
18
|
+
case 3:
|
|
19
|
+
kindStr = "getter";
|
|
20
|
+
break;
|
|
21
|
+
case 4:
|
|
22
|
+
kindStr = "setter";
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
kindStr = "field";
|
|
26
|
+
}
|
|
27
|
+
var ctx = {
|
|
28
|
+
kind: kindStr,
|
|
29
|
+
name: isPrivate ? "#" + name : name,
|
|
30
|
+
static: isStatic,
|
|
31
|
+
private: isPrivate,
|
|
32
|
+
metadata: metadata
|
|
33
|
+
};
|
|
34
|
+
var decoratorFinishedRef = {
|
|
35
|
+
v: false
|
|
36
|
+
};
|
|
37
|
+
ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
|
|
38
|
+
var get, set;
|
|
39
|
+
if (kind === 0) {
|
|
40
|
+
if (isPrivate) {
|
|
41
|
+
get = desc.get;
|
|
42
|
+
set = desc.set;
|
|
43
|
+
} else {
|
|
44
|
+
get = function() {
|
|
45
|
+
return this[name];
|
|
46
|
+
};
|
|
47
|
+
set = function(v) {
|
|
48
|
+
this[name] = v;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
} else if (kind === 2) {
|
|
52
|
+
get = function() {
|
|
53
|
+
return desc.value;
|
|
54
|
+
};
|
|
55
|
+
} else {
|
|
56
|
+
if (kind === 1 || kind === 3) {
|
|
57
|
+
get = function() {
|
|
58
|
+
return desc.get.call(this);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (kind === 1 || kind === 4) {
|
|
62
|
+
set = function(v) {
|
|
63
|
+
desc.set.call(this, v);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
ctx.access = get && set ? {
|
|
68
|
+
get: get,
|
|
69
|
+
set: set
|
|
70
|
+
} : get ? {
|
|
71
|
+
get: get
|
|
72
|
+
} : {
|
|
73
|
+
set: set
|
|
74
|
+
};
|
|
75
|
+
try {
|
|
76
|
+
return dec(value, ctx);
|
|
77
|
+
} finally{
|
|
78
|
+
decoratorFinishedRef.v = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function assertNotFinished(decoratorFinishedRef, fnName) {
|
|
82
|
+
if (decoratorFinishedRef.v) {
|
|
83
|
+
throw new Error("attempted to call " + fnName + " after decoration was finished");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function assertCallable(fn, hint) {
|
|
87
|
+
if (typeof fn !== "function") {
|
|
88
|
+
throw new TypeError(hint + " must be a function");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function assertValidReturnValue(kind, value) {
|
|
92
|
+
var type = typeof value;
|
|
93
|
+
if (kind === 1) {
|
|
94
|
+
if (type !== "object" || value === null) {
|
|
95
|
+
throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
|
|
96
|
+
}
|
|
97
|
+
if (value.get !== undefined) {
|
|
98
|
+
assertCallable(value.get, "accessor.get");
|
|
99
|
+
}
|
|
100
|
+
if (value.set !== undefined) {
|
|
101
|
+
assertCallable(value.set, "accessor.set");
|
|
102
|
+
}
|
|
103
|
+
if (value.init !== undefined) {
|
|
104
|
+
assertCallable(value.init, "accessor.init");
|
|
105
|
+
}
|
|
106
|
+
} else if (type !== "function") {
|
|
107
|
+
var hint;
|
|
108
|
+
if (kind === 0) {
|
|
109
|
+
hint = "field";
|
|
110
|
+
} else if (kind === 10) {
|
|
111
|
+
hint = "class";
|
|
112
|
+
} else {
|
|
113
|
+
hint = "method";
|
|
114
|
+
}
|
|
115
|
+
throw new TypeError(hint + " decorators must return a function or void 0");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
|
|
119
|
+
var decs = decInfo[0];
|
|
120
|
+
var desc, init, value;
|
|
121
|
+
if (isPrivate) {
|
|
122
|
+
if (kind === 0 || kind === 1) {
|
|
123
|
+
desc = {
|
|
124
|
+
get: decInfo[3],
|
|
125
|
+
set: decInfo[4]
|
|
126
|
+
};
|
|
127
|
+
} else if (kind === 3) {
|
|
128
|
+
desc = {
|
|
129
|
+
get: decInfo[3]
|
|
130
|
+
};
|
|
131
|
+
} else if (kind === 4) {
|
|
132
|
+
desc = {
|
|
133
|
+
set: decInfo[3]
|
|
134
|
+
};
|
|
135
|
+
} else {
|
|
136
|
+
desc = {
|
|
137
|
+
value: decInfo[3]
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
} else if (kind !== 0) {
|
|
141
|
+
desc = Object.getOwnPropertyDescriptor(base, name);
|
|
142
|
+
}
|
|
143
|
+
if (kind === 1) {
|
|
144
|
+
value = {
|
|
145
|
+
get: desc.get,
|
|
146
|
+
set: desc.set
|
|
147
|
+
};
|
|
148
|
+
} else if (kind === 2) {
|
|
149
|
+
value = desc.value;
|
|
150
|
+
} else if (kind === 3) {
|
|
151
|
+
value = desc.get;
|
|
152
|
+
} else if (kind === 4) {
|
|
153
|
+
value = desc.set;
|
|
154
|
+
}
|
|
155
|
+
var newValue, get, set;
|
|
156
|
+
if (typeof decs === "function") {
|
|
157
|
+
newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
158
|
+
if (newValue !== void 0) {
|
|
159
|
+
assertValidReturnValue(kind, newValue);
|
|
160
|
+
if (kind === 0) {
|
|
161
|
+
init = newValue;
|
|
162
|
+
} else if (kind === 1) {
|
|
163
|
+
init = newValue.init;
|
|
164
|
+
get = newValue.get || value.get;
|
|
165
|
+
set = newValue.set || value.set;
|
|
166
|
+
value = {
|
|
167
|
+
get: get,
|
|
168
|
+
set: set
|
|
169
|
+
};
|
|
170
|
+
} else {
|
|
171
|
+
value = newValue;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
for(var i = decs.length - 1; i >= 0; i--){
|
|
176
|
+
var dec = decs[i];
|
|
177
|
+
newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
178
|
+
if (newValue !== void 0) {
|
|
179
|
+
assertValidReturnValue(kind, newValue);
|
|
180
|
+
var newInit;
|
|
181
|
+
if (kind === 0) {
|
|
182
|
+
newInit = newValue;
|
|
183
|
+
} else if (kind === 1) {
|
|
184
|
+
newInit = newValue.init;
|
|
185
|
+
get = newValue.get || value.get;
|
|
186
|
+
set = newValue.set || value.set;
|
|
187
|
+
value = {
|
|
188
|
+
get: get,
|
|
189
|
+
set: set
|
|
190
|
+
};
|
|
191
|
+
} else {
|
|
192
|
+
value = newValue;
|
|
193
|
+
}
|
|
194
|
+
if (newInit !== void 0) {
|
|
195
|
+
if (init === void 0) {
|
|
196
|
+
init = newInit;
|
|
197
|
+
} else if (typeof init === "function") {
|
|
198
|
+
init = [
|
|
199
|
+
init,
|
|
200
|
+
newInit
|
|
201
|
+
];
|
|
202
|
+
} else {
|
|
203
|
+
init.push(newInit);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (kind === 0 || kind === 1) {
|
|
210
|
+
if (init === void 0) {
|
|
211
|
+
init = function(instance, init) {
|
|
212
|
+
return init;
|
|
213
|
+
};
|
|
214
|
+
} else if (typeof init !== "function") {
|
|
215
|
+
var ownInitializers = init;
|
|
216
|
+
init = function(instance, init) {
|
|
217
|
+
var value = init;
|
|
218
|
+
for(var i = 0; i < ownInitializers.length; i++){
|
|
219
|
+
value = ownInitializers[i].call(instance, value);
|
|
220
|
+
}
|
|
221
|
+
return value;
|
|
222
|
+
};
|
|
223
|
+
} else {
|
|
224
|
+
var originalInitializer = init;
|
|
225
|
+
init = function(instance, init) {
|
|
226
|
+
return originalInitializer.call(instance, init);
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
ret.push(init);
|
|
230
|
+
}
|
|
231
|
+
if (kind !== 0) {
|
|
232
|
+
if (kind === 1) {
|
|
233
|
+
desc.get = value.get;
|
|
234
|
+
desc.set = value.set;
|
|
235
|
+
} else if (kind === 2) {
|
|
236
|
+
desc.value = value;
|
|
237
|
+
} else if (kind === 3) {
|
|
238
|
+
desc.get = value;
|
|
239
|
+
} else if (kind === 4) {
|
|
240
|
+
desc.set = value;
|
|
241
|
+
}
|
|
242
|
+
if (isPrivate) {
|
|
243
|
+
if (kind === 1) {
|
|
244
|
+
ret.push(function(instance, args) {
|
|
245
|
+
return value.get.call(instance, args);
|
|
246
|
+
});
|
|
247
|
+
ret.push(function(instance, args) {
|
|
248
|
+
return value.set.call(instance, args);
|
|
249
|
+
});
|
|
250
|
+
} else if (kind === 2) {
|
|
251
|
+
ret.push(value);
|
|
252
|
+
} else {
|
|
253
|
+
ret.push(function(instance, args) {
|
|
254
|
+
return value.call(instance, args);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
Object.defineProperty(base, name, desc);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function applyMemberDecs(Class, decInfos, metadata) {
|
|
263
|
+
var ret = [];
|
|
264
|
+
var protoInitializers;
|
|
265
|
+
var staticInitializers;
|
|
266
|
+
var existingProtoNonFields = new Map();
|
|
267
|
+
var existingStaticNonFields = new Map();
|
|
268
|
+
for(var i = 0; i < decInfos.length; i++){
|
|
269
|
+
var decInfo = decInfos[i];
|
|
270
|
+
if (!Array.isArray(decInfo)) continue;
|
|
271
|
+
var kind = decInfo[1];
|
|
272
|
+
var name = decInfo[2];
|
|
273
|
+
var isPrivate = decInfo.length > 3;
|
|
274
|
+
var isStatic = kind >= 5;
|
|
275
|
+
var base;
|
|
276
|
+
var initializers;
|
|
277
|
+
if (isStatic) {
|
|
278
|
+
base = Class;
|
|
279
|
+
kind = kind - 5;
|
|
280
|
+
staticInitializers = staticInitializers || [];
|
|
281
|
+
initializers = staticInitializers;
|
|
282
|
+
} else {
|
|
283
|
+
base = Class.prototype;
|
|
284
|
+
protoInitializers = protoInitializers || [];
|
|
285
|
+
initializers = protoInitializers;
|
|
286
|
+
}
|
|
287
|
+
if (kind !== 0 && !isPrivate) {
|
|
288
|
+
var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
|
|
289
|
+
var existingKind = existingNonFields.get(name) || 0;
|
|
290
|
+
if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) {
|
|
291
|
+
throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
|
|
292
|
+
} else if (!existingKind && kind > 2) {
|
|
293
|
+
existingNonFields.set(name, kind);
|
|
294
|
+
} else {
|
|
295
|
+
existingNonFields.set(name, true);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
|
|
299
|
+
}
|
|
300
|
+
pushInitializers(ret, protoInitializers);
|
|
301
|
+
pushInitializers(ret, staticInitializers);
|
|
302
|
+
return ret;
|
|
303
|
+
}
|
|
304
|
+
function pushInitializers(ret, initializers) {
|
|
305
|
+
if (initializers) {
|
|
306
|
+
ret.push(function(instance) {
|
|
307
|
+
for(var i = 0; i < initializers.length; i++){
|
|
308
|
+
initializers[i].call(instance);
|
|
309
|
+
}
|
|
310
|
+
return instance;
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function applyClassDecs(targetClass, classDecs, metadata) {
|
|
315
|
+
if (classDecs.length > 0) {
|
|
316
|
+
var initializers = [];
|
|
317
|
+
var newClass = targetClass;
|
|
318
|
+
var name = targetClass.name;
|
|
319
|
+
for(var i = classDecs.length - 1; i >= 0; i--){
|
|
320
|
+
var decoratorFinishedRef = {
|
|
321
|
+
v: false
|
|
322
|
+
};
|
|
323
|
+
try {
|
|
324
|
+
var nextNewClass = classDecs[i](newClass, {
|
|
325
|
+
kind: "class",
|
|
326
|
+
name: name,
|
|
327
|
+
addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
|
|
328
|
+
metadata
|
|
329
|
+
});
|
|
330
|
+
} finally{
|
|
331
|
+
decoratorFinishedRef.v = true;
|
|
332
|
+
}
|
|
333
|
+
if (nextNewClass !== undefined) {
|
|
334
|
+
assertValidReturnValue(10, nextNewClass);
|
|
335
|
+
newClass = nextNewClass;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return [
|
|
339
|
+
defineMetadata(newClass, metadata),
|
|
340
|
+
function() {
|
|
341
|
+
for(var i = 0; i < initializers.length; i++){
|
|
342
|
+
initializers[i].call(newClass);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
];
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function defineMetadata(Class, metadata) {
|
|
349
|
+
return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
|
|
350
|
+
configurable: true,
|
|
351
|
+
enumerable: true,
|
|
352
|
+
value: metadata
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) {
|
|
356
|
+
if (parentClass !== void 0) {
|
|
357
|
+
var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
|
|
358
|
+
}
|
|
359
|
+
var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata);
|
|
360
|
+
var e = applyMemberDecs(targetClass, memberDecs, metadata);
|
|
361
|
+
if (!classDecs.length) defineMetadata(targetClass, metadata);
|
|
362
|
+
return {
|
|
363
|
+
e: e,
|
|
364
|
+
get c () {
|
|
365
|
+
return applyClassDecs(targetClass, classDecs, metadata);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
};
|
|
6
369
|
}
|
|
7
|
-
|
|
8
|
-
|
|
370
|
+
function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
371
|
+
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
372
|
+
}
|
|
373
|
+
var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto;
|
|
374
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
9
375
|
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
10
|
-
import { SerialQueue } from '@aztec/foundation/queue';
|
|
11
376
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
12
377
|
import { Timer } from '@aztec/foundation/timer';
|
|
13
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
14
378
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
15
379
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
16
|
-
import {
|
|
380
|
+
import { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PMessage, PeerErrorSeverity, TopicType, createTopicString, getTopicsForConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
|
|
17
381
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
18
382
|
import { Tx } from '@aztec/stdlib/tx';
|
|
19
383
|
import { compressComponentVersions } from '@aztec/stdlib/versioning';
|
|
20
|
-
import { Attributes, OtelMetricsAdapter, WithTracer, trackSpan } from '@aztec/telemetry-client';
|
|
384
|
+
import { Attributes, OtelMetricsAdapter, SpanStatusCode, WithTracer, trackSpan } from '@aztec/telemetry-client';
|
|
21
385
|
import { gossipsub } from '@chainsafe/libp2p-gossipsub';
|
|
22
|
-
import { createPeerScoreParams
|
|
386
|
+
import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
23
387
|
import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
|
|
24
388
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
25
389
|
import { yamux } from '@chainsafe/libp2p-yamux';
|
|
@@ -30,30 +394,51 @@ import { mplex } from '@libp2p/mplex';
|
|
|
30
394
|
import { tcp } from '@libp2p/tcp';
|
|
31
395
|
import { ENR } from '@nethermindeth/enr';
|
|
32
396
|
import { createLibp2p } from 'libp2p';
|
|
33
|
-
import {
|
|
397
|
+
import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, DoubleSpendTxValidator, FishermanAttestationValidator, getDefaultAllowedSetupFunctions } from '../../msg_validators/index.js';
|
|
34
398
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
35
|
-
import {
|
|
36
|
-
import { createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
|
|
37
|
-
import { AggregateTxValidator, DataTxValidator, DoubleSpendTxValidator, MetadataTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
|
|
399
|
+
import { createFirstStageTxValidationsForGossipedTransactions, createSecondStageTxValidationsForGossipedTransactions, createTxValidatorForBlockProposalReceivedTxs, createTxValidatorForReqResponseReceivedTxs } from '../../msg_validators/tx_validator/factory.js';
|
|
38
400
|
import { GossipSubEvent } from '../../types/index.js';
|
|
39
401
|
import { convertToMultiaddr } from '../../util.js';
|
|
40
402
|
import { getVersions } from '../../versioning.js';
|
|
41
403
|
import { AztecDatastore } from '../data_store.js';
|
|
42
404
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
43
405
|
import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
44
|
-
import { gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
406
|
+
import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
407
|
+
import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
|
|
45
408
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
46
409
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
47
|
-
import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/
|
|
48
|
-
import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
|
|
49
|
-
import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
50
|
-
import { pingHandler, reqRespBlockHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/protocols/index.js';
|
|
410
|
+
import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError, pingHandler, reqGoodbyeHandler, reqRespBlockHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
|
|
51
411
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
52
412
|
import { P2PInstrumentation } from './instrumentation.js';
|
|
413
|
+
_dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation)=>({
|
|
414
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString()
|
|
415
|
+
})), _dec1 = trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block)=>({
|
|
416
|
+
[Attributes.BLOCK_NUMBER]: block.blockNumber.toString(),
|
|
417
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString()
|
|
418
|
+
})), _dec2 = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
|
|
419
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber,
|
|
420
|
+
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
421
|
+
[Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then((i)=>i.toString())
|
|
422
|
+
})), _dec3 = trackSpan('Libp2pService.validateAndStoreCheckpointProposal', (_peerId, checkpoint)=>({
|
|
423
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString()
|
|
424
|
+
})), _dec4 = trackSpan('Libp2pService.processValidCheckpointProposal', async (checkpoint)=>({
|
|
425
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
|
|
426
|
+
[Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
|
|
427
|
+
[Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then((i)=>i.toString())
|
|
428
|
+
})), _dec5 = trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
|
|
429
|
+
[Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString()
|
|
430
|
+
})), _dec6 = trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
|
|
431
|
+
[Attributes.TX_HASH]: requestedTxHash.toString()
|
|
432
|
+
})), _dec7 = trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock)=>({
|
|
433
|
+
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString()
|
|
434
|
+
})), _dec8 = trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation)=>({
|
|
435
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
436
|
+
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
437
|
+
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then((i)=>i.toString())
|
|
438
|
+
}));
|
|
53
439
|
/**
|
|
54
440
|
* Lib P2P implementation of the P2PService interface.
|
|
55
441
|
*/ export class LibP2PService extends WithTracer {
|
|
56
|
-
clientType;
|
|
57
442
|
config;
|
|
58
443
|
node;
|
|
59
444
|
peerDiscoveryService;
|
|
@@ -64,45 +449,114 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
64
449
|
epochCache;
|
|
65
450
|
proofVerifier;
|
|
66
451
|
worldStateSynchronizer;
|
|
67
|
-
|
|
68
|
-
|
|
452
|
+
static{
|
|
453
|
+
({ e: [_initProto] } = _apply_decs_2203_r(this, [
|
|
454
|
+
[
|
|
455
|
+
_dec,
|
|
456
|
+
2,
|
|
457
|
+
"validateAndStoreCheckpointAttestation"
|
|
458
|
+
],
|
|
459
|
+
[
|
|
460
|
+
_dec1,
|
|
461
|
+
2,
|
|
462
|
+
"validateAndStoreBlockProposal"
|
|
463
|
+
],
|
|
464
|
+
[
|
|
465
|
+
_dec2,
|
|
466
|
+
2,
|
|
467
|
+
"processValidBlockProposal"
|
|
468
|
+
],
|
|
469
|
+
[
|
|
470
|
+
_dec3,
|
|
471
|
+
2,
|
|
472
|
+
"validateAndStoreCheckpointProposal"
|
|
473
|
+
],
|
|
474
|
+
[
|
|
475
|
+
_dec4,
|
|
476
|
+
2,
|
|
477
|
+
"processValidCheckpointProposal"
|
|
478
|
+
],
|
|
479
|
+
[
|
|
480
|
+
_dec5,
|
|
481
|
+
2,
|
|
482
|
+
"validateRequestedBlockTxs"
|
|
483
|
+
],
|
|
484
|
+
[
|
|
485
|
+
_dec6,
|
|
486
|
+
2,
|
|
487
|
+
"validateRequestedTxs"
|
|
488
|
+
],
|
|
489
|
+
[
|
|
490
|
+
_dec7,
|
|
491
|
+
2,
|
|
492
|
+
"validateRequestedBlock"
|
|
493
|
+
],
|
|
494
|
+
[
|
|
495
|
+
_dec8,
|
|
496
|
+
2,
|
|
497
|
+
"validateCheckpointAttestation"
|
|
498
|
+
]
|
|
499
|
+
], []));
|
|
500
|
+
}
|
|
69
501
|
discoveryRunningPromise;
|
|
70
502
|
msgIdSeenValidators;
|
|
71
503
|
// Message validators
|
|
72
|
-
attestationValidator;
|
|
73
504
|
blockProposalValidator;
|
|
505
|
+
checkpointProposalValidator;
|
|
506
|
+
checkpointAttestationValidator;
|
|
74
507
|
protocolVersion;
|
|
75
508
|
topicStrings;
|
|
76
509
|
feesCache;
|
|
510
|
+
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */ duplicateProposalCallback;
|
|
511
|
+
/** Callback invoked when a duplicate attestation is detected (triggers slashing). */ duplicateAttestationCallback;
|
|
77
512
|
/**
|
|
78
513
|
* Callback for when a block is received from a peer.
|
|
79
514
|
* @param block - The block received from the peer.
|
|
80
515
|
* @returns The attestation for the block, if any.
|
|
81
516
|
*/ blockReceivedCallback;
|
|
517
|
+
/**
|
|
518
|
+
* Callback for when a checkpoint proposal is received from a peer.
|
|
519
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
520
|
+
* @returns The attestations for the checkpoint, if any.
|
|
521
|
+
*/ checkpointReceivedCallback;
|
|
82
522
|
gossipSubEventHandler;
|
|
83
523
|
instrumentation;
|
|
84
|
-
|
|
85
|
-
|
|
524
|
+
telemetry;
|
|
525
|
+
logger;
|
|
526
|
+
constructor(config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
|
|
527
|
+
super(telemetry, 'LibP2PService'), this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.msgIdSeenValidators = (_initProto(this), {}), this.protocolVersion = '', this.topicStrings = {};
|
|
528
|
+
this.telemetry = telemetry;
|
|
529
|
+
// Create child logger with fisherman prefix if in fisherman mode
|
|
530
|
+
this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
|
|
86
531
|
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
|
|
87
532
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
88
533
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
89
|
-
this.msgIdSeenValidators[TopicType.
|
|
534
|
+
this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
535
|
+
this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
90
536
|
const versions = getVersions(config);
|
|
91
537
|
this.protocolVersion = compressComponentVersions(versions);
|
|
92
538
|
logger.info(`Started libp2p service with protocol version ${this.protocolVersion}`);
|
|
93
539
|
this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
|
|
94
540
|
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
95
|
-
this.topicStrings[TopicType.
|
|
96
|
-
this.
|
|
541
|
+
this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(TopicType.checkpoint_proposal, this.protocolVersion);
|
|
542
|
+
this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(TopicType.checkpoint_attestation, this.protocolVersion);
|
|
97
543
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, {
|
|
98
544
|
txsPermitted: !config.disableTransactions
|
|
99
545
|
});
|
|
546
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
547
|
+
txsPermitted: !config.disableTransactions
|
|
548
|
+
});
|
|
549
|
+
this.checkpointAttestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry) : new CheckpointAttestationValidator(epochCache);
|
|
100
550
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
101
551
|
this.blockReceivedCallback = async (block)=>{
|
|
102
|
-
this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber
|
|
103
|
-
p2pMessageIdentifier: await block.
|
|
552
|
+
this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`, {
|
|
553
|
+
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier()
|
|
104
554
|
});
|
|
105
|
-
return
|
|
555
|
+
return false;
|
|
556
|
+
};
|
|
557
|
+
this.checkpointReceivedCallback = (checkpoint)=>{
|
|
558
|
+
this.logger.debug(`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`);
|
|
559
|
+
return Promise.resolve(undefined);
|
|
106
560
|
};
|
|
107
561
|
}
|
|
108
562
|
updateConfig(config) {
|
|
@@ -113,13 +567,13 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
113
567
|
* @param config - The configuration to use when creating the service.
|
|
114
568
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
115
569
|
* @returns The new service.
|
|
116
|
-
*/ static async new(
|
|
570
|
+
*/ static async new(config, peerId, deps) {
|
|
117
571
|
const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, telemetry, logger, packageVersion } = deps;
|
|
118
572
|
const { p2pPort, maxPeerCount, listenAddress } = config;
|
|
119
573
|
const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
|
|
120
574
|
const datastore = new AztecDatastore(peerStore);
|
|
121
|
-
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
|
|
122
|
-
const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service
|
|
575
|
+
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
|
|
576
|
+
const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`, logger.getBindings()));
|
|
123
577
|
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
124
578
|
const bootstrapNodes = [
|
|
125
579
|
...config.privatePeers,
|
|
@@ -133,9 +587,6 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
133
587
|
}
|
|
134
588
|
const versions = getVersions(config);
|
|
135
589
|
const protocolVersion = compressComponentVersions(versions);
|
|
136
|
-
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
137
|
-
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
138
|
-
const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
|
|
139
590
|
const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
|
|
140
591
|
const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
141
592
|
const peerId = await enr.peerId();
|
|
@@ -153,6 +604,15 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
153
604
|
const announceTcpMultiaddr = config.p2pIp ? [
|
|
154
605
|
convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
|
|
155
606
|
] : [];
|
|
607
|
+
// Create dynamic topic score params based on network configuration
|
|
608
|
+
const l1Constants = epochCache.getL1Constants();
|
|
609
|
+
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
610
|
+
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
611
|
+
heartbeatIntervalMs: config.gossipsubInterval,
|
|
612
|
+
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
613
|
+
blockDurationMs: config.blockDurationMs,
|
|
614
|
+
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot
|
|
615
|
+
});
|
|
156
616
|
const node = await createLibp2p({
|
|
157
617
|
start: false,
|
|
158
618
|
peerId,
|
|
@@ -253,38 +713,26 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
253
713
|
scoreParams: createPeerScoreParams({
|
|
254
714
|
// IPColocation factor can be disabled for local testing - default to -5
|
|
255
715
|
IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
|
|
256
|
-
topics:
|
|
257
|
-
[txTopic]: createTopicScoreParams({
|
|
258
|
-
topicWeight: 1,
|
|
259
|
-
invalidMessageDeliveriesWeight: -20,
|
|
260
|
-
invalidMessageDeliveriesDecay: 0.5
|
|
261
|
-
}),
|
|
262
|
-
[blockAttestationTopic]: createTopicScoreParams({
|
|
263
|
-
topicWeight: 1,
|
|
264
|
-
invalidMessageDeliveriesWeight: -20,
|
|
265
|
-
invalidMessageDeliveriesDecay: 0.5
|
|
266
|
-
}),
|
|
267
|
-
[blockProposalTopic]: createTopicScoreParams({
|
|
268
|
-
topicWeight: 1,
|
|
269
|
-
invalidMessageDeliveriesWeight: -20,
|
|
270
|
-
invalidMessageDeliveriesDecay: 0.5
|
|
271
|
-
})
|
|
272
|
-
}
|
|
716
|
+
topics: topicScoreParams
|
|
273
717
|
})
|
|
274
718
|
}),
|
|
275
719
|
components: (components)=>({
|
|
276
720
|
connectionManager: components.connectionManager
|
|
277
721
|
})
|
|
278
722
|
},
|
|
279
|
-
logger: createLibp2pComponentLogger(logger.module)
|
|
723
|
+
logger: createLibp2pComponentLogger(logger.module, logger.getBindings())
|
|
280
724
|
});
|
|
281
|
-
const peerScoring = new PeerScoring(config);
|
|
725
|
+
const peerScoring = new PeerScoring(config, telemetry);
|
|
282
726
|
const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
|
|
283
727
|
const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
|
|
284
|
-
//
|
|
285
|
-
|
|
728
|
+
// Configure application-specific scoring for gossipsub.
|
|
729
|
+
// The weight scales app score to align with gossipsub thresholds:
|
|
730
|
+
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
731
|
+
// - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
|
|
732
|
+
// Note: positive topic scores can offset penalties, so alignment is best-effort.
|
|
733
|
+
node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
|
|
286
734
|
node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
287
|
-
return new LibP2PService(
|
|
735
|
+
return new LibP2PService(config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
|
|
288
736
|
}
|
|
289
737
|
/**
|
|
290
738
|
* Starts the LibP2P service.
|
|
@@ -300,17 +748,6 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
300
748
|
throw new Error('Announce address not provided.');
|
|
301
749
|
}
|
|
302
750
|
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
303
|
-
// Start job queue, peer discovery service and libp2p node
|
|
304
|
-
this.jobQueue.start();
|
|
305
|
-
await this.peerManager.initializePeers();
|
|
306
|
-
if (!this.config.p2pDiscoveryDisabled) {
|
|
307
|
-
await this.peerDiscoveryService.start();
|
|
308
|
-
}
|
|
309
|
-
await this.node.start();
|
|
310
|
-
// Subscribe to standard GossipSub topics by default
|
|
311
|
-
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)){
|
|
312
|
-
this.subscribeToTopic(this.topicStrings[topic]);
|
|
313
|
-
}
|
|
314
751
|
// Create request response protocol handlers
|
|
315
752
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
316
753
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
@@ -322,27 +759,37 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
322
759
|
[ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
|
|
323
760
|
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
|
|
324
761
|
};
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
|
|
762
|
+
if (!this.config.disableTransactions) {
|
|
763
|
+
const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.archiver, this.mempools.txPool);
|
|
328
764
|
requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
|
|
329
765
|
}
|
|
330
766
|
if (!this.config.disableTransactions) {
|
|
331
767
|
requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
|
|
332
768
|
}
|
|
333
|
-
// add GossipSub listener
|
|
334
|
-
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
335
|
-
// Start running promise for peer discovery
|
|
336
|
-
this.discoveryRunningPromise = new RunningPromise(()=>this.peerManager.heartbeat(), this.logger, this.config.peerCheckIntervalMS);
|
|
337
|
-
this.discoveryRunningPromise.start();
|
|
338
769
|
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
339
770
|
const reqrespSubProtocolValidators = {
|
|
340
771
|
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
341
|
-
// TODO(#11336): A request validator for blocks
|
|
342
772
|
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
343
|
-
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this)
|
|
773
|
+
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
774
|
+
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this)
|
|
344
775
|
};
|
|
776
|
+
await this.peerManager.initializePeers();
|
|
345
777
|
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
778
|
+
await this.node.start();
|
|
779
|
+
// Subscribe to standard GossipSub topics by default
|
|
780
|
+
for (const topic of getTopicsForConfig(this.config.disableTransactions)){
|
|
781
|
+
this.subscribeToTopic(this.topicStrings[topic]);
|
|
782
|
+
}
|
|
783
|
+
// add GossipSub listener
|
|
784
|
+
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
785
|
+
// Start running promise for peer discovery and metrics collection
|
|
786
|
+
if (!this.config.p2pDiscoveryDisabled) {
|
|
787
|
+
await this.peerDiscoveryService.start();
|
|
788
|
+
}
|
|
789
|
+
this.discoveryRunningPromise = new RunningPromise(async ()=>{
|
|
790
|
+
await this.peerManager.heartbeat();
|
|
791
|
+
}, this.logger, this.config.peerCheckIntervalMS);
|
|
792
|
+
this.discoveryRunningPromise.start();
|
|
346
793
|
this.logger.info(`Started P2P service`, {
|
|
347
794
|
listen: this.config.listenAddress,
|
|
348
795
|
port: this.config.p2pPort,
|
|
@@ -359,8 +806,6 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
359
806
|
// Stop peer manager
|
|
360
807
|
this.logger.debug('Stopping peer manager...');
|
|
361
808
|
await this.peerManager.stop();
|
|
362
|
-
this.logger.debug('Stopping job queue...');
|
|
363
|
-
await this.jobQueue.end();
|
|
364
809
|
this.logger.debug('Stopping running promise...');
|
|
365
810
|
await this.discoveryRunningPromise?.stop();
|
|
366
811
|
this.logger.debug('Stopping peer discovery service...');
|
|
@@ -380,6 +825,9 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
380
825
|
getPeers(includePending) {
|
|
381
826
|
return this.peerManager.getPeers(includePending);
|
|
382
827
|
}
|
|
828
|
+
getGossipMeshPeerCount(topicType) {
|
|
829
|
+
return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
|
|
830
|
+
}
|
|
383
831
|
handleGossipSubEvent(e) {
|
|
384
832
|
this.logger.trace(`Received PUBSUB message.`);
|
|
385
833
|
const safeJob = async ()=>{
|
|
@@ -399,6 +847,9 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
399
847
|
*/ sendBatchRequest(protocol, requests, pinnedPeerId) {
|
|
400
848
|
return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
|
|
401
849
|
}
|
|
850
|
+
sendRequestToPeer(peerId, subProtocol, payload, dialTimeout) {
|
|
851
|
+
return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
|
|
852
|
+
}
|
|
402
853
|
/**
|
|
403
854
|
* Get the ENR of the node
|
|
404
855
|
* @returns The ENR of the node
|
|
@@ -408,6 +859,22 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
408
859
|
registerBlockReceivedCallback(callback) {
|
|
409
860
|
this.blockReceivedCallback = callback;
|
|
410
861
|
}
|
|
862
|
+
registerCheckpointReceivedCallback(callback) {
|
|
863
|
+
this.checkpointReceivedCallback = callback;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Registers a callback to be invoked when a duplicate proposal is detected.
|
|
867
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
868
|
+
*/ registerDuplicateProposalCallback(callback) {
|
|
869
|
+
this.duplicateProposalCallback = callback;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Registers a callback to be invoked when a duplicate attestation is detected.
|
|
873
|
+
* A validator signing attestations for different proposals at the same slot.
|
|
874
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
875
|
+
*/ registerDuplicateAttestationCallback(callback) {
|
|
876
|
+
this.duplicateAttestationCallback = callback;
|
|
877
|
+
}
|
|
411
878
|
/**
|
|
412
879
|
* Subscribes to a topic.
|
|
413
880
|
* @param topic - The topic to subscribe to.
|
|
@@ -426,7 +893,9 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
426
893
|
if (!this.node.services.pubsub) {
|
|
427
894
|
throw new Error('Pubsub service not available.');
|
|
428
895
|
}
|
|
429
|
-
const
|
|
896
|
+
const isBlockProposal = topic === this.topicStrings[TopicType.block_proposal];
|
|
897
|
+
const traceContext = this.config.debugP2PInstrumentMessages && isBlockProposal ? this.telemetry.getTraceContext() : undefined;
|
|
898
|
+
const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages, traceContext);
|
|
430
899
|
const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
|
|
431
900
|
return result.recipients.length;
|
|
432
901
|
}
|
|
@@ -440,12 +909,15 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
440
909
|
case this.topicStrings[TopicType.tx]:
|
|
441
910
|
topicType = TopicType.tx;
|
|
442
911
|
break;
|
|
443
|
-
case this.topicStrings[TopicType.block_attestation]:
|
|
444
|
-
topicType = TopicType.block_attestation;
|
|
445
|
-
break;
|
|
446
912
|
case this.topicStrings[TopicType.block_proposal]:
|
|
447
913
|
topicType = TopicType.block_proposal;
|
|
448
914
|
break;
|
|
915
|
+
case this.topicStrings[TopicType.checkpoint_proposal]:
|
|
916
|
+
topicType = TopicType.checkpoint_proposal;
|
|
917
|
+
break;
|
|
918
|
+
case this.topicStrings[TopicType.checkpoint_attestation]:
|
|
919
|
+
topicType = TopicType.checkpoint_attestation;
|
|
920
|
+
break;
|
|
449
921
|
default:
|
|
450
922
|
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
451
923
|
break;
|
|
@@ -466,23 +938,95 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
466
938
|
};
|
|
467
939
|
}
|
|
468
940
|
/**
|
|
941
|
+
* Safely deserializes a P2PMessage from raw message data.
|
|
942
|
+
* @param msgId - The message ID.
|
|
943
|
+
* @param source - The peer ID of the message source.
|
|
944
|
+
* @param data - The raw message data.
|
|
945
|
+
* @returns The deserialized P2PMessage or undefined if deserialization fails.
|
|
946
|
+
*/ safelyDeserializeP2PMessage(msgId, source, data) {
|
|
947
|
+
try {
|
|
948
|
+
return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
|
|
949
|
+
} catch (err) {
|
|
950
|
+
this.logger.error(`Error deserializing P2PMessage`, err, {
|
|
951
|
+
msgId,
|
|
952
|
+
source: source.toString()
|
|
953
|
+
});
|
|
954
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
|
|
955
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
|
|
956
|
+
return undefined;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
469
960
|
* Handles a new gossip message that was received by the client.
|
|
470
961
|
* @param topic - The message's topic.
|
|
471
962
|
* @param data - The message data
|
|
472
963
|
*/ async handleNewGossipMessage(msg, msgId, source) {
|
|
473
|
-
const
|
|
964
|
+
const msgReceivedTime = Date.now();
|
|
965
|
+
let topicType;
|
|
966
|
+
const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
|
|
967
|
+
if (!p2pMessage) {
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
474
970
|
const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
|
|
475
971
|
if (!preValidationResult.result) {
|
|
476
972
|
return;
|
|
477
973
|
}
|
|
974
|
+
// Determine topic type for attributes
|
|
478
975
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
479
|
-
|
|
976
|
+
topicType = TopicType.tx;
|
|
977
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
978
|
+
topicType = TopicType.checkpoint_attestation;
|
|
979
|
+
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
980
|
+
topicType = TopicType.block_proposal;
|
|
981
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
982
|
+
topicType = TopicType.checkpoint_proposal;
|
|
480
983
|
}
|
|
481
|
-
|
|
482
|
-
|
|
984
|
+
// Process the message, optionally within a linked span for trace propagation
|
|
985
|
+
const processMessage = async ()=>{
|
|
986
|
+
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
987
|
+
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
988
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
989
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
990
|
+
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
991
|
+
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
992
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
993
|
+
await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
|
|
994
|
+
} else {
|
|
995
|
+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
const latency = p2pMessage.timestamp !== undefined ? msgReceivedTime - p2pMessage.timestamp.getTime() : undefined;
|
|
999
|
+
const propagatedContext = p2pMessage.traceContext ? this.telemetry.extractPropagatedContext(p2pMessage.traceContext) : undefined;
|
|
1000
|
+
if (propagatedContext) {
|
|
1001
|
+
await this.tracer.startActiveSpan('LibP2PService.processMessage', {
|
|
1002
|
+
attributes: {
|
|
1003
|
+
[Attributes.TOPIC_NAME]: topicType,
|
|
1004
|
+
[Attributes.PEER_ID]: source.toString()
|
|
1005
|
+
}
|
|
1006
|
+
}, propagatedContext, async (span)=>{
|
|
1007
|
+
try {
|
|
1008
|
+
await processMessage();
|
|
1009
|
+
span.setStatus({
|
|
1010
|
+
code: SpanStatusCode.OK
|
|
1011
|
+
});
|
|
1012
|
+
} catch (err) {
|
|
1013
|
+
span.setStatus({
|
|
1014
|
+
code: SpanStatusCode.ERROR,
|
|
1015
|
+
message: String(err)
|
|
1016
|
+
});
|
|
1017
|
+
if (typeof err === 'string' || err && err instanceof Error) {
|
|
1018
|
+
span.recordException(err);
|
|
1019
|
+
}
|
|
1020
|
+
throw err;
|
|
1021
|
+
} finally{
|
|
1022
|
+
span.end();
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
} else {
|
|
1026
|
+
await processMessage();
|
|
483
1027
|
}
|
|
484
|
-
if (
|
|
485
|
-
|
|
1028
|
+
if (latency !== undefined && topicType !== undefined) {
|
|
1029
|
+
this.instrumentation.recordMessageLatency(topicType, latency);
|
|
486
1030
|
}
|
|
487
1031
|
return;
|
|
488
1032
|
}
|
|
@@ -494,6 +1038,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
494
1038
|
try {
|
|
495
1039
|
resultAndObj = await validationFunc();
|
|
496
1040
|
} catch (err) {
|
|
1041
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
|
|
497
1042
|
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
498
1043
|
msgId,
|
|
499
1044
|
source: source.toString(),
|
|
@@ -509,26 +1054,71 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
509
1054
|
async handleGossipedTx(payloadData, msgId, source) {
|
|
510
1055
|
const validationFunc = async ()=>{
|
|
511
1056
|
const tx = Tx.fromBuffer(payloadData);
|
|
512
|
-
const
|
|
513
|
-
const
|
|
1057
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1058
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1059
|
+
// Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
|
|
1060
|
+
const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1061
|
+
const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
|
|
1062
|
+
if (!firstStageOutcome.allPassed) {
|
|
1063
|
+
const { name } = firstStageOutcome.failure;
|
|
1064
|
+
let { severity } = firstStageOutcome.failure;
|
|
1065
|
+
// Double spend validator has a special case handler. We perform more detailed examination
|
|
1066
|
+
// as to how recently the nullifier was entered into the tree and if the transaction should
|
|
1067
|
+
// have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
|
|
1068
|
+
if (name === 'doubleSpendValidator') {
|
|
1069
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1070
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1071
|
+
}
|
|
1072
|
+
this.peerManager.penalizePeer(source, severity);
|
|
1073
|
+
return {
|
|
1074
|
+
result: TopicValidatorResult.Reject
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
1078
|
+
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
1079
|
+
if (canAdd === 'ignored') {
|
|
1080
|
+
return {
|
|
1081
|
+
result: TopicValidatorResult.Ignore,
|
|
1082
|
+
obj: tx
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
// Stage 2: expensive proof verification
|
|
1086
|
+
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
1087
|
+
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
1088
|
+
if (!secondStageOutcome.allPassed) {
|
|
1089
|
+
const { severity } = secondStageOutcome.failure;
|
|
1090
|
+
this.peerManager.penalizePeer(source, severity);
|
|
1091
|
+
return {
|
|
1092
|
+
result: TopicValidatorResult.Reject
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
// Pool add: persist the tx
|
|
1096
|
+
const txHash = tx.getTxHash();
|
|
1097
|
+
const addResult = await this.mempools.txPool.addPendingTxs([
|
|
1098
|
+
tx
|
|
1099
|
+
], {
|
|
1100
|
+
source: 'gossip'
|
|
1101
|
+
});
|
|
1102
|
+
const wasAccepted = addResult.accepted.some((h)=>h.equals(txHash));
|
|
1103
|
+
const wasIgnored = addResult.ignored.some((h)=>h.equals(txHash));
|
|
514
1104
|
this.logger.trace(`Validate propagated tx`, {
|
|
515
|
-
|
|
516
|
-
|
|
1105
|
+
wasAccepted,
|
|
1106
|
+
wasIgnored,
|
|
517
1107
|
[Attributes.P2P_ID]: source.toString()
|
|
518
1108
|
});
|
|
519
|
-
if (
|
|
1109
|
+
if (wasAccepted) {
|
|
520
1110
|
return {
|
|
521
|
-
result: TopicValidatorResult.
|
|
1111
|
+
result: TopicValidatorResult.Accept,
|
|
1112
|
+
obj: tx
|
|
522
1113
|
};
|
|
523
|
-
} else if (
|
|
1114
|
+
} else if (wasIgnored) {
|
|
524
1115
|
return {
|
|
525
1116
|
result: TopicValidatorResult.Ignore,
|
|
526
1117
|
obj: tx
|
|
527
1118
|
};
|
|
528
1119
|
} else {
|
|
529
1120
|
return {
|
|
530
|
-
result: TopicValidatorResult.
|
|
531
|
-
obj: tx
|
|
1121
|
+
result: TopicValidatorResult.Reject
|
|
532
1122
|
};
|
|
533
1123
|
}
|
|
534
1124
|
};
|
|
@@ -536,164 +1126,430 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
536
1126
|
if (result !== TopicValidatorResult.Accept || !tx) {
|
|
537
1127
|
return;
|
|
538
1128
|
}
|
|
1129
|
+
// Tx was accepted into pool and will be propagated - just log and record metrics
|
|
539
1130
|
const txHash = tx.getTxHash();
|
|
540
1131
|
const txHashString = txHash.toString();
|
|
541
1132
|
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
542
1133
|
source: source.toString(),
|
|
543
1134
|
txHash: txHashString
|
|
544
1135
|
});
|
|
545
|
-
|
|
546
|
-
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
await this.mempools.txPool.addTxs([
|
|
550
|
-
tx
|
|
551
|
-
]);
|
|
1136
|
+
this.instrumentation.incrementTxReceived(1);
|
|
552
1137
|
}
|
|
553
1138
|
/**
|
|
554
|
-
* Process
|
|
555
|
-
*
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
*/ async processAttestationFromPeer(payloadData, msgId, source) {
|
|
559
|
-
const validationFunc = async ()=>{
|
|
560
|
-
const attestation = BlockAttestation.fromBuffer(payloadData);
|
|
561
|
-
const isValid = await this.validateAttestation(source, attestation);
|
|
562
|
-
const exists = isValid && await this.mempools.attestationPool.hasAttestation(attestation);
|
|
563
|
-
this.logger.trace(`Validate propagated block attestation`, {
|
|
564
|
-
isValid,
|
|
565
|
-
exists,
|
|
566
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
567
|
-
[Attributes.P2P_ID]: source.toString()
|
|
568
|
-
});
|
|
569
|
-
if (!isValid) {
|
|
570
|
-
return {
|
|
571
|
-
result: TopicValidatorResult.Reject
|
|
572
|
-
};
|
|
573
|
-
} else if (exists) {
|
|
574
|
-
return {
|
|
575
|
-
result: TopicValidatorResult.Ignore,
|
|
576
|
-
obj: attestation
|
|
577
|
-
};
|
|
578
|
-
} else {
|
|
579
|
-
return {
|
|
580
|
-
result: TopicValidatorResult.Accept,
|
|
581
|
-
obj: attestation
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
};
|
|
585
|
-
const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_attestation);
|
|
1139
|
+
* Process a checkpoint attestation from a peer.
|
|
1140
|
+
* Validates the attestation and adds it to the pool.
|
|
1141
|
+
*/ async processCheckpointAttestationFromPeer(payloadData, msgId, source) {
|
|
1142
|
+
const { result, obj: attestation } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_attestation);
|
|
586
1143
|
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
587
1144
|
return;
|
|
588
1145
|
}
|
|
589
|
-
this.logger.
|
|
590
|
-
p2pMessageIdentifier: await attestation.
|
|
591
|
-
slot: attestation.slotNumber
|
|
1146
|
+
this.logger.verbose(`Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`, {
|
|
1147
|
+
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
1148
|
+
slot: attestation.slotNumber,
|
|
592
1149
|
archive: attestation.archive.toString(),
|
|
593
1150
|
source: source.toString()
|
|
594
1151
|
});
|
|
595
|
-
await this.mempools.attestationPool.addAttestations([
|
|
596
|
-
attestation
|
|
597
|
-
]);
|
|
598
1152
|
}
|
|
599
|
-
async
|
|
600
|
-
const
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
1153
|
+
/** Validates a checkpoint attestation and adds it to the pool. Penalizes the peer if validation fails. */ async validateAndStoreCheckpointAttestation(peerId, attestation) {
|
|
1154
|
+
const validationResult = await this.checkpointAttestationValidator.validate(attestation);
|
|
1155
|
+
if (validationResult.result === 'reject') {
|
|
1156
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1157
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1158
|
+
return {
|
|
1159
|
+
result: TopicValidatorResult.Reject
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
if (validationResult.result === 'ignore') {
|
|
1163
|
+
return {
|
|
1164
|
+
result: TopicValidatorResult.Ignore,
|
|
1165
|
+
obj: attestation
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
// Try to add the attestation: this handles existence check, cap check, and adding in one call
|
|
1169
|
+
// count is the number of attestations by this signer for this slot (for duplicate detection)
|
|
1170
|
+
const slot = attestation.payload.header.slotNumber;
|
|
1171
|
+
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
|
|
1172
|
+
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
1173
|
+
added,
|
|
1174
|
+
alreadyExists,
|
|
1175
|
+
count,
|
|
1176
|
+
[Attributes.SLOT_NUMBER]: slot.toString(),
|
|
1177
|
+
[Attributes.P2P_ID]: peerId.toString()
|
|
1178
|
+
});
|
|
1179
|
+
// Exact same attestation received, no need to re-broadcast
|
|
1180
|
+
if (alreadyExists) {
|
|
1181
|
+
return {
|
|
1182
|
+
result: TopicValidatorResult.Ignore,
|
|
1183
|
+
obj: attestation
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
// Could not add (cap reached for signer), no need to re-broadcast
|
|
1187
|
+
if (!added) {
|
|
1188
|
+
this.logger.warn(`Dropping checkpoint attestation due to cap`, {
|
|
1189
|
+
slot: slot.toString(),
|
|
1190
|
+
archive: attestation.archive.toString(),
|
|
1191
|
+
source: peerId.toString(),
|
|
1192
|
+
attester: attestation.getSender()?.toString(),
|
|
1193
|
+
count
|
|
611
1194
|
});
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
1195
|
+
return {
|
|
1196
|
+
result: TopicValidatorResult.Ignore,
|
|
1197
|
+
obj: attestation
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
// Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
|
|
1201
|
+
// count is the number of attestations by this signer for this slot
|
|
1202
|
+
if (count === 2) {
|
|
1203
|
+
const attester = attestation.getSender();
|
|
1204
|
+
if (attester) {
|
|
1205
|
+
this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
|
|
1206
|
+
slot: slot.toString(),
|
|
1207
|
+
archive: attestation.archive.toString(),
|
|
1208
|
+
source: peerId.toString(),
|
|
1209
|
+
attester: attester.toString()
|
|
1210
|
+
});
|
|
1211
|
+
this.duplicateAttestationCallback?.({
|
|
1212
|
+
slot,
|
|
1213
|
+
attester
|
|
1214
|
+
});
|
|
626
1215
|
}
|
|
1216
|
+
}
|
|
1217
|
+
// Attestation was added successfully - accept it so other nodes can also detect the equivocation
|
|
1218
|
+
return {
|
|
1219
|
+
result: TopicValidatorResult.Accept,
|
|
1220
|
+
obj: attestation
|
|
627
1221
|
};
|
|
628
|
-
|
|
629
|
-
|
|
1222
|
+
}
|
|
1223
|
+
async processBlockFromPeer(payloadData, msgId, source) {
|
|
1224
|
+
const { result, obj: block, metadata: { isEquivocated } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)), msgId, source, TopicType.block_proposal);
|
|
1225
|
+
// If not accepted or equivocated, return
|
|
1226
|
+
if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
|
|
630
1227
|
return;
|
|
631
1228
|
}
|
|
632
1229
|
await this.processValidBlockProposal(block, source);
|
|
633
1230
|
}
|
|
634
|
-
|
|
1231
|
+
/** Validates a block proposal. Triggers a penalization to the peer that sent it if invalid. Adds to the mempool if valid. */ async validateAndStoreBlockProposal(peerId, block) {
|
|
1232
|
+
const validationResult = await this.blockProposalValidator.validate(block);
|
|
1233
|
+
if (validationResult.result === 'reject') {
|
|
1234
|
+
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1235
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1236
|
+
return {
|
|
1237
|
+
result: TopicValidatorResult.Reject
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
if (validationResult.result === 'ignore') {
|
|
1241
|
+
return {
|
|
1242
|
+
result: TopicValidatorResult.Ignore,
|
|
1243
|
+
obj: block
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1247
|
+
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1248
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1249
|
+
// Duplicate proposal received, no need to re-broadcast
|
|
1250
|
+
if (alreadyExists) {
|
|
1251
|
+
this.logger.debug(`Ignoring duplicate block proposal received`, {
|
|
1252
|
+
...block.toBlockInfo(),
|
|
1253
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1254
|
+
proposer: block.getSender()?.toString(),
|
|
1255
|
+
source: peerId.toString()
|
|
1256
|
+
});
|
|
1257
|
+
return {
|
|
1258
|
+
result: TopicValidatorResult.Ignore,
|
|
1259
|
+
obj: block,
|
|
1260
|
+
metadata: {
|
|
1261
|
+
isEquivocated
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1266
|
+
if (!added) {
|
|
1267
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1268
|
+
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1269
|
+
...block.toBlockInfo(),
|
|
1270
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1271
|
+
count,
|
|
1272
|
+
proposer: block.getSender()?.toString(),
|
|
1273
|
+
source: peerId.toString()
|
|
1274
|
+
});
|
|
1275
|
+
return {
|
|
1276
|
+
result: TopicValidatorResult.Reject,
|
|
1277
|
+
metadata: {
|
|
1278
|
+
isEquivocated
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1283
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1284
|
+
if (isEquivocated) {
|
|
1285
|
+
const proposer = block.getSender();
|
|
1286
|
+
this.logger.warn(`Detected duplicate block proposal (equivocation) at slot ${block.slotNumber}`, {
|
|
1287
|
+
...block.toBlockInfo(),
|
|
1288
|
+
source: peerId.toString(),
|
|
1289
|
+
proposer: proposer?.toString()
|
|
1290
|
+
});
|
|
1291
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1292
|
+
if (proposer && count === 2) {
|
|
1293
|
+
this.duplicateProposalCallback?.({
|
|
1294
|
+
slot: block.slotNumber,
|
|
1295
|
+
proposer,
|
|
1296
|
+
type: 'block'
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
return {
|
|
1300
|
+
result: TopicValidatorResult.Accept,
|
|
1301
|
+
obj: block,
|
|
1302
|
+
metadata: {
|
|
1303
|
+
isEquivocated
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
// Otherwise, we're good to go!
|
|
1308
|
+
return {
|
|
1309
|
+
result: TopicValidatorResult.Accept,
|
|
1310
|
+
obj: block
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
1314
|
+
// should not be here as it does not deal with p2p networking.
|
|
635
1315
|
async processValidBlockProposal(block, sender) {
|
|
636
|
-
const slot = block.slotNumber
|
|
637
|
-
const previousSlot = slot - 1n;
|
|
1316
|
+
const slot = block.slotNumber;
|
|
638
1317
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
639
|
-
p2pMessageIdentifier: await block.
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
source: sender.toString()
|
|
1318
|
+
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
1319
|
+
source: sender.toString(),
|
|
1320
|
+
...block.toBlockInfo()
|
|
643
1321
|
});
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
1322
|
+
// Mark the txs in this proposal as protected
|
|
1323
|
+
await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
|
|
1324
|
+
// Call the block received callback to validate the proposal.
|
|
1325
|
+
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1326
|
+
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1327
|
+
if (!isValid) {
|
|
1328
|
+
this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* Handle a gossiped checkpoint proposal.
|
|
1333
|
+
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1334
|
+
*/ async handleGossipedCheckpointProposal(payloadData, msgId, source) {
|
|
1335
|
+
const { result, obj: checkpoint, metadata: { isEquivocated, processBlock } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_proposal);
|
|
1336
|
+
// If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
|
|
1337
|
+
// TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
|
|
1338
|
+
if (processBlock && checkpoint?.getBlockProposal()) {
|
|
1339
|
+
await this.processValidBlockProposal(checkpoint.getBlockProposal(), source);
|
|
1340
|
+
}
|
|
1341
|
+
if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
await this.processValidCheckpointProposal(checkpoint.toCore(), source);
|
|
1345
|
+
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
|
|
1348
|
+
* its last block (if present) to the mempool if valid. Triggers equivocation detection on both.
|
|
1349
|
+
*/ async validateAndStoreCheckpointProposal(peerId, checkpoint) {
|
|
1350
|
+
const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1351
|
+
if (validationResult.result === 'reject') {
|
|
1352
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1353
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1354
|
+
return {
|
|
1355
|
+
result: TopicValidatorResult.Reject
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
if (validationResult.result === 'ignore') {
|
|
1359
|
+
return {
|
|
1360
|
+
result: TopicValidatorResult.Ignore,
|
|
1361
|
+
obj: checkpoint
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
// Extract and try to add the block proposal first if present
|
|
1365
|
+
const blockProposal = checkpoint.getBlockProposal();
|
|
1366
|
+
let processBlock = false;
|
|
1367
|
+
if (blockProposal) {
|
|
1368
|
+
this.logger.debug(`Validating block proposal from propagated checkpoint`, {
|
|
1369
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1370
|
+
[Attributes.P2P_ID]: peerId.toString()
|
|
1371
|
+
});
|
|
1372
|
+
const { result, obj, metadata: { isEquivocated } = {} } = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1373
|
+
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1374
|
+
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1375
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1376
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1377
|
+
isEquivocated,
|
|
1378
|
+
result
|
|
660
1379
|
});
|
|
661
|
-
|
|
1380
|
+
return {
|
|
1381
|
+
result: TopicValidatorResult.Reject
|
|
1382
|
+
};
|
|
1383
|
+
} else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1384
|
+
processBlock = true;
|
|
662
1385
|
}
|
|
663
1386
|
}
|
|
1387
|
+
// Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
|
|
1388
|
+
const checkpointCore = checkpoint.toCore();
|
|
1389
|
+
const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
|
|
1390
|
+
const { added, alreadyExists, count } = tryAddResult;
|
|
1391
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1392
|
+
// Duplicate proposal received, do not re-broadcast
|
|
1393
|
+
if (alreadyExists) {
|
|
1394
|
+
this.logger.debug(`Ignoring duplicate checkpoint proposal received`, {
|
|
1395
|
+
...checkpoint.toCheckpointInfo(),
|
|
1396
|
+
source: peerId.toString()
|
|
1397
|
+
});
|
|
1398
|
+
return {
|
|
1399
|
+
result: TopicValidatorResult.Ignore,
|
|
1400
|
+
obj: checkpoint,
|
|
1401
|
+
metadata: {
|
|
1402
|
+
isEquivocated,
|
|
1403
|
+
processBlock
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1408
|
+
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1409
|
+
if (!added) {
|
|
1410
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1411
|
+
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1412
|
+
...checkpoint.toCheckpointInfo(),
|
|
1413
|
+
count,
|
|
1414
|
+
source: peerId.toString()
|
|
1415
|
+
});
|
|
1416
|
+
return {
|
|
1417
|
+
result: TopicValidatorResult.Reject,
|
|
1418
|
+
obj: checkpoint,
|
|
1419
|
+
metadata: {
|
|
1420
|
+
isEquivocated,
|
|
1421
|
+
processBlock
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
}
|
|
1425
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1426
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1427
|
+
if (isEquivocated) {
|
|
1428
|
+
const proposer = checkpoint.getSender();
|
|
1429
|
+
this.logger.warn(`Detected duplicate checkpoint proposal (equivocation) at slot ${checkpoint.slotNumber}`, {
|
|
1430
|
+
...checkpoint.toCheckpointInfo(),
|
|
1431
|
+
source: peerId.toString(),
|
|
1432
|
+
proposer: proposer?.toString()
|
|
1433
|
+
});
|
|
1434
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1435
|
+
if (proposer && count === 2) {
|
|
1436
|
+
this.duplicateProposalCallback?.({
|
|
1437
|
+
slot: checkpoint.slotNumber,
|
|
1438
|
+
proposer,
|
|
1439
|
+
type: 'checkpoint'
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
return {
|
|
1443
|
+
result: TopicValidatorResult.Accept,
|
|
1444
|
+
obj: checkpoint,
|
|
1445
|
+
metadata: {
|
|
1446
|
+
isEquivocated,
|
|
1447
|
+
processBlock
|
|
1448
|
+
}
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
// Otherwise, we're good to go!
|
|
1452
|
+
return {
|
|
1453
|
+
result: TopicValidatorResult.Accept,
|
|
1454
|
+
obj: checkpoint,
|
|
1455
|
+
metadata: {
|
|
1456
|
+
processBlock,
|
|
1457
|
+
isEquivocated
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
664
1460
|
}
|
|
665
1461
|
/**
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*/ async
|
|
669
|
-
|
|
1462
|
+
* Process a validated checkpoint proposal.
|
|
1463
|
+
* Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
|
|
1464
|
+
*/ async processValidCheckpointProposal(checkpoint, sender) {
|
|
1465
|
+
const slot = checkpoint.slotNumber;
|
|
1466
|
+
this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1467
|
+
p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
|
|
1468
|
+
slot: checkpoint.slotNumber,
|
|
1469
|
+
archive: checkpoint.archive.toString(),
|
|
1470
|
+
source: sender.toString()
|
|
1471
|
+
});
|
|
1472
|
+
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1473
|
+
// to validate and potentially generate attestations
|
|
1474
|
+
const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
|
|
1475
|
+
if (attestations && attestations.length > 0) {
|
|
1476
|
+
// If the callback returned attestations, add them to the pool and propagate them
|
|
1477
|
+
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
1478
|
+
for (const attestation of attestations){
|
|
1479
|
+
await this.propagate(attestation);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
670
1482
|
}
|
|
671
1483
|
/**
|
|
672
1484
|
* Propagates provided message to peers.
|
|
673
1485
|
* @param message - The message to propagate.
|
|
674
1486
|
*/ async propagate(message) {
|
|
675
|
-
const p2pMessageIdentifier = await message.
|
|
1487
|
+
const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
|
|
676
1488
|
this.logger.trace(`Message ${p2pMessageIdentifier} queued`, {
|
|
677
1489
|
p2pMessageIdentifier
|
|
678
1490
|
});
|
|
679
|
-
void this.
|
|
680
|
-
await this.sendToPeers(message);
|
|
681
|
-
}).catch((error)=>{
|
|
1491
|
+
void this.sendToPeers(message).catch((error)=>{
|
|
682
1492
|
this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, {
|
|
683
1493
|
error
|
|
684
1494
|
});
|
|
685
1495
|
});
|
|
686
1496
|
}
|
|
687
1497
|
/**
|
|
688
|
-
* Validate the requested block transactions.
|
|
1498
|
+
* Validate the requested block transactions. Allow partial returns.
|
|
689
1499
|
* @param request - The block transactions request.
|
|
690
1500
|
* @param response - The block transactions response.
|
|
691
1501
|
* @param peerId - The ID of the peer that made the request.
|
|
692
1502
|
* @returns True if the requested block transactions are valid, false otherwise.
|
|
693
|
-
*/ async validateRequestedBlockTxs(
|
|
1503
|
+
*/ async validateRequestedBlockTxs(request, response, peerId) {
|
|
694
1504
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
695
1505
|
try {
|
|
696
|
-
|
|
1506
|
+
if (!response.archiveRoot.equals(request.archiveRoot)) {
|
|
1507
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1508
|
+
throw new ValidationError(`Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`);
|
|
1509
|
+
}
|
|
1510
|
+
if (response.txIndices.getLength() !== request.txIndices.getLength()) {
|
|
1511
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1512
|
+
throw new ValidationError(`Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`);
|
|
1513
|
+
}
|
|
1514
|
+
// Check no duplicates and not exceeding returnable count
|
|
1515
|
+
const requestedIndices = new Set(request.txIndices.getTrueIndices());
|
|
1516
|
+
const availableIndices = new Set(response.txIndices.getTrueIndices());
|
|
1517
|
+
const maxReturnable = [
|
|
1518
|
+
...requestedIndices
|
|
1519
|
+
].filter((i)=>availableIndices.has(i)).length;
|
|
1520
|
+
const returnedHashes = await Promise.all(response.txs.map((tx)=>tx.getTxHash().toString()));
|
|
1521
|
+
const uniqueReturned = new Set(returnedHashes.map((h)=>h.toString()));
|
|
1522
|
+
if (uniqueReturned.size !== returnedHashes.length) {
|
|
1523
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1524
|
+
throw new ValidationError(`Received duplicate txs in block txs response`);
|
|
1525
|
+
}
|
|
1526
|
+
if (response.txs.length > maxReturnable) {
|
|
1527
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1528
|
+
throw new ValidationError(`Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`);
|
|
1529
|
+
}
|
|
1530
|
+
// Given proposal (should have locally), ensure returned txs are valid subset and match request indices
|
|
1531
|
+
const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
|
|
1532
|
+
if (proposal) {
|
|
1533
|
+
// Build intersected indices
|
|
1534
|
+
const intersectIdx = request.txIndices.getTrueIndices().filter((i)=>response.txIndices.isSet(i));
|
|
1535
|
+
// Enforce subset membership and preserve increasing order by index.
|
|
1536
|
+
const hashToIndexInProposal = new Map(proposal.txHashes.map((h, i)=>[
|
|
1537
|
+
h.toString(),
|
|
1538
|
+
i
|
|
1539
|
+
]));
|
|
1540
|
+
const allowedIndexSet = new Set(intersectIdx);
|
|
1541
|
+
const indices = returnedHashes.map((h)=>hashToIndexInProposal.get(h));
|
|
1542
|
+
const allAllowed = indices.every((idx)=>idx !== undefined && allowedIndexSet.has(idx));
|
|
1543
|
+
const strictlyIncreasing = indices.every((idx, i)=>i === 0 ? idx !== undefined : idx > indices[i - 1]);
|
|
1544
|
+
if (!allAllowed || !strictlyIncreasing) {
|
|
1545
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1546
|
+
throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
|
|
1547
|
+
}
|
|
1548
|
+
} else {
|
|
1549
|
+
// No local proposal, cannot check the membership/order of the returned txs
|
|
1550
|
+
this.logger.warn(`Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`);
|
|
1551
|
+
return false;
|
|
1552
|
+
}
|
|
697
1553
|
await Promise.all(response.txs.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator)));
|
|
698
1554
|
return true;
|
|
699
1555
|
} catch (e) {
|
|
@@ -715,13 +1571,13 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
715
1571
|
* ReqRespSubProtocol.TX subprotocol validation.
|
|
716
1572
|
*
|
|
717
1573
|
* @param requestedTxHash - The collection of the txs that was requested.
|
|
718
|
-
* @param responseTx - The
|
|
1574
|
+
* @param responseTx - The collection of txs that was received as a response to the request.
|
|
719
1575
|
* @param peerId - The peer ID of the peer that sent the tx.
|
|
720
1576
|
* @returns True if the whole collection of txs is valid, false otherwise.
|
|
721
1577
|
*/ async validateRequestedTxs(requestedTxHash, responseTx, peerId) {
|
|
722
1578
|
const requested = new Set(requestedTxHash.map((h)=>h.toString()));
|
|
723
1579
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
724
|
-
//TODO: (mralj) - this is somewhat naive implementation, if single tx is
|
|
1580
|
+
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
|
|
725
1581
|
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
726
1582
|
try {
|
|
727
1583
|
await Promise.all(responseTx.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
|
|
@@ -735,50 +1591,62 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
735
1591
|
return false;
|
|
736
1592
|
}
|
|
737
1593
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1594
|
+
/**
|
|
1595
|
+
* Validates a BLOCK response.
|
|
1596
|
+
*
|
|
1597
|
+
* If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
|
|
1598
|
+
* Penalizes on block number mismatch or hash mismatch.
|
|
1599
|
+
*
|
|
1600
|
+
* @param requestedBlockNumber - The requested block number.
|
|
1601
|
+
* @param responseBlock - The block returned by the peer.
|
|
1602
|
+
* @param peerId - The peer that returned the block.
|
|
1603
|
+
* @returns True if the response is valid, false otherwise.
|
|
1604
|
+
*/ async validateRequestedBlock(requestedBlockNumber, responseBlock, peerId) {
|
|
1605
|
+
try {
|
|
1606
|
+
const reqNum = Number(requestedBlockNumber.toString());
|
|
1607
|
+
if (responseBlock.number !== reqNum) {
|
|
1608
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1609
|
+
return false;
|
|
1610
|
+
}
|
|
1611
|
+
const local = await this.archiver.getBlock(BlockNumber(reqNum));
|
|
1612
|
+
if (!local) {
|
|
1613
|
+
// We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
|
|
1614
|
+
// TODO: Consider extending this validator to accept an expected hash or
|
|
1615
|
+
// performing quorum-based checks when using P2P syncing prior to L1 sync.
|
|
1616
|
+
this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
|
|
1617
|
+
return false;
|
|
1618
|
+
}
|
|
1619
|
+
const [localHash, respHash] = await Promise.all([
|
|
1620
|
+
local.hash(),
|
|
1621
|
+
responseBlock.hash()
|
|
1622
|
+
]);
|
|
1623
|
+
if (!localHash.equals(respHash)) {
|
|
1624
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1625
|
+
return false;
|
|
1626
|
+
}
|
|
1627
|
+
return true;
|
|
1628
|
+
} catch (e) {
|
|
1629
|
+
this.logger.warn(`Error validating requested block`, e);
|
|
1630
|
+
return false;
|
|
1631
|
+
}
|
|
745
1632
|
}
|
|
746
1633
|
async validateRequestedTx(tx, peerId, txValidator, requested) {
|
|
747
|
-
|
|
748
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
749
|
-
throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
|
|
750
|
-
}
|
|
1634
|
+
const penalize = (severity)=>this.peerManager.penalizePeer(peerId, severity);
|
|
751
1635
|
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
752
|
-
|
|
1636
|
+
penalize(PeerErrorSeverity.MidToleranceError);
|
|
753
1637
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
754
1638
|
}
|
|
755
1639
|
const { result } = await txValidator.validateTx(tx);
|
|
756
1640
|
if (result === 'invalid') {
|
|
757
|
-
|
|
1641
|
+
penalize(PeerErrorSeverity.LowToleranceError);
|
|
758
1642
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
|
|
759
1643
|
}
|
|
760
1644
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
for (const validator of messageValidators){
|
|
767
|
-
const outcome = await this.runValidations(tx, validator);
|
|
768
|
-
if (outcome.allPassed) {
|
|
769
|
-
continue;
|
|
770
|
-
}
|
|
771
|
-
const { name } = outcome.failure;
|
|
772
|
-
let { severity } = outcome.failure;
|
|
773
|
-
// Double spend validator has a special case handler
|
|
774
|
-
if (name === 'doubleSpendValidator') {
|
|
775
|
-
const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
|
|
776
|
-
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
777
|
-
}
|
|
778
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
779
|
-
return false;
|
|
780
|
-
}
|
|
781
|
-
return true;
|
|
1645
|
+
createRequestedTxValidator() {
|
|
1646
|
+
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1647
|
+
l1ChainId: this.config.l1ChainId,
|
|
1648
|
+
rollupVersion: this.config.rollupVersion
|
|
1649
|
+
});
|
|
782
1650
|
}
|
|
783
1651
|
async getGasFees(blockNumber) {
|
|
784
1652
|
if (blockNumber === this.feesCache?.blockNumber) {
|
|
@@ -792,38 +1660,41 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
792
1660
|
};
|
|
793
1661
|
return gasFees;
|
|
794
1662
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
1663
|
+
/**
|
|
1664
|
+
* Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
|
|
1665
|
+
*/ getBatchTxRequesterService() {
|
|
1666
|
+
return {
|
|
1667
|
+
reqResp: this.reqresp,
|
|
1668
|
+
connectionSampler: this.reqresp.getConnectionSampler(),
|
|
1669
|
+
txValidatorConfig: {
|
|
1670
|
+
l1ChainId: this.config.l1ChainId,
|
|
1671
|
+
rollupVersion: this.config.rollupVersion,
|
|
1672
|
+
proofVerifier: this.proofVerifier
|
|
1673
|
+
},
|
|
1674
|
+
peerScoring: this.peerManager
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
async validateTxsReceivedInBlockProposal(txs) {
|
|
1678
|
+
const validator = createTxValidatorForBlockProposalReceivedTxs(this.proofVerifier, {
|
|
1679
|
+
l1ChainId: this.config.l1ChainId,
|
|
1680
|
+
rollupVersion: this.config.rollupVersion
|
|
1681
|
+
}, this.logger.getBindings());
|
|
1682
|
+
const results = await Promise.all(txs.map(async (tx)=>{
|
|
1683
|
+
const result = await validator.validateTx(tx);
|
|
1684
|
+
return result.result !== 'invalid';
|
|
811
1685
|
}));
|
|
1686
|
+
if (results.some((value)=>value === false)) {
|
|
1687
|
+
throw new Error('Invalid tx detected');
|
|
1688
|
+
}
|
|
812
1689
|
}
|
|
813
|
-
/**
|
|
814
|
-
* Create message validators for the given block number and timestamp.
|
|
815
|
-
*
|
|
816
|
-
* Each validator is a pair of a validator and a severity.
|
|
817
|
-
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
818
|
-
*
|
|
819
|
-
* @param currentBlockNumber - The current synced block number.
|
|
820
|
-
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
821
|
-
* @returns The message validators.
|
|
822
|
-
*/ async createMessageValidators(currentBlockNumber, nextSlotTimestamp) {
|
|
1690
|
+
/** Creates the first stage (fast) validators for gossiped transactions. */ async createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp) {
|
|
823
1691
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
824
1692
|
const allowedInSetup = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
|
|
825
|
-
const
|
|
826
|
-
return
|
|
1693
|
+
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1694
|
+
return createFirstStageTxValidationsForGossipedTransactions(nextSlotTimestamp, blockNumber, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, !this.config.disableTransactions, allowedInSetup, this.logger.getBindings());
|
|
1695
|
+
}
|
|
1696
|
+
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */ createSecondStageMessageValidators() {
|
|
1697
|
+
return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
|
|
827
1698
|
}
|
|
828
1699
|
/**
|
|
829
1700
|
* Run validations on a tx.
|
|
@@ -878,11 +1749,11 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
878
1749
|
}
|
|
879
1750
|
const snapshotValidator = new DoubleSpendTxValidator({
|
|
880
1751
|
nullifiersExist: async (nullifiers)=>{
|
|
881
|
-
const merkleTree = this.worldStateSynchronizer.getSnapshot(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow);
|
|
1752
|
+
const merkleTree = this.worldStateSynchronizer.getSnapshot(BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow));
|
|
882
1753
|
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
883
1754
|
return indices.map((index)=>index !== undefined);
|
|
884
1755
|
}
|
|
885
|
-
});
|
|
1756
|
+
}, this.logger.getBindings());
|
|
886
1757
|
const validSnapshot = await snapshotValidator.validateTx(tx);
|
|
887
1758
|
if (validSnapshot.result !== 'valid') {
|
|
888
1759
|
return PeerErrorSeverity.LowToleranceError;
|
|
@@ -890,31 +1761,17 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
890
1761
|
return PeerErrorSeverity.HighToleranceError;
|
|
891
1762
|
}
|
|
892
1763
|
/**
|
|
893
|
-
* Validate
|
|
1764
|
+
* Validate a checkpoint attestation.
|
|
894
1765
|
*
|
|
895
|
-
* @param attestation - The attestation to validate.
|
|
896
|
-
* @returns True if the attestation is valid, false otherwise.
|
|
897
|
-
*/ async
|
|
898
|
-
const
|
|
899
|
-
if (
|
|
900
|
-
this.
|
|
901
|
-
|
|
902
|
-
}
|
|
903
|
-
return true;
|
|
904
|
-
}
|
|
905
|
-
/**
|
|
906
|
-
* Validate a block proposal.
|
|
907
|
-
*
|
|
908
|
-
* @param block - The block proposal to validate.
|
|
909
|
-
* @returns True if the block proposal is valid, false otherwise.
|
|
910
|
-
*/ async validateBlockProposal(peerId, block) {
|
|
911
|
-
const severity = await this.blockProposalValidator.validate(block);
|
|
912
|
-
if (severity) {
|
|
913
|
-
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
914
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
915
|
-
return false;
|
|
1766
|
+
* @param attestation - The checkpoint attestation to validate.
|
|
1767
|
+
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1768
|
+
*/ async validateCheckpointAttestation(peerId, attestation) {
|
|
1769
|
+
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1770
|
+
if (result.result === 'reject') {
|
|
1771
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1772
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
916
1773
|
}
|
|
917
|
-
return
|
|
1774
|
+
return result;
|
|
918
1775
|
}
|
|
919
1776
|
getPeerScore(peerId) {
|
|
920
1777
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
@@ -924,7 +1781,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
924
1781
|
}
|
|
925
1782
|
async sendToPeers(message) {
|
|
926
1783
|
const parent = message.constructor;
|
|
927
|
-
const identifier = await message.
|
|
1784
|
+
const identifier = await message.p2pMessageLoggingIdentifier().then((i)=>i.toString());
|
|
928
1785
|
this.logger.trace(`Sending message ${identifier}`, {
|
|
929
1786
|
p2pMessageIdentifier: identifier
|
|
930
1787
|
});
|
|
@@ -951,44 +1808,3 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
951
1808
|
}
|
|
952
1809
|
}
|
|
953
1810
|
}
|
|
954
|
-
_ts_decorate([
|
|
955
|
-
trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
|
|
956
|
-
[Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
|
|
957
|
-
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
958
|
-
[Attributes.P2P_ID]: await block.p2pMessageIdentifier().then((i)=>i.toString())
|
|
959
|
-
}))
|
|
960
|
-
], LibP2PService.prototype, "processValidBlockProposal", null);
|
|
961
|
-
_ts_decorate([
|
|
962
|
-
trackSpan('Libp2pService.broadcastAttestation', async (attestation)=>({
|
|
963
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
|
|
964
|
-
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
965
|
-
[Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
|
|
966
|
-
}))
|
|
967
|
-
], LibP2PService.prototype, "broadcastAttestation", null);
|
|
968
|
-
_ts_decorate([
|
|
969
|
-
trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
|
|
970
|
-
[Attributes.BLOCK_HASH]: request.blockHash.toString()
|
|
971
|
-
}))
|
|
972
|
-
], LibP2PService.prototype, "validateRequestedBlockTxs", null);
|
|
973
|
-
_ts_decorate([
|
|
974
|
-
trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
|
|
975
|
-
[Attributes.TX_HASH]: requestedTxHash.toString()
|
|
976
|
-
}))
|
|
977
|
-
], LibP2PService.prototype, "validateRequestedTxs", null);
|
|
978
|
-
_ts_decorate([
|
|
979
|
-
trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
|
|
980
|
-
[Attributes.TX_HASH]: tx.getTxHash().toString()
|
|
981
|
-
}))
|
|
982
|
-
], LibP2PService.prototype, "validatePropagatedTx", null);
|
|
983
|
-
_ts_decorate([
|
|
984
|
-
trackSpan('Libp2pService.validateAttestation', async (_, attestation)=>({
|
|
985
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
|
|
986
|
-
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
987
|
-
[Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
|
|
988
|
-
}))
|
|
989
|
-
], LibP2PService.prototype, "validateAttestation", null);
|
|
990
|
-
_ts_decorate([
|
|
991
|
-
trackSpan('Libp2pService.validateBlockProposal', (_peerId, block)=>({
|
|
992
|
-
[Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString()
|
|
993
|
-
}))
|
|
994
|
-
], LibP2PService.prototype, "validateBlockProposal", null);
|