@aztec/p2p 0.0.1-commit.993d52e → 0.0.1-commit.9a89641

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 (473) 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 +34 -19
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +120 -73
  13. package/dest/config.d.ts +160 -110
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +139 -49
  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 +274 -197
  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 +12 -5
  37. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  38. package/dest/mem_pools/instrumentation.js +38 -17
  39. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -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 +1 -7
  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/invalid_txs_after_mining_rule.d.ts +1 -1
  58. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +3 -4
  60. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +1 -1
  61. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
  62. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +6 -7
  63. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +1 -1
  64. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  65. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +6 -5
  66. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +41 -9
  67. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  68. package/dest/mem_pools/tx_pool_v2/interfaces.js +3 -1
  69. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +17 -8
  70. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  71. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +20 -7
  72. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +15 -1
  73. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  74. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +55 -41
  75. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +12 -4
  76. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  77. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +23 -6
  78. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +17 -3
  79. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  80. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +234 -120
  81. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -3
  82. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  83. package/dest/msg_validators/attestation_validator/attestation_validator.js +38 -15
  84. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
  85. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  86. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +4 -5
  87. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +11 -5
  88. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  89. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +11 -3
  90. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +11 -5
  91. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  92. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +23 -3
  93. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +35 -10
  94. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/proposal_validator/proposal_validator.js +128 -56
  96. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  97. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  98. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
  99. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
  100. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  101. package/dest/msg_validators/tx_validator/allowed_public_setup.js +25 -21
  102. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  103. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  104. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  105. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  106. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  107. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  108. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  109. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  110. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  111. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  112. package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
  113. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  114. package/dest/msg_validators/tx_validator/data_validator.js +36 -2
  115. package/dest/msg_validators/tx_validator/factory.d.ts +25 -7
  116. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  117. package/dest/msg_validators/tx_validator/factory.js +55 -16
  118. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  119. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  120. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  121. package/dest/msg_validators/tx_validator/gas_validator.d.ts +53 -7
  122. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  123. package/dest/msg_validators/tx_validator/gas_validator.js +88 -41
  124. package/dest/msg_validators/tx_validator/index.d.ts +4 -1
  125. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  126. package/dest/msg_validators/tx_validator/index.js +3 -0
  127. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  128. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  129. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  130. package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
  131. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  132. package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
  133. package/dest/msg_validators/tx_validator/timestamp_validator.js +1 -1
  134. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
  135. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  136. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
  137. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  138. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  139. package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
  140. package/dest/services/data_store.d.ts +1 -1
  141. package/dest/services/data_store.d.ts.map +1 -1
  142. package/dest/services/data_store.js +5 -5
  143. package/dest/services/discv5/discV5_service.d.ts +13 -2
  144. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  145. package/dest/services/discv5/discV5_service.js +119 -23
  146. package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
  147. package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
  148. package/dest/services/discv5/persisted_enr_store.js +145 -0
  149. package/dest/services/dummy_service.d.ts +15 -15
  150. package/dest/services/dummy_service.d.ts.map +1 -1
  151. package/dest/services/dummy_service.js +15 -16
  152. package/dest/services/encoding.d.ts +23 -6
  153. package/dest/services/encoding.d.ts.map +1 -1
  154. package/dest/services/encoding.js +32 -16
  155. package/dest/services/gossipsub/topic_score_params.d.ts +6 -12
  156. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  157. package/dest/services/gossipsub/topic_score_params.js +4 -14
  158. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  159. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  160. package/dest/services/libp2p/instrumentation.js +14 -0
  161. package/dest/services/libp2p/libp2p_service.d.ts +46 -47
  162. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  163. package/dest/services/libp2p/libp2p_service.js +460 -320
  164. package/dest/services/peer-manager/metrics.d.ts +3 -1
  165. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  166. package/dest/services/peer-manager/metrics.js +6 -0
  167. package/dest/services/peer-manager/peer_manager.d.ts +20 -3
  168. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  169. package/dest/services/peer-manager/peer_manager.js +83 -26
  170. package/dest/services/peer-manager/peer_scoring.d.ts +34 -2
  171. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  172. package/dest/services/peer-manager/peer_scoring.js +102 -13
  173. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -8
  174. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  175. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +94 -122
  176. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +10 -6
  177. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  178. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
  179. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  180. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
  181. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -11
  182. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  183. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +52 -15
  184. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
  185. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
  186. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
  187. package/dest/services/reqresp/config.d.ts +15 -3
  188. package/dest/services/reqresp/config.d.ts.map +1 -1
  189. package/dest/services/reqresp/config.js +11 -0
  190. package/dest/services/reqresp/interface.d.ts +16 -18
  191. package/dest/services/reqresp/interface.d.ts.map +1 -1
  192. package/dest/services/reqresp/interface.js +10 -20
  193. package/dest/services/reqresp/metrics.d.ts +1 -1
  194. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  195. package/dest/services/reqresp/metrics.js +0 -1
  196. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
  197. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  198. package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
  199. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  200. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  201. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
  202. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
  203. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  204. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +42 -24
  205. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  206. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  207. package/dest/services/reqresp/protocols/index.js +0 -1
  208. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  209. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  210. package/dest/services/reqresp/protocols/tx.js +1 -3
  211. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  212. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  213. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  214. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  215. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  216. package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -13
  217. package/dest/services/reqresp/reqresp.d.ts +7 -29
  218. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  219. package/dest/services/reqresp/reqresp.js +75 -216
  220. package/dest/services/service.d.ts +29 -12
  221. package/dest/services/service.d.ts.map +1 -1
  222. package/dest/services/tx_collection/config.d.ts +2 -23
  223. package/dest/services/tx_collection/config.d.ts.map +1 -1
  224. package/dest/services/tx_collection/config.js +2 -55
  225. package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
  226. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
  227. package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
  228. package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
  229. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  230. package/dest/services/tx_collection/file_store_tx_source.js +39 -29
  231. package/dest/services/tx_collection/index.d.ts +2 -3
  232. package/dest/services/tx_collection/index.d.ts.map +1 -1
  233. package/dest/services/tx_collection/index.js +0 -1
  234. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  235. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  236. package/dest/services/tx_collection/instrumentation.js +0 -2
  237. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  238. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  239. package/dest/services/tx_collection/request_tracker.js +84 -0
  240. package/dest/services/tx_collection/tx_collection.d.ts +36 -55
  241. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  242. package/dest/services/tx_collection/tx_collection.js +275 -119
  243. package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
  244. package/dest/services/tx_collection/tx_collection_sink.js +2 -2
  245. package/dest/services/tx_collection/tx_source.d.ts +6 -5
  246. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  247. package/dest/services/tx_collection/tx_source.js +13 -8
  248. package/dest/services/tx_file_store/tx_file_store.d.ts +1 -3
  249. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  250. package/dest/services/tx_file_store/tx_file_store.js +4 -14
  251. package/dest/services/tx_provider.d.ts +3 -1
  252. package/dest/services/tx_provider.d.ts.map +1 -1
  253. package/dest/services/tx_provider.js +3 -0
  254. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  255. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  256. package/dest/test-helpers/make-test-p2p-clients.js +5 -2
  257. package/dest/test-helpers/mock-pubsub.d.ts +23 -9
  258. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  259. package/dest/test-helpers/mock-pubsub.js +44 -44
  260. package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
  261. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  262. package/dest/test-helpers/reqresp-nodes.js +16 -18
  263. package/dest/test-helpers/test_tx_provider.d.ts +3 -1
  264. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
  265. package/dest/test-helpers/test_tx_provider.js +3 -0
  266. package/dest/test-helpers/testbench-utils.d.ts +15 -14
  267. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  268. package/dest/test-helpers/testbench-utils.js +51 -16
  269. package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
  270. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  271. package/dest/testbench/p2p_client_testbench_worker.js +104 -41
  272. package/dest/testbench/worker_client_manager.d.ts +12 -6
  273. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  274. package/dest/testbench/worker_client_manager.js +57 -11
  275. package/dest/util.d.ts +12 -7
  276. package/dest/util.d.ts.map +1 -1
  277. package/dest/util.js +35 -14
  278. package/dest/versioning.d.ts +3 -6
  279. package/dest/versioning.d.ts.map +1 -1
  280. package/dest/versioning.js +3 -24
  281. package/package.json +15 -16
  282. package/src/bootstrap/bootstrap.ts +17 -3
  283. package/src/client/factory.ts +62 -9
  284. package/src/client/interface.ts +48 -18
  285. package/src/client/p2p_client.ts +140 -106
  286. package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
  287. package/src/config.ts +241 -57
  288. package/src/errors/p2p-service.error.ts +11 -0
  289. package/src/errors/reqresp.error.ts +13 -19
  290. package/src/index.ts +0 -1
  291. package/src/mem_pools/attestation_pool/attestation_pool.ts +329 -243
  292. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +244 -69
  293. package/src/mem_pools/attestation_pool/mocks.ts +13 -8
  294. package/src/mem_pools/index.ts +0 -3
  295. package/src/mem_pools/instrumentation.ts +27 -17
  296. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
  297. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +7 -7
  298. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +4 -5
  299. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -2
  300. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  301. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +67 -0
  302. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +1 -3
  303. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -7
  304. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +5 -6
  305. package/src/mem_pools/tx_pool_v2/interfaces.ts +40 -8
  306. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +35 -13
  307. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +62 -41
  308. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +36 -7
  309. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +260 -124
  310. package/src/msg_validators/attestation_validator/README.md +49 -0
  311. package/src/msg_validators/attestation_validator/attestation_validator.ts +46 -14
  312. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +15 -7
  313. package/src/msg_validators/proposal_validator/README.md +123 -0
  314. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +26 -4
  315. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +43 -7
  316. package/src/msg_validators/proposal_validator/proposal_validator.ts +150 -58
  317. package/src/msg_validators/tx_validator/README.md +17 -3
  318. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
  319. package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
  320. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  321. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  322. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  323. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  324. package/src/msg_validators/tx_validator/data_validator.ts +44 -1
  325. package/src/msg_validators/tx_validator/factory.ts +66 -9
  326. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  327. package/src/msg_validators/tx_validator/gas_validator.ts +117 -39
  328. package/src/msg_validators/tx_validator/index.ts +3 -0
  329. package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
  330. package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
  331. package/src/msg_validators/tx_validator/timestamp_validator.ts +1 -1
  332. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
  333. package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
  334. package/src/services/data_store.ts +5 -13
  335. package/src/services/discv5/discV5_service.ts +126 -14
  336. package/src/services/discv5/persisted_enr_store.ts +158 -0
  337. package/src/services/dummy_service.ts +20 -39
  338. package/src/services/encoding.ts +35 -19
  339. package/src/services/gossipsub/README.md +33 -11
  340. package/src/services/gossipsub/topic_score_params.ts +9 -18
  341. package/src/services/libp2p/instrumentation.ts +14 -0
  342. package/src/services/libp2p/libp2p_service.ts +508 -358
  343. package/src/services/peer-manager/metrics.ts +7 -0
  344. package/src/services/peer-manager/peer_manager.ts +91 -25
  345. package/src/services/peer-manager/peer_scoring.ts +102 -8
  346. package/src/services/reqresp/README.md +194 -0
  347. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  348. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +91 -137
  349. package/src/services/reqresp/batch-tx-requester/interface.ts +13 -5
  350. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
  351. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
  352. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
  353. package/src/services/reqresp/config.ts +19 -2
  354. package/src/services/reqresp/interface.ts +21 -47
  355. package/src/services/reqresp/metrics.ts +0 -1
  356. package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
  357. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
  358. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
  359. package/src/services/reqresp/protocols/index.ts +0 -1
  360. package/src/services/reqresp/protocols/tx.ts +1 -3
  361. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  362. package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -13
  363. package/src/services/reqresp/reqresp.ts +87 -260
  364. package/src/services/service.ts +35 -28
  365. package/src/services/tx_collection/config.ts +3 -80
  366. package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
  367. package/src/services/tx_collection/file_store_tx_source.ts +43 -31
  368. package/src/services/tx_collection/index.ts +1 -6
  369. package/src/services/tx_collection/instrumentation.ts +1 -7
  370. package/src/services/tx_collection/request_tracker.ts +127 -0
  371. package/src/services/tx_collection/tx_collection.ts +331 -176
  372. package/src/services/tx_collection/tx_collection_sink.ts +2 -2
  373. package/src/services/tx_collection/tx_source.ts +10 -8
  374. package/src/services/tx_file_store/tx_file_store.ts +5 -17
  375. package/src/services/tx_provider.ts +5 -0
  376. package/src/test-helpers/make-test-p2p-clients.ts +4 -1
  377. package/src/test-helpers/mock-pubsub.ts +46 -60
  378. package/src/test-helpers/reqresp-nodes.ts +13 -23
  379. package/src/test-helpers/test_tx_provider.ts +5 -0
  380. package/src/test-helpers/testbench-utils.ts +64 -28
  381. package/src/testbench/p2p_client_testbench_worker.ts +111 -57
  382. package/src/testbench/worker_client_manager.ts +72 -25
  383. package/src/util.ts +33 -18
  384. package/src/versioning.ts +3 -33
  385. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
  386. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
  387. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -304
  388. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
  389. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
  390. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
  391. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
  392. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  393. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
  394. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
  395. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
  396. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
  397. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
  398. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
  399. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
  400. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
  401. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
  402. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
  403. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
  404. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
  405. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
  406. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
  407. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
  408. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
  409. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
  410. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
  411. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
  412. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
  413. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
  414. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
  415. package/dest/mem_pools/tx_pool/index.d.ts +0 -3
  416. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  417. package/dest/mem_pools/tx_pool/index.js +0 -2
  418. package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
  419. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  420. package/dest/mem_pools/tx_pool/priority.js +0 -15
  421. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
  422. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  423. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  424. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  425. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  426. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
  427. package/dest/msg_validators/clock_tolerance.d.ts +0 -21
  428. package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
  429. package/dest/msg_validators/clock_tolerance.js +0 -37
  430. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -24
  431. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
  432. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -378
  433. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
  434. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  435. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
  436. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  437. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  438. package/dest/services/reqresp/protocols/block.js +0 -32
  439. package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -54
  440. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
  441. package/dest/services/tx_collection/fast_tx_collection.js +0 -327
  442. package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
  443. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
  444. package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
  445. package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -49
  446. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
  447. package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
  448. package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
  449. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
  450. package/dest/services/tx_collection/slow_tx_collection.js +0 -211
  451. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -345
  452. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
  453. package/src/mem_pools/tx_pool/README.md +0 -270
  454. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
  455. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
  456. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
  457. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
  458. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
  459. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
  460. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
  461. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
  462. package/src/mem_pools/tx_pool/index.ts +0 -2
  463. package/src/mem_pools/tx_pool/priority.ts +0 -20
  464. package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
  465. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
  466. package/src/msg_validators/clock_tolerance.ts +0 -51
  467. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -373
  468. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
  469. package/src/services/reqresp/protocols/block.ts +0 -37
  470. package/src/services/tx_collection/fast_tx_collection.ts +0 -387
  471. package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
  472. package/src/services/tx_collection/proposal_tx_collector.ts +0 -113
  473. package/src/services/tx_collection/slow_tx_collection.ts +0 -266
@@ -1,14 +1,15 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
- import { Fr } from '@aztec/foundation/curves/bn254';
3
+ import { compactArray, maxBy, merge } from '@aztec/foundation/collection';
4
4
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
5
5
  import { RunningPromise } from '@aztec/foundation/running-promise';
6
6
  import { Timer } from '@aztec/foundation/timer';
7
7
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
8
8
  import { protocolContractsHash } from '@aztec/protocol-contracts';
9
- import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
9
+ import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
10
+ import { DEFAULT_MAX_BLOCKS_PER_CHECKPOINT } from '@aztec/stdlib/config';
10
11
  import type { ContractDataSource } from '@aztec/stdlib/contract';
11
- import { GasFees } from '@aztec/stdlib/gas';
12
+ import { type BlockMinFeesProvider, GasFees, getNetworkTxGasLimits } from '@aztec/stdlib/gas';
12
13
  import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
13
14
  import {
14
15
  BlockProposal,
@@ -17,16 +18,18 @@ import {
17
18
  type CheckpointProposalCore,
18
19
  type Gossipable,
19
20
  P2PMessage,
20
- type ValidationResult as P2PValidationResult,
21
21
  PeerErrorSeverity,
22
+ PeerErrorSeverityByHarshness,
22
23
  TopicType,
23
24
  createTopicString,
24
25
  getTopicsForConfig,
25
26
  metricsTopicStrToLabels,
26
27
  } from '@aztec/stdlib/p2p';
28
+ import { ConsensusTimetable, getDefaultCheckpointProposalSyncGrace } from '@aztec/stdlib/timetable';
27
29
  import { MerkleTreeId } from '@aztec/stdlib/trees';
28
- import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
30
+ import { Tx, type TxValidationResult } from '@aztec/stdlib/tx';
29
31
  import type { UInt64 } from '@aztec/stdlib/types';
32
+ import { InvalidBlockProposalTxsError } from '@aztec/stdlib/validators';
30
33
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
31
34
  import {
32
35
  Attributes,
@@ -50,13 +53,15 @@ import { yamux } from '@chainsafe/libp2p-yamux';
50
53
  import { bootstrap } from '@libp2p/bootstrap';
51
54
  import { identify } from '@libp2p/identify';
52
55
  import { type Message, type MultiaddrConnection, type PeerId, TopicValidatorResult } from '@libp2p/interface';
53
- import type { ConnectionManager } from '@libp2p/interface-internal';
56
+ import type { AddressManager, ConnectionManager } from '@libp2p/interface-internal';
54
57
  import { mplex } from '@libp2p/mplex';
55
58
  import { tcp } from '@libp2p/tcp';
59
+ import { multiaddr } from '@multiformats/multiaddr';
56
60
  import { ENR } from '@nethermindeth/enr';
57
61
  import { createLibp2p } from 'libp2p';
58
62
 
59
63
  import type { P2PConfig } from '../../config.js';
64
+ import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
60
65
  import type { MemPools } from '../../mem_pools/interface.js';
61
66
  import {
62
67
  BlockProposalValidator,
@@ -72,38 +77,34 @@ import {
72
77
  createFirstStageTxValidationsForGossipedTransactions,
73
78
  createSecondStageTxValidationsForGossipedTransactions,
74
79
  createTxValidatorForBlockProposalReceivedTxs,
75
- createTxValidatorForReqResponseReceivedTxs,
76
80
  } from '../../msg_validators/tx_validator/factory.js';
81
+ import { TxValidationCache } from '../../msg_validators/tx_validator/tx_validation_cache.js';
77
82
  import { GossipSubEvent } from '../../types/index.js';
78
83
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
79
84
  import { getVersions } from '../../versioning.js';
80
85
  import { AztecDatastore } from '../data_store.js';
81
86
  import { DiscV5Service } from '../discv5/discV5_service.js';
82
- import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
87
+ import { SnappyTransform, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
83
88
  import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
84
89
  import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
85
90
  import type { PeerManagerInterface } from '../peer-manager/interface.js';
86
91
  import { PeerManager } from '../peer-manager/peer_manager.js';
87
92
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
88
93
  import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
89
- import type { P2PReqRespConfig } from '../reqresp/config.js';
94
+ import { type P2PReqRespConfig, YAMUX_MAX_MESSAGE_SIZE_BYTES } from '../reqresp/config.js';
90
95
  import {
91
96
  AuthRequest,
92
97
  BlockTxsRequest,
93
98
  BlockTxsResponse,
94
- DEFAULT_SUB_PROTOCOL_VALIDATORS,
95
99
  type ReqRespInterface,
96
100
  type ReqRespResponse,
97
101
  ReqRespSubProtocol,
98
102
  type ReqRespSubProtocolHandler,
99
103
  type ReqRespSubProtocolHandlers,
100
- type ReqRespSubProtocolValidators,
101
104
  StatusMessage,
102
- type SubProtocolMap,
103
105
  ValidationError,
104
106
  pingHandler,
105
107
  reqGoodbyeHandler,
106
- reqRespBlockHandler,
107
108
  reqRespBlockTxsHandler,
108
109
  reqRespStatusHandler,
109
110
  reqRespTxHandler,
@@ -111,13 +112,33 @@ import {
111
112
  import { ReqResp } from '../reqresp/reqresp.js';
112
113
  import type {
113
114
  P2PBlockReceivedCallback,
115
+ P2PCheckpointAttestationCallback,
114
116
  P2PCheckpointReceivedCallback,
115
117
  P2PDuplicateAttestationCallback,
118
+ P2POversizedProposalCallback,
116
119
  P2PService,
117
120
  PeerDiscoveryService,
118
121
  } from '../service.js';
119
122
  import { P2PInstrumentation } from './instrumentation.js';
120
123
 
124
+ /**
125
+ * Builds the {@link ConsensusTimetable} shared by the gossip validators for proposal/attestation receive-window
126
+ * bounds. Derived purely from protocol slot-timing constants plus the block sub-slot duration and the consensus
127
+ * materialization grace, so every node agrees on these bounds without depending on proposer operational budgets.
128
+ */
129
+ function buildConsensusTimetable(
130
+ config: P2PConfig,
131
+ l1Constants: ReturnType<EpochCacheInterface['getL1Constants']>,
132
+ ): ConsensusTimetable {
133
+ const blockDuration = config.blockDurationMs / 1000;
134
+ return new ConsensusTimetable({
135
+ l1Constants,
136
+ blockDuration,
137
+ checkpointProposalSyncGrace:
138
+ config.checkpointProposalSyncGraceSeconds ?? getDefaultCheckpointProposalSyncGrace(blockDuration),
139
+ });
140
+ }
141
+
121
142
  interface ValidationResult {
122
143
  name: string;
123
144
  isValid: TxValidationResult;
@@ -129,7 +150,7 @@ type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: Vali
129
150
  // REFACTOR: Unify with the type above
130
151
  type ReceivedMessageValidationResult<T, M = undefined> =
131
152
  | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
132
- | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
153
+ | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M; severity: PeerErrorSeverity };
133
154
 
134
155
  /**
135
156
  * Lib P2P implementation of the P2PService interface.
@@ -146,8 +167,6 @@ export class LibP2PService extends WithTracer implements P2PService {
146
167
  private protocolVersion = '';
147
168
  private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
148
169
 
149
- private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
150
-
151
170
  /** Callback invoked when a duplicate proposal is detected (triggers slashing). */
152
171
  private duplicateProposalCallback?: (info: {
153
172
  slot: SlotNumber;
@@ -155,9 +174,15 @@ export class LibP2PService extends WithTracer implements P2PService {
155
174
  type: 'checkpoint' | 'block';
156
175
  }) => void;
157
176
 
177
+ /** Callback invoked when an oversized block proposal is stored as slashing evidence (triggers slashing). */
178
+ private oversizedProposalCallback?: P2POversizedProposalCallback;
179
+
158
180
  /** Callback invoked when a duplicate attestation is detected (triggers slashing). */
159
181
  private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
160
182
 
183
+ /** Callback invoked when a valid checkpoint attestation is accepted into the pool. */
184
+ private checkpointAttestationCallback?: P2PCheckpointAttestationCallback;
185
+
161
186
  /**
162
187
  * Callback for when a block is received from a peer.
163
188
  * @param block - The block received from the peer.
@@ -170,10 +195,19 @@ export class LibP2PService extends WithTracer implements P2PService {
170
195
  * @param checkpoint - The checkpoint proposal received from the peer.
171
196
  * @returns The attestations for the checkpoint, if any.
172
197
  */
173
- private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
198
+ private allNodesCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
199
+ /**
200
+ * Callback for when a checkpoint proposal is received - specifically for validators - from a peer.
201
+ * @param checkpoint - The checkpoint proposal received from the peer.
202
+ * @returns The attestations for the checkpoint, if any.
203
+ */
204
+ private validatorCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
174
205
 
175
206
  private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
176
207
 
208
+ private ipChangedHandler?: (ip: string) => void;
209
+ private discoveredP2pIp?: string;
210
+
177
211
  private instrumentation: P2PInstrumentation;
178
212
 
179
213
  private telemetry: TelemetryClient;
@@ -191,8 +225,10 @@ export class LibP2PService extends WithTracer implements P2PService {
191
225
  private epochCache: EpochCacheInterface,
192
226
  private proofVerifier: ClientProtocolCircuitVerifier,
193
227
  private worldStateSynchronizer: WorldStateSynchronizer,
228
+ private blockMinFeesProvider: BlockMinFeesProvider,
194
229
  telemetry: TelemetryClient,
195
230
  logger: Logger = createLogger('p2p:libp2p_service'),
231
+ private txValidationCache?: TxValidationCache,
196
232
  ) {
197
233
  super(telemetry, 'LibP2PService');
198
234
  this.telemetry = telemetry;
@@ -222,40 +258,66 @@ export class LibP2PService extends WithTracer implements P2PService {
222
258
  this.protocolVersion,
223
259
  );
224
260
 
225
- this.blockProposalValidator = new BlockProposalValidator(epochCache, {
226
- txsPermitted: !config.disableTransactions,
227
- maxTxsPerBlock: config.maxTxsPerBlock,
228
- });
229
- this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
261
+ // Build the consensus timetable once from protocol slot-timing constants and inject it into every
262
+ // validator so they share one set of receive-window bounds, independent of proposer operational budgets.
263
+ const consensusTimetable = buildConsensusTimetable(config, epochCache.getL1Constants());
264
+ const proposalValidatorOpts = {
230
265
  txsPermitted: !config.disableTransactions,
231
- maxTxsPerBlock: config.maxTxsPerBlock,
232
- });
266
+ maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
267
+ maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
268
+ skipSlotValidation: config.skipProposalSlotValidation,
269
+ signatureContext: {
270
+ chainId: config.l1ChainId,
271
+ rollupAddress: config.rollupAddress,
272
+ },
273
+ clockDisparityMs: config.maxGossipClockDisparityMs,
274
+ };
275
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, consensusTimetable, proposalValidatorOpts);
276
+ this.checkpointProposalValidator = new CheckpointProposalValidator(
277
+ epochCache,
278
+ consensusTimetable,
279
+ proposalValidatorOpts,
280
+ );
281
+ const attestationValidatorOpts = {
282
+ signatureContext: proposalValidatorOpts.signatureContext,
283
+ clockDisparityMs: config.maxGossipClockDisparityMs,
284
+ };
233
285
  this.checkpointAttestationValidator = config.fishermanMode
234
- ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
235
- : new CheckpointAttestationValidator(epochCache);
286
+ ? new FishermanAttestationValidator(
287
+ epochCache,
288
+ consensusTimetable,
289
+ mempools.attestationPool,
290
+ telemetry,
291
+ attestationValidatorOpts,
292
+ )
293
+ : new CheckpointAttestationValidator(epochCache, consensusTimetable, attestationValidatorOpts);
236
294
 
237
295
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
238
296
 
239
297
  this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
240
- this.logger.debug(
241
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
298
+ this.logger.warn(
299
+ `Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
242
300
  { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
243
301
  );
244
- return false;
302
+ return true;
245
303
  };
246
304
 
247
- this.checkpointReceivedCallback = (
248
- checkpoint: CheckpointProposalCore,
305
+ this.allNodesCheckpointReceivedCallback = (
306
+ _checkpoint: CheckpointProposalCore,
307
+ ): Promise<CheckpointAttestation[] | undefined> => {
308
+ throw new CheckpointProposalReceivedCallbackNotRegisteredError();
309
+ };
310
+
311
+ this.validatorCheckpointReceivedCallback = (
312
+ _checkpoint: CheckpointProposalCore,
249
313
  ): Promise<CheckpointAttestation[] | undefined> => {
250
- this.logger.debug(
251
- `Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
252
- );
253
314
  return Promise.resolve(undefined);
254
315
  };
255
316
  }
256
317
 
257
- public updateConfig(config: Partial<P2PReqRespConfig>) {
318
+ public updateConfig(config: Partial<P2PReqRespConfig & Pick<P2PConfig, 'skipIncomingProposals'>>) {
258
319
  this.reqresp.updateConfig(config);
320
+ this.config = merge(this.config, config);
259
321
  }
260
322
 
261
323
  /**
@@ -274,9 +336,11 @@ export class LibP2PService extends WithTracer implements P2PService {
274
336
  proofVerifier: ClientProtocolCircuitVerifier;
275
337
  worldStateSynchronizer: WorldStateSynchronizer;
276
338
  peerStore: AztecAsyncKVStore;
339
+ blockMinFeesProvider: BlockMinFeesProvider;
277
340
  telemetry: TelemetryClient;
278
341
  logger: Logger;
279
342
  packageVersion: string;
343
+ txValidationCache?: TxValidationCache;
280
344
  },
281
345
  ) {
282
346
  const {
@@ -286,9 +350,11 @@ export class LibP2PService extends WithTracer implements P2PService {
286
350
  mempools,
287
351
  proofVerifier,
288
352
  peerStore,
353
+ blockMinFeesProvider,
289
354
  telemetry,
290
355
  logger,
291
356
  packageVersion,
357
+ txValidationCache,
292
358
  } = deps;
293
359
  const { p2pPort, maxPeerCount, listenAddress } = config;
294
360
  const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
@@ -303,6 +369,7 @@ export class LibP2PService extends WithTracer implements P2PService {
303
369
  packageVersion,
304
370
  telemetry,
305
371
  createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
372
+ peerStore,
306
373
  );
307
374
 
308
375
  // Seed libp2p's bootstrap discovery with private and trusted peers
@@ -317,34 +384,49 @@ export class LibP2PService extends WithTracer implements P2PService {
317
384
  const protocolVersion = compressComponentVersions(versions);
318
385
 
319
386
  const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
320
- const directPeers = (
387
+ const directPeers = compactArray(
321
388
  await Promise.all(
322
389
  preferredPeersEnrs.map(async enr => {
323
- const peerId = await enr.peerId();
324
- const address = enr.getLocationMultiaddr('tcp');
325
- if (address === undefined) {
326
- throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
390
+ try {
391
+ const peerId = await enr.peerId();
392
+ const address = enr.getLocationMultiaddr('tcp');
393
+ if (address === undefined) {
394
+ throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
395
+ }
396
+ return {
397
+ id: peerId,
398
+ addrs: [address],
399
+ };
400
+ } catch (err) {
401
+ // A malformed configured ENR shouldn't abort node setup — skip it and log.
402
+ logger.warn(`Skipping preferred peer with invalid ENR`, { err });
403
+ return undefined;
327
404
  }
328
- return {
329
- id: peerId,
330
- addrs: [address],
331
- };
332
405
  }),
333
- )
334
- ).filter(peer => peer !== undefined);
406
+ ),
407
+ );
335
408
 
336
409
  const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
337
410
 
338
- // Create dynamic topic score params based on network configuration
411
+ // Create dynamic topic score params based on network configuration. Scoring uses the network-wide
412
+ // max-blocks-per-checkpoint config value directly to size expected per-slot message rates; these are
413
+ // peer-rate thresholds, not consensus deadlines, so they need no proposer operational budgets.
339
414
  const l1Constants = epochCache.getL1Constants();
340
415
  const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
341
416
  slotDurationMs: l1Constants.slotDuration * 1000,
342
417
  heartbeatIntervalMs: config.gossipsubInterval,
343
418
  targetCommitteeSize: l1Constants.targetCommitteeSize,
344
- blockDurationMs: config.blockDurationMs,
419
+ maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint ?? DEFAULT_MAX_BLOCKS_PER_CHECKPOINT,
345
420
  expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
346
421
  });
347
422
 
423
+ // Restrict gossipsub to exactly the topics we subscribe to. Without this, an arbitrary-topic
424
+ // message is transformed, msg-id'd and inserted into the seenCache before the subscription check,
425
+ // so a crafted topic colliding on msg id can suppress a real message as a duplicate.
426
+ const allowedTopics = getTopicsForConfig(config.disableTransactions).map(topic =>
427
+ createTopicString(topic, protocolVersion),
428
+ );
429
+
348
430
  const node = await createLibp2p({
349
431
  start: false,
350
432
  peerId,
@@ -376,7 +458,8 @@ export class LibP2PService extends WithTracer implements P2PService {
376
458
  ],
377
459
  datastore,
378
460
  peerDiscovery,
379
- streamMuxers: [yamux(), mplex()],
461
+ // Pin the yamux frame size: MAX_REQRESP_REQUEST_SIZE_BYTES relies on a reqresp request fitting in one frame.
462
+ streamMuxers: [yamux({ maxMessageSize: YAMUX_MAX_MESSAGE_SIZE_BYTES }), mplex()],
380
463
  connectionEncryption: [noise()],
381
464
  connectionManager: {
382
465
  minConnections: 0, // Disable libp2p peer dialing, we do it manually
@@ -390,7 +473,7 @@ export class LibP2PService extends WithTracer implements P2PService {
390
473
  },
391
474
  connectionGater: {
392
475
  denyInboundConnection: (maConn: MultiaddrConnection) => {
393
- const allowed = peerManager.isNodeAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
476
+ const allowed = peerManager.isAddressAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
394
477
  if (allowed) {
395
478
  return false;
396
479
  }
@@ -401,7 +484,7 @@ export class LibP2PService extends WithTracer implements P2PService {
401
484
  denyInboundEncryptedConnection: (peerId: PeerId, _maConn: MultiaddrConnection) => {
402
485
  //NOTE: it is not necessary to check address here because this was already done by
403
486
  // denyInboundConnection
404
- const allowed = peerManager.isNodeAllowedToConnect(peerId);
487
+ const allowed = peerManager.isPeerAllowedToConnect(peerId);
405
488
  if (allowed) {
406
489
  return false;
407
490
  }
@@ -429,9 +512,13 @@ export class LibP2PService extends WithTracer implements P2PService {
429
512
  mcacheLength: config.gossipsubMcacheLength,
430
513
  mcacheGossip: config.gossipsubMcacheGossip,
431
514
  seenTTL: config.gossipsubSeenTTL,
515
+ allowedTopics,
516
+ // No fastMsgIdFn: the fast-path dedup cache keys on a non-cryptographic 64-bit hash of the
517
+ // raw data only (no topic), so a collision — accidental or engineered via a weak seed — drops
518
+ // a different message with no fallback to the full id. Dedup instead rests solely on the
519
+ // cryptographic, topic-framed msgIdFn below.
432
520
  msgIdFn: getMsgIdFn,
433
521
  msgIdToStrFn: msgIdToStrFn,
434
- fastMsgIdFn: fastMsgIdFn,
435
522
  dataTransform: new SnappyTransform(),
436
523
  metricsRegister: otelMetricsAdapter,
437
524
  metricsTopicStrToLabel: metricsTopicStrToLabels(protocolVersion),
@@ -443,8 +530,9 @@ export class LibP2PService extends WithTracer implements P2PService {
443
530
  topics: topicScoreParams,
444
531
  }),
445
532
  }) as (components: GossipSubComponents) => GossipSub,
446
- components: (components: { connectionManager: ConnectionManager }) => ({
533
+ components: (components: { connectionManager: ConnectionManager; addressManager: AddressManager }) => ({
447
534
  connectionManager: components.connectionManager,
535
+ addressManager: components.addressManager,
448
536
  }),
449
537
  },
450
538
  logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
@@ -466,6 +554,9 @@ export class LibP2PService extends WithTracer implements P2PService {
466
554
  epochCache,
467
555
  );
468
556
 
557
+ // Gate req/resp data protocols for unauthenticated peers when p2pAllowOnlyValidators is enabled
558
+ reqresp.setShouldRejectPeer(peerId => peerManager.shouldDisableP2PGossip(peerId));
559
+
469
560
  // Configure application-specific scoring for gossipsub.
470
561
  // The weight scales app score to align with gossipsub thresholds:
471
562
  // - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
@@ -486,8 +577,10 @@ export class LibP2PService extends WithTracer implements P2PService {
486
577
  epochCache,
487
578
  proofVerifier,
488
579
  worldStateSynchronizer,
580
+ blockMinFeesProvider,
489
581
  telemetry,
490
582
  logger,
583
+ txValidationCache,
491
584
  );
492
585
  }
493
586
 
@@ -501,24 +594,21 @@ export class LibP2PService extends WithTracer implements P2PService {
501
594
  throw new Error('P2P service already started');
502
595
  }
503
596
 
504
- // Get listen & announce addresses for logging
505
597
  const { p2pIp, p2pPort } = this.config;
506
- if (!p2pIp) {
507
- throw new Error('Announce address not provided.');
598
+ if (!p2pIp && !this.config.queryForIp) {
599
+ throw new Error('Announce address not provided and queryForIp is not enabled.');
508
600
  }
509
- const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
601
+ const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
510
602
 
511
603
  // Create request response protocol handlers
512
604
  const txHandler = reqRespTxHandler(this.mempools);
513
605
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
514
- const blockHandler = reqRespBlockHandler(this.archiver);
515
606
  const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
516
607
 
517
608
  const requestResponseHandlers: Partial<ReqRespSubProtocolHandlers> = {
518
609
  [ReqRespSubProtocol.PING]: pingHandler,
519
610
  [ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
520
611
  [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
521
- [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
522
612
  };
523
613
 
524
614
  if (!this.config.disableTransactions) {
@@ -534,17 +624,9 @@ export class LibP2PService extends WithTracer implements P2PService {
534
624
  requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
535
625
  }
536
626
 
537
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
538
- const reqrespSubProtocolValidators = {
539
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
540
- [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
541
- [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
542
- [ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
543
- };
544
-
545
627
  await this.peerManager.initializePeers();
546
628
 
547
- await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
629
+ await this.reqresp.start(requestResponseHandlers);
548
630
 
549
631
  await this.node.start();
550
632
 
@@ -560,6 +642,38 @@ export class LibP2PService extends WithTracer implements P2PService {
560
642
  if (!this.config.p2pDiscoveryDisabled) {
561
643
  await this.peerDiscoveryService.start();
562
644
  }
645
+
646
+ // Bridge discv5 IP changes to libp2p's AddressManager so peers see the updated address
647
+ if (this.config.queryForIp) {
648
+ this.discoveredP2pIp = this.config.p2pIp;
649
+ this.logger.info('IP change tracking enabled, bridging discv5 IP updates to libp2p AddressManager');
650
+ this.ipChangedHandler = (ip: string) => {
651
+ const addressManager = this.node.services.components.addressManager;
652
+ const newAddr = multiaddr(convertToMultiaddr(ip, this.config.p2pPort, 'tcp'));
653
+ const previousIp = this.discoveredP2pIp;
654
+
655
+ if (previousIp) {
656
+ const oldAddr = multiaddr(convertToMultiaddr(previousIp, this.config.p2pPort, 'tcp'));
657
+ addressManager.removeObservedAddr(oldAddr);
658
+ this.logger.info('Libp2p announce address updated due to IP change', {
659
+ previousIp,
660
+ newIp: ip,
661
+ newMultiaddr: newAddr.toString(),
662
+ });
663
+ } else {
664
+ this.logger.info('Libp2p announce address set from initial discv5 IP discovery', {
665
+ ip,
666
+ multiaddr: newAddr.toString(),
667
+ });
668
+ }
669
+
670
+ addressManager.addObservedAddr(newAddr);
671
+ addressManager.confirmObservedAddr(newAddr);
672
+ this.discoveredP2pIp = ip;
673
+ };
674
+ this.peerDiscoveryService.on('ip:changed', this.ipChangedHandler);
675
+ }
676
+
563
677
  this.discoveryRunningPromise = new RunningPromise(
564
678
  async () => {
565
679
  await this.peerManager.heartbeat();
@@ -585,6 +699,11 @@ export class LibP2PService extends WithTracer implements P2PService {
585
699
  // Remove gossip sub listener
586
700
  this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
587
701
 
702
+ if (this.ipChangedHandler) {
703
+ this.peerDiscoveryService.removeListener('ip:changed', this.ipChangedHandler);
704
+ this.ipChangedHandler = undefined;
705
+ }
706
+
588
707
  // Stop peer manager
589
708
  this.logger.debug('Stopping peer manager...');
590
709
  await this.peerManager.stop();
@@ -599,12 +718,8 @@ export class LibP2PService extends WithTracer implements P2PService {
599
718
  this.logger.info('LibP2P service stopped');
600
719
  }
601
720
 
602
- addReqRespSubProtocol(
603
- subProtocol: ReqRespSubProtocol,
604
- handler: ReqRespSubProtocolHandler,
605
- validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
606
- ): Promise<void> {
607
- return this.reqresp.addSubProtocol(subProtocol, handler, validator);
721
+ addReqRespSubProtocol(subProtocol: ReqRespSubProtocol, handler: ReqRespSubProtocolHandler): Promise<void> {
722
+ return this.reqresp.addSubProtocol(subProtocol, handler);
608
723
  }
609
724
 
610
725
  public registerThisValidatorAddresses(address: EthAddress[]): void {
@@ -632,20 +747,6 @@ export class LibP2PService extends WithTracer implements P2PService {
632
747
  setImmediate(() => void safeJob());
633
748
  }
634
749
 
635
- /**
636
- * Send a batch of requests to peers, and return the responses
637
- * @param protocol - The request response protocol to use
638
- * @param requests - The requests to send to the peers
639
- * @returns The responses to the requests
640
- */
641
- sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
642
- protocol: SubProtocol,
643
- requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
644
- pinnedPeerId: PeerId | undefined,
645
- ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]> {
646
- return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
647
- }
648
-
649
750
  public sendRequestToPeer(
650
751
  peerId: PeerId,
651
752
  subProtocol: ReqRespSubProtocol,
@@ -667,8 +768,12 @@ export class LibP2PService extends WithTracer implements P2PService {
667
768
  this.blockReceivedCallback = callback;
668
769
  }
669
770
 
670
- public registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
671
- this.checkpointReceivedCallback = callback;
771
+ public registerValidatorCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
772
+ this.validatorCheckpointReceivedCallback = callback;
773
+ }
774
+
775
+ public registerAllNodesCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
776
+ this.allNodesCheckpointReceivedCallback = callback;
672
777
  }
673
778
 
674
779
  /**
@@ -681,6 +786,13 @@ export class LibP2PService extends WithTracer implements P2PService {
681
786
  this.duplicateProposalCallback = callback;
682
787
  }
683
788
 
789
+ /**
790
+ * Registers a callback to be invoked when an oversized block proposal is stored as slashing evidence.
791
+ */
792
+ public registerOversizedProposalCallback(callback: P2POversizedProposalCallback): void {
793
+ this.oversizedProposalCallback = callback;
794
+ }
795
+
684
796
  /**
685
797
  * Registers a callback to be invoked when a duplicate attestation is detected.
686
798
  * A validator signing attestations for different proposals at the same slot.
@@ -690,6 +802,10 @@ export class LibP2PService extends WithTracer implements P2PService {
690
802
  this.duplicateAttestationCallback = callback;
691
803
  }
692
804
 
805
+ public registerCheckpointAttestationCallback(callback: P2PCheckpointAttestationCallback): void {
806
+ this.checkpointAttestationCallback = callback;
807
+ }
808
+
693
809
  /**
694
810
  * Subscribes to a topic.
695
811
  * @param topic - The topic to subscribe to.
@@ -754,6 +870,9 @@ export class LibP2PService extends WithTracer implements P2PService {
754
870
  if (!validator || !validator.addMessage(msgId)) {
755
871
  this.instrumentation.incMessagePrevalidationStatus(false, topicType);
756
872
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
873
+ if (topicType === TopicType.tx) {
874
+ this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
875
+ }
757
876
  return { result: false, topicType };
758
877
  }
759
878
 
@@ -815,6 +934,15 @@ export class LibP2PService extends WithTracer implements P2PService {
815
934
 
816
935
  // Process the message, optionally within a linked span for trace propagation
817
936
  const processMessage = async () => {
937
+ if (
938
+ this.config.skipIncomingProposals &&
939
+ (msg.topic === this.topicStrings[TopicType.block_proposal] ||
940
+ msg.topic === this.topicStrings[TopicType.checkpoint_proposal])
941
+ ) {
942
+ this.logger.warn(`Ignoring incoming proposal (skipIncomingProposals is set)`, { topic: msg.topic });
943
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
944
+ return;
945
+ }
818
946
  if (msg.topic === this.topicStrings[TopicType.tx]) {
819
947
  await this.handleGossipedTx(p2pMessage.payload, msgId, source);
820
948
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
@@ -880,30 +1008,67 @@ export class LibP2PService extends WithTracer implements P2PService {
880
1008
  source: PeerId,
881
1009
  topicType: TopicType,
882
1010
  ): Promise<ReceivedMessageValidationResult<T, M>> {
883
- let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
1011
+ // Default to reject result with a penalty if validation function throws an error
1012
+ let resultAndObj: ReceivedMessageValidationResult<T, M> = {
1013
+ result: TopicValidatorResult.Reject,
1014
+ severity: PeerErrorSeverity.MidToleranceError,
1015
+ };
884
1016
  const timer = new Timer();
885
1017
  try {
886
1018
  resultAndObj = await validationFunc();
887
1019
  } catch (err) {
888
- this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
889
- this.logger.error(`Error deserializing and validating gossipsub message`, err, {
890
- msgId,
891
- source: source.toString(),
892
- topicType,
893
- });
1020
+ this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
1021
+ }
1022
+
1023
+ const validationTimeMs = timer.ms();
1024
+ const mcacheWindowMs = this.config.gossipsubMcacheLength * this.config.gossipsubInterval;
1025
+ if (validationTimeMs > mcacheWindowMs * 0.75) {
1026
+ this.instrumentation.incSlowValidation(topicType);
1027
+ this.logger.warn(
1028
+ `Gossip validation for ${topicType} took ${validationTimeMs}ms, approaching mcache eviction window of ${mcacheWindowMs}ms. ` +
1029
+ `Message forwarding may be skipped if validation exceeds the window.`,
1030
+ { msgId, source: source.toString(), topicType, validationTimeMs, mcacheWindowMs },
1031
+ );
894
1032
  }
895
1033
 
896
1034
  if (resultAndObj.result === TopicValidatorResult.Accept) {
1035
+ this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
897
1036
  this.instrumentation.recordMessageValidation(topicType, timer);
1037
+ } else if (resultAndObj.result === TopicValidatorResult.Reject) {
1038
+ this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
1039
+ msgId,
1040
+ source: source.toString(),
1041
+ topicType,
1042
+ severity: resultAndObj.severity,
1043
+ });
1044
+ this.peerManager.penalizePeer(source, resultAndObj.severity);
1045
+ } else {
1046
+ this.logger.trace(`Message ${topicType} ignored by validator`, { msgId, source: source.toString(), topicType });
898
1047
  }
899
1048
 
900
1049
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
901
1050
  return resultAndObj;
902
1051
  }
903
1052
 
1053
+ private tryDeserialize<T>(deserializeFunc: () => T, msgId: string, source: PeerId): T | undefined {
1054
+ try {
1055
+ return deserializeFunc();
1056
+ } catch (err) {
1057
+ this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
1058
+ err,
1059
+ msgId,
1060
+ source: source.toString(),
1061
+ });
1062
+ return undefined;
1063
+ }
1064
+ }
1065
+
904
1066
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
905
1067
  const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
906
- const tx = Tx.fromBuffer(payloadData);
1068
+ const tx = this.tryDeserialize(() => Tx.fromBuffer(payloadData), msgId, source);
1069
+ if (!tx) {
1070
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.LowToleranceError };
1071
+ }
907
1072
 
908
1073
  const currentBlockNumber = await this.archiver.getBlockNumber();
909
1074
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
@@ -923,13 +1088,20 @@ export class LibP2PService extends WithTracer implements P2PService {
923
1088
  severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
924
1089
  }
925
1090
 
926
- this.peerManager.penalizePeer(source, severity);
927
- return { result: TopicValidatorResult.Reject };
1091
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
1092
+ validator: name,
1093
+ severity,
1094
+ source: source.toString(),
1095
+ });
1096
+ return { result: TopicValidatorResult.Reject, severity };
928
1097
  }
929
1098
 
930
1099
  // Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
931
1100
  const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
932
1101
  if (canAdd === 'ignored') {
1102
+ this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
1103
+ source: source.toString(),
1104
+ });
933
1105
  return { result: TopicValidatorResult.Ignore, obj: tx };
934
1106
  }
935
1107
 
@@ -937,9 +1109,13 @@ export class LibP2PService extends WithTracer implements P2PService {
937
1109
  const secondStageValidators = this.createSecondStageMessageValidators();
938
1110
  const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
939
1111
  if (!secondStageOutcome.allPassed) {
940
- const { severity } = secondStageOutcome.failure;
941
- this.peerManager.penalizePeer(source, severity);
942
- return { result: TopicValidatorResult.Reject };
1112
+ const { severity, name } = secondStageOutcome.failure;
1113
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
1114
+ validator: name,
1115
+ severity,
1116
+ source: source.toString(),
1117
+ });
1118
+ return { result: TopicValidatorResult.Reject, severity };
943
1119
  }
944
1120
 
945
1121
  // Pool add: persist the tx
@@ -949,7 +1125,7 @@ export class LibP2PService extends WithTracer implements P2PService {
949
1125
  const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
950
1126
  const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
951
1127
 
952
- this.logger.trace(`Validate propagated tx`, {
1128
+ this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
953
1129
  wasAccepted,
954
1130
  wasIgnored,
955
1131
  [Attributes.P2P_ID]: source.toString(),
@@ -960,7 +1136,11 @@ export class LibP2PService extends WithTracer implements P2PService {
960
1136
  } else if (wasIgnored) {
961
1137
  return { result: TopicValidatorResult.Ignore, obj: tx };
962
1138
  } else {
963
- return { result: TopicValidatorResult.Reject };
1139
+ this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
1140
+ source: source.toString(),
1141
+ txHash: txHash.toString(),
1142
+ });
1143
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
964
1144
  }
965
1145
  };
966
1146
 
@@ -990,7 +1170,16 @@ export class LibP2PService extends WithTracer implements P2PService {
990
1170
  source: PeerId,
991
1171
  ): Promise<void> {
992
1172
  const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
993
- () => this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)),
1173
+ () => {
1174
+ const attestation = this.tryDeserialize(() => CheckpointAttestation.fromBuffer(payloadData), msgId, source);
1175
+ if (!attestation) {
1176
+ return Promise.resolve({
1177
+ result: TopicValidatorResult.Reject,
1178
+ severity: PeerErrorSeverity.LowToleranceError,
1179
+ });
1180
+ }
1181
+ return this.validateAndStoreCheckpointAttestation(source, attestation);
1182
+ },
994
1183
  msgId,
995
1184
  source,
996
1185
  TopicType.checkpoint_attestation,
@@ -1023,8 +1212,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1023
1212
 
1024
1213
  if (validationResult.result === 'reject') {
1025
1214
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1026
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1027
- return { result: TopicValidatorResult.Reject };
1215
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1028
1216
  }
1029
1217
 
1030
1218
  if (validationResult.result === 'ignore') {
@@ -1050,16 +1238,16 @@ export class LibP2PService extends WithTracer implements P2PService {
1050
1238
  return { result: TopicValidatorResult.Ignore, obj: attestation };
1051
1239
  }
1052
1240
 
1053
- // Could not add (cap reached for signer), no need to re-broadcast
1241
+ // Could not add (cap reached for signer), penalize and do not re-broadcast
1054
1242
  if (!added) {
1055
- this.logger.warn(`Dropping checkpoint attestation due to cap`, {
1243
+ this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
1056
1244
  slot: slot.toString(),
1057
1245
  archive: attestation.archive.toString(),
1058
1246
  source: peerId.toString(),
1059
1247
  attester: attestation.getSender()?.toString(),
1060
1248
  count,
1061
1249
  });
1062
- return { result: TopicValidatorResult.Ignore, obj: attestation };
1250
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
1063
1251
  }
1064
1252
 
1065
1253
  // Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
@@ -1078,6 +1266,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1078
1266
  }
1079
1267
 
1080
1268
  // Attestation was added successfully - accept it so other nodes can also detect the equivocation
1269
+ this.checkpointAttestationCallback?.(attestation);
1081
1270
  return { result: TopicValidatorResult.Accept, obj: attestation };
1082
1271
  }
1083
1272
 
@@ -1085,16 +1274,17 @@ export class LibP2PService extends WithTracer implements P2PService {
1085
1274
  const {
1086
1275
  result,
1087
1276
  obj: block,
1088
- metadata: { isEquivocated } = {},
1089
- } = await this.validateReceivedMessage<BlockProposal, { isEquivocated: boolean }>(
1277
+ metadata: { isEquivocated, isOversized } = {},
1278
+ } = await this.validateReceivedMessage<BlockProposal, { isEquivocated: boolean; isOversized: boolean }>(
1090
1279
  () => this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)),
1091
1280
  msgId,
1092
1281
  source,
1093
1282
  TopicType.block_proposal,
1094
1283
  );
1095
1284
 
1096
- // If not accepted or equivocated, return
1097
- if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
1285
+ // If not accepted, equivocated, or oversized, return. Oversized proposals are re-broadcast as
1286
+ // slashing evidence but never attested or processed.
1287
+ if (result !== TopicValidatorResult.Accept || !block || isEquivocated || isOversized) {
1098
1288
  return;
1099
1289
  }
1100
1290
 
@@ -1109,13 +1299,12 @@ export class LibP2PService extends WithTracer implements P2PService {
1109
1299
  protected async validateAndStoreBlockProposal(
1110
1300
  peerId: PeerId,
1111
1301
  block: BlockProposal,
1112
- ): Promise<ReceivedMessageValidationResult<BlockProposal, { isEquivocated: boolean }>> {
1302
+ ): Promise<ReceivedMessageValidationResult<BlockProposal, { isEquivocated: boolean; isOversized: boolean }>> {
1113
1303
  const validationResult = await this.blockProposalValidator.validate(block);
1114
1304
 
1115
1305
  if (validationResult.result === 'reject') {
1116
1306
  this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
1117
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1118
- return { result: TopicValidatorResult.Reject };
1307
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1119
1308
  }
1120
1309
 
1121
1310
  if (validationResult.result === 'ignore') {
@@ -1125,6 +1314,12 @@ export class LibP2PService extends WithTracer implements P2PService {
1125
1314
  // Try to add the proposal: this handles existence check, cap check, and adding in one call
1126
1315
  const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1127
1316
  const isEquivocated = count !== undefined && count > 1;
1317
+ // An oversized proposal (index at or beyond the consensus per-checkpoint limit) is structurally valid
1318
+ // proposer misbehavior: it is stored and re-broadcast as slashing evidence but never processed or
1319
+ // attested to. No-ops when maxBlocksPerCheckpoint is unset (local/test).
1320
+ const isOversized =
1321
+ this.config.maxBlocksPerCheckpoint !== undefined &&
1322
+ block.indexWithinCheckpoint >= this.config.maxBlocksPerCheckpoint;
1128
1323
 
1129
1324
  // Duplicate proposal received, no need to re-broadcast
1130
1325
  if (alreadyExists) {
@@ -1134,12 +1329,11 @@ export class LibP2PService extends WithTracer implements P2PService {
1134
1329
  proposer: block.getSender()?.toString(),
1135
1330
  source: peerId.toString(),
1136
1331
  });
1137
- return { result: TopicValidatorResult.Ignore, obj: block, metadata: { isEquivocated } };
1332
+ return { result: TopicValidatorResult.Ignore, obj: block, metadata: { isEquivocated, isOversized } };
1138
1333
  }
1139
1334
 
1140
1335
  // Too many blocks received for this slot and index, penalize peer and do not re-broadcast
1141
1336
  if (!added) {
1142
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1143
1337
  this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1144
1338
  ...block.toBlockInfo(),
1145
1339
  indexWithinCheckpoint: block.indexWithinCheckpoint,
@@ -1147,7 +1341,27 @@ export class LibP2PService extends WithTracer implements P2PService {
1147
1341
  proposer: block.getSender()?.toString(),
1148
1342
  source: peerId.toString(),
1149
1343
  });
1150
- return { result: TopicValidatorResult.Reject, metadata: { isEquivocated } };
1344
+ return {
1345
+ result: TopicValidatorResult.Reject,
1346
+ metadata: { isEquivocated, isOversized },
1347
+ severity: PeerErrorSeverity.HighToleranceError,
1348
+ };
1349
+ }
1350
+
1351
+ // The proposal was stored: if oversized, invoke the oversized callback so the proposer can be
1352
+ // slashed. Fired alongside (not instead of) equivocation detection below.
1353
+ if (isOversized) {
1354
+ const proposer = block.getSender();
1355
+ if (proposer) {
1356
+ this.logger.warn(`Detected oversized block proposal at slot ${block.slotNumber}`, {
1357
+ ...block.toBlockInfo(),
1358
+ indexWithinCheckpoint: block.indexWithinCheckpoint,
1359
+ maxBlocksPerCheckpoint: this.config.maxBlocksPerCheckpoint,
1360
+ source: peerId.toString(),
1361
+ proposer: proposer.toString(),
1362
+ });
1363
+ this.oversizedProposalCallback?.({ slot: block.slotNumber, proposer });
1364
+ }
1151
1365
  }
1152
1366
 
1153
1367
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1163,11 +1377,11 @@ export class LibP2PService extends WithTracer implements P2PService {
1163
1377
  if (proposer && count === 2) {
1164
1378
  this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
1165
1379
  }
1166
- return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
1380
+ return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated, isOversized } };
1167
1381
  }
1168
1382
 
1169
1383
  // Otherwise, we're good to go!
1170
- return { result: TopicValidatorResult.Accept, obj: block };
1384
+ return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated: false, isOversized } };
1171
1385
  }
1172
1386
 
1173
1387
  // REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
@@ -1188,11 +1402,29 @@ export class LibP2PService extends WithTracer implements P2PService {
1188
1402
  // Mark the txs in this proposal as protected
1189
1403
  await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
1190
1404
 
1191
- // Call the block received callback to validate the proposal.
1192
- // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1193
- const isValid = await this.blockReceivedCallback(block, sender);
1194
- if (!isValid) {
1195
- this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1405
+ if (!(await this.tryBlockReceivedCallback(block, sender))) {
1406
+ // Release the protections this proposal created so its txs return to pending. Only entries still
1407
+ // keyed to this slot are cleared, so a tx referenced by a live proposal at another slot stays protected.
1408
+ await this.mempools.txPool.unprotectTxs(block.txHashes, slot);
1409
+ }
1410
+ }
1411
+
1412
+ /**
1413
+ * Runs the block received callback to validate a proposal, and returns whether it was accepted.
1414
+ * A callback that throws is reported as a rejection: the proposal is no more usable than one explicitly
1415
+ * rejected, and letting the error escape would leave the proposal's tx protections in place.
1416
+ * Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1417
+ */
1418
+ private async tryBlockReceivedCallback(block: BlockProposal, sender: PeerId): Promise<boolean> {
1419
+ try {
1420
+ const isValid = await this.blockReceivedCallback(block, sender);
1421
+ if (!isValid) {
1422
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1423
+ }
1424
+ return isValid;
1425
+ } catch (err) {
1426
+ this.logger.error(`Error validating block proposal for block ${block.blockNumber}`, err, block.toBlockInfo());
1427
+ return false;
1196
1428
  }
1197
1429
  }
1198
1430
 
@@ -1204,25 +1436,45 @@ export class LibP2PService extends WithTracer implements P2PService {
1204
1436
  const {
1205
1437
  result,
1206
1438
  obj: checkpoint,
1207
- metadata: { isEquivocated, processBlock } = {},
1208
- } = await this.validateReceivedMessage<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>(
1439
+ metadata: { isEquivocated, processBlock, isOversized } = {},
1440
+ } = await this.validateReceivedMessage<
1441
+ CheckpointProposal,
1442
+ { isEquivocated: boolean; processBlock: boolean; isOversized: boolean }
1443
+ >(
1209
1444
  () => this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)),
1210
1445
  msgId,
1211
1446
  source,
1212
1447
  TopicType.checkpoint_proposal,
1213
1448
  );
1214
1449
 
1450
+ // An oversized checkpoint is re-broadcast as slashing evidence but never attested or processed.
1451
+ // Process checkpoint proposal if valid and neither equivocated nor oversized.
1452
+ const processCheckpointFn = () =>
1453
+ result === TopicValidatorResult.Accept && checkpoint && !isEquivocated && !isOversized
1454
+ ? this.processValidCheckpointProposal(checkpoint.toCore(), source)
1455
+ : Promise.resolve();
1456
+
1215
1457
  // If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
1216
1458
  // TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
1217
- if (processBlock && checkpoint?.getBlockProposal()) {
1218
- await this.processValidBlockProposal(checkpoint.getBlockProposal()!, source);
1219
- }
1220
-
1221
- if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
1459
+ const processBlockFn = () =>
1460
+ processBlock && checkpoint && checkpoint.getBlockProposal()
1461
+ ? this.processValidBlockProposal(checkpoint.getBlockProposal()!, source)
1462
+ : Promise.resolve();
1463
+
1464
+ // A node that skips checkpoint validation attests without re-executing the embedded last block, so run
1465
+ // the checkpoint callback first: this creates and broadcasts the attestation before the block is
1466
+ // processed. Otherwise the block's re-execution — which can stall until the re-execution deadline
1467
+ // waiting for a parent that may never arrive — would delay the attestation past the slot's attestation
1468
+ // window, after which peers reject it as stale.
1469
+ if (this.config.skipCheckpointProposalValidation) {
1470
+ await processCheckpointFn();
1471
+ await processBlockFn();
1222
1472
  return;
1223
1473
  }
1224
1474
 
1225
- await this.processValidCheckpointProposal(checkpoint.toCore(), source);
1475
+ // Process the block first, since it's required for the checkpoint proposal validation.
1476
+ await processBlockFn();
1477
+ await processCheckpointFn();
1226
1478
  }
1227
1479
 
1228
1480
  /**
@@ -1235,13 +1487,17 @@ export class LibP2PService extends WithTracer implements P2PService {
1235
1487
  protected async validateAndStoreCheckpointProposal(
1236
1488
  peerId: PeerId,
1237
1489
  checkpoint: CheckpointProposal,
1238
- ): Promise<ReceivedMessageValidationResult<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>> {
1490
+ ): Promise<
1491
+ ReceivedMessageValidationResult<
1492
+ CheckpointProposal,
1493
+ { isEquivocated: boolean; processBlock: boolean; isOversized: boolean }
1494
+ >
1495
+ > {
1239
1496
  const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
1240
1497
 
1241
1498
  if (validationResult.result === 'reject') {
1242
1499
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1243
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1244
- return { result: TopicValidatorResult.Reject };
1500
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1245
1501
  }
1246
1502
 
1247
1503
  if (validationResult.result === 'ignore') {
@@ -1251,25 +1507,30 @@ export class LibP2PService extends WithTracer implements P2PService {
1251
1507
  // Extract and try to add the block proposal first if present
1252
1508
  const blockProposal = checkpoint.getBlockProposal();
1253
1509
  let processBlock = false;
1510
+ let isOversized = false;
1254
1511
  if (blockProposal) {
1255
1512
  this.logger.debug(`Validating block proposal from propagated checkpoint`, {
1256
1513
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1257
1514
  [Attributes.P2P_ID]: peerId.toString(),
1258
1515
  });
1259
- const {
1260
- result,
1261
- obj,
1262
- metadata: { isEquivocated } = {},
1263
- } = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1264
- if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1516
+ const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1517
+ const { obj, metadata: { isEquivocated, isOversized: blockIsOversized } = {} } = blockProposalResult;
1518
+ isOversized = blockIsOversized ?? false;
1519
+
1520
+ if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1265
1521
  this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
1266
1522
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1267
1523
  [Attributes.P2P_ID]: peerId.toString(),
1268
1524
  isEquivocated,
1269
- result,
1525
+ result: blockProposalResult.result,
1270
1526
  });
1271
- return { result: TopicValidatorResult.Reject };
1272
- } else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1527
+ return {
1528
+ result: TopicValidatorResult.Reject,
1529
+ severity:
1530
+ 'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError,
1531
+ };
1532
+ } else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated && !isOversized) {
1533
+ // An oversized terminal block is re-broadcast as slashing evidence but never processed.
1273
1534
  processBlock = true;
1274
1535
  }
1275
1536
  }
@@ -1289,20 +1550,24 @@ export class LibP2PService extends WithTracer implements P2PService {
1289
1550
  return {
1290
1551
  result: TopicValidatorResult.Ignore,
1291
1552
  obj: checkpoint,
1292
- metadata: { isEquivocated, processBlock },
1553
+ metadata: { isEquivocated, processBlock, isOversized },
1293
1554
  };
1294
1555
  }
1295
1556
 
1296
- // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
1557
+ // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast.
1297
1558
  // Note: We still return the checkpoint obj so the lastBlock can be processed if valid
1298
1559
  if (!added) {
1299
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1300
1560
  this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1301
1561
  ...checkpoint.toCheckpointInfo(),
1302
1562
  count,
1303
1563
  source: peerId.toString(),
1304
1564
  });
1305
- return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
1565
+ return {
1566
+ result: TopicValidatorResult.Reject,
1567
+ obj: checkpoint,
1568
+ metadata: { isEquivocated, processBlock, isOversized },
1569
+ severity: PeerErrorSeverity.HighToleranceError,
1570
+ };
1306
1571
  }
1307
1572
 
1308
1573
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1321,12 +1586,16 @@ export class LibP2PService extends WithTracer implements P2PService {
1321
1586
  return {
1322
1587
  result: TopicValidatorResult.Accept,
1323
1588
  obj: checkpoint,
1324
- metadata: { isEquivocated, processBlock },
1589
+ metadata: { isEquivocated, processBlock, isOversized },
1325
1590
  };
1326
1591
  }
1327
1592
 
1328
1593
  // Otherwise, we're good to go!
1329
- return { result: TopicValidatorResult.Accept, obj: checkpoint, metadata: { processBlock, isEquivocated } };
1594
+ return {
1595
+ result: TopicValidatorResult.Accept,
1596
+ obj: checkpoint,
1597
+ metadata: { processBlock, isEquivocated, isOversized },
1598
+ };
1330
1599
  }
1331
1600
 
1332
1601
  /**
@@ -1347,9 +1616,11 @@ export class LibP2PService extends WithTracer implements P2PService {
1347
1616
  source: sender.toString(),
1348
1617
  });
1349
1618
 
1619
+ await this.allNodesCheckpointReceivedCallback(checkpoint, sender);
1620
+
1350
1621
  // Call the checkpoint received callback with the core version (without lastBlock)
1351
1622
  // to validate and potentially generate attestations
1352
- const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
1623
+ const attestations = await this.validatorCheckpointReceivedCallback(checkpoint, sender);
1353
1624
  if (attestations && attestations.length > 0) {
1354
1625
  // If the callback returned attestations, add them to the pool and propagate them
1355
1626
  await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
@@ -1372,82 +1643,87 @@ export class LibP2PService extends WithTracer implements P2PService {
1372
1643
  }
1373
1644
 
1374
1645
  /**
1375
- * Validate the requested block transactions. Allow partial returns.
1646
+ * Validate the requested block transactions request-response consistency.
1647
+ * It does NOT validate the transactions themselves.
1376
1648
  * @param request - The block transactions request.
1377
1649
  * @param response - The block transactions response.
1378
1650
  * @param peerId - The ID of the peer that made the request.
1379
- * @returns True if the requested block transactions are valid, false otherwise.
1651
+ * @returns True if the request-response is consistent, false otherwise.
1380
1652
  */
1381
- @trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
1653
+ @trackSpan('Libp2pService.validateRequestedBlockTxsConsistency', request => ({
1382
1654
  [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
1383
1655
  }))
1384
- protected async validateRequestedBlockTxs(
1656
+ protected async validateRequestedBlockTxsConsistency(
1385
1657
  request: BlockTxsRequest,
1386
1658
  response: BlockTxsResponse,
1387
1659
  peerId: PeerId,
1388
1660
  ): Promise<boolean> {
1389
- const requestedTxValidator = this.createRequestedTxValidator();
1390
-
1391
1661
  try {
1392
- if (!response.archiveRoot.equals(request.archiveRoot)) {
1662
+ // Check for duplicates txs (or hashes) in the response.
1663
+ const returnedHashes = response.txs.map(tx => tx.getTxHash().toString());
1664
+ const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
1665
+ if (uniqueReturned.size !== returnedHashes.length) {
1393
1666
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1394
- throw new ValidationError(
1395
- `Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`,
1667
+ throw new ValidationError(`Received duplicate txs in block txs response`);
1668
+ }
1669
+
1670
+ // We get the block tx hashes from the proposal or the archiver.
1671
+ const proposal = await this.mempools.attestationPool.getBlockProposalByArchive(request.archiveRoot.toString());
1672
+ const blockTxHashes =
1673
+ proposal?.txHashes ??
1674
+ (await this.archiver.getBlock({ archive: request.archiveRoot }))?.body.txEffects.map(e => e.txHash);
1675
+
1676
+ // If we don't have the block, we can't verify membership/order of the returned txs.
1677
+ if (!blockTxHashes) {
1678
+ // This shouldn't happen, since we asked for the block (proposal).
1679
+ // Neither a local proposal nor an archived block: we cannot verify membership/order of the
1680
+ // returned txs. This is a local-state gap, not a peer fault, so we do not penalize.
1681
+ this.logger.warn(
1682
+ `Block ${request.archiveRoot.toString()} not found in attestation pool or archiver; cannot validate membership/order of returned txs`,
1396
1683
  );
1684
+ // NOTE: We mark the response as invalid, given the limitations of a true/false return value.
1685
+ return false;
1397
1686
  }
1398
1687
 
1399
- if (response.txIndices.getLength() !== request.txIndices.getLength()) {
1400
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1688
+ // Verify that the returned tx hashes are a subset of (tx hashes by index) U (explicitly requested tx hashes).
1689
+ const uniqueRequestedHashes = new Set([
1690
+ // tx hashes requested by index.
1691
+ ...request.txIndices.getTrueIndices().map(i => blockTxHashes[i].toString()),
1692
+ // explicitly requested tx hashes.
1693
+ ...request.txHashes.map(h => h.toString()),
1694
+ ]);
1695
+ if (!returnedHashes.every(h => uniqueRequestedHashes.has(h))) {
1696
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1401
1697
  throw new ValidationError(
1402
- `Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`,
1698
+ 'Returned txs should be a subset of (tx hashes by index) U (explicitly requested tx hashes)',
1403
1699
  );
1404
1700
  }
1405
1701
 
1406
- // Check no duplicates and not exceeding returnable count
1407
- const requestedIndices = new Set(request.txIndices.getTrueIndices());
1408
- const availableIndices = new Set(response.txIndices.getTrueIndices());
1409
- const maxReturnable = [...requestedIndices].filter(i => availableIndices.has(i)).length;
1410
-
1411
- const returnedHashes = await Promise.all(response.txs.map(tx => tx.getTxHash().toString()));
1412
- const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
1413
- if (uniqueReturned.size !== returnedHashes.length) {
1414
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1415
- throw new ValidationError(`Received duplicate txs in block txs response`);
1702
+ // Tx indices information is optional, but if present, we need to verify a few things.
1703
+ if (!response.peerHasBlock()) {
1704
+ this.logger.debug(`Peer ${peerId.toString()} signalled missing block`);
1705
+ return true;
1416
1706
  }
1417
- if (response.txs.length > maxReturnable) {
1707
+
1708
+ // If the response has a non-empty bitvector, it needs to be consistent with the number of txs in the block.
1709
+ if (response.txIndices.getLength() !== blockTxHashes.length) {
1418
1710
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1419
1711
  throw new ValidationError(
1420
- `Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`,
1712
+ `Received block txs with mismatched bitvector length: expected ${blockTxHashes.length}, got ${response.txIndices.getLength()}`,
1421
1713
  );
1422
1714
  }
1423
1715
 
1424
- // Given proposal (should have locally), ensure returned txs are valid subset and match request indices
1425
- const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
1426
- if (proposal) {
1427
- // Build intersected indices
1428
- const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
1429
-
1430
- // Enforce subset membership and preserve increasing order by index.
1431
- const hashToIndexInProposal = new Map<string, number>(
1432
- proposal.txHashes.map((h, i) => [h.toString(), i] as [string, number]),
1433
- );
1434
- const allowedIndexSet = new Set(intersectIdx);
1435
- const indices = returnedHashes.map(h => hashToIndexInProposal.get(h));
1436
- const allAllowed = indices.every(idx => idx !== undefined && allowedIndexSet.has(idx));
1437
- const strictlyIncreasing = indices.every((idx, i) => (i === 0 ? idx !== undefined : idx! > indices[i - 1]!));
1438
- if (!allAllowed || !strictlyIncreasing) {
1439
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1440
- throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
1441
- }
1442
- } else {
1443
- // No local proposal, cannot check the membership/order of the returned txs
1444
- this.logger.warn(
1445
- `Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`,
1446
- );
1447
- return false;
1716
+ // For every index we requested that the peer claims to have (per its bitvector), the
1717
+ // corresponding tx must be present in the response. A peer advertising availability but
1718
+ // withholding the tx is inconsistent.
1719
+ const returnedHashSet = new Set(returnedHashes);
1720
+ const expectedIndices = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
1721
+ const missingExpected = expectedIndices.some(i => !returnedHashSet.has(blockTxHashes[i].toString()));
1722
+ if (missingExpected) {
1723
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1724
+ throw new ValidationError('Peer advertised requested txs via indices but did not return them');
1448
1725
  }
1449
1726
 
1450
- await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
1451
1727
  return true;
1452
1728
  } catch (e: any) {
1453
1729
  if (e instanceof ValidationError) {
@@ -1460,125 +1736,8 @@ export class LibP2PService extends WithTracer implements P2PService {
1460
1736
  }
1461
1737
  }
1462
1738
 
1463
- /**
1464
- * Validate a collection of txs that has been requested from a peer.
1465
- *
1466
- * The core component of this validator is that each tx hash MUST match the requested tx hash,
1467
- * In order to perform this check, the tx proof must be verified.
1468
- *
1469
- * Note: This function is called from within `ReqResp.sendRequest` as part of the
1470
- * ReqRespSubProtocol.TX subprotocol validation.
1471
- *
1472
- * @param requestedTxHash - The collection of the txs that was requested.
1473
- * @param responseTx - The collection of txs that was received as a response to the request.
1474
- * @param peerId - The peer ID of the peer that sent the tx.
1475
- * @returns True if the whole collection of txs is valid, false otherwise.
1476
- */
1477
- @trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx) => ({
1478
- [Attributes.TX_HASH]: requestedTxHash.toString(),
1479
- }))
1480
- private async validateRequestedTxs(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
1481
- const requested = new Set(requestedTxHash.map(h => h.toString()));
1482
- const requestedTxValidator = this.createRequestedTxValidator();
1483
-
1484
- //TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
1485
- // I think we should still extract the valid txs and return them, so that we can still use the response.
1486
- try {
1487
- await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
1488
- return true;
1489
- } catch (e: any) {
1490
- if (e instanceof ValidationError) {
1491
- this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
1492
- } else {
1493
- this.logger.error(`Error during validation of requested txs`, e);
1494
- }
1495
-
1496
- return false;
1497
- }
1498
- }
1499
-
1500
- /**
1501
- * Validates a BLOCK response.
1502
- *
1503
- * If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
1504
- * Penalizes on block number mismatch or hash mismatch.
1505
- *
1506
- * @param requestedBlockNumber - The requested block number.
1507
- * @param responseBlock - The block returned by the peer.
1508
- * @param peerId - The peer that returned the block.
1509
- * @returns True if the response is valid, false otherwise.
1510
- */
1511
- @trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
1512
- [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
1513
- }))
1514
- protected async validateRequestedBlock(
1515
- requestedBlockNumber: Fr,
1516
- responseBlock: L2Block,
1517
- peerId: PeerId,
1518
- ): Promise<boolean> {
1519
- try {
1520
- const reqNum = Number(requestedBlockNumber.toString());
1521
- if (responseBlock.number !== reqNum) {
1522
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1523
- return false;
1524
- }
1525
-
1526
- const local = await this.archiver.getBlock(BlockNumber(reqNum));
1527
- if (!local) {
1528
- // We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
1529
- // TODO: Consider extending this validator to accept an expected hash or
1530
- // performing quorum-based checks when using P2P syncing prior to L1 sync.
1531
- this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
1532
- return false;
1533
- }
1534
- const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
1535
- if (!localHash.equals(respHash)) {
1536
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1537
- return false;
1538
- }
1539
-
1540
- return true;
1541
- } catch (e) {
1542
- this.logger.warn(`Error validating requested block`, e);
1543
- return false;
1544
- }
1545
- }
1546
-
1547
- protected async validateRequestedTx(
1548
- tx: Tx,
1549
- peerId: PeerId,
1550
- txValidator: TxValidator,
1551
- requested?: Set<`0x${string}`>,
1552
- ) {
1553
- const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
1554
- if (requested && !requested.has(tx.getTxHash().toString())) {
1555
- penalize(PeerErrorSeverity.MidToleranceError);
1556
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
1557
- }
1558
-
1559
- const { result } = await txValidator.validateTx(tx);
1560
- if (result === 'invalid') {
1561
- penalize(PeerErrorSeverity.LowToleranceError);
1562
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
1563
- }
1564
- }
1565
-
1566
- protected createRequestedTxValidator(): TxValidator {
1567
- return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
1568
- l1ChainId: this.config.l1ChainId,
1569
- rollupVersion: this.config.rollupVersion,
1570
- });
1571
- }
1572
-
1573
- private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
1574
- if (blockNumber === this.feesCache?.blockNumber) {
1575
- return this.feesCache.gasFees;
1576
- }
1577
-
1578
- const header = await this.archiver.getBlockHeader(blockNumber);
1579
- const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
1580
- this.feesCache = { blockNumber, gasFees };
1581
- return gasFees;
1739
+ private getGasFees(): Promise<GasFees> {
1740
+ return this.blockMinFeesProvider.getCurrentMinFees();
1582
1741
  }
1583
1742
 
1584
1743
  /**
@@ -1592,8 +1751,10 @@ export class LibP2PService extends WithTracer implements P2PService {
1592
1751
  l1ChainId: this.config.l1ChainId,
1593
1752
  rollupVersion: this.config.rollupVersion,
1594
1753
  proofVerifier: this.proofVerifier,
1754
+ txValidationCache: this.txValidationCache,
1595
1755
  },
1596
1756
  peerScoring: this.peerManager,
1757
+ validateRequestedBlockTxsConsistency: this.validateRequestedBlockTxsConsistency.bind(this),
1597
1758
  };
1598
1759
  }
1599
1760
 
@@ -1602,16 +1763,19 @@ export class LibP2PService extends WithTracer implements P2PService {
1602
1763
  this.proofVerifier,
1603
1764
  { l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
1604
1765
  this.logger.getBindings(),
1766
+ this.txValidationCache,
1605
1767
  );
1606
1768
 
1607
1769
  const results = await Promise.all(
1608
- txs.map(async tx => {
1609
- const result = await validator.validateTx(tx);
1610
- return result.result !== 'invalid';
1611
- }),
1770
+ txs.map(async tx => ({ txHash: tx.getTxHash(), result: await validator.validateTx(tx) })),
1612
1771
  );
1613
- if (results.some(value => value === false)) {
1614
- throw new Error('Invalid tx detected');
1772
+
1773
+ const invalidTxs = results.flatMap(({ txHash, result }) =>
1774
+ result.result === 'invalid' ? [{ txHash, reasons: result.reason }] : [],
1775
+ );
1776
+
1777
+ if (invalidTxs.length > 0) {
1778
+ throw new InvalidBlockProposalTxsError(invalidTxs);
1615
1779
  }
1616
1780
  }
1617
1781
 
@@ -1620,9 +1784,14 @@ export class LibP2PService extends WithTracer implements P2PService {
1620
1784
  currentBlockNumber: BlockNumber,
1621
1785
  nextSlotTimestamp: UInt64,
1622
1786
  ): Promise<Record<string, TransactionValidator>> {
1623
- const gasFees = await this.getGasFees(currentBlockNumber);
1624
- const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1787
+ const gasFees = await this.getGasFees();
1788
+ const allowedInSetup = [
1789
+ ...(await getDefaultAllowedSetupFunctions()),
1790
+ ...(this.config.txPublicSetupAllowListExtend ?? []),
1791
+ ];
1625
1792
  const blockNumber = BlockNumber(currentBlockNumber + 1);
1793
+ const l1Constants = await this.archiver.getL1Constants();
1794
+ const networkTxGasLimits = getNetworkTxGasLimits(this.config, l1Constants);
1626
1795
 
1627
1796
  return createFirstStageTxValidationsForGossipedTransactions(
1628
1797
  nextSlotTimestamp,
@@ -1636,6 +1805,10 @@ export class LibP2PService extends WithTracer implements P2PService {
1636
1805
  !this.config.disableTransactions,
1637
1806
  allowedInSetup,
1638
1807
  this.logger.getBindings(),
1808
+ {
1809
+ maxTxL2Gas: networkTxGasLimits.l2Gas,
1810
+ maxTxDAGas: networkTxGasLimits.daGas,
1811
+ },
1639
1812
  );
1640
1813
  }
1641
1814
 
@@ -1661,8 +1834,10 @@ export class LibP2PService extends WithTracer implements P2PService {
1661
1834
 
1662
1835
  // A promise that resolves when all validations have been run
1663
1836
  const allValidations = await Promise.all(validationPromises);
1664
- const failed = allValidations.find(x => !x.isValid);
1665
- if (failed) {
1837
+ const failures = allValidations.filter(x => !x.isValid);
1838
+ if (failures.length > 0) {
1839
+ // Pick the most severe failure (lowest tolerance = harshest penalty)
1840
+ const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
1666
1841
  return {
1667
1842
  allPassed: false,
1668
1843
  failure: {
@@ -1715,31 +1890,6 @@ export class LibP2PService extends WithTracer implements P2PService {
1715
1890
  return PeerErrorSeverity.HighToleranceError;
1716
1891
  }
1717
1892
 
1718
- /**
1719
- * Validate a checkpoint attestation.
1720
- *
1721
- * @param attestation - The checkpoint attestation to validate.
1722
- * @returns True if the checkpoint attestation is valid, false otherwise.
1723
- */
1724
- @trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
1725
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
1726
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1727
- [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1728
- }))
1729
- public async validateCheckpointAttestation(
1730
- peerId: PeerId,
1731
- attestation: CheckpointAttestation,
1732
- ): Promise<P2PValidationResult> {
1733
- const result = await this.checkpointAttestationValidator.validate(attestation);
1734
-
1735
- if (result.result === 'reject') {
1736
- this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1737
- this.peerManager.penalizePeer(peerId, result.severity);
1738
- }
1739
-
1740
- return result;
1741
- }
1742
-
1743
1893
  public getPeerScore(peerId: PeerId): number {
1744
1894
  return this.node.services.pubsub.score.score(peerId.toString());
1745
1895
  }