@aztec/p2p 0.0.1-commit.f2ce05ee → 0.0.1-commit.f5d02921e
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 +9 -9
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +52 -14
- 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 +164 -224
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +20 -10
- package/dest/config.d.ts +52 -16
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +100 -37
- 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 +21 -12
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +75 -40
- 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 +2 -2
- 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 +16 -14
- 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 +2 -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 +1 -1
- 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 +7 -5
- 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 +30 -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 +78 -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 +144 -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 +364 -189
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +5 -4
- package/dest/msg_validators/clock_tolerance.d.ts +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +4 -3
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +53 -41
- 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/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 +67 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +104 -37
- 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/dummy_service.d.ts +12 -6
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +12 -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/topic_score_params.d.ts +18 -6
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +32 -10
- package/dest/services/libp2p/libp2p_service.d.ts +37 -23
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +274 -173
- 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 +24 -9
- package/dest/services/peer-manager/peer_scoring.d.ts +5 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +28 -10
- 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/interface.d.ts +10 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +15 -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/tx.d.ts +7 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/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/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +30 -14
- 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 +1 -2
- package/dest/test-helpers/mock-pubsub.d.ts +30 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +105 -4
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -2
- 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 +115 -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 +57 -27
- package/dest/testbench/worker_client_manager.d.ts +3 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +6 -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 +102 -25
- package/src/client/interface.ts +52 -34
- package/src/client/p2p_client.ts +190 -266
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +33 -14
- package/src/config.ts +149 -43
- 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 +104 -50
- 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 +2 -1
- package/src/mem_pools/index.ts +1 -1
- package/src/mem_pools/instrumentation.ts +17 -13
- 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 +4 -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 +5 -5
- 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 +32 -12
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +209 -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 +410 -187
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +5 -4
- package/src/msg_validators/clock_tolerance.ts +4 -3
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +69 -45
- package/src/msg_validators/tx_validator/README.md +119 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +5 -5
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
- package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
- package/src/msg_validators/tx_validator/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 +394 -78
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +123 -27
- 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/dummy_service.ts +18 -7
- package/src/services/encoding.ts +18 -10
- package/src/services/gossipsub/README.md +29 -14
- package/src/services/gossipsub/topic_score_params.ts +49 -13
- package/src/services/libp2p/libp2p_service.ts +288 -198
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +28 -9
- package/src/services/peer-manager/peer_scoring.ts +21 -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/interface.ts +26 -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/tx.ts +22 -0
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/reqresp.ts +35 -15
- 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 +4 -6
- package/src/test-helpers/mock-pubsub.ts +146 -9
- package/src/test-helpers/reqresp-nodes.ts +3 -6
- package/src/test-helpers/testbench-utils.ts +137 -43
- package/src/testbench/p2p_client_testbench_worker.ts +63 -30
- package/src/testbench/worker_client_manager.ts +13 -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/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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import {
|
|
3
|
+
import { maxBy } from '@aztec/foundation/collection';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
6
6
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
@@ -17,13 +17,12 @@ import {
|
|
|
17
17
|
CheckpointProposal,
|
|
18
18
|
type CheckpointProposalCore,
|
|
19
19
|
type Gossipable,
|
|
20
|
-
P2PClientType,
|
|
21
20
|
P2PMessage,
|
|
22
|
-
type ValidationResult as P2PValidationResult,
|
|
23
21
|
PeerErrorSeverity,
|
|
22
|
+
PeerErrorSeverityByHarshness,
|
|
24
23
|
TopicType,
|
|
25
24
|
createTopicString,
|
|
26
|
-
|
|
25
|
+
getTopicsForConfig,
|
|
27
26
|
metricsTopicStrToLabels,
|
|
28
27
|
} from '@aztec/stdlib/p2p';
|
|
29
28
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -59,6 +58,7 @@ import { ENR } from '@nethermindeth/enr';
|
|
|
59
58
|
import { createLibp2p } from 'libp2p';
|
|
60
59
|
|
|
61
60
|
import type { P2PConfig } from '../../config.js';
|
|
61
|
+
import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
|
|
62
62
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
63
63
|
import {
|
|
64
64
|
BlockProposalValidator,
|
|
@@ -70,9 +70,11 @@ import {
|
|
|
70
70
|
} from '../../msg_validators/index.js';
|
|
71
71
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
72
72
|
import {
|
|
73
|
-
type
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
type TransactionValidator,
|
|
74
|
+
createFirstStageTxValidationsForGossipedTransactions,
|
|
75
|
+
createSecondStageTxValidationsForGossipedTransactions,
|
|
76
|
+
createTxValidatorForBlockProposalReceivedTxs,
|
|
77
|
+
createTxValidatorForReqResponseReceivedTxs,
|
|
76
78
|
} from '../../msg_validators/tx_validator/factory.js';
|
|
77
79
|
import { GossipSubEvent } from '../../types/index.js';
|
|
78
80
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
@@ -88,6 +90,9 @@ import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
|
88
90
|
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
89
91
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
90
92
|
import {
|
|
93
|
+
AuthRequest,
|
|
94
|
+
BlockTxsRequest,
|
|
95
|
+
BlockTxsResponse,
|
|
91
96
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
92
97
|
type ReqRespInterface,
|
|
93
98
|
type ReqRespResponse,
|
|
@@ -95,14 +100,9 @@ import {
|
|
|
95
100
|
type ReqRespSubProtocolHandler,
|
|
96
101
|
type ReqRespSubProtocolHandlers,
|
|
97
102
|
type ReqRespSubProtocolValidators,
|
|
103
|
+
StatusMessage,
|
|
98
104
|
type SubProtocolMap,
|
|
99
105
|
ValidationError,
|
|
100
|
-
} from '../reqresp/index.js';
|
|
101
|
-
import {
|
|
102
|
-
AuthRequest,
|
|
103
|
-
BlockTxsRequest,
|
|
104
|
-
BlockTxsResponse,
|
|
105
|
-
StatusMessage,
|
|
106
106
|
pingHandler,
|
|
107
107
|
reqGoodbyeHandler,
|
|
108
108
|
reqRespBlockHandler,
|
|
@@ -114,6 +114,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
114
114
|
import type {
|
|
115
115
|
P2PBlockReceivedCallback,
|
|
116
116
|
P2PCheckpointReceivedCallback,
|
|
117
|
+
P2PDuplicateAttestationCallback,
|
|
117
118
|
P2PService,
|
|
118
119
|
PeerDiscoveryService,
|
|
119
120
|
} from '../service.js';
|
|
@@ -130,12 +131,12 @@ type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: Vali
|
|
|
130
131
|
// REFACTOR: Unify with the type above
|
|
131
132
|
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
132
133
|
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
133
|
-
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
134
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M; severity: PeerErrorSeverity };
|
|
134
135
|
|
|
135
136
|
/**
|
|
136
137
|
* Lib P2P implementation of the P2PService interface.
|
|
137
138
|
*/
|
|
138
|
-
export class LibP2PService
|
|
139
|
+
export class LibP2PService extends WithTracer implements P2PService {
|
|
139
140
|
private discoveryRunningPromise?: RunningPromise;
|
|
140
141
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
141
142
|
|
|
@@ -156,6 +157,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
156
157
|
type: 'checkpoint' | 'block';
|
|
157
158
|
}) => void;
|
|
158
159
|
|
|
160
|
+
/** Callback invoked when a duplicate attestation is detected (triggers slashing). */
|
|
161
|
+
private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
|
|
162
|
+
|
|
159
163
|
/**
|
|
160
164
|
* Callback for when a block is received from a peer.
|
|
161
165
|
* @param block - The block received from the peer.
|
|
@@ -168,7 +172,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
168
172
|
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
169
173
|
* @returns The attestations for the checkpoint, if any.
|
|
170
174
|
*/
|
|
171
|
-
private
|
|
175
|
+
private allNodesCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
176
|
+
/**
|
|
177
|
+
* Callback for when a checkpoint proposal is received - specifically for validators - from a peer.
|
|
178
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
179
|
+
* @returns The attestations for the checkpoint, if any.
|
|
180
|
+
*/
|
|
181
|
+
private validatorCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
172
182
|
|
|
173
183
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
174
184
|
|
|
@@ -179,7 +189,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
179
189
|
protected logger: Logger;
|
|
180
190
|
|
|
181
191
|
constructor(
|
|
182
|
-
private clientType: T,
|
|
183
192
|
private config: P2PConfig,
|
|
184
193
|
protected node: PubSubLibp2p,
|
|
185
194
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
@@ -221,10 +230,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
221
230
|
this.protocolVersion,
|
|
222
231
|
);
|
|
223
232
|
|
|
224
|
-
|
|
225
|
-
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
233
|
+
const proposalValidatorOpts = {
|
|
226
234
|
txsPermitted: !config.disableTransactions,
|
|
227
|
-
|
|
235
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
236
|
+
};
|
|
237
|
+
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
238
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
228
239
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
229
240
|
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
230
241
|
: new CheckpointAttestationValidator(epochCache);
|
|
@@ -232,19 +243,22 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
232
243
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
233
244
|
|
|
234
245
|
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
235
|
-
this.logger.
|
|
236
|
-
`Handler not yet registered
|
|
246
|
+
this.logger.warn(
|
|
247
|
+
`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
|
|
237
248
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
238
249
|
);
|
|
239
|
-
return
|
|
250
|
+
return true;
|
|
240
251
|
};
|
|
241
252
|
|
|
242
|
-
this.
|
|
243
|
-
|
|
253
|
+
this.allNodesCheckpointReceivedCallback = (
|
|
254
|
+
_checkpoint: CheckpointProposalCore,
|
|
255
|
+
): Promise<CheckpointAttestation[] | undefined> => {
|
|
256
|
+
throw new CheckpointProposalReceivedCallbackNotRegisteredError();
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
this.validatorCheckpointReceivedCallback = (
|
|
260
|
+
_checkpoint: CheckpointProposalCore,
|
|
244
261
|
): Promise<CheckpointAttestation[] | undefined> => {
|
|
245
|
-
this.logger.debug(
|
|
246
|
-
`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
|
|
247
|
-
);
|
|
248
262
|
return Promise.resolve(undefined);
|
|
249
263
|
};
|
|
250
264
|
}
|
|
@@ -259,8 +273,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
259
273
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
260
274
|
* @returns The new service.
|
|
261
275
|
*/
|
|
262
|
-
public static async new
|
|
263
|
-
clientType: T,
|
|
276
|
+
public static async new(
|
|
264
277
|
config: P2PConfig,
|
|
265
278
|
peerId: PeerId,
|
|
266
279
|
deps: {
|
|
@@ -338,6 +351,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
338
351
|
heartbeatIntervalMs: config.gossipsubInterval,
|
|
339
352
|
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
340
353
|
blockDurationMs: config.blockDurationMs,
|
|
354
|
+
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
|
|
341
355
|
});
|
|
342
356
|
|
|
343
357
|
const node = await createLibp2p({
|
|
@@ -471,7 +485,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
471
485
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
472
486
|
|
|
473
487
|
return new LibP2PService(
|
|
474
|
-
clientType,
|
|
475
488
|
config,
|
|
476
489
|
node,
|
|
477
490
|
peerDiscoveryService,
|
|
@@ -545,7 +558,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
545
558
|
await this.node.start();
|
|
546
559
|
|
|
547
560
|
// Subscribe to standard GossipSub topics by default
|
|
548
|
-
for (const topic of
|
|
561
|
+
for (const topic of getTopicsForConfig(this.config.disableTransactions)) {
|
|
549
562
|
this.subscribeToTopic(this.topicStrings[topic]);
|
|
550
563
|
}
|
|
551
564
|
|
|
@@ -611,6 +624,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
611
624
|
return this.peerManager.getPeers(includePending);
|
|
612
625
|
}
|
|
613
626
|
|
|
627
|
+
public getGossipMeshPeerCount(topicType: TopicType): number {
|
|
628
|
+
return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
|
|
629
|
+
}
|
|
630
|
+
|
|
614
631
|
private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
|
|
615
632
|
this.logger.trace(`Received PUBSUB message.`);
|
|
616
633
|
|
|
@@ -659,8 +676,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
659
676
|
this.blockReceivedCallback = callback;
|
|
660
677
|
}
|
|
661
678
|
|
|
662
|
-
public
|
|
663
|
-
this.
|
|
679
|
+
public registerValidatorCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
680
|
+
this.validatorCheckpointReceivedCallback = callback;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
public registerAllNodesCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
684
|
+
this.allNodesCheckpointReceivedCallback = callback;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
public async notifyOwnCheckpointProposal(checkpoint: CheckpointProposalCore): Promise<void> {
|
|
688
|
+
await this.allNodesCheckpointReceivedCallback(checkpoint, this.node.peerId);
|
|
664
689
|
}
|
|
665
690
|
|
|
666
691
|
/**
|
|
@@ -673,6 +698,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
673
698
|
this.duplicateProposalCallback = callback;
|
|
674
699
|
}
|
|
675
700
|
|
|
701
|
+
/**
|
|
702
|
+
* Registers a callback to be invoked when a duplicate attestation is detected.
|
|
703
|
+
* A validator signing attestations for different proposals at the same slot.
|
|
704
|
+
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
705
|
+
*/
|
|
706
|
+
public registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void {
|
|
707
|
+
this.duplicateAttestationCallback = callback;
|
|
708
|
+
}
|
|
709
|
+
|
|
676
710
|
/**
|
|
677
711
|
* Subscribes to a topic.
|
|
678
712
|
* @param topic - The topic to subscribe to.
|
|
@@ -737,6 +771,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
737
771
|
if (!validator || !validator.addMessage(msgId)) {
|
|
738
772
|
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
739
773
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
774
|
+
if (topicType === TopicType.tx) {
|
|
775
|
+
this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
|
|
776
|
+
}
|
|
740
777
|
return { result: false, topicType };
|
|
741
778
|
}
|
|
742
779
|
|
|
@@ -801,9 +838,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
801
838
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
802
839
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
803
840
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
804
|
-
|
|
805
|
-
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
806
|
-
}
|
|
841
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
807
842
|
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
808
843
|
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
809
844
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
@@ -865,45 +900,128 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
865
900
|
source: PeerId,
|
|
866
901
|
topicType: TopicType,
|
|
867
902
|
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
868
|
-
|
|
903
|
+
// Default to reject result with a penalty if validation function throws an error
|
|
904
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = {
|
|
905
|
+
result: TopicValidatorResult.Reject,
|
|
906
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
907
|
+
};
|
|
869
908
|
const timer = new Timer();
|
|
870
909
|
try {
|
|
871
910
|
resultAndObj = await validationFunc();
|
|
872
911
|
} catch (err) {
|
|
873
|
-
this.
|
|
874
|
-
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
875
|
-
msgId,
|
|
876
|
-
source: source.toString(),
|
|
877
|
-
topicType,
|
|
878
|
-
});
|
|
912
|
+
this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
|
|
879
913
|
}
|
|
880
914
|
|
|
881
915
|
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
916
|
+
this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
|
|
882
917
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
918
|
+
} else if (resultAndObj.result === TopicValidatorResult.Reject) {
|
|
919
|
+
this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
|
|
920
|
+
msgId,
|
|
921
|
+
source: source.toString(),
|
|
922
|
+
topicType,
|
|
923
|
+
severity: resultAndObj.severity,
|
|
924
|
+
});
|
|
925
|
+
this.peerManager.penalizePeer(source, resultAndObj.severity);
|
|
926
|
+
} else {
|
|
927
|
+
this.logger.trace(`Message ${topicType} ignored by validator`, { msgId, source: source.toString(), topicType });
|
|
883
928
|
}
|
|
884
929
|
|
|
885
930
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
|
|
886
931
|
return resultAndObj;
|
|
887
932
|
}
|
|
888
933
|
|
|
934
|
+
private tryDeserialize<T>(deserializeFunc: () => T, msgId: string, source: PeerId): T | undefined {
|
|
935
|
+
try {
|
|
936
|
+
return deserializeFunc();
|
|
937
|
+
} catch (err) {
|
|
938
|
+
this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
|
|
939
|
+
err,
|
|
940
|
+
msgId,
|
|
941
|
+
source: source.toString(),
|
|
942
|
+
});
|
|
943
|
+
return undefined;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
889
947
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
890
948
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
891
|
-
const tx = Tx.fromBuffer(payloadData);
|
|
892
|
-
|
|
893
|
-
|
|
949
|
+
const tx = this.tryDeserialize(() => Tx.fromBuffer(payloadData), msgId, source);
|
|
950
|
+
if (!tx) {
|
|
951
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.LowToleranceError };
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
955
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
956
|
+
|
|
957
|
+
// Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
|
|
958
|
+
const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
959
|
+
const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
|
|
960
|
+
if (!firstStageOutcome.allPassed) {
|
|
961
|
+
const { name } = firstStageOutcome.failure;
|
|
962
|
+
let { severity } = firstStageOutcome.failure;
|
|
963
|
+
|
|
964
|
+
// Double spend validator has a special case handler. We perform more detailed examination
|
|
965
|
+
// as to how recently the nullifier was entered into the tree and if the transaction should
|
|
966
|
+
// have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
|
|
967
|
+
if (name === 'doubleSpendValidator') {
|
|
968
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1);
|
|
969
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
|
|
973
|
+
validator: name,
|
|
974
|
+
severity,
|
|
975
|
+
source: source.toString(),
|
|
976
|
+
});
|
|
977
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
981
|
+
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
982
|
+
if (canAdd === 'ignored') {
|
|
983
|
+
this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
|
|
984
|
+
source: source.toString(),
|
|
985
|
+
});
|
|
986
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// Stage 2: expensive proof verification
|
|
990
|
+
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
991
|
+
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
992
|
+
if (!secondStageOutcome.allPassed) {
|
|
993
|
+
const { severity, name } = secondStageOutcome.failure;
|
|
994
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
|
|
995
|
+
validator: name,
|
|
996
|
+
severity,
|
|
997
|
+
source: source.toString(),
|
|
998
|
+
});
|
|
999
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
1000
|
+
}
|
|
894
1001
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1002
|
+
// Pool add: persist the tx
|
|
1003
|
+
const txHash = tx.getTxHash();
|
|
1004
|
+
const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
|
|
1005
|
+
|
|
1006
|
+
const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
|
|
1007
|
+
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
1008
|
+
|
|
1009
|
+
this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
|
|
1010
|
+
wasAccepted,
|
|
1011
|
+
wasIgnored,
|
|
898
1012
|
[Attributes.P2P_ID]: source.toString(),
|
|
899
1013
|
});
|
|
900
1014
|
|
|
901
|
-
if (
|
|
902
|
-
return { result: TopicValidatorResult.
|
|
903
|
-
} else if (
|
|
1015
|
+
if (wasAccepted) {
|
|
1016
|
+
return { result: TopicValidatorResult.Accept, obj: tx };
|
|
1017
|
+
} else if (wasIgnored) {
|
|
904
1018
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
905
1019
|
} else {
|
|
906
|
-
|
|
1020
|
+
this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
|
|
1021
|
+
source: source.toString(),
|
|
1022
|
+
txHash: txHash.toString(),
|
|
1023
|
+
});
|
|
1024
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
907
1025
|
}
|
|
908
1026
|
};
|
|
909
1027
|
|
|
@@ -912,6 +1030,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
912
1030
|
return;
|
|
913
1031
|
}
|
|
914
1032
|
|
|
1033
|
+
// Tx was accepted into pool and will be propagated - just log and record metrics
|
|
915
1034
|
const txHash = tx.getTxHash();
|
|
916
1035
|
const txHashString = txHash.toString();
|
|
917
1036
|
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
@@ -919,13 +1038,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
919
1038
|
txHash: txHashString,
|
|
920
1039
|
});
|
|
921
1040
|
|
|
922
|
-
if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
|
|
923
|
-
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
924
|
-
return;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
1041
|
this.instrumentation.incrementTxReceived(1);
|
|
928
|
-
await this.mempools.txPool.addTxs([tx]);
|
|
929
1042
|
}
|
|
930
1043
|
|
|
931
1044
|
/**
|
|
@@ -938,7 +1051,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
938
1051
|
source: PeerId,
|
|
939
1052
|
): Promise<void> {
|
|
940
1053
|
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
941
|
-
() =>
|
|
1054
|
+
() => {
|
|
1055
|
+
const attestation = this.tryDeserialize(() => CheckpointAttestation.fromBuffer(payloadData), msgId, source);
|
|
1056
|
+
if (!attestation) {
|
|
1057
|
+
return Promise.resolve({
|
|
1058
|
+
result: TopicValidatorResult.Reject,
|
|
1059
|
+
severity: PeerErrorSeverity.LowToleranceError,
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
return this.validateAndStoreCheckpointAttestation(source, attestation);
|
|
1063
|
+
},
|
|
942
1064
|
msgId,
|
|
943
1065
|
source,
|
|
944
1066
|
TopicType.checkpoint_attestation,
|
|
@@ -971,48 +1093,60 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
971
1093
|
|
|
972
1094
|
if (validationResult.result === 'reject') {
|
|
973
1095
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
974
|
-
|
|
975
|
-
return { result: TopicValidatorResult.Reject };
|
|
1096
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
976
1097
|
}
|
|
977
1098
|
|
|
978
1099
|
if (validationResult.result === 'ignore') {
|
|
979
1100
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
980
1101
|
}
|
|
981
1102
|
|
|
982
|
-
// Get committee size for the attestation's slot
|
|
983
|
-
const slot = attestation.payload.header.slotNumber;
|
|
984
|
-
const { committee } = await this.epochCache.getCommittee(slot);
|
|
985
|
-
const committeeSize = committee?.length ?? 0;
|
|
986
|
-
|
|
987
1103
|
// Try to add the attestation: this handles existence check, cap check, and adding in one call
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1104
|
+
// count is the number of attestations by this signer for this slot (for duplicate detection)
|
|
1105
|
+
const slot = attestation.payload.header.slotNumber;
|
|
1106
|
+
const { added, alreadyExists, count } =
|
|
1107
|
+
await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
|
|
992
1108
|
|
|
993
1109
|
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
994
1110
|
added,
|
|
995
1111
|
alreadyExists,
|
|
1112
|
+
count,
|
|
996
1113
|
[Attributes.SLOT_NUMBER]: slot.toString(),
|
|
997
1114
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
998
1115
|
});
|
|
999
1116
|
|
|
1000
|
-
//
|
|
1117
|
+
// Exact same attestation received, no need to re-broadcast
|
|
1001
1118
|
if (alreadyExists) {
|
|
1002
1119
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1003
1120
|
}
|
|
1004
1121
|
|
|
1005
|
-
// Could not add (cap reached),
|
|
1122
|
+
// Could not add (cap reached for signer), penalize and do not re-broadcast
|
|
1006
1123
|
if (!added) {
|
|
1007
|
-
this.logger.warn(`
|
|
1124
|
+
this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
|
|
1008
1125
|
slot: slot.toString(),
|
|
1009
1126
|
archive: attestation.archive.toString(),
|
|
1010
1127
|
source: peerId.toString(),
|
|
1128
|
+
attester: attestation.getSender()?.toString(),
|
|
1129
|
+
count,
|
|
1011
1130
|
});
|
|
1012
|
-
return { result: TopicValidatorResult.
|
|
1131
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
|
|
1135
|
+
// count is the number of attestations by this signer for this slot
|
|
1136
|
+
if (count === 2) {
|
|
1137
|
+
const attester = attestation.getSender();
|
|
1138
|
+
if (attester) {
|
|
1139
|
+
this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
|
|
1140
|
+
slot: slot.toString(),
|
|
1141
|
+
archive: attestation.archive.toString(),
|
|
1142
|
+
source: peerId.toString(),
|
|
1143
|
+
attester: attester.toString(),
|
|
1144
|
+
});
|
|
1145
|
+
this.duplicateAttestationCallback?.({ slot, attester });
|
|
1146
|
+
}
|
|
1013
1147
|
}
|
|
1014
1148
|
|
|
1015
|
-
// Attestation was added successfully
|
|
1149
|
+
// Attestation was added successfully - accept it so other nodes can also detect the equivocation
|
|
1016
1150
|
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
1017
1151
|
}
|
|
1018
1152
|
|
|
@@ -1049,8 +1183,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1049
1183
|
|
|
1050
1184
|
if (validationResult.result === 'reject') {
|
|
1051
1185
|
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1052
|
-
|
|
1053
|
-
return { result: TopicValidatorResult.Reject };
|
|
1186
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1054
1187
|
}
|
|
1055
1188
|
|
|
1056
1189
|
if (validationResult.result === 'ignore') {
|
|
@@ -1058,8 +1191,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1058
1191
|
}
|
|
1059
1192
|
|
|
1060
1193
|
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1061
|
-
const { added, alreadyExists,
|
|
1062
|
-
const isEquivocated =
|
|
1194
|
+
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1195
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1063
1196
|
|
|
1064
1197
|
// Duplicate proposal received, no need to re-broadcast
|
|
1065
1198
|
if (alreadyExists) {
|
|
@@ -1074,15 +1207,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1074
1207
|
|
|
1075
1208
|
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1076
1209
|
if (!added) {
|
|
1077
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1078
1210
|
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1079
1211
|
...block.toBlockInfo(),
|
|
1080
1212
|
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1081
|
-
|
|
1213
|
+
count,
|
|
1082
1214
|
proposer: block.getSender()?.toString(),
|
|
1083
1215
|
source: peerId.toString(),
|
|
1084
1216
|
});
|
|
1085
|
-
return {
|
|
1217
|
+
return {
|
|
1218
|
+
result: TopicValidatorResult.Reject,
|
|
1219
|
+
metadata: { isEquivocated },
|
|
1220
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1221
|
+
};
|
|
1086
1222
|
}
|
|
1087
1223
|
|
|
1088
1224
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1095,7 +1231,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1095
1231
|
proposer: proposer?.toString(),
|
|
1096
1232
|
});
|
|
1097
1233
|
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1098
|
-
if (proposer &&
|
|
1234
|
+
if (proposer && count === 2) {
|
|
1099
1235
|
this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
|
|
1100
1236
|
}
|
|
1101
1237
|
return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
|
|
@@ -1120,14 +1256,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1120
1256
|
...block.toBlockInfo(),
|
|
1121
1257
|
});
|
|
1122
1258
|
|
|
1123
|
-
// Mark the txs in this proposal as
|
|
1124
|
-
await this.mempools.txPool.
|
|
1259
|
+
// Mark the txs in this proposal as protected
|
|
1260
|
+
await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
|
|
1125
1261
|
|
|
1126
1262
|
// Call the block received callback to validate the proposal.
|
|
1127
1263
|
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1128
1264
|
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1129
1265
|
if (!isValid) {
|
|
1130
|
-
this.logger.
|
|
1266
|
+
this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1131
1267
|
}
|
|
1132
1268
|
}
|
|
1133
1269
|
|
|
@@ -1175,8 +1311,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1175
1311
|
|
|
1176
1312
|
if (validationResult.result === 'reject') {
|
|
1177
1313
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1178
|
-
|
|
1179
|
-
return { result: TopicValidatorResult.Reject };
|
|
1314
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1180
1315
|
}
|
|
1181
1316
|
|
|
1182
1317
|
if (validationResult.result === 'ignore') {
|
|
@@ -1191,20 +1326,21 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1191
1326
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1192
1327
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1193
1328
|
});
|
|
1194
|
-
const
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
metadata: { isEquivocated } = {},
|
|
1198
|
-
} = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1199
|
-
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1329
|
+
const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1330
|
+
const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
|
|
1331
|
+
if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1200
1332
|
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1201
1333
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1202
1334
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1203
1335
|
isEquivocated,
|
|
1204
|
-
result,
|
|
1336
|
+
result: blockProposalResult.result,
|
|
1205
1337
|
});
|
|
1206
|
-
return {
|
|
1207
|
-
|
|
1338
|
+
return {
|
|
1339
|
+
result: TopicValidatorResult.Reject,
|
|
1340
|
+
severity:
|
|
1341
|
+
'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError,
|
|
1342
|
+
};
|
|
1343
|
+
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1208
1344
|
processBlock = true;
|
|
1209
1345
|
}
|
|
1210
1346
|
}
|
|
@@ -1212,8 +1348,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1212
1348
|
// Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
|
|
1213
1349
|
const checkpointCore = checkpoint.toCore();
|
|
1214
1350
|
const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
|
|
1215
|
-
const { added, alreadyExists,
|
|
1216
|
-
const isEquivocated =
|
|
1351
|
+
const { added, alreadyExists, count } = tryAddResult;
|
|
1352
|
+
const isEquivocated = count !== undefined && count > 1;
|
|
1217
1353
|
|
|
1218
1354
|
// Duplicate proposal received, do not re-broadcast
|
|
1219
1355
|
if (alreadyExists) {
|
|
@@ -1231,13 +1367,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1231
1367
|
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1232
1368
|
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1233
1369
|
if (!added) {
|
|
1234
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1235
1370
|
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1236
1371
|
...checkpoint.toCheckpointInfo(),
|
|
1237
|
-
|
|
1372
|
+
count,
|
|
1238
1373
|
source: peerId.toString(),
|
|
1239
1374
|
});
|
|
1240
|
-
return {
|
|
1375
|
+
return {
|
|
1376
|
+
result: TopicValidatorResult.Reject,
|
|
1377
|
+
obj: checkpoint,
|
|
1378
|
+
metadata: { isEquivocated, processBlock },
|
|
1379
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1380
|
+
};
|
|
1241
1381
|
}
|
|
1242
1382
|
|
|
1243
1383
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1250,7 +1390,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1250
1390
|
proposer: proposer?.toString(),
|
|
1251
1391
|
});
|
|
1252
1392
|
// Invoke the duplicate callback on the first duplicate spotted only
|
|
1253
|
-
if (proposer &&
|
|
1393
|
+
if (proposer && count === 2) {
|
|
1254
1394
|
this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
|
|
1255
1395
|
}
|
|
1256
1396
|
return {
|
|
@@ -1282,9 +1422,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1282
1422
|
source: sender.toString(),
|
|
1283
1423
|
});
|
|
1284
1424
|
|
|
1425
|
+
await this.allNodesCheckpointReceivedCallback(checkpoint, sender);
|
|
1426
|
+
|
|
1285
1427
|
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1286
1428
|
// to validate and potentially generate attestations
|
|
1287
|
-
const attestations = await this.
|
|
1429
|
+
const attestations = await this.validatorCheckpointReceivedCallback(checkpoint, sender);
|
|
1288
1430
|
if (attestations && attestations.length > 0) {
|
|
1289
1431
|
// If the callback returned attestations, add them to the pool and propagate them
|
|
1290
1432
|
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
@@ -1499,43 +1641,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1499
1641
|
}
|
|
1500
1642
|
|
|
1501
1643
|
protected createRequestedTxValidator(): TxValidator {
|
|
1502
|
-
return
|
|
1644
|
+
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1503
1645
|
l1ChainId: this.config.l1ChainId,
|
|
1504
1646
|
rollupVersion: this.config.rollupVersion,
|
|
1505
1647
|
});
|
|
1506
1648
|
}
|
|
1507
1649
|
|
|
1508
|
-
@trackSpan('Libp2pService.validatePropagatedTx', tx => ({
|
|
1509
|
-
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
1510
|
-
}))
|
|
1511
|
-
private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
|
|
1512
|
-
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1513
|
-
|
|
1514
|
-
// We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
|
|
1515
|
-
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1516
|
-
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1517
|
-
|
|
1518
|
-
for (const validator of messageValidators) {
|
|
1519
|
-
const outcome = await this.runValidations(tx, validator);
|
|
1520
|
-
|
|
1521
|
-
if (outcome.allPassed) {
|
|
1522
|
-
continue;
|
|
1523
|
-
}
|
|
1524
|
-
const { name } = outcome.failure;
|
|
1525
|
-
let { severity } = outcome.failure;
|
|
1526
|
-
|
|
1527
|
-
// Double spend validator has a special case handler
|
|
1528
|
-
if (name === 'doubleSpendValidator') {
|
|
1529
|
-
const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
|
|
1530
|
-
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1534
|
-
return false;
|
|
1535
|
-
}
|
|
1536
|
-
return true;
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
1650
|
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
1540
1651
|
if (blockNumber === this.feesCache?.blockNumber) {
|
|
1541
1652
|
return this.feesCache.gasFees;
|
|
@@ -1563,60 +1674,62 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1563
1674
|
};
|
|
1564
1675
|
}
|
|
1565
1676
|
|
|
1566
|
-
public async
|
|
1567
|
-
const
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1677
|
+
public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
|
|
1678
|
+
const validator = createTxValidatorForBlockProposalReceivedTxs(
|
|
1679
|
+
this.proofVerifier,
|
|
1680
|
+
{ l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
|
|
1681
|
+
this.logger.getBindings(),
|
|
1682
|
+
);
|
|
1572
1683
|
|
|
1573
|
-
await Promise.all(
|
|
1684
|
+
const results = await Promise.all(
|
|
1574
1685
|
txs.map(async tx => {
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
if (!outcome.allPassed) {
|
|
1578
|
-
throw new Error('Invalid tx detected', { cause: { outcome } });
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1686
|
+
const result = await validator.validateTx(tx);
|
|
1687
|
+
return result.result !== 'invalid';
|
|
1581
1688
|
}),
|
|
1582
1689
|
);
|
|
1690
|
+
if (results.some(value => value === false)) {
|
|
1691
|
+
throw new Error('Invalid tx detected');
|
|
1692
|
+
}
|
|
1583
1693
|
}
|
|
1584
1694
|
|
|
1585
|
-
/**
|
|
1586
|
-
|
|
1587
|
-
*
|
|
1588
|
-
* Each validator is a pair of a validator and a severity.
|
|
1589
|
-
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
1590
|
-
*
|
|
1591
|
-
* @param currentBlockNumber - The current synced block number.
|
|
1592
|
-
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
1593
|
-
* @returns The message validators.
|
|
1594
|
-
*/
|
|
1595
|
-
private async createMessageValidators(
|
|
1695
|
+
/** Creates the first stage (fast) validators for gossiped transactions. */
|
|
1696
|
+
protected async createFirstStageMessageValidators(
|
|
1596
1697
|
currentBlockNumber: BlockNumber,
|
|
1597
1698
|
nextSlotTimestamp: UInt64,
|
|
1598
|
-
): Promise<Record<string,
|
|
1699
|
+
): Promise<Record<string, TransactionValidator>> {
|
|
1599
1700
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
1600
|
-
const allowedInSetup =
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1701
|
+
const allowedInSetup = [
|
|
1702
|
+
...(await getDefaultAllowedSetupFunctions()),
|
|
1703
|
+
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
1704
|
+
];
|
|
1705
|
+
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1706
|
+
const l1Constants = await this.archiver.getL1Constants();
|
|
1707
|
+
|
|
1708
|
+
return createFirstStageTxValidationsForGossipedTransactions(
|
|
1605
1709
|
nextSlotTimestamp,
|
|
1606
|
-
|
|
1710
|
+
blockNumber,
|
|
1607
1711
|
this.worldStateSynchronizer,
|
|
1608
1712
|
gasFees,
|
|
1609
1713
|
this.config.l1ChainId,
|
|
1610
1714
|
this.config.rollupVersion,
|
|
1611
1715
|
protocolContractsHash,
|
|
1612
1716
|
this.archiver,
|
|
1613
|
-
this.proofVerifier,
|
|
1614
1717
|
!this.config.disableTransactions,
|
|
1615
1718
|
allowedInSetup,
|
|
1616
1719
|
this.logger.getBindings(),
|
|
1720
|
+
{
|
|
1721
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
1722
|
+
maxBlockL2Gas: this.config.validateMaxL2BlockGas,
|
|
1723
|
+
maxBlockDAGas: this.config.validateMaxDABlockGas,
|
|
1724
|
+
},
|
|
1617
1725
|
);
|
|
1618
1726
|
}
|
|
1619
1727
|
|
|
1728
|
+
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
|
|
1729
|
+
protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
|
|
1730
|
+
return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1620
1733
|
/**
|
|
1621
1734
|
* Run validations on a tx.
|
|
1622
1735
|
* @param tx - The tx to validate.
|
|
@@ -1625,7 +1738,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1625
1738
|
*/
|
|
1626
1739
|
private async runValidations(
|
|
1627
1740
|
tx: Tx,
|
|
1628
|
-
messageValidators: Record<string,
|
|
1741
|
+
messageValidators: Record<string, TransactionValidator>,
|
|
1629
1742
|
): Promise<ValidationOutcome> {
|
|
1630
1743
|
const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
|
|
1631
1744
|
const { result } = await validator.validateTx(tx);
|
|
@@ -1634,8 +1747,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1634
1747
|
|
|
1635
1748
|
// A promise that resolves when all validations have been run
|
|
1636
1749
|
const allValidations = await Promise.all(validationPromises);
|
|
1637
|
-
const
|
|
1638
|
-
if (
|
|
1750
|
+
const failures = allValidations.filter(x => !x.isValid);
|
|
1751
|
+
if (failures.length > 0) {
|
|
1752
|
+
// Pick the most severe failure (lowest tolerance = harshest penalty)
|
|
1753
|
+
const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
|
|
1639
1754
|
return {
|
|
1640
1755
|
allPassed: false,
|
|
1641
1756
|
failure: {
|
|
@@ -1688,31 +1803,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1688
1803
|
return PeerErrorSeverity.HighToleranceError;
|
|
1689
1804
|
}
|
|
1690
1805
|
|
|
1691
|
-
/**
|
|
1692
|
-
* Validate a checkpoint attestation.
|
|
1693
|
-
*
|
|
1694
|
-
* @param attestation - The checkpoint attestation to validate.
|
|
1695
|
-
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1696
|
-
*/
|
|
1697
|
-
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1698
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1699
|
-
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1700
|
-
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1701
|
-
}))
|
|
1702
|
-
public async validateCheckpointAttestation(
|
|
1703
|
-
peerId: PeerId,
|
|
1704
|
-
attestation: CheckpointAttestation,
|
|
1705
|
-
): Promise<P2PValidationResult> {
|
|
1706
|
-
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1707
|
-
|
|
1708
|
-
if (result.result === 'reject') {
|
|
1709
|
-
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1710
|
-
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1713
|
-
return result;
|
|
1714
|
-
}
|
|
1715
|
-
|
|
1716
1806
|
public getPeerScore(peerId: PeerId): number {
|
|
1717
1807
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
1718
1808
|
}
|