@aztec/p2p 0.0.1-commit.42ee6df9b → 0.0.1-commit.431c48d
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 +32 -23
- package/dest/client/interface.d.ts +44 -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 +119 -59
- package/dest/config.d.ts +150 -107
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +77 -26
- 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 +270 -198
- 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 +10 -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 +29 -20
- 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.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 +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
- 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 +3 -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 +64 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +3 -4
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +6 -7
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +1 -1
- 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 +6 -5
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +11 -1
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +24 -0
- 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 +16 -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 +83 -32
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +50 -6
- 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 +243 -127
- 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 -23
- 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 +18 -18
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +19 -18
- 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 +6 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +21 -0
- package/dest/services/libp2p/libp2p_service.d.ts +40 -43
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +370 -276
- package/dest/services/peer-manager/peer_manager.d.ts +26 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +103 -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 +41 -19
- 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 +33 -9
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +57 -44
- 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 +11 -6
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +35 -14
- package/dest/versioning.d.ts +3 -6
- package/dest/versioning.d.ts.map +1 -1
- package/dest/versioning.js +3 -24
- package/package.json +17 -17
- package/src/bootstrap/bootstrap.ts +17 -3
- package/src/client/factory.ts +48 -24
- package/src/client/interface.ts +39 -17
- package/src/client/p2p_client.ts +135 -92
- package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
- package/src/config.ts +159 -34
- package/src/errors/reqresp.error.ts +13 -19
- package/src/mem_pools/attestation_pool/attestation_pool.ts +325 -242
- 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 +30 -20
- 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 +2 -4
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -2
- 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 +67 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +1 -3
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -7
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +5 -6
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +27 -0
- 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 +94 -31
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +270 -133
- 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 -14
- package/src/services/discv5/persisted_enr_store.ts +158 -0
- package/src/services/dummy_service.ts +25 -44
- 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 +22 -0
- package/src/services/libp2p/libp2p_service.ts +433 -302
- package/src/services/peer-manager/peer_manager.ts +112 -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 +48 -37
- 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 +61 -60
- 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 +32 -17
- 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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
+
import { compactArray } from '@aztec/foundation/collection';
|
|
2
3
|
import { makeEthSignDigest, tryRecoverAddress } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
3
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
5
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -35,6 +36,8 @@ const MAX_CACHED_PEER_AGE_MS = 5 * 60 * 1000; // 5 minutes
|
|
|
35
36
|
const DEFAULT_FAILED_PEER_BAN_TIME_MS = 5 * 60 * 1000; // 5 minutes timeout after failing MAX_DIAL_ATTEMPTS
|
|
36
37
|
const GOODBYE_DIAL_TIMEOUT_MS = 1000;
|
|
37
38
|
const FAILED_AUTH_HANDSHAKE_EXPIRY_MS = 60 * 60 * 1000; // 1 hour
|
|
39
|
+
const ZERO_PEER_WARNING_THRESHOLD_HEARTBEATS = 3; // tolerate transient dips, such as at startup
|
|
40
|
+
const ZERO_PEER_WARNING_REPEAT_INTERVAL_MS = 60 * 1000;
|
|
38
41
|
|
|
39
42
|
type CachedPeer = {
|
|
40
43
|
peerId: PeerId;
|
|
@@ -70,6 +73,10 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
70
73
|
private failedAuthHandshakes: Map<string, FailedAuthHandshakeEntry> = new Map();
|
|
71
74
|
private validatorAddresses: EthAddress[] = [];
|
|
72
75
|
private initializedPreferredPeers: boolean = false;
|
|
76
|
+
private consecutiveZeroPeerHeartbeats: number = 0;
|
|
77
|
+
private zeroPeerWarningHeartbeats: number = 0;
|
|
78
|
+
private zeroPeerWarningIssued: boolean = false;
|
|
79
|
+
private lastConnectedPeerAtMs: number | undefined;
|
|
73
80
|
|
|
74
81
|
private metrics: PeerManagerMetrics;
|
|
75
82
|
private handlers: {
|
|
@@ -114,6 +121,10 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
114
121
|
|
|
115
122
|
// Display peer counts every 60 seconds
|
|
116
123
|
this.displayPeerCountsPeerHeartbeat = Math.floor(60_000 / this.config.peerCheckIntervalMS);
|
|
124
|
+
this.zeroPeerWarningHeartbeats = Math.max(
|
|
125
|
+
1,
|
|
126
|
+
Math.floor(ZERO_PEER_WARNING_REPEAT_INTERVAL_MS / this.config.peerCheckIntervalMS),
|
|
127
|
+
);
|
|
117
128
|
}
|
|
118
129
|
/**
|
|
119
130
|
* Initializes the trusted peers.
|
|
@@ -164,6 +175,7 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
164
175
|
public async heartbeat() {
|
|
165
176
|
this.heartbeatCounter++;
|
|
166
177
|
this.peerScoring.decayAllScores();
|
|
178
|
+
this.peerScoring.pruneExpiredBans();
|
|
167
179
|
this.cleanupExpiredTimeouts();
|
|
168
180
|
|
|
169
181
|
await this.setupDirectPeersIfValidator();
|
|
@@ -171,6 +183,45 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
171
183
|
await this.processScheduledDisconnects();
|
|
172
184
|
|
|
173
185
|
this.discover();
|
|
186
|
+
this.checkPeerConnectivity();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Flags a node that has been left without any connected peers, since it can neither gossip nor propagate txs.
|
|
191
|
+
*
|
|
192
|
+
* Warnings only start after a few consecutive zero-peer heartbeats so that startup or a transient dip stays quiet,
|
|
193
|
+
* and then repeat roughly once a minute instead of on every heartbeat. Recovery is logged once.
|
|
194
|
+
*/
|
|
195
|
+
private checkPeerConnectivity() {
|
|
196
|
+
const connectedPeerCount = this.libP2PNode.getPeers().length;
|
|
197
|
+
const now = this.dateProvider.now();
|
|
198
|
+
|
|
199
|
+
if (connectedPeerCount > 0) {
|
|
200
|
+
if (this.zeroPeerWarningIssued) {
|
|
201
|
+
this.logger.info(`Peer connectivity restored with ${connectedPeerCount} connected peers`, {
|
|
202
|
+
connectedPeerCount,
|
|
203
|
+
zeroPeerHeartbeats: this.consecutiveZeroPeerHeartbeats,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
this.consecutiveZeroPeerHeartbeats = 0;
|
|
207
|
+
this.zeroPeerWarningIssued = false;
|
|
208
|
+
this.lastConnectedPeerAtMs = now;
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
this.consecutiveZeroPeerHeartbeats++;
|
|
213
|
+
const heartbeatsSinceThreshold = this.consecutiveZeroPeerHeartbeats - ZERO_PEER_WARNING_THRESHOLD_HEARTBEATS;
|
|
214
|
+
if (heartbeatsSinceThreshold < 0 || heartbeatsSinceThreshold % this.zeroPeerWarningHeartbeats !== 0) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
this.zeroPeerWarningIssued = true;
|
|
219
|
+
this.logger.warn('Node has no connected peers; gossip and tx propagation are unavailable', {
|
|
220
|
+
zeroPeerHeartbeats: this.consecutiveZeroPeerHeartbeats,
|
|
221
|
+
peerCheckIntervalMS: this.config.peerCheckIntervalMS,
|
|
222
|
+
msSinceLastConnectedPeer: this.lastConnectedPeerAtMs === undefined ? undefined : now - this.lastConnectedPeerAtMs,
|
|
223
|
+
cachedPeers: this.cachedPeers.size,
|
|
224
|
+
});
|
|
174
225
|
}
|
|
175
226
|
|
|
176
227
|
/*
|
|
@@ -198,21 +249,27 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
198
249
|
.then(peerIds => peerIds.forEach(peerId => this.preferredPeers.add(peerId.toString())))
|
|
199
250
|
.catch(e => this.logger.error('Error initializing preferred peers', e));
|
|
200
251
|
|
|
201
|
-
const directPeers = (
|
|
252
|
+
const directPeers = compactArray(
|
|
202
253
|
await Promise.all(
|
|
203
254
|
preferredPeersEnrs.map(async enr => {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
255
|
+
try {
|
|
256
|
+
const peerId = await enr.peerId();
|
|
257
|
+
const address = enr.getLocationMultiaddr('tcp');
|
|
258
|
+
if (address === undefined) {
|
|
259
|
+
throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
id: peerId,
|
|
263
|
+
addrs: [address],
|
|
264
|
+
};
|
|
265
|
+
} catch (err) {
|
|
266
|
+
// A malformed configured ENR shouldn't abort preferred-peer setup — skip it and log.
|
|
267
|
+
this.logger.warn(`Skipping preferred peer with invalid ENR`, { err });
|
|
268
|
+
return undefined;
|
|
208
269
|
}
|
|
209
|
-
return {
|
|
210
|
-
id: peerId,
|
|
211
|
-
addrs: [address],
|
|
212
|
-
};
|
|
213
270
|
}),
|
|
214
|
-
)
|
|
215
|
-
)
|
|
271
|
+
),
|
|
272
|
+
);
|
|
216
273
|
|
|
217
274
|
await Promise.all(
|
|
218
275
|
directPeers.map(peer => {
|
|
@@ -494,15 +551,38 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
494
551
|
*
|
|
495
552
|
* @returns: True if node is allowed to connect, otherwise false
|
|
496
553
|
* */
|
|
497
|
-
|
|
498
|
-
|
|
554
|
+
/**
|
|
555
|
+
* Whether a peer is allowed to connect, given its peer id. Rejects peers serving an active ban and
|
|
556
|
+
* peers that have exceeded the failed auth-handshake limit. Use this once the peer id is known —
|
|
557
|
+
* i.e. for the encrypted-inbound gater and when dialing.
|
|
558
|
+
*/
|
|
559
|
+
public isPeerAllowedToConnect(peerId: string | PeerId): boolean {
|
|
560
|
+
const id = peerId.toString();
|
|
561
|
+
if (this.peerScoring.getScoreState(id) === PeerScoreState.Banned) {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
return this.isWithinFailedAuthLimit(id);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Whether a connection from an address is allowed. Bans are keyed by peer id, which isn't known at
|
|
569
|
+
* the raw-inbound layer, so only the failed auth-handshake limit (also tracked per address) is
|
|
570
|
+
* enforced here; the ban is applied once the peer id is known via {@link isPeerAllowedToConnect}.
|
|
571
|
+
*/
|
|
572
|
+
public isAddressAllowedToConnect(address: string): boolean {
|
|
573
|
+
return this.isWithinFailedAuthLimit(address);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** Whether the failed auth-handshake count for a peer id or address is below the configured limit. */
|
|
577
|
+
private isWithinFailedAuthLimit(key: string): boolean {
|
|
578
|
+
const entry = this.failedAuthHandshakes.get(key);
|
|
499
579
|
if (!entry) {
|
|
500
580
|
return true;
|
|
501
581
|
}
|
|
502
582
|
|
|
503
583
|
// In case entry is too old, remove it and allow connection
|
|
504
584
|
if (this.dateProvider.now() - entry.lastFailureTimestamp > FAILED_AUTH_HANDSHAKE_EXPIRY_MS) {
|
|
505
|
-
this.failedAuthHandshakes.delete(
|
|
585
|
+
this.failedAuthHandshakes.delete(key);
|
|
506
586
|
return true;
|
|
507
587
|
}
|
|
508
588
|
|
|
@@ -527,6 +607,7 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
527
607
|
protectedConnections: protectedPeerCount,
|
|
528
608
|
maxPeerCount: this.config.maxPeerCount,
|
|
529
609
|
cachedPeers: this.cachedPeers.size,
|
|
610
|
+
discv5KadPeers: this.peerDiscoveryService.getKadValues().length,
|
|
530
611
|
...this.peerScoring.getStats(),
|
|
531
612
|
});
|
|
532
613
|
|
|
@@ -728,6 +809,12 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
728
809
|
return;
|
|
729
810
|
}
|
|
730
811
|
|
|
812
|
+
// Don't dial banned peers or those that have exceeded the auth failure threshold
|
|
813
|
+
if (!this.isPeerAllowedToConnect(peerId)) {
|
|
814
|
+
this.logger.trace(`Skipping peer ${peerId} due to ban or failed auth handshake attempts`);
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
|
|
731
818
|
const [multiaddrTcp] = await Promise.all([enr.getFullMultiaddr('tcp')]);
|
|
732
819
|
|
|
733
820
|
this.logger.trace(`Handling discovered peer ${peerId} at ${multiaddrTcp?.toString() ?? 'undefined address'}`);
|
|
@@ -985,14 +1072,14 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
985
1072
|
const peerIdStr = peerId.toString();
|
|
986
1073
|
|
|
987
1074
|
const existingEntry = this.failedAuthHandshakes.get(peerIdStr);
|
|
1075
|
+
const failureCount = (existingEntry?.count || 0) + 1;
|
|
988
1076
|
this.failedAuthHandshakes.set(peerIdStr, {
|
|
989
|
-
count:
|
|
1077
|
+
count: failureCount,
|
|
990
1078
|
lastFailureTimestamp: now,
|
|
991
1079
|
});
|
|
992
1080
|
|
|
993
1081
|
const connections = this.libP2PNode.getConnections(peerId);
|
|
994
1082
|
connections.forEach(conn => {
|
|
995
|
-
// We mark the IP address
|
|
996
1083
|
const address = conn.remoteAddr.nodeAddress().address;
|
|
997
1084
|
const existingAddressEntry = this.failedAuthHandshakes.get(address);
|
|
998
1085
|
this.failedAuthHandshakes.set(address, {
|
|
@@ -1000,6 +1087,15 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
1000
1087
|
lastFailureTimestamp: now,
|
|
1001
1088
|
});
|
|
1002
1089
|
});
|
|
1090
|
+
|
|
1091
|
+
// Ban the peer from being re-dialed for a cooldown period (exponential backoff)
|
|
1092
|
+
const banTimeMs = this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS;
|
|
1093
|
+
const backoffMs = banTimeMs * Math.pow(2, Math.min(failureCount - 1, 5));
|
|
1094
|
+
this.timedOutPeers.set(peerIdStr, {
|
|
1095
|
+
peerId: peerIdStr,
|
|
1096
|
+
timeoutUntilMs: now + backoffMs,
|
|
1097
|
+
});
|
|
1098
|
+
this.cachedPeers.delete(peerIdStr);
|
|
1003
1099
|
}
|
|
1004
1100
|
|
|
1005
1101
|
/*
|
|
@@ -57,6 +57,9 @@ const MIN_SCORE_BEFORE_BAN = -100;
|
|
|
57
57
|
const MIN_SCORE_BEFORE_DISCONNECT = -50;
|
|
58
58
|
const SCORE_CLEANUP_THRESHOLD = 0.1;
|
|
59
59
|
|
|
60
|
+
/** An active ban: the score the peer held when banned, and the timestamp at which the ban lifts. */
|
|
61
|
+
type BanRecord = { score: number; expiry: number };
|
|
62
|
+
|
|
60
63
|
export class PeerScoring {
|
|
61
64
|
private logger = createLogger('p2p:peer-scoring');
|
|
62
65
|
private scores: Map<string, number> = new Map();
|
|
@@ -67,11 +70,21 @@ export class PeerScoring {
|
|
|
67
70
|
|
|
68
71
|
private peerStateCounter: UpDownCounter;
|
|
69
72
|
|
|
73
|
+
/** Active bans, keyed by peer id. Held in memory only, so they are cleared on restart. */
|
|
74
|
+
private bannedPeers: Map<string, BanRecord> = new Map();
|
|
75
|
+
/**
|
|
76
|
+
* How long a peer remains banned once its score crosses MIN_SCORE_BEFORE_BAN. While banned, the
|
|
77
|
+
* peer's ban score is returned by getScore regardless of decay, so it cannot recover its way out
|
|
78
|
+
* of the ban early. After the ban expires the live (decayed) score takes over again.
|
|
79
|
+
*/
|
|
80
|
+
private readonly banDurationMs: number;
|
|
81
|
+
|
|
70
82
|
constructor(
|
|
71
83
|
config: P2PConfig,
|
|
72
84
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
73
85
|
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
74
86
|
) {
|
|
87
|
+
this.banDurationMs = config.peerBanDurationSeconds * 1000;
|
|
75
88
|
const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
|
|
76
89
|
this.peerPenalties = {
|
|
77
90
|
[PeerErrorSeverity.HighToleranceError]:
|
|
@@ -113,9 +126,31 @@ export class PeerScoring {
|
|
|
113
126
|
|
|
114
127
|
this.scores.set(peerId, currentScore);
|
|
115
128
|
this.lastUpdateTime.set(peerId, currentTime);
|
|
129
|
+
|
|
130
|
+
this.maybeBanPeer(peerId, currentScore);
|
|
131
|
+
|
|
116
132
|
return currentScore;
|
|
117
133
|
}
|
|
118
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Records a ban for a peer whose score has crossed the ban threshold, with an expiry banDurationMs
|
|
137
|
+
* in the future. No-op if the score is above the threshold or the peer is already serving an active
|
|
138
|
+
* ban (an existing ban is not extended; the original window stands). A previously expired ban does
|
|
139
|
+
* not block a fresh one — getActiveBanScore prunes it first.
|
|
140
|
+
*/
|
|
141
|
+
private maybeBanPeer(peerId: string, score: number): void {
|
|
142
|
+
if (score >= MIN_SCORE_BEFORE_BAN || this.getActiveBanScore(peerId) !== undefined) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const record: BanRecord = { score, expiry: this.dateProvider.now() + this.banDurationMs };
|
|
146
|
+
this.bannedPeers.set(peerId, record);
|
|
147
|
+
this.logger.verbose(`Banning peer ${peerId} until ${new Date(record.expiry).toISOString()}`, {
|
|
148
|
+
peerId,
|
|
149
|
+
score,
|
|
150
|
+
expiry: record.expiry,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
119
154
|
decayAllScores(): void {
|
|
120
155
|
const currentTime = this.dateProvider.now();
|
|
121
156
|
for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
|
|
@@ -135,17 +170,58 @@ export class PeerScoring {
|
|
|
135
170
|
}
|
|
136
171
|
}
|
|
137
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Removes bans whose window has elapsed. Expired bans are otherwise only pruned lazily when their
|
|
175
|
+
* peer's score is next queried, so a banned peer that disconnects and is never queried again would
|
|
176
|
+
* linger in the map. Called periodically (per heartbeat) to bound the ban map's size.
|
|
177
|
+
*/
|
|
178
|
+
pruneExpiredBans(): void {
|
|
179
|
+
const now = this.dateProvider.now();
|
|
180
|
+
const expired = [...this.bannedPeers.entries()].filter(([, ban]) => ban.expiry <= now).map(([peerId]) => peerId);
|
|
181
|
+
for (const peerId of expired) {
|
|
182
|
+
this.bannedPeers.delete(peerId);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Resets all peer scores. Useful for benchmarks to prevent cross-case contamination. */
|
|
187
|
+
resetAllScores(): void {
|
|
188
|
+
this.scores.clear();
|
|
189
|
+
this.lastUpdateTime.clear();
|
|
190
|
+
this.bannedPeers.clear();
|
|
191
|
+
}
|
|
192
|
+
|
|
138
193
|
removePeer(peerId: string): void {
|
|
139
194
|
this.scores.delete(peerId);
|
|
140
195
|
this.lastUpdateTime.delete(peerId);
|
|
141
196
|
}
|
|
142
197
|
|
|
198
|
+
/**
|
|
199
|
+
* The single source of truth for whether a peer is banned. Returns the ban score while the ban is
|
|
200
|
+
* active, or undefined if the peer is not banned. A ban that has expired is lazily lifted before
|
|
201
|
+
* returning undefined, so callers never see a stale ban.
|
|
202
|
+
*/
|
|
203
|
+
private getActiveBanScore(peerId: string): number | undefined {
|
|
204
|
+
const ban = this.bannedPeers.get(peerId);
|
|
205
|
+
if (ban === undefined) {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
if (ban.expiry > this.dateProvider.now()) {
|
|
209
|
+
return ban.score;
|
|
210
|
+
}
|
|
211
|
+
// Ban expired: lift it so the peer can recover.
|
|
212
|
+
this.bannedPeers.delete(peerId);
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
|
|
143
216
|
getScore(peerId: string): number {
|
|
144
|
-
|
|
217
|
+
// While a ban is active its ban score is returned regardless of how the live score has decayed,
|
|
218
|
+
// so the peer stays banned for the full duration.
|
|
219
|
+
return this.getActiveBanScore(peerId) ?? this.scores.get(peerId) ?? 0;
|
|
145
220
|
}
|
|
146
221
|
|
|
147
222
|
public getScoreState(peerId: string): PeerScoreState {
|
|
148
|
-
//
|
|
223
|
+
// A banned peer stays banned for the full ban duration regardless of score decay (see getScore /
|
|
224
|
+
// maybeBanPeer), rather than silently recovering once its decayed score is cleaned up.
|
|
149
225
|
const score = this.getScore(peerId);
|
|
150
226
|
if (score < MIN_SCORE_BEFORE_BAN) {
|
|
151
227
|
return PeerScoreState.Banned;
|
|
@@ -159,7 +235,9 @@ export class PeerScoring {
|
|
|
159
235
|
getStats(): { medianScore: number; healthyCount: number; disconnectCount: number; bannedCount: number } {
|
|
160
236
|
const stateCounts = { healthy: 0, disconnect: 0, banned: 0 };
|
|
161
237
|
|
|
162
|
-
|
|
238
|
+
// Include banned peers whose live score may have been decayed away but whose ban is still active.
|
|
239
|
+
const peerIds = new Set([...this.scores.keys(), ...this.bannedPeers.keys()]);
|
|
240
|
+
for (const peerId of peerIds) {
|
|
163
241
|
const state = this.getScoreState(peerId);
|
|
164
242
|
switch (state) {
|
|
165
243
|
case PeerScoreState.Healthy:
|
|
@@ -14,9 +14,8 @@ Applied before the protocol handler runs.
|
|
|
14
14
|
| STATUS | 5/s | 10/s | same |
|
|
15
15
|
| AUTH | 5/s | 10/s | same |
|
|
16
16
|
| GOODBYE | 5/s | 10/s | same |
|
|
17
|
-
| BLOCK | 2/s | 5/s | same |
|
|
18
17
|
| BLOCK_TXS | 10/s | 200/s | same |
|
|
19
|
-
| TX |
|
|
18
|
+
| TX | 10/s | 200/s | same |
|
|
20
19
|
|
|
21
20
|
- Per-peer limit exceeded: `HighToleranceError` penalty + `RATE_LIMIT_EXCEEDED` status. Penalty fires inside `RequestResponseRateLimiter.allow()`, not the stream handler.
|
|
22
21
|
- Global limit exceeded: `RATE_LIMIT_EXCEEDED` status only (no peer penalty).
|
|
@@ -46,7 +45,6 @@ Per-protocol size limits checked via preamble before decompression.
|
|
|
46
45
|
| Error Type | Severity |
|
|
47
46
|
|------------|----------|
|
|
48
47
|
| GOODBYE subprotocol errors | None |
|
|
49
|
-
| `CollectiveReqRespTimeoutError` / `InvalidResponseError` | None |
|
|
50
48
|
| `AbortError` / connection close / muxer closed | None |
|
|
51
49
|
| `ECONNRESET` / `EPIPE` / `ECONNREFUSED` / `ERR_UNEXPECTED_EOF` | HighToleranceError |
|
|
52
50
|
| `ERR_UNSUPPORTED_PROTOCOL` | HighToleranceError |
|
|
@@ -150,26 +148,6 @@ Protected peers (private/trusted/preferred) are always considered "authenticated
|
|
|
150
148
|
|
|
151
149
|
## Block Data Protocols
|
|
152
150
|
|
|
153
|
-
### BLOCK Protocol (`/aztec/req/block/1.0.0`)
|
|
154
|
-
|
|
155
|
-
**Server side**:
|
|
156
|
-
|
|
157
|
-
| Rule | Consequence | File |
|
|
158
|
-
|------|-------------|------|
|
|
159
|
-
| Request must parse as `Fr` | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block.ts` |
|
|
160
|
-
| Block lookup throws | `INTERNAL_ERROR` status | same |
|
|
161
|
-
| Block not found | SUCCESS + empty buffer (design choice; no `NOT_FOUND` status used) | same |
|
|
162
|
-
|
|
163
|
-
**Requester side** (Snappy limit: 3 MB):
|
|
164
|
-
|
|
165
|
-
| Rule | Consequence | File |
|
|
166
|
-
|------|-------------|------|
|
|
167
|
-
| Response block number must match requested | LowToleranceError; rejected | `libp2p_service.ts` (`validateRequestedBlock`) |
|
|
168
|
-
| Local block must exist for hash verification | Rejected (no penalty) | same |
|
|
169
|
-
| Response block hash must equal local block hash | MidToleranceError; rejected | same |
|
|
170
|
-
|
|
171
|
-
**Limitation**: the local-block requirement means BLOCK req/resp is unusable for initial P2P-only sync (before L1 sync provides local copies for verification). A TODO in the code acknowledges this.
|
|
172
|
-
|
|
173
151
|
### BLOCK_TXS Protocol (`/aztec/req/block_txs/1.0.0`)
|
|
174
152
|
|
|
175
153
|
**Server side**:
|
|
@@ -179,23 +157,10 @@ Protected peers (private/trusted/preferred) are always considered "authenticated
|
|
|
179
157
|
| Request must parse as `BlockTxsRequest` (Fr + TxHashArray + BitVector) | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block_txs/block_txs_handler.ts` |
|
|
180
158
|
| BitVector length: non-negative and <= `MAX_TXS_PER_BLOCK` (65536) | Deserialization throws -> `BADLY_FORMED_REQUEST` | `protocols/block_txs/bitvector.ts` |
|
|
181
159
|
| Archive root not found and no explicit txHashes | `NOT_FOUND` status | handler |
|
|
182
|
-
| Internal error during lookup | Unhandled exception -> stream abort (no `INTERNAL_ERROR` status
|
|
160
|
+
| Internal error during lookup | Unhandled exception -> stream abort (no `INTERNAL_ERROR` status) | handler |
|
|
183
161
|
|
|
184
162
|
Conditional registration: BLOCK_TXS handler only registered when `config.disableTransactions` is false. Otherwise peers get `ERR_UNSUPPORTED_PROTOCOL`.
|
|
185
163
|
|
|
186
|
-
**Requester side via `sendBatchRequest`** (Snappy limit: `max(N, 1) * 512 + 1` KB):
|
|
187
|
-
|
|
188
|
-
| Rule | Consequence | File |
|
|
189
|
-
|------|-------------|------|
|
|
190
|
-
| Archive root must match request | MidToleranceError | `libp2p_service.ts` (`validateRequestedBlockTxs`) |
|
|
191
|
-
| BitVector length must match request | MidToleranceError | same |
|
|
192
|
-
| No duplicate tx hashes | MidToleranceError | same |
|
|
193
|
-
| Tx count within bounds | MidToleranceError | same |
|
|
194
|
-
| Local block proposal must exist for archive root | Rejected (no penalty) | same |
|
|
195
|
-
| All tx hashes must be in proposal's tx list at allowed indices | LowToleranceError | same |
|
|
196
|
-
| Txs in strictly increasing index order | LowToleranceError | same |
|
|
197
|
-
| Each tx passes well-formedness (Metadata [4 fields], Size, Data, Proof) | LowToleranceError | same |
|
|
198
|
-
|
|
199
164
|
**Requester side via `BatchTxRequester`** (separate validation path):
|
|
200
165
|
|
|
201
166
|
| Rule | Consequence | File |
|
|
@@ -4,9 +4,10 @@ import { FifoMemoryQueue, type ISemaphore, Semaphore } from '@aztec/foundation/q
|
|
|
4
4
|
import { sleep } from '@aztec/foundation/sleep';
|
|
5
5
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
6
6
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
7
|
-
import { Tx, TxArray, TxHash } from '@aztec/stdlib/tx';
|
|
7
|
+
import { Tx, TxArray, TxHash, type TxValidator } from '@aztec/stdlib/tx';
|
|
8
8
|
|
|
9
9
|
import type { PeerId } from '@libp2p/interface';
|
|
10
|
+
import { strict as assert } from 'assert';
|
|
10
11
|
|
|
11
12
|
import type { IRequestTracker } from '../../tx_collection/request_tracker.js';
|
|
12
13
|
import { ReqRespSubProtocol } from '.././interface.js';
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
import type { BatchTxRequesterLibP2PService, BatchTxRequesterOptions, ITxMetadataCollection } from './interface.js';
|
|
22
23
|
import { MissingTxMetadataCollection } from './missing_txs.js';
|
|
23
24
|
import { type IPeerCollection, PeerCollection } from './peer_collection.js';
|
|
24
|
-
import {
|
|
25
|
+
import { createBatchRequestTxValidator } from './tx_validator.js';
|
|
25
26
|
|
|
26
27
|
/*
|
|
27
28
|
* Tries to fetch all missing transaction until deadline is hit.
|
|
@@ -51,7 +52,7 @@ export class BatchTxRequester {
|
|
|
51
52
|
private readonly txsMetadata: ITxMetadataCollection;
|
|
52
53
|
private readonly smartRequesterSemaphore: ISemaphore;
|
|
53
54
|
private readonly txQueue: FifoMemoryQueue<Tx>;
|
|
54
|
-
private readonly txValidator:
|
|
55
|
+
private readonly txValidator: TxValidator;
|
|
55
56
|
private readonly smartParallelWorkerCount: number;
|
|
56
57
|
private readonly dumbParallelWorkerCount: number;
|
|
57
58
|
private readonly txBatchSize: number;
|
|
@@ -78,7 +79,7 @@ export class BatchTxRequester {
|
|
|
78
79
|
this.opts.dumbParallelWorkerCount ?? DEFAULT_BATCH_TX_REQUESTER_DUMB_PARALLEL_WORKER_COUNT;
|
|
79
80
|
this.txBatchSize = this.opts.txBatchSize ?? DEFAULT_BATCH_TX_REQUESTER_TX_BATCH_SIZE;
|
|
80
81
|
this.txQueue = new FifoMemoryQueue(this.logger);
|
|
81
|
-
this.txValidator = this.opts.txValidator ??
|
|
82
|
+
this.txValidator = this.opts.txValidator ?? createBatchRequestTxValidator(this.p2pService.txValidatorConfig);
|
|
82
83
|
|
|
83
84
|
if (this.opts.peerCollection) {
|
|
84
85
|
this.peers = this.opts.peerCollection;
|
|
@@ -97,7 +98,7 @@ export class BatchTxRequester {
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/*
|
|
100
|
-
* Fetches all missing transactions and yields them
|
|
101
|
+
* Fetches all missing transactions and yields them one by one
|
|
101
102
|
* */
|
|
102
103
|
public async *run(): AsyncGenerator<Tx, Tx | undefined, unknown> {
|
|
103
104
|
try {
|
|
@@ -428,6 +429,15 @@ export class BatchTxRequester {
|
|
|
428
429
|
}
|
|
429
430
|
|
|
430
431
|
const blockResponse = BlockTxsResponse.fromBuffer(response.data);
|
|
432
|
+
|
|
433
|
+
// Validate response. Peers will be penalised by the validator if they send invalid response.
|
|
434
|
+
const isValid = await this.p2pService.validateRequestedBlockTxsConsistency(request, blockResponse, peerId);
|
|
435
|
+
if (!isValid) {
|
|
436
|
+
this.logger.debug(`Peer ${peerId.toString()} sent invalid response`);
|
|
437
|
+
this.handleFailResponseFromPeer(peerId, ReqRespStatus.INTERNAL_ERROR);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
|
|
431
441
|
await this.handleSuccessResponseFromPeer(peerId, blockResponse);
|
|
432
442
|
} catch (err: any) {
|
|
433
443
|
this.logger.error(`Failed to get valid response from peer ${peerId.toString()}: ${err.message}`, {
|
|
@@ -445,27 +455,24 @@ export class BatchTxRequester {
|
|
|
445
455
|
* Handles failed response form the peer
|
|
446
456
|
* There are 3 scenarios
|
|
447
457
|
* - RATE_LIMIT_EXCEEDED: We mark this and don't query this peer again for some_time
|
|
458
|
+
* - INTERNAL_ERROR: We use this to cover cases where the request-response consistency validation fails.
|
|
448
459
|
* - FAILURE and UNKNOWN: We penalise this, if peer has been penalised this way N times they are not queried again
|
|
449
460
|
* this implies we will query these peers couple of more times and give them a chance to "redeem" themselves before completely ignoring them
|
|
450
461
|
*/
|
|
451
462
|
private handleFailResponseFromPeer(peerId: PeerId, responseStatus: ReqRespStatus) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if (responseStatus === ReqRespStatus.RATE_LIMIT_EXCEEDED) {
|
|
468
|
-
this.peers.markPeerRateLimitExceeded(peerId);
|
|
463
|
+
switch (responseStatus) {
|
|
464
|
+
case ReqRespStatus.RATE_LIMIT_EXCEEDED:
|
|
465
|
+
this.peers.markPeerRateLimitExceeded(peerId);
|
|
466
|
+
return;
|
|
467
|
+
case ReqRespStatus.INTERNAL_ERROR:
|
|
468
|
+
this.peers.markPeerDumb(peerId);
|
|
469
|
+
this.txsMetadata.clearPeerData(peerId);
|
|
470
|
+
return;
|
|
471
|
+
default: // includes FAILURE, UNKNOWN
|
|
472
|
+
this.peers.penalisePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
473
|
+
this.peers.markPeerDumb(peerId);
|
|
474
|
+
this.txsMetadata.clearPeerData(peerId);
|
|
475
|
+
return;
|
|
469
476
|
}
|
|
470
477
|
}
|
|
471
478
|
|
|
@@ -485,7 +492,7 @@ export class BatchTxRequester {
|
|
|
485
492
|
* Handles received txs.
|
|
486
493
|
* Transactions are validated and then put on async queue
|
|
487
494
|
* to be yielded by main running loop
|
|
488
|
-
|
|
495
|
+
*/
|
|
489
496
|
private async handleReceivedTxs(peerId: PeerId, txs: TxArray) {
|
|
490
497
|
const newTxs = txs.filter(tx => !this.txsMetadata.alreadyFetched(tx.txHash));
|
|
491
498
|
|
|
@@ -493,12 +500,12 @@ export class BatchTxRequester {
|
|
|
493
500
|
return;
|
|
494
501
|
}
|
|
495
502
|
|
|
496
|
-
//TODO: this validation can be slow, maybe spawn worker just for validation
|
|
503
|
+
// TODO: this validation can be slow, maybe spawn worker just for validation
|
|
497
504
|
// We could use the async queue for communication.
|
|
498
505
|
const validationResults = await Promise.allSettled(
|
|
499
506
|
newTxs.map(async tx => ({
|
|
500
507
|
tx,
|
|
501
|
-
isValid: (await this.txValidator.
|
|
508
|
+
isValid: (await this.txValidator.validateTx(tx)).result === 'valid',
|
|
502
509
|
})),
|
|
503
510
|
);
|
|
504
511
|
|
|
@@ -553,9 +560,10 @@ export class BatchTxRequester {
|
|
|
553
560
|
return;
|
|
554
561
|
}
|
|
555
562
|
|
|
556
|
-
|
|
557
|
-
if (
|
|
558
|
-
this.
|
|
563
|
+
// If the peer doesn't have the block, we mark them as dumb.
|
|
564
|
+
if (!response.peerHasBlock()) {
|
|
565
|
+
this.peers.markPeerDumb(peerId);
|
|
566
|
+
this.txsMetadata.clearPeerData(peerId);
|
|
559
567
|
return;
|
|
560
568
|
}
|
|
561
569
|
|
|
@@ -573,21 +581,6 @@ export class BatchTxRequester {
|
|
|
573
581
|
this.smartRequesterSemaphore.release();
|
|
574
582
|
}
|
|
575
583
|
|
|
576
|
-
/**
|
|
577
|
-
* Handles an archive root mismatch between local state and peer response.
|
|
578
|
-
*
|
|
579
|
-
* - Response archive is Fr.ZERO (peer pruned proposal, legitimate): marks peer dumb.
|
|
580
|
-
* - Non-zero archive mismatch (malicious response): penalises + marks dumb.
|
|
581
|
-
*/
|
|
582
|
-
private handleArchiveRootMismatch(peerId: PeerId, response: BlockTxsResponse): void {
|
|
583
|
-
if (!response.archiveRoot.isZero()) {
|
|
584
|
-
this.peers.penalisePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
this.peers.markPeerDumb(peerId);
|
|
588
|
-
this.txsMetadata.clearPeerData(peerId);
|
|
589
|
-
}
|
|
590
|
-
|
|
591
584
|
private peerHasSomeTxsWeAreMissing(_peerId: PeerId, response: BlockTxsResponse): boolean {
|
|
592
585
|
if (response.txIndices.isEmpty()) {
|
|
593
586
|
return false;
|
|
@@ -603,15 +596,9 @@ export class BatchTxRequester {
|
|
|
603
596
|
}
|
|
604
597
|
|
|
605
598
|
private extractHashesPeerHasFromResponse(response: BlockTxsResponse): Array<TxHash> {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (indicesOfHashesPeerHas.has(idx)) {
|
|
610
|
-
hashes.push(hash);
|
|
611
|
-
}
|
|
612
|
-
});
|
|
613
|
-
|
|
614
|
-
return hashes;
|
|
599
|
+
// Should already have been validated, but just in case.
|
|
600
|
+
assert(response.txIndices.getLength() === this.blockTxsSource.txHashes.length);
|
|
601
|
+
return response.txIndices.getTrueIndices().map(idx => this.blockTxsSource.txHashes[idx]);
|
|
615
602
|
}
|
|
616
603
|
|
|
617
604
|
/*
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { ISemaphore } from '@aztec/foundation/queue';
|
|
2
2
|
import type { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
3
|
-
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
3
|
+
import type { Tx, TxHash, TxValidator } from '@aztec/stdlib/tx';
|
|
4
4
|
|
|
5
5
|
import type { PeerId } from '@libp2p/interface';
|
|
6
6
|
|
|
7
7
|
import type { ConnectionSampler } from '../connection-sampler/connection_sampler.js';
|
|
8
|
+
import type { BlockTxsRequest, BlockTxsResponse } from '../index.js';
|
|
8
9
|
import type { ReqRespInterface } from '../interface.js';
|
|
9
10
|
import type { IPeerCollection } from './peer_collection.js';
|
|
10
|
-
import type { BatchRequestTxValidatorConfig
|
|
11
|
+
import type { BatchRequestTxValidatorConfig } from './tx_validator.js';
|
|
11
12
|
|
|
12
13
|
export interface IPeerPenalizer {
|
|
13
14
|
penalizePeer(peerId: PeerId, penalty: PeerErrorSeverity): void;
|
|
@@ -32,13 +33,19 @@ export interface ITxMetadataCollection {
|
|
|
32
33
|
*/
|
|
33
34
|
export interface BatchTxRequesterLibP2PService {
|
|
34
35
|
/** ReqResp interface for sending requests to peers */
|
|
35
|
-
reqResp: Pick<ReqRespInterface, '
|
|
36
|
+
reqResp: Pick<ReqRespInterface, 'sendRequestToPeer'>;
|
|
36
37
|
/** Connection sampler for getting peer lists */
|
|
37
38
|
connectionSampler: Pick<ConnectionSampler, 'getPeerListSortedByConnectionCountAsc'>;
|
|
38
39
|
/** Configuration needed for transaction validation */
|
|
39
40
|
txValidatorConfig: BatchRequestTxValidatorConfig;
|
|
40
41
|
/** Peer scoring for penalizing peers */
|
|
41
42
|
peerScoring: IPeerPenalizer;
|
|
43
|
+
/** Validate the requested block transactions request-response consistency */
|
|
44
|
+
validateRequestedBlockTxsConsistency: (
|
|
45
|
+
request: BlockTxsRequest,
|
|
46
|
+
response: BlockTxsResponse,
|
|
47
|
+
peerId: PeerId,
|
|
48
|
+
) => Promise<boolean>;
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
export interface BatchTxRequesterOptions {
|
|
@@ -50,5 +57,5 @@ export interface BatchTxRequesterOptions {
|
|
|
50
57
|
semaphore?: ISemaphore;
|
|
51
58
|
peerCollection?: IPeerCollection;
|
|
52
59
|
/** Optional tx validator for testing - if not provided, one is created from p2pService.txValidatorConfig */
|
|
53
|
-
txValidator?:
|
|
60
|
+
txValidator?: TxValidator;
|
|
54
61
|
}
|