@aztec/p2p 0.0.1-commit.2ed92850 → 0.0.1-commit.43597cc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bootstrap/bootstrap.d.ts +4 -3
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +4 -4
- package/dest/client/factory.d.ts +3 -3
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +11 -8
- package/dest/client/interface.d.ts +9 -2
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +7 -4
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +24 -7
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
- package/dest/config.d.ts +16 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +7 -2
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +94 -87
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +411 -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 +351 -85
- 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/index.d.ts +2 -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 +1 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +2 -2
- package/dest/mem_pools/interface.d.ts +3 -3
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
- package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +43 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +103 -0
- package/dest/mem_pools/tx_pool_v2/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 +119 -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 +90 -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 +89 -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 +131 -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 +17 -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 +63 -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 +91 -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 +70 -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 +63 -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 +5 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/index.js +4 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +197 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.js +6 -0
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +71 -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 +95 -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 +99 -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 +332 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +55 -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 +156 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +69 -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 +748 -0
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +7 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.js +5 -5
- 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 +5 -4
- 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 +3 -2
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +3 -2
- package/dest/msg_validators/tx_validator/factory.d.ts +8 -3
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +21 -11
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +3 -2
- 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 +2 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
- package/dest/msg_validators/tx_validator/size_validator.d.ts +3 -1
- package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/size_validator.js +4 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +2 -2
- 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 +18 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +42 -0
- 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 +161 -0
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
- package/dest/services/gossipsub/topic_score_params.js +324 -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 +14 -3
- package/dest/services/libp2p/libp2p_service.d.ts +80 -33
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +352 -284
- package/dest/services/peer-manager/metrics.d.ts +2 -2
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +20 -5
- 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 +47 -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 +566 -0
- package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
- package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +37 -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 +151 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +139 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +21 -0
- package/dest/services/reqresp/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/interface.d.ts +3 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -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 +5 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +6 -4
- 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 +23 -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 +44 -13
- 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 +58 -22
- package/dest/services/service.d.ts +21 -1
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +4 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +9 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +5 -4
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +17 -10
- package/dest/services/tx_collection/index.d.ts +2 -1
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +1 -0
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +9 -2
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +48 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
- package/dest/services/tx_collection/proposal_tx_collector.js +49 -0
- package/dest/services/tx_collection/tx_collection.d.ts +4 -4
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +5 -5
- package/dest/services/tx_file_store/config.d.ts +18 -0
- package/dest/services/tx_file_store/config.d.ts.map +1 -0
- package/dest/services/tx_file_store/config.js +26 -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 +47 -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 +149 -0
- 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/reqresp-nodes.d.ts +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -1
- package/dest/test-helpers/test_tx_provider.d.ts +40 -0
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
- package/dest/test-helpers/test_tx_provider.js +41 -0
- package/dest/test-helpers/testbench-utils.d.ts +152 -0
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
- package/dest/test-helpers/testbench-utils.js +308 -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 +212 -131
- package/dest/testbench/worker_client_manager.d.ts +51 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +226 -44
- package/package.json +14 -14
- package/src/bootstrap/bootstrap.ts +7 -4
- package/src/client/factory.ts +13 -14
- package/src/client/interface.ts +13 -1
- package/src/client/p2p_client.ts +32 -8
- package/src/client/test/tx_proposal_collector/README.md +227 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +336 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
- package/src/config.ts +22 -2
- package/src/mem_pools/attestation_pool/attestation_pool.ts +444 -90
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +436 -100
- package/src/mem_pools/attestation_pool/index.ts +9 -2
- package/src/mem_pools/index.ts +1 -1
- package/src/mem_pools/instrumentation.ts +2 -1
- package/src/mem_pools/interface.ts +2 -2
- package/src/mem_pools/tx_pool_v2/README.md +209 -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/eviction/eviction_manager.ts +147 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +118 -0
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +111 -0
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +23 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +164 -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 +86 -0
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +72 -0
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +31 -0
- package/src/mem_pools/tx_pool_v2/index.ts +11 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +227 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +161 -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 +417 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +212 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +882 -0
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +10 -4
- package/src/msg_validators/proposal_validator/proposal_validator.ts +5 -5
- package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
- package/src/msg_validators/tx_validator/block_header_validator.ts +7 -8
- package/src/msg_validators/tx_validator/data_validator.ts +6 -2
- package/src/msg_validators/tx_validator/double_spend_validator.ts +4 -3
- package/src/msg_validators/tx_validator/factory.ts +64 -23
- package/src/msg_validators/tx_validator/gas_validator.ts +9 -3
- package/src/msg_validators/tx_validator/metadata_validator.ts +6 -3
- package/src/msg_validators/tx_validator/phases_validator.ts +5 -3
- package/src/msg_validators/tx_validator/size_validator.ts +6 -2
- package/src/msg_validators/tx_validator/timestamp_validator.ts +6 -3
- 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 +51 -0
- package/src/services/gossipsub/README.md +626 -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 +451 -0
- package/src/services/index.ts +1 -0
- package/src/services/libp2p/instrumentation.ts +15 -2
- package/src/services/libp2p/libp2p_service.ts +381 -305
- package/src/services/peer-manager/metrics.ts +21 -4
- package/src/services/peer-manager/peer_scoring.ts +29 -1
- package/src/services/reqresp/batch-tx-requester/README.md +305 -0
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
- package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
- package/src/services/reqresp/batch-tx-requester/interface.ts +57 -0
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +209 -0
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +16 -0
- package/src/services/reqresp/interface.ts +3 -0
- package/src/services/reqresp/metrics.ts +34 -9
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +7 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -11
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +57 -9
- package/src/services/reqresp/reqresp.ts +66 -19
- package/src/services/service.ts +24 -0
- package/src/services/tx_collection/config.ts +15 -1
- package/src/services/tx_collection/fast_tx_collection.ts +30 -17
- package/src/services/tx_collection/index.ts +5 -0
- package/src/services/tx_collection/instrumentation.ts +11 -2
- package/src/services/tx_collection/proposal_tx_collector.ts +112 -0
- package/src/services/tx_collection/tx_collection.ts +4 -4
- package/src/services/tx_file_store/config.ts +43 -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 +173 -0
- package/src/services/tx_provider_instrumentation.ts +11 -5
- package/src/test-helpers/index.ts +2 -0
- package/src/test-helpers/reqresp-nodes.ts +2 -1
- package/src/test-helpers/test_tx_provider.ts +64 -0
- package/src/test-helpers/testbench-utils.ts +362 -0
- package/src/testbench/p2p_client_testbench_worker.ts +321 -122
- package/src/testbench/worker_client_manager.ts +304 -47
- 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/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -320
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -264
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { randomInt } from '@aztec/foundation/crypto/random';
|
|
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';
|
|
@@ -46,7 +45,7 @@ import {
|
|
|
46
45
|
type GossipsubMessage,
|
|
47
46
|
gossipsub,
|
|
48
47
|
} from '@chainsafe/libp2p-gossipsub';
|
|
49
|
-
import { createPeerScoreParams
|
|
48
|
+
import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
50
49
|
import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
|
|
51
50
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
52
51
|
import { yamux } from '@chainsafe/libp2p-yamux';
|
|
@@ -60,58 +59,57 @@ import { ENR } from '@nethermindeth/enr';
|
|
|
60
59
|
import { createLibp2p } from 'libp2p';
|
|
61
60
|
|
|
62
61
|
import type { P2PConfig } from '../../config.js';
|
|
63
|
-
import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
|
|
64
62
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
65
63
|
import {
|
|
66
64
|
BlockProposalValidator,
|
|
67
65
|
CheckpointAttestationValidator,
|
|
68
66
|
CheckpointProposalValidator,
|
|
67
|
+
DoubleSpendTxValidator,
|
|
69
68
|
FishermanAttestationValidator,
|
|
70
|
-
|
|
69
|
+
getDefaultAllowedSetupFunctions,
|
|
71
70
|
} from '../../msg_validators/index.js';
|
|
72
71
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
73
|
-
import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
|
|
74
|
-
import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
|
|
75
72
|
import {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
TxProofValidator,
|
|
81
|
-
} from '../../msg_validators/tx_validator/index.js';
|
|
73
|
+
type MessageValidator,
|
|
74
|
+
createTxMessageValidators,
|
|
75
|
+
createTxReqRespValidator,
|
|
76
|
+
} from '../../msg_validators/tx_validator/factory.js';
|
|
82
77
|
import { GossipSubEvent } from '../../types/index.js';
|
|
83
78
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
84
79
|
import { getVersions } from '../../versioning.js';
|
|
85
80
|
import { AztecDatastore } from '../data_store.js';
|
|
86
81
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
87
82
|
import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
88
|
-
import { gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
83
|
+
import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
84
|
+
import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
|
|
89
85
|
import type { PeerManagerInterface } from '../peer-manager/interface.js';
|
|
90
86
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
91
87
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
88
|
+
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
92
89
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
93
90
|
import {
|
|
94
91
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
95
92
|
type ReqRespInterface,
|
|
93
|
+
type ReqRespResponse,
|
|
96
94
|
ReqRespSubProtocol,
|
|
97
95
|
type ReqRespSubProtocolHandler,
|
|
98
96
|
type ReqRespSubProtocolHandlers,
|
|
99
97
|
type ReqRespSubProtocolValidators,
|
|
100
98
|
type SubProtocolMap,
|
|
101
99
|
ValidationError,
|
|
102
|
-
} from '../reqresp/
|
|
103
|
-
import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
|
|
104
|
-
import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
100
|
+
} from '../reqresp/index.js';
|
|
105
101
|
import {
|
|
106
102
|
AuthRequest,
|
|
107
103
|
BlockTxsRequest,
|
|
108
104
|
BlockTxsResponse,
|
|
109
105
|
StatusMessage,
|
|
110
106
|
pingHandler,
|
|
107
|
+
reqGoodbyeHandler,
|
|
111
108
|
reqRespBlockHandler,
|
|
109
|
+
reqRespBlockTxsHandler,
|
|
112
110
|
reqRespStatusHandler,
|
|
113
111
|
reqRespTxHandler,
|
|
114
|
-
} from '../reqresp/
|
|
112
|
+
} from '../reqresp/index.js';
|
|
115
113
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
116
114
|
import type {
|
|
117
115
|
P2PBlockReceivedCallback,
|
|
@@ -130,9 +128,9 @@ interface ValidationResult {
|
|
|
130
128
|
type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
|
|
131
129
|
|
|
132
130
|
// REFACTOR: Unify with the type above
|
|
133
|
-
type ReceivedMessageValidationResult<T> =
|
|
134
|
-
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject
|
|
135
|
-
| { obj?:
|
|
131
|
+
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
132
|
+
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
133
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
136
134
|
|
|
137
135
|
/**
|
|
138
136
|
* Lib P2P implementation of the P2PService interface.
|
|
@@ -151,6 +149,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
151
149
|
|
|
152
150
|
private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
|
|
153
151
|
|
|
152
|
+
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */
|
|
153
|
+
private duplicateProposalCallback?: (info: {
|
|
154
|
+
slot: SlotNumber;
|
|
155
|
+
proposer: EthAddress;
|
|
156
|
+
type: 'checkpoint' | 'block';
|
|
157
|
+
}) => void;
|
|
158
|
+
|
|
154
159
|
/**
|
|
155
160
|
* Callback for when a block is received from a peer.
|
|
156
161
|
* @param block - The block received from the peer.
|
|
@@ -179,9 +184,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
179
184
|
protected node: PubSubLibp2p,
|
|
180
185
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
181
186
|
private reqresp: ReqRespInterface,
|
|
182
|
-
|
|
187
|
+
protected peerManager: PeerManagerInterface,
|
|
183
188
|
protected mempools: MemPools,
|
|
184
|
-
|
|
189
|
+
protected archiver: L2BlockSource & ContractDataSource,
|
|
185
190
|
private epochCache: EpochCacheInterface,
|
|
186
191
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
187
192
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
@@ -286,14 +291,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
286
291
|
|
|
287
292
|
const datastore = new AztecDatastore(peerStore);
|
|
288
293
|
|
|
289
|
-
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
|
|
294
|
+
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
|
|
290
295
|
|
|
291
296
|
const peerDiscoveryService = new DiscV5Service(
|
|
292
297
|
peerId,
|
|
293
298
|
config,
|
|
294
299
|
packageVersion,
|
|
295
300
|
telemetry,
|
|
296
|
-
createLogger(`${logger.module}:discv5_service
|
|
301
|
+
createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
|
|
297
302
|
);
|
|
298
303
|
|
|
299
304
|
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
@@ -307,11 +312,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
307
312
|
const versions = getVersions(config);
|
|
308
313
|
const protocolVersion = compressComponentVersions(versions);
|
|
309
314
|
|
|
310
|
-
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
311
|
-
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
312
|
-
const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
|
|
313
|
-
const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
|
|
314
|
-
|
|
315
315
|
const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
|
|
316
316
|
const directPeers = (
|
|
317
317
|
await Promise.all(
|
|
@@ -331,6 +331,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
331
331
|
|
|
332
332
|
const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
|
|
333
333
|
|
|
334
|
+
// Create dynamic topic score params based on network configuration
|
|
335
|
+
const l1Constants = epochCache.getL1Constants();
|
|
336
|
+
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
337
|
+
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
338
|
+
heartbeatIntervalMs: config.gossipsubInterval,
|
|
339
|
+
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
340
|
+
blockDurationMs: config.blockDurationMs,
|
|
341
|
+
});
|
|
342
|
+
|
|
334
343
|
const node = await createLibp2p({
|
|
335
344
|
start: false,
|
|
336
345
|
peerId,
|
|
@@ -426,35 +435,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
426
435
|
scoreParams: createPeerScoreParams({
|
|
427
436
|
// IPColocation factor can be disabled for local testing - default to -5
|
|
428
437
|
IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
|
|
429
|
-
topics:
|
|
430
|
-
[txTopic]: createTopicScoreParams({
|
|
431
|
-
topicWeight: 1,
|
|
432
|
-
invalidMessageDeliveriesWeight: -20,
|
|
433
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
434
|
-
}),
|
|
435
|
-
[blockProposalTopic]: createTopicScoreParams({
|
|
436
|
-
topicWeight: 1,
|
|
437
|
-
invalidMessageDeliveriesWeight: -20,
|
|
438
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
439
|
-
}),
|
|
440
|
-
[checkpointProposalTopic]: createTopicScoreParams({
|
|
441
|
-
topicWeight: 1,
|
|
442
|
-
invalidMessageDeliveriesWeight: -20,
|
|
443
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
444
|
-
}),
|
|
445
|
-
[checkpointAttestationTopic]: createTopicScoreParams({
|
|
446
|
-
topicWeight: 1,
|
|
447
|
-
invalidMessageDeliveriesWeight: -20,
|
|
448
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
449
|
-
}),
|
|
450
|
-
},
|
|
438
|
+
topics: topicScoreParams,
|
|
451
439
|
}),
|
|
452
440
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
453
441
|
components: (components: { connectionManager: ConnectionManager }) => ({
|
|
454
442
|
connectionManager: components.connectionManager,
|
|
455
443
|
}),
|
|
456
444
|
},
|
|
457
|
-
logger: createLibp2pComponentLogger(logger.module),
|
|
445
|
+
logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
|
|
458
446
|
});
|
|
459
447
|
|
|
460
448
|
const peerScoring = new PeerScoring(config, telemetry);
|
|
@@ -473,8 +461,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
473
461
|
epochCache,
|
|
474
462
|
);
|
|
475
463
|
|
|
476
|
-
//
|
|
477
|
-
|
|
464
|
+
// Configure application-specific scoring for gossipsub.
|
|
465
|
+
// The weight scales app score to align with gossipsub thresholds:
|
|
466
|
+
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
467
|
+
// - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
|
|
468
|
+
// Note: positive topic scores can offset penalties, so alignment is best-effort.
|
|
469
|
+
node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
|
|
478
470
|
node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
|
|
479
471
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
480
472
|
|
|
@@ -526,7 +518,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
526
518
|
};
|
|
527
519
|
|
|
528
520
|
if (!this.config.disableTransactions) {
|
|
529
|
-
const blockTxsHandler = reqRespBlockTxsHandler(
|
|
521
|
+
const blockTxsHandler = reqRespBlockTxsHandler(
|
|
522
|
+
this.mempools.attestationPool,
|
|
523
|
+
this.archiver,
|
|
524
|
+
this.mempools.txPool,
|
|
525
|
+
);
|
|
530
526
|
requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
|
|
531
527
|
}
|
|
532
528
|
|
|
@@ -642,6 +638,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
642
638
|
return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
|
|
643
639
|
}
|
|
644
640
|
|
|
641
|
+
public sendRequestToPeer(
|
|
642
|
+
peerId: PeerId,
|
|
643
|
+
subProtocol: ReqRespSubProtocol,
|
|
644
|
+
payload: Buffer,
|
|
645
|
+
dialTimeout?: number,
|
|
646
|
+
): Promise<ReqRespResponse> {
|
|
647
|
+
return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
|
|
648
|
+
}
|
|
649
|
+
|
|
645
650
|
/**
|
|
646
651
|
* Get the ENR of the node
|
|
647
652
|
* @returns The ENR of the node
|
|
@@ -658,6 +663,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
658
663
|
this.checkpointReceivedCallback = callback;
|
|
659
664
|
}
|
|
660
665
|
|
|
666
|
+
/**
|
|
667
|
+
* Registers a callback to be invoked when a duplicate proposal is detected.
|
|
668
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
669
|
+
*/
|
|
670
|
+
public registerDuplicateProposalCallback(
|
|
671
|
+
callback: (info: { slot: SlotNumber; proposer: EthAddress; type: 'checkpoint' | 'block' }) => void,
|
|
672
|
+
): void {
|
|
673
|
+
this.duplicateProposalCallback = callback;
|
|
674
|
+
}
|
|
675
|
+
|
|
661
676
|
/**
|
|
662
677
|
* Subscribes to a topic.
|
|
663
678
|
* @param topic - The topic to subscribe to.
|
|
@@ -844,13 +859,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
844
859
|
return;
|
|
845
860
|
}
|
|
846
861
|
|
|
847
|
-
protected async validateReceivedMessage<T>(
|
|
848
|
-
validationFunc: () => Promise<ReceivedMessageValidationResult<T>>,
|
|
862
|
+
protected async validateReceivedMessage<T, M = undefined>(
|
|
863
|
+
validationFunc: () => Promise<ReceivedMessageValidationResult<T, M>>,
|
|
849
864
|
msgId: string,
|
|
850
865
|
source: PeerId,
|
|
851
866
|
topicType: TopicType,
|
|
852
|
-
): Promise<ReceivedMessageValidationResult<T>> {
|
|
853
|
-
let resultAndObj: ReceivedMessageValidationResult<T> = { result: TopicValidatorResult.Reject };
|
|
867
|
+
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
868
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
|
|
854
869
|
const timer = new Timer();
|
|
855
870
|
try {
|
|
856
871
|
resultAndObj = await validationFunc();
|
|
@@ -922,47 +937,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
922
937
|
msgId: string,
|
|
923
938
|
source: PeerId,
|
|
924
939
|
): Promise<void> {
|
|
925
|
-
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointAttestation>> = async () => {
|
|
926
|
-
const attestation = CheckpointAttestation.fromBuffer(payloadData);
|
|
927
|
-
const pool = this.mempools.attestationPool;
|
|
928
|
-
const validationResult = await this.validateCheckpointAttestation(source, attestation);
|
|
929
|
-
const isValid = validationResult.result === 'accept';
|
|
930
|
-
const exists = isValid && (await pool.hasCheckpointAttestation(attestation));
|
|
931
|
-
|
|
932
|
-
let canAdd = true;
|
|
933
|
-
if (isValid && !exists) {
|
|
934
|
-
const slot = attestation.payload.header.slotNumber;
|
|
935
|
-
const { committee } = await this.epochCache.getCommittee(slot);
|
|
936
|
-
const committeeSize = committee?.length ?? 0;
|
|
937
|
-
canAdd = await pool.canAddCheckpointAttestation(attestation, committeeSize);
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
941
|
-
isValid,
|
|
942
|
-
exists,
|
|
943
|
-
canAdd,
|
|
944
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
945
|
-
[Attributes.P2P_ID]: source.toString(),
|
|
946
|
-
});
|
|
947
|
-
|
|
948
|
-
if (validationResult.result === 'reject') {
|
|
949
|
-
return { result: TopicValidatorResult.Reject };
|
|
950
|
-
} else if (validationResult.result === 'ignore' || exists) {
|
|
951
|
-
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
952
|
-
} else if (!canAdd) {
|
|
953
|
-
this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
|
|
954
|
-
slot: attestation.payload.header.slotNumber.toString(),
|
|
955
|
-
archive: attestation.archive.toString(),
|
|
956
|
-
source: source.toString(),
|
|
957
|
-
});
|
|
958
|
-
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
959
|
-
} else {
|
|
960
|
-
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
961
|
-
}
|
|
962
|
-
};
|
|
963
|
-
|
|
964
940
|
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
965
|
-
|
|
941
|
+
() => this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)),
|
|
966
942
|
msgId,
|
|
967
943
|
source,
|
|
968
944
|
TopicType.checkpoint_attestation,
|
|
@@ -972,8 +948,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
972
948
|
return;
|
|
973
949
|
}
|
|
974
950
|
|
|
975
|
-
this.logger.
|
|
976
|
-
`Received checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
951
|
+
this.logger.verbose(
|
|
952
|
+
`Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
977
953
|
{
|
|
978
954
|
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
979
955
|
slot: attestation.slotNumber,
|
|
@@ -981,60 +957,154 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
981
957
|
source: source.toString(),
|
|
982
958
|
},
|
|
983
959
|
);
|
|
984
|
-
|
|
985
|
-
await this.mempools.attestationPool.addCheckpointAttestations([attestation]);
|
|
986
960
|
}
|
|
987
961
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
962
|
+
/** Validates a checkpoint attestation and adds it to the pool. Penalizes the peer if validation fails. */
|
|
963
|
+
@trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation) => ({
|
|
964
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
965
|
+
}))
|
|
966
|
+
protected async validateAndStoreCheckpointAttestation(
|
|
967
|
+
peerId: PeerId,
|
|
968
|
+
attestation: CheckpointAttestation,
|
|
969
|
+
): Promise<ReceivedMessageValidationResult<CheckpointAttestation>> {
|
|
970
|
+
const validationResult = await this.checkpointAttestationValidator.validate(attestation);
|
|
994
971
|
|
|
995
|
-
|
|
996
|
-
|
|
972
|
+
if (validationResult.result === 'reject') {
|
|
973
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
974
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
975
|
+
return { result: TopicValidatorResult.Reject };
|
|
976
|
+
}
|
|
997
977
|
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
978
|
+
if (validationResult.result === 'ignore') {
|
|
979
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// Get committee size for the attestation's slot
|
|
983
|
+
const slot = attestation.payload.header.slotNumber;
|
|
984
|
+
const { committee } = await this.epochCache.getCommittee(slot);
|
|
985
|
+
const committeeSize = committee?.length ?? 0;
|
|
986
|
+
|
|
987
|
+
// Try to add the attestation: this handles existence check, cap check, and adding in one call
|
|
988
|
+
const { added, alreadyExists } = await this.mempools.attestationPool.tryAddCheckpointAttestation(
|
|
989
|
+
attestation,
|
|
990
|
+
committeeSize,
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
994
|
+
added,
|
|
995
|
+
alreadyExists,
|
|
996
|
+
[Attributes.SLOT_NUMBER]: slot.toString(),
|
|
997
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
// Duplicate attestation received, no need to re-broadcast
|
|
1001
|
+
if (alreadyExists) {
|
|
1002
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
// Could not add (cap reached), no need to re-broadcast
|
|
1006
|
+
if (!added) {
|
|
1007
|
+
this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
|
|
1008
|
+
slot: slot.toString(),
|
|
1009
|
+
archive: attestation.archive.toString(),
|
|
1010
|
+
source: peerId.toString(),
|
|
1004
1011
|
});
|
|
1012
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1013
|
+
}
|
|
1005
1014
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
return { result: TopicValidatorResult.Ignore, obj: block };
|
|
1010
|
-
} else if (!canAdd) {
|
|
1011
|
-
this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
|
|
1012
|
-
this.logger.warn(`Penalizing peer for block proposal exceeding per-slot cap`, {
|
|
1013
|
-
slot: block.slotNumber.toString(),
|
|
1014
|
-
archive: block.archive.toString(),
|
|
1015
|
-
source: source.toString(),
|
|
1016
|
-
});
|
|
1017
|
-
return { result: TopicValidatorResult.Reject };
|
|
1018
|
-
} else {
|
|
1019
|
-
return { result: TopicValidatorResult.Accept, obj: block };
|
|
1020
|
-
}
|
|
1021
|
-
};
|
|
1015
|
+
// Attestation was added successfully
|
|
1016
|
+
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
1017
|
+
}
|
|
1022
1018
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1019
|
+
protected async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1020
|
+
const {
|
|
1021
|
+
result,
|
|
1022
|
+
obj: block,
|
|
1023
|
+
metadata: { isEquivocated } = {},
|
|
1024
|
+
} = await this.validateReceivedMessage<BlockProposal, { isEquivocated: boolean }>(
|
|
1025
|
+
() => this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)),
|
|
1025
1026
|
msgId,
|
|
1026
1027
|
source,
|
|
1027
1028
|
TopicType.block_proposal,
|
|
1028
1029
|
);
|
|
1029
1030
|
|
|
1030
|
-
|
|
1031
|
+
// If not accepted or equivocated, return
|
|
1032
|
+
if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
|
|
1031
1033
|
return;
|
|
1032
1034
|
}
|
|
1033
1035
|
|
|
1034
1036
|
await this.processValidBlockProposal(block, source);
|
|
1035
1037
|
}
|
|
1036
1038
|
|
|
1037
|
-
|
|
1039
|
+
/** Validates a block proposal. Triggers a penalization to the peer that sent it if invalid. Adds to the mempool if valid. */
|
|
1040
|
+
@trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block) => ({
|
|
1041
|
+
[Attributes.BLOCK_NUMBER]: block.blockNumber.toString(),
|
|
1042
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1043
|
+
}))
|
|
1044
|
+
protected async validateAndStoreBlockProposal(
|
|
1045
|
+
peerId: PeerId,
|
|
1046
|
+
block: BlockProposal,
|
|
1047
|
+
): Promise<ReceivedMessageValidationResult<BlockProposal, { isEquivocated: boolean }>> {
|
|
1048
|
+
const validationResult = await this.blockProposalValidator.validate(block);
|
|
1049
|
+
|
|
1050
|
+
if (validationResult.result === 'reject') {
|
|
1051
|
+
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1052
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1053
|
+
return { result: TopicValidatorResult.Reject };
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
if (validationResult.result === 'ignore') {
|
|
1057
|
+
return { result: TopicValidatorResult.Ignore, obj: block };
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1061
|
+
const { added, alreadyExists, totalForPosition } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1062
|
+
const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
|
|
1063
|
+
|
|
1064
|
+
// Duplicate proposal received, no need to re-broadcast
|
|
1065
|
+
if (alreadyExists) {
|
|
1066
|
+
this.logger.debug(`Ignoring duplicate block proposal received`, {
|
|
1067
|
+
...block.toBlockInfo(),
|
|
1068
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1069
|
+
proposer: block.getSender()?.toString(),
|
|
1070
|
+
source: peerId.toString(),
|
|
1071
|
+
});
|
|
1072
|
+
return { result: TopicValidatorResult.Ignore, obj: block, metadata: { isEquivocated } };
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1076
|
+
if (!added) {
|
|
1077
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1078
|
+
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1079
|
+
...block.toBlockInfo(),
|
|
1080
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1081
|
+
totalForPosition,
|
|
1082
|
+
proposer: block.getSender()?.toString(),
|
|
1083
|
+
source: peerId.toString(),
|
|
1084
|
+
});
|
|
1085
|
+
return { result: TopicValidatorResult.Reject, metadata: { isEquivocated } };
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1089
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1090
|
+
if (isEquivocated) {
|
|
1091
|
+
const proposer = block.getSender();
|
|
1092
|
+
this.logger.warn(`Detected duplicate block proposal (equivocation) at slot ${block.slotNumber}`, {
|
|
1093
|
+
...block.toBlockInfo(),
|
|
1094
|
+
source: peerId.toString(),
|
|
1095
|
+
proposer: proposer?.toString(),
|
|
1096
|
+
});
|
|
1097
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1098
|
+
if (proposer && totalForPosition === 2) {
|
|
1099
|
+
this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
|
|
1100
|
+
}
|
|
1101
|
+
return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// Otherwise, we're good to go!
|
|
1105
|
+
return { result: TopicValidatorResult.Accept, obj: block };
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1038
1108
|
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
1039
1109
|
// should not be here as it does not deal with p2p networking.
|
|
1040
1110
|
@trackSpan('Libp2pService.processValidBlockProposal', async block => ({
|
|
@@ -1042,7 +1112,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1042
1112
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
1043
1113
|
[Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1044
1114
|
}))
|
|
1045
|
-
|
|
1115
|
+
protected async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
|
|
1046
1116
|
const slot = block.slotNumber;
|
|
1047
1117
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1048
1118
|
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
@@ -1050,22 +1120,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1050
1120
|
...block.toBlockInfo(),
|
|
1051
1121
|
});
|
|
1052
1122
|
|
|
1053
|
-
// Attempt to add proposal
|
|
1054
|
-
try {
|
|
1055
|
-
await this.mempools.attestationPool.addBlockProposal(block);
|
|
1056
|
-
} catch (err: unknown) {
|
|
1057
|
-
// Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
|
|
1058
|
-
if (err instanceof ProposalSlotCapExceededError) {
|
|
1059
|
-
this.logger.warn(`Dropping block proposal due to per-slot proposal cap`, {
|
|
1060
|
-
slot: String(slot),
|
|
1061
|
-
archive: block.archive.toString(),
|
|
1062
|
-
error: (err as Error).message,
|
|
1063
|
-
});
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
throw err;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
1123
|
// Mark the txs in this proposal as non-evictable
|
|
1070
1124
|
await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
|
|
1071
1125
|
|
|
@@ -1081,67 +1135,145 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1081
1135
|
* Handle a gossiped checkpoint proposal.
|
|
1082
1136
|
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1083
1137
|
*/
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1138
|
+
protected async handleGossipedCheckpointProposal(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1139
|
+
const {
|
|
1140
|
+
result,
|
|
1141
|
+
obj: checkpoint,
|
|
1142
|
+
metadata: { isEquivocated, processBlock } = {},
|
|
1143
|
+
} = await this.validateReceivedMessage<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>(
|
|
1144
|
+
() => this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)),
|
|
1145
|
+
msgId,
|
|
1146
|
+
source,
|
|
1147
|
+
TopicType.checkpoint_proposal,
|
|
1148
|
+
);
|
|
1149
|
+
|
|
1150
|
+
// If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
|
|
1151
|
+
// TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
|
|
1152
|
+
if (processBlock && checkpoint?.getBlockProposal()) {
|
|
1153
|
+
await this.processValidBlockProposal(checkpoint.getBlockProposal()!, source);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
await this.processValidCheckpointProposal(checkpoint.toCore(), source);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
|
|
1165
|
+
* its last block (if present) to the mempool if valid. Triggers equivocation detection on both.
|
|
1166
|
+
*/
|
|
1167
|
+
@trackSpan('Libp2pService.validateAndStoreCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1168
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1169
|
+
}))
|
|
1170
|
+
protected async validateAndStoreCheckpointProposal(
|
|
1171
|
+
peerId: PeerId,
|
|
1172
|
+
checkpoint: CheckpointProposal,
|
|
1173
|
+
): Promise<ReceivedMessageValidationResult<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>> {
|
|
1174
|
+
const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1175
|
+
|
|
1176
|
+
if (validationResult.result === 'reject') {
|
|
1177
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1178
|
+
this.peerManager.penalizePeer(peerId, validationResult.severity);
|
|
1179
|
+
return { result: TopicValidatorResult.Reject };
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
if (validationResult.result === 'ignore') {
|
|
1183
|
+
return { result: TopicValidatorResult.Ignore, obj: checkpoint };
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// Extract and try to add the block proposal first if present
|
|
1187
|
+
const blockProposal = checkpoint.getBlockProposal();
|
|
1188
|
+
let processBlock = false;
|
|
1189
|
+
if (blockProposal) {
|
|
1190
|
+
this.logger.debug(`Validating block proposal from propagated checkpoint`, {
|
|
1099
1191
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1100
|
-
[Attributes.P2P_ID]:
|
|
1192
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1101
1193
|
});
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
this.
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1194
|
+
const {
|
|
1195
|
+
result,
|
|
1196
|
+
obj,
|
|
1197
|
+
metadata: { isEquivocated } = {},
|
|
1198
|
+
} = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1199
|
+
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1200
|
+
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1201
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1202
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
1203
|
+
isEquivocated,
|
|
1204
|
+
result,
|
|
1113
1205
|
});
|
|
1114
1206
|
return { result: TopicValidatorResult.Reject };
|
|
1115
|
-
} else {
|
|
1116
|
-
|
|
1207
|
+
} else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1208
|
+
processBlock = true;
|
|
1117
1209
|
}
|
|
1118
|
-
}
|
|
1210
|
+
}
|
|
1119
1211
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1212
|
+
// Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
|
|
1213
|
+
const checkpointCore = checkpoint.toCore();
|
|
1214
|
+
const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
|
|
1215
|
+
const { added, alreadyExists, totalForPosition } = tryAddResult;
|
|
1216
|
+
const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
|
|
1217
|
+
|
|
1218
|
+
// Duplicate proposal received, do not re-broadcast
|
|
1219
|
+
if (alreadyExists) {
|
|
1220
|
+
this.logger.debug(`Ignoring duplicate checkpoint proposal received`, {
|
|
1221
|
+
...checkpoint.toCheckpointInfo(),
|
|
1222
|
+
source: peerId.toString(),
|
|
1223
|
+
});
|
|
1224
|
+
return {
|
|
1225
|
+
result: TopicValidatorResult.Ignore,
|
|
1226
|
+
obj: checkpoint,
|
|
1227
|
+
metadata: { isEquivocated, processBlock },
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1126
1230
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1231
|
+
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1232
|
+
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1233
|
+
if (!added) {
|
|
1234
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1235
|
+
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1236
|
+
...checkpoint.toCheckpointInfo(),
|
|
1237
|
+
totalForPosition,
|
|
1238
|
+
source: peerId.toString(),
|
|
1239
|
+
});
|
|
1240
|
+
return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1244
|
+
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1245
|
+
if (isEquivocated) {
|
|
1246
|
+
const proposer = checkpoint.getSender();
|
|
1247
|
+
this.logger.warn(`Detected duplicate checkpoint proposal (equivocation) at slot ${checkpoint.slotNumber}`, {
|
|
1248
|
+
...checkpoint.toCheckpointInfo(),
|
|
1249
|
+
source: peerId.toString(),
|
|
1250
|
+
proposer: proposer?.toString(),
|
|
1251
|
+
});
|
|
1252
|
+
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1253
|
+
if (proposer && totalForPosition === 2) {
|
|
1254
|
+
this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
|
|
1255
|
+
}
|
|
1256
|
+
return {
|
|
1257
|
+
result: TopicValidatorResult.Accept,
|
|
1258
|
+
obj: checkpoint,
|
|
1259
|
+
metadata: { isEquivocated, processBlock },
|
|
1260
|
+
};
|
|
1129
1261
|
}
|
|
1130
1262
|
|
|
1131
|
-
|
|
1263
|
+
// Otherwise, we're good to go!
|
|
1264
|
+
return { result: TopicValidatorResult.Accept, obj: checkpoint, metadata: { processBlock, isEquivocated } };
|
|
1132
1265
|
}
|
|
1133
1266
|
|
|
1134
1267
|
/**
|
|
1135
1268
|
* Process a validated checkpoint proposal.
|
|
1136
|
-
*
|
|
1137
|
-
* The block callback is invoked before the checkpoint callback.
|
|
1269
|
+
* Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
|
|
1138
1270
|
*/
|
|
1139
1271
|
@trackSpan('Libp2pService.processValidCheckpointProposal', async checkpoint => ({
|
|
1140
1272
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
|
|
1141
1273
|
[Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
|
|
1142
1274
|
[Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1143
1275
|
}))
|
|
1144
|
-
|
|
1276
|
+
protected async processValidCheckpointProposal(checkpoint: CheckpointProposalCore, sender: PeerId) {
|
|
1145
1277
|
const slot = checkpoint.slotNumber;
|
|
1146
1278
|
this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1147
1279
|
p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
|
|
@@ -1150,37 +1282,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1150
1282
|
source: sender.toString(),
|
|
1151
1283
|
});
|
|
1152
1284
|
|
|
1153
|
-
// Extract block proposal before adding to pool (pool stores them separately)
|
|
1154
|
-
const blockProposal = checkpoint.getBlockProposal();
|
|
1155
|
-
|
|
1156
|
-
// Add proposal to the pool (this extracts and stores block proposal separately)
|
|
1157
|
-
await this.mempools.attestationPool.addCheckpointProposal(checkpoint);
|
|
1158
|
-
|
|
1159
|
-
// Mark txs as non-evictable if present (from the last block)
|
|
1160
|
-
if (checkpoint.txHashes.length > 0) {
|
|
1161
|
-
await this.mempools.txPool.markTxsAsNonEvictable(checkpoint.txHashes);
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
// If there was a last block proposal, invoke the block callback first for validation.
|
|
1165
|
-
// Note: The block proposal is already stored in the pool by addCheckpointProposal.
|
|
1166
|
-
if (blockProposal) {
|
|
1167
|
-
const isValid = await this.blockReceivedCallback(blockProposal, sender);
|
|
1168
|
-
if (!isValid) {
|
|
1169
|
-
this.logger.warn(`Block proposal from checkpoint failed validation`, {
|
|
1170
|
-
slot: slot.toString(),
|
|
1171
|
-
archive: checkpoint.archive.toString(),
|
|
1172
|
-
blockNumber: blockProposal.blockNumber.toString(),
|
|
1173
|
-
});
|
|
1174
|
-
return;
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
1285
|
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1179
1286
|
// to validate and potentially generate attestations
|
|
1180
|
-
const attestations = await this.checkpointReceivedCallback(checkpoint
|
|
1287
|
+
const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
|
|
1181
1288
|
if (attestations && attestations.length > 0) {
|
|
1182
1289
|
// If the callback returned attestations, add them to the pool and propagate them
|
|
1183
|
-
await this.mempools.attestationPool.
|
|
1290
|
+
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
1184
1291
|
for (const attestation of attestations) {
|
|
1185
1292
|
await this.propagate(attestation);
|
|
1186
1293
|
}
|
|
@@ -1207,9 +1314,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1207
1314
|
* @returns True if the requested block transactions are valid, false otherwise.
|
|
1208
1315
|
*/
|
|
1209
1316
|
@trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
|
|
1210
|
-
[Attributes.
|
|
1317
|
+
[Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
|
|
1211
1318
|
}))
|
|
1212
|
-
|
|
1319
|
+
protected async validateRequestedBlockTxs(
|
|
1213
1320
|
request: BlockTxsRequest,
|
|
1214
1321
|
response: BlockTxsResponse,
|
|
1215
1322
|
peerId: PeerId,
|
|
@@ -1217,10 +1324,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1217
1324
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
1218
1325
|
|
|
1219
1326
|
try {
|
|
1220
|
-
if (!response.
|
|
1327
|
+
if (!response.archiveRoot.equals(request.archiveRoot)) {
|
|
1221
1328
|
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1222
1329
|
throw new ValidationError(
|
|
1223
|
-
`Received block txs for unexpected
|
|
1330
|
+
`Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`,
|
|
1224
1331
|
);
|
|
1225
1332
|
}
|
|
1226
1333
|
|
|
@@ -1250,7 +1357,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1250
1357
|
}
|
|
1251
1358
|
|
|
1252
1359
|
// Given proposal (should have locally), ensure returned txs are valid subset and match request indices
|
|
1253
|
-
const proposal = await this.mempools.attestationPool.getBlockProposal(request.
|
|
1360
|
+
const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
|
|
1254
1361
|
if (proposal) {
|
|
1255
1362
|
// Build intersected indices
|
|
1256
1363
|
const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
|
|
@@ -1270,7 +1377,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1270
1377
|
} else {
|
|
1271
1378
|
// No local proposal, cannot check the membership/order of the returned txs
|
|
1272
1379
|
this.logger.warn(
|
|
1273
|
-
`Block proposal not found for
|
|
1380
|
+
`Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`,
|
|
1274
1381
|
);
|
|
1275
1382
|
return false;
|
|
1276
1383
|
}
|
|
@@ -1309,7 +1416,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1309
1416
|
const requested = new Set(requestedTxHash.map(h => h.toString()));
|
|
1310
1417
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
1311
1418
|
|
|
1312
|
-
//TODO: (mralj) - this is somewhat naive implementation, if single tx is
|
|
1419
|
+
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
|
|
1313
1420
|
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
1314
1421
|
try {
|
|
1315
1422
|
await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
|
|
@@ -1339,7 +1446,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1339
1446
|
@trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
|
|
1340
1447
|
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
|
|
1341
1448
|
}))
|
|
1342
|
-
|
|
1449
|
+
protected async validateRequestedBlock(
|
|
1343
1450
|
requestedBlockNumber: Fr,
|
|
1344
1451
|
responseBlock: L2Block,
|
|
1345
1452
|
peerId: PeerId,
|
|
@@ -1372,28 +1479,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1372
1479
|
}
|
|
1373
1480
|
}
|
|
1374
1481
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
rollupVersion: new Fr(this.config.rollupVersion),
|
|
1382
|
-
protocolContractsHash,
|
|
1383
|
-
vkTreeRoot: getVKTreeRoot(),
|
|
1384
|
-
}),
|
|
1385
|
-
new TxProofValidator(this.proofVerifier),
|
|
1386
|
-
);
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
private async validateRequestedTx(tx: Tx, peerId: PeerId, txValidator: TxValidator, requested?: Set<`0x${string}`>) {
|
|
1482
|
+
protected async validateRequestedTx(
|
|
1483
|
+
tx: Tx,
|
|
1484
|
+
peerId: PeerId,
|
|
1485
|
+
txValidator: TxValidator,
|
|
1486
|
+
requested?: Set<`0x${string}`>,
|
|
1487
|
+
) {
|
|
1390
1488
|
const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
|
|
1391
|
-
|
|
1392
|
-
if (!(await tx.validateTxHash())) {
|
|
1393
|
-
penalize(PeerErrorSeverity.MidToleranceError);
|
|
1394
|
-
throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
1489
|
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
1398
1490
|
penalize(PeerErrorSeverity.MidToleranceError);
|
|
1399
1491
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
@@ -1406,6 +1498,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1406
1498
|
}
|
|
1407
1499
|
}
|
|
1408
1500
|
|
|
1501
|
+
protected createRequestedTxValidator(): TxValidator {
|
|
1502
|
+
return createTxReqRespValidator(this.proofVerifier, {
|
|
1503
|
+
l1ChainId: this.config.l1ChainId,
|
|
1504
|
+
rollupVersion: this.config.rollupVersion,
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1409
1508
|
@trackSpan('Libp2pService.validatePropagatedTx', tx => ({
|
|
1410
1509
|
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
1411
1510
|
}))
|
|
@@ -1448,6 +1547,22 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1448
1547
|
return gasFees;
|
|
1449
1548
|
}
|
|
1450
1549
|
|
|
1550
|
+
/**
|
|
1551
|
+
* Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
|
|
1552
|
+
*/
|
|
1553
|
+
public getBatchTxRequesterService(): BatchTxRequesterLibP2PService {
|
|
1554
|
+
return {
|
|
1555
|
+
reqResp: this.reqresp,
|
|
1556
|
+
connectionSampler: this.reqresp.getConnectionSampler(),
|
|
1557
|
+
txValidatorConfig: {
|
|
1558
|
+
l1ChainId: this.config.l1ChainId,
|
|
1559
|
+
rollupVersion: this.config.rollupVersion,
|
|
1560
|
+
proofVerifier: this.proofVerifier,
|
|
1561
|
+
},
|
|
1562
|
+
peerScoring: this.peerManager,
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1451
1566
|
public async validate(txs: Tx[]): Promise<void> {
|
|
1452
1567
|
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1453
1568
|
|
|
@@ -1498,6 +1613,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1498
1613
|
this.proofVerifier,
|
|
1499
1614
|
!this.config.disableTransactions,
|
|
1500
1615
|
allowedInSetup,
|
|
1616
|
+
this.logger.getBindings(),
|
|
1501
1617
|
);
|
|
1502
1618
|
}
|
|
1503
1619
|
|
|
@@ -1551,15 +1667,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1551
1667
|
return PeerErrorSeverity.HighToleranceError;
|
|
1552
1668
|
}
|
|
1553
1669
|
|
|
1554
|
-
const snapshotValidator = new DoubleSpendTxValidator(
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1670
|
+
const snapshotValidator = new DoubleSpendTxValidator(
|
|
1671
|
+
{
|
|
1672
|
+
nullifiersExist: async (nullifiers: Buffer[]) => {
|
|
1673
|
+
const merkleTree = this.worldStateSynchronizer.getSnapshot(
|
|
1674
|
+
BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
|
|
1675
|
+
);
|
|
1676
|
+
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
1677
|
+
return indices.map(index => index !== undefined);
|
|
1678
|
+
},
|
|
1561
1679
|
},
|
|
1562
|
-
|
|
1680
|
+
this.logger.getBindings(),
|
|
1681
|
+
);
|
|
1563
1682
|
|
|
1564
1683
|
const validSnapshot = await snapshotValidator.validateTx(tx);
|
|
1565
1684
|
if (validSnapshot.result !== 'valid') {
|
|
@@ -1587,50 +1706,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1587
1706
|
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1588
1707
|
|
|
1589
1708
|
if (result.result === 'reject') {
|
|
1590
|
-
this.logger.
|
|
1591
|
-
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
return result;
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
/**
|
|
1598
|
-
* Validate a block proposal.
|
|
1599
|
-
*
|
|
1600
|
-
* @param block - The block proposal to validate.
|
|
1601
|
-
* @returns True if the block proposal is valid, false otherwise.
|
|
1602
|
-
*/
|
|
1603
|
-
@trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
|
|
1604
|
-
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1605
|
-
}))
|
|
1606
|
-
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<P2PValidationResult> {
|
|
1607
|
-
const result = await this.blockProposalValidator.validate(block);
|
|
1608
|
-
|
|
1609
|
-
if (result.result === 'reject') {
|
|
1610
|
-
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1611
|
-
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
|
-
return result;
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
/**
|
|
1618
|
-
* Validate a checkpoint proposal.
|
|
1619
|
-
*
|
|
1620
|
-
* @param checkpoint - The checkpoint proposal to validate.
|
|
1621
|
-
* @returns True if the checkpoint proposal is valid, false otherwise.
|
|
1622
|
-
*/
|
|
1623
|
-
@trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1624
|
-
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1625
|
-
}))
|
|
1626
|
-
public async validateCheckpointProposal(
|
|
1627
|
-
peerId: PeerId,
|
|
1628
|
-
checkpoint: CheckpointProposal,
|
|
1629
|
-
): Promise<P2PValidationResult> {
|
|
1630
|
-
const result = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1631
|
-
|
|
1632
|
-
if (result.result === 'reject') {
|
|
1633
|
-
this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1709
|
+
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1634
1710
|
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1635
1711
|
}
|
|
1636
1712
|
|