@aztec/p2p 0.0.1-commit.e558bd1c → 0.0.1-commit.e5a3663dd
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/client/factory.d.ts +10 -9
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +54 -15
- package/dest/client/interface.d.ts +47 -34
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +39 -51
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +173 -226
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +23 -10
- package/dest/config.d.ts +137 -92
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +113 -40
- package/dest/errors/p2p-service.error.d.ts +9 -0
- package/dest/errors/p2p-service.error.d.ts.map +1 -0
- package/dest/errors/p2p-service.error.js +10 -0
- 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 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +24 -13
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +80 -43
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- 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 +57 -57
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +7 -5
- package/dest/mem_pools/index.d.ts +2 -2
- package/dest/mem_pools/index.d.ts.map +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 +33 -15
- 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/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 +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +7 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +12 -4
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +3 -2
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +2 -1
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +54 -5
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +9 -7
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/index.d.ts +3 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +2 -1
- 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 +33 -12
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +5 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +81 -15
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +147 -19
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +50 -45
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +12 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +17 -6
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +14 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +365 -189
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +9 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +37 -12
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -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 +2 -2
- package/dest/msg_validators/clock_tolerance.d.ts +12 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +61 -3
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -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 +9 -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 +19 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +88 -44
- 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.js +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +16 -3
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +35 -2
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +13 -3
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
- package/dest/msg_validators/tx_validator/factory.d.ts +133 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +247 -60
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +99 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +137 -53
- package/dest/msg_validators/tx_validator/index.d.ts +3 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +2 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
- 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 +22 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +20 -4
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- 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 +5 -5
- package/dest/services/dummy_service.d.ts +13 -6
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +13 -5
- package/dest/services/encoding.d.ts +7 -3
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +18 -11
- 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 +184 -0
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
- package/dest/services/gossipsub/topic_score_params.js +363 -0
- package/dest/services/libp2p/instrumentation.d.ts +3 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +14 -0
- package/dest/services/libp2p/libp2p_service.d.ts +42 -39
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +336 -269
- package/dest/services/peer-manager/metrics.d.ts +3 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +6 -0
- package/dest/services/peer-manager/peer_manager.d.ts +6 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +39 -11
- package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +57 -12
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +12 -8
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +83 -106
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +4 -7
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +11 -13
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +31 -46
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -11
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +52 -15
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- package/dest/services/reqresp/config.d.ts +3 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/interface.d.ts +23 -9
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +23 -10
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +0 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +3 -3
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +7 -1
- 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 +15 -0
- package/dest/services/reqresp/protocols/index.d.ts +1 -2
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +0 -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 +21 -3
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
- package/dest/services/reqresp/reqresp.d.ts +4 -2
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +40 -15
- package/dest/services/service.d.ts +26 -4
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +19 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +46 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +3 -4
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +80 -76
- 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 +38 -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 +100 -0
- 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 +2 -1
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -7
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
- package/dest/services/tx_collection/request_tracker.d.ts +53 -0
- package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/request_tracker.js +84 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +7 -3
- 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 +23 -13
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +75 -3
- 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 +13 -7
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +26 -7
- package/dest/services/tx_file_store/config.d.ts +1 -3
- package/dest/services/tx_file_store/config.d.ts.map +1 -1
- package/dest/services/tx_file_store/config.js +0 -4
- package/dest/services/tx_file_store/tx_file_store.d.ts +4 -3
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +9 -6
- package/dest/services/tx_provider.d.ts +4 -4
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +9 -8
- 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 +4 -2
- package/dest/test-helpers/mock-pubsub.d.ts +40 -6
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +139 -13
- 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 +8 -5
- package/dest/test-helpers/testbench-utils.d.ts +35 -24
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +125 -38
- package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +84 -27
- package/dest/testbench/worker_client_manager.d.ts +10 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +55 -3
- package/dest/util.d.ts +3 -3
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +108 -26
- package/src/client/interface.ts +52 -34
- package/src/client/p2p_client.ts +201 -269
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +35 -14
- package/src/config.ts +181 -46
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/index.ts +1 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +109 -53
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +61 -57
- package/src/mem_pools/attestation_pool/index.ts +3 -3
- package/src/mem_pools/attestation_pool/mocks.ts +14 -8
- package/src/mem_pools/index.ts +1 -1
- package/src/mem_pools/instrumentation.ts +22 -14
- package/src/mem_pools/interface.ts +2 -2
- package/src/mem_pools/tx_pool_v2/README.md +85 -11
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +7 -3
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -4
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +5 -0
- package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +59 -4
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +8 -8
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
- package/src/mem_pools/tx_pool_v2/index.ts +2 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +35 -12
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +215 -27
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +58 -45
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +34 -8
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +412 -187
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +41 -9
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +12 -2
- package/src/msg_validators/clock_tolerance.ts +79 -3
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +23 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +34 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +111 -47
- package/src/msg_validators/tx_validator/README.md +127 -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 +1 -1
- package/src/msg_validators/tx_validator/block_header_validator.ts +15 -3
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +42 -1
- package/src/msg_validators/tx_validator/double_spend_validator.ts +11 -6
- package/src/msg_validators/tx_validator/factory.ts +396 -78
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +199 -54
- package/src/msg_validators/tx_validator/index.ts +2 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
- package/src/msg_validators/tx_validator/timestamp_validator.ts +23 -18
- package/src/services/data_store.ts +5 -13
- package/src/services/dummy_service.ts +19 -7
- package/src/services/encoding.ts +18 -10
- 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 +519 -0
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +358 -298
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +45 -11
- package/src/services/peer-manager/peer_scoring.ts +52 -5
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/README.md +46 -7
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +79 -112
- package/src/services/reqresp/batch-tx-requester/interface.ts +3 -6
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +30 -71
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/config.ts +2 -2
- package/src/services/reqresp/interface.ts +45 -10
- package/src/services/reqresp/metrics.ts +0 -1
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +2 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +17 -0
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +23 -3
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
- package/src/services/reqresp/reqresp.ts +53 -16
- package/src/services/service.ts +37 -3
- package/src/services/tx_collection/config.ts +68 -0
- package/src/services/tx_collection/fast_tx_collection.ts +83 -76
- package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
- package/src/services/tx_collection/file_store_tx_source.ts +129 -0
- package/src/services/tx_collection/index.ts +1 -0
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/proposal_tx_collector.ts +9 -13
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/slow_tx_collection.ts +66 -33
- package/src/services/tx_collection/tx_collection.ts +114 -19
- package/src/services/tx_collection/tx_collection_sink.ts +30 -34
- package/src/services/tx_collection/tx_source.ts +28 -8
- package/src/services/tx_file_store/config.ts +0 -6
- package/src/services/tx_file_store/tx_file_store.ts +10 -8
- package/src/services/tx_provider.ts +10 -9
- package/src/test-helpers/make-test-p2p-clients.ts +6 -6
- package/src/test-helpers/mock-pubsub.ts +180 -14
- package/src/test-helpers/reqresp-nodes.ts +9 -9
- package/src/test-helpers/testbench-utils.ts +147 -43
- package/src/testbench/p2p_client_testbench_worker.ts +93 -30
- package/src/testbench/worker_client_manager.ts +68 -6
- package/src/util.ts +8 -2
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
- package/dest/mem_pools/tx_pool/index.d.ts +0 -3
- package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/index.js +0 -2
- package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
- package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/priority.js +0 -15
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
- 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 -212
- package/dest/services/reqresp/protocols/block.d.ts +0 -9
- package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
- package/dest/services/reqresp/protocols/block.js +0 -32
- package/src/mem_pools/tx_pool/README.md +0 -270
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
- package/src/mem_pools/tx_pool/index.ts +0 -2
- package/src/mem_pools/tx_pool/priority.ts +0 -20
- package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
- package/src/services/reqresp/protocols/block.ts +0 -37
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import {
|
|
4
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import { maxBy, merge } from '@aztec/foundation/collection';
|
|
5
4
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
6
5
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
7
6
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
7
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
9
8
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
10
|
-
import type { EthAddress,
|
|
9
|
+
import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
|
|
11
10
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
12
|
-
import { GasFees } from '@aztec/stdlib/gas';
|
|
11
|
+
import { type BlockMinFeesProvider, GasFees } from '@aztec/stdlib/gas';
|
|
13
12
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
14
13
|
import {
|
|
15
14
|
BlockProposal,
|
|
@@ -17,13 +16,12 @@ import {
|
|
|
17
16
|
CheckpointProposal,
|
|
18
17
|
type CheckpointProposalCore,
|
|
19
18
|
type Gossipable,
|
|
20
|
-
P2PClientType,
|
|
21
19
|
P2PMessage,
|
|
22
|
-
type ValidationResult as P2PValidationResult,
|
|
23
20
|
PeerErrorSeverity,
|
|
21
|
+
PeerErrorSeverityByHarshness,
|
|
24
22
|
TopicType,
|
|
25
23
|
createTopicString,
|
|
26
|
-
|
|
24
|
+
getTopicsForConfig,
|
|
27
25
|
metricsTopicStrToLabels,
|
|
28
26
|
} from '@aztec/stdlib/p2p';
|
|
29
27
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -45,7 +43,7 @@ import {
|
|
|
45
43
|
type GossipsubMessage,
|
|
46
44
|
gossipsub,
|
|
47
45
|
} from '@chainsafe/libp2p-gossipsub';
|
|
48
|
-
import { createPeerScoreParams
|
|
46
|
+
import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
49
47
|
import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
|
|
50
48
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
51
49
|
import { yamux } from '@chainsafe/libp2p-yamux';
|
|
@@ -59,6 +57,7 @@ import { ENR } from '@nethermindeth/enr';
|
|
|
59
57
|
import { createLibp2p } from 'libp2p';
|
|
60
58
|
|
|
61
59
|
import type { P2PConfig } from '../../config.js';
|
|
60
|
+
import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
|
|
62
61
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
63
62
|
import {
|
|
64
63
|
BlockProposalValidator,
|
|
@@ -70,9 +69,11 @@ import {
|
|
|
70
69
|
} from '../../msg_validators/index.js';
|
|
71
70
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
72
71
|
import {
|
|
73
|
-
type
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
type TransactionValidator,
|
|
73
|
+
createFirstStageTxValidationsForGossipedTransactions,
|
|
74
|
+
createSecondStageTxValidationsForGossipedTransactions,
|
|
75
|
+
createTxValidatorForBlockProposalReceivedTxs,
|
|
76
|
+
createTxValidatorForReqResponseReceivedTxs,
|
|
76
77
|
} from '../../msg_validators/tx_validator/factory.js';
|
|
77
78
|
import { GossipSubEvent } from '../../types/index.js';
|
|
78
79
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
@@ -80,13 +81,17 @@ import { getVersions } from '../../versioning.js';
|
|
|
80
81
|
import { AztecDatastore } from '../data_store.js';
|
|
81
82
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
82
83
|
import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
83
|
-
import { gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
84
|
+
import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
85
|
+
import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
|
|
84
86
|
import type { PeerManagerInterface } from '../peer-manager/interface.js';
|
|
85
87
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
86
88
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
87
89
|
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
88
90
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
89
91
|
import {
|
|
92
|
+
AuthRequest,
|
|
93
|
+
BlockTxsRequest,
|
|
94
|
+
BlockTxsResponse,
|
|
90
95
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
91
96
|
type ReqRespInterface,
|
|
92
97
|
type ReqRespResponse,
|
|
@@ -94,17 +99,11 @@ import {
|
|
|
94
99
|
type ReqRespSubProtocolHandler,
|
|
95
100
|
type ReqRespSubProtocolHandlers,
|
|
96
101
|
type ReqRespSubProtocolValidators,
|
|
102
|
+
StatusMessage,
|
|
97
103
|
type SubProtocolMap,
|
|
98
104
|
ValidationError,
|
|
99
|
-
} from '../reqresp/index.js';
|
|
100
|
-
import {
|
|
101
|
-
AuthRequest,
|
|
102
|
-
BlockTxsRequest,
|
|
103
|
-
BlockTxsResponse,
|
|
104
|
-
StatusMessage,
|
|
105
105
|
pingHandler,
|
|
106
106
|
reqGoodbyeHandler,
|
|
107
|
-
reqRespBlockHandler,
|
|
108
107
|
reqRespBlockTxsHandler,
|
|
109
108
|
reqRespStatusHandler,
|
|
110
109
|
reqRespTxHandler,
|
|
@@ -113,6 +112,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
113
112
|
import type {
|
|
114
113
|
P2PBlockReceivedCallback,
|
|
115
114
|
P2PCheckpointReceivedCallback,
|
|
115
|
+
P2PDuplicateAttestationCallback,
|
|
116
116
|
P2PService,
|
|
117
117
|
PeerDiscoveryService,
|
|
118
118
|
} from '../service.js';
|
|
@@ -129,12 +129,12 @@ type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: Vali
|
|
|
129
129
|
// REFACTOR: Unify with the type above
|
|
130
130
|
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
131
131
|
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
132
|
-
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
132
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M; severity: PeerErrorSeverity };
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
135
|
* Lib P2P implementation of the P2PService interface.
|
|
136
136
|
*/
|
|
137
|
-
export class LibP2PService
|
|
137
|
+
export class LibP2PService extends WithTracer implements P2PService {
|
|
138
138
|
private discoveryRunningPromise?: RunningPromise;
|
|
139
139
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
140
140
|
|
|
@@ -146,8 +146,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
146
146
|
private protocolVersion = '';
|
|
147
147
|
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
|
|
148
148
|
|
|
149
|
-
private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
|
|
150
|
-
|
|
151
149
|
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */
|
|
152
150
|
private duplicateProposalCallback?: (info: {
|
|
153
151
|
slot: SlotNumber;
|
|
@@ -155,6 +153,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
155
153
|
type: 'checkpoint' | 'block';
|
|
156
154
|
}) => void;
|
|
157
155
|
|
|
156
|
+
/** Callback invoked when a duplicate attestation is detected (triggers slashing). */
|
|
157
|
+
private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
|
|
158
|
+
|
|
158
159
|
/**
|
|
159
160
|
* Callback for when a block is received from a peer.
|
|
160
161
|
* @param block - The block received from the peer.
|
|
@@ -167,7 +168,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
167
168
|
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
168
169
|
* @returns The attestations for the checkpoint, if any.
|
|
169
170
|
*/
|
|
170
|
-
private
|
|
171
|
+
private allNodesCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
172
|
+
/**
|
|
173
|
+
* Callback for when a checkpoint proposal is received - specifically for validators - from a peer.
|
|
174
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
175
|
+
* @returns The attestations for the checkpoint, if any.
|
|
176
|
+
*/
|
|
177
|
+
private validatorCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
171
178
|
|
|
172
179
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
173
180
|
|
|
@@ -178,7 +185,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
178
185
|
protected logger: Logger;
|
|
179
186
|
|
|
180
187
|
constructor(
|
|
181
|
-
private clientType: T,
|
|
182
188
|
private config: P2PConfig,
|
|
183
189
|
protected node: PubSubLibp2p,
|
|
184
190
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
@@ -189,6 +195,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
189
195
|
private epochCache: EpochCacheInterface,
|
|
190
196
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
191
197
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
198
|
+
private blockMinFeesProvider: BlockMinFeesProvider,
|
|
192
199
|
telemetry: TelemetryClient,
|
|
193
200
|
logger: Logger = createLogger('p2p:libp2p_service'),
|
|
194
201
|
) {
|
|
@@ -220,36 +227,54 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
220
227
|
this.protocolVersion,
|
|
221
228
|
);
|
|
222
229
|
|
|
223
|
-
|
|
224
|
-
|
|
230
|
+
const p2pPropagationTime = config.attestationPropagationTime;
|
|
231
|
+
const proposalValidatorOpts = {
|
|
225
232
|
txsPermitted: !config.disableTransactions,
|
|
226
|
-
|
|
233
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
234
|
+
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
|
|
235
|
+
p2pPropagationTime,
|
|
236
|
+
signatureContext: {
|
|
237
|
+
chainId: config.l1ChainId,
|
|
238
|
+
rollupAddress: config.l1Contracts.rollupAddress,
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
242
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
243
|
+
const attestationValidatorOpts = {
|
|
244
|
+
l1PublishingTime: config.l1PublishingTime,
|
|
245
|
+
p2pPropagationTime,
|
|
246
|
+
signatureContext: proposalValidatorOpts.signatureContext,
|
|
247
|
+
};
|
|
227
248
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
228
|
-
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
229
|
-
: new CheckpointAttestationValidator(epochCache);
|
|
249
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, attestationValidatorOpts)
|
|
250
|
+
: new CheckpointAttestationValidator(epochCache, attestationValidatorOpts);
|
|
230
251
|
|
|
231
252
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
232
253
|
|
|
233
254
|
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
234
|
-
this.logger.
|
|
235
|
-
`Handler not yet registered
|
|
255
|
+
this.logger.warn(
|
|
256
|
+
`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
|
|
236
257
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
237
258
|
);
|
|
238
|
-
return
|
|
259
|
+
return true;
|
|
239
260
|
};
|
|
240
261
|
|
|
241
|
-
this.
|
|
242
|
-
|
|
262
|
+
this.allNodesCheckpointReceivedCallback = (
|
|
263
|
+
_checkpoint: CheckpointProposalCore,
|
|
264
|
+
): Promise<CheckpointAttestation[] | undefined> => {
|
|
265
|
+
throw new CheckpointProposalReceivedCallbackNotRegisteredError();
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
this.validatorCheckpointReceivedCallback = (
|
|
269
|
+
_checkpoint: CheckpointProposalCore,
|
|
243
270
|
): Promise<CheckpointAttestation[] | undefined> => {
|
|
244
|
-
this.logger.debug(
|
|
245
|
-
`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
|
|
246
|
-
);
|
|
247
271
|
return Promise.resolve(undefined);
|
|
248
272
|
};
|
|
249
273
|
}
|
|
250
274
|
|
|
251
|
-
public updateConfig(config: Partial<P2PReqRespConfig
|
|
275
|
+
public updateConfig(config: Partial<P2PReqRespConfig & Pick<P2PConfig, 'skipIncomingProposals'>>) {
|
|
252
276
|
this.reqresp.updateConfig(config);
|
|
277
|
+
this.config = merge(this.config, config);
|
|
253
278
|
}
|
|
254
279
|
|
|
255
280
|
/**
|
|
@@ -258,8 +283,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
258
283
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
259
284
|
* @returns The new service.
|
|
260
285
|
*/
|
|
261
|
-
public static async new
|
|
262
|
-
clientType: T,
|
|
286
|
+
public static async new(
|
|
263
287
|
config: P2PConfig,
|
|
264
288
|
peerId: PeerId,
|
|
265
289
|
deps: {
|
|
@@ -269,6 +293,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
269
293
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
270
294
|
worldStateSynchronizer: WorldStateSynchronizer;
|
|
271
295
|
peerStore: AztecAsyncKVStore;
|
|
296
|
+
blockMinFeesProvider: BlockMinFeesProvider;
|
|
272
297
|
telemetry: TelemetryClient;
|
|
273
298
|
logger: Logger;
|
|
274
299
|
packageVersion: string;
|
|
@@ -281,6 +306,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
281
306
|
mempools,
|
|
282
307
|
proofVerifier,
|
|
283
308
|
peerStore,
|
|
309
|
+
blockMinFeesProvider,
|
|
284
310
|
telemetry,
|
|
285
311
|
logger,
|
|
286
312
|
packageVersion,
|
|
@@ -311,11 +337,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
311
337
|
const versions = getVersions(config);
|
|
312
338
|
const protocolVersion = compressComponentVersions(versions);
|
|
313
339
|
|
|
314
|
-
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
315
|
-
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
316
|
-
const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
|
|
317
|
-
const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
|
|
318
|
-
|
|
319
340
|
const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
|
|
320
341
|
const directPeers = (
|
|
321
342
|
await Promise.all(
|
|
@@ -335,6 +356,19 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
335
356
|
|
|
336
357
|
const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
|
|
337
358
|
|
|
359
|
+
// Create dynamic topic score params based on network configuration
|
|
360
|
+
const l1Constants = epochCache.getL1Constants();
|
|
361
|
+
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
362
|
+
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
363
|
+
ethereumSlotDuration: l1Constants.ethereumSlotDuration,
|
|
364
|
+
heartbeatIntervalMs: config.gossipsubInterval,
|
|
365
|
+
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
366
|
+
blockDurationMs: config.blockDurationMs,
|
|
367
|
+
l1PublishingTime: config.l1PublishingTime,
|
|
368
|
+
p2pPropagationTime: config.attestationPropagationTime,
|
|
369
|
+
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
|
|
370
|
+
});
|
|
371
|
+
|
|
338
372
|
const node = await createLibp2p({
|
|
339
373
|
start: false,
|
|
340
374
|
peerId,
|
|
@@ -430,28 +464,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
430
464
|
scoreParams: createPeerScoreParams({
|
|
431
465
|
// IPColocation factor can be disabled for local testing - default to -5
|
|
432
466
|
IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
|
|
433
|
-
topics:
|
|
434
|
-
[txTopic]: createTopicScoreParams({
|
|
435
|
-
topicWeight: 1,
|
|
436
|
-
invalidMessageDeliveriesWeight: -20,
|
|
437
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
438
|
-
}),
|
|
439
|
-
[blockProposalTopic]: createTopicScoreParams({
|
|
440
|
-
topicWeight: 1,
|
|
441
|
-
invalidMessageDeliveriesWeight: -20,
|
|
442
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
443
|
-
}),
|
|
444
|
-
[checkpointProposalTopic]: createTopicScoreParams({
|
|
445
|
-
topicWeight: 1,
|
|
446
|
-
invalidMessageDeliveriesWeight: -20,
|
|
447
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
448
|
-
}),
|
|
449
|
-
[checkpointAttestationTopic]: createTopicScoreParams({
|
|
450
|
-
topicWeight: 1,
|
|
451
|
-
invalidMessageDeliveriesWeight: -20,
|
|
452
|
-
invalidMessageDeliveriesDecay: 0.5,
|
|
453
|
-
}),
|
|
454
|
-
},
|
|
467
|
+
topics: topicScoreParams,
|
|
455
468
|
}),
|
|
456
469
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
457
470
|
components: (components: { connectionManager: ConnectionManager }) => ({
|
|
@@ -477,13 +490,19 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
477
490
|
epochCache,
|
|
478
491
|
);
|
|
479
492
|
|
|
480
|
-
//
|
|
481
|
-
|
|
493
|
+
// Gate req/resp data protocols for unauthenticated peers when p2pAllowOnlyValidators is enabled
|
|
494
|
+
reqresp.setShouldRejectPeer(peerId => peerManager.shouldDisableP2PGossip(peerId));
|
|
495
|
+
|
|
496
|
+
// Configure application-specific scoring for gossipsub.
|
|
497
|
+
// The weight scales app score to align with gossipsub thresholds:
|
|
498
|
+
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
499
|
+
// - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
|
|
500
|
+
// Note: positive topic scores can offset penalties, so alignment is best-effort.
|
|
501
|
+
node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
|
|
482
502
|
node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
|
|
483
503
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
484
504
|
|
|
485
505
|
return new LibP2PService(
|
|
486
|
-
clientType,
|
|
487
506
|
config,
|
|
488
507
|
node,
|
|
489
508
|
peerDiscoveryService,
|
|
@@ -494,6 +513,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
494
513
|
epochCache,
|
|
495
514
|
proofVerifier,
|
|
496
515
|
worldStateSynchronizer,
|
|
516
|
+
blockMinFeesProvider,
|
|
497
517
|
telemetry,
|
|
498
518
|
logger,
|
|
499
519
|
);
|
|
@@ -519,14 +539,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
519
539
|
// Create request response protocol handlers
|
|
520
540
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
521
541
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
522
|
-
const blockHandler = reqRespBlockHandler(this.archiver);
|
|
523
542
|
const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
|
|
524
543
|
|
|
525
544
|
const requestResponseHandlers: Partial<ReqRespSubProtocolHandlers> = {
|
|
526
545
|
[ReqRespSubProtocol.PING]: pingHandler,
|
|
527
546
|
[ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
|
|
528
547
|
[ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
|
|
529
|
-
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
|
|
530
548
|
};
|
|
531
549
|
|
|
532
550
|
if (!this.config.disableTransactions) {
|
|
@@ -547,7 +565,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
547
565
|
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
548
566
|
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
549
567
|
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
550
|
-
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
551
568
|
};
|
|
552
569
|
|
|
553
570
|
await this.peerManager.initializePeers();
|
|
@@ -557,7 +574,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
557
574
|
await this.node.start();
|
|
558
575
|
|
|
559
576
|
// Subscribe to standard GossipSub topics by default
|
|
560
|
-
for (const topic of
|
|
577
|
+
for (const topic of getTopicsForConfig(this.config.disableTransactions)) {
|
|
561
578
|
this.subscribeToTopic(this.topicStrings[topic]);
|
|
562
579
|
}
|
|
563
580
|
|
|
@@ -623,6 +640,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
623
640
|
return this.peerManager.getPeers(includePending);
|
|
624
641
|
}
|
|
625
642
|
|
|
643
|
+
public getGossipMeshPeerCount(topicType: TopicType): number {
|
|
644
|
+
return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
|
|
645
|
+
}
|
|
646
|
+
|
|
626
647
|
private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
|
|
627
648
|
this.logger.trace(`Received PUBSUB message.`);
|
|
628
649
|
|
|
@@ -671,8 +692,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
671
692
|
this.blockReceivedCallback = callback;
|
|
672
693
|
}
|
|
673
694
|
|
|
674
|
-
public
|
|
675
|
-
this.
|
|
695
|
+
public registerValidatorCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
696
|
+
this.validatorCheckpointReceivedCallback = callback;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
public registerAllNodesCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
700
|
+
this.allNodesCheckpointReceivedCallback = callback;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
public async notifyOwnCheckpointProposal(checkpoint: CheckpointProposalCore): Promise<void> {
|
|
704
|
+
await this.allNodesCheckpointReceivedCallback(checkpoint, this.node.peerId);
|
|
676
705
|
}
|
|
677
706
|
|
|
678
707
|
/**
|
|
@@ -685,6 +714,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
685
714
|
this.duplicateProposalCallback = callback;
|
|
686
715
|
}
|
|
687
716
|
|
|
717
|
+
/**
|
|
718
|
+
* Registers a callback to be invoked when a duplicate attestation is detected.
|
|
719
|
+
* A validator signing attestations for different proposals at the same slot.
|
|
720
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
721
|
+
*/
|
|
722
|
+
public registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void {
|
|
723
|
+
this.duplicateAttestationCallback = callback;
|
|
724
|
+
}
|
|
725
|
+
|
|
688
726
|
/**
|
|
689
727
|
* Subscribes to a topic.
|
|
690
728
|
* @param topic - The topic to subscribe to.
|
|
@@ -749,6 +787,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
749
787
|
if (!validator || !validator.addMessage(msgId)) {
|
|
750
788
|
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
751
789
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
790
|
+
if (topicType === TopicType.tx) {
|
|
791
|
+
this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
|
|
792
|
+
}
|
|
752
793
|
return { result: false, topicType };
|
|
753
794
|
}
|
|
754
795
|
|
|
@@ -810,12 +851,19 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
810
851
|
|
|
811
852
|
// Process the message, optionally within a linked span for trace propagation
|
|
812
853
|
const processMessage = async () => {
|
|
854
|
+
if (
|
|
855
|
+
this.config.skipIncomingProposals &&
|
|
856
|
+
(msg.topic === this.topicStrings[TopicType.block_proposal] ||
|
|
857
|
+
msg.topic === this.topicStrings[TopicType.checkpoint_proposal])
|
|
858
|
+
) {
|
|
859
|
+
this.logger.warn(`Ignoring incoming proposal (skipIncomingProposals is set)`, { topic: msg.topic });
|
|
860
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
813
863
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
814
864
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
815
865
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
816
|
-
|
|
817
|
-
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
818
|
-
}
|
|
866
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
819
867
|
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
820
868
|
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
821
869
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
@@ -877,45 +925,139 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
877
925
|
source: PeerId,
|
|
878
926
|
topicType: TopicType,
|
|
879
927
|
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
880
|
-
|
|
928
|
+
// Default to reject result with a penalty if validation function throws an error
|
|
929
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = {
|
|
930
|
+
result: TopicValidatorResult.Reject,
|
|
931
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
932
|
+
};
|
|
881
933
|
const timer = new Timer();
|
|
882
934
|
try {
|
|
883
935
|
resultAndObj = await validationFunc();
|
|
884
936
|
} catch (err) {
|
|
885
|
-
this.
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
937
|
+
this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
const validationTimeMs = timer.ms();
|
|
941
|
+
const mcacheWindowMs = this.config.gossipsubMcacheLength * this.config.gossipsubInterval;
|
|
942
|
+
if (validationTimeMs > mcacheWindowMs * 0.75) {
|
|
943
|
+
this.instrumentation.incSlowValidation(topicType);
|
|
944
|
+
this.logger.warn(
|
|
945
|
+
`Gossip validation for ${topicType} took ${validationTimeMs}ms, approaching mcache eviction window of ${mcacheWindowMs}ms. ` +
|
|
946
|
+
`Message forwarding may be skipped if validation exceeds the window.`,
|
|
947
|
+
{ msgId, source: source.toString(), topicType, validationTimeMs, mcacheWindowMs },
|
|
948
|
+
);
|
|
891
949
|
}
|
|
892
950
|
|
|
893
951
|
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
952
|
+
this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
|
|
894
953
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
954
|
+
} else if (resultAndObj.result === TopicValidatorResult.Reject) {
|
|
955
|
+
this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
|
|
956
|
+
msgId,
|
|
957
|
+
source: source.toString(),
|
|
958
|
+
topicType,
|
|
959
|
+
severity: resultAndObj.severity,
|
|
960
|
+
});
|
|
961
|
+
this.peerManager.penalizePeer(source, resultAndObj.severity);
|
|
962
|
+
} else {
|
|
963
|
+
this.logger.trace(`Message ${topicType} ignored by validator`, { msgId, source: source.toString(), topicType });
|
|
895
964
|
}
|
|
896
965
|
|
|
897
966
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
|
|
898
967
|
return resultAndObj;
|
|
899
968
|
}
|
|
900
969
|
|
|
970
|
+
private tryDeserialize<T>(deserializeFunc: () => T, msgId: string, source: PeerId): T | undefined {
|
|
971
|
+
try {
|
|
972
|
+
return deserializeFunc();
|
|
973
|
+
} catch (err) {
|
|
974
|
+
this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
|
|
975
|
+
err,
|
|
976
|
+
msgId,
|
|
977
|
+
source: source.toString(),
|
|
978
|
+
});
|
|
979
|
+
return undefined;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
901
983
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
902
984
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
903
|
-
const tx = Tx.fromBuffer(payloadData);
|
|
904
|
-
|
|
905
|
-
|
|
985
|
+
const tx = this.tryDeserialize(() => Tx.fromBuffer(payloadData), msgId, source);
|
|
986
|
+
if (!tx) {
|
|
987
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.LowToleranceError };
|
|
988
|
+
}
|
|
906
989
|
|
|
907
|
-
this.
|
|
908
|
-
|
|
909
|
-
|
|
990
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
991
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
992
|
+
|
|
993
|
+
// Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
|
|
994
|
+
const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
995
|
+
const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
|
|
996
|
+
if (!firstStageOutcome.allPassed) {
|
|
997
|
+
const { name } = firstStageOutcome.failure;
|
|
998
|
+
let { severity } = firstStageOutcome.failure;
|
|
999
|
+
|
|
1000
|
+
// Double spend validator has a special case handler. We perform more detailed examination
|
|
1001
|
+
// as to how recently the nullifier was entered into the tree and if the transaction should
|
|
1002
|
+
// have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
|
|
1003
|
+
if (name === 'doubleSpendValidator') {
|
|
1004
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1005
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
|
|
1009
|
+
validator: name,
|
|
1010
|
+
severity,
|
|
1011
|
+
source: source.toString(),
|
|
1012
|
+
});
|
|
1013
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
1017
|
+
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
1018
|
+
if (canAdd === 'ignored') {
|
|
1019
|
+
this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
|
|
1020
|
+
source: source.toString(),
|
|
1021
|
+
});
|
|
1022
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// Stage 2: expensive proof verification
|
|
1026
|
+
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
1027
|
+
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
1028
|
+
if (!secondStageOutcome.allPassed) {
|
|
1029
|
+
const { severity, name } = secondStageOutcome.failure;
|
|
1030
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
|
|
1031
|
+
validator: name,
|
|
1032
|
+
severity,
|
|
1033
|
+
source: source.toString(),
|
|
1034
|
+
});
|
|
1035
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// Pool add: persist the tx
|
|
1039
|
+
const txHash = tx.getTxHash();
|
|
1040
|
+
const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
|
|
1041
|
+
|
|
1042
|
+
const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
|
|
1043
|
+
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
1044
|
+
|
|
1045
|
+
this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
|
|
1046
|
+
wasAccepted,
|
|
1047
|
+
wasIgnored,
|
|
910
1048
|
[Attributes.P2P_ID]: source.toString(),
|
|
911
1049
|
});
|
|
912
1050
|
|
|
913
|
-
if (
|
|
914
|
-
return { result: TopicValidatorResult.
|
|
915
|
-
} else if (
|
|
1051
|
+
if (wasAccepted) {
|
|
1052
|
+
return { result: TopicValidatorResult.Accept, obj: tx };
|
|
1053
|
+
} else if (wasIgnored) {
|
|
916
1054
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
917
1055
|
} else {
|
|
918
|
-
|
|
1056
|
+
this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
|
|
1057
|
+
source: source.toString(),
|
|
1058
|
+
txHash: txHash.toString(),
|
|
1059
|
+
});
|
|
1060
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
919
1061
|
}
|
|
920
1062
|
};
|
|
921
1063
|
|
|
@@ -924,6 +1066,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
924
1066
|
return;
|
|
925
1067
|
}
|
|
926
1068
|
|
|
1069
|
+
// Tx was accepted into pool and will be propagated - just log and record metrics
|
|
927
1070
|
const txHash = tx.getTxHash();
|
|
928
1071
|
const txHashString = txHash.toString();
|
|
929
1072
|
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
@@ -931,13 +1074,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
931
1074
|
txHash: txHashString,
|
|
932
1075
|
});
|
|
933
1076
|
|
|
934
|
-
if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
|
|
935
|
-
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
|
-
|
|
939
1077
|
this.instrumentation.incrementTxReceived(1);
|
|
940
|
-
await this.mempools.txPool.addTxs([tx]);
|
|
941
1078
|
}
|
|
942
1079
|
|
|
943
1080
|
/**
|
|
@@ -950,7 +1087,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
950
1087
|
source: PeerId,
|
|
951
1088
|
): Promise<void> {
|
|
952
1089
|
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
953
|
-
() =>
|
|
1090
|
+
() => {
|
|
1091
|
+
const attestation = this.tryDeserialize(() => CheckpointAttestation.fromBuffer(payloadData), msgId, source);
|
|
1092
|
+
if (!attestation) {
|
|
1093
|
+
return Promise.resolve({
|
|
1094
|
+
result: TopicValidatorResult.Reject,
|
|
1095
|
+
severity: PeerErrorSeverity.LowToleranceError,
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
return this.validateAndStoreCheckpointAttestation(source, attestation);
|
|
1099
|
+
},
|
|
954
1100
|
msgId,
|
|
955
1101
|
source,
|
|
956
1102
|
TopicType.checkpoint_attestation,
|
|
@@ -983,48 +1129,60 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
983
1129
|
|
|
984
1130
|
if (validationResult.result === 'reject') {
|
|
985
1131
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
986
|
-
|
|
987
|
-
return { result: TopicValidatorResult.Reject };
|
|
1132
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
988
1133
|
}
|
|
989
1134
|
|
|
990
1135
|
if (validationResult.result === 'ignore') {
|
|
991
1136
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
992
1137
|
}
|
|
993
1138
|
|
|
994
|
-
// Get committee size for the attestation's slot
|
|
995
|
-
const slot = attestation.payload.header.slotNumber;
|
|
996
|
-
const { committee } = await this.epochCache.getCommittee(slot);
|
|
997
|
-
const committeeSize = committee?.length ?? 0;
|
|
998
|
-
|
|
999
1139
|
// Try to add the attestation: this handles existence check, cap check, and adding in one call
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1140
|
+
// count is the number of attestations by this signer for this slot (for duplicate detection)
|
|
1141
|
+
const slot = attestation.payload.header.slotNumber;
|
|
1142
|
+
const { added, alreadyExists, count } =
|
|
1143
|
+
await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
|
|
1004
1144
|
|
|
1005
1145
|
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
1006
1146
|
added,
|
|
1007
1147
|
alreadyExists,
|
|
1148
|
+
count,
|
|
1008
1149
|
[Attributes.SLOT_NUMBER]: slot.toString(),
|
|
1009
1150
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1010
1151
|
});
|
|
1011
1152
|
|
|
1012
|
-
//
|
|
1153
|
+
// Exact same attestation received, no need to re-broadcast
|
|
1013
1154
|
if (alreadyExists) {
|
|
1014
1155
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1015
1156
|
}
|
|
1016
1157
|
|
|
1017
|
-
// Could not add (cap reached),
|
|
1158
|
+
// Could not add (cap reached for signer), penalize and do not re-broadcast
|
|
1018
1159
|
if (!added) {
|
|
1019
|
-
this.logger.warn(`
|
|
1160
|
+
this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
|
|
1020
1161
|
slot: slot.toString(),
|
|
1021
1162
|
archive: attestation.archive.toString(),
|
|
1022
1163
|
source: peerId.toString(),
|
|
1164
|
+
attester: attestation.getSender()?.toString(),
|
|
1165
|
+
count,
|
|
1023
1166
|
});
|
|
1024
|
-
return { result: TopicValidatorResult.
|
|
1167
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
|
|
1171
|
+
// count is the number of attestations by this signer for this slot
|
|
1172
|
+
if (count === 2) {
|
|
1173
|
+
const attester = attestation.getSender();
|
|
1174
|
+
if (attester) {
|
|
1175
|
+
this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
|
|
1176
|
+
slot: slot.toString(),
|
|
1177
|
+
archive: attestation.archive.toString(),
|
|
1178
|
+
source: peerId.toString(),
|
|
1179
|
+
attester: attester.toString(),
|
|
1180
|
+
});
|
|
1181
|
+
this.duplicateAttestationCallback?.({ slot, attester });
|
|
1182
|
+
}
|
|
1025
1183
|
}
|
|
1026
1184
|
|
|
1027
|
-
// Attestation was added successfully
|
|
1185
|
+
// Attestation was added successfully - accept it so other nodes can also detect the equivocation
|
|
1028
1186
|
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
1029
1187
|
}
|
|
1030
1188
|
|
|
@@ -1061,8 +1219,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1061
1219
|
|
|
1062
1220
|
if (validationResult.result === 'reject') {
|
|
1063
1221
|
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1064
|
-
|
|
1065
|
-
return { result: TopicValidatorResult.Reject };
|
|
1222
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1066
1223
|
}
|
|
1067
1224
|
|
|
1068
1225
|
if (validationResult.result === 'ignore') {
|
|
@@ -1070,8 +1227,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1070
1227
|
}
|
|
1071
1228
|
|
|
1072
1229
|
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1073
|
-
const { added, alreadyExists,
|
|
1074
|
-
const isEquivocated =
|
|
1230
|
+
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1231
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1075
1232
|
|
|
1076
1233
|
// Duplicate proposal received, no need to re-broadcast
|
|
1077
1234
|
if (alreadyExists) {
|
|
@@ -1086,15 +1243,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1086
1243
|
|
|
1087
1244
|
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1088
1245
|
if (!added) {
|
|
1089
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1090
1246
|
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1091
1247
|
...block.toBlockInfo(),
|
|
1092
1248
|
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1093
|
-
|
|
1249
|
+
count,
|
|
1094
1250
|
proposer: block.getSender()?.toString(),
|
|
1095
1251
|
source: peerId.toString(),
|
|
1096
1252
|
});
|
|
1097
|
-
return {
|
|
1253
|
+
return {
|
|
1254
|
+
result: TopicValidatorResult.Reject,
|
|
1255
|
+
metadata: { isEquivocated },
|
|
1256
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1257
|
+
};
|
|
1098
1258
|
}
|
|
1099
1259
|
|
|
1100
1260
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1107,7 +1267,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1107
1267
|
proposer: proposer?.toString(),
|
|
1108
1268
|
});
|
|
1109
1269
|
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1110
|
-
if (proposer &&
|
|
1270
|
+
if (proposer && count === 2) {
|
|
1111
1271
|
this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
|
|
1112
1272
|
}
|
|
1113
1273
|
return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
|
|
@@ -1132,14 +1292,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1132
1292
|
...block.toBlockInfo(),
|
|
1133
1293
|
});
|
|
1134
1294
|
|
|
1135
|
-
// Mark the txs in this proposal as
|
|
1136
|
-
await this.mempools.txPool.
|
|
1295
|
+
// Mark the txs in this proposal as protected
|
|
1296
|
+
await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
|
|
1137
1297
|
|
|
1138
1298
|
// Call the block received callback to validate the proposal.
|
|
1139
1299
|
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1140
1300
|
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1141
1301
|
if (!isValid) {
|
|
1142
|
-
this.logger.
|
|
1302
|
+
this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1143
1303
|
}
|
|
1144
1304
|
}
|
|
1145
1305
|
|
|
@@ -1187,8 +1347,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1187
1347
|
|
|
1188
1348
|
if (validationResult.result === 'reject') {
|
|
1189
1349
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1190
|
-
|
|
1191
|
-
return { result: TopicValidatorResult.Reject };
|
|
1350
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1192
1351
|
}
|
|
1193
1352
|
|
|
1194
1353
|
if (validationResult.result === 'ignore') {
|
|
@@ -1203,20 +1362,21 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1203
1362
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1204
1363
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1205
1364
|
});
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
metadata: { isEquivocated } = {},
|
|
1210
|
-
} = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1211
|
-
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1365
|
+
const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1366
|
+
const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
|
|
1367
|
+
if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1212
1368
|
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1213
1369
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1214
1370
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1215
1371
|
isEquivocated,
|
|
1216
|
-
result,
|
|
1372
|
+
result: blockProposalResult.result,
|
|
1217
1373
|
});
|
|
1218
|
-
return {
|
|
1219
|
-
|
|
1374
|
+
return {
|
|
1375
|
+
result: TopicValidatorResult.Reject,
|
|
1376
|
+
severity:
|
|
1377
|
+
'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError,
|
|
1378
|
+
};
|
|
1379
|
+
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1220
1380
|
processBlock = true;
|
|
1221
1381
|
}
|
|
1222
1382
|
}
|
|
@@ -1224,8 +1384,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1224
1384
|
// Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
|
|
1225
1385
|
const checkpointCore = checkpoint.toCore();
|
|
1226
1386
|
const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
|
|
1227
|
-
const { added, alreadyExists,
|
|
1228
|
-
const isEquivocated =
|
|
1387
|
+
const { added, alreadyExists, count } = tryAddResult;
|
|
1388
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1229
1389
|
|
|
1230
1390
|
// Duplicate proposal received, do not re-broadcast
|
|
1231
1391
|
if (alreadyExists) {
|
|
@@ -1243,13 +1403,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1243
1403
|
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1244
1404
|
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1245
1405
|
if (!added) {
|
|
1246
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1247
1406
|
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1248
1407
|
...checkpoint.toCheckpointInfo(),
|
|
1249
|
-
|
|
1408
|
+
count,
|
|
1250
1409
|
source: peerId.toString(),
|
|
1251
1410
|
});
|
|
1252
|
-
return {
|
|
1411
|
+
return {
|
|
1412
|
+
result: TopicValidatorResult.Reject,
|
|
1413
|
+
obj: checkpoint,
|
|
1414
|
+
metadata: { isEquivocated, processBlock },
|
|
1415
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1416
|
+
};
|
|
1253
1417
|
}
|
|
1254
1418
|
|
|
1255
1419
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1262,7 +1426,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1262
1426
|
proposer: proposer?.toString(),
|
|
1263
1427
|
});
|
|
1264
1428
|
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1265
|
-
if (proposer &&
|
|
1429
|
+
if (proposer && count === 2) {
|
|
1266
1430
|
this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
|
|
1267
1431
|
}
|
|
1268
1432
|
return {
|
|
@@ -1294,9 +1458,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1294
1458
|
source: sender.toString(),
|
|
1295
1459
|
});
|
|
1296
1460
|
|
|
1461
|
+
await this.allNodesCheckpointReceivedCallback(checkpoint, sender);
|
|
1462
|
+
|
|
1297
1463
|
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1298
1464
|
// to validate and potentially generate attestations
|
|
1299
|
-
const attestations = await this.
|
|
1465
|
+
const attestations = await this.validatorCheckpointReceivedCallback(checkpoint, sender);
|
|
1300
1466
|
if (attestations && attestations.length > 0) {
|
|
1301
1467
|
// If the callback returned attestations, add them to the pool and propagate them
|
|
1302
1468
|
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
@@ -1444,53 +1610,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1444
1610
|
}
|
|
1445
1611
|
}
|
|
1446
1612
|
|
|
1447
|
-
/**
|
|
1448
|
-
* Validates a BLOCK response.
|
|
1449
|
-
*
|
|
1450
|
-
* If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
|
|
1451
|
-
* Penalizes on block number mismatch or hash mismatch.
|
|
1452
|
-
*
|
|
1453
|
-
* @param requestedBlockNumber - The requested block number.
|
|
1454
|
-
* @param responseBlock - The block returned by the peer.
|
|
1455
|
-
* @param peerId - The peer that returned the block.
|
|
1456
|
-
* @returns True if the response is valid, false otherwise.
|
|
1457
|
-
*/
|
|
1458
|
-
@trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
|
|
1459
|
-
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
|
|
1460
|
-
}))
|
|
1461
|
-
protected async validateRequestedBlock(
|
|
1462
|
-
requestedBlockNumber: Fr,
|
|
1463
|
-
responseBlock: L2Block,
|
|
1464
|
-
peerId: PeerId,
|
|
1465
|
-
): Promise<boolean> {
|
|
1466
|
-
try {
|
|
1467
|
-
const reqNum = Number(requestedBlockNumber.toString());
|
|
1468
|
-
if (responseBlock.number !== reqNum) {
|
|
1469
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1470
|
-
return false;
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
|
-
const local = await this.archiver.getBlock(BlockNumber(reqNum));
|
|
1474
|
-
if (!local) {
|
|
1475
|
-
// We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
|
|
1476
|
-
// TODO: Consider extending this validator to accept an expected hash or
|
|
1477
|
-
// performing quorum-based checks when using P2P syncing prior to L1 sync.
|
|
1478
|
-
this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
|
|
1479
|
-
return false;
|
|
1480
|
-
}
|
|
1481
|
-
const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
|
|
1482
|
-
if (!localHash.equals(respHash)) {
|
|
1483
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1484
|
-
return false;
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
return true;
|
|
1488
|
-
} catch (e) {
|
|
1489
|
-
this.logger.warn(`Error validating requested block`, e);
|
|
1490
|
-
return false;
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
1613
|
protected async validateRequestedTx(
|
|
1495
1614
|
tx: Tx,
|
|
1496
1615
|
peerId: PeerId,
|
|
@@ -1511,52 +1630,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1511
1630
|
}
|
|
1512
1631
|
|
|
1513
1632
|
protected createRequestedTxValidator(): TxValidator {
|
|
1514
|
-
return
|
|
1633
|
+
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1515
1634
|
l1ChainId: this.config.l1ChainId,
|
|
1516
1635
|
rollupVersion: this.config.rollupVersion,
|
|
1517
1636
|
});
|
|
1518
1637
|
}
|
|
1519
1638
|
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
}))
|
|
1523
|
-
private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
|
|
1524
|
-
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1525
|
-
|
|
1526
|
-
// We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
|
|
1527
|
-
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1528
|
-
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1529
|
-
|
|
1530
|
-
for (const validator of messageValidators) {
|
|
1531
|
-
const outcome = await this.runValidations(tx, validator);
|
|
1532
|
-
|
|
1533
|
-
if (outcome.allPassed) {
|
|
1534
|
-
continue;
|
|
1535
|
-
}
|
|
1536
|
-
const { name } = outcome.failure;
|
|
1537
|
-
let { severity } = outcome.failure;
|
|
1538
|
-
|
|
1539
|
-
// Double spend validator has a special case handler
|
|
1540
|
-
if (name === 'doubleSpendValidator') {
|
|
1541
|
-
const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
|
|
1542
|
-
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1546
|
-
return false;
|
|
1547
|
-
}
|
|
1548
|
-
return true;
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
1552
|
-
if (blockNumber === this.feesCache?.blockNumber) {
|
|
1553
|
-
return this.feesCache.gasFees;
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
const header = await this.archiver.getBlockHeader(blockNumber);
|
|
1557
|
-
const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
|
|
1558
|
-
this.feesCache = { blockNumber, gasFees };
|
|
1559
|
-
return gasFees;
|
|
1639
|
+
private getGasFees(): Promise<GasFees> {
|
|
1640
|
+
return this.blockMinFeesProvider.getCurrentMinFees();
|
|
1560
1641
|
}
|
|
1561
1642
|
|
|
1562
1643
|
/**
|
|
@@ -1575,60 +1656,62 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1575
1656
|
};
|
|
1576
1657
|
}
|
|
1577
1658
|
|
|
1578
|
-
public async
|
|
1579
|
-
const
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1659
|
+
public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
|
|
1660
|
+
const validator = createTxValidatorForBlockProposalReceivedTxs(
|
|
1661
|
+
this.proofVerifier,
|
|
1662
|
+
{ l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
|
|
1663
|
+
this.logger.getBindings(),
|
|
1664
|
+
);
|
|
1584
1665
|
|
|
1585
|
-
await Promise.all(
|
|
1666
|
+
const results = await Promise.all(
|
|
1586
1667
|
txs.map(async tx => {
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
if (!outcome.allPassed) {
|
|
1590
|
-
throw new Error('Invalid tx detected', { cause: { outcome } });
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1668
|
+
const result = await validator.validateTx(tx);
|
|
1669
|
+
return result.result !== 'invalid';
|
|
1593
1670
|
}),
|
|
1594
1671
|
);
|
|
1672
|
+
if (results.some(value => value === false)) {
|
|
1673
|
+
throw new Error('Invalid tx detected');
|
|
1674
|
+
}
|
|
1595
1675
|
}
|
|
1596
1676
|
|
|
1597
|
-
/**
|
|
1598
|
-
|
|
1599
|
-
*
|
|
1600
|
-
* Each validator is a pair of a validator and a severity.
|
|
1601
|
-
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
1602
|
-
*
|
|
1603
|
-
* @param currentBlockNumber - The current synced block number.
|
|
1604
|
-
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
1605
|
-
* @returns The message validators.
|
|
1606
|
-
*/
|
|
1607
|
-
private async createMessageValidators(
|
|
1677
|
+
/** Creates the first stage (fast) validators for gossiped transactions. */
|
|
1678
|
+
protected async createFirstStageMessageValidators(
|
|
1608
1679
|
currentBlockNumber: BlockNumber,
|
|
1609
1680
|
nextSlotTimestamp: UInt64,
|
|
1610
|
-
): Promise<Record<string,
|
|
1611
|
-
const gasFees = await this.getGasFees(
|
|
1612
|
-
const allowedInSetup =
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1681
|
+
): Promise<Record<string, TransactionValidator>> {
|
|
1682
|
+
const gasFees = await this.getGasFees();
|
|
1683
|
+
const allowedInSetup = [
|
|
1684
|
+
...(await getDefaultAllowedSetupFunctions()),
|
|
1685
|
+
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
1686
|
+
];
|
|
1687
|
+
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1688
|
+
const l1Constants = await this.archiver.getL1Constants();
|
|
1689
|
+
|
|
1690
|
+
return createFirstStageTxValidationsForGossipedTransactions(
|
|
1617
1691
|
nextSlotTimestamp,
|
|
1618
|
-
|
|
1692
|
+
blockNumber,
|
|
1619
1693
|
this.worldStateSynchronizer,
|
|
1620
1694
|
gasFees,
|
|
1621
1695
|
this.config.l1ChainId,
|
|
1622
1696
|
this.config.rollupVersion,
|
|
1623
1697
|
protocolContractsHash,
|
|
1624
1698
|
this.archiver,
|
|
1625
|
-
this.proofVerifier,
|
|
1626
1699
|
!this.config.disableTransactions,
|
|
1627
1700
|
allowedInSetup,
|
|
1628
1701
|
this.logger.getBindings(),
|
|
1702
|
+
{
|
|
1703
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
1704
|
+
maxBlockL2Gas: this.config.validateMaxL2BlockGas,
|
|
1705
|
+
maxBlockDAGas: this.config.validateMaxDABlockGas,
|
|
1706
|
+
},
|
|
1629
1707
|
);
|
|
1630
1708
|
}
|
|
1631
1709
|
|
|
1710
|
+
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
|
|
1711
|
+
protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
|
|
1712
|
+
return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1632
1715
|
/**
|
|
1633
1716
|
* Run validations on a tx.
|
|
1634
1717
|
* @param tx - The tx to validate.
|
|
@@ -1637,7 +1720,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1637
1720
|
*/
|
|
1638
1721
|
private async runValidations(
|
|
1639
1722
|
tx: Tx,
|
|
1640
|
-
messageValidators: Record<string,
|
|
1723
|
+
messageValidators: Record<string, TransactionValidator>,
|
|
1641
1724
|
): Promise<ValidationOutcome> {
|
|
1642
1725
|
const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
|
|
1643
1726
|
const { result } = await validator.validateTx(tx);
|
|
@@ -1646,8 +1729,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1646
1729
|
|
|
1647
1730
|
// A promise that resolves when all validations have been run
|
|
1648
1731
|
const allValidations = await Promise.all(validationPromises);
|
|
1649
|
-
const
|
|
1650
|
-
if (
|
|
1732
|
+
const failures = allValidations.filter(x => !x.isValid);
|
|
1733
|
+
if (failures.length > 0) {
|
|
1734
|
+
// Pick the most severe failure (lowest tolerance = harshest penalty)
|
|
1735
|
+
const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
|
|
1651
1736
|
return {
|
|
1652
1737
|
allPassed: false,
|
|
1653
1738
|
failure: {
|
|
@@ -1700,31 +1785,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1700
1785
|
return PeerErrorSeverity.HighToleranceError;
|
|
1701
1786
|
}
|
|
1702
1787
|
|
|
1703
|
-
/**
|
|
1704
|
-
* Validate a checkpoint attestation.
|
|
1705
|
-
*
|
|
1706
|
-
* @param attestation - The checkpoint attestation to validate.
|
|
1707
|
-
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1708
|
-
*/
|
|
1709
|
-
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1710
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1711
|
-
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1712
|
-
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1713
|
-
}))
|
|
1714
|
-
public async validateCheckpointAttestation(
|
|
1715
|
-
peerId: PeerId,
|
|
1716
|
-
attestation: CheckpointAttestation,
|
|
1717
|
-
): Promise<P2PValidationResult> {
|
|
1718
|
-
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1719
|
-
|
|
1720
|
-
if (result.result === 'reject') {
|
|
1721
|
-
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1722
|
-
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1723
|
-
}
|
|
1724
|
-
|
|
1725
|
-
return result;
|
|
1726
|
-
}
|
|
1727
|
-
|
|
1728
1788
|
public getPeerScore(peerId: PeerId): number {
|
|
1729
1789
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
1730
1790
|
}
|