@aztec/p2p 0.0.1-commit.9ef841308 → 0.0.1-commit.a4600f49
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 +7 -6
- package/dest/bootstrap/bootstrap.d.ts +1 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +22 -6
- package/dest/client/factory.d.ts +4 -3
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +33 -24
- package/dest/client/interface.d.ts +48 -11
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +34 -19
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +105 -46
- package/dest/config.d.ts +143 -107
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +72 -26
- 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/reqresp.error.d.ts +9 -16
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +10 -17
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +98 -56
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +269 -196
- 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 +218 -59
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +6 -4
- package/dest/mem_pools/instrumentation.d.ts +9 -4
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +28 -9
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -5
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +1 -7
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +6 -6
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
- 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/invalid_txs_after_reorg_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +33 -5
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +5 -2
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +8 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +15 -1
- 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 +31 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -3
- 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 +19 -8
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +17 -4
- 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 +208 -118
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +38 -16
- 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 +4 -5
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +8 -3
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +2 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +8 -3
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +8 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +25 -3
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +85 -15
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +3 -3
- package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +1 -0
- package/dest/msg_validators/tx_validator/factory.d.ts +14 -15
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +29 -16
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +47 -10
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +65 -48
- 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/phases_validator.js +2 -2
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
- 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 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
- 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/discv5/discV5_service.d.ts +13 -2
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +119 -25
- package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
- package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
- package/dest/services/discv5/persisted_enr_store.js +145 -0
- package/dest/services/dummy_service.d.ts +15 -15
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +15 -16
- package/dest/services/encoding.d.ts +19 -6
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +25 -15
- package/dest/services/gossipsub/topic_score_params.d.ts +6 -12
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +4 -14
- 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 +40 -40
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +292 -264
- package/dest/services/peer-manager/peer_manager.d.ts +15 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +59 -17
- package/dest/services/peer-manager/peer_scoring.d.ts +30 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +74 -3
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +1 -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 +35 -44
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +8 -5
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
- package/dest/services/reqresp/config.d.ts +15 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/config.js +11 -0
- package/dest/services/reqresp/interface.d.ts +16 -18
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +10 -20
- 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/bitvector.d.ts +4 -3
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
- 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 +31 -28
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
- 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 +42 -24
- 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 +1 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +1 -3
- 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 +3 -13
- package/dest/services/reqresp/reqresp.d.ts +7 -29
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +59 -209
- package/dest/services/service.d.ts +23 -16
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +2 -23
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +2 -55
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
- package/dest/services/tx_collection/index.d.ts +2 -3
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +0 -1
- 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 +0 -2
- package/dest/services/tx_collection/tx_collection.d.ts +35 -51
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +275 -119
- package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +2 -2
- package/dest/services/tx_collection/tx_source.d.ts +1 -1
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +4 -1
- package/dest/services/tx_file_store/tx_file_store.d.ts +1 -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 +4 -14
- package/dest/services/tx_provider.d.ts +3 -1
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +3 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +5 -2
- package/dest/test-helpers/mock-pubsub.d.ts +21 -12
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +39 -47
- package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +16 -18
- package/dest/test-helpers/test_tx_provider.d.ts +3 -1
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
- package/dest/test-helpers/test_tx_provider.js +3 -0
- package/dest/test-helpers/testbench-utils.d.ts +15 -14
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +28 -13
- package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +60 -27
- package/dest/testbench/worker_client_manager.d.ts +10 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +51 -8
- package/dest/util.d.ts +8 -8
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +38 -10
- package/dest/versioning.d.ts +3 -6
- package/dest/versioning.d.ts.map +1 -1
- package/dest/versioning.js +3 -24
- package/package.json +16 -16
- package/src/bootstrap/bootstrap.ts +17 -3
- package/src/client/factory.ts +49 -25
- package/src/client/interface.ts +44 -17
- package/src/client/p2p_client.ts +125 -79
- package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
- package/src/config.ts +146 -34
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/errors/reqresp.error.ts +13 -19
- package/src/mem_pools/attestation_pool/attestation_pool.ts +324 -239
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +238 -63
- package/src/mem_pools/attestation_pool/mocks.ts +13 -8
- package/src/mem_pools/instrumentation.ts +18 -12
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +7 -7
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +1 -1
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -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/invalid_txs_after_reorg_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/interfaces.ts +31 -4
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +13 -7
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +35 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +22 -8
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +233 -123
- package/src/msg_validators/attestation_validator/attestation_validator.ts +46 -15
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +15 -7
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +15 -3
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +26 -3
- package/src/msg_validators/proposal_validator/proposal_validator.ts +94 -12
- package/src/msg_validators/tx_validator/README.md +13 -3
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +3 -3
- package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
- package/src/msg_validators/tx_validator/data_validator.ts +2 -0
- package/src/msg_validators/tx_validator/factory.ts +37 -20
- package/src/msg_validators/tx_validator/gas_validator.ts +99 -54
- package/src/msg_validators/tx_validator/index.ts +2 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
- package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
- package/src/services/data_store.ts +5 -13
- package/src/services/discv5/discV5_service.ts +126 -16
- package/src/services/discv5/persisted_enr_store.ts +158 -0
- package/src/services/dummy_service.ts +20 -39
- package/src/services/encoding.ts +28 -20
- package/src/services/gossipsub/README.md +33 -11
- package/src/services/gossipsub/topic_score_params.ts +9 -18
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +342 -290
- package/src/services/peer-manager/peer_manager.ts +63 -16
- package/src/services/peer-manager/peer_scoring.ts +81 -3
- package/src/services/reqresp/README.md +2 -37
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +39 -52
- package/src/services/reqresp/batch-tx-requester/interface.ts +11 -4
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
- package/src/services/reqresp/config.ts +19 -2
- package/src/services/reqresp/interface.ts +21 -47
- package/src/services/reqresp/metrics.ts +0 -1
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +1 -3
- package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -13
- package/src/services/reqresp/reqresp.ts +69 -252
- package/src/services/service.ts +28 -32
- package/src/services/tx_collection/config.ts +3 -80
- package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
- package/src/services/tx_collection/index.ts +1 -6
- package/src/services/tx_collection/instrumentation.ts +1 -7
- package/src/services/tx_collection/tx_collection.ts +330 -173
- package/src/services/tx_collection/tx_collection_sink.ts +2 -2
- package/src/services/tx_collection/tx_source.ts +2 -1
- package/src/services/tx_file_store/tx_file_store.ts +5 -17
- package/src/services/tx_provider.ts +5 -0
- package/src/test-helpers/make-test-p2p-clients.ts +3 -0
- package/src/test-helpers/mock-pubsub.ts +41 -64
- package/src/test-helpers/reqresp-nodes.ts +12 -22
- package/src/test-helpers/test_tx_provider.ts +5 -0
- package/src/test-helpers/testbench-utils.ts +35 -26
- package/src/testbench/p2p_client_testbench_worker.ts +68 -44
- package/src/testbench/worker_client_manager.ts +59 -19
- package/src/util.ts +33 -14
- package/src/versioning.ts +3 -33
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -315
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
- package/dest/msg_validators/clock_tolerance.d.ts +0 -21
- package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
- package/dest/msg_validators/clock_tolerance.js +0 -38
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
- 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/dest/services/tx_collection/fast_tx_collection.d.ts +0 -51
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/fast_tx_collection.js +0 -311
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -48
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
- package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/slow_tx_collection.js +0 -211
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -355
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
- package/src/msg_validators/clock_tolerance.ts +0 -52
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
- package/src/services/reqresp/protocols/block.ts +0 -37
- package/src/services/tx_collection/fast_tx_collection.ts +0 -361
- package/src/services/tx_collection/proposal_tx_collector.ts +0 -108
- package/src/services/tx_collection/slow_tx_collection.ts +0 -266
|
@@ -370,15 +370,17 @@ function applyDecs2203RFactory() {
|
|
|
370
370
|
function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
371
371
|
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
372
372
|
}
|
|
373
|
-
var _dec, _dec1, _dec2, _dec3, _dec4, _dec5,
|
|
373
|
+
var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _initProto;
|
|
374
374
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
375
|
-
import { maxBy } from '@aztec/foundation/collection';
|
|
375
|
+
import { compactArray, maxBy, merge } from '@aztec/foundation/collection';
|
|
376
376
|
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
377
377
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
378
378
|
import { Timer } from '@aztec/foundation/timer';
|
|
379
379
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
380
|
-
import {
|
|
380
|
+
import { DEFAULT_MAX_BLOCKS_PER_CHECKPOINT } from '@aztec/stdlib/config';
|
|
381
|
+
import { getNetworkTxGasLimits } from '@aztec/stdlib/gas';
|
|
381
382
|
import { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PMessage, PeerErrorSeverity, PeerErrorSeverityByHarshness, TopicType, createTopicString, getTopicsForConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
|
|
383
|
+
import { ConsensusTimetable, getDefaultCheckpointProposalSyncGrace } from '@aztec/stdlib/timetable';
|
|
382
384
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
383
385
|
import { Tx } from '@aztec/stdlib/tx';
|
|
384
386
|
import { compressComponentVersions } from '@aztec/stdlib/versioning';
|
|
@@ -396,22 +398,36 @@ import { tcp } from '@libp2p/tcp';
|
|
|
396
398
|
import { multiaddr } from '@multiformats/multiaddr';
|
|
397
399
|
import { ENR } from '@nethermindeth/enr';
|
|
398
400
|
import { createLibp2p } from 'libp2p';
|
|
401
|
+
import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
|
|
399
402
|
import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, DoubleSpendTxValidator, FishermanAttestationValidator, getDefaultAllowedSetupFunctions } from '../../msg_validators/index.js';
|
|
400
403
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
401
|
-
import { createFirstStageTxValidationsForGossipedTransactions, createSecondStageTxValidationsForGossipedTransactions, createTxValidatorForBlockProposalReceivedTxs
|
|
404
|
+
import { createFirstStageTxValidationsForGossipedTransactions, createSecondStageTxValidationsForGossipedTransactions, createTxValidatorForBlockProposalReceivedTxs } from '../../msg_validators/tx_validator/factory.js';
|
|
402
405
|
import { GossipSubEvent } from '../../types/index.js';
|
|
403
406
|
import { convertToMultiaddr } from '../../util.js';
|
|
404
407
|
import { getVersions } from '../../versioning.js';
|
|
405
408
|
import { AztecDatastore } from '../data_store.js';
|
|
406
409
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
407
|
-
import { SnappyTransform,
|
|
410
|
+
import { SnappyTransform, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
408
411
|
import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
409
412
|
import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
|
|
410
413
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
411
414
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
412
|
-
import {
|
|
415
|
+
import { YAMUX_MAX_MESSAGE_SIZE_BYTES } from '../reqresp/config.js';
|
|
416
|
+
import { ReqRespSubProtocol, ValidationError, pingHandler, reqGoodbyeHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
|
|
413
417
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
414
418
|
import { P2PInstrumentation } from './instrumentation.js';
|
|
419
|
+
/**
|
|
420
|
+
* Builds the {@link ConsensusTimetable} shared by the gossip validators for proposal/attestation receive-window
|
|
421
|
+
* bounds. Derived purely from protocol slot-timing constants plus the block sub-slot duration and the consensus
|
|
422
|
+
* materialization grace, so every node agrees on these bounds without depending on proposer operational budgets.
|
|
423
|
+
*/ function buildConsensusTimetable(config, l1Constants) {
|
|
424
|
+
const blockDuration = config.blockDurationMs / 1000;
|
|
425
|
+
return new ConsensusTimetable({
|
|
426
|
+
l1Constants,
|
|
427
|
+
blockDuration,
|
|
428
|
+
checkpointProposalSyncGrace: config.checkpointProposalSyncGraceSeconds ?? getDefaultCheckpointProposalSyncGrace(blockDuration)
|
|
429
|
+
});
|
|
430
|
+
}
|
|
415
431
|
_dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation)=>({
|
|
416
432
|
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString()
|
|
417
433
|
})), _dec1 = trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block)=>({
|
|
@@ -427,12 +443,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
427
443
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
|
|
428
444
|
[Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
|
|
429
445
|
[Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then((i)=>i.toString())
|
|
430
|
-
})), _dec5 = trackSpan('Libp2pService.
|
|
446
|
+
})), _dec5 = trackSpan('Libp2pService.validateRequestedBlockTxsConsistency', (request)=>({
|
|
431
447
|
[Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString()
|
|
432
|
-
})), _dec6 = trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
|
|
433
|
-
[Attributes.TX_HASH]: requestedTxHash.toString()
|
|
434
|
-
})), _dec7 = trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock)=>({
|
|
435
|
-
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString()
|
|
436
448
|
}));
|
|
437
449
|
/**
|
|
438
450
|
* Lib P2P implementation of the P2PService interface.
|
|
@@ -447,6 +459,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
447
459
|
epochCache;
|
|
448
460
|
proofVerifier;
|
|
449
461
|
worldStateSynchronizer;
|
|
462
|
+
blockMinFeesProvider;
|
|
463
|
+
txValidationCache;
|
|
450
464
|
static{
|
|
451
465
|
({ e: [_initProto] } = _apply_decs_2203_r(this, [
|
|
452
466
|
[
|
|
@@ -477,17 +491,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
477
491
|
[
|
|
478
492
|
_dec5,
|
|
479
493
|
2,
|
|
480
|
-
"
|
|
481
|
-
],
|
|
482
|
-
[
|
|
483
|
-
_dec6,
|
|
484
|
-
2,
|
|
485
|
-
"validateRequestedTxs"
|
|
486
|
-
],
|
|
487
|
-
[
|
|
488
|
-
_dec7,
|
|
489
|
-
2,
|
|
490
|
-
"validateRequestedBlock"
|
|
494
|
+
"validateRequestedBlockTxsConsistency"
|
|
491
495
|
]
|
|
492
496
|
], []));
|
|
493
497
|
}
|
|
@@ -499,9 +503,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
499
503
|
checkpointAttestationValidator;
|
|
500
504
|
protocolVersion;
|
|
501
505
|
topicStrings;
|
|
502
|
-
feesCache;
|
|
503
506
|
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */ duplicateProposalCallback;
|
|
507
|
+
/** Callback invoked when an oversized block proposal is stored as slashing evidence (triggers slashing). */ oversizedProposalCallback;
|
|
504
508
|
/** Callback invoked when a duplicate attestation is detected (triggers slashing). */ duplicateAttestationCallback;
|
|
509
|
+
/** Callback invoked when a valid checkpoint attestation is accepted into the pool. */ checkpointAttestationCallback;
|
|
505
510
|
/**
|
|
506
511
|
* Callback for when a block is received from a peer.
|
|
507
512
|
* @param block - The block received from the peer.
|
|
@@ -511,15 +516,20 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
511
516
|
* Callback for when a checkpoint proposal is received from a peer.
|
|
512
517
|
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
513
518
|
* @returns The attestations for the checkpoint, if any.
|
|
514
|
-
*/
|
|
519
|
+
*/ allNodesCheckpointReceivedCallback;
|
|
520
|
+
/**
|
|
521
|
+
* Callback for when a checkpoint proposal is received - specifically for validators - from a peer.
|
|
522
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
523
|
+
* @returns The attestations for the checkpoint, if any.
|
|
524
|
+
*/ validatorCheckpointReceivedCallback;
|
|
515
525
|
gossipSubEventHandler;
|
|
516
526
|
ipChangedHandler;
|
|
517
|
-
|
|
527
|
+
discoveredP2pIp;
|
|
518
528
|
instrumentation;
|
|
519
529
|
telemetry;
|
|
520
530
|
logger;
|
|
521
|
-
constructor(config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
|
|
522
|
-
super(telemetry, 'LibP2PService'), this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.msgIdSeenValidators = (_initProto(this), {}), this.protocolVersion = '', this.topicStrings = {};
|
|
531
|
+
constructor(config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, blockMinFeesProvider, telemetry, logger = createLogger('p2p:libp2p_service'), txValidationCache){
|
|
532
|
+
super(telemetry, 'LibP2PService'), this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.blockMinFeesProvider = blockMinFeesProvider, this.txValidationCache = txValidationCache, this.msgIdSeenValidators = (_initProto(this), {}), this.protocolVersion = '', this.topicStrings = {};
|
|
523
533
|
this.telemetry = telemetry;
|
|
524
534
|
// Create child logger with fisherman prefix if in fisherman mode
|
|
525
535
|
this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
|
|
@@ -535,13 +545,27 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
535
545
|
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
536
546
|
this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(TopicType.checkpoint_proposal, this.protocolVersion);
|
|
537
547
|
this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(TopicType.checkpoint_attestation, this.protocolVersion);
|
|
548
|
+
// Build the consensus timetable once from protocol slot-timing constants and inject it into every
|
|
549
|
+
// validator so they share one set of receive-window bounds, independent of proposer operational budgets.
|
|
550
|
+
const consensusTimetable = buildConsensusTimetable(config, epochCache.getL1Constants());
|
|
538
551
|
const proposalValidatorOpts = {
|
|
539
552
|
txsPermitted: !config.disableTransactions,
|
|
540
|
-
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint
|
|
553
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
554
|
+
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
|
|
555
|
+
skipSlotValidation: config.skipProposalSlotValidation,
|
|
556
|
+
signatureContext: {
|
|
557
|
+
chainId: config.l1ChainId,
|
|
558
|
+
rollupAddress: config.rollupAddress
|
|
559
|
+
},
|
|
560
|
+
clockDisparityMs: config.maxGossipClockDisparityMs
|
|
561
|
+
};
|
|
562
|
+
this.blockProposalValidator = new BlockProposalValidator(epochCache, consensusTimetable, proposalValidatorOpts);
|
|
563
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, consensusTimetable, proposalValidatorOpts);
|
|
564
|
+
const attestationValidatorOpts = {
|
|
565
|
+
signatureContext: proposalValidatorOpts.signatureContext,
|
|
566
|
+
clockDisparityMs: config.maxGossipClockDisparityMs
|
|
541
567
|
};
|
|
542
|
-
this.
|
|
543
|
-
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
544
|
-
this.checkpointAttestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry) : new CheckpointAttestationValidator(epochCache);
|
|
568
|
+
this.checkpointAttestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, consensusTimetable, mempools.attestationPool, telemetry, attestationValidatorOpts) : new CheckpointAttestationValidator(epochCache, consensusTimetable, attestationValidatorOpts);
|
|
545
569
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
546
570
|
this.blockReceivedCallback = async (block)=>{
|
|
547
571
|
this.logger.warn(`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`, {
|
|
@@ -549,13 +573,16 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
549
573
|
});
|
|
550
574
|
return true;
|
|
551
575
|
};
|
|
552
|
-
this.
|
|
553
|
-
|
|
576
|
+
this.allNodesCheckpointReceivedCallback = (_checkpoint)=>{
|
|
577
|
+
throw new CheckpointProposalReceivedCallbackNotRegisteredError();
|
|
578
|
+
};
|
|
579
|
+
this.validatorCheckpointReceivedCallback = (_checkpoint)=>{
|
|
554
580
|
return Promise.resolve(undefined);
|
|
555
581
|
};
|
|
556
582
|
}
|
|
557
583
|
updateConfig(config) {
|
|
558
584
|
this.reqresp.updateConfig(config);
|
|
585
|
+
this.config = merge(this.config, config);
|
|
559
586
|
}
|
|
560
587
|
/**
|
|
561
588
|
* Creates an instance of the LibP2P service.
|
|
@@ -563,12 +590,12 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
563
590
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
564
591
|
* @returns The new service.
|
|
565
592
|
*/ static async new(config, peerId, deps) {
|
|
566
|
-
const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, telemetry, logger, packageVersion } = deps;
|
|
593
|
+
const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, blockMinFeesProvider, telemetry, logger, packageVersion, txValidationCache } = deps;
|
|
567
594
|
const { p2pPort, maxPeerCount, listenAddress } = config;
|
|
568
595
|
const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
|
|
569
596
|
const datastore = new AztecDatastore(peerStore);
|
|
570
597
|
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
|
|
571
|
-
const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`, logger.getBindings()));
|
|
598
|
+
const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`, logger.getBindings()), peerStore);
|
|
572
599
|
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
573
600
|
const bootstrapNodes = [
|
|
574
601
|
...config.privatePeers,
|
|
@@ -583,31 +610,45 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
583
610
|
const versions = getVersions(config);
|
|
584
611
|
const protocolVersion = compressComponentVersions(versions);
|
|
585
612
|
const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
|
|
586
|
-
const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
613
|
+
const directPeers = compactArray(await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
614
|
+
try {
|
|
615
|
+
const peerId = await enr.peerId();
|
|
616
|
+
const address = enr.getLocationMultiaddr('tcp');
|
|
617
|
+
if (address === undefined) {
|
|
618
|
+
throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
|
|
619
|
+
}
|
|
620
|
+
return {
|
|
621
|
+
id: peerId,
|
|
622
|
+
addrs: [
|
|
623
|
+
address
|
|
624
|
+
]
|
|
625
|
+
};
|
|
626
|
+
} catch (err) {
|
|
627
|
+
// A malformed configured ENR shouldn't abort node setup — skip it and log.
|
|
628
|
+
logger.warn(`Skipping preferred peer with invalid ENR`, {
|
|
629
|
+
err
|
|
630
|
+
});
|
|
631
|
+
return undefined;
|
|
591
632
|
}
|
|
592
|
-
|
|
593
|
-
id: peerId,
|
|
594
|
-
addrs: [
|
|
595
|
-
address
|
|
596
|
-
]
|
|
597
|
-
};
|
|
598
|
-
}))).filter((peer)=>peer !== undefined);
|
|
633
|
+
})));
|
|
599
634
|
const announceTcpMultiaddr = config.p2pIp ? [
|
|
600
635
|
convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
|
|
601
636
|
] : [];
|
|
602
|
-
// Create dynamic topic score params based on network configuration
|
|
637
|
+
// Create dynamic topic score params based on network configuration. Scoring uses the network-wide
|
|
638
|
+
// max-blocks-per-checkpoint config value directly to size expected per-slot message rates; these are
|
|
639
|
+
// peer-rate thresholds, not consensus deadlines, so they need no proposer operational budgets.
|
|
603
640
|
const l1Constants = epochCache.getL1Constants();
|
|
604
641
|
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
605
642
|
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
606
643
|
heartbeatIntervalMs: config.gossipsubInterval,
|
|
607
644
|
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
608
|
-
|
|
645
|
+
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint ?? DEFAULT_MAX_BLOCKS_PER_CHECKPOINT,
|
|
609
646
|
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot
|
|
610
647
|
});
|
|
648
|
+
// Restrict gossipsub to exactly the topics we subscribe to. Without this, an arbitrary-topic
|
|
649
|
+
// message is transformed, msg-id'd and inserted into the seenCache before the subscription check,
|
|
650
|
+
// so a crafted topic colliding on msg id can suppress a real message as a duplicate.
|
|
651
|
+
const allowedTopics = getTopicsForConfig(config.disableTransactions).map((topic)=>createTopicString(topic, protocolVersion));
|
|
611
652
|
const node = await createLibp2p({
|
|
612
653
|
start: false,
|
|
613
654
|
peerId,
|
|
@@ -641,8 +682,11 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
641
682
|
],
|
|
642
683
|
datastore,
|
|
643
684
|
peerDiscovery,
|
|
685
|
+
// Pin the yamux frame size: MAX_REQRESP_REQUEST_SIZE_BYTES relies on a reqresp request fitting in one frame.
|
|
644
686
|
streamMuxers: [
|
|
645
|
-
yamux(
|
|
687
|
+
yamux({
|
|
688
|
+
maxMessageSize: YAMUX_MAX_MESSAGE_SIZE_BYTES
|
|
689
|
+
}),
|
|
646
690
|
mplex()
|
|
647
691
|
],
|
|
648
692
|
connectionEncryption: [
|
|
@@ -660,7 +704,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
660
704
|
},
|
|
661
705
|
connectionGater: {
|
|
662
706
|
denyInboundConnection: (maConn)=>{
|
|
663
|
-
const allowed = peerManager.
|
|
707
|
+
const allowed = peerManager.isAddressAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
|
|
664
708
|
if (allowed) {
|
|
665
709
|
return false;
|
|
666
710
|
}
|
|
@@ -670,7 +714,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
670
714
|
denyInboundEncryptedConnection: (peerId, _maConn)=>{
|
|
671
715
|
//NOTE: it is not necessary to check address here because this was already done by
|
|
672
716
|
// denyInboundConnection
|
|
673
|
-
const allowed = peerManager.
|
|
717
|
+
const allowed = peerManager.isPeerAllowedToConnect(peerId);
|
|
674
718
|
if (allowed) {
|
|
675
719
|
return false;
|
|
676
720
|
}
|
|
@@ -697,9 +741,13 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
697
741
|
mcacheLength: config.gossipsubMcacheLength,
|
|
698
742
|
mcacheGossip: config.gossipsubMcacheGossip,
|
|
699
743
|
seenTTL: config.gossipsubSeenTTL,
|
|
744
|
+
allowedTopics,
|
|
745
|
+
// No fastMsgIdFn: the fast-path dedup cache keys on a non-cryptographic 64-bit hash of the
|
|
746
|
+
// raw data only (no topic), so a collision — accidental or engineered via a weak seed — drops
|
|
747
|
+
// a different message with no fallback to the full id. Dedup instead rests solely on the
|
|
748
|
+
// cryptographic, topic-framed msgIdFn below.
|
|
700
749
|
msgIdFn: getMsgIdFn,
|
|
701
750
|
msgIdToStrFn: msgIdToStrFn,
|
|
702
|
-
fastMsgIdFn: fastMsgIdFn,
|
|
703
751
|
dataTransform: new SnappyTransform(),
|
|
704
752
|
metricsRegister: otelMetricsAdapter,
|
|
705
753
|
metricsTopicStrToLabel: metricsTopicStrToLabels(protocolVersion),
|
|
@@ -721,6 +769,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
721
769
|
const peerScoring = new PeerScoring(config, telemetry);
|
|
722
770
|
const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
|
|
723
771
|
const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
|
|
772
|
+
// Gate req/resp data protocols for unauthenticated peers when p2pAllowOnlyValidators is enabled
|
|
773
|
+
reqresp.setShouldRejectPeer((peerId)=>peerManager.shouldDisableP2PGossip(peerId));
|
|
724
774
|
// Configure application-specific scoring for gossipsub.
|
|
725
775
|
// The weight scales app score to align with gossipsub thresholds:
|
|
726
776
|
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
@@ -728,7 +778,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
728
778
|
// Note: positive topic scores can offset penalties, so alignment is best-effort.
|
|
729
779
|
node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
|
|
730
780
|
node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
731
|
-
return new LibP2PService(config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
|
|
781
|
+
return new LibP2PService(config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, blockMinFeesProvider, telemetry, logger, txValidationCache);
|
|
732
782
|
}
|
|
733
783
|
/**
|
|
734
784
|
* Starts the LibP2P service.
|
|
@@ -738,22 +788,19 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
738
788
|
if (this.node.status === 'started') {
|
|
739
789
|
throw new Error('P2P service already started');
|
|
740
790
|
}
|
|
741
|
-
// Get listen & announce addresses for logging
|
|
742
791
|
const { p2pIp, p2pPort } = this.config;
|
|
743
792
|
if (!p2pIp && !this.config.queryForIp) {
|
|
744
|
-
throw new Error('Announce address not provided.');
|
|
793
|
+
throw new Error('Announce address not provided and queryForIp is not enabled.');
|
|
745
794
|
}
|
|
746
795
|
const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
|
|
747
796
|
// Create request response protocol handlers
|
|
748
797
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
749
798
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
750
|
-
const blockHandler = reqRespBlockHandler(this.archiver);
|
|
751
799
|
const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
|
|
752
800
|
const requestResponseHandlers = {
|
|
753
801
|
[ReqRespSubProtocol.PING]: pingHandler,
|
|
754
802
|
[ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
|
|
755
|
-
[ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this)
|
|
756
|
-
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
|
|
803
|
+
[ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this)
|
|
757
804
|
};
|
|
758
805
|
if (!this.config.disableTransactions) {
|
|
759
806
|
const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.archiver, this.mempools.txPool);
|
|
@@ -762,15 +809,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
762
809
|
if (!this.config.disableTransactions) {
|
|
763
810
|
requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
|
|
764
811
|
}
|
|
765
|
-
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
766
|
-
const reqrespSubProtocolValidators = {
|
|
767
|
-
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
768
|
-
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
769
|
-
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
770
|
-
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this)
|
|
771
|
-
};
|
|
772
812
|
await this.peerManager.initializePeers();
|
|
773
|
-
await this.reqresp.start(requestResponseHandlers
|
|
813
|
+
await this.reqresp.start(requestResponseHandlers);
|
|
774
814
|
await this.node.start();
|
|
775
815
|
// Subscribe to standard GossipSub topics by default
|
|
776
816
|
for (const topic of getTopicsForConfig(this.config.disableTransactions)){
|
|
@@ -782,26 +822,31 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
782
822
|
if (!this.config.p2pDiscoveryDisabled) {
|
|
783
823
|
await this.peerDiscoveryService.start();
|
|
784
824
|
}
|
|
785
|
-
//
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
if (this.config.queryForIp && !p2pIp) {
|
|
825
|
+
// Bridge discv5 IP changes to libp2p's AddressManager so peers see the updated address
|
|
826
|
+
if (this.config.queryForIp) {
|
|
827
|
+
this.discoveredP2pIp = this.config.p2pIp;
|
|
828
|
+
this.logger.info('IP change tracking enabled, bridging discv5 IP updates to libp2p AddressManager');
|
|
790
829
|
this.ipChangedHandler = (ip)=>{
|
|
791
830
|
const addressManager = this.node.services.components.addressManager;
|
|
792
831
|
const newAddr = multiaddr(convertToMultiaddr(ip, this.config.p2pPort, 'tcp'));
|
|
793
|
-
|
|
794
|
-
if (
|
|
795
|
-
const oldAddr = multiaddr(convertToMultiaddr(
|
|
832
|
+
const previousIp = this.discoveredP2pIp;
|
|
833
|
+
if (previousIp) {
|
|
834
|
+
const oldAddr = multiaddr(convertToMultiaddr(previousIp, this.config.p2pPort, 'tcp'));
|
|
796
835
|
addressManager.removeObservedAddr(oldAddr);
|
|
836
|
+
this.logger.info('Libp2p announce address updated due to IP change', {
|
|
837
|
+
previousIp,
|
|
838
|
+
newIp: ip,
|
|
839
|
+
newMultiaddr: newAddr.toString()
|
|
840
|
+
});
|
|
841
|
+
} else {
|
|
842
|
+
this.logger.info('Libp2p announce address set from initial discv5 IP discovery', {
|
|
843
|
+
ip,
|
|
844
|
+
multiaddr: newAddr.toString()
|
|
845
|
+
});
|
|
797
846
|
}
|
|
798
847
|
addressManager.addObservedAddr(newAddr);
|
|
799
848
|
addressManager.confirmObservedAddr(newAddr);
|
|
800
|
-
// Store discovered IP
|
|
801
849
|
this.discoveredP2pIp = ip;
|
|
802
|
-
this.logger.info('Public IP discovered via discv5', {
|
|
803
|
-
ip
|
|
804
|
-
});
|
|
805
850
|
};
|
|
806
851
|
this.peerDiscoveryService.on('ip:changed', this.ipChangedHandler);
|
|
807
852
|
}
|
|
@@ -812,7 +857,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
812
857
|
this.logger.info(`Started P2P service`, {
|
|
813
858
|
listen: this.config.listenAddress,
|
|
814
859
|
port: this.config.p2pPort,
|
|
815
|
-
announce: announceTcpMultiaddr
|
|
860
|
+
announce: announceTcpMultiaddr,
|
|
816
861
|
peerId: this.node.peerId.toString()
|
|
817
862
|
});
|
|
818
863
|
}
|
|
@@ -822,9 +867,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
822
867
|
*/ async stop() {
|
|
823
868
|
// Remove gossip sub listener
|
|
824
869
|
this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
825
|
-
// Remove ip:changed listener if registered
|
|
826
870
|
if (this.ipChangedHandler) {
|
|
827
|
-
this.peerDiscoveryService.
|
|
871
|
+
this.peerDiscoveryService.removeListener('ip:changed', this.ipChangedHandler);
|
|
828
872
|
this.ipChangedHandler = undefined;
|
|
829
873
|
}
|
|
830
874
|
// Stop peer manager
|
|
@@ -840,8 +884,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
840
884
|
await this.stopLibP2P();
|
|
841
885
|
this.logger.info('LibP2P service stopped');
|
|
842
886
|
}
|
|
843
|
-
addReqRespSubProtocol(subProtocol, handler
|
|
844
|
-
return this.reqresp.addSubProtocol(subProtocol, handler
|
|
887
|
+
addReqRespSubProtocol(subProtocol, handler) {
|
|
888
|
+
return this.reqresp.addSubProtocol(subProtocol, handler);
|
|
845
889
|
}
|
|
846
890
|
registerThisValidatorAddresses(address) {
|
|
847
891
|
this.peerManager.registerThisValidatorAddresses(address);
|
|
@@ -863,14 +907,6 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
863
907
|
};
|
|
864
908
|
setImmediate(()=>void safeJob());
|
|
865
909
|
}
|
|
866
|
-
/**
|
|
867
|
-
* Send a batch of requests to peers, and return the responses
|
|
868
|
-
* @param protocol - The request response protocol to use
|
|
869
|
-
* @param requests - The requests to send to the peers
|
|
870
|
-
* @returns The responses to the requests
|
|
871
|
-
*/ sendBatchRequest(protocol, requests, pinnedPeerId) {
|
|
872
|
-
return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
|
|
873
|
-
}
|
|
874
910
|
sendRequestToPeer(peerId, subProtocol, payload, dialTimeout) {
|
|
875
911
|
return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
|
|
876
912
|
}
|
|
@@ -883,8 +919,11 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
883
919
|
registerBlockReceivedCallback(callback) {
|
|
884
920
|
this.blockReceivedCallback = callback;
|
|
885
921
|
}
|
|
886
|
-
|
|
887
|
-
this.
|
|
922
|
+
registerValidatorCheckpointReceivedCallback(callback) {
|
|
923
|
+
this.validatorCheckpointReceivedCallback = callback;
|
|
924
|
+
}
|
|
925
|
+
registerAllNodesCheckpointReceivedCallback(callback) {
|
|
926
|
+
this.allNodesCheckpointReceivedCallback = callback;
|
|
888
927
|
}
|
|
889
928
|
/**
|
|
890
929
|
* Registers a callback to be invoked when a duplicate proposal is detected.
|
|
@@ -893,12 +932,20 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
893
932
|
this.duplicateProposalCallback = callback;
|
|
894
933
|
}
|
|
895
934
|
/**
|
|
935
|
+
* Registers a callback to be invoked when an oversized block proposal is stored as slashing evidence.
|
|
936
|
+
*/ registerOversizedProposalCallback(callback) {
|
|
937
|
+
this.oversizedProposalCallback = callback;
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
896
940
|
* Registers a callback to be invoked when a duplicate attestation is detected.
|
|
897
941
|
* A validator signing attestations for different proposals at the same slot.
|
|
898
942
|
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
899
943
|
*/ registerDuplicateAttestationCallback(callback) {
|
|
900
944
|
this.duplicateAttestationCallback = callback;
|
|
901
945
|
}
|
|
946
|
+
registerCheckpointAttestationCallback(callback) {
|
|
947
|
+
this.checkpointAttestationCallback = callback;
|
|
948
|
+
}
|
|
902
949
|
/**
|
|
903
950
|
* Subscribes to a topic.
|
|
904
951
|
* @param topic - The topic to subscribe to.
|
|
@@ -1013,6 +1060,13 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1013
1060
|
}
|
|
1014
1061
|
// Process the message, optionally within a linked span for trace propagation
|
|
1015
1062
|
const processMessage = async ()=>{
|
|
1063
|
+
if (this.config.skipIncomingProposals && (msg.topic === this.topicStrings[TopicType.block_proposal] || msg.topic === this.topicStrings[TopicType.checkpoint_proposal])) {
|
|
1064
|
+
this.logger.warn(`Ignoring incoming proposal (skipIncomingProposals is set)`, {
|
|
1065
|
+
topic: msg.topic
|
|
1066
|
+
});
|
|
1067
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1016
1070
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
1017
1071
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
1018
1072
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
@@ -1076,6 +1130,18 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1076
1130
|
topicType
|
|
1077
1131
|
});
|
|
1078
1132
|
}
|
|
1133
|
+
const validationTimeMs = timer.ms();
|
|
1134
|
+
const mcacheWindowMs = this.config.gossipsubMcacheLength * this.config.gossipsubInterval;
|
|
1135
|
+
if (validationTimeMs > mcacheWindowMs * 0.75) {
|
|
1136
|
+
this.instrumentation.incSlowValidation(topicType);
|
|
1137
|
+
this.logger.warn(`Gossip validation for ${topicType} took ${validationTimeMs}ms, approaching mcache eviction window of ${mcacheWindowMs}ms. ` + `Message forwarding may be skipped if validation exceeds the window.`, {
|
|
1138
|
+
msgId,
|
|
1139
|
+
source: source.toString(),
|
|
1140
|
+
topicType,
|
|
1141
|
+
validationTimeMs,
|
|
1142
|
+
mcacheWindowMs
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1079
1145
|
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
1080
1146
|
this.logger.debug(`Message ${topicType} accepted by validator`, {
|
|
1081
1147
|
msgId,
|
|
@@ -1310,15 +1376,17 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1310
1376
|
}
|
|
1311
1377
|
}
|
|
1312
1378
|
// Attestation was added successfully - accept it so other nodes can also detect the equivocation
|
|
1379
|
+
this.checkpointAttestationCallback?.(attestation);
|
|
1313
1380
|
return {
|
|
1314
1381
|
result: TopicValidatorResult.Accept,
|
|
1315
1382
|
obj: attestation
|
|
1316
1383
|
};
|
|
1317
1384
|
}
|
|
1318
1385
|
async processBlockFromPeer(payloadData, msgId, source) {
|
|
1319
|
-
const { result, obj: block, metadata: { isEquivocated } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)), msgId, source, TopicType.block_proposal);
|
|
1320
|
-
// If not accepted or
|
|
1321
|
-
|
|
1386
|
+
const { result, obj: block, metadata: { isEquivocated, isOversized } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)), msgId, source, TopicType.block_proposal);
|
|
1387
|
+
// If not accepted, equivocated, or oversized, return. Oversized proposals are re-broadcast as
|
|
1388
|
+
// slashing evidence but never attested or processed.
|
|
1389
|
+
if (result !== TopicValidatorResult.Accept || !block || isEquivocated || isOversized) {
|
|
1322
1390
|
return;
|
|
1323
1391
|
}
|
|
1324
1392
|
await this.processValidBlockProposal(block, source);
|
|
@@ -1341,6 +1409,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1341
1409
|
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1342
1410
|
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1343
1411
|
const isEquivocated = count !== undefined && count > 1;
|
|
1412
|
+
// An oversized proposal (index at or beyond the consensus per-checkpoint limit) is structurally valid
|
|
1413
|
+
// proposer misbehavior: it is stored and re-broadcast as slashing evidence but never processed or
|
|
1414
|
+
// attested to. No-ops when maxBlocksPerCheckpoint is unset (local/test).
|
|
1415
|
+
const isOversized = this.config.maxBlocksPerCheckpoint !== undefined && block.indexWithinCheckpoint >= this.config.maxBlocksPerCheckpoint;
|
|
1344
1416
|
// Duplicate proposal received, no need to re-broadcast
|
|
1345
1417
|
if (alreadyExists) {
|
|
1346
1418
|
this.logger.debug(`Ignoring duplicate block proposal received`, {
|
|
@@ -1353,7 +1425,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1353
1425
|
result: TopicValidatorResult.Ignore,
|
|
1354
1426
|
obj: block,
|
|
1355
1427
|
metadata: {
|
|
1356
|
-
isEquivocated
|
|
1428
|
+
isEquivocated,
|
|
1429
|
+
isOversized
|
|
1357
1430
|
}
|
|
1358
1431
|
};
|
|
1359
1432
|
}
|
|
@@ -1369,11 +1442,30 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1369
1442
|
return {
|
|
1370
1443
|
result: TopicValidatorResult.Reject,
|
|
1371
1444
|
metadata: {
|
|
1372
|
-
isEquivocated
|
|
1445
|
+
isEquivocated,
|
|
1446
|
+
isOversized
|
|
1373
1447
|
},
|
|
1374
1448
|
severity: PeerErrorSeverity.HighToleranceError
|
|
1375
1449
|
};
|
|
1376
1450
|
}
|
|
1451
|
+
// The proposal was stored: if oversized, invoke the oversized callback so the proposer can be
|
|
1452
|
+
// slashed. Fired alongside (not instead of) equivocation detection below.
|
|
1453
|
+
if (isOversized) {
|
|
1454
|
+
const proposer = block.getSender();
|
|
1455
|
+
if (proposer) {
|
|
1456
|
+
this.logger.warn(`Detected oversized block proposal at slot ${block.slotNumber}`, {
|
|
1457
|
+
...block.toBlockInfo(),
|
|
1458
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1459
|
+
maxBlocksPerCheckpoint: this.config.maxBlocksPerCheckpoint,
|
|
1460
|
+
source: peerId.toString(),
|
|
1461
|
+
proposer: proposer.toString()
|
|
1462
|
+
});
|
|
1463
|
+
this.oversizedProposalCallback?.({
|
|
1464
|
+
slot: block.slotNumber,
|
|
1465
|
+
proposer
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1377
1469
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1378
1470
|
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1379
1471
|
if (isEquivocated) {
|
|
@@ -1395,14 +1487,19 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1395
1487
|
result: TopicValidatorResult.Accept,
|
|
1396
1488
|
obj: block,
|
|
1397
1489
|
metadata: {
|
|
1398
|
-
isEquivocated
|
|
1490
|
+
isEquivocated,
|
|
1491
|
+
isOversized
|
|
1399
1492
|
}
|
|
1400
1493
|
};
|
|
1401
1494
|
}
|
|
1402
1495
|
// Otherwise, we're good to go!
|
|
1403
1496
|
return {
|
|
1404
1497
|
result: TopicValidatorResult.Accept,
|
|
1405
|
-
obj: block
|
|
1498
|
+
obj: block,
|
|
1499
|
+
metadata: {
|
|
1500
|
+
isEquivocated: false,
|
|
1501
|
+
isOversized
|
|
1502
|
+
}
|
|
1406
1503
|
};
|
|
1407
1504
|
}
|
|
1408
1505
|
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
@@ -1421,22 +1518,35 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1421
1518
|
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1422
1519
|
if (!isValid) {
|
|
1423
1520
|
this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1521
|
+
// Release the protections this proposal created so its txs return to pending. Only entries still
|
|
1522
|
+
// keyed to this slot are cleared, so a tx referenced by a live proposal at another slot stays protected.
|
|
1523
|
+
await this.mempools.txPool.unprotectTxs(block.txHashes, slot);
|
|
1424
1524
|
}
|
|
1425
1525
|
}
|
|
1426
1526
|
/**
|
|
1427
1527
|
* Handle a gossiped checkpoint proposal.
|
|
1428
1528
|
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1429
1529
|
*/ async handleGossipedCheckpointProposal(payloadData, msgId, source) {
|
|
1430
|
-
const { result, obj: checkpoint, metadata: { isEquivocated, processBlock } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_proposal);
|
|
1530
|
+
const { result, obj: checkpoint, metadata: { isEquivocated, processBlock, isOversized } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_proposal);
|
|
1531
|
+
// An oversized checkpoint is re-broadcast as slashing evidence but never attested or processed.
|
|
1532
|
+
// Process checkpoint proposal if valid and neither equivocated nor oversized.
|
|
1533
|
+
const processCheckpointFn = ()=>result === TopicValidatorResult.Accept && checkpoint && !isEquivocated && !isOversized ? this.processValidCheckpointProposal(checkpoint.toCore(), source) : Promise.resolve();
|
|
1431
1534
|
// If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
|
|
1432
1535
|
// TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1536
|
+
const processBlockFn = ()=>processBlock && checkpoint && checkpoint.getBlockProposal() ? this.processValidBlockProposal(checkpoint.getBlockProposal(), source) : Promise.resolve();
|
|
1537
|
+
// A node that skips checkpoint validation attests without re-executing the embedded last block, so run
|
|
1538
|
+
// the checkpoint callback first: this creates and broadcasts the attestation before the block is
|
|
1539
|
+
// processed. Otherwise the block's re-execution — which can stall until the re-execution deadline
|
|
1540
|
+
// waiting for a parent that may never arrive — would delay the attestation past the slot's attestation
|
|
1541
|
+
// window, after which peers reject it as stale.
|
|
1542
|
+
if (this.config.skipCheckpointProposalValidation) {
|
|
1543
|
+
await processCheckpointFn();
|
|
1544
|
+
await processBlockFn();
|
|
1437
1545
|
return;
|
|
1438
1546
|
}
|
|
1439
|
-
|
|
1547
|
+
// Process the block first, since it's required for the checkpoint proposal validation.
|
|
1548
|
+
await processBlockFn();
|
|
1549
|
+
await processCheckpointFn();
|
|
1440
1550
|
}
|
|
1441
1551
|
/**
|
|
1442
1552
|
* Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
|
|
@@ -1459,13 +1569,15 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1459
1569
|
// Extract and try to add the block proposal first if present
|
|
1460
1570
|
const blockProposal = checkpoint.getBlockProposal();
|
|
1461
1571
|
let processBlock = false;
|
|
1572
|
+
let isOversized = false;
|
|
1462
1573
|
if (blockProposal) {
|
|
1463
1574
|
this.logger.debug(`Validating block proposal from propagated checkpoint`, {
|
|
1464
1575
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1465
1576
|
[Attributes.P2P_ID]: peerId.toString()
|
|
1466
1577
|
});
|
|
1467
1578
|
const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1468
|
-
const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
|
|
1579
|
+
const { obj, metadata: { isEquivocated, isOversized: blockIsOversized } = {} } = blockProposalResult;
|
|
1580
|
+
isOversized = blockIsOversized ?? false;
|
|
1469
1581
|
if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1470
1582
|
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1471
1583
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
@@ -1477,7 +1589,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1477
1589
|
result: TopicValidatorResult.Reject,
|
|
1478
1590
|
severity: 'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError
|
|
1479
1591
|
};
|
|
1480
|
-
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1592
|
+
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated && !isOversized) {
|
|
1593
|
+
// An oversized terminal block is re-broadcast as slashing evidence but never processed.
|
|
1481
1594
|
processBlock = true;
|
|
1482
1595
|
}
|
|
1483
1596
|
}
|
|
@@ -1497,11 +1610,12 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1497
1610
|
obj: checkpoint,
|
|
1498
1611
|
metadata: {
|
|
1499
1612
|
isEquivocated,
|
|
1500
|
-
processBlock
|
|
1613
|
+
processBlock,
|
|
1614
|
+
isOversized
|
|
1501
1615
|
}
|
|
1502
1616
|
};
|
|
1503
1617
|
}
|
|
1504
|
-
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1618
|
+
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast.
|
|
1505
1619
|
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1506
1620
|
if (!added) {
|
|
1507
1621
|
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
@@ -1514,7 +1628,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1514
1628
|
obj: checkpoint,
|
|
1515
1629
|
metadata: {
|
|
1516
1630
|
isEquivocated,
|
|
1517
|
-
processBlock
|
|
1631
|
+
processBlock,
|
|
1632
|
+
isOversized
|
|
1518
1633
|
},
|
|
1519
1634
|
severity: PeerErrorSeverity.HighToleranceError
|
|
1520
1635
|
};
|
|
@@ -1541,7 +1656,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1541
1656
|
obj: checkpoint,
|
|
1542
1657
|
metadata: {
|
|
1543
1658
|
isEquivocated,
|
|
1544
|
-
processBlock
|
|
1659
|
+
processBlock,
|
|
1660
|
+
isOversized
|
|
1545
1661
|
}
|
|
1546
1662
|
};
|
|
1547
1663
|
}
|
|
@@ -1551,7 +1667,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1551
1667
|
obj: checkpoint,
|
|
1552
1668
|
metadata: {
|
|
1553
1669
|
processBlock,
|
|
1554
|
-
isEquivocated
|
|
1670
|
+
isEquivocated,
|
|
1671
|
+
isOversized
|
|
1555
1672
|
}
|
|
1556
1673
|
};
|
|
1557
1674
|
}
|
|
@@ -1566,9 +1683,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1566
1683
|
archive: checkpoint.archive.toString(),
|
|
1567
1684
|
source: sender.toString()
|
|
1568
1685
|
});
|
|
1686
|
+
await this.allNodesCheckpointReceivedCallback(checkpoint, sender);
|
|
1569
1687
|
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1570
1688
|
// to validate and potentially generate attestations
|
|
1571
|
-
const attestations = await this.
|
|
1689
|
+
const attestations = await this.validatorCheckpointReceivedCallback(checkpoint, sender);
|
|
1572
1690
|
if (attestations && attestations.length > 0) {
|
|
1573
1691
|
// If the callback returned attestations, add them to the pool and propagate them
|
|
1574
1692
|
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
@@ -1592,62 +1710,66 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1592
1710
|
});
|
|
1593
1711
|
}
|
|
1594
1712
|
/**
|
|
1595
|
-
* Validate the requested block transactions
|
|
1713
|
+
* Validate the requested block transactions request-response consistency.
|
|
1714
|
+
* It does NOT validate the transactions themselves.
|
|
1596
1715
|
* @param request - The block transactions request.
|
|
1597
1716
|
* @param response - The block transactions response.
|
|
1598
1717
|
* @param peerId - The ID of the peer that made the request.
|
|
1599
|
-
* @returns True if the
|
|
1600
|
-
*/ async
|
|
1601
|
-
const requestedTxValidator = this.createRequestedTxValidator();
|
|
1718
|
+
* @returns True if the request-response is consistent, false otherwise.
|
|
1719
|
+
*/ async validateRequestedBlockTxsConsistency(request, response, peerId) {
|
|
1602
1720
|
try {
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
throw new ValidationError(`Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`);
|
|
1606
|
-
}
|
|
1607
|
-
if (response.txIndices.getLength() !== request.txIndices.getLength()) {
|
|
1608
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1609
|
-
throw new ValidationError(`Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`);
|
|
1610
|
-
}
|
|
1611
|
-
// Check no duplicates and not exceeding returnable count
|
|
1612
|
-
const requestedIndices = new Set(request.txIndices.getTrueIndices());
|
|
1613
|
-
const availableIndices = new Set(response.txIndices.getTrueIndices());
|
|
1614
|
-
const maxReturnable = [
|
|
1615
|
-
...requestedIndices
|
|
1616
|
-
].filter((i)=>availableIndices.has(i)).length;
|
|
1617
|
-
const returnedHashes = await Promise.all(response.txs.map((tx)=>tx.getTxHash().toString()));
|
|
1721
|
+
// Check for duplicates txs (or hashes) in the response.
|
|
1722
|
+
const returnedHashes = response.txs.map((tx)=>tx.getTxHash().toString());
|
|
1618
1723
|
const uniqueReturned = new Set(returnedHashes.map((h)=>h.toString()));
|
|
1619
1724
|
if (uniqueReturned.size !== returnedHashes.length) {
|
|
1620
1725
|
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1621
1726
|
throw new ValidationError(`Received duplicate txs in block txs response`);
|
|
1622
1727
|
}
|
|
1623
|
-
|
|
1728
|
+
// We get the block tx hashes from the proposal or the archiver.
|
|
1729
|
+
const proposal = await this.mempools.attestationPool.getBlockProposalByArchive(request.archiveRoot.toString());
|
|
1730
|
+
const blockTxHashes = proposal?.txHashes ?? (await this.archiver.getBlock({
|
|
1731
|
+
archive: request.archiveRoot
|
|
1732
|
+
}))?.body.txEffects.map((e)=>e.txHash);
|
|
1733
|
+
// If we don't have the block, we can't verify membership/order of the returned txs.
|
|
1734
|
+
if (!blockTxHashes) {
|
|
1735
|
+
// This shouldn't happen, since we asked for the block (proposal).
|
|
1736
|
+
// Neither a local proposal nor an archived block: we cannot verify membership/order of the
|
|
1737
|
+
// returned txs. This is a local-state gap, not a peer fault, so we do not penalize.
|
|
1738
|
+
this.logger.warn(`Block ${request.archiveRoot.toString()} not found in attestation pool or archiver; cannot validate membership/order of returned txs`);
|
|
1739
|
+
// NOTE: We mark the response as invalid, given the limitations of a true/false return value.
|
|
1740
|
+
return false;
|
|
1741
|
+
}
|
|
1742
|
+
// Verify that the returned tx hashes are a subset of (tx hashes by index) U (explicitly requested tx hashes).
|
|
1743
|
+
const uniqueRequestedHashes = new Set([
|
|
1744
|
+
// tx hashes requested by index.
|
|
1745
|
+
...request.txIndices.getTrueIndices().map((i)=>blockTxHashes[i].toString()),
|
|
1746
|
+
// explicitly requested tx hashes.
|
|
1747
|
+
...request.txHashes.map((h)=>h.toString())
|
|
1748
|
+
]);
|
|
1749
|
+
if (!returnedHashes.every((h)=>uniqueRequestedHashes.has(h))) {
|
|
1750
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1751
|
+
throw new ValidationError('Returned txs should be a subset of (tx hashes by index) U (explicitly requested tx hashes)');
|
|
1752
|
+
}
|
|
1753
|
+
// Tx indices information is optional, but if present, we need to verify a few things.
|
|
1754
|
+
if (!response.peerHasBlock()) {
|
|
1755
|
+
this.logger.debug(`Peer ${peerId.toString()} signalled missing block`);
|
|
1756
|
+
return true;
|
|
1757
|
+
}
|
|
1758
|
+
// If the response has a non-empty bitvector, it needs to be consistent with the number of txs in the block.
|
|
1759
|
+
if (response.txIndices.getLength() !== blockTxHashes.length) {
|
|
1624
1760
|
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1625
|
-
throw new ValidationError(`Received
|
|
1761
|
+
throw new ValidationError(`Received block txs with mismatched bitvector length: expected ${blockTxHashes.length}, got ${response.txIndices.getLength()}`);
|
|
1626
1762
|
}
|
|
1627
|
-
//
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
]));
|
|
1637
|
-
const allowedIndexSet = new Set(intersectIdx);
|
|
1638
|
-
const indices = returnedHashes.map((h)=>hashToIndexInProposal.get(h));
|
|
1639
|
-
const allAllowed = indices.every((idx)=>idx !== undefined && allowedIndexSet.has(idx));
|
|
1640
|
-
const strictlyIncreasing = indices.every((idx, i)=>i === 0 ? idx !== undefined : idx > indices[i - 1]);
|
|
1641
|
-
if (!allAllowed || !strictlyIncreasing) {
|
|
1642
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1643
|
-
throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
|
|
1644
|
-
}
|
|
1645
|
-
} else {
|
|
1646
|
-
// No local proposal, cannot check the membership/order of the returned txs
|
|
1647
|
-
this.logger.warn(`Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`);
|
|
1648
|
-
return false;
|
|
1763
|
+
// For every index we requested that the peer claims to have (per its bitvector), the
|
|
1764
|
+
// corresponding tx must be present in the response. A peer advertising availability but
|
|
1765
|
+
// withholding the tx is inconsistent.
|
|
1766
|
+
const returnedHashSet = new Set(returnedHashes);
|
|
1767
|
+
const expectedIndices = request.txIndices.getTrueIndices().filter((i)=>response.txIndices.isSet(i));
|
|
1768
|
+
const missingExpected = expectedIndices.some((i)=>!returnedHashSet.has(blockTxHashes[i].toString()));
|
|
1769
|
+
if (missingExpected) {
|
|
1770
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1771
|
+
throw new ValidationError('Peer advertised requested txs via indices but did not return them');
|
|
1649
1772
|
}
|
|
1650
|
-
await Promise.all(response.txs.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator)));
|
|
1651
1773
|
return true;
|
|
1652
1774
|
} catch (e) {
|
|
1653
1775
|
if (e instanceof ValidationError) {
|
|
@@ -1658,104 +1780,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1658
1780
|
return false;
|
|
1659
1781
|
}
|
|
1660
1782
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
*
|
|
1664
|
-
* The core component of this validator is that each tx hash MUST match the requested tx hash,
|
|
1665
|
-
* In order to perform this check, the tx proof must be verified.
|
|
1666
|
-
*
|
|
1667
|
-
* Note: This function is called from within `ReqResp.sendRequest` as part of the
|
|
1668
|
-
* ReqRespSubProtocol.TX subprotocol validation.
|
|
1669
|
-
*
|
|
1670
|
-
* @param requestedTxHash - The collection of the txs that was requested.
|
|
1671
|
-
* @param responseTx - The collection of txs that was received as a response to the request.
|
|
1672
|
-
* @param peerId - The peer ID of the peer that sent the tx.
|
|
1673
|
-
* @returns True if the whole collection of txs is valid, false otherwise.
|
|
1674
|
-
*/ async validateRequestedTxs(requestedTxHash, responseTx, peerId) {
|
|
1675
|
-
const requested = new Set(requestedTxHash.map((h)=>h.toString()));
|
|
1676
|
-
const requestedTxValidator = this.createRequestedTxValidator();
|
|
1677
|
-
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
|
|
1678
|
-
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
1679
|
-
try {
|
|
1680
|
-
await Promise.all(responseTx.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
|
|
1681
|
-
return true;
|
|
1682
|
-
} catch (e) {
|
|
1683
|
-
if (e instanceof ValidationError) {
|
|
1684
|
-
this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
|
|
1685
|
-
} else {
|
|
1686
|
-
this.logger.error(`Error during validation of requested txs`, e);
|
|
1687
|
-
}
|
|
1688
|
-
return false;
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
/**
|
|
1692
|
-
* Validates a BLOCK response.
|
|
1693
|
-
*
|
|
1694
|
-
* If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
|
|
1695
|
-
* Penalizes on block number mismatch or hash mismatch.
|
|
1696
|
-
*
|
|
1697
|
-
* @param requestedBlockNumber - The requested block number.
|
|
1698
|
-
* @param responseBlock - The block returned by the peer.
|
|
1699
|
-
* @param peerId - The peer that returned the block.
|
|
1700
|
-
* @returns True if the response is valid, false otherwise.
|
|
1701
|
-
*/ async validateRequestedBlock(requestedBlockNumber, responseBlock, peerId) {
|
|
1702
|
-
try {
|
|
1703
|
-
const reqNum = Number(requestedBlockNumber.toString());
|
|
1704
|
-
if (responseBlock.number !== reqNum) {
|
|
1705
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1706
|
-
return false;
|
|
1707
|
-
}
|
|
1708
|
-
const local = await this.archiver.getBlock(BlockNumber(reqNum));
|
|
1709
|
-
if (!local) {
|
|
1710
|
-
// We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
|
|
1711
|
-
// TODO: Consider extending this validator to accept an expected hash or
|
|
1712
|
-
// performing quorum-based checks when using P2P syncing prior to L1 sync.
|
|
1713
|
-
this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
|
|
1714
|
-
return false;
|
|
1715
|
-
}
|
|
1716
|
-
const [localHash, respHash] = await Promise.all([
|
|
1717
|
-
local.hash(),
|
|
1718
|
-
responseBlock.hash()
|
|
1719
|
-
]);
|
|
1720
|
-
if (!localHash.equals(respHash)) {
|
|
1721
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1722
|
-
return false;
|
|
1723
|
-
}
|
|
1724
|
-
return true;
|
|
1725
|
-
} catch (e) {
|
|
1726
|
-
this.logger.warn(`Error validating requested block`, e);
|
|
1727
|
-
return false;
|
|
1728
|
-
}
|
|
1729
|
-
}
|
|
1730
|
-
async validateRequestedTx(tx, peerId, txValidator, requested) {
|
|
1731
|
-
const penalize = (severity)=>this.peerManager.penalizePeer(peerId, severity);
|
|
1732
|
-
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
1733
|
-
penalize(PeerErrorSeverity.MidToleranceError);
|
|
1734
|
-
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
1735
|
-
}
|
|
1736
|
-
const { result } = await txValidator.validateTx(tx);
|
|
1737
|
-
if (result === 'invalid') {
|
|
1738
|
-
penalize(PeerErrorSeverity.LowToleranceError);
|
|
1739
|
-
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
createRequestedTxValidator() {
|
|
1743
|
-
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1744
|
-
l1ChainId: this.config.l1ChainId,
|
|
1745
|
-
rollupVersion: this.config.rollupVersion
|
|
1746
|
-
});
|
|
1747
|
-
}
|
|
1748
|
-
async getGasFees(blockNumber) {
|
|
1749
|
-
if (blockNumber === this.feesCache?.blockNumber) {
|
|
1750
|
-
return this.feesCache.gasFees;
|
|
1751
|
-
}
|
|
1752
|
-
const header = await this.archiver.getBlockHeader(blockNumber);
|
|
1753
|
-
const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
|
|
1754
|
-
this.feesCache = {
|
|
1755
|
-
blockNumber,
|
|
1756
|
-
gasFees
|
|
1757
|
-
};
|
|
1758
|
-
return gasFees;
|
|
1783
|
+
getGasFees() {
|
|
1784
|
+
return this.blockMinFeesProvider.getCurrentMinFees();
|
|
1759
1785
|
}
|
|
1760
1786
|
/**
|
|
1761
1787
|
* Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
|
|
@@ -1766,16 +1792,18 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1766
1792
|
txValidatorConfig: {
|
|
1767
1793
|
l1ChainId: this.config.l1ChainId,
|
|
1768
1794
|
rollupVersion: this.config.rollupVersion,
|
|
1769
|
-
proofVerifier: this.proofVerifier
|
|
1795
|
+
proofVerifier: this.proofVerifier,
|
|
1796
|
+
txValidationCache: this.txValidationCache
|
|
1770
1797
|
},
|
|
1771
|
-
peerScoring: this.peerManager
|
|
1798
|
+
peerScoring: this.peerManager,
|
|
1799
|
+
validateRequestedBlockTxsConsistency: this.validateRequestedBlockTxsConsistency.bind(this)
|
|
1772
1800
|
};
|
|
1773
1801
|
}
|
|
1774
1802
|
async validateTxsReceivedInBlockProposal(txs) {
|
|
1775
1803
|
const validator = createTxValidatorForBlockProposalReceivedTxs(this.proofVerifier, {
|
|
1776
1804
|
l1ChainId: this.config.l1ChainId,
|
|
1777
1805
|
rollupVersion: this.config.rollupVersion
|
|
1778
|
-
}, this.logger.getBindings());
|
|
1806
|
+
}, this.logger.getBindings(), this.txValidationCache);
|
|
1779
1807
|
const results = await Promise.all(txs.map(async (tx)=>{
|
|
1780
1808
|
const result = await validator.validateTx(tx);
|
|
1781
1809
|
return result.result !== 'invalid';
|
|
@@ -1785,17 +1813,17 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1785
1813
|
}
|
|
1786
1814
|
}
|
|
1787
1815
|
/** Creates the first stage (fast) validators for gossiped transactions. */ async createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp) {
|
|
1788
|
-
const gasFees = await this.getGasFees(
|
|
1816
|
+
const gasFees = await this.getGasFees();
|
|
1789
1817
|
const allowedInSetup = [
|
|
1790
1818
|
...await getDefaultAllowedSetupFunctions(),
|
|
1791
1819
|
...this.config.txPublicSetupAllowListExtend ?? []
|
|
1792
1820
|
];
|
|
1793
1821
|
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1794
1822
|
const l1Constants = await this.archiver.getL1Constants();
|
|
1823
|
+
const networkTxGasLimits = getNetworkTxGasLimits(this.config, l1Constants);
|
|
1795
1824
|
return createFirstStageTxValidationsForGossipedTransactions(nextSlotTimestamp, blockNumber, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, !this.config.disableTransactions, allowedInSetup, this.logger.getBindings(), {
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
maxBlockDAGas: this.config.validateMaxDABlockGas
|
|
1825
|
+
maxTxL2Gas: networkTxGasLimits.l2Gas,
|
|
1826
|
+
maxTxDAGas: networkTxGasLimits.daGas
|
|
1799
1827
|
});
|
|
1800
1828
|
}
|
|
1801
1829
|
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */ createSecondStageMessageValidators() {
|