@aztec/p2p 0.0.1-commit.1142ef1 → 0.0.1-commit.125b3452
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -3
- package/dest/bootstrap/bootstrap.d.ts +4 -3
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +4 -4
- package/dest/client/factory.d.ts +11 -11
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +58 -18
- package/dest/client/interface.d.ts +46 -33
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +41 -51
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +167 -225
- 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 +59 -16
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +98 -40
- 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 +104 -88
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +445 -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 +373 -96
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts +4 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +8 -5
- 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 +4 -2
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +18 -16
- package/dest/mem_pools/interface.d.ts +5 -5
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +15 -10
- 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 +91 -50
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +19 -5
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +59 -3
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +79 -5
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +47 -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 +123 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +3 -3
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +2 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- 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/priority.d.ts +2 -2
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +4 -4
- 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 +3 -1
- package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
- package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +43 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +103 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +47 -0
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +128 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +94 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +97 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +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 +180 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +25 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_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 +75 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts +6 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/index.js +5 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +215 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.js +10 -0
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +134 -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 +216 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts +26 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.js +70 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +108 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +337 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +62 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +167 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +78 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +923 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +3 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +41 -10
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -5
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +18 -6
- 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/proposal_validator/block_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +90 -54
- 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 +2 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
- package/dest/msg_validators/tx_validator/archive_cache.d.ts +3 -3
- package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/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 +137 -5
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +249 -58
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +24 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +68 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +114 -52
- package/dest/msg_validators/tx_validator/index.d.ts +4 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +3 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +6 -6
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +24 -3
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +74 -26
- package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
- package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/size_validator.js +23 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +22 -5
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +8 -8
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +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.js +1 -1
- package/dest/services/dummy_service.d.ts +24 -4
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +46 -1
- package/dest/services/encoding.d.ts +3 -3
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +13 -13
- 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 +1 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +19 -8
- package/dest/services/libp2p/libp2p_service.d.ts +101 -43
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +498 -376
- package/dest/services/peer-manager/metrics.d.ts +4 -2
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +26 -5
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +2 -1
- package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +33 -4
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +54 -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 +556 -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 +48 -0
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +35 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +136 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +62 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +176 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +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/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 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +12 -0
- package/dest/services/reqresp/constants.d.ts +12 -0
- package/dest/services/reqresp/constants.d.ts.map +1 -0
- package/dest/services/reqresp/constants.js +7 -0
- package/dest/services/reqresp/interface.d.ts +12 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +15 -1
- 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 -5
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +5 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +12 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +7 -5
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +27 -9
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +29 -6
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +59 -13
- package/dest/services/reqresp/protocols/status.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +2 -1
- package/dest/services/reqresp/protocols/tx.d.ts +7 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/reqresp.d.ts +6 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +70 -26
- package/dest/services/service.d.ts +42 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +22 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +55 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +7 -4
- 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 +10 -2
- 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 -5
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +60 -26
- package/dest/services/tx_collection/tx_collection.d.ts +29 -16
- 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 +18 -8
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +26 -29
- package/dest/services/tx_collection/tx_source.d.ts +8 -3
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +19 -2
- package/dest/services/tx_file_store/config.d.ts +16 -0
- package/dest/services/tx_file_store/config.d.ts.map +1 -0
- package/dest/services/tx_file_store/config.js +22 -0
- package/dest/services/tx_file_store/index.d.ts +4 -0
- package/dest/services/tx_file_store/index.d.ts.map +1 -0
- package/dest/services/tx_file_store/index.js +3 -0
- package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
- package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
- package/dest/services/tx_file_store/instrumentation.js +29 -0
- package/dest/services/tx_file_store/tx_file_store.d.ts +48 -0
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
- package/dest/services/tx_file_store/tx_file_store.js +152 -0
- package/dest/services/tx_provider.d.ts +6 -6
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +9 -8
- package/dest/services/tx_provider_instrumentation.d.ts +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.js +5 -5
- package/dest/test-helpers/index.d.ts +3 -1
- package/dest/test-helpers/index.d.ts.map +1 -1
- package/dest/test-helpers/index.js +2 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts +7 -8
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +1 -2
- package/dest/test-helpers/mock-pubsub.d.ts +30 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +105 -4
- 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 +367 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +221 -140
- package/dest/testbench/worker_client_manager.d.ts +53 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +231 -45
- package/dest/util.d.ts +3 -3
- package/dest/util.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/bootstrap/bootstrap.ts +7 -4
- package/src/client/factory.ts +108 -37
- package/src/client/interface.ts +56 -34
- package/src/client/p2p_client.ts +205 -274
- 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 +155 -46
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +497 -91
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +460 -112
- package/src/mem_pools/attestation_pool/index.ts +9 -2
- package/src/mem_pools/attestation_pool/mocks.ts +7 -4
- package/src/mem_pools/index.ts +4 -1
- package/src/mem_pools/instrumentation.ts +19 -14
- package/src/mem_pools/interface.ts +4 -4
- package/src/mem_pools/tx_pool/README.md +29 -14
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +130 -75
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +66 -5
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +119 -4
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +163 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +4 -2
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
- package/src/mem_pools/tx_pool/priority.ts +4 -4
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
- package/src/mem_pools/tx_pool_v2/README.md +283 -0
- package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +120 -0
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +160 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +122 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +125 -0
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +27 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +219 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +91 -0
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +99 -0
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +32 -0
- package/src/mem_pools/tx_pool_v2/index.ts +12 -0
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +247 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +337 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +430 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +238 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1105 -0
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -14
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +16 -10
- package/src/msg_validators/clock_tolerance.ts +51 -0
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +88 -65
- package/src/msg_validators/tx_validator/README.md +119 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +5 -5
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
- package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
- package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
- package/src/msg_validators/tx_validator/block_header_validator.ts +21 -8
- package/src/msg_validators/tx_validator/data_validator.ts +6 -2
- package/src/msg_validators/tx_validator/double_spend_validator.ts +15 -9
- package/src/msg_validators/tx_validator/factory.ts +406 -56
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +44 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +140 -55
- package/src/msg_validators/tx_validator/index.ts +3 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +18 -7
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +86 -29
- package/src/msg_validators/tx_validator/size_validator.ts +22 -0
- package/src/msg_validators/tx_validator/timestamp_validator.ts +29 -21
- package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +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 +59 -2
- package/src/services/encoding.ts +11 -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 +20 -7
- package/src/services/libp2p/libp2p_service.ts +546 -404
- package/src/services/peer-manager/metrics.ts +28 -4
- package/src/services/peer-manager/peer_manager.ts +2 -1
- package/src/services/peer-manager/peer_scoring.ts +29 -1
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/README.md +305 -0
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +698 -0
- package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
- package/src/services/reqresp/batch-tx-requester/interface.ts +55 -0
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +168 -0
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +249 -0
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +16 -0
- package/src/services/reqresp/constants.ts +14 -0
- package/src/services/reqresp/interface.ts +29 -1
- package/src/services/reqresp/metrics.ts +34 -9
- 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 +74 -9
- package/src/services/reqresp/protocols/status.ts +5 -3
- package/src/services/reqresp/protocols/tx.ts +22 -0
- package/src/services/reqresp/reqresp.ts +81 -22
- package/src/services/service.ts +55 -2
- package/src/services/tx_collection/config.ts +83 -1
- package/src/services/tx_collection/fast_tx_collection.ts +93 -47
- 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 +17 -2
- 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 +68 -35
- package/src/services/tx_collection/tx_collection.ts +121 -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 +12 -11
- package/src/services/tx_provider_instrumentation.ts +11 -5
- package/src/test-helpers/index.ts +2 -0
- package/src/test-helpers/make-test-p2p-clients.ts +4 -6
- package/src/test-helpers/mock-pubsub.ts +146 -9
- 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 +431 -0
- package/src/testbench/p2p_client_testbench_worker.ts +335 -136
- package/src/testbench/worker_client_manager.ts +312 -47
- package/src/util.ts +8 -2
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -40
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -218
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -31
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -180
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +0 -15
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +0 -88
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -183
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -320
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -264
- package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +0 -108
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -206
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import {
|
|
2
|
+
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { maxBy } from '@aztec/foundation/collection';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
6
6
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
7
7
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
8
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
9
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
10
9
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
11
10
|
import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
12
11
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
@@ -18,12 +17,13 @@ import {
|
|
|
18
17
|
CheckpointProposal,
|
|
19
18
|
type CheckpointProposalCore,
|
|
20
19
|
type Gossipable,
|
|
21
|
-
P2PClientType,
|
|
22
20
|
P2PMessage,
|
|
21
|
+
type ValidationResult as P2PValidationResult,
|
|
23
22
|
PeerErrorSeverity,
|
|
23
|
+
PeerErrorSeverityByHarshness,
|
|
24
24
|
TopicType,
|
|
25
25
|
createTopicString,
|
|
26
|
-
|
|
26
|
+
getTopicsForConfig,
|
|
27
27
|
metricsTopicStrToLabels,
|
|
28
28
|
} from '@aztec/stdlib/p2p';
|
|
29
29
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
type GossipsubMessage,
|
|
46
46
|
gossipsub,
|
|
47
47
|
} from '@chainsafe/libp2p-gossipsub';
|
|
48
|
-
import { createPeerScoreParams
|
|
48
|
+
import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
49
49
|
import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
|
|
50
50
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
51
51
|
import { yamux } from '@chainsafe/libp2p-yamux';
|
|
@@ -59,61 +59,62 @@ import { ENR } from '@nethermindeth/enr';
|
|
|
59
59
|
import { createLibp2p } from 'libp2p';
|
|
60
60
|
|
|
61
61
|
import type { P2PConfig } from '../../config.js';
|
|
62
|
-
import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
|
|
63
62
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
64
63
|
import {
|
|
65
64
|
BlockProposalValidator,
|
|
66
65
|
CheckpointAttestationValidator,
|
|
67
66
|
CheckpointProposalValidator,
|
|
67
|
+
DoubleSpendTxValidator,
|
|
68
68
|
FishermanAttestationValidator,
|
|
69
|
+
getDefaultAllowedSetupFunctions,
|
|
69
70
|
} from '../../msg_validators/index.js';
|
|
70
71
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
71
|
-
import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
|
|
72
|
-
import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
|
|
73
72
|
import {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
} from '../../msg_validators/tx_validator/
|
|
73
|
+
type TransactionValidator,
|
|
74
|
+
createFirstStageTxValidationsForGossipedTransactions,
|
|
75
|
+
createSecondStageTxValidationsForGossipedTransactions,
|
|
76
|
+
createTxValidatorForBlockProposalReceivedTxs,
|
|
77
|
+
createTxValidatorForReqResponseReceivedTxs,
|
|
78
|
+
} from '../../msg_validators/tx_validator/factory.js';
|
|
80
79
|
import { GossipSubEvent } from '../../types/index.js';
|
|
81
80
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
82
81
|
import { getVersions } from '../../versioning.js';
|
|
83
82
|
import { AztecDatastore } from '../data_store.js';
|
|
84
83
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
85
84
|
import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
86
|
-
import { gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
85
|
+
import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
86
|
+
import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
|
|
87
87
|
import type { PeerManagerInterface } from '../peer-manager/interface.js';
|
|
88
88
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
89
89
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
90
|
+
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
90
91
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
91
92
|
import {
|
|
93
|
+
AuthRequest,
|
|
94
|
+
BlockTxsRequest,
|
|
95
|
+
BlockTxsResponse,
|
|
92
96
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
93
97
|
type ReqRespInterface,
|
|
98
|
+
type ReqRespResponse,
|
|
94
99
|
ReqRespSubProtocol,
|
|
95
100
|
type ReqRespSubProtocolHandler,
|
|
96
101
|
type ReqRespSubProtocolHandlers,
|
|
97
102
|
type ReqRespSubProtocolValidators,
|
|
103
|
+
StatusMessage,
|
|
98
104
|
type SubProtocolMap,
|
|
99
105
|
ValidationError,
|
|
100
|
-
} from '../reqresp/interface.js';
|
|
101
|
-
import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
|
|
102
|
-
import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
103
|
-
import {
|
|
104
|
-
AuthRequest,
|
|
105
|
-
BlockTxsRequest,
|
|
106
|
-
BlockTxsResponse,
|
|
107
|
-
StatusMessage,
|
|
108
106
|
pingHandler,
|
|
107
|
+
reqGoodbyeHandler,
|
|
109
108
|
reqRespBlockHandler,
|
|
109
|
+
reqRespBlockTxsHandler,
|
|
110
110
|
reqRespStatusHandler,
|
|
111
111
|
reqRespTxHandler,
|
|
112
|
-
} from '../reqresp/
|
|
112
|
+
} from '../reqresp/index.js';
|
|
113
113
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
114
114
|
import type {
|
|
115
115
|
P2PBlockReceivedCallback,
|
|
116
116
|
P2PCheckpointReceivedCallback,
|
|
117
|
+
P2PDuplicateAttestationCallback,
|
|
117
118
|
P2PService,
|
|
118
119
|
PeerDiscoveryService,
|
|
119
120
|
} from '../service.js';
|
|
@@ -128,14 +129,14 @@ interface ValidationResult {
|
|
|
128
129
|
type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
|
|
129
130
|
|
|
130
131
|
// REFACTOR: Unify with the type above
|
|
131
|
-
type ReceivedMessageValidationResult<T> =
|
|
132
|
-
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject
|
|
133
|
-
| { obj?:
|
|
132
|
+
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
133
|
+
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
134
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
134
135
|
|
|
135
136
|
/**
|
|
136
137
|
* Lib P2P implementation of the P2PService interface.
|
|
137
138
|
*/
|
|
138
|
-
export class LibP2PService
|
|
139
|
+
export class LibP2PService extends WithTracer implements P2PService {
|
|
139
140
|
private discoveryRunningPromise?: RunningPromise;
|
|
140
141
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
141
142
|
|
|
@@ -149,6 +150,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
149
150
|
|
|
150
151
|
private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
|
|
151
152
|
|
|
153
|
+
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */
|
|
154
|
+
private duplicateProposalCallback?: (info: {
|
|
155
|
+
slot: SlotNumber;
|
|
156
|
+
proposer: EthAddress;
|
|
157
|
+
type: 'checkpoint' | 'block';
|
|
158
|
+
}) => void;
|
|
159
|
+
|
|
160
|
+
/** Callback invoked when a duplicate attestation is detected (triggers slashing). */
|
|
161
|
+
private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
|
|
162
|
+
|
|
152
163
|
/**
|
|
153
164
|
* Callback for when a block is received from a peer.
|
|
154
165
|
* @param block - The block received from the peer.
|
|
@@ -172,14 +183,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
172
183
|
protected logger: Logger;
|
|
173
184
|
|
|
174
185
|
constructor(
|
|
175
|
-
private clientType: T,
|
|
176
186
|
private config: P2PConfig,
|
|
177
187
|
protected node: PubSubLibp2p,
|
|
178
188
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
179
189
|
private reqresp: ReqRespInterface,
|
|
180
|
-
|
|
190
|
+
protected peerManager: PeerManagerInterface,
|
|
181
191
|
protected mempools: MemPools,
|
|
182
|
-
|
|
192
|
+
protected archiver: L2BlockSource & ContractDataSource,
|
|
183
193
|
private epochCache: EpochCacheInterface,
|
|
184
194
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
185
195
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
@@ -214,10 +224,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
214
224
|
this.protocolVersion,
|
|
215
225
|
);
|
|
216
226
|
|
|
217
|
-
|
|
218
|
-
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
227
|
+
const proposalValidatorOpts = {
|
|
219
228
|
txsPermitted: !config.disableTransactions,
|
|
220
|
-
|
|
229
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock,
|
|
230
|
+
};
|
|
231
|
+
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
232
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
221
233
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
222
234
|
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
223
235
|
: new CheckpointAttestationValidator(epochCache);
|
|
@@ -225,11 +237,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
225
237
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
226
238
|
|
|
227
239
|
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
228
|
-
this.logger.
|
|
229
|
-
`Handler not yet registered
|
|
240
|
+
this.logger.warn(
|
|
241
|
+
`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
|
|
230
242
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
231
243
|
);
|
|
232
|
-
return
|
|
244
|
+
return true;
|
|
233
245
|
};
|
|
234
246
|
|
|
235
247
|
this.checkpointReceivedCallback = (
|
|
@@ -252,8 +264,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
252
264
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
253
265
|
* @returns The new service.
|
|
254
266
|
*/
|
|
255
|
-
public static async new
|
|
256
|
-
clientType: T,
|
|
267
|
+
public static async new(
|
|
257
268
|
config: P2PConfig,
|
|
258
269
|
peerId: PeerId,
|
|
259
270
|
deps: {
|
|
@@ -284,14 +295,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
284
295
|
|
|
285
296
|
const datastore = new AztecDatastore(peerStore);
|
|
286
297
|
|
|
287
|
-
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
|
|
298
|
+
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
|
|
288
299
|
|
|
289
300
|
const peerDiscoveryService = new DiscV5Service(
|
|
290
301
|
peerId,
|
|
291
302
|
config,
|
|
292
303
|
packageVersion,
|
|
293
304
|
telemetry,
|
|
294
|
-
createLogger(`${logger.module}:discv5_service
|
|
305
|
+
createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
|
|
295
306
|
);
|
|
296
307
|
|
|
297
308
|
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
@@ -305,11 +316,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
305
316
|
const versions = getVersions(config);
|
|
306
317
|
const protocolVersion = compressComponentVersions(versions);
|
|
307
318
|
|
|
308
|
-
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
309
|
-
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
310
|
-
const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
|
|
311
|
-
const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
|
|
312
|
-
|
|
313
319
|
const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
|
|
314
320
|
const directPeers = (
|
|
315
321
|
await Promise.all(
|
|
@@ -329,6 +335,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
329
335
|
|
|
330
336
|
const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
|
|
331
337
|
|
|
338
|
+
// Create dynamic topic score params based on network configuration
|
|
339
|
+
const l1Constants = epochCache.getL1Constants();
|
|
340
|
+
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
341
|
+
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
342
|
+
heartbeatIntervalMs: config.gossipsubInterval,
|
|
343
|
+
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
344
|
+
blockDurationMs: config.blockDurationMs,
|
|
345
|
+
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
|
|
346
|
+
});
|
|
347
|
+
|
|
332
348
|
const node = await createLibp2p({
|
|
333
349
|
start: false,
|
|
334
350
|
peerId,
|
|
@@ -424,35 +440,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
424
440
|
scoreParams: createPeerScoreParams({
|
|
425
441
|
// IPColocation factor can be disabled for local testing - default to -5
|
|
426
442
|
IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
|
|
427
|
-
topics:
|
|
428
|
-
[txTopic]: createTopicScoreParams({
|
|
429
|
-
topicWeight: 1,
|
|
430
|
-
invalidMessageDeliveriesWeight: -20,
|
|
431
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
432
|
-
}),
|
|
433
|
-
[blockProposalTopic]: createTopicScoreParams({
|
|
434
|
-
topicWeight: 1,
|
|
435
|
-
invalidMessageDeliveriesWeight: -20,
|
|
436
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
437
|
-
}),
|
|
438
|
-
[checkpointProposalTopic]: createTopicScoreParams({
|
|
439
|
-
topicWeight: 1,
|
|
440
|
-
invalidMessageDeliveriesWeight: -20,
|
|
441
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
442
|
-
}),
|
|
443
|
-
[checkpointAttestationTopic]: createTopicScoreParams({
|
|
444
|
-
topicWeight: 1,
|
|
445
|
-
invalidMessageDeliveriesWeight: -20,
|
|
446
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
447
|
-
}),
|
|
448
|
-
},
|
|
443
|
+
topics: topicScoreParams,
|
|
449
444
|
}),
|
|
450
445
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
451
446
|
components: (components: { connectionManager: ConnectionManager }) => ({
|
|
452
447
|
connectionManager: components.connectionManager,
|
|
453
448
|
}),
|
|
454
449
|
},
|
|
455
|
-
logger: createLibp2pComponentLogger(logger.module),
|
|
450
|
+
logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
|
|
456
451
|
});
|
|
457
452
|
|
|
458
453
|
const peerScoring = new PeerScoring(config, telemetry);
|
|
@@ -471,13 +466,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
471
466
|
epochCache,
|
|
472
467
|
);
|
|
473
468
|
|
|
474
|
-
//
|
|
475
|
-
|
|
469
|
+
// Configure application-specific scoring for gossipsub.
|
|
470
|
+
// The weight scales app score to align with gossipsub thresholds:
|
|
471
|
+
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
472
|
+
// - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
|
|
473
|
+
// Note: positive topic scores can offset penalties, so alignment is best-effort.
|
|
474
|
+
node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
|
|
476
475
|
node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
|
|
477
476
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
478
477
|
|
|
479
478
|
return new LibP2PService(
|
|
480
|
-
clientType,
|
|
481
479
|
config,
|
|
482
480
|
node,
|
|
483
481
|
peerDiscoveryService,
|
|
@@ -524,7 +522,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
524
522
|
};
|
|
525
523
|
|
|
526
524
|
if (!this.config.disableTransactions) {
|
|
527
|
-
const blockTxsHandler = reqRespBlockTxsHandler(
|
|
525
|
+
const blockTxsHandler = reqRespBlockTxsHandler(
|
|
526
|
+
this.mempools.attestationPool,
|
|
527
|
+
this.archiver,
|
|
528
|
+
this.mempools.txPool,
|
|
529
|
+
);
|
|
528
530
|
requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
|
|
529
531
|
}
|
|
530
532
|
|
|
@@ -547,7 +549,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
547
549
|
await this.node.start();
|
|
548
550
|
|
|
549
551
|
// Subscribe to standard GossipSub topics by default
|
|
550
|
-
for (const topic of
|
|
552
|
+
for (const topic of getTopicsForConfig(this.config.disableTransactions)) {
|
|
551
553
|
this.subscribeToTopic(this.topicStrings[topic]);
|
|
552
554
|
}
|
|
553
555
|
|
|
@@ -613,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
613
615
|
return this.peerManager.getPeers(includePending);
|
|
614
616
|
}
|
|
615
617
|
|
|
618
|
+
public getGossipMeshPeerCount(topicType: TopicType): number {
|
|
619
|
+
return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
|
|
620
|
+
}
|
|
621
|
+
|
|
616
622
|
private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
|
|
617
623
|
this.logger.trace(`Received PUBSUB message.`);
|
|
618
624
|
|
|
@@ -640,6 +646,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
640
646
|
return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
|
|
641
647
|
}
|
|
642
648
|
|
|
649
|
+
public sendRequestToPeer(
|
|
650
|
+
peerId: PeerId,
|
|
651
|
+
subProtocol: ReqRespSubProtocol,
|
|
652
|
+
payload: Buffer,
|
|
653
|
+
dialTimeout?: number,
|
|
654
|
+
): Promise<ReqRespResponse> {
|
|
655
|
+
return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
|
|
656
|
+
}
|
|
657
|
+
|
|
643
658
|
/**
|
|
644
659
|
* Get the ENR of the node
|
|
645
660
|
* @returns The ENR of the node
|
|
@@ -656,6 +671,25 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
656
671
|
this.checkpointReceivedCallback = callback;
|
|
657
672
|
}
|
|
658
673
|
|
|
674
|
+
/**
|
|
675
|
+
* Registers a callback to be invoked when a duplicate proposal is detected.
|
|
676
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
677
|
+
*/
|
|
678
|
+
public registerDuplicateProposalCallback(
|
|
679
|
+
callback: (info: { slot: SlotNumber; proposer: EthAddress; type: 'checkpoint' | 'block' }) => void,
|
|
680
|
+
): void {
|
|
681
|
+
this.duplicateProposalCallback = callback;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Registers a callback to be invoked when a duplicate attestation is detected.
|
|
686
|
+
* A validator signing attestations for different proposals at the same slot.
|
|
687
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
688
|
+
*/
|
|
689
|
+
public registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void {
|
|
690
|
+
this.duplicateAttestationCallback = callback;
|
|
691
|
+
}
|
|
692
|
+
|
|
659
693
|
/**
|
|
660
694
|
* Subscribes to a topic.
|
|
661
695
|
* @param topic - The topic to subscribe to.
|
|
@@ -720,6 +754,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
720
754
|
if (!validator || !validator.addMessage(msgId)) {
|
|
721
755
|
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
722
756
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
757
|
+
if (topicType === TopicType.tx) {
|
|
758
|
+
this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
|
|
759
|
+
}
|
|
723
760
|
return { result: false, topicType };
|
|
724
761
|
}
|
|
725
762
|
|
|
@@ -784,9 +821,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
784
821
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
785
822
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
786
823
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
787
|
-
|
|
788
|
-
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
789
|
-
}
|
|
824
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
790
825
|
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
791
826
|
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
792
827
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
@@ -842,13 +877,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
842
877
|
return;
|
|
843
878
|
}
|
|
844
879
|
|
|
845
|
-
protected async validateReceivedMessage<T>(
|
|
846
|
-
validationFunc: () => Promise<ReceivedMessageValidationResult<T>>,
|
|
880
|
+
protected async validateReceivedMessage<T, M = undefined>(
|
|
881
|
+
validationFunc: () => Promise<ReceivedMessageValidationResult<T, M>>,
|
|
847
882
|
msgId: string,
|
|
848
883
|
source: PeerId,
|
|
849
884
|
topicType: TopicType,
|
|
850
|
-
): Promise<ReceivedMessageValidationResult<T>> {
|
|
851
|
-
let resultAndObj: ReceivedMessageValidationResult<T> = { result: TopicValidatorResult.Reject };
|
|
885
|
+
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
886
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
|
|
852
887
|
const timer = new Timer();
|
|
853
888
|
try {
|
|
854
889
|
resultAndObj = await validationFunc();
|
|
@@ -872,21 +907,76 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
872
907
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
873
908
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
874
909
|
const tx = Tx.fromBuffer(payloadData);
|
|
875
|
-
const isValid = await this.validatePropagatedTx(tx, source);
|
|
876
|
-
const exists = isValid && (await this.mempools.txPool.hasTx(tx.getTxHash()));
|
|
877
910
|
|
|
878
|
-
this.
|
|
879
|
-
|
|
880
|
-
|
|
911
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
912
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
913
|
+
|
|
914
|
+
// Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
|
|
915
|
+
const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
916
|
+
const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
|
|
917
|
+
if (!firstStageOutcome.allPassed) {
|
|
918
|
+
const { name } = firstStageOutcome.failure;
|
|
919
|
+
let { severity } = firstStageOutcome.failure;
|
|
920
|
+
|
|
921
|
+
// Double spend validator has a special case handler. We perform more detailed examination
|
|
922
|
+
// as to how recently the nullifier was entered into the tree and if the transaction should
|
|
923
|
+
// have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
|
|
924
|
+
if (name === 'doubleSpendValidator') {
|
|
925
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1);
|
|
926
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
|
|
930
|
+
validator: name,
|
|
931
|
+
severity,
|
|
932
|
+
source: source.toString(),
|
|
933
|
+
});
|
|
934
|
+
this.peerManager.penalizePeer(source, severity);
|
|
935
|
+
return { result: TopicValidatorResult.Reject };
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
939
|
+
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
940
|
+
if (canAdd === 'ignored') {
|
|
941
|
+
this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
|
|
942
|
+
source: source.toString(),
|
|
943
|
+
});
|
|
944
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// Stage 2: expensive proof verification
|
|
948
|
+
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
949
|
+
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
950
|
+
if (!secondStageOutcome.allPassed) {
|
|
951
|
+
const { severity, name } = secondStageOutcome.failure;
|
|
952
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
|
|
953
|
+
validator: name,
|
|
954
|
+
severity,
|
|
955
|
+
source: source.toString(),
|
|
956
|
+
});
|
|
957
|
+
this.peerManager.penalizePeer(source, severity);
|
|
958
|
+
return { result: TopicValidatorResult.Reject };
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// Pool add: persist the tx
|
|
962
|
+
const txHash = tx.getTxHash();
|
|
963
|
+
const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
|
|
964
|
+
|
|
965
|
+
const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
|
|
966
|
+
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
967
|
+
|
|
968
|
+
this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
|
|
969
|
+
wasAccepted,
|
|
970
|
+
wasIgnored,
|
|
881
971
|
[Attributes.P2P_ID]: source.toString(),
|
|
882
972
|
});
|
|
883
973
|
|
|
884
|
-
if (
|
|
885
|
-
return { result: TopicValidatorResult.
|
|
886
|
-
} else if (
|
|
974
|
+
if (wasAccepted) {
|
|
975
|
+
return { result: TopicValidatorResult.Accept, obj: tx };
|
|
976
|
+
} else if (wasIgnored) {
|
|
887
977
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
888
978
|
} else {
|
|
889
|
-
return { result: TopicValidatorResult.
|
|
979
|
+
return { result: TopicValidatorResult.Reject };
|
|
890
980
|
}
|
|
891
981
|
};
|
|
892
982
|
|
|
@@ -895,6 +985,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
895
985
|
return;
|
|
896
986
|
}
|
|
897
987
|
|
|
988
|
+
// Tx was accepted into pool and will be propagated - just log and record metrics
|
|
898
989
|
const txHash = tx.getTxHash();
|
|
899
990
|
const txHashString = txHash.toString();
|
|
900
991
|
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
@@ -902,13 +993,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
902
993
|
txHash: txHashString,
|
|
903
994
|
});
|
|
904
995
|
|
|
905
|
-
if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
|
|
906
|
-
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
907
|
-
return;
|
|
908
|
-
}
|
|
909
|
-
|
|
910
996
|
this.instrumentation.incrementTxReceived(1);
|
|
911
|
-
await this.mempools.txPool.addTxs([tx]);
|
|
912
997
|
}
|
|
913
998
|
|
|
914
999
|
/**
|
|
@@ -920,46 +1005,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
920
1005
|
msgId: string,
|
|
921
1006
|
source: PeerId,
|
|
922
1007
|
): Promise<void> {
|
|
923
|
-
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointAttestation>> = async () => {
|
|
924
|
-
const attestation = CheckpointAttestation.fromBuffer(payloadData);
|
|
925
|
-
const pool = this.mempools.attestationPool;
|
|
926
|
-
const isValid = await this.validateCheckpointAttestation(source, attestation);
|
|
927
|
-
const exists = isValid && (await pool.hasCheckpointAttestation(attestation));
|
|
928
|
-
|
|
929
|
-
let canAdd = true;
|
|
930
|
-
if (isValid && !exists) {
|
|
931
|
-
const slot = attestation.payload.header.slotNumber;
|
|
932
|
-
const { committee } = await this.epochCache.getCommittee(slot);
|
|
933
|
-
const committeeSize = committee?.length ?? 0;
|
|
934
|
-
canAdd = await pool.canAddCheckpointAttestation(attestation, committeeSize);
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
938
|
-
isValid,
|
|
939
|
-
exists,
|
|
940
|
-
canAdd,
|
|
941
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
942
|
-
[Attributes.P2P_ID]: source.toString(),
|
|
943
|
-
});
|
|
944
|
-
|
|
945
|
-
if (!isValid) {
|
|
946
|
-
return { result: TopicValidatorResult.Reject };
|
|
947
|
-
} else if (exists) {
|
|
948
|
-
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
949
|
-
} else if (!canAdd) {
|
|
950
|
-
this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
|
|
951
|
-
slot: attestation.payload.header.slotNumber.toString(),
|
|
952
|
-
archive: attestation.archive.toString(),
|
|
953
|
-
source: source.toString(),
|
|
954
|
-
});
|
|
955
|
-
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
956
|
-
} else {
|
|
957
|
-
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
958
|
-
}
|
|
959
|
-
};
|
|
960
|
-
|
|
961
1008
|
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
962
|
-
|
|
1009
|
+
() => this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)),
|
|
963
1010
|
msgId,
|
|
964
1011
|
source,
|
|
965
1012
|
TopicType.checkpoint_attestation,
|
|
@@ -969,8 +1016,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
969
1016
|
return;
|
|
970
1017
|
}
|
|
971
1018
|
|
|
972
|
-
this.logger.
|
|
973
|
-
`Received checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
1019
|
+
this.logger.verbose(
|
|
1020
|
+
`Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
974
1021
|
{
|
|
975
1022
|
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
976
1023
|
slot: attestation.slotNumber,
|
|
@@ -978,59 +1025,167 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
978
1025
|
source: source.toString(),
|
|
979
1026
|
},
|
|
980
1027
|
);
|
|
981
|
-
|
|
982
|
-
await this.mempools.attestationPool.addCheckpointAttestations([attestation]);
|
|
983
1028
|
}
|
|
984
1029
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1030
|
+
/** Validates a checkpoint attestation and adds it to the pool. Penalizes the peer if validation fails. */
|
|
1031
|
+
@trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation) => ({
|
|
1032
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
1033
|
+
}))
|
|
1034
|
+
protected async validateAndStoreCheckpointAttestation(
|
|
1035
|
+
peerId: PeerId,
|
|
1036
|
+
attestation: CheckpointAttestation,
|
|
1037
|
+
): Promise<ReceivedMessageValidationResult<CheckpointAttestation>> {
|
|
1038
|
+
const validationResult = await this.checkpointAttestationValidator.validate(attestation);
|
|
1039
|
+
|
|
1040
|
+
if (validationResult.result === 'reject') {
|
|
1041
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1042
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1043
|
+
return { result: TopicValidatorResult.Reject };
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
if (validationResult.result === 'ignore') {
|
|
1047
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
// Try to add the attestation: this handles existence check, cap check, and adding in one call
|
|
1051
|
+
// count is the number of attestations by this signer for this slot (for duplicate detection)
|
|
1052
|
+
const slot = attestation.payload.header.slotNumber;
|
|
1053
|
+
const { added, alreadyExists, count } =
|
|
1054
|
+
await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
|
|
1055
|
+
|
|
1056
|
+
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
1057
|
+
added,
|
|
1058
|
+
alreadyExists,
|
|
1059
|
+
count,
|
|
1060
|
+
[Attributes.SLOT_NUMBER]: slot.toString(),
|
|
1061
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1062
|
+
});
|
|
990
1063
|
|
|
991
|
-
|
|
992
|
-
|
|
1064
|
+
// Exact same attestation received, no need to re-broadcast
|
|
1065
|
+
if (alreadyExists) {
|
|
1066
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1067
|
+
}
|
|
993
1068
|
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1069
|
+
// Could not add (cap reached for signer), no need to re-broadcast
|
|
1070
|
+
if (!added) {
|
|
1071
|
+
this.logger.warn(`Dropping checkpoint attestation due to cap`, {
|
|
1072
|
+
slot: slot.toString(),
|
|
1073
|
+
archive: attestation.archive.toString(),
|
|
1074
|
+
source: peerId.toString(),
|
|
1075
|
+
attester: attestation.getSender()?.toString(),
|
|
1076
|
+
count,
|
|
1000
1077
|
});
|
|
1078
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1079
|
+
}
|
|
1001
1080
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
this.
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1081
|
+
// Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
|
|
1082
|
+
// count is the number of attestations by this signer for this slot
|
|
1083
|
+
if (count === 2) {
|
|
1084
|
+
const attester = attestation.getSender();
|
|
1085
|
+
if (attester) {
|
|
1086
|
+
this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
|
|
1087
|
+
slot: slot.toString(),
|
|
1088
|
+
archive: attestation.archive.toString(),
|
|
1089
|
+
source: peerId.toString(),
|
|
1090
|
+
attester: attester.toString(),
|
|
1012
1091
|
});
|
|
1013
|
-
|
|
1014
|
-
} else {
|
|
1015
|
-
return { result: TopicValidatorResult.Accept, obj: block };
|
|
1092
|
+
this.duplicateAttestationCallback?.({ slot, attester });
|
|
1016
1093
|
}
|
|
1017
|
-
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// Attestation was added successfully - accept it so other nodes can also detect the equivocation
|
|
1097
|
+
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
1098
|
+
}
|
|
1018
1099
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1100
|
+
protected async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1101
|
+
const {
|
|
1102
|
+
result,
|
|
1103
|
+
obj: block,
|
|
1104
|
+
metadata: { isEquivocated } = {},
|
|
1105
|
+
} = await this.validateReceivedMessage<BlockProposal, { isEquivocated: boolean }>(
|
|
1106
|
+
() => this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)),
|
|
1021
1107
|
msgId,
|
|
1022
1108
|
source,
|
|
1023
1109
|
TopicType.block_proposal,
|
|
1024
1110
|
);
|
|
1025
1111
|
|
|
1026
|
-
|
|
1112
|
+
// If not accepted or equivocated, return
|
|
1113
|
+
if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
|
|
1027
1114
|
return;
|
|
1028
1115
|
}
|
|
1029
1116
|
|
|
1030
1117
|
await this.processValidBlockProposal(block, source);
|
|
1031
1118
|
}
|
|
1032
1119
|
|
|
1033
|
-
|
|
1120
|
+
/** Validates a block proposal. Triggers a penalization to the peer that sent it if invalid. Adds to the mempool if valid. */
|
|
1121
|
+
@trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block) => ({
|
|
1122
|
+
[Attributes.BLOCK_NUMBER]: block.blockNumber.toString(),
|
|
1123
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1124
|
+
}))
|
|
1125
|
+
protected async validateAndStoreBlockProposal(
|
|
1126
|
+
peerId: PeerId,
|
|
1127
|
+
block: BlockProposal,
|
|
1128
|
+
): Promise<ReceivedMessageValidationResult<BlockProposal, { isEquivocated: boolean }>> {
|
|
1129
|
+
const validationResult = await this.blockProposalValidator.validate(block);
|
|
1130
|
+
|
|
1131
|
+
if (validationResult.result === 'reject') {
|
|
1132
|
+
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1133
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1134
|
+
return { result: TopicValidatorResult.Reject };
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
if (validationResult.result === 'ignore') {
|
|
1138
|
+
return { result: TopicValidatorResult.Ignore, obj: block };
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1142
|
+
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1143
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1144
|
+
|
|
1145
|
+
// Duplicate proposal received, no need to re-broadcast
|
|
1146
|
+
if (alreadyExists) {
|
|
1147
|
+
this.logger.debug(`Ignoring duplicate block proposal received`, {
|
|
1148
|
+
...block.toBlockInfo(),
|
|
1149
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1150
|
+
proposer: block.getSender()?.toString(),
|
|
1151
|
+
source: peerId.toString(),
|
|
1152
|
+
});
|
|
1153
|
+
return { result: TopicValidatorResult.Ignore, obj: block, metadata: { isEquivocated } };
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1157
|
+
if (!added) {
|
|
1158
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1159
|
+
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1160
|
+
...block.toBlockInfo(),
|
|
1161
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1162
|
+
count,
|
|
1163
|
+
proposer: block.getSender()?.toString(),
|
|
1164
|
+
source: peerId.toString(),
|
|
1165
|
+
});
|
|
1166
|
+
return { result: TopicValidatorResult.Reject, metadata: { isEquivocated } };
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1170
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1171
|
+
if (isEquivocated) {
|
|
1172
|
+
const proposer = block.getSender();
|
|
1173
|
+
this.logger.warn(`Detected duplicate block proposal (equivocation) at slot ${block.slotNumber}`, {
|
|
1174
|
+
...block.toBlockInfo(),
|
|
1175
|
+
source: peerId.toString(),
|
|
1176
|
+
proposer: proposer?.toString(),
|
|
1177
|
+
});
|
|
1178
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1179
|
+
if (proposer && count === 2) {
|
|
1180
|
+
this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
|
|
1181
|
+
}
|
|
1182
|
+
return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
// Otherwise, we're good to go!
|
|
1186
|
+
return { result: TopicValidatorResult.Accept, obj: block };
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1034
1189
|
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
1035
1190
|
// should not be here as it does not deal with p2p networking.
|
|
1036
1191
|
@trackSpan('Libp2pService.processValidBlockProposal', async block => ({
|
|
@@ -1038,7 +1193,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1038
1193
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
1039
1194
|
[Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1040
1195
|
}))
|
|
1041
|
-
|
|
1196
|
+
protected async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
|
|
1042
1197
|
const slot = block.slotNumber;
|
|
1043
1198
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1044
1199
|
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
@@ -1046,30 +1201,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1046
1201
|
...block.toBlockInfo(),
|
|
1047
1202
|
});
|
|
1048
1203
|
|
|
1049
|
-
//
|
|
1050
|
-
|
|
1051
|
-
await this.mempools.attestationPool.addBlockProposal(block);
|
|
1052
|
-
} catch (err: unknown) {
|
|
1053
|
-
// Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
|
|
1054
|
-
if (err instanceof ProposalSlotCapExceededError) {
|
|
1055
|
-
this.logger.warn(`Dropping block proposal due to per-slot proposal cap`, {
|
|
1056
|
-
slot: String(slot),
|
|
1057
|
-
archive: block.archive.toString(),
|
|
1058
|
-
error: (err as Error).message,
|
|
1059
|
-
});
|
|
1060
|
-
return;
|
|
1061
|
-
}
|
|
1062
|
-
throw err;
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
// Mark the txs in this proposal as non-evictable
|
|
1066
|
-
await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
|
|
1204
|
+
// Mark the txs in this proposal as protected
|
|
1205
|
+
await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
|
|
1067
1206
|
|
|
1068
1207
|
// Call the block received callback to validate the proposal.
|
|
1069
1208
|
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1070
1209
|
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1071
1210
|
if (!isValid) {
|
|
1072
|
-
this.logger.
|
|
1211
|
+
this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1073
1212
|
}
|
|
1074
1213
|
}
|
|
1075
1214
|
|
|
@@ -1077,66 +1216,145 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1077
1216
|
* Handle a gossiped checkpoint proposal.
|
|
1078
1217
|
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1079
1218
|
*/
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1219
|
+
protected async handleGossipedCheckpointProposal(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1220
|
+
const {
|
|
1221
|
+
result,
|
|
1222
|
+
obj: checkpoint,
|
|
1223
|
+
metadata: { isEquivocated, processBlock } = {},
|
|
1224
|
+
} = await this.validateReceivedMessage<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>(
|
|
1225
|
+
() => this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)),
|
|
1226
|
+
msgId,
|
|
1227
|
+
source,
|
|
1228
|
+
TopicType.checkpoint_proposal,
|
|
1229
|
+
);
|
|
1230
|
+
|
|
1231
|
+
// If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
|
|
1232
|
+
// TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
|
|
1233
|
+
if (processBlock && checkpoint?.getBlockProposal()) {
|
|
1234
|
+
await this.processValidBlockProposal(checkpoint.getBlockProposal()!, source);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
await this.processValidCheckpointProposal(checkpoint.toCore(), source);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
|
|
1246
|
+
* its last block (if present) to the mempool if valid. Triggers equivocation detection on both.
|
|
1247
|
+
*/
|
|
1248
|
+
@trackSpan('Libp2pService.validateAndStoreCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1249
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1250
|
+
}))
|
|
1251
|
+
protected async validateAndStoreCheckpointProposal(
|
|
1252
|
+
peerId: PeerId,
|
|
1253
|
+
checkpoint: CheckpointProposal,
|
|
1254
|
+
): Promise<ReceivedMessageValidationResult<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>> {
|
|
1255
|
+
const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1256
|
+
|
|
1257
|
+
if (validationResult.result === 'reject') {
|
|
1258
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1259
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1260
|
+
return { result: TopicValidatorResult.Reject };
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
if (validationResult.result === 'ignore') {
|
|
1264
|
+
return { result: TopicValidatorResult.Ignore, obj: checkpoint };
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
// Extract and try to add the block proposal first if present
|
|
1268
|
+
const blockProposal = checkpoint.getBlockProposal();
|
|
1269
|
+
let processBlock = false;
|
|
1270
|
+
if (blockProposal) {
|
|
1271
|
+
this.logger.debug(`Validating block proposal from propagated checkpoint`, {
|
|
1094
1272
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1095
|
-
[Attributes.P2P_ID]:
|
|
1273
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1096
1274
|
});
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
this.
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1275
|
+
const {
|
|
1276
|
+
result,
|
|
1277
|
+
obj,
|
|
1278
|
+
metadata: { isEquivocated } = {},
|
|
1279
|
+
} = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1280
|
+
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1281
|
+
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1282
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1283
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1284
|
+
isEquivocated,
|
|
1285
|
+
result,
|
|
1108
1286
|
});
|
|
1109
1287
|
return { result: TopicValidatorResult.Reject };
|
|
1110
|
-
} else {
|
|
1111
|
-
|
|
1288
|
+
} else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1289
|
+
processBlock = true;
|
|
1112
1290
|
}
|
|
1113
|
-
}
|
|
1291
|
+
}
|
|
1114
1292
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1293
|
+
// Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
|
|
1294
|
+
const checkpointCore = checkpoint.toCore();
|
|
1295
|
+
const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
|
|
1296
|
+
const { added, alreadyExists, count } = tryAddResult;
|
|
1297
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1298
|
+
|
|
1299
|
+
// Duplicate proposal received, do not re-broadcast
|
|
1300
|
+
if (alreadyExists) {
|
|
1301
|
+
this.logger.debug(`Ignoring duplicate checkpoint proposal received`, {
|
|
1302
|
+
...checkpoint.toCheckpointInfo(),
|
|
1303
|
+
source: peerId.toString(),
|
|
1304
|
+
});
|
|
1305
|
+
return {
|
|
1306
|
+
result: TopicValidatorResult.Ignore,
|
|
1307
|
+
obj: checkpoint,
|
|
1308
|
+
metadata: { isEquivocated, processBlock },
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1121
1311
|
|
|
1122
|
-
|
|
1123
|
-
|
|
1312
|
+
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1313
|
+
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1314
|
+
if (!added) {
|
|
1315
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1316
|
+
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1317
|
+
...checkpoint.toCheckpointInfo(),
|
|
1318
|
+
count,
|
|
1319
|
+
source: peerId.toString(),
|
|
1320
|
+
});
|
|
1321
|
+
return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1325
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1326
|
+
if (isEquivocated) {
|
|
1327
|
+
const proposer = checkpoint.getSender();
|
|
1328
|
+
this.logger.warn(`Detected duplicate checkpoint proposal (equivocation) at slot ${checkpoint.slotNumber}`, {
|
|
1329
|
+
...checkpoint.toCheckpointInfo(),
|
|
1330
|
+
source: peerId.toString(),
|
|
1331
|
+
proposer: proposer?.toString(),
|
|
1332
|
+
});
|
|
1333
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1334
|
+
if (proposer && count === 2) {
|
|
1335
|
+
this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
|
|
1336
|
+
}
|
|
1337
|
+
return {
|
|
1338
|
+
result: TopicValidatorResult.Accept,
|
|
1339
|
+
obj: checkpoint,
|
|
1340
|
+
metadata: { isEquivocated, processBlock },
|
|
1341
|
+
};
|
|
1124
1342
|
}
|
|
1125
1343
|
|
|
1126
|
-
|
|
1344
|
+
// Otherwise, we're good to go!
|
|
1345
|
+
return { result: TopicValidatorResult.Accept, obj: checkpoint, metadata: { processBlock, isEquivocated } };
|
|
1127
1346
|
}
|
|
1128
1347
|
|
|
1129
1348
|
/**
|
|
1130
1349
|
* Process a validated checkpoint proposal.
|
|
1131
|
-
*
|
|
1132
|
-
* The block callback is invoked before the checkpoint callback.
|
|
1350
|
+
* Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
|
|
1133
1351
|
*/
|
|
1134
1352
|
@trackSpan('Libp2pService.processValidCheckpointProposal', async checkpoint => ({
|
|
1135
1353
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
|
|
1136
1354
|
[Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
|
|
1137
1355
|
[Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1138
1356
|
}))
|
|
1139
|
-
|
|
1357
|
+
protected async processValidCheckpointProposal(checkpoint: CheckpointProposalCore, sender: PeerId) {
|
|
1140
1358
|
const slot = checkpoint.slotNumber;
|
|
1141
1359
|
this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1142
1360
|
p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
|
|
@@ -1145,37 +1363,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1145
1363
|
source: sender.toString(),
|
|
1146
1364
|
});
|
|
1147
1365
|
|
|
1148
|
-
// Extract block proposal before adding to pool (pool stores them separately)
|
|
1149
|
-
const blockProposal = checkpoint.getBlockProposal();
|
|
1150
|
-
|
|
1151
|
-
// Add proposal to the pool (this extracts and stores block proposal separately)
|
|
1152
|
-
await this.mempools.attestationPool.addCheckpointProposal(checkpoint);
|
|
1153
|
-
|
|
1154
|
-
// Mark txs as non-evictable if present (from the last block)
|
|
1155
|
-
if (checkpoint.txHashes.length > 0) {
|
|
1156
|
-
await this.mempools.txPool.markTxsAsNonEvictable(checkpoint.txHashes);
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
// If there was a last block proposal, invoke the block callback first for validation.
|
|
1160
|
-
// Note: The block proposal is already stored in the pool by addCheckpointProposal.
|
|
1161
|
-
if (blockProposal) {
|
|
1162
|
-
const isValid = await this.blockReceivedCallback(blockProposal, sender);
|
|
1163
|
-
if (!isValid) {
|
|
1164
|
-
this.logger.warn(`Block proposal from checkpoint failed validation`, {
|
|
1165
|
-
slot: slot.toString(),
|
|
1166
|
-
archive: checkpoint.archive.toString(),
|
|
1167
|
-
blockNumber: blockProposal.blockNumber.toString(),
|
|
1168
|
-
});
|
|
1169
|
-
return;
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
1366
|
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1174
1367
|
// to validate and potentially generate attestations
|
|
1175
|
-
const attestations = await this.checkpointReceivedCallback(checkpoint
|
|
1368
|
+
const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
|
|
1176
1369
|
if (attestations && attestations.length > 0) {
|
|
1177
1370
|
// If the callback returned attestations, add them to the pool and propagate them
|
|
1178
|
-
await this.mempools.attestationPool.
|
|
1371
|
+
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
1179
1372
|
for (const attestation of attestations) {
|
|
1180
1373
|
await this.propagate(attestation);
|
|
1181
1374
|
}
|
|
@@ -1202,9 +1395,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1202
1395
|
* @returns True if the requested block transactions are valid, false otherwise.
|
|
1203
1396
|
*/
|
|
1204
1397
|
@trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
|
|
1205
|
-
[Attributes.
|
|
1398
|
+
[Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
|
|
1206
1399
|
}))
|
|
1207
|
-
|
|
1400
|
+
protected async validateRequestedBlockTxs(
|
|
1208
1401
|
request: BlockTxsRequest,
|
|
1209
1402
|
response: BlockTxsResponse,
|
|
1210
1403
|
peerId: PeerId,
|
|
@@ -1212,10 +1405,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1212
1405
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
1213
1406
|
|
|
1214
1407
|
try {
|
|
1215
|
-
if (!response.
|
|
1408
|
+
if (!response.archiveRoot.equals(request.archiveRoot)) {
|
|
1216
1409
|
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1217
1410
|
throw new ValidationError(
|
|
1218
|
-
`Received block txs for unexpected
|
|
1411
|
+
`Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`,
|
|
1219
1412
|
);
|
|
1220
1413
|
}
|
|
1221
1414
|
|
|
@@ -1245,7 +1438,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1245
1438
|
}
|
|
1246
1439
|
|
|
1247
1440
|
// Given proposal (should have locally), ensure returned txs are valid subset and match request indices
|
|
1248
|
-
const proposal = await this.mempools.attestationPool.getBlockProposal(request.
|
|
1441
|
+
const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
|
|
1249
1442
|
if (proposal) {
|
|
1250
1443
|
// Build intersected indices
|
|
1251
1444
|
const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
|
|
@@ -1265,7 +1458,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1265
1458
|
} else {
|
|
1266
1459
|
// No local proposal, cannot check the membership/order of the returned txs
|
|
1267
1460
|
this.logger.warn(
|
|
1268
|
-
`Block proposal not found for
|
|
1461
|
+
`Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`,
|
|
1269
1462
|
);
|
|
1270
1463
|
return false;
|
|
1271
1464
|
}
|
|
@@ -1304,7 +1497,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1304
1497
|
const requested = new Set(requestedTxHash.map(h => h.toString()));
|
|
1305
1498
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
1306
1499
|
|
|
1307
|
-
//TODO: (mralj) - this is somewhat naive implementation, if single tx is
|
|
1500
|
+
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
|
|
1308
1501
|
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
1309
1502
|
try {
|
|
1310
1503
|
await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
|
|
@@ -1334,7 +1527,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1334
1527
|
@trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
|
|
1335
1528
|
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
|
|
1336
1529
|
}))
|
|
1337
|
-
|
|
1530
|
+
protected async validateRequestedBlock(
|
|
1338
1531
|
requestedBlockNumber: Fr,
|
|
1339
1532
|
responseBlock: L2Block,
|
|
1340
1533
|
peerId: PeerId,
|
|
@@ -1367,27 +1560,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1367
1560
|
}
|
|
1368
1561
|
}
|
|
1369
1562
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
protocolContractsHash,
|
|
1377
|
-
vkTreeRoot: getVKTreeRoot(),
|
|
1378
|
-
}),
|
|
1379
|
-
new TxProofValidator(this.proofVerifier),
|
|
1380
|
-
);
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
private async validateRequestedTx(tx: Tx, peerId: PeerId, txValidator: TxValidator, requested?: Set<`0x${string}`>) {
|
|
1563
|
+
protected async validateRequestedTx(
|
|
1564
|
+
tx: Tx,
|
|
1565
|
+
peerId: PeerId,
|
|
1566
|
+
txValidator: TxValidator,
|
|
1567
|
+
requested?: Set<`0x${string}`>,
|
|
1568
|
+
) {
|
|
1384
1569
|
const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
|
|
1385
|
-
|
|
1386
|
-
if (!(await tx.validateTxHash())) {
|
|
1387
|
-
penalize(PeerErrorSeverity.MidToleranceError);
|
|
1388
|
-
throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
1570
|
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
1392
1571
|
penalize(PeerErrorSeverity.MidToleranceError);
|
|
1393
1572
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
@@ -1400,35 +1579,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1400
1579
|
}
|
|
1401
1580
|
}
|
|
1402
1581
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
// We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
|
|
1410
|
-
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1411
|
-
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1412
|
-
|
|
1413
|
-
for (const validator of messageValidators) {
|
|
1414
|
-
const outcome = await this.runValidations(tx, validator);
|
|
1415
|
-
|
|
1416
|
-
if (outcome.allPassed) {
|
|
1417
|
-
continue;
|
|
1418
|
-
}
|
|
1419
|
-
const { name } = outcome.failure;
|
|
1420
|
-
let { severity } = outcome.failure;
|
|
1421
|
-
|
|
1422
|
-
// Double spend validator has a special case handler
|
|
1423
|
-
if (name === 'doubleSpendValidator') {
|
|
1424
|
-
const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
|
|
1425
|
-
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1429
|
-
return false;
|
|
1430
|
-
}
|
|
1431
|
-
return true;
|
|
1582
|
+
protected createRequestedTxValidator(): TxValidator {
|
|
1583
|
+
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1584
|
+
l1ChainId: this.config.l1ChainId,
|
|
1585
|
+
rollupVersion: this.config.rollupVersion,
|
|
1586
|
+
});
|
|
1432
1587
|
}
|
|
1433
1588
|
|
|
1434
1589
|
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
@@ -1442,59 +1597,78 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1442
1597
|
return gasFees;
|
|
1443
1598
|
}
|
|
1444
1599
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1600
|
+
/**
|
|
1601
|
+
* Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
|
|
1602
|
+
*/
|
|
1603
|
+
public getBatchTxRequesterService(): BatchTxRequesterLibP2PService {
|
|
1604
|
+
return {
|
|
1605
|
+
reqResp: this.reqresp,
|
|
1606
|
+
connectionSampler: this.reqresp.getConnectionSampler(),
|
|
1607
|
+
txValidatorConfig: {
|
|
1608
|
+
l1ChainId: this.config.l1ChainId,
|
|
1609
|
+
rollupVersion: this.config.rollupVersion,
|
|
1610
|
+
proofVerifier: this.proofVerifier,
|
|
1611
|
+
},
|
|
1612
|
+
peerScoring: this.peerManager,
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1447
1615
|
|
|
1448
|
-
|
|
1449
|
-
const
|
|
1450
|
-
|
|
1616
|
+
public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
|
|
1617
|
+
const validator = createTxValidatorForBlockProposalReceivedTxs(
|
|
1618
|
+
this.proofVerifier,
|
|
1619
|
+
{ l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
|
|
1620
|
+
this.logger.getBindings(),
|
|
1621
|
+
);
|
|
1451
1622
|
|
|
1452
|
-
await Promise.all(
|
|
1623
|
+
const results = await Promise.all(
|
|
1453
1624
|
txs.map(async tx => {
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
if (!outcome.allPassed) {
|
|
1457
|
-
throw new Error('Invalid tx detected', { cause: { outcome } });
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1625
|
+
const result = await validator.validateTx(tx);
|
|
1626
|
+
return result.result !== 'invalid';
|
|
1460
1627
|
}),
|
|
1461
1628
|
);
|
|
1629
|
+
if (results.some(value => value === false)) {
|
|
1630
|
+
throw new Error('Invalid tx detected');
|
|
1631
|
+
}
|
|
1462
1632
|
}
|
|
1463
1633
|
|
|
1464
|
-
/**
|
|
1465
|
-
|
|
1466
|
-
*
|
|
1467
|
-
* Each validator is a pair of a validator and a severity.
|
|
1468
|
-
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
1469
|
-
*
|
|
1470
|
-
* @param currentBlockNumber - The current synced block number.
|
|
1471
|
-
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
1472
|
-
* @returns The message validators.
|
|
1473
|
-
*/
|
|
1474
|
-
private async createMessageValidators(
|
|
1634
|
+
/** Creates the first stage (fast) validators for gossiped transactions. */
|
|
1635
|
+
protected async createFirstStageMessageValidators(
|
|
1475
1636
|
currentBlockNumber: BlockNumber,
|
|
1476
1637
|
nextSlotTimestamp: UInt64,
|
|
1477
|
-
): Promise<Record<string,
|
|
1638
|
+
): Promise<Record<string, TransactionValidator>> {
|
|
1478
1639
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
1479
|
-
const allowedInSetup =
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1640
|
+
const allowedInSetup = [
|
|
1641
|
+
...(await getDefaultAllowedSetupFunctions()),
|
|
1642
|
+
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
1643
|
+
];
|
|
1644
|
+
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1645
|
+
const l1Constants = await this.archiver.getL1Constants();
|
|
1646
|
+
|
|
1647
|
+
return createFirstStageTxValidationsForGossipedTransactions(
|
|
1484
1648
|
nextSlotTimestamp,
|
|
1485
|
-
|
|
1649
|
+
blockNumber,
|
|
1486
1650
|
this.worldStateSynchronizer,
|
|
1487
1651
|
gasFees,
|
|
1488
1652
|
this.config.l1ChainId,
|
|
1489
1653
|
this.config.rollupVersion,
|
|
1490
1654
|
protocolContractsHash,
|
|
1491
1655
|
this.archiver,
|
|
1492
|
-
this.proofVerifier,
|
|
1493
1656
|
!this.config.disableTransactions,
|
|
1494
1657
|
allowedInSetup,
|
|
1658
|
+
this.logger.getBindings(),
|
|
1659
|
+
{
|
|
1660
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
1661
|
+
maxBlockL2Gas: this.config.validateMaxL2BlockGas,
|
|
1662
|
+
maxBlockDAGas: this.config.validateMaxDABlockGas,
|
|
1663
|
+
},
|
|
1495
1664
|
);
|
|
1496
1665
|
}
|
|
1497
1666
|
|
|
1667
|
+
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
|
|
1668
|
+
protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
|
|
1669
|
+
return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1498
1672
|
/**
|
|
1499
1673
|
* Run validations on a tx.
|
|
1500
1674
|
* @param tx - The tx to validate.
|
|
@@ -1503,7 +1677,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1503
1677
|
*/
|
|
1504
1678
|
private async runValidations(
|
|
1505
1679
|
tx: Tx,
|
|
1506
|
-
messageValidators: Record<string,
|
|
1680
|
+
messageValidators: Record<string, TransactionValidator>,
|
|
1507
1681
|
): Promise<ValidationOutcome> {
|
|
1508
1682
|
const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
|
|
1509
1683
|
const { result } = await validator.validateTx(tx);
|
|
@@ -1512,8 +1686,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1512
1686
|
|
|
1513
1687
|
// A promise that resolves when all validations have been run
|
|
1514
1688
|
const allValidations = await Promise.all(validationPromises);
|
|
1515
|
-
const
|
|
1516
|
-
if (
|
|
1689
|
+
const failures = allValidations.filter(x => !x.isValid);
|
|
1690
|
+
if (failures.length > 0) {
|
|
1691
|
+
// Pick the most severe failure (lowest tolerance = harshest penalty)
|
|
1692
|
+
const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
|
|
1517
1693
|
return {
|
|
1518
1694
|
allPassed: false,
|
|
1519
1695
|
failure: {
|
|
@@ -1545,15 +1721,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1545
1721
|
return PeerErrorSeverity.HighToleranceError;
|
|
1546
1722
|
}
|
|
1547
1723
|
|
|
1548
|
-
const snapshotValidator = new DoubleSpendTxValidator(
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1724
|
+
const snapshotValidator = new DoubleSpendTxValidator(
|
|
1725
|
+
{
|
|
1726
|
+
nullifiersExist: async (nullifiers: Buffer[]) => {
|
|
1727
|
+
const merkleTree = this.worldStateSynchronizer.getSnapshot(
|
|
1728
|
+
BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
|
|
1729
|
+
);
|
|
1730
|
+
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
1731
|
+
return indices.map(index => index !== undefined);
|
|
1732
|
+
},
|
|
1555
1733
|
},
|
|
1556
|
-
|
|
1734
|
+
this.logger.getBindings(),
|
|
1735
|
+
);
|
|
1557
1736
|
|
|
1558
1737
|
const validSnapshot = await snapshotValidator.validateTx(tx);
|
|
1559
1738
|
if (validSnapshot.result !== 'valid') {
|
|
@@ -1574,55 +1753,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1574
1753
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1575
1754
|
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1576
1755
|
}))
|
|
1577
|
-
public async validateCheckpointAttestation(
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
return false;
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
return true;
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
/**
|
|
1589
|
-
* Validate a block proposal.
|
|
1590
|
-
*
|
|
1591
|
-
* @param block - The block proposal to validate.
|
|
1592
|
-
* @returns True if the block proposal is valid, false otherwise.
|
|
1593
|
-
*/
|
|
1594
|
-
@trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
|
|
1595
|
-
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1596
|
-
}))
|
|
1597
|
-
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
|
|
1598
|
-
const severity = await this.blockProposalValidator.validate(block);
|
|
1599
|
-
if (severity) {
|
|
1600
|
-
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1601
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1602
|
-
return false;
|
|
1603
|
-
}
|
|
1604
|
-
|
|
1605
|
-
return true;
|
|
1606
|
-
}
|
|
1756
|
+
public async validateCheckpointAttestation(
|
|
1757
|
+
peerId: PeerId,
|
|
1758
|
+
attestation: CheckpointAttestation,
|
|
1759
|
+
): Promise<P2PValidationResult> {
|
|
1760
|
+
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1607
1761
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
* @param checkpoint - The checkpoint proposal to validate.
|
|
1612
|
-
* @returns True if the checkpoint proposal is valid, false otherwise.
|
|
1613
|
-
*/
|
|
1614
|
-
@trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1615
|
-
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1616
|
-
}))
|
|
1617
|
-
public async validateCheckpointProposal(peerId: PeerId, checkpoint: CheckpointProposal): Promise<boolean> {
|
|
1618
|
-
const severity = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1619
|
-
if (severity) {
|
|
1620
|
-
this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1621
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1622
|
-
return false;
|
|
1762
|
+
if (result.result === 'reject') {
|
|
1763
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1764
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1623
1765
|
}
|
|
1624
1766
|
|
|
1625
|
-
return
|
|
1767
|
+
return result;
|
|
1626
1768
|
}
|
|
1627
1769
|
|
|
1628
1770
|
public getPeerScore(peerId: PeerId): number {
|