@aztec/p2p 0.0.1-commit.21ecf947b → 0.0.1-commit.2448fdb
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 +6 -6
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +31 -28
- package/dest/client/interface.d.ts +10 -19
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +7 -18
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +51 -96
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -7
- package/dest/config.d.ts +29 -10
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +80 -31
- 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/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +4 -4
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +3 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +9 -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 +5 -4
- 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 +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +5 -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 +12 -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 +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -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 +18 -6
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +3 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +49 -9
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +102 -14
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +5 -2
- 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 +21 -12
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -4
- 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 +9 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +11 -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 +279 -153
- 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 +48 -36
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- 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/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/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/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/services/dummy_service.d.ts +4 -4
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +4 -4
- package/dest/services/encoding.d.ts +6 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +16 -9
- 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 +16 -13
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +97 -93
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -3
- 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 +5 -9
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -6
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +10 -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 +25 -46
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- 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 +17 -9
- package/dest/services/service.d.ts +5 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +39 -33
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +4 -2
- package/dest/services/tx_collection/file_store_tx_source.d.ts +16 -6
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +50 -9
- 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/missing_txs_tracker.d.ts +32 -0
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
- 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/slow_tx_collection.d.ts +2 -2
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +10 -8
- package/dest/services/tx_collection/tx_collection.d.ts +5 -4
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.d.ts +6 -5
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +13 -22
- 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/tx_file_store.js +1 -1
- package/dest/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +4 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- 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 +4 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +8 -2
- 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 +6 -3
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +3 -2
- 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 +13 -12
- 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 +4 -1
- package/dest/util.d.ts +2 -2
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +53 -46
- package/src/client/interface.ts +11 -20
- package/src/client/p2p_client.ts +55 -126
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +19 -10
- package/src/config.ts +115 -33
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
- package/src/mem_pools/tx_pool/priority.ts +4 -4
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
- package/src/mem_pools/tx_pool_v2/README.md +9 -1
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +11 -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 +5 -4
- 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 +2 -2
- 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 +12 -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 +1 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +17 -6
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +143 -17
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +25 -14
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +25 -8
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +311 -148
- package/src/msg_validators/attestation_validator/README.md +49 -0
- 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 +63 -40
- package/src/msg_validators/tx_validator/README.md +119 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
- 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/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +42 -1
- 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/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
- package/src/services/dummy_service.ts +6 -6
- package/src/services/encoding.ts +16 -8
- 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 +111 -101
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +6 -6
- package/src/services/reqresp/batch-tx-requester/interface.ts +1 -5
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +23 -71
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/reqresp.ts +19 -11
- package/src/services/service.ts +11 -2
- package/src/services/tx_collection/fast_tx_collection.ts +51 -30
- package/src/services/tx_collection/file_store_tx_collection.ts +7 -3
- package/src/services/tx_collection/file_store_tx_source.ts +65 -9
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
- package/src/services/tx_collection/slow_tx_collection.ts +8 -9
- package/src/services/tx_collection/tx_collection.ts +4 -3
- package/src/services/tx_collection/tx_collection_sink.ts +15 -29
- package/src/services/tx_collection/tx_source.ts +28 -8
- package/src/services/tx_file_store/tx_file_store.ts +1 -1
- package/src/services/tx_provider.ts +2 -2
- package/src/test-helpers/make-test-p2p-clients.ts +0 -2
- package/src/test-helpers/mock-pubsub.ts +13 -6
- package/src/test-helpers/reqresp-nodes.ts +2 -5
- package/src/test-helpers/testbench-utils.ts +4 -3
- package/src/testbench/p2p_client_testbench_worker.ts +21 -17
- package/src/testbench/worker_client_manager.ts +11 -4
- package/src/util.ts +7 -1
- 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/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# ReqResp Protocols
|
|
2
|
+
|
|
3
|
+
This module implements libp2p request-response protocols for the Aztec P2P network. All protocols share common transport-level validation (rate limiting, timeouts, Snappy decompression, error penalties) with protocol-specific logic layered on top.
|
|
4
|
+
|
|
5
|
+
## Common Transport Validation
|
|
6
|
+
|
|
7
|
+
### Rate Limiting (Responder Side)
|
|
8
|
+
|
|
9
|
+
Applied before the protocol handler runs.
|
|
10
|
+
|
|
11
|
+
| Protocol | Peer Limit | Global Limit | File |
|
|
12
|
+
|----------|-----------|-------------|------|
|
|
13
|
+
| PING | 5/s | 10/s | `rate-limiter/rate_limits.ts` |
|
|
14
|
+
| STATUS | 5/s | 10/s | same |
|
|
15
|
+
| AUTH | 5/s | 10/s | same |
|
|
16
|
+
| GOODBYE | 5/s | 10/s | same |
|
|
17
|
+
| BLOCK | 2/s | 5/s | same |
|
|
18
|
+
| BLOCK_TXS | 10/s | 200/s | same |
|
|
19
|
+
| TX | (see rate limits file) | (see rate limits file) | same |
|
|
20
|
+
|
|
21
|
+
- Per-peer limit exceeded: `HighToleranceError` penalty + `RATE_LIMIT_EXCEEDED` status. Penalty fires inside `RequestResponseRateLimiter.allow()`, not the stream handler.
|
|
22
|
+
- Global limit exceeded: `RATE_LIMIT_EXCEEDED` status only (no peer penalty).
|
|
23
|
+
|
|
24
|
+
### Response Status Byte (Requester Side)
|
|
25
|
+
|
|
26
|
+
| Rule | Consequence | File |
|
|
27
|
+
|------|-------------|------|
|
|
28
|
+
| First chunk must be exactly 1 byte | `ReqRespStatusError(UNKNOWN)` | `status.ts` |
|
|
29
|
+
| Byte must be valid `ReqRespStatus` enum (0-4, 126, 127) | `ReqRespStatusError(UNKNOWN)` | same |
|
|
30
|
+
|
|
31
|
+
Note: `prettyPrintReqRespStatus` is missing a `NOT_FOUND` case (minor logging bug).
|
|
32
|
+
|
|
33
|
+
### Snappy Decompression (Requester Side)
|
|
34
|
+
|
|
35
|
+
Per-protocol size limits checked via preamble before decompression.
|
|
36
|
+
|
|
37
|
+
### Timeouts (Requester Side)
|
|
38
|
+
|
|
39
|
+
| Timeout | Default | Penalty |
|
|
40
|
+
|---------|---------|---------|
|
|
41
|
+
| Individual request | 10s | HighToleranceError |
|
|
42
|
+
| Dial | 5s | HighToleranceError |
|
|
43
|
+
|
|
44
|
+
### Error Penalty Categorization (Requester Side)
|
|
45
|
+
|
|
46
|
+
| Error Type | Severity |
|
|
47
|
+
|------------|----------|
|
|
48
|
+
| GOODBYE subprotocol errors | None |
|
|
49
|
+
| `CollectiveReqRespTimeoutError` / `InvalidResponseError` | None |
|
|
50
|
+
| `AbortError` / connection close / muxer closed | None |
|
|
51
|
+
| `ECONNRESET` / `EPIPE` / `ECONNREFUSED` / `ERR_UNEXPECTED_EOF` | HighToleranceError |
|
|
52
|
+
| `ERR_UNSUPPORTED_PROTOCOL` | HighToleranceError |
|
|
53
|
+
| `IndividualReqRespTimeoutError` / `TimeoutError` | HighToleranceError |
|
|
54
|
+
| Catch-all | HighToleranceError |
|
|
55
|
+
|
|
56
|
+
### Request Error Penalty (Responder Side)
|
|
57
|
+
|
|
58
|
+
| Error Type | Severity |
|
|
59
|
+
|------------|----------|
|
|
60
|
+
| `BADLY_FORMED_REQUEST` | LowToleranceError |
|
|
61
|
+
| All others | None |
|
|
62
|
+
|
|
63
|
+
### Notes
|
|
64
|
+
|
|
65
|
+
- Request payloads are NOT snappy-compressed (asymmetric: only responses use snappy).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Handshake Protocols
|
|
70
|
+
|
|
71
|
+
### Connection-Level Gating (Before Any Handshake)
|
|
72
|
+
|
|
73
|
+
| Rule | Consequence | File |
|
|
74
|
+
|------|-------------|------|
|
|
75
|
+
| Deny inbound connection from IP/peerId with too many failed auth handshakes | Connection denied | `libp2p_service.ts` |
|
|
76
|
+
| Threshold: `p2pMaxFailedAuthAttemptsAllowed` (default 3) | Tracked per peerId AND per IP | `peer_manager.ts` |
|
|
77
|
+
| Failed auth entries expire after 1 hour | Peer can reconnect; no escalating penalty for repeat offenders | same |
|
|
78
|
+
|
|
79
|
+
### Handshake Trigger Logic (`peer:connect`)
|
|
80
|
+
|
|
81
|
+
1. `p2pDisableStatusHandshake` = true: no handshake
|
|
82
|
+
2. `p2pAllowOnlyValidators` = false: STATUS handshake
|
|
83
|
+
3. Peer is protected (trusted/private/preferred): STATUS handshake
|
|
84
|
+
4. Otherwise: AUTH handshake (superset of STATUS)
|
|
85
|
+
|
|
86
|
+
Config constraint: `p2pDisableStatusHandshake && p2pAllowOnlyValidators` is disallowed.
|
|
87
|
+
|
|
88
|
+
### STATUS Protocol (`/aztec/req/status/1.0.0`)
|
|
89
|
+
|
|
90
|
+
**Requester side** (`peer_manager.ts`):
|
|
91
|
+
|
|
92
|
+
| Rule | Consequence |
|
|
93
|
+
|------|-------------|
|
|
94
|
+
| Response status must be SUCCESS | Peer scheduled for disconnect |
|
|
95
|
+
| `compressedComponentsVersion` must match | Peer scheduled for disconnect |
|
|
96
|
+
| Any exception | Peer scheduled for disconnect |
|
|
97
|
+
|
|
98
|
+
`StatusMessage.validate()` currently only checks `compressedComponentsVersion`. Fields `latestBlockNumber`, `latestBlockHash`, `finalizedBlockNumber` are NOT validated (TODO in code).
|
|
99
|
+
|
|
100
|
+
**Responder side**: no validation of incoming request content (always responds with own status). This means the requester leaks its blockchain state to any peer before validation.
|
|
101
|
+
|
|
102
|
+
**Deserialization bounds**: `MAX_VERSION_STRING_LENGTH` = 64 bytes, `MAX_BLOCK_HASH_STRING_LENGTH` = 128 bytes. Expected response size: 1 KB.
|
|
103
|
+
|
|
104
|
+
### AUTH Protocol (`/aztec/req/auth/1.0.0`)
|
|
105
|
+
|
|
106
|
+
**Requester side** (`peer_manager.ts`):
|
|
107
|
+
|
|
108
|
+
| # | Rule | Consequence |
|
|
109
|
+
|---|------|-------------|
|
|
110
|
+
| 1 | Response status is SUCCESS | `markAuthHandshakeFailed` + disconnect |
|
|
111
|
+
| 2 | `compressedComponentsVersion` match | `markAuthHandshakeFailed` + disconnect |
|
|
112
|
+
| 3 | Valid ECDSA signature recovery from challenge response | `markAuthHandshakeFailed` + disconnect |
|
|
113
|
+
| 4 | Recovered address is a registered validator | `markAuthHandshakeFailed` + disconnect |
|
|
114
|
+
| 5 | Validator address not already authenticated to different peerId | Silent return (no disconnect, no failure marking -- peer stays connected but unauthenticated) |
|
|
115
|
+
| 6 | Any exception | `markAuthHandshakeFailed` + disconnect |
|
|
116
|
+
|
|
117
|
+
Challenge: random `Fr`, payload = `keccak256("Aztec Validator Challenge:" + challenge)`, signed with `eth_sign` style. Challenge is NOT bound to peer identity (transport encryption via Noise is the binding layer).
|
|
118
|
+
|
|
119
|
+
On success: peer added to authenticated maps, prior failures cleared (including IP-based ones -- shared-IP peers benefit from a legitimate validator's success).
|
|
120
|
+
|
|
121
|
+
**Responder side** (`validator-client/src/validator.ts` + `peer_manager.ts`):
|
|
122
|
+
|
|
123
|
+
| # | Rule | Consequence |
|
|
124
|
+
|---|------|-------------|
|
|
125
|
+
| 1 | Peer must be protected (`shouldTrustWithIdentity` in `peer_manager.ts`) | Returns empty buffer (SUCCESS status + empty payload -> requester gets parse error -> `markAuthHandshakeFailed`) |
|
|
126
|
+
| 2 | Node must have registered validator address | Returns empty buffer (same consequence) |
|
|
127
|
+
|
|
128
|
+
**Unauthenticated peer gossip**: when `p2pAllowOnlyValidators` is true, unauthenticated peers get `appSpecificScore = -Infinity`, completely excluding them from all gossip.
|
|
129
|
+
|
|
130
|
+
### PING Protocol (`/aztec/req/ping/1.0.0`)
|
|
131
|
+
|
|
132
|
+
No validation on either side. Responder returns `Buffer.from('pong')`. Expected response: 1 KB.
|
|
133
|
+
|
|
134
|
+
### GOODBYE Protocol (`/aztec/req/goodbye/1.0.0`)
|
|
135
|
+
|
|
136
|
+
**Responder**: buffer must be 1 byte (defaults to `UNKNOWN` on invalid length). Goodbye reason byte is NOT validated against the enum -- any byte 0-255 accepted. Peer scheduled for disconnect regardless of reason.
|
|
137
|
+
|
|
138
|
+
**Requester**: response errors are never penalized (GOODBYE subprotocol exempt from error categorization).
|
|
139
|
+
|
|
140
|
+
### Periodic Re-validation
|
|
141
|
+
|
|
142
|
+
| Rule | Interval | File |
|
|
143
|
+
|------|----------|------|
|
|
144
|
+
| Authenticated validators re-checked against current validator set | Every heartbeat (`peerCheckIntervalMS`) | `peer_manager.ts` |
|
|
145
|
+
| If validator address no longer registered, auth entry removed | Same | same |
|
|
146
|
+
|
|
147
|
+
Protected peers (private/trusted/preferred) are always considered "authenticated" without AUTH handshake.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Block Data Protocols
|
|
152
|
+
|
|
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
|
+
### BLOCK_TXS Protocol (`/aztec/req/block_txs/1.0.0`)
|
|
174
|
+
|
|
175
|
+
**Server side**:
|
|
176
|
+
|
|
177
|
+
| Rule | Consequence | File |
|
|
178
|
+
|------|-------------|------|
|
|
179
|
+
| Request must parse as `BlockTxsRequest` (Fr + TxHashArray + BitVector) | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block_txs/block_txs_handler.ts` |
|
|
180
|
+
| BitVector length: non-negative and <= `MAX_TXS_PER_BLOCK` (65536) | Deserialization throws -> `BADLY_FORMED_REQUEST` | `protocols/block_txs/bitvector.ts` |
|
|
181
|
+
| 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, unlike BLOCK) | handler |
|
|
183
|
+
|
|
184
|
+
Conditional registration: BLOCK_TXS handler only registered when `config.disableTransactions` is false. Otherwise peers get `ERR_UNSUPPORTED_PROTOCOL`.
|
|
185
|
+
|
|
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
|
+
**Requester side via `BatchTxRequester`** (separate validation path):
|
|
200
|
+
|
|
201
|
+
| Rule | Consequence | File |
|
|
202
|
+
|------|-------------|------|
|
|
203
|
+
| Non-SUCCESS status: `FAILURE`/`UNKNOWN` | HighToleranceError + "bad peer" tracking | `batch-tx-requester/batch_tx_requester.ts` |
|
|
204
|
+
| `RATE_LIMIT_EXCEEDED` | Peer marked rate-limited (cooldown) | same |
|
|
205
|
+
| `NOT_FOUND` / `BADLY_FORMED_REQUEST` / `INTERNAL_ERROR` | Falls through silently (no penalty) | same |
|
|
206
|
+
| Each tx validated (Metadata + Size + Data + Proof) | LowToleranceError per invalid tx; valid txs from same response still accepted | same |
|
|
207
|
+
| Archive root match + non-empty txIndices | No penalty on mismatch; peer not promoted to "smart" | same |
|
|
208
|
+
|
|
209
|
+
**Double penalty on transport errors**: when `BatchTxRequester` encounters a transport error (e.g., ECONNRESET), both `sendRequestToPeer`'s internal handler and the `BatchTxRequester`'s catch block penalize the peer, resulting in double HighToleranceError.
|
|
210
|
+
|
|
211
|
+
See [BatchTxRequester README](batch-tx-requester/README.md) for the full architecture (peer classification, worker model, wire protocol).
|
|
212
|
+
|
|
213
|
+
### TX Protocol (`/aztec/req/tx/1.0.0`)
|
|
214
|
+
|
|
215
|
+
**Server side**:
|
|
216
|
+
|
|
217
|
+
| Rule | Consequence | File |
|
|
218
|
+
|------|-------------|------|
|
|
219
|
+
| Request must parse as `TxHashArray` | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/tx.ts` |
|
|
220
|
+
|
|
221
|
+
**Requester side** (validator registered at startup, not the default noop):
|
|
222
|
+
|
|
223
|
+
| Rule | Consequence | File |
|
|
224
|
+
|------|-------------|------|
|
|
225
|
+
| Each returned tx hash must be in the requested set | MidToleranceError | `libp2p_service.ts` (`validateRequestedTxs`) |
|
|
226
|
+
| Each tx passes well-formedness (Metadata + Size + Data + Proof) | LowToleranceError | same |
|
|
227
|
+
|
|
228
|
+
Snappy limit: `max(N, 1) * 512 + 1` KB.
|
|
229
|
+
|
|
@@ -10,6 +10,7 @@ import { Tx, TxArray, TxHash } from '@aztec/stdlib/tx';
|
|
|
10
10
|
import type { PeerId } from '@libp2p/interface';
|
|
11
11
|
import { peerIdFromString } from '@libp2p/peer-id';
|
|
12
12
|
|
|
13
|
+
import type { IMissingTxsTracker } from '../../tx_collection/missing_txs_tracker.js';
|
|
13
14
|
import { ReqRespSubProtocol } from '.././interface.js';
|
|
14
15
|
import { BlockTxsRequest, BlockTxsResponse, type BlockTxsSource } from '.././protocols/index.js';
|
|
15
16
|
import { ReqRespStatus } from '.././status.js';
|
|
@@ -20,7 +21,7 @@ import {
|
|
|
20
21
|
DEFAULT_BATCH_TX_REQUESTER_TX_BATCH_SIZE,
|
|
21
22
|
} from './config.js';
|
|
22
23
|
import type { BatchTxRequesterLibP2PService, BatchTxRequesterOptions, ITxMetadataCollection } from './interface.js';
|
|
23
|
-
import {
|
|
24
|
+
import { MissingTxMetadataCollection } from './missing_txs.js';
|
|
24
25
|
import { type IPeerCollection, PeerCollection } from './peer_collection.js';
|
|
25
26
|
import { BatchRequestTxValidator, type IBatchRequestTxValidator } from './tx_validator.js';
|
|
26
27
|
|
|
@@ -60,7 +61,7 @@ export class BatchTxRequester {
|
|
|
60
61
|
private readonly txBatchSize: number;
|
|
61
62
|
|
|
62
63
|
constructor(
|
|
63
|
-
|
|
64
|
+
missingTxsTracker: IMissingTxsTracker,
|
|
64
65
|
blockTxsSource: BlockTxsSource,
|
|
65
66
|
pinnedPeer: PeerId | undefined,
|
|
66
67
|
timeoutMs: number,
|
|
@@ -99,8 +100,7 @@ export class BatchTxRequester {
|
|
|
99
100
|
this.p2pService.peerScoring,
|
|
100
101
|
);
|
|
101
102
|
}
|
|
102
|
-
|
|
103
|
-
this.txsMetadata = new MissingTxMetadataCollection(entries, this.txBatchSize);
|
|
103
|
+
this.txsMetadata = new MissingTxMetadataCollection(missingTxsTracker, this.txBatchSize);
|
|
104
104
|
this.smartRequesterSemaphore = this.opts.semaphore ?? new Semaphore(0);
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -661,7 +661,7 @@ export class BatchTxRequester {
|
|
|
661
661
|
/*
|
|
662
662
|
* @returns true if all missing txs have been fetched */
|
|
663
663
|
private fetchedAllTxs() {
|
|
664
|
-
return
|
|
664
|
+
return this.txsMetadata.getMissingTxHashes().size == 0;
|
|
665
665
|
}
|
|
666
666
|
|
|
667
667
|
/*
|
|
@@ -679,7 +679,7 @@ export class BatchTxRequester {
|
|
|
679
679
|
this.unlockSmartRequesterSemaphores();
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
-
return aborted || this.
|
|
682
|
+
return aborted || this.fetchedAllTxs() || this.dateProvider.now() > this.deadline;
|
|
683
683
|
}
|
|
684
684
|
|
|
685
685
|
/*
|
|
@@ -6,7 +6,6 @@ import type { PeerId } from '@libp2p/interface';
|
|
|
6
6
|
|
|
7
7
|
import type { ConnectionSampler } from '../connection-sampler/connection_sampler.js';
|
|
8
8
|
import type { ReqRespInterface } from '../interface.js';
|
|
9
|
-
import type { MissingTxMetadata } from './missing_txs.js';
|
|
10
9
|
import type { IPeerCollection } from './peer_collection.js';
|
|
11
10
|
import type { BatchRequestTxValidatorConfig, IBatchRequestTxValidator } from './tx_validator.js';
|
|
12
11
|
|
|
@@ -15,18 +14,15 @@ export interface IPeerPenalizer {
|
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
export interface ITxMetadataCollection {
|
|
18
|
-
size: number;
|
|
19
|
-
values(): IterableIterator<MissingTxMetadata>;
|
|
20
17
|
getMissingTxHashes(): Set<string>;
|
|
18
|
+
markFetched(peerId: PeerId, tx: Tx): boolean;
|
|
21
19
|
getTxsToRequestFromThePeer(peer: PeerId): TxHash[];
|
|
22
20
|
markRequested(txHash: TxHash): void;
|
|
23
21
|
markInFlightBySmartPeer(txHash: TxHash): void;
|
|
24
22
|
markNotInFlightBySmartPeer(txHash: TxHash): void;
|
|
25
23
|
alreadyFetched(txHash: TxHash): boolean;
|
|
26
24
|
// Returns true if tx was marked as fetched, false if it was already marked as fetched
|
|
27
|
-
markFetched(peerId: PeerId, tx: Tx): boolean;
|
|
28
25
|
markPeerHas(peerId: PeerId, txHashes: TxHash[]): void;
|
|
29
|
-
getFetchedTxs(): Tx[];
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
/**
|
|
@@ -2,13 +2,13 @@ import { type Tx, TxHash } from '@aztec/stdlib/tx';
|
|
|
2
2
|
|
|
3
3
|
import type { PeerId } from '@libp2p/interface';
|
|
4
4
|
|
|
5
|
+
import type { IMissingTxsTracker } from '../../tx_collection/missing_txs_tracker.js';
|
|
5
6
|
import { DEFAULT_BATCH_TX_REQUESTER_TX_BATCH_SIZE } from './config.js';
|
|
6
7
|
import type { ITxMetadataCollection } from './interface.js';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
class MissingTxMetadata {
|
|
9
10
|
constructor(
|
|
10
|
-
public readonly txHash:
|
|
11
|
-
public fetched = false,
|
|
11
|
+
public readonly txHash: string,
|
|
12
12
|
public requestedCount = 0,
|
|
13
13
|
public inFlightCount = 0,
|
|
14
14
|
public tx: Tx | undefined = undefined,
|
|
@@ -30,24 +30,6 @@ export class MissingTxMetadata {
|
|
|
30
30
|
public isInFlight(): boolean {
|
|
31
31
|
return this.inFlightCount > 0;
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
//Returns true if this is the first time we mark it as fetched
|
|
35
|
-
public markAsFetched(peerId: PeerId, tx: Tx): boolean {
|
|
36
|
-
if (this.fetched) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
this.fetched = true;
|
|
41
|
-
this.tx = tx;
|
|
42
|
-
|
|
43
|
-
this.peers.add(peerId.toString());
|
|
44
|
-
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
public toString() {
|
|
49
|
-
return this.txHash.toString();
|
|
50
|
-
}
|
|
51
33
|
}
|
|
52
34
|
|
|
53
35
|
/*
|
|
@@ -55,21 +37,18 @@ export class MissingTxMetadata {
|
|
|
55
37
|
* This could be better optimized but given expected count of missing txs (N < 100)
|
|
56
38
|
* At the moment there is no need for it. And benefit is that we have everything in single store
|
|
57
39
|
* */
|
|
58
|
-
export class MissingTxMetadataCollection
|
|
40
|
+
export class MissingTxMetadataCollection implements ITxMetadataCollection {
|
|
41
|
+
private txMetadata = new Map<string, MissingTxMetadata>();
|
|
42
|
+
|
|
59
43
|
constructor(
|
|
60
|
-
|
|
44
|
+
private missingTxsTracker: IMissingTxsTracker,
|
|
61
45
|
private readonly txBatchSize: number = DEFAULT_BATCH_TX_REQUESTER_TX_BATCH_SIZE,
|
|
62
46
|
) {
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
public getSortedByRequestedCountAsc(txs: string[]): MissingTxMetadata[] {
|
|
66
|
-
return Array.from(this.values().filter(txMeta => txs.includes(txMeta.txHash.toString()))).sort(
|
|
67
|
-
(a, b) => a.requestedCount - b.requestedCount,
|
|
68
|
-
);
|
|
47
|
+
missingTxsTracker.missingTxHashes.forEach(hash => this.txMetadata.set(hash, new MissingTxMetadata(hash)));
|
|
69
48
|
}
|
|
70
49
|
|
|
71
50
|
public getPrioritizingNotInFlightAndLowerRequestCount(txs: string[]): MissingTxMetadata[] {
|
|
72
|
-
const filtered = Array.from(this.values()).filter(txMeta => txs.includes(txMeta.txHash.toString()));
|
|
51
|
+
const filtered = Array.from(this.txMetadata.values()).filter(txMeta => txs.includes(txMeta.txHash.toString()));
|
|
73
52
|
|
|
74
53
|
const [notInFlight, inFlight] = filtered.reduce<[MissingTxMetadata[], MissingTxMetadata[]]>(
|
|
75
54
|
(buckets, tx) => {
|
|
@@ -85,43 +64,15 @@ export class MissingTxMetadataCollection extends Map<string, MissingTxMetadata>
|
|
|
85
64
|
return [...notInFlight, ...inFlight];
|
|
86
65
|
}
|
|
87
66
|
|
|
88
|
-
public getFetchedTxHashes(): Set<string> {
|
|
89
|
-
return new Set(
|
|
90
|
-
this.values()
|
|
91
|
-
.filter(t => t.fetched)
|
|
92
|
-
.map(t => t.txHash.toString()),
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
67
|
public getMissingTxHashes(): Set<string> {
|
|
97
|
-
return
|
|
98
|
-
this.values()
|
|
99
|
-
.filter(t => !t.fetched)
|
|
100
|
-
.map(t => t.txHash.toString()),
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
public getInFlightTxHashes(): Set<string> {
|
|
105
|
-
return new Set(
|
|
106
|
-
this.values()
|
|
107
|
-
.filter(t => t.isInFlight())
|
|
108
|
-
.map(t => t.txHash.toString()),
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
public getFetchedTxs(): Tx[] {
|
|
113
|
-
return Array.from(
|
|
114
|
-
this.values()
|
|
115
|
-
.map(t => t.tx)
|
|
116
|
-
.filter(t => !!t),
|
|
117
|
-
);
|
|
68
|
+
return this.missingTxsTracker.missingTxHashes;
|
|
118
69
|
}
|
|
119
70
|
|
|
120
71
|
public getTxsPeerHas(peer: PeerId): Set<string> {
|
|
121
72
|
const peerIdStr = peer.toString();
|
|
122
73
|
const txsPeerHas = new Set<string>();
|
|
123
74
|
|
|
124
|
-
this.values().forEach(txMeta => {
|
|
75
|
+
this.txMetadata.values().forEach(txMeta => {
|
|
125
76
|
if (txMeta.peers.has(peerIdStr)) {
|
|
126
77
|
txsPeerHas.add(txMeta.txHash.toString());
|
|
127
78
|
}
|
|
@@ -132,13 +83,13 @@ export class MissingTxMetadataCollection extends Map<string, MissingTxMetadata>
|
|
|
132
83
|
|
|
133
84
|
public getTxsToRequestFromThePeer(peer: PeerId): TxHash[] {
|
|
134
85
|
const txsPeerHas = this.getTxsPeerHas(peer);
|
|
135
|
-
const
|
|
86
|
+
const missingTxHashes = this.getMissingTxHashes();
|
|
136
87
|
|
|
137
|
-
const txsToRequest = txsPeerHas.
|
|
88
|
+
const txsToRequest = txsPeerHas.intersection(missingTxHashes);
|
|
138
89
|
|
|
139
90
|
if (txsToRequest.size >= this.txBatchSize) {
|
|
140
91
|
return this.getPrioritizingNotInFlightAndLowerRequestCount(Array.from(txsToRequest))
|
|
141
|
-
.map(t => t.txHash)
|
|
92
|
+
.map(t => TxHash.fromString(t.txHash))
|
|
142
93
|
.slice(0, this.txBatchSize);
|
|
143
94
|
}
|
|
144
95
|
|
|
@@ -150,13 +101,13 @@ export class MissingTxMetadataCollection extends Map<string, MissingTxMetadata>
|
|
|
150
101
|
Array.from(this.getMissingTxHashes().difference(txsToRequest)),
|
|
151
102
|
)
|
|
152
103
|
.slice(0, countToFill)
|
|
153
|
-
.map(t => t.txHash);
|
|
104
|
+
.map(t => TxHash.fromString(t.txHash));
|
|
154
105
|
|
|
155
106
|
return [...Array.from(txsToRequest).map(t => TxHash.fromString(t)), ...txsToFill];
|
|
156
107
|
}
|
|
157
108
|
|
|
158
109
|
public markRequested(txHash: TxHash) {
|
|
159
|
-
this.get(txHash.toString())?.markAsRequested();
|
|
110
|
+
this.txMetadata.get(txHash.toString())?.markAsRequested();
|
|
160
111
|
}
|
|
161
112
|
|
|
162
113
|
/*
|
|
@@ -165,7 +116,7 @@ export class MissingTxMetadataCollection extends Map<string, MissingTxMetadata>
|
|
|
165
116
|
* "dumb" peer might return it, or might not - we don't know
|
|
166
117
|
* */
|
|
167
118
|
public markInFlightBySmartPeer(txHash: TxHash) {
|
|
168
|
-
this.get(txHash.toString())?.markInFlight();
|
|
119
|
+
this.txMetadata.get(txHash.toString())?.markInFlight();
|
|
169
120
|
}
|
|
170
121
|
|
|
171
122
|
/*
|
|
@@ -173,16 +124,16 @@ export class MissingTxMetadataCollection extends Map<string, MissingTxMetadata>
|
|
|
173
124
|
* Because the smart peer should return this tx, whereas
|
|
174
125
|
* "dumb" peer might return it, or might not - we don't know*/
|
|
175
126
|
public markNotInFlightBySmartPeer(txHash: TxHash) {
|
|
176
|
-
this.get(txHash.toString())?.markNotInFlight();
|
|
127
|
+
this.txMetadata.get(txHash.toString())?.markNotInFlight();
|
|
177
128
|
}
|
|
178
129
|
|
|
179
130
|
public alreadyFetched(txHash: TxHash): boolean {
|
|
180
|
-
return this.
|
|
131
|
+
return !this.missingTxsTracker.isMissing(txHash.toString());
|
|
181
132
|
}
|
|
182
133
|
|
|
183
134
|
public markFetched(peerId: PeerId, tx: Tx): boolean {
|
|
184
135
|
const txHashStr = tx.txHash.toString();
|
|
185
|
-
const txMeta = this.get(txHashStr);
|
|
136
|
+
const txMeta = this.txMetadata.get(txHashStr);
|
|
186
137
|
if (!txMeta) {
|
|
187
138
|
//TODO: what to do about peer which sent txs we didn't request?
|
|
188
139
|
// 1. don't request from it in the scope of this batch request
|
|
@@ -192,7 +143,8 @@ export class MissingTxMetadataCollection extends Map<string, MissingTxMetadata>
|
|
|
192
143
|
return false;
|
|
193
144
|
}
|
|
194
145
|
|
|
195
|
-
|
|
146
|
+
txMeta.peers.add(peerId.toString());
|
|
147
|
+
return this.missingTxsTracker.markFetched(tx);
|
|
196
148
|
}
|
|
197
149
|
|
|
198
150
|
public markPeerHas(peerId: PeerId, txHash: TxHash[]) {
|
|
@@ -200,7 +152,7 @@ export class MissingTxMetadataCollection extends Map<string, MissingTxMetadata>
|
|
|
200
152
|
txHash
|
|
201
153
|
.map(t => t.toString())
|
|
202
154
|
.forEach(txh => {
|
|
203
|
-
const txMeta = this.get(txh);
|
|
155
|
+
const txMeta = this.txMetadata.get(txh);
|
|
204
156
|
if (txMeta) {
|
|
205
157
|
txMeta.peers.add(peerIdStr);
|
|
206
158
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
|
|
2
2
|
import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { createTxValidatorForReqResponseReceivedTxs } from '../../../msg_validators/index.js';
|
|
5
5
|
|
|
6
6
|
export interface BatchRequestTxValidatorConfig {
|
|
7
7
|
l1ChainId: number;
|
|
@@ -29,7 +29,7 @@ export class BatchRequestTxValidator implements IBatchRequestTxValidator {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
static createRequestedTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
|
|
32
|
-
return
|
|
32
|
+
return createTxValidatorForReqResponseReceivedTxs(config.proofVerifier, {
|
|
33
33
|
l1ChainId: config.l1ChainId,
|
|
34
34
|
rollupVersion: config.rollupVersion,
|
|
35
35
|
});
|
|
@@ -97,9 +97,10 @@ export function prettyPrintRateLimitStatus(status: RateLimitStatus) {
|
|
|
97
97
|
* 2. Individual rate limits for each peer.
|
|
98
98
|
*
|
|
99
99
|
* How it works:
|
|
100
|
-
* - When a request comes in, it first checks against the
|
|
101
|
-
* - If the
|
|
102
|
-
* - The request is only allowed if both the
|
|
100
|
+
* - When a request comes in, it first checks against the peer's individual rate limit.
|
|
101
|
+
* - If the peer limit allows, it then checks against the global rate limit.
|
|
102
|
+
* - The request is only allowed if both the peer-specific and global limits allow it.
|
|
103
|
+
* - Checking peer limit first ensures a rate-limited peer cannot exhaust the global quota.
|
|
103
104
|
* - It automatically creates and manages rate limiters for new peers as they make requests.
|
|
104
105
|
* - It periodically cleans up rate limiters for inactive peers to conserve memory.
|
|
105
106
|
*
|
|
@@ -119,10 +120,6 @@ export class SubProtocolRateLimiter {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
allow(peerId: PeerId): RateLimitStatus {
|
|
122
|
-
if (!this.globalLimiter.allow()) {
|
|
123
|
-
return RateLimitStatus.DeniedGlobal;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
123
|
const peerIdStr = peerId.toString();
|
|
127
124
|
let peerLimiter: PeerRateLimiter | undefined = this.peerLimiters.get(peerIdStr);
|
|
128
125
|
if (!peerLimiter) {
|
|
@@ -135,10 +132,17 @@ export class SubProtocolRateLimiter {
|
|
|
135
132
|
} else {
|
|
136
133
|
peerLimiter.lastAccess = Date.now();
|
|
137
134
|
}
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
|
|
136
|
+
// Check peer limit first: a rate-limited peer must not consume global quota,
|
|
137
|
+
// otherwise one spamming peer can starve all others by exhausting the global bucket.
|
|
138
|
+
if (!peerLimiter.limiter.allow()) {
|
|
140
139
|
return RateLimitStatus.DeniedPeer;
|
|
141
140
|
}
|
|
141
|
+
|
|
142
|
+
if (!this.globalLimiter.allow()) {
|
|
143
|
+
return RateLimitStatus.DeniedGlobal;
|
|
144
|
+
}
|
|
145
|
+
|
|
142
146
|
return RateLimitStatus.Allowed;
|
|
143
147
|
}
|
|
144
148
|
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
IndividualReqRespTimeoutError,
|
|
17
17
|
InvalidResponseError,
|
|
18
18
|
} from '../../errors/reqresp.error.js';
|
|
19
|
-
import { SnappyTransform } from '../encoding.js';
|
|
19
|
+
import { OversizedSnappyResponseError, SnappyTransform } from '../encoding.js';
|
|
20
20
|
import type { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
21
21
|
import {
|
|
22
22
|
DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS,
|
|
@@ -462,7 +462,7 @@ export class ReqResp implements ReqRespInterface {
|
|
|
462
462
|
);
|
|
463
463
|
return resp;
|
|
464
464
|
} catch (e: any) {
|
|
465
|
-
this.logger.
|
|
465
|
+
this.logger.debug(`SUBPROTOCOL: ${subProtocol}\n`, e);
|
|
466
466
|
// On error we immediately abort the stream, this is preferred way,
|
|
467
467
|
// because it signals to the sender that error happened, whereas
|
|
468
468
|
// closing the stream only closes our side and is much slower
|
|
@@ -553,16 +553,10 @@ export class ReqResp implements ReqRespInterface {
|
|
|
553
553
|
data: message,
|
|
554
554
|
};
|
|
555
555
|
} catch (e: any) {
|
|
556
|
+
// All errors (invalid status bytes, oversized snappy responses, corrupt data, etc.)
|
|
557
|
+
// are re-thrown so the caller can penalize the peer via handleResponseError.
|
|
556
558
|
this.logger.debug(`Reading message failed: ${e.message}`);
|
|
557
|
-
|
|
558
|
-
let status = ReqRespStatus.UNKNOWN;
|
|
559
|
-
if (e instanceof ReqRespStatusError) {
|
|
560
|
-
status = e.status;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
return {
|
|
564
|
-
status,
|
|
565
|
-
};
|
|
559
|
+
throw e;
|
|
566
560
|
}
|
|
567
561
|
}
|
|
568
562
|
|
|
@@ -778,6 +772,20 @@ export class ReqResp implements ReqRespInterface {
|
|
|
778
772
|
return undefined;
|
|
779
773
|
}
|
|
780
774
|
|
|
775
|
+
// Invalid status byte: the peer sent a status byte that doesn't match any known status code.
|
|
776
|
+
// This is a protocol violation, penalize harshly.
|
|
777
|
+
if (e instanceof ReqRespStatusError) {
|
|
778
|
+
this.logger.warn(`Invalid status byte from peer ${peerId.toString()} in ${subProtocol}: ${e.message}`, logTags);
|
|
779
|
+
return PeerErrorSeverity.LowToleranceError;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// Oversized snappy response: the peer is sending data that exceeds the allowed size.
|
|
783
|
+
// This is a protocol violation that wastes bandwidth, so penalize harshly.
|
|
784
|
+
if (e instanceof OversizedSnappyResponseError) {
|
|
785
|
+
this.logger.warn(`Oversized response from peer ${peerId.toString()} in ${subProtocol}: ${e.message}`, logTags);
|
|
786
|
+
return PeerErrorSeverity.LowToleranceError;
|
|
787
|
+
}
|
|
788
|
+
|
|
781
789
|
return this.categorizeConnectionErrors(e, peerId, subProtocol);
|
|
782
790
|
}
|
|
783
791
|
|
package/src/services/service.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
BlockProposal,
|
|
6
|
+
CheckpointAttestation,
|
|
7
|
+
CheckpointProposalCore,
|
|
8
|
+
Gossipable,
|
|
9
|
+
TopicType,
|
|
10
|
+
} from '@aztec/stdlib/p2p';
|
|
5
11
|
import type { Tx } from '@aztec/stdlib/tx';
|
|
6
12
|
|
|
7
13
|
import type { PeerId } from '@libp2p/interface';
|
|
@@ -130,7 +136,10 @@ export interface P2PService {
|
|
|
130
136
|
|
|
131
137
|
getPeers(includePending?: boolean): PeerInfo[];
|
|
132
138
|
|
|
133
|
-
|
|
139
|
+
/** Returns the number of peers in the GossipSub mesh for a given topic type. */
|
|
140
|
+
getGossipMeshPeerCount(topicType: TopicType): number;
|
|
141
|
+
|
|
142
|
+
validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void>;
|
|
134
143
|
|
|
135
144
|
addReqRespSubProtocol(
|
|
136
145
|
subProtocol: ReqRespSubProtocol,
|