@aztec/p2p 0.0.1-commit.f504929 → 0.0.1-commit.f5a9928

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.
Files changed (483) hide show
  1. package/README.md +130 -3
  2. package/dest/bootstrap/bootstrap.d.ts +1 -1
  3. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  4. package/dest/bootstrap/bootstrap.js +22 -6
  5. package/dest/client/factory.d.ts +5 -4
  6. package/dest/client/factory.d.ts.map +1 -1
  7. package/dest/client/factory.js +39 -16
  8. package/dest/client/interface.d.ts +52 -12
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +36 -20
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +142 -81
  13. package/dest/config.d.ts +163 -98
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +130 -20
  16. package/dest/errors/p2p-service.error.d.ts +9 -0
  17. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  18. package/dest/errors/p2p-service.error.js +10 -0
  19. package/dest/errors/reqresp.error.d.ts +9 -16
  20. package/dest/errors/reqresp.error.d.ts.map +1 -1
  21. package/dest/errors/reqresp.error.js +10 -17
  22. package/dest/index.d.ts +1 -2
  23. package/dest/index.d.ts.map +1 -1
  24. package/dest/index.js +0 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +101 -59
  26. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/attestation_pool.js +272 -199
  28. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  29. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  30. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +224 -65
  31. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
  32. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  33. package/dest/mem_pools/attestation_pool/mocks.js +6 -4
  34. package/dest/mem_pools/index.d.ts +1 -2
  35. package/dest/mem_pools/index.d.ts.map +1 -1
  36. package/dest/mem_pools/instrumentation.d.ts +9 -4
  37. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  38. package/dest/mem_pools/instrumentation.js +28 -9
  39. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +10 -5
  40. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
  41. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +29 -20
  42. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +3 -3
  43. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
  44. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +6 -6
  45. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  46. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  47. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +5 -4
  48. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
  49. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +3 -1
  51. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
  52. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  53. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
  54. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  55. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  56. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +64 -0
  57. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +7 -1
  58. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +1 -1
  60. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
  61. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +3 -4
  62. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +1 -1
  63. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
  64. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +6 -7
  65. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +1 -1
  66. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  67. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +6 -5
  68. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +1 -1
  69. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  70. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +8 -6
  71. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +2 -2
  72. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
  73. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
  74. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +11 -1
  75. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -1
  76. package/dest/mem_pools/tx_pool_v2/instrumentation.js +24 -0
  77. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +41 -9
  78. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  79. package/dest/mem_pools/tx_pool_v2/interfaces.js +3 -1
  80. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +29 -11
  81. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  82. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +46 -16
  83. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +15 -1
  84. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  85. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +55 -41
  86. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +19 -4
  87. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  88. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +86 -32
  89. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +50 -6
  90. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  91. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +262 -131
  92. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -3
  93. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  94. package/dest/msg_validators/attestation_validator/attestation_validator.js +38 -15
  95. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
  96. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  97. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +4 -5
  98. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +11 -5
  99. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  100. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +11 -3
  101. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +11 -5
  102. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  103. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +23 -3
  104. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +35 -10
  105. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  106. package/dest/msg_validators/proposal_validator/proposal_validator.js +128 -56
  107. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  108. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  109. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
  110. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
  111. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  112. package/dest/msg_validators/tx_validator/allowed_public_setup.js +21 -32
  113. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  114. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  115. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  116. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  117. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  118. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  119. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  120. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  121. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  122. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  123. package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
  124. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  125. package/dest/msg_validators/tx_validator/data_validator.js +36 -2
  126. package/dest/msg_validators/tx_validator/factory.d.ts +25 -7
  127. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  128. package/dest/msg_validators/tx_validator/factory.js +55 -16
  129. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  130. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  131. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  132. package/dest/msg_validators/tx_validator/gas_validator.d.ts +53 -7
  133. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  134. package/dest/msg_validators/tx_validator/gas_validator.js +88 -41
  135. package/dest/msg_validators/tx_validator/index.d.ts +4 -1
  136. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  137. package/dest/msg_validators/tx_validator/index.js +3 -0
  138. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  139. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  140. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  141. package/dest/msg_validators/tx_validator/phases_validator.d.ts +21 -1
  142. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  143. package/dest/msg_validators/tx_validator/phases_validator.js +49 -2
  144. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
  145. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  146. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
  147. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  148. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  149. package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
  150. package/dest/services/data_store.d.ts +1 -1
  151. package/dest/services/data_store.d.ts.map +1 -1
  152. package/dest/services/data_store.js +5 -5
  153. package/dest/services/discv5/discV5_service.d.ts +13 -2
  154. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  155. package/dest/services/discv5/discV5_service.js +119 -23
  156. package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
  157. package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
  158. package/dest/services/discv5/persisted_enr_store.js +145 -0
  159. package/dest/services/dummy_service.d.ts +18 -16
  160. package/dest/services/dummy_service.d.ts.map +1 -1
  161. package/dest/services/dummy_service.js +21 -16
  162. package/dest/services/encoding.d.ts +23 -6
  163. package/dest/services/encoding.d.ts.map +1 -1
  164. package/dest/services/encoding.js +32 -16
  165. package/dest/services/gossipsub/topic_score_params.d.ts +6 -12
  166. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  167. package/dest/services/gossipsub/topic_score_params.js +4 -14
  168. package/dest/services/libp2p/instrumentation.d.ts +6 -1
  169. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  170. package/dest/services/libp2p/instrumentation.js +21 -0
  171. package/dest/services/libp2p/libp2p_service.d.ts +51 -51
  172. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  173. package/dest/services/libp2p/libp2p_service.js +499 -333
  174. package/dest/services/peer-manager/peer_manager.d.ts +31 -3
  175. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  176. package/dest/services/peer-manager/peer_manager.js +125 -25
  177. package/dest/services/peer-manager/peer_scoring.d.ts +34 -2
  178. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  179. package/dest/services/peer-manager/peer_scoring.js +102 -13
  180. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -8
  181. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  182. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +81 -86
  183. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +10 -6
  184. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  185. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
  186. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  187. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
  188. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
  189. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  190. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
  191. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
  192. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
  193. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
  194. package/dest/services/reqresp/config.d.ts +15 -3
  195. package/dest/services/reqresp/config.d.ts.map +1 -1
  196. package/dest/services/reqresp/config.js +11 -0
  197. package/dest/services/reqresp/interface.d.ts +16 -18
  198. package/dest/services/reqresp/interface.d.ts.map +1 -1
  199. package/dest/services/reqresp/interface.js +10 -20
  200. package/dest/services/reqresp/metrics.d.ts +1 -1
  201. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  202. package/dest/services/reqresp/metrics.js +0 -1
  203. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
  204. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  205. package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
  206. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  207. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  208. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
  209. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
  210. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  211. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +42 -24
  212. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  213. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  214. package/dest/services/reqresp/protocols/index.js +0 -1
  215. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  216. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  217. package/dest/services/reqresp/protocols/tx.js +1 -3
  218. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  219. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  220. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  221. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  222. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  223. package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -13
  224. package/dest/services/reqresp/reqresp.d.ts +7 -29
  225. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  226. package/dest/services/reqresp/reqresp.js +73 -215
  227. package/dest/services/service.d.ts +43 -18
  228. package/dest/services/service.d.ts.map +1 -1
  229. package/dest/services/tx_collection/config.d.ts +2 -23
  230. package/dest/services/tx_collection/config.d.ts.map +1 -1
  231. package/dest/services/tx_collection/config.js +2 -55
  232. package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
  233. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
  234. package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
  235. package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
  236. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  237. package/dest/services/tx_collection/file_store_tx_source.js +39 -29
  238. package/dest/services/tx_collection/index.d.ts +2 -3
  239. package/dest/services/tx_collection/index.d.ts.map +1 -1
  240. package/dest/services/tx_collection/index.js +0 -1
  241. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  242. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  243. package/dest/services/tx_collection/instrumentation.js +0 -2
  244. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  245. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  246. package/dest/services/tx_collection/request_tracker.js +84 -0
  247. package/dest/services/tx_collection/tx_collection.d.ts +36 -55
  248. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  249. package/dest/services/tx_collection/tx_collection.js +275 -119
  250. package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
  251. package/dest/services/tx_collection/tx_collection_sink.js +2 -2
  252. package/dest/services/tx_collection/tx_source.d.ts +6 -5
  253. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  254. package/dest/services/tx_collection/tx_source.js +13 -8
  255. package/dest/services/tx_file_store/tx_file_store.d.ts +1 -3
  256. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  257. package/dest/services/tx_file_store/tx_file_store.js +4 -14
  258. package/dest/services/tx_provider.d.ts +3 -1
  259. package/dest/services/tx_provider.d.ts.map +1 -1
  260. package/dest/services/tx_provider.js +3 -0
  261. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  262. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  263. package/dest/test-helpers/make-test-p2p-clients.js +5 -2
  264. package/dest/test-helpers/mock-pubsub.d.ts +33 -9
  265. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  266. package/dest/test-helpers/mock-pubsub.js +57 -44
  267. package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
  268. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  269. package/dest/test-helpers/reqresp-nodes.js +16 -18
  270. package/dest/test-helpers/test_tx_provider.d.ts +3 -1
  271. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
  272. package/dest/test-helpers/test_tx_provider.js +3 -0
  273. package/dest/test-helpers/testbench-utils.d.ts +15 -14
  274. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  275. package/dest/test-helpers/testbench-utils.js +49 -15
  276. package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
  277. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  278. package/dest/testbench/p2p_client_testbench_worker.js +104 -41
  279. package/dest/testbench/worker_client_manager.d.ts +12 -6
  280. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  281. package/dest/testbench/worker_client_manager.js +57 -11
  282. package/dest/util.d.ts +12 -7
  283. package/dest/util.d.ts.map +1 -1
  284. package/dest/util.js +35 -14
  285. package/dest/versioning.d.ts +3 -6
  286. package/dest/versioning.d.ts.map +1 -1
  287. package/dest/versioning.js +3 -24
  288. package/package.json +17 -17
  289. package/src/bootstrap/bootstrap.ts +17 -3
  290. package/src/client/factory.ts +62 -9
  291. package/src/client/interface.ts +48 -18
  292. package/src/client/p2p_client.ts +159 -113
  293. package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
  294. package/src/config.ts +233 -20
  295. package/src/errors/p2p-service.error.ts +11 -0
  296. package/src/errors/reqresp.error.ts +13 -19
  297. package/src/index.ts +0 -1
  298. package/src/mem_pools/attestation_pool/attestation_pool.ts +327 -242
  299. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +244 -69
  300. package/src/mem_pools/attestation_pool/mocks.ts +13 -8
  301. package/src/mem_pools/index.ts +0 -3
  302. package/src/mem_pools/instrumentation.ts +18 -12
  303. package/src/mem_pools/tx_pool_v2/README.md +9 -1
  304. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +30 -20
  305. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +7 -7
  306. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +4 -5
  307. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -2
  308. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  309. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +67 -0
  310. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +11 -1
  311. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +1 -3
  312. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -7
  313. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +5 -6
  314. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +15 -6
  315. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +2 -1
  316. package/src/mem_pools/tx_pool_v2/instrumentation.ts +27 -0
  317. package/src/mem_pools/tx_pool_v2/interfaces.ts +40 -8
  318. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +72 -20
  319. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +62 -41
  320. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +107 -32
  321. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +291 -137
  322. package/src/msg_validators/attestation_validator/README.md +49 -0
  323. package/src/msg_validators/attestation_validator/attestation_validator.ts +46 -14
  324. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +15 -7
  325. package/src/msg_validators/proposal_validator/README.md +123 -0
  326. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +26 -4
  327. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +43 -7
  328. package/src/msg_validators/proposal_validator/proposal_validator.ts +150 -58
  329. package/src/msg_validators/tx_validator/README.md +17 -3
  330. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
  331. package/src/msg_validators/tx_validator/allowed_public_setup.ts +16 -35
  332. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  333. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  334. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  335. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  336. package/src/msg_validators/tx_validator/data_validator.ts +44 -1
  337. package/src/msg_validators/tx_validator/factory.ts +66 -9
  338. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  339. package/src/msg_validators/tx_validator/gas_validator.ts +117 -39
  340. package/src/msg_validators/tx_validator/index.ts +3 -0
  341. package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
  342. package/src/msg_validators/tx_validator/phases_validator.ts +60 -1
  343. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
  344. package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
  345. package/src/services/data_store.ts +5 -13
  346. package/src/services/discv5/discV5_service.ts +126 -14
  347. package/src/services/discv5/persisted_enr_store.ts +158 -0
  348. package/src/services/dummy_service.ts +26 -40
  349. package/src/services/encoding.ts +35 -19
  350. package/src/services/gossipsub/README.md +33 -11
  351. package/src/services/gossipsub/topic_score_params.ts +9 -18
  352. package/src/services/libp2p/instrumentation.ts +22 -0
  353. package/src/services/libp2p/libp2p_service.ts +560 -369
  354. package/src/services/peer-manager/peer_manager.ts +138 -24
  355. package/src/services/peer-manager/peer_scoring.ts +102 -8
  356. package/src/services/reqresp/README.md +194 -0
  357. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  358. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +77 -95
  359. package/src/services/reqresp/batch-tx-requester/interface.ts +13 -5
  360. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
  361. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
  362. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
  363. package/src/services/reqresp/config.ts +19 -2
  364. package/src/services/reqresp/interface.ts +21 -47
  365. package/src/services/reqresp/metrics.ts +0 -1
  366. package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
  367. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
  368. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
  369. package/src/services/reqresp/protocols/index.ts +0 -1
  370. package/src/services/reqresp/protocols/tx.ts +1 -3
  371. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  372. package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -13
  373. package/src/services/reqresp/reqresp.ts +84 -259
  374. package/src/services/service.ts +51 -35
  375. package/src/services/tx_collection/config.ts +3 -80
  376. package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
  377. package/src/services/tx_collection/file_store_tx_source.ts +43 -31
  378. package/src/services/tx_collection/index.ts +1 -6
  379. package/src/services/tx_collection/instrumentation.ts +1 -7
  380. package/src/services/tx_collection/request_tracker.ts +127 -0
  381. package/src/services/tx_collection/tx_collection.ts +331 -176
  382. package/src/services/tx_collection/tx_collection_sink.ts +2 -2
  383. package/src/services/tx_collection/tx_source.ts +10 -8
  384. package/src/services/tx_file_store/tx_file_store.ts +5 -17
  385. package/src/services/tx_provider.ts +5 -0
  386. package/src/test-helpers/make-test-p2p-clients.ts +4 -1
  387. package/src/test-helpers/mock-pubsub.ts +61 -60
  388. package/src/test-helpers/reqresp-nodes.ts +13 -23
  389. package/src/test-helpers/test_tx_provider.ts +5 -0
  390. package/src/test-helpers/testbench-utils.ts +63 -28
  391. package/src/testbench/p2p_client_testbench_worker.ts +111 -57
  392. package/src/testbench/worker_client_manager.ts +72 -25
  393. package/src/util.ts +33 -18
  394. package/src/versioning.ts +3 -33
  395. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
  396. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
  397. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -304
  398. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
  399. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
  400. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
  401. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
  402. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  403. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
  404. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
  405. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
  406. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
  407. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
  408. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
  409. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
  410. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
  411. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
  412. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
  413. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
  414. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
  415. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
  416. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
  417. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
  418. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
  419. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
  420. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
  421. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
  422. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
  423. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
  424. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
  425. package/dest/mem_pools/tx_pool/index.d.ts +0 -3
  426. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  427. package/dest/mem_pools/tx_pool/index.js +0 -2
  428. package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
  429. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  430. package/dest/mem_pools/tx_pool/priority.js +0 -15
  431. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
  432. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  433. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  434. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  435. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  436. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
  437. package/dest/msg_validators/clock_tolerance.d.ts +0 -21
  438. package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
  439. package/dest/msg_validators/clock_tolerance.js +0 -37
  440. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -24
  441. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
  442. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -378
  443. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
  444. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  445. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
  446. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  447. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  448. package/dest/services/reqresp/protocols/block.js +0 -32
  449. package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -54
  450. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
  451. package/dest/services/tx_collection/fast_tx_collection.js +0 -327
  452. package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
  453. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
  454. package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
  455. package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -49
  456. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
  457. package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
  458. package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
  459. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
  460. package/dest/services/tx_collection/slow_tx_collection.js +0 -211
  461. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -345
  462. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
  463. package/src/mem_pools/tx_pool/README.md +0 -270
  464. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
  465. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
  466. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
  467. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
  468. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
  469. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
  470. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
  471. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
  472. package/src/mem_pools/tx_pool/index.ts +0 -2
  473. package/src/mem_pools/tx_pool/priority.ts +0 -20
  474. package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
  475. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
  476. package/src/msg_validators/clock_tolerance.ts +0 -51
  477. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -373
  478. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
  479. package/src/services/reqresp/protocols/block.ts +0 -37
  480. package/src/services/tx_collection/fast_tx_collection.ts +0 -387
  481. package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
  482. package/src/services/tx_collection/proposal_tx_collector.ts +0 -113
  483. 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';
@@ -32,9 +33,11 @@ import { PeerScoreState, type PeerScoring } from './peer_scoring.js';
32
33
  const MAX_DIAL_ATTEMPTS = 3;
33
34
  const MAX_CACHED_PEERS = 100;
34
35
  const MAX_CACHED_PEER_AGE_MS = 5 * 60 * 1000; // 5 minutes
35
- const FAILED_PEER_BAN_TIME_MS = 5 * 60 * 1000; // 5 minutes timeout after failing MAX_DIAL_ATTEMPTS
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
- const peerId = await enr.peerId();
205
- const address = enr.getLocationMultiaddr('tcp');
206
- if (address === undefined) {
207
- throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
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
- ).filter(peer => peer !== undefined);
271
+ ),
272
+ );
216
273
 
217
274
  await Promise.all(
218
275
  directPeers.map(peer => {
@@ -226,20 +283,30 @@ export class PeerManager implements PeerManagerInterface {
226
283
  }
227
284
 
228
285
  /**
229
- * Cleans up expired timeouts.
286
+ * Cleans up expired timeouts and stale failed-auth-handshake entries.
230
287
  *
231
288
  * When peers fail to dial after a number of retries, they are temporarily timed out.
232
289
  * This function removes any peers that have been in the timed out state for too long.
233
290
  * To give them a chance to reconnect.
291
+ *
292
+ * Also evicts entries from the failed-auth-handshake map whose expiry window has passed.
293
+ * Without this, peers that probe once and never reconnect would leave their entries in the
294
+ * map forever, causing an unbounded memory leak.
234
295
  */
235
296
  private cleanupExpiredTimeouts() {
236
- // Clean up expired timeouts
237
297
  const now = this.dateProvider.now();
298
+
238
299
  for (const [peerId, timedOutPeer] of this.timedOutPeers.entries()) {
239
300
  if (now >= timedOutPeer.timeoutUntilMs) {
240
301
  this.timedOutPeers.delete(peerId);
241
302
  }
242
303
  }
304
+
305
+ for (const [id, entry] of this.failedAuthHandshakes.entries()) {
306
+ if (now - entry.lastFailureTimestamp > FAILED_AUTH_HANDSHAKE_EXPIRY_MS) {
307
+ this.failedAuthHandshakes.delete(id);
308
+ }
309
+ }
243
310
  }
244
311
 
245
312
  /**
@@ -303,15 +370,20 @@ export class PeerManager implements PeerManagerInterface {
303
370
  */
304
371
  private handleDisconnectedPeerEvent(e: CustomEvent<PeerId>) {
305
372
  const peerId = e.detail;
373
+ const peerIdStr = peerId.toString();
306
374
  this.metrics.peerDisconnected(peerId);
307
- this.logger.verbose(`Disconnected from peer ${peerId.toString()}`);
308
- const validatorAddress = this.authenticatedPeerIdToValidatorAddress.get(peerId.toString());
375
+ this.logger.verbose(`Disconnected from peer ${peerIdStr}`);
376
+ const validatorAddress = this.authenticatedPeerIdToValidatorAddress.get(peerIdStr);
309
377
  if (validatorAddress !== undefined) {
310
378
  this.logger.info(
311
- `Removing authentication for validator ${validatorAddress} at peer id ${peerId.toString()} due to disconnection`,
379
+ `Removing authentication for validator ${validatorAddress} at peer id ${peerIdStr} due to disconnection`,
312
380
  );
313
381
  this.authenticatedValidatorAddressToPeerId.delete(validatorAddress.toString());
314
- this.authenticatedPeerIdToValidatorAddress.delete(peerId.toString());
382
+ this.authenticatedPeerIdToValidatorAddress.delete(peerIdStr);
383
+ }
384
+
385
+ if (this.peerScoring.getScoreState(peerIdStr) === PeerScoreState.Healthy) {
386
+ this.peerScoring.removePeer(peerIdStr);
315
387
  }
316
388
  }
317
389
 
@@ -479,15 +551,38 @@ export class PeerManager implements PeerManagerInterface {
479
551
  *
480
552
  * @returns: True if node is allowed to connect, otherwise false
481
553
  * */
482
- public isNodeAllowedToConnect(id: string | PeerId): boolean {
483
- const entry = this.failedAuthHandshakes.get(id.toString());
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);
484
579
  if (!entry) {
485
580
  return true;
486
581
  }
487
582
 
488
583
  // In case entry is too old, remove it and allow connection
489
584
  if (this.dateProvider.now() - entry.lastFailureTimestamp > FAILED_AUTH_HANDSHAKE_EXPIRY_MS) {
490
- this.failedAuthHandshakes.delete(id.toString());
585
+ this.failedAuthHandshakes.delete(key);
491
586
  return true;
492
587
  }
493
588
 
@@ -512,6 +607,7 @@ export class PeerManager implements PeerManagerInterface {
512
607
  protectedConnections: protectedPeerCount,
513
608
  maxPeerCount: this.config.maxPeerCount,
514
609
  cachedPeers: this.cachedPeers.size,
610
+ discv5KadPeers: this.peerDiscoveryService.getKadValues().length,
515
611
  ...this.peerScoring.getStats(),
516
612
  });
517
613
 
@@ -713,6 +809,12 @@ export class PeerManager implements PeerManagerInterface {
713
809
  return;
714
810
  }
715
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
+
716
818
  const [multiaddrTcp] = await Promise.all([enr.getFullMultiaddr('tcp')]);
717
819
 
718
820
  this.logger.trace(`Handling discovered peer ${peerId} at ${multiaddrTcp?.toString() ?? 'undefined address'}`);
@@ -776,7 +878,8 @@ export class PeerManager implements PeerManagerInterface {
776
878
  // Add to timed out peers
777
879
  this.timedOutPeers.set(id, {
778
880
  peerId: id,
779
- timeoutUntilMs: this.dateProvider.now() + FAILED_PEER_BAN_TIME_MS,
881
+ timeoutUntilMs:
882
+ this.dateProvider.now() + (this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS),
780
883
  });
781
884
  }
782
885
  }
@@ -938,6 +1041,8 @@ export class PeerManager implements PeerManagerInterface {
938
1041
  `Received auth for validator ${sender.toString()} from peer ${peerIdString}, but this validator is already authenticated to peer ${peerForAddress.toString()}`,
939
1042
  { ...logData, address: sender.toString() },
940
1043
  );
1044
+ this.markAuthHandshakeFailed(peerId);
1045
+ this.markPeerForDisconnect(peerId);
941
1046
  return;
942
1047
  }
943
1048
 
@@ -967,14 +1072,14 @@ export class PeerManager implements PeerManagerInterface {
967
1072
  const peerIdStr = peerId.toString();
968
1073
 
969
1074
  const existingEntry = this.failedAuthHandshakes.get(peerIdStr);
1075
+ const failureCount = (existingEntry?.count || 0) + 1;
970
1076
  this.failedAuthHandshakes.set(peerIdStr, {
971
- count: (existingEntry?.count || 0) + 1,
1077
+ count: failureCount,
972
1078
  lastFailureTimestamp: now,
973
1079
  });
974
1080
 
975
1081
  const connections = this.libP2PNode.getConnections(peerId);
976
1082
  connections.forEach(conn => {
977
- // We mark the IP address
978
1083
  const address = conn.remoteAddr.nodeAddress().address;
979
1084
  const existingAddressEntry = this.failedAuthHandshakes.get(address);
980
1085
  this.failedAuthHandshakes.set(address, {
@@ -982,6 +1087,15 @@ export class PeerManager implements PeerManagerInterface {
982
1087
  lastFailureTimestamp: now,
983
1088
  });
984
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);
985
1099
  }
986
1100
 
987
1101
  /*
@@ -1,5 +1,6 @@
1
1
  import { median } from '@aztec/foundation/collection';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
+ import { DateProvider } from '@aztec/foundation/timer';
3
4
  import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
4
5
  import {
5
6
  Attributes,
@@ -54,6 +55,10 @@ export enum PeerScoreState {
54
55
  // TODO: move into config / constants
55
56
  const MIN_SCORE_BEFORE_BAN = -100;
56
57
  const MIN_SCORE_BEFORE_DISCONNECT = -50;
58
+ const SCORE_CLEANUP_THRESHOLD = 0.1;
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 };
57
62
 
58
63
  export class PeerScoring {
59
64
  private logger = createLogger('p2p:peer-scoring');
@@ -65,7 +70,21 @@ export class PeerScoring {
65
70
 
66
71
  private peerStateCounter: UpDownCounter;
67
72
 
68
- constructor(config: P2PConfig, telemetry: TelemetryClient = getTelemetryClient()) {
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
+
82
+ constructor(
83
+ config: P2PConfig,
84
+ telemetry: TelemetryClient = getTelemetryClient(),
85
+ private readonly dateProvider: DateProvider = new DateProvider(),
86
+ ) {
87
+ this.banDurationMs = config.peerBanDurationSeconds * 1000;
69
88
  const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
70
89
  this.peerPenalties = {
71
90
  [PeerErrorSeverity.HighToleranceError]:
@@ -92,7 +111,7 @@ export class PeerScoring {
92
111
  }
93
112
 
94
113
  updateScore(peerId: string, scoreDelta: number): number {
95
- const currentTime = Date.now();
114
+ const currentTime = this.dateProvider.now();
96
115
  const lastUpdate = this.lastUpdateTime.get(peerId) || currentTime;
97
116
  const timePassed = currentTime - lastUpdate;
98
117
  const decayPeriods = Math.floor(timePassed / this.decayInterval);
@@ -107,29 +126,102 @@ export class PeerScoring {
107
126
 
108
127
  this.scores.set(peerId, currentScore);
109
128
  this.lastUpdateTime.set(peerId, currentTime);
129
+
130
+ this.maybeBanPeer(peerId, currentScore);
131
+
110
132
  return currentScore;
111
133
  }
112
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
+
113
154
  decayAllScores(): void {
114
- const currentTime = Date.now();
155
+ const currentTime = this.dateProvider.now();
115
156
  for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
116
157
  const timePassed = currentTime - lastUpdate;
117
158
  const decayPeriods = Math.floor(timePassed / this.decayInterval);
118
159
  if (decayPeriods > 0) {
119
160
  let score = this.scores.get(peerId) || 0;
120
161
  score *= Math.pow(this.decayFactor, decayPeriods);
121
- this.scores.set(peerId, score);
122
- this.lastUpdateTime.set(peerId, currentTime);
162
+ if (Math.abs(score) < SCORE_CLEANUP_THRESHOLD) {
163
+ this.scores.delete(peerId);
164
+ this.lastUpdateTime.delete(peerId);
165
+ } else {
166
+ this.scores.set(peerId, score);
167
+ this.lastUpdateTime.set(peerId, currentTime);
168
+ }
123
169
  }
124
170
  }
125
171
  }
126
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
+
193
+ removePeer(peerId: string): void {
194
+ this.scores.delete(peerId);
195
+ this.lastUpdateTime.delete(peerId);
196
+ }
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
+
127
216
  getScore(peerId: string): number {
128
- return this.scores.get(peerId) || 0;
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;
129
220
  }
130
221
 
131
222
  public getScoreState(peerId: string): PeerScoreState {
132
- // TODO(#11329): permanently store banned peers?
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.
133
225
  const score = this.getScore(peerId);
134
226
  if (score < MIN_SCORE_BEFORE_BAN) {
135
227
  return PeerScoreState.Banned;
@@ -143,7 +235,9 @@ export class PeerScoring {
143
235
  getStats(): { medianScore: number; healthyCount: number; disconnectCount: number; bannedCount: number } {
144
236
  const stateCounts = { healthy: 0, disconnect: 0, banned: 0 };
145
237
 
146
- for (const peerId of this.scores.keys()) {
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) {
147
241
  const state = this.getScoreState(peerId);
148
242
  switch (state) {
149
243
  case PeerScoreState.Healthy:
@@ -0,0 +1,194 @@
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_TXS | 10/s | 200/s | same |
18
+ | TX | 10/s | 200/s | same |
19
+
20
+ - Per-peer limit exceeded: `HighToleranceError` penalty + `RATE_LIMIT_EXCEEDED` status. Penalty fires inside `RequestResponseRateLimiter.allow()`, not the stream handler.
21
+ - Global limit exceeded: `RATE_LIMIT_EXCEEDED` status only (no peer penalty).
22
+
23
+ ### Response Status Byte (Requester Side)
24
+
25
+ | Rule | Consequence | File |
26
+ |------|-------------|------|
27
+ | First chunk must be exactly 1 byte | `ReqRespStatusError(UNKNOWN)` | `status.ts` |
28
+ | Byte must be valid `ReqRespStatus` enum (0-4, 126, 127) | `ReqRespStatusError(UNKNOWN)` | same |
29
+
30
+ Note: `prettyPrintReqRespStatus` is missing a `NOT_FOUND` case (minor logging bug).
31
+
32
+ ### Snappy Decompression (Requester Side)
33
+
34
+ Per-protocol size limits checked via preamble before decompression.
35
+
36
+ ### Timeouts (Requester Side)
37
+
38
+ | Timeout | Default | Penalty |
39
+ |---------|---------|---------|
40
+ | Individual request | 10s | HighToleranceError |
41
+ | Dial | 5s | HighToleranceError |
42
+
43
+ ### Error Penalty Categorization (Requester Side)
44
+
45
+ | Error Type | Severity |
46
+ |------------|----------|
47
+ | GOODBYE subprotocol errors | None |
48
+ | `AbortError` / connection close / muxer closed | None |
49
+ | `ECONNRESET` / `EPIPE` / `ECONNREFUSED` / `ERR_UNEXPECTED_EOF` | HighToleranceError |
50
+ | `ERR_UNSUPPORTED_PROTOCOL` | HighToleranceError |
51
+ | `IndividualReqRespTimeoutError` / `TimeoutError` | HighToleranceError |
52
+ | Catch-all | HighToleranceError |
53
+
54
+ ### Request Error Penalty (Responder Side)
55
+
56
+ | Error Type | Severity |
57
+ |------------|----------|
58
+ | `BADLY_FORMED_REQUEST` | LowToleranceError |
59
+ | All others | None |
60
+
61
+ ### Notes
62
+
63
+ - Request payloads are NOT snappy-compressed (asymmetric: only responses use snappy).
64
+
65
+ ---
66
+
67
+ ## Handshake Protocols
68
+
69
+ ### Connection-Level Gating (Before Any Handshake)
70
+
71
+ | Rule | Consequence | File |
72
+ |------|-------------|------|
73
+ | Deny inbound connection from IP/peerId with too many failed auth handshakes | Connection denied | `libp2p_service.ts` |
74
+ | Threshold: `p2pMaxFailedAuthAttemptsAllowed` (default 3) | Tracked per peerId AND per IP | `peer_manager.ts` |
75
+ | Failed auth entries expire after 1 hour | Peer can reconnect; no escalating penalty for repeat offenders | same |
76
+
77
+ ### Handshake Trigger Logic (`peer:connect`)
78
+
79
+ 1. `p2pDisableStatusHandshake` = true: no handshake
80
+ 2. `p2pAllowOnlyValidators` = false: STATUS handshake
81
+ 3. Peer is protected (trusted/private/preferred): STATUS handshake
82
+ 4. Otherwise: AUTH handshake (superset of STATUS)
83
+
84
+ Config constraint: `p2pDisableStatusHandshake && p2pAllowOnlyValidators` is disallowed.
85
+
86
+ ### STATUS Protocol (`/aztec/req/status/1.0.0`)
87
+
88
+ **Requester side** (`peer_manager.ts`):
89
+
90
+ | Rule | Consequence |
91
+ |------|-------------|
92
+ | Response status must be SUCCESS | Peer scheduled for disconnect |
93
+ | `compressedComponentsVersion` must match | Peer scheduled for disconnect |
94
+ | Any exception | Peer scheduled for disconnect |
95
+
96
+ `StatusMessage.validate()` currently only checks `compressedComponentsVersion`. Fields `latestBlockNumber`, `latestBlockHash`, `finalizedBlockNumber` are NOT validated (TODO in code).
97
+
98
+ **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.
99
+
100
+ **Deserialization bounds**: `MAX_VERSION_STRING_LENGTH` = 64 bytes, `MAX_BLOCK_HASH_STRING_LENGTH` = 128 bytes. Expected response size: 1 KB.
101
+
102
+ ### AUTH Protocol (`/aztec/req/auth/1.0.0`)
103
+
104
+ **Requester side** (`peer_manager.ts`):
105
+
106
+ | # | Rule | Consequence |
107
+ |---|------|-------------|
108
+ | 1 | Response status is SUCCESS | `markAuthHandshakeFailed` + disconnect |
109
+ | 2 | `compressedComponentsVersion` match | `markAuthHandshakeFailed` + disconnect |
110
+ | 3 | Valid ECDSA signature recovery from challenge response | `markAuthHandshakeFailed` + disconnect |
111
+ | 4 | Recovered address is a registered validator | `markAuthHandshakeFailed` + disconnect |
112
+ | 5 | Validator address not already authenticated to different peerId | Silent return (no disconnect, no failure marking -- peer stays connected but unauthenticated) |
113
+ | 6 | Any exception | `markAuthHandshakeFailed` + disconnect |
114
+
115
+ 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).
116
+
117
+ On success: peer added to authenticated maps, prior failures cleared (including IP-based ones -- shared-IP peers benefit from a legitimate validator's success).
118
+
119
+ **Responder side** (`validator-client/src/validator.ts` + `peer_manager.ts`):
120
+
121
+ | # | Rule | Consequence |
122
+ |---|------|-------------|
123
+ | 1 | Peer must be protected (`shouldTrustWithIdentity` in `peer_manager.ts`) | Returns empty buffer (SUCCESS status + empty payload -> requester gets parse error -> `markAuthHandshakeFailed`) |
124
+ | 2 | Node must have registered validator address | Returns empty buffer (same consequence) |
125
+
126
+ **Unauthenticated peer gossip**: when `p2pAllowOnlyValidators` is true, unauthenticated peers get `appSpecificScore = -Infinity`, completely excluding them from all gossip.
127
+
128
+ ### PING Protocol (`/aztec/req/ping/1.0.0`)
129
+
130
+ No validation on either side. Responder returns `Buffer.from('pong')`. Expected response: 1 KB.
131
+
132
+ ### GOODBYE Protocol (`/aztec/req/goodbye/1.0.0`)
133
+
134
+ **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.
135
+
136
+ **Requester**: response errors are never penalized (GOODBYE subprotocol exempt from error categorization).
137
+
138
+ ### Periodic Re-validation
139
+
140
+ | Rule | Interval | File |
141
+ |------|----------|------|
142
+ | Authenticated validators re-checked against current validator set | Every heartbeat (`peerCheckIntervalMS`) | `peer_manager.ts` |
143
+ | If validator address no longer registered, auth entry removed | Same | same |
144
+
145
+ Protected peers (private/trusted/preferred) are always considered "authenticated" without AUTH handshake.
146
+
147
+ ---
148
+
149
+ ## Block Data Protocols
150
+
151
+ ### BLOCK_TXS Protocol (`/aztec/req/block_txs/1.0.0`)
152
+
153
+ **Server side**:
154
+
155
+ | Rule | Consequence | File |
156
+ |------|-------------|------|
157
+ | Request must parse as `BlockTxsRequest` (Fr + TxHashArray + BitVector) | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block_txs/block_txs_handler.ts` |
158
+ | BitVector length: non-negative and <= `MAX_TXS_PER_BLOCK` (65536) | Deserialization throws -> `BADLY_FORMED_REQUEST` | `protocols/block_txs/bitvector.ts` |
159
+ | Archive root not found and no explicit txHashes | `NOT_FOUND` status | handler |
160
+ | Internal error during lookup | Unhandled exception -> stream abort (no `INTERNAL_ERROR` status) | handler |
161
+
162
+ Conditional registration: BLOCK_TXS handler only registered when `config.disableTransactions` is false. Otherwise peers get `ERR_UNSUPPORTED_PROTOCOL`.
163
+
164
+ **Requester side via `BatchTxRequester`** (separate validation path):
165
+
166
+ | Rule | Consequence | File |
167
+ |------|-------------|------|
168
+ | Non-SUCCESS status: `FAILURE`/`UNKNOWN` | HighToleranceError + "bad peer" tracking | `batch-tx-requester/batch_tx_requester.ts` |
169
+ | `RATE_LIMIT_EXCEEDED` | Peer marked rate-limited (cooldown) | same |
170
+ | `NOT_FOUND` / `BADLY_FORMED_REQUEST` / `INTERNAL_ERROR` | Falls through silently (no penalty) | same |
171
+ | Each tx validated (Metadata + Size + Data + Proof) | LowToleranceError per invalid tx; valid txs from same response still accepted | same |
172
+ | Archive root match + non-empty txIndices | No penalty on mismatch; peer not promoted to "smart" | same |
173
+
174
+ **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.
175
+
176
+ See [BatchTxRequester README](batch-tx-requester/README.md) for the full architecture (peer classification, worker model, wire protocol).
177
+
178
+ ### TX Protocol (`/aztec/req/tx/1.0.0`)
179
+
180
+ **Server side**:
181
+
182
+ | Rule | Consequence | File |
183
+ |------|-------------|------|
184
+ | Request must parse as `TxHashArray` | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/tx.ts` |
185
+
186
+ **Requester side** (validator registered at startup, not the default noop):
187
+
188
+ | Rule | Consequence | File |
189
+ |------|-------------|------|
190
+ | Each returned tx hash must be in the requested set | MidToleranceError | `libp2p_service.ts` (`validateRequestedTxs`) |
191
+ | Each tx passes well-formedness (Metadata + Size + Data + Proof) | LowToleranceError | same |
192
+
193
+ Snappy limit: `max(N, 1) * 512 + 1` KB.
194
+