@aztec/p2p 0.0.1-commit.b655e406 → 0.0.1-commit.d1f2d6c

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 (366) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +1 -1
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/client/factory.d.ts +2 -2
  4. package/dest/client/factory.d.ts.map +1 -1
  5. package/dest/client/factory.js +2 -3
  6. package/dest/client/index.d.ts +1 -1
  7. package/dest/client/interface.d.ts +18 -3
  8. package/dest/client/interface.d.ts.map +1 -1
  9. package/dest/client/p2p_client.d.ts +16 -37
  10. package/dest/client/p2p_client.d.ts.map +1 -1
  11. package/dest/client/p2p_client.js +464 -126
  12. package/dest/config.d.ts +62 -59
  13. package/dest/config.d.ts.map +1 -1
  14. package/dest/config.js +21 -14
  15. package/dest/enr/generate-enr.d.ts +1 -1
  16. package/dest/enr/index.d.ts +1 -1
  17. package/dest/errors/attestation-pool.error.d.ts +7 -0
  18. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  19. package/dest/errors/attestation-pool.error.js +12 -0
  20. package/dest/errors/reqresp.error.d.ts +1 -1
  21. package/dest/errors/reqresp.error.d.ts.map +1 -1
  22. package/dest/index.d.ts +1 -1
  23. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +77 -36
  24. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  26. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +241 -266
  28. package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
  29. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +24 -14
  30. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  31. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +123 -95
  32. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +18 -12
  33. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  34. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +91 -108
  35. package/dest/mem_pools/attestation_pool/mocks.d.ts +234 -10
  36. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  37. package/dest/mem_pools/attestation_pool/mocks.js +17 -13
  38. package/dest/mem_pools/index.d.ts +1 -1
  39. package/dest/mem_pools/instrumentation.d.ts +9 -1
  40. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  41. package/dest/mem_pools/instrumentation.js +36 -9
  42. package/dest/mem_pools/interface.d.ts +3 -4
  43. package/dest/mem_pools/interface.d.ts.map +1 -1
  44. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +33 -58
  45. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  46. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +314 -335
  47. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
  48. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
  49. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
  50. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
  51. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
  52. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
  53. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
  54. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  55. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
  56. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
  57. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  58. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
  59. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
  60. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  61. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
  62. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
  63. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  64. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
  65. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
  66. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
  67. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
  68. package/dest/mem_pools/tx_pool/index.d.ts +1 -2
  69. package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
  70. package/dest/mem_pools/tx_pool/index.js +0 -1
  71. package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
  72. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  73. package/dest/mem_pools/tx_pool/priority.js +6 -1
  74. package/dest/mem_pools/tx_pool/tx_pool.d.ts +11 -6
  75. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  76. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  77. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  78. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +30 -24
  79. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +7 -6
  80. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  81. package/dest/msg_validators/attestation_validator/attestation_validator.js +57 -24
  82. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
  83. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  84. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +71 -0
  85. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  86. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  87. package/dest/msg_validators/attestation_validator/index.js +1 -0
  88. package/dest/msg_validators/clock_tolerance.d.ts +21 -0
  89. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  90. package/dest/msg_validators/clock_tolerance.js +37 -0
  91. package/dest/msg_validators/index.d.ts +2 -2
  92. package/dest/msg_validators/index.d.ts.map +1 -1
  93. package/dest/msg_validators/index.js +1 -1
  94. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
  95. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
  96. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
  97. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
  98. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
  99. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
  100. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
  101. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
  102. package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
  103. package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
  104. package/dest/msg_validators/proposal_validator/index.js +3 -0
  105. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
  106. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
  107. package/dest/msg_validators/proposal_validator/proposal_validator.js +104 -0
  108. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
  109. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
  110. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +212 -0
  111. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  112. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  113. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
  114. package/dest/msg_validators/tx_validator/archive_cache.d.ts +2 -2
  115. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  116. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +2 -2
  117. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  118. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  119. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  120. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +1 -1
  121. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  122. package/dest/msg_validators/tx_validator/factory.d.ts +4 -3
  123. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  124. package/dest/msg_validators/tx_validator/factory.js +1 -1
  125. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
  126. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
  127. package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
  128. package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
  129. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  130. package/dest/msg_validators/tx_validator/gas_validator.js +8 -14
  131. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  132. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  133. package/dest/msg_validators/tx_validator/index.js +1 -0
  134. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +2 -2
  135. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  136. package/dest/msg_validators/tx_validator/phases_validator.d.ts +1 -1
  137. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  138. package/dest/msg_validators/tx_validator/phases_validator.js +3 -1
  139. package/dest/msg_validators/tx_validator/size_validator.d.ts +6 -0
  140. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  141. package/dest/msg_validators/tx_validator/size_validator.js +20 -0
  142. package/dest/msg_validators/tx_validator/test_utils.d.ts +2 -2
  143. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
  144. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
  145. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  146. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +1 -1
  147. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  148. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +1 -1
  149. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  150. package/dest/services/data_store.d.ts +1 -1
  151. package/dest/services/data_store.d.ts.map +1 -1
  152. package/dest/services/discv5/discV5_service.d.ts +1 -1
  153. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  154. package/dest/services/dummy_service.d.ts +6 -2
  155. package/dest/services/dummy_service.d.ts.map +1 -1
  156. package/dest/services/dummy_service.js +3 -0
  157. package/dest/services/encoding.d.ts +1 -1
  158. package/dest/services/encoding.d.ts.map +1 -1
  159. package/dest/services/encoding.js +7 -6
  160. package/dest/services/gossipsub/scoring.d.ts +1 -1
  161. package/dest/services/index.d.ts +1 -1
  162. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  163. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  164. package/dest/services/libp2p/instrumentation.js +26 -72
  165. package/dest/services/libp2p/libp2p_service.d.ts +41 -80
  166. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  167. package/dest/services/libp2p/libp2p_service.js +899 -175
  168. package/dest/services/peer-manager/interface.d.ts +1 -1
  169. package/dest/services/peer-manager/metrics.d.ts +8 -1
  170. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  171. package/dest/services/peer-manager/metrics.js +24 -16
  172. package/dest/services/peer-manager/peer_manager.d.ts +2 -33
  173. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  174. package/dest/services/peer-manager/peer_manager.js +6 -12
  175. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  176. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  177. package/dest/services/peer-manager/peer_scoring.js +37 -2
  178. package/dest/services/reqresp/config.d.ts +1 -1
  179. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +1 -1
  180. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  181. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -4
  182. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  183. package/dest/services/reqresp/constants.d.ts +12 -0
  184. package/dest/services/reqresp/constants.d.ts.map +1 -0
  185. package/dest/services/reqresp/constants.js +7 -0
  186. package/dest/services/reqresp/index.d.ts +1 -1
  187. package/dest/services/reqresp/interface.d.ts +2 -2
  188. package/dest/services/reqresp/interface.d.ts.map +1 -1
  189. package/dest/services/reqresp/interface.js +1 -1
  190. package/dest/services/reqresp/metrics.d.ts +1 -1
  191. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  192. package/dest/services/reqresp/metrics.js +5 -21
  193. package/dest/services/reqresp/protocols/auth.d.ts +2 -2
  194. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
  195. package/dest/services/reqresp/protocols/auth.js +2 -2
  196. package/dest/services/reqresp/protocols/block.d.ts +1 -1
  197. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  198. package/dest/services/reqresp/protocols/block.js +3 -2
  199. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
  200. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  201. package/dest/services/reqresp/protocols/block_txs/bitvector.js +7 -0
  202. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  203. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +4 -6
  204. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  205. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +1 -1
  206. package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
  207. package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
  208. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  209. package/dest/services/reqresp/protocols/index.d.ts +1 -1
  210. package/dest/services/reqresp/protocols/ping.d.ts +1 -1
  211. package/dest/services/reqresp/protocols/status.d.ts +6 -5
  212. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  213. package/dest/services/reqresp/protocols/status.js +7 -3
  214. package/dest/services/reqresp/protocols/tx.d.ts +2 -3
  215. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  216. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  217. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
  218. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  219. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  220. package/dest/services/reqresp/reqresp.d.ts +1 -41
  221. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  222. package/dest/services/reqresp/reqresp.js +402 -24
  223. package/dest/services/reqresp/status.d.ts +2 -2
  224. package/dest/services/reqresp/status.d.ts.map +1 -1
  225. package/dest/services/service.d.ts +16 -3
  226. package/dest/services/service.d.ts.map +1 -1
  227. package/dest/services/tx_collection/config.d.ts +1 -1
  228. package/dest/services/tx_collection/config.js +1 -1
  229. package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -9
  230. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  231. package/dest/services/tx_collection/index.d.ts +1 -1
  232. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  233. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  234. package/dest/services/tx_collection/instrumentation.js +4 -14
  235. package/dest/services/tx_collection/slow_tx_collection.d.ts +4 -5
  236. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  237. package/dest/services/tx_collection/slow_tx_collection.js +2 -1
  238. package/dest/services/tx_collection/tx_collection.d.ts +7 -7
  239. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  240. package/dest/services/tx_collection/tx_collection_sink.d.ts +3 -3
  241. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  242. package/dest/services/tx_collection/tx_source.d.ts +1 -1
  243. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  244. package/dest/services/tx_provider.d.ts +4 -2
  245. package/dest/services/tx_provider.d.ts.map +1 -1
  246. package/dest/services/tx_provider.js +11 -2
  247. package/dest/services/tx_provider_instrumentation.d.ts +5 -2
  248. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  249. package/dest/services/tx_provider_instrumentation.js +13 -13
  250. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  251. package/dest/test-helpers/get-ports.d.ts +1 -1
  252. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  253. package/dest/test-helpers/index.d.ts +1 -1
  254. package/dest/test-helpers/make-enrs.d.ts +1 -1
  255. package/dest/test-helpers/make-test-p2p-clients.d.ts +2 -2
  256. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  257. package/dest/test-helpers/mock-pubsub.d.ts +4 -4
  258. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  259. package/dest/test-helpers/mock-tx-helpers.d.ts +2 -2
  260. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -1
  261. package/dest/test-helpers/mock-tx-helpers.js +1 -1
  262. package/dest/test-helpers/reqresp-nodes.d.ts +2 -2
  263. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  264. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  265. package/dest/testbench/p2p_client_testbench_worker.js +39 -22
  266. package/dest/testbench/parse_log_file.d.ts +1 -1
  267. package/dest/testbench/testbench.d.ts +1 -1
  268. package/dest/testbench/worker_client_manager.d.ts +1 -1
  269. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  270. package/dest/testbench/worker_client_manager.js +6 -1
  271. package/dest/types/index.d.ts +1 -1
  272. package/dest/util.d.ts +2 -1
  273. package/dest/util.d.ts.map +1 -1
  274. package/dest/util.js +11 -2
  275. package/dest/versioning.d.ts +1 -1
  276. package/package.json +19 -18
  277. package/src/client/factory.ts +5 -10
  278. package/src/client/interface.ts +20 -2
  279. package/src/client/p2p_client.ts +108 -155
  280. package/src/config.ts +30 -19
  281. package/src/errors/attestation-pool.error.ts +13 -0
  282. package/src/mem_pools/attestation_pool/attestation_pool.ts +86 -35
  283. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +243 -278
  284. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +175 -111
  285. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +147 -136
  286. package/src/mem_pools/attestation_pool/mocks.ts +21 -15
  287. package/src/mem_pools/instrumentation.ts +47 -10
  288. package/src/mem_pools/interface.ts +2 -4
  289. package/src/mem_pools/tx_pool/README.md +270 -0
  290. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +367 -371
  291. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
  292. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
  293. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
  294. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
  295. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
  296. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
  297. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
  298. package/src/mem_pools/tx_pool/index.ts +0 -1
  299. package/src/mem_pools/tx_pool/priority.ts +8 -1
  300. package/src/mem_pools/tx_pool/tx_pool.ts +11 -5
  301. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +23 -17
  302. package/src/msg_validators/attestation_validator/attestation_validator.ts +45 -32
  303. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +88 -0
  304. package/src/msg_validators/attestation_validator/index.ts +1 -0
  305. package/src/msg_validators/clock_tolerance.ts +51 -0
  306. package/src/msg_validators/index.ts +1 -1
  307. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
  308. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
  309. package/src/msg_validators/proposal_validator/index.ts +3 -0
  310. package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
  311. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
  312. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  313. package/src/msg_validators/tx_validator/block_header_validator.ts +1 -1
  314. package/src/msg_validators/tx_validator/data_validator.ts +12 -4
  315. package/src/msg_validators/tx_validator/factory.ts +3 -2
  316. package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
  317. package/src/msg_validators/tx_validator/gas_validator.ts +8 -25
  318. package/src/msg_validators/tx_validator/index.ts +1 -0
  319. package/src/msg_validators/tx_validator/metadata_validator.ts +13 -5
  320. package/src/msg_validators/tx_validator/phases_validator.ts +3 -1
  321. package/src/msg_validators/tx_validator/size_validator.ts +18 -0
  322. package/src/msg_validators/tx_validator/test_utils.ts +1 -1
  323. package/src/msg_validators/tx_validator/timestamp_validator.ts +5 -2
  324. package/src/services/dummy_service.ts +6 -0
  325. package/src/services/encoding.ts +6 -5
  326. package/src/services/libp2p/instrumentation.ts +26 -71
  327. package/src/services/libp2p/libp2p_service.ts +580 -160
  328. package/src/services/peer-manager/metrics.ts +27 -16
  329. package/src/services/peer-manager/peer_manager.ts +7 -4
  330. package/src/services/peer-manager/peer_scoring.ts +42 -3
  331. package/src/services/reqresp/connection-sampler/connection_sampler.ts +3 -1
  332. package/src/services/reqresp/constants.ts +14 -0
  333. package/src/services/reqresp/interface.ts +1 -1
  334. package/src/services/reqresp/metrics.ts +7 -23
  335. package/src/services/reqresp/protocols/auth.ts +2 -2
  336. package/src/services/reqresp/protocols/block.ts +3 -2
  337. package/src/services/reqresp/protocols/block_txs/bitvector.ts +9 -0
  338. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +1 -1
  339. package/src/services/reqresp/protocols/status.ts +16 -12
  340. package/src/services/reqresp/protocols/tx.ts +1 -2
  341. package/src/services/service.ts +19 -4
  342. package/src/services/tx_collection/config.ts +1 -1
  343. package/src/services/tx_collection/fast_tx_collection.ts +3 -2
  344. package/src/services/tx_collection/instrumentation.ts +4 -21
  345. package/src/services/tx_collection/slow_tx_collection.ts +5 -4
  346. package/src/services/tx_collection/tx_collection.ts +6 -5
  347. package/src/services/tx_provider.ts +19 -3
  348. package/src/services/tx_provider_instrumentation.ts +18 -14
  349. package/src/test-helpers/mock-pubsub.ts +1 -1
  350. package/src/test-helpers/mock-tx-helpers.ts +1 -1
  351. package/src/test-helpers/reqresp-nodes.ts +1 -1
  352. package/src/testbench/p2p_client_testbench_worker.ts +45 -22
  353. package/src/testbench/worker_client_manager.ts +6 -1
  354. package/src/util.ts +12 -2
  355. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -80
  356. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  357. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -238
  358. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
  359. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  360. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -70
  361. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  362. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  363. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  364. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -283
  365. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -81
  366. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
@@ -1,23 +1,26 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
- import { randomInt } from '@aztec/foundation/crypto';
3
- import { Fr } from '@aztec/foundation/fields';
2
+ import { BlockNumber } from '@aztec/foundation/branded-types';
3
+ import { randomInt } from '@aztec/foundation/crypto/random';
4
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
5
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
5
- import { SerialQueue } from '@aztec/foundation/queue';
6
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
7
7
  import { Timer } from '@aztec/foundation/timer';
8
8
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
9
9
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
10
10
  import { protocolContractsHash } from '@aztec/protocol-contracts';
11
- import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
11
+ import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
12
12
  import type { ContractDataSource } from '@aztec/stdlib/contract';
13
13
  import { GasFees } from '@aztec/stdlib/gas';
14
14
  import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
15
15
  import {
16
- BlockAttestation,
17
16
  BlockProposal,
17
+ CheckpointAttestation,
18
+ CheckpointProposal,
19
+ type CheckpointProposalCore,
18
20
  type Gossipable,
19
21
  P2PClientType,
20
22
  P2PMessage,
23
+ type ValidationResult as P2PValidationResult,
21
24
  PeerErrorSeverity,
22
25
  TopicType,
23
26
  createTopicString,
@@ -28,7 +31,14 @@ import { MerkleTreeId } from '@aztec/stdlib/trees';
28
31
  import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
29
32
  import type { UInt64 } from '@aztec/stdlib/types';
30
33
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
31
- import { Attributes, OtelMetricsAdapter, type TelemetryClient, WithTracer, trackSpan } from '@aztec/telemetry-client';
34
+ import {
35
+ Attributes,
36
+ OtelMetricsAdapter,
37
+ SpanStatusCode,
38
+ type TelemetryClient,
39
+ WithTracer,
40
+ trackSpan,
41
+ } from '@aztec/telemetry-client';
32
42
 
33
43
  import {
34
44
  type GossipSub,
@@ -50,8 +60,15 @@ import { ENR } from '@nethermindeth/enr';
50
60
  import { createLibp2p } from 'libp2p';
51
61
 
52
62
  import type { P2PConfig } from '../../config.js';
63
+ import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
53
64
  import type { MemPools } from '../../mem_pools/interface.js';
54
- import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
65
+ import {
66
+ BlockProposalValidator,
67
+ CheckpointAttestationValidator,
68
+ CheckpointProposalValidator,
69
+ FishermanAttestationValidator,
70
+ SizeTxValidator,
71
+ } from '../../msg_validators/index.js';
55
72
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
56
73
  import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
57
74
  import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
@@ -96,7 +113,12 @@ import {
96
113
  reqRespTxHandler,
97
114
  } from '../reqresp/protocols/index.js';
98
115
  import { ReqResp } from '../reqresp/reqresp.js';
99
- import type { P2PBlockReceivedCallback, P2PService, PeerDiscoveryService } from '../service.js';
116
+ import type {
117
+ P2PBlockReceivedCallback,
118
+ P2PCheckpointReceivedCallback,
119
+ P2PService,
120
+ PeerDiscoveryService,
121
+ } from '../service.js';
100
122
  import { P2PInstrumentation } from './instrumentation.js';
101
123
 
102
124
  interface ValidationResult {
@@ -116,18 +138,18 @@ type ReceivedMessageValidationResult<T> =
116
138
  * Lib P2P implementation of the P2PService interface.
117
139
  */
118
140
  export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
119
- private jobQueue: SerialQueue = new SerialQueue();
120
141
  private discoveryRunningPromise?: RunningPromise;
121
142
  private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
122
143
 
123
144
  // Message validators
124
- private attestationValidator: AttestationValidator;
125
145
  private blockProposalValidator: BlockProposalValidator;
146
+ private checkpointProposalValidator: CheckpointProposalValidator;
147
+ private checkpointAttestationValidator: CheckpointAttestationValidator;
126
148
 
127
149
  private protocolVersion = '';
128
150
  private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
129
151
 
130
- private feesCache: { blockNumber: number; gasFees: GasFees } | undefined;
152
+ private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
131
153
 
132
154
  /**
133
155
  * Callback for when a block is received from a peer.
@@ -136,10 +158,21 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
136
158
  */
137
159
  private blockReceivedCallback: P2PBlockReceivedCallback;
138
160
 
161
+ /**
162
+ * Callback for when a checkpoint proposal is received from a peer.
163
+ * @param checkpoint - The checkpoint proposal received from the peer.
164
+ * @returns The attestations for the checkpoint, if any.
165
+ */
166
+ private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
167
+
139
168
  private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
140
169
 
141
170
  private instrumentation: P2PInstrumentation;
142
171
 
172
+ private telemetry: TelemetryClient;
173
+
174
+ protected logger: Logger;
175
+
143
176
  constructor(
144
177
  private clientType: T,
145
178
  private config: P2PConfig,
@@ -147,21 +180,26 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
147
180
  private peerDiscoveryService: PeerDiscoveryService,
148
181
  private reqresp: ReqRespInterface,
149
182
  private peerManager: PeerManagerInterface,
150
- protected mempools: MemPools<T>,
183
+ protected mempools: MemPools,
151
184
  private archiver: L2BlockSource & ContractDataSource,
152
185
  private epochCache: EpochCacheInterface,
153
186
  private proofVerifier: ClientProtocolCircuitVerifier,
154
187
  private worldStateSynchronizer: WorldStateSynchronizer,
155
188
  telemetry: TelemetryClient,
156
- protected logger = createLogger('p2p:libp2p_service'),
189
+ logger: Logger = createLogger('p2p:libp2p_service'),
157
190
  ) {
158
191
  super(telemetry, 'LibP2PService');
192
+ this.telemetry = telemetry;
193
+
194
+ // Create child logger with fisherman prefix if in fisherman mode
195
+ this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
159
196
 
160
197
  this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
161
198
 
162
199
  this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
163
200
  this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
164
- this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
201
+ this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
202
+ this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
165
203
 
166
204
  const versions = getVersions(config);
167
205
  this.protocolVersion = compressComponentVersions(versions);
@@ -169,22 +207,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
169
207
 
170
208
  this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
171
209
  this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
172
- this.topicStrings[TopicType.block_attestation] = createTopicString(
173
- TopicType.block_attestation,
210
+ this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(
211
+ TopicType.checkpoint_proposal,
212
+ this.protocolVersion,
213
+ );
214
+ this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(
215
+ TopicType.checkpoint_attestation,
174
216
  this.protocolVersion,
175
217
  );
176
218
 
177
- this.attestationValidator = new AttestationValidator(epochCache);
178
219
  this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
220
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
221
+ txsPermitted: !config.disableTransactions,
222
+ });
223
+ this.checkpointAttestationValidator = config.fishermanMode
224
+ ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
225
+ : new CheckpointAttestationValidator(epochCache);
179
226
 
180
227
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
181
228
 
182
- this.blockReceivedCallback = async (block: BlockProposal): Promise<BlockAttestation[] | undefined> => {
229
+ this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
183
230
  this.logger.debug(
184
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`,
185
- { p2pMessageIdentifier: await block.p2pMessageIdentifier() },
231
+ `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
232
+ { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
186
233
  );
187
- return undefined;
234
+ return false;
235
+ };
236
+
237
+ this.checkpointReceivedCallback = (
238
+ checkpoint: CheckpointProposalCore,
239
+ ): Promise<CheckpointAttestation[] | undefined> => {
240
+ this.logger.debug(
241
+ `Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
242
+ );
243
+ return Promise.resolve(undefined);
188
244
  };
189
245
  }
190
246
 
@@ -203,7 +259,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
203
259
  config: P2PConfig,
204
260
  peerId: PeerId,
205
261
  deps: {
206
- mempools: MemPools<T>;
262
+ mempools: MemPools;
207
263
  l2BlockSource: L2BlockSource & ContractDataSource;
208
264
  epochCache: EpochCacheInterface;
209
265
  proofVerifier: ClientProtocolCircuitVerifier;
@@ -253,7 +309,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
253
309
 
254
310
  const txTopic = createTopicString(TopicType.tx, protocolVersion);
255
311
  const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
256
- const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
312
+ const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
313
+ const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
257
314
 
258
315
  const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
259
316
  const directPeers = (
@@ -375,12 +432,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
375
432
  invalidMessageDeliveriesWeight: -20,
376
433
  invalidMessageDeliveriesDecay: 0.5,
377
434
  }),
378
- [blockAttestationTopic]: createTopicScoreParams({
435
+ [blockProposalTopic]: createTopicScoreParams({
379
436
  topicWeight: 1,
380
437
  invalidMessageDeliveriesWeight: -20,
381
438
  invalidMessageDeliveriesDecay: 0.5,
382
439
  }),
383
- [blockProposalTopic]: createTopicScoreParams({
440
+ [checkpointProposalTopic]: createTopicScoreParams({
441
+ topicWeight: 1,
442
+ invalidMessageDeliveriesWeight: -20,
443
+ invalidMessageDeliveriesDecay: 0.5,
444
+ }),
445
+ [checkpointAttestationTopic]: createTopicScoreParams({
384
446
  topicWeight: 1,
385
447
  invalidMessageDeliveriesWeight: -20,
386
448
  invalidMessageDeliveriesDecay: 0.5,
@@ -395,7 +457,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
395
457
  logger: createLibp2pComponentLogger(logger.module),
396
458
  });
397
459
 
398
- const peerScoring = new PeerScoring(config);
460
+ const peerScoring = new PeerScoring(config, telemetry);
399
461
  const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
400
462
 
401
463
  const peerManager = new PeerManager(
@@ -450,20 +512,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
450
512
  }
451
513
  const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
452
514
 
453
- // Start job queue, peer discovery service and libp2p node
454
- this.jobQueue.start();
455
-
456
- await this.peerManager.initializePeers();
457
- if (!this.config.p2pDiscoveryDisabled) {
458
- await this.peerDiscoveryService.start();
459
- }
460
- await this.node.start();
461
-
462
- // Subscribe to standard GossipSub topics by default
463
- for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
464
- this.subscribeToTopic(this.topicStrings[topic]);
465
- }
466
-
467
515
  // Create request response protocol handlers
468
516
  const txHandler = reqRespTxHandler(this.mempools);
469
517
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
@@ -477,8 +525,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
477
525
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
478
526
  };
479
527
 
480
- // Only handle block transactions request if attestation pool is available to the client
481
- if (this.mempools.attestationPool && !this.config.disableTransactions) {
528
+ if (!this.config.disableTransactions) {
482
529
  const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
483
530
  requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
484
531
  }
@@ -487,25 +534,41 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
487
534
  requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
488
535
  }
489
536
 
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
+ await this.peerManager.initializePeers();
546
+
547
+ await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
548
+
549
+ await this.node.start();
550
+
551
+ // Subscribe to standard GossipSub topics by default
552
+ for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
553
+ this.subscribeToTopic(this.topicStrings[topic]);
554
+ }
555
+
490
556
  // add GossipSub listener
491
557
  this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
492
558
 
493
- // Start running promise for peer discovery
559
+ // Start running promise for peer discovery and metrics collection
560
+ if (!this.config.p2pDiscoveryDisabled) {
561
+ await this.peerDiscoveryService.start();
562
+ }
494
563
  this.discoveryRunningPromise = new RunningPromise(
495
- () => this.peerManager.heartbeat(),
564
+ async () => {
565
+ await this.peerManager.heartbeat();
566
+ },
496
567
  this.logger,
497
568
  this.config.peerCheckIntervalMS,
498
569
  );
499
570
  this.discoveryRunningPromise.start();
500
571
 
501
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
502
- const reqrespSubProtocolValidators = {
503
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
504
- // TODO(#11336): A request validator for blocks
505
- [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
506
- [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
507
- };
508
- await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
509
572
  this.logger.info(`Started P2P service`, {
510
573
  listen: this.config.listenAddress,
511
574
  port: this.config.p2pPort,
@@ -525,9 +588,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
525
588
  // Stop peer manager
526
589
  this.logger.debug('Stopping peer manager...');
527
590
  await this.peerManager.stop();
528
-
529
- this.logger.debug('Stopping job queue...');
530
- await this.jobQueue.end();
531
591
  this.logger.debug('Stopping running promise...');
532
592
  await this.discoveryRunningPromise?.stop();
533
593
  this.logger.debug('Stopping peer discovery service...');
@@ -594,6 +654,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
594
654
  this.blockReceivedCallback = callback;
595
655
  }
596
656
 
657
+ public registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
658
+ this.checkpointReceivedCallback = callback;
659
+ }
660
+
597
661
  /**
598
662
  * Subscribes to a topic.
599
663
  * @param topic - The topic to subscribe to.
@@ -615,7 +679,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
615
679
  if (!this.node.services.pubsub) {
616
680
  throw new Error('Pubsub service not available.');
617
681
  }
618
- const p2pMessage = P2PMessage.fromGossipable(message);
682
+ const isBlockProposal = topic === this.topicStrings[TopicType.block_proposal];
683
+ const traceContext =
684
+ this.config.debugP2PInstrumentMessages && isBlockProposal ? this.telemetry.getTraceContext() : undefined;
685
+ const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages, traceContext);
619
686
  const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
620
687
  return result.recipients.length;
621
688
  }
@@ -636,12 +703,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
636
703
  case this.topicStrings[TopicType.tx]:
637
704
  topicType = TopicType.tx;
638
705
  break;
639
- case this.topicStrings[TopicType.block_attestation]:
640
- topicType = TopicType.block_attestation;
641
- break;
642
706
  case this.topicStrings[TopicType.block_proposal]:
643
707
  topicType = TopicType.block_proposal;
644
708
  break;
709
+ case this.topicStrings[TopicType.checkpoint_proposal]:
710
+ topicType = TopicType.checkpoint_proposal;
711
+ break;
712
+ case this.topicStrings[TopicType.checkpoint_attestation]:
713
+ topicType = TopicType.checkpoint_attestation;
714
+ break;
645
715
  default:
646
716
  this.logger.error(`Received message on unknown topic: ${msg.topic}`);
647
717
  break;
@@ -660,13 +730,39 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
660
730
  return { result: true, topicType };
661
731
  }
662
732
 
733
+ /**
734
+ * Safely deserializes a P2PMessage from raw message data.
735
+ * @param msgId - The message ID.
736
+ * @param source - The peer ID of the message source.
737
+ * @param data - The raw message data.
738
+ * @returns The deserialized P2PMessage or undefined if deserialization fails.
739
+ */
740
+ private safelyDeserializeP2PMessage(msgId: string, source: PeerId, data: Uint8Array): P2PMessage | undefined {
741
+ try {
742
+ return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
743
+ } catch (err) {
744
+ this.logger.error(`Error deserializing P2PMessage`, err, {
745
+ msgId,
746
+ source: source.toString(),
747
+ });
748
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
749
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
750
+ return undefined;
751
+ }
752
+ }
753
+
663
754
  /**
664
755
  * Handles a new gossip message that was received by the client.
665
756
  * @param topic - The message's topic.
666
757
  * @param data - The message data
667
758
  */
668
759
  protected async handleNewGossipMessage(msg: Message, msgId: string, source: PeerId) {
669
- const p2pMessage = P2PMessage.fromMessageData(Buffer.from(msg.data));
760
+ const msgReceivedTime = Date.now();
761
+ let topicType: TopicType | undefined;
762
+ const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
763
+ if (!p2pMessage) {
764
+ return;
765
+ }
670
766
 
671
767
  const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
672
768
 
@@ -674,14 +770,75 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
674
770
  return;
675
771
  }
676
772
 
773
+ // Determine topic type for attributes
677
774
  if (msg.topic === this.topicStrings[TopicType.tx]) {
678
- await this.handleGossipedTx(p2pMessage.payload, msgId, source);
775
+ topicType = TopicType.tx;
776
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
777
+ topicType = TopicType.checkpoint_attestation;
778
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
779
+ topicType = TopicType.block_proposal;
780
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
781
+ topicType = TopicType.checkpoint_proposal;
679
782
  }
680
- if (msg.topic === this.topicStrings[TopicType.block_attestation] && this.clientType === P2PClientType.Full) {
681
- await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
783
+
784
+ // Process the message, optionally within a linked span for trace propagation
785
+ const processMessage = async () => {
786
+ if (msg.topic === this.topicStrings[TopicType.tx]) {
787
+ await this.handleGossipedTx(p2pMessage.payload, msgId, source);
788
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
789
+ if (this.clientType === P2PClientType.Full) {
790
+ await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
791
+ }
792
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
793
+ await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
794
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
795
+ await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
796
+ } else {
797
+ this.logger.error(`Received message on unknown topic: ${msg.topic}`);
798
+ }
799
+ };
800
+
801
+ const latency = p2pMessage.timestamp !== undefined ? msgReceivedTime - p2pMessage.timestamp.getTime() : undefined;
802
+ const propagatedContext = p2pMessage.traceContext
803
+ ? this.telemetry.extractPropagatedContext(p2pMessage.traceContext)
804
+ : undefined;
805
+
806
+ if (propagatedContext) {
807
+ await this.tracer.startActiveSpan(
808
+ 'LibP2PService.processMessage',
809
+ {
810
+ attributes: {
811
+ [Attributes.TOPIC_NAME]: topicType!,
812
+ [Attributes.PEER_ID]: source.toString(),
813
+ },
814
+ },
815
+ propagatedContext,
816
+ async span => {
817
+ try {
818
+ await processMessage();
819
+ span.setStatus({
820
+ code: SpanStatusCode.OK,
821
+ });
822
+ } catch (err) {
823
+ span.setStatus({
824
+ code: SpanStatusCode.ERROR,
825
+ message: String(err),
826
+ });
827
+ if (typeof err === 'string' || (err && err instanceof Error)) {
828
+ span.recordException(err);
829
+ }
830
+ throw err;
831
+ } finally {
832
+ span.end();
833
+ }
834
+ },
835
+ );
836
+ } else {
837
+ await processMessage();
682
838
  }
683
- if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
684
- await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
839
+
840
+ if (latency !== undefined && topicType !== undefined) {
841
+ this.instrumentation.recordMessageLatency(topicType, latency);
685
842
  }
686
843
 
687
844
  return;
@@ -698,6 +855,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
698
855
  try {
699
856
  resultAndObj = await validationFunc();
700
857
  } catch (err) {
858
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
701
859
  this.logger.error(`Error deserializing and validating gossipsub message`, err, {
702
860
  msgId,
703
861
  source: source.toString(),
@@ -751,42 +909,63 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
751
909
  return;
752
910
  }
753
911
 
912
+ this.instrumentation.incrementTxReceived(1);
754
913
  await this.mempools.txPool.addTxs([tx]);
755
914
  }
756
915
 
757
916
  /**
758
- * Process Attestation From Peer
759
- * When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
760
- *
761
- * @param attestation - The attestation to process.
917
+ * Process a checkpoint attestation from a peer.
918
+ * Validates the attestation and adds it to the pool.
762
919
  */
763
- private async processAttestationFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
764
- const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockAttestation>> = async () => {
765
- const attestation = BlockAttestation.fromBuffer(payloadData);
766
- const isValid = await this.validateAttestation(source, attestation);
767
- const exists = isValid && (await this.mempools.attestationPool!.hasAttestation(attestation));
920
+ private async processCheckpointAttestationFromPeer(
921
+ payloadData: Buffer,
922
+ msgId: string,
923
+ source: PeerId,
924
+ ): Promise<void> {
925
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointAttestation>> = async () => {
926
+ const attestation = CheckpointAttestation.fromBuffer(payloadData);
927
+ const pool = this.mempools.attestationPool;
928
+ const validationResult = await this.validateCheckpointAttestation(source, attestation);
929
+ const isValid = validationResult.result === 'accept';
930
+ const exists = isValid && (await pool.hasCheckpointAttestation(attestation));
931
+
932
+ let canAdd = true;
933
+ if (isValid && !exists) {
934
+ const slot = attestation.payload.header.slotNumber;
935
+ const { committee } = await this.epochCache.getCommittee(slot);
936
+ const committeeSize = committee?.length ?? 0;
937
+ canAdd = await pool.canAddCheckpointAttestation(attestation, committeeSize);
938
+ }
768
939
 
769
- this.logger.trace(`Validate propagated block attestation`, {
940
+ this.logger.trace(`Validate propagated checkpoint attestation`, {
770
941
  isValid,
771
942
  exists,
943
+ canAdd,
772
944
  [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
773
945
  [Attributes.P2P_ID]: source.toString(),
774
946
  });
775
947
 
776
- if (!isValid) {
948
+ if (validationResult.result === 'reject') {
777
949
  return { result: TopicValidatorResult.Reject };
778
- } else if (exists) {
950
+ } else if (validationResult.result === 'ignore' || exists) {
951
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
952
+ } else if (!canAdd) {
953
+ this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
954
+ slot: attestation.payload.header.slotNumber.toString(),
955
+ archive: attestation.archive.toString(),
956
+ source: source.toString(),
957
+ });
779
958
  return { result: TopicValidatorResult.Ignore, obj: attestation };
780
959
  } else {
781
960
  return { result: TopicValidatorResult.Accept, obj: attestation };
782
961
  }
783
962
  };
784
963
 
785
- const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
964
+ const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
786
965
  validationFunc,
787
966
  msgId,
788
967
  source,
789
- TopicType.block_attestation,
968
+ TopicType.checkpoint_attestation,
790
969
  );
791
970
 
792
971
  if (result !== TopicValidatorResult.Accept || !attestation) {
@@ -794,38 +973,48 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
794
973
  }
795
974
 
796
975
  this.logger.debug(
797
- `Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`,
976
+ `Received checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
798
977
  {
799
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
800
- slot: attestation.slotNumber.toNumber(),
978
+ p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
979
+ slot: attestation.slotNumber,
801
980
  archive: attestation.archive.toString(),
802
981
  source: source.toString(),
803
982
  },
804
983
  );
805
984
 
806
- await this.mempools.attestationPool!.addAttestations([attestation]);
985
+ await this.mempools.attestationPool.addCheckpointAttestations([attestation]);
807
986
  }
808
987
 
809
988
  private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
810
989
  const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
811
990
  const block = BlockProposal.fromBuffer(payloadData);
812
- const isValid = await this.validateBlockProposal(source, block);
991
+ const validationResult = await this.validateBlockProposal(source, block);
992
+ const isValid = validationResult.result === 'accept';
993
+ const pool = this.mempools.attestationPool;
813
994
 
814
- // Note that we dont have an attestation pool if we're a prover node, but we still
815
- // subscribe to block proposal topics in order to prevent their txs from being cleared.
816
- const exists = isValid && (await this.mempools.attestationPool?.hasBlockProposal(block));
995
+ const exists = isValid && (await pool.hasBlockProposal(block));
996
+ const canAdd = isValid && (await pool.canAddProposal(block));
817
997
 
818
998
  this.logger.trace(`Validate propagated block proposal`, {
819
999
  isValid,
820
1000
  exists,
821
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
1001
+ canAdd,
1002
+ [Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
822
1003
  [Attributes.P2P_ID]: source.toString(),
823
1004
  });
824
1005
 
825
- if (!isValid) {
1006
+ if (validationResult.result === 'reject') {
826
1007
  return { result: TopicValidatorResult.Reject };
827
- } else if (exists) {
1008
+ } else if (validationResult.result === 'ignore' || exists) {
828
1009
  return { result: TopicValidatorResult.Ignore, obj: block };
1010
+ } else if (!canAdd) {
1011
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
1012
+ this.logger.warn(`Penalizing peer for block proposal exceeding per-slot cap`, {
1013
+ slot: block.slotNumber.toString(),
1014
+ archive: block.archive.toString(),
1015
+ source: source.toString(),
1016
+ });
1017
+ return { result: TopicValidatorResult.Reject };
829
1018
  } else {
830
1019
  return { result: TopicValidatorResult.Accept, obj: block };
831
1020
  }
@@ -846,55 +1035,156 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
846
1035
  }
847
1036
 
848
1037
  // REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
1038
+ // REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
1039
+ // should not be here as it does not deal with p2p networking.
849
1040
  @trackSpan('Libp2pService.processValidBlockProposal', async block => ({
850
- [Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
1041
+ [Attributes.SLOT_NUMBER]: block.slotNumber,
851
1042
  [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
852
- [Attributes.P2P_ID]: await block.p2pMessageIdentifier().then(i => i.toString()),
1043
+ [Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
853
1044
  }))
854
1045
  private async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
855
- const slot = block.slotNumber.toBigInt();
856
- const previousSlot = slot - 1n;
1046
+ const slot = block.slotNumber;
857
1047
  this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
858
- p2pMessageIdentifier: await block.p2pMessageIdentifier(),
859
- slot: block.slotNumber.toNumber(),
860
- archive: block.archive.toString(),
1048
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
861
1049
  source: sender.toString(),
1050
+ ...block.toBlockInfo(),
862
1051
  });
863
- const attestationsForPreviousSlot = await this.mempools.attestationPool?.getAttestationsForSlot(previousSlot);
864
- if (attestationsForPreviousSlot !== undefined) {
865
- this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
1052
+
1053
+ // Attempt to add proposal
1054
+ try {
1055
+ await this.mempools.attestationPool.addBlockProposal(block);
1056
+ } catch (err: unknown) {
1057
+ // Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
1058
+ if (err instanceof ProposalSlotCapExceededError) {
1059
+ this.logger.warn(`Dropping block proposal due to per-slot proposal cap`, {
1060
+ slot: String(slot),
1061
+ archive: block.archive.toString(),
1062
+ error: (err as Error).message,
1063
+ });
1064
+ return;
1065
+ }
1066
+ throw err;
866
1067
  }
867
1068
 
868
1069
  // Mark the txs in this proposal as non-evictable
869
1070
  await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
870
- await this.mempools.attestationPool?.addBlockProposal(block);
871
- const attestations = await this.blockReceivedCallback(block, sender);
872
1071
 
873
- // TODO: fix up this pattern - the abstraction is not nice
874
- // The attestation can be undefined if no handler is registered / the validator deems the block invalid
875
- if (attestations?.length) {
876
- for (const attestation of attestations) {
877
- this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber.toNumber()}`, {
878
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
879
- slot: attestation.slotNumber.toNumber(),
880
- archive: attestation.archive.toString(),
1072
+ // Call the block received callback to validate the proposal.
1073
+ // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1074
+ const isValid = await this.blockReceivedCallback(block, sender);
1075
+ if (!isValid) {
1076
+ this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1077
+ }
1078
+ }
1079
+
1080
+ /**
1081
+ * Handle a gossiped checkpoint proposal.
1082
+ * Validates and processes the checkpoint proposal, then triggers the callback for attestation.
1083
+ */
1084
+ private async handleGossipedCheckpointProposal(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
1085
+ // TODO(palla/mbps): This pattern is repeated across multiple message handlers, consider abstracting it.
1086
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointProposal>> = async () => {
1087
+ const checkpoint = CheckpointProposal.fromBuffer(payloadData);
1088
+ const validationResult = await this.validateCheckpointProposal(source, checkpoint);
1089
+ const isValid = validationResult.result === 'accept';
1090
+ const pool = this.mempools.attestationPool;
1091
+
1092
+ const exists = isValid && (await pool.hasCheckpointProposal(checkpoint));
1093
+ const canAdd = isValid && (await pool.canAddCheckpointProposal(checkpoint));
1094
+
1095
+ this.logger.trace(`Validate propagated checkpoint proposal`, {
1096
+ isValid,
1097
+ exists,
1098
+ canAdd,
1099
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1100
+ [Attributes.P2P_ID]: source.toString(),
1101
+ });
1102
+
1103
+ if (validationResult.result === 'reject') {
1104
+ return { result: TopicValidatorResult.Reject };
1105
+ } else if (validationResult.result === 'ignore' || exists) {
1106
+ return { result: TopicValidatorResult.Ignore, obj: checkpoint };
1107
+ } else if (!canAdd) {
1108
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
1109
+ this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1110
+ slot: checkpoint.slotNumber.toString(),
1111
+ archive: checkpoint.archive.toString(),
1112
+ source: source.toString(),
881
1113
  });
882
- await this.broadcastAttestation(attestation);
1114
+ return { result: TopicValidatorResult.Reject };
1115
+ } else {
1116
+ return { result: TopicValidatorResult.Accept, obj: checkpoint };
883
1117
  }
1118
+ };
1119
+
1120
+ const { result, obj: checkpoint } = await this.validateReceivedMessage<CheckpointProposal>(
1121
+ validationFunc,
1122
+ msgId,
1123
+ source,
1124
+ TopicType.checkpoint_proposal,
1125
+ );
1126
+
1127
+ if (result !== TopicValidatorResult.Accept || !checkpoint) {
1128
+ return;
884
1129
  }
1130
+
1131
+ await this.processValidCheckpointProposal(checkpoint, source);
885
1132
  }
886
1133
 
887
1134
  /**
888
- * Broadcast an attestation to all peers.
889
- * @param attestation - The attestation to broadcast.
1135
+ * Process a validated checkpoint proposal.
1136
+ * Extracts and processes the last block proposal (if present) first, then processes the checkpoint.
1137
+ * The block callback is invoked before the checkpoint callback.
890
1138
  */
891
- @trackSpan('Libp2pService.broadcastAttestation', async attestation => ({
892
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
893
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
894
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then(i => i.toString()),
1139
+ @trackSpan('Libp2pService.processValidCheckpointProposal', async checkpoint => ({
1140
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
1141
+ [Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
1142
+ [Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then(i => i.toString()),
895
1143
  }))
896
- private async broadcastAttestation(attestation: BlockAttestation) {
897
- await this.propagate(attestation);
1144
+ private async processValidCheckpointProposal(checkpoint: CheckpointProposal, sender: PeerId) {
1145
+ const slot = checkpoint.slotNumber;
1146
+ this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
1147
+ p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
1148
+ slot: checkpoint.slotNumber,
1149
+ archive: checkpoint.archive.toString(),
1150
+ source: sender.toString(),
1151
+ });
1152
+
1153
+ // Extract block proposal before adding to pool (pool stores them separately)
1154
+ const blockProposal = checkpoint.getBlockProposal();
1155
+
1156
+ // Add proposal to the pool (this extracts and stores block proposal separately)
1157
+ await this.mempools.attestationPool.addCheckpointProposal(checkpoint);
1158
+
1159
+ // Mark txs as non-evictable if present (from the last block)
1160
+ if (checkpoint.txHashes.length > 0) {
1161
+ await this.mempools.txPool.markTxsAsNonEvictable(checkpoint.txHashes);
1162
+ }
1163
+
1164
+ // If there was a last block proposal, invoke the block callback first for validation.
1165
+ // Note: The block proposal is already stored in the pool by addCheckpointProposal.
1166
+ if (blockProposal) {
1167
+ const isValid = await this.blockReceivedCallback(blockProposal, sender);
1168
+ if (!isValid) {
1169
+ this.logger.warn(`Block proposal from checkpoint failed validation`, {
1170
+ slot: slot.toString(),
1171
+ archive: checkpoint.archive.toString(),
1172
+ blockNumber: blockProposal.blockNumber.toString(),
1173
+ });
1174
+ return;
1175
+ }
1176
+ }
1177
+
1178
+ // Call the checkpoint received callback with the core version (without lastBlock)
1179
+ // to validate and potentially generate attestations
1180
+ const attestations = await this.checkpointReceivedCallback(checkpoint.toCore(), sender);
1181
+ if (attestations && attestations.length > 0) {
1182
+ // If the callback returned attestations, add them to the pool and propagate them
1183
+ await this.mempools.attestationPool.addCheckpointAttestations(attestations);
1184
+ for (const attestation of attestations) {
1185
+ await this.propagate(attestation);
1186
+ }
1187
+ }
898
1188
  }
899
1189
 
900
1190
  /**
@@ -902,19 +1192,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
902
1192
  * @param message - The message to propagate.
903
1193
  */
904
1194
  public async propagate<T extends Gossipable>(message: T) {
905
- const p2pMessageIdentifier = await message.p2pMessageIdentifier();
1195
+ const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
906
1196
  this.logger.trace(`Message ${p2pMessageIdentifier} queued`, { p2pMessageIdentifier });
907
- void this.jobQueue
908
- .put(async () => {
909
- await this.sendToPeers(message);
910
- })
911
- .catch(error => {
912
- this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
913
- });
1197
+ void this.sendToPeers(message).catch(error => {
1198
+ this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
1199
+ });
914
1200
  }
915
1201
 
916
1202
  /**
917
- * Validate the requested block transactions.
1203
+ * Validate the requested block transactions. Allow partial returns.
918
1204
  * @param request - The block transactions request.
919
1205
  * @param response - The block transactions response.
920
1206
  * @param peerId - The ID of the peer that made the request.
@@ -924,14 +1210,71 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
924
1210
  [Attributes.BLOCK_HASH]: request.blockHash.toString(),
925
1211
  }))
926
1212
  private async validateRequestedBlockTxs(
927
- _request: BlockTxsRequest,
1213
+ request: BlockTxsRequest,
928
1214
  response: BlockTxsResponse,
929
1215
  peerId: PeerId,
930
1216
  ): Promise<boolean> {
931
1217
  const requestedTxValidator = this.createRequestedTxValidator();
932
1218
 
933
1219
  try {
934
- // TODO(palla/txs): Validate that this tx belongs to the block hash being requested
1220
+ if (!response.blockHash.equals(request.blockHash)) {
1221
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1222
+ throw new ValidationError(
1223
+ `Received block txs for unexpected block: expected ${request.blockHash.toString()}, got ${response.blockHash.toString()}`,
1224
+ );
1225
+ }
1226
+
1227
+ if (response.txIndices.getLength() !== request.txIndices.getLength()) {
1228
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1229
+ throw new ValidationError(
1230
+ `Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`,
1231
+ );
1232
+ }
1233
+
1234
+ // Check no duplicates and not exceeding returnable count
1235
+ const requestedIndices = new Set(request.txIndices.getTrueIndices());
1236
+ const availableIndices = new Set(response.txIndices.getTrueIndices());
1237
+ const maxReturnable = [...requestedIndices].filter(i => availableIndices.has(i)).length;
1238
+
1239
+ const returnedHashes = await Promise.all(response.txs.map(tx => tx.getTxHash().toString()));
1240
+ const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
1241
+ if (uniqueReturned.size !== returnedHashes.length) {
1242
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1243
+ throw new ValidationError(`Received duplicate txs in block txs response`);
1244
+ }
1245
+ if (response.txs.length > maxReturnable) {
1246
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1247
+ throw new ValidationError(
1248
+ `Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`,
1249
+ );
1250
+ }
1251
+
1252
+ // Given proposal (should have locally), ensure returned txs are valid subset and match request indices
1253
+ const proposal = await this.mempools.attestationPool.getBlockProposal(request.blockHash.toString());
1254
+ if (proposal) {
1255
+ // Build intersected indices
1256
+ const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
1257
+
1258
+ // Enforce subset membership and preserve increasing order by index.
1259
+ const hashToIndexInProposal = new Map<string, number>(
1260
+ proposal.txHashes.map((h, i) => [h.toString(), i] as [string, number]),
1261
+ );
1262
+ const allowedIndexSet = new Set(intersectIdx);
1263
+ const indices = returnedHashes.map(h => hashToIndexInProposal.get(h));
1264
+ const allAllowed = indices.every(idx => idx !== undefined && allowedIndexSet.has(idx));
1265
+ const strictlyIncreasing = indices.every((idx, i) => (i === 0 ? idx !== undefined : idx! > indices[i - 1]!));
1266
+ if (!allAllowed || !strictlyIncreasing) {
1267
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1268
+ throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
1269
+ }
1270
+ } else {
1271
+ // No local proposal, cannot check the membership/order of the returned txs
1272
+ this.logger.warn(
1273
+ `Block proposal not found for block hash ${request.blockHash.toString()}; cannot validate membership/order of returned txs`,
1274
+ );
1275
+ return false;
1276
+ }
1277
+
935
1278
  await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
936
1279
  return true;
937
1280
  } catch (e: any) {
@@ -955,7 +1298,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
955
1298
  * ReqRespSubProtocol.TX subprotocol validation.
956
1299
  *
957
1300
  * @param requestedTxHash - The collection of the txs that was requested.
958
- * @param responseTx - The collectin of txs that was received as a response to the request.
1301
+ * @param responseTx - The collection of txs that was received as a response to the request.
959
1302
  * @param peerId - The peer ID of the peer that sent the tx.
960
1303
  * @returns True if the whole collection of txs is valid, false otherwise.
961
1304
  */
@@ -982,9 +1325,57 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
982
1325
  }
983
1326
  }
984
1327
 
1328
+ /**
1329
+ * Validates a BLOCK response.
1330
+ *
1331
+ * If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
1332
+ * Penalizes on block number mismatch or hash mismatch.
1333
+ *
1334
+ * @param requestedBlockNumber - The requested block number.
1335
+ * @param responseBlock - The block returned by the peer.
1336
+ * @param peerId - The peer that returned the block.
1337
+ * @returns True if the response is valid, false otherwise.
1338
+ */
1339
+ @trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
1340
+ [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
1341
+ }))
1342
+ private async validateRequestedBlock(
1343
+ requestedBlockNumber: Fr,
1344
+ responseBlock: L2Block,
1345
+ peerId: PeerId,
1346
+ ): Promise<boolean> {
1347
+ try {
1348
+ const reqNum = Number(requestedBlockNumber.toString());
1349
+ if (responseBlock.number !== reqNum) {
1350
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1351
+ return false;
1352
+ }
1353
+
1354
+ const local = await this.archiver.getBlock(BlockNumber(reqNum));
1355
+ if (!local) {
1356
+ // We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
1357
+ // TODO: Consider extending this validator to accept an expected hash or
1358
+ // performing quorum-based checks when using P2P syncing prior to L1 sync.
1359
+ this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
1360
+ return false;
1361
+ }
1362
+ const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
1363
+ if (!localHash.equals(respHash)) {
1364
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1365
+ return false;
1366
+ }
1367
+
1368
+ return true;
1369
+ } catch (e) {
1370
+ this.logger.warn(`Error validating requested block`, e);
1371
+ return false;
1372
+ }
1373
+ }
1374
+
985
1375
  private createRequestedTxValidator(): TxValidator {
986
1376
  return new AggregateTxValidator(
987
1377
  new DataTxValidator(),
1378
+ new SizeTxValidator(),
988
1379
  new MetadataTxValidator({
989
1380
  l1ChainId: new Fr(this.config.l1ChainId),
990
1381
  rollupVersion: new Fr(this.config.rollupVersion),
@@ -996,19 +1387,21 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
996
1387
  }
997
1388
 
998
1389
  private async validateRequestedTx(tx: Tx, peerId: PeerId, txValidator: TxValidator, requested?: Set<`0x${string}`>) {
1390
+ const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
1391
+
999
1392
  if (!(await tx.validateTxHash())) {
1000
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1393
+ penalize(PeerErrorSeverity.MidToleranceError);
1001
1394
  throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
1002
1395
  }
1003
1396
 
1004
1397
  if (requested && !requested.has(tx.getTxHash().toString())) {
1005
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1398
+ penalize(PeerErrorSeverity.MidToleranceError);
1006
1399
  throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
1007
1400
  }
1008
1401
 
1009
1402
  const { result } = await txValidator.validateTx(tx);
1010
1403
  if (result === 'invalid') {
1011
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1404
+ penalize(PeerErrorSeverity.LowToleranceError);
1012
1405
  throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
1013
1406
  }
1014
1407
  }
@@ -1034,7 +1427,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1034
1427
 
1035
1428
  // Double spend validator has a special case handler
1036
1429
  if (name === 'doubleSpendValidator') {
1037
- const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
1430
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
1038
1431
  severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1039
1432
  }
1040
1433
 
@@ -1044,7 +1437,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1044
1437
  return true;
1045
1438
  }
1046
1439
 
1047
- private async getGasFees(blockNumber: number): Promise<GasFees> {
1440
+ private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
1048
1441
  if (blockNumber === this.feesCache?.blockNumber) {
1049
1442
  return this.feesCache.gasFees;
1050
1443
  }
@@ -1085,13 +1478,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1085
1478
  * @returns The message validators.
1086
1479
  */
1087
1480
  private async createMessageValidators(
1088
- currentBlockNumber: number,
1481
+ currentBlockNumber: BlockNumber,
1089
1482
  nextSlotTimestamp: UInt64,
1090
1483
  ): Promise<Record<string, MessageValidator>[]> {
1091
1484
  const gasFees = await this.getGasFees(currentBlockNumber);
1092
1485
  const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1093
1486
 
1094
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
1487
+ const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1095
1488
 
1096
1489
  return createTxMessageValidators(
1097
1490
  nextSlotTimestamp,
@@ -1153,7 +1546,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1153
1546
  * @param peerId - The peer ID of the peer that sent the tx.
1154
1547
  * @returns Severity
1155
1548
  */
1156
- private async handleDoubleSpendFailure(tx: Tx, blockNumber: number): Promise<PeerErrorSeverity> {
1549
+ private async handleDoubleSpendFailure(tx: Tx, blockNumber: BlockNumber): Promise<PeerErrorSeverity> {
1157
1550
  if (blockNumber <= this.config.doubleSpendSeverePeerPenaltyWindow) {
1158
1551
  return PeerErrorSeverity.HighToleranceError;
1159
1552
  }
@@ -1161,7 +1554,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1161
1554
  const snapshotValidator = new DoubleSpendTxValidator({
1162
1555
  nullifiersExist: async (nullifiers: Buffer[]) => {
1163
1556
  const merkleTree = this.worldStateSynchronizer.getSnapshot(
1164
- blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow,
1557
+ BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
1165
1558
  );
1166
1559
  const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
1167
1560
  return indices.map(index => index !== undefined);
@@ -1177,24 +1570,28 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1177
1570
  }
1178
1571
 
1179
1572
  /**
1180
- * Validate an attestation.
1573
+ * Validate a checkpoint attestation.
1181
1574
  *
1182
- * @param attestation - The attestation to validate.
1183
- * @returns True if the attestation is valid, false otherwise.
1575
+ * @param attestation - The checkpoint attestation to validate.
1576
+ * @returns True if the checkpoint attestation is valid, false otherwise.
1184
1577
  */
1185
- @trackSpan('Libp2pService.validateAttestation', async (_, attestation) => ({
1186
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
1578
+ @trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
1579
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
1187
1580
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1188
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then(i => i.toString()),
1581
+ [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1189
1582
  }))
1190
- public async validateAttestation(peerId: PeerId, attestation: BlockAttestation): Promise<boolean> {
1191
- const severity = await this.attestationValidator.validate(attestation);
1192
- if (severity) {
1193
- this.peerManager.penalizePeer(peerId, severity);
1194
- return false;
1583
+ public async validateCheckpointAttestation(
1584
+ peerId: PeerId,
1585
+ attestation: CheckpointAttestation,
1586
+ ): Promise<P2PValidationResult> {
1587
+ const result = await this.checkpointAttestationValidator.validate(attestation);
1588
+
1589
+ if (result.result === 'reject') {
1590
+ this.logger.debug(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1591
+ this.peerManager.penalizePeer(peerId, result.severity);
1195
1592
  }
1196
1593
 
1197
- return true;
1594
+ return result;
1198
1595
  }
1199
1596
 
1200
1597
  /**
@@ -1204,17 +1601,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1204
1601
  * @returns True if the block proposal is valid, false otherwise.
1205
1602
  */
1206
1603
  @trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
1207
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
1604
+ [Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
1208
1605
  }))
1209
- public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
1210
- const severity = await this.blockProposalValidator.validate(block);
1211
- if (severity) {
1606
+ public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<P2PValidationResult> {
1607
+ const result = await this.blockProposalValidator.validate(block);
1608
+
1609
+ if (result.result === 'reject') {
1212
1610
  this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
1213
- this.peerManager.penalizePeer(peerId, severity);
1214
- return false;
1611
+ this.peerManager.penalizePeer(peerId, result.severity);
1215
1612
  }
1216
1613
 
1217
- return true;
1614
+ return result;
1615
+ }
1616
+
1617
+ /**
1618
+ * Validate a checkpoint proposal.
1619
+ *
1620
+ * @param checkpoint - The checkpoint proposal to validate.
1621
+ * @returns True if the checkpoint proposal is valid, false otherwise.
1622
+ */
1623
+ @trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint) => ({
1624
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1625
+ }))
1626
+ public async validateCheckpointProposal(
1627
+ peerId: PeerId,
1628
+ checkpoint: CheckpointProposal,
1629
+ ): Promise<P2PValidationResult> {
1630
+ const result = await this.checkpointProposalValidator.validate(checkpoint);
1631
+
1632
+ if (result.result === 'reject') {
1633
+ this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1634
+ this.peerManager.penalizePeer(peerId, result.severity);
1635
+ }
1636
+
1637
+ return result;
1218
1638
  }
1219
1639
 
1220
1640
  public getPeerScore(peerId: PeerId): number {
@@ -1228,7 +1648,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1228
1648
  private async sendToPeers<T extends Gossipable>(message: T) {
1229
1649
  const parent = message.constructor as typeof Gossipable;
1230
1650
 
1231
- const identifier = await message.p2pMessageIdentifier().then(i => i.toString());
1651
+ const identifier = await message.p2pMessageLoggingIdentifier().then(i => i.toString());
1232
1652
  this.logger.trace(`Sending message ${identifier}`, { p2pMessageIdentifier: identifier });
1233
1653
 
1234
1654
  const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);