@aztec/p2p 0.0.1-commit.cd76b27 → 0.0.1-commit.ce4f8c4f2

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 (267) hide show
  1. package/README.md +129 -3
  2. package/dest/client/factory.d.ts +5 -6
  3. package/dest/client/factory.d.ts.map +1 -1
  4. package/dest/client/factory.js +28 -26
  5. package/dest/client/interface.d.ts +6 -13
  6. package/dest/client/interface.d.ts.map +1 -1
  7. package/dest/client/p2p_client.d.ts +5 -13
  8. package/dest/client/p2p_client.d.ts.map +1 -1
  9. package/dest/client/p2p_client.js +25 -92
  10. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +4 -5
  11. package/dest/config.d.ts +33 -15
  12. package/dest/config.d.ts.map +1 -1
  13. package/dest/config.js +86 -37
  14. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -4
  15. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  16. package/dest/mem_pools/attestation_pool/attestation_pool.js +8 -4
  17. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
  18. package/dest/mem_pools/instrumentation.d.ts +4 -2
  19. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  20. package/dest/mem_pools/instrumentation.js +16 -14
  21. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  22. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  23. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
  24. package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
  25. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  26. package/dest/mem_pools/tx_pool/priority.js +4 -4
  27. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  28. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  29. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
  30. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  31. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  32. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +3 -2
  33. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
  34. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
  35. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +2 -0
  36. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +7 -1
  37. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  38. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
  39. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
  40. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  41. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +10 -6
  42. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +1 -1
  43. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  44. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +8 -6
  45. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +2 -2
  46. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
  47. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
  48. package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
  49. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool_v2/index.js +1 -1
  51. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +15 -9
  52. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  53. package/dest/mem_pools/tx_pool_v2/interfaces.js +3 -1
  54. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +48 -11
  55. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  56. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +81 -17
  57. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
  58. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +26 -44
  60. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +5 -3
  61. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  62. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +6 -0
  63. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +3 -2
  64. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  65. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +196 -151
  66. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
  67. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  68. package/dest/msg_validators/attestation_validator/attestation_validator.js +5 -4
  69. package/dest/msg_validators/clock_tolerance.d.ts +1 -1
  70. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  71. package/dest/msg_validators/clock_tolerance.js +4 -3
  72. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
  73. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  74. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
  75. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
  76. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  77. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
  78. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
  79. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  80. package/dest/msg_validators/proposal_validator/proposal_validator.js +53 -41
  81. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
  82. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  83. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
  84. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
  85. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  86. package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
  87. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  88. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  89. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  90. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  91. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  92. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  93. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  94. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/tx_validator/data_validator.js +35 -2
  96. package/dest/msg_validators/tx_validator/factory.d.ts +133 -6
  97. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  98. package/dest/msg_validators/tx_validator/factory.js +247 -60
  99. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  100. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  101. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  102. package/dest/msg_validators/tx_validator/gas_validator.d.ts +67 -3
  103. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  104. package/dest/msg_validators/tx_validator/gas_validator.js +104 -37
  105. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  106. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  107. package/dest/msg_validators/tx_validator/index.js +2 -0
  108. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  109. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  110. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  111. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  112. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  113. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  114. package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
  115. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  116. package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
  117. package/dest/services/discv5/discV5_service.d.ts +1 -1
  118. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  119. package/dest/services/discv5/discV5_service.js +4 -2
  120. package/dest/services/dummy_service.d.ts +2 -3
  121. package/dest/services/dummy_service.d.ts.map +1 -1
  122. package/dest/services/dummy_service.js +1 -4
  123. package/dest/services/encoding.d.ts +6 -2
  124. package/dest/services/encoding.d.ts.map +1 -1
  125. package/dest/services/encoding.js +14 -8
  126. package/dest/services/libp2p/libp2p_service.d.ts +20 -20
  127. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  128. package/dest/services/libp2p/libp2p_service.js +221 -143
  129. package/dest/services/peer-manager/metrics.d.ts +3 -1
  130. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  131. package/dest/services/peer-manager/metrics.js +6 -0
  132. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  133. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  134. package/dest/services/peer-manager/peer_manager.js +6 -3
  135. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -8
  136. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  137. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +82 -101
  138. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +3 -2
  139. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  140. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
  141. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  142. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
  143. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -11
  144. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  145. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +52 -15
  146. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
  147. package/dest/services/reqresp/reqresp.d.ts +1 -1
  148. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  149. package/dest/services/reqresp/reqresp.js +19 -10
  150. package/dest/services/service.d.ts +8 -2
  151. package/dest/services/service.d.ts.map +1 -1
  152. package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -4
  153. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  154. package/dest/services/tx_collection/fast_tx_collection.js +57 -73
  155. package/dest/services/tx_collection/proposal_tx_collector.d.ts +6 -7
  156. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  157. package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
  158. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  159. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  160. package/dest/services/tx_collection/request_tracker.js +84 -0
  161. package/dest/services/tx_collection/slow_tx_collection.js +1 -1
  162. package/dest/services/tx_collection/tx_collection.d.ts +3 -6
  163. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  164. package/dest/services/tx_provider.d.ts +3 -3
  165. package/dest/services/tx_provider.d.ts.map +1 -1
  166. package/dest/services/tx_provider.js +4 -4
  167. package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
  168. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  169. package/dest/test-helpers/make-test-p2p-clients.js +1 -2
  170. package/dest/test-helpers/mock-pubsub.d.ts +7 -3
  171. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  172. package/dest/test-helpers/mock-pubsub.js +11 -3
  173. package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
  174. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  175. package/dest/test-helpers/reqresp-nodes.js +2 -2
  176. package/dest/test-helpers/testbench-utils.d.ts +2 -2
  177. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  178. package/dest/test-helpers/testbench-utils.js +22 -3
  179. package/dest/testbench/p2p_client_testbench_worker.js +10 -9
  180. package/dest/testbench/worker_client_manager.d.ts +3 -1
  181. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  182. package/dest/testbench/worker_client_manager.js +6 -2
  183. package/dest/util.d.ts +9 -4
  184. package/dest/util.d.ts.map +1 -1
  185. package/dest/util.js +2 -9
  186. package/package.json +14 -14
  187. package/src/client/factory.ts +45 -45
  188. package/src/client/interface.ts +5 -19
  189. package/src/client/p2p_client.ts +26 -122
  190. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +5 -8
  191. package/src/config.ts +125 -43
  192. package/src/mem_pools/attestation_pool/attestation_pool.ts +8 -7
  193. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
  194. package/src/mem_pools/instrumentation.ts +17 -13
  195. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  196. package/src/mem_pools/tx_pool/priority.ts +4 -4
  197. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
  198. package/src/mem_pools/tx_pool_v2/README.md +9 -1
  199. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +3 -2
  200. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -0
  201. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +11 -1
  202. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +2 -2
  203. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +10 -6
  204. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +15 -6
  205. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +2 -1
  206. package/src/mem_pools/tx_pool_v2/index.ts +1 -1
  207. package/src/mem_pools/tx_pool_v2/interfaces.ts +16 -8
  208. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +115 -20
  209. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +29 -43
  210. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +17 -2
  211. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +207 -154
  212. package/src/msg_validators/attestation_validator/README.md +49 -0
  213. package/src/msg_validators/attestation_validator/attestation_validator.ts +5 -4
  214. package/src/msg_validators/clock_tolerance.ts +4 -3
  215. package/src/msg_validators/proposal_validator/README.md +123 -0
  216. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
  217. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
  218. package/src/msg_validators/proposal_validator/proposal_validator.ts +69 -45
  219. package/src/msg_validators/tx_validator/README.md +119 -0
  220. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
  221. package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
  222. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  223. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  224. package/src/msg_validators/tx_validator/data_validator.ts +42 -1
  225. package/src/msg_validators/tx_validator/factory.ts +394 -78
  226. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  227. package/src/msg_validators/tx_validator/gas_validator.ts +123 -27
  228. package/src/msg_validators/tx_validator/index.ts +2 -0
  229. package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
  230. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  231. package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
  232. package/src/services/discv5/discV5_service.ts +4 -2
  233. package/src/services/dummy_service.ts +1 -5
  234. package/src/services/encoding.ts +14 -7
  235. package/src/services/libp2p/libp2p_service.ts +235 -166
  236. package/src/services/peer-manager/metrics.ts +7 -0
  237. package/src/services/peer-manager/peer_manager.ts +7 -3
  238. package/src/services/reqresp/README.md +229 -0
  239. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  240. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +78 -111
  241. package/src/services/reqresp/batch-tx-requester/interface.ts +2 -1
  242. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
  243. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
  244. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
  245. package/src/services/reqresp/reqresp.ts +22 -12
  246. package/src/services/service.ts +8 -1
  247. package/src/services/tx_collection/fast_tx_collection.ts +57 -83
  248. package/src/services/tx_collection/proposal_tx_collector.ts +8 -13
  249. package/src/services/tx_collection/request_tracker.ts +127 -0
  250. package/src/services/tx_collection/slow_tx_collection.ts +1 -1
  251. package/src/services/tx_collection/tx_collection.ts +3 -5
  252. package/src/services/tx_provider.ts +2 -2
  253. package/src/test-helpers/make-test-p2p-clients.ts +1 -3
  254. package/src/test-helpers/mock-pubsub.ts +12 -6
  255. package/src/test-helpers/reqresp-nodes.ts +3 -6
  256. package/src/test-helpers/testbench-utils.ts +30 -4
  257. package/src/testbench/p2p_client_testbench_worker.ts +7 -12
  258. package/src/testbench/worker_client_manager.ts +13 -5
  259. package/src/util.ts +9 -13
  260. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
  261. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
  262. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
  263. package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
  264. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
  265. package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
  266. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
  267. package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
@@ -370,14 +370,15 @@ function applyDecs2203RFactory() {
370
370
  function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
371
371
  return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
372
372
  }
373
- var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _initProto;
373
+ var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _initProto;
374
374
  import { BlockNumber } from '@aztec/foundation/branded-types';
375
+ import { maxBy } from '@aztec/foundation/collection';
375
376
  import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
376
377
  import { RunningPromise } from '@aztec/foundation/running-promise';
377
378
  import { Timer } from '@aztec/foundation/timer';
378
379
  import { protocolContractsHash } from '@aztec/protocol-contracts';
379
380
  import { GasFees } from '@aztec/stdlib/gas';
380
- import { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PClientType, P2PMessage, PeerErrorSeverity, TopicType, createTopicString, getTopicsForClientAndConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
381
+ import { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PMessage, PeerErrorSeverity, PeerErrorSeverityByHarshness, TopicType, createTopicString, getTopicsForConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
381
382
  import { MerkleTreeId } from '@aztec/stdlib/trees';
382
383
  import { Tx } from '@aztec/stdlib/tx';
383
384
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
@@ -392,11 +393,12 @@ import { identify } from '@libp2p/identify';
392
393
  import { TopicValidatorResult } from '@libp2p/interface';
393
394
  import { mplex } from '@libp2p/mplex';
394
395
  import { tcp } from '@libp2p/tcp';
396
+ import { multiaddr } from '@multiformats/multiaddr';
395
397
  import { ENR } from '@nethermindeth/enr';
396
398
  import { createLibp2p } from 'libp2p';
397
399
  import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, DoubleSpendTxValidator, FishermanAttestationValidator, getDefaultAllowedSetupFunctions } from '../../msg_validators/index.js';
398
400
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
399
- import { createTxMessageValidators, createTxReqRespValidator } from '../../msg_validators/tx_validator/factory.js';
401
+ import { createFirstStageTxValidationsForGossipedTransactions, createSecondStageTxValidationsForGossipedTransactions, createTxValidatorForBlockProposalReceivedTxs, createTxValidatorForReqResponseReceivedTxs } from '../../msg_validators/tx_validator/factory.js';
400
402
  import { GossipSubEvent } from '../../types/index.js';
401
403
  import { convertToMultiaddr } from '../../util.js';
402
404
  import { getVersions } from '../../versioning.js';
@@ -407,8 +409,7 @@ import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring
407
409
  import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
408
410
  import { PeerManager } from '../peer-manager/peer_manager.js';
409
411
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
410
- import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/index.js';
411
- import { pingHandler, reqGoodbyeHandler, reqRespBlockHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
412
+ import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError, pingHandler, reqGoodbyeHandler, reqRespBlockHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
412
413
  import { ReqResp } from '../reqresp/reqresp.js';
413
414
  import { P2PInstrumentation } from './instrumentation.js';
414
415
  _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation)=>({
@@ -432,17 +433,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
432
433
  [Attributes.TX_HASH]: requestedTxHash.toString()
433
434
  })), _dec7 = trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock)=>({
434
435
  [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString()
435
- })), _dec8 = trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
436
- [Attributes.TX_HASH]: tx.getTxHash().toString()
437
- })), _dec9 = trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation)=>({
438
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
439
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
440
- [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then((i)=>i.toString())
441
436
  }));
442
437
  /**
443
438
  * Lib P2P implementation of the P2PService interface.
444
439
  */ export class LibP2PService extends WithTracer {
445
- clientType;
446
440
  config;
447
441
  node;
448
442
  peerDiscoveryService;
@@ -494,16 +488,6 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
494
488
  _dec7,
495
489
  2,
496
490
  "validateRequestedBlock"
497
- ],
498
- [
499
- _dec8,
500
- 2,
501
- "validatePropagatedTx"
502
- ],
503
- [
504
- _dec9,
505
- 2,
506
- "validateCheckpointAttestation"
507
491
  ]
508
492
  ], []));
509
493
  }
@@ -529,11 +513,13 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
529
513
  * @returns The attestations for the checkpoint, if any.
530
514
  */ checkpointReceivedCallback;
531
515
  gossipSubEventHandler;
516
+ ipChangedHandler;
517
+ /** Discovered public IP address (set when queryForIp is enabled and no static IP was configured). */ discoveredP2pIp;
532
518
  instrumentation;
533
519
  telemetry;
534
520
  logger;
535
- constructor(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
536
- super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.msgIdSeenValidators = (_initProto(this), {}), this.protocolVersion = '', this.topicStrings = {};
521
+ constructor(config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
522
+ super(telemetry, 'LibP2PService'), this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.msgIdSeenValidators = (_initProto(this), {}), this.protocolVersion = '', this.topicStrings = {};
537
523
  this.telemetry = telemetry;
538
524
  // Create child logger with fisherman prefix if in fisherman mode
539
525
  this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
@@ -549,19 +535,19 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
549
535
  this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
550
536
  this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(TopicType.checkpoint_proposal, this.protocolVersion);
551
537
  this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(TopicType.checkpoint_attestation, this.protocolVersion);
552
- this.blockProposalValidator = new BlockProposalValidator(epochCache, {
553
- txsPermitted: !config.disableTransactions
554
- });
555
- this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
556
- txsPermitted: !config.disableTransactions
557
- });
538
+ const proposalValidatorOpts = {
539
+ txsPermitted: !config.disableTransactions,
540
+ maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint
541
+ };
542
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
543
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
558
544
  this.checkpointAttestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry) : new CheckpointAttestationValidator(epochCache);
559
545
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
560
546
  this.blockReceivedCallback = async (block)=>{
561
- this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`, {
547
+ this.logger.warn(`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`, {
562
548
  p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier()
563
549
  });
564
- return false;
550
+ return true;
565
551
  };
566
552
  this.checkpointReceivedCallback = (checkpoint)=>{
567
553
  this.logger.debug(`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`);
@@ -576,7 +562,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
576
562
  * @param config - The configuration to use when creating the service.
577
563
  * @param txPool - The transaction pool to be accessed by the service.
578
564
  * @returns The new service.
579
- */ static async new(clientType, config, peerId, deps) {
565
+ */ static async new(config, peerId, deps) {
580
566
  const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, telemetry, logger, packageVersion } = deps;
581
567
  const { p2pPort, maxPeerCount, listenAddress } = config;
582
568
  const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
@@ -726,7 +712,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
726
712
  })
727
713
  }),
728
714
  components: (components)=>({
729
- connectionManager: components.connectionManager
715
+ connectionManager: components.connectionManager,
716
+ addressManager: components.addressManager
730
717
  })
731
718
  },
732
719
  logger: createLibp2pComponentLogger(logger.module, logger.getBindings())
@@ -741,7 +728,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
741
728
  // Note: positive topic scores can offset penalties, so alignment is best-effort.
742
729
  node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
743
730
  node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
744
- return new LibP2PService(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
731
+ return new LibP2PService(config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
745
732
  }
746
733
  /**
747
734
  * Starts the LibP2P service.
@@ -753,10 +740,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
753
740
  }
754
741
  // Get listen & announce addresses for logging
755
742
  const { p2pIp, p2pPort } = this.config;
756
- if (!p2pIp) {
743
+ if (!p2pIp && !this.config.queryForIp) {
757
744
  throw new Error('Announce address not provided.');
758
745
  }
759
- const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
746
+ const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
760
747
  // Create request response protocol handlers
761
748
  const txHandler = reqRespTxHandler(this.mempools);
762
749
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
@@ -786,7 +773,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
786
773
  await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
787
774
  await this.node.start();
788
775
  // Subscribe to standard GossipSub topics by default
789
- for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)){
776
+ for (const topic of getTopicsForConfig(this.config.disableTransactions)){
790
777
  this.subscribeToTopic(this.topicStrings[topic]);
791
778
  }
792
779
  // add GossipSub listener
@@ -795,6 +782,29 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
795
782
  if (!this.config.p2pDiscoveryDisabled) {
796
783
  await this.peerDiscoveryService.start();
797
784
  }
785
+ // When queryForIp is enabled and no static IP was configured, bridge discv5 IP discovery to libp2p.
786
+ // Discv5 discovers our public IP via peer WHOAREYOU exchanges (enrUpdate=true) and emits 'ip:changed'.
787
+ // We confirm the discovered address in the libp2p AddressManager so it appears in getMultiaddrs()
788
+ // and is pushed to all connected peers via the identify protocol.
789
+ if (this.config.queryForIp && !p2pIp) {
790
+ this.ipChangedHandler = (ip)=>{
791
+ const addressManager = this.node.services.components.addressManager;
792
+ const newAddr = multiaddr(convertToMultiaddr(ip, this.config.p2pPort, 'tcp'));
793
+ // Remove old discovered IP if one exists
794
+ if (this.discoveredP2pIp) {
795
+ const oldAddr = multiaddr(convertToMultiaddr(this.discoveredP2pIp, this.config.p2pPort, 'tcp'));
796
+ addressManager.removeObservedAddr(oldAddr);
797
+ }
798
+ addressManager.addObservedAddr(newAddr);
799
+ addressManager.confirmObservedAddr(newAddr);
800
+ // Store discovered IP
801
+ this.discoveredP2pIp = ip;
802
+ this.logger.info('Public IP discovered via discv5', {
803
+ ip
804
+ });
805
+ };
806
+ this.peerDiscoveryService.on('ip:changed', this.ipChangedHandler);
807
+ }
798
808
  this.discoveryRunningPromise = new RunningPromise(async ()=>{
799
809
  await this.peerManager.heartbeat();
800
810
  }, this.logger, this.config.peerCheckIntervalMS);
@@ -802,7 +812,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
802
812
  this.logger.info(`Started P2P service`, {
803
813
  listen: this.config.listenAddress,
804
814
  port: this.config.p2pPort,
805
- announce: announceTcpMultiaddr,
815
+ announce: announceTcpMultiaddr ?? 'pending (queryForIp=true)',
806
816
  peerId: this.node.peerId.toString()
807
817
  });
808
818
  }
@@ -812,6 +822,11 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
812
822
  */ async stop() {
813
823
  // Remove gossip sub listener
814
824
  this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
825
+ // Remove ip:changed listener if registered
826
+ if (this.ipChangedHandler) {
827
+ this.peerDiscoveryService.off('ip:changed', this.ipChangedHandler);
828
+ this.ipChangedHandler = undefined;
829
+ }
815
830
  // Stop peer manager
816
831
  this.logger.debug('Stopping peer manager...');
817
832
  await this.peerManager.stop();
@@ -935,6 +950,12 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
935
950
  if (!validator || !validator.addMessage(msgId)) {
936
951
  this.instrumentation.incMessagePrevalidationStatus(false, topicType);
937
952
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
953
+ if (topicType === TopicType.tx) {
954
+ this.logger.verbose(`Ignoring already-seen tx gossip message`, {
955
+ msgId,
956
+ source: source.toString()
957
+ });
958
+ }
938
959
  return {
939
960
  result: false,
940
961
  topicType
@@ -995,9 +1016,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
995
1016
  if (msg.topic === this.topicStrings[TopicType.tx]) {
996
1017
  await this.handleGossipedTx(p2pMessage.payload, msgId, source);
997
1018
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
998
- if (this.clientType === P2PClientType.Full) {
999
- await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
1000
- }
1019
+ await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
1001
1020
  } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
1002
1021
  await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
1003
1022
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
@@ -1042,39 +1061,119 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1042
1061
  return;
1043
1062
  }
1044
1063
  async validateReceivedMessage(validationFunc, msgId, source, topicType) {
1064
+ // Default to reject result with a penalty if validation function throws an error
1045
1065
  let resultAndObj = {
1046
- result: TopicValidatorResult.Reject
1066
+ result: TopicValidatorResult.Reject,
1067
+ severity: PeerErrorSeverity.MidToleranceError
1047
1068
  };
1048
1069
  const timer = new Timer();
1049
1070
  try {
1050
1071
  resultAndObj = await validationFunc();
1051
1072
  } catch (err) {
1052
- this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
1053
- this.logger.error(`Error deserializing and validating gossipsub message`, err, {
1073
+ this.logger.error(`Error validating gossipsub message`, err, {
1054
1074
  msgId,
1055
1075
  source: source.toString(),
1056
1076
  topicType
1057
1077
  });
1058
1078
  }
1059
1079
  if (resultAndObj.result === TopicValidatorResult.Accept) {
1080
+ this.logger.debug(`Message ${topicType} accepted by validator`, {
1081
+ msgId,
1082
+ source: source.toString(),
1083
+ topicType
1084
+ });
1060
1085
  this.instrumentation.recordMessageValidation(topicType, timer);
1086
+ } else if (resultAndObj.result === TopicValidatorResult.Reject) {
1087
+ this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
1088
+ msgId,
1089
+ source: source.toString(),
1090
+ topicType,
1091
+ severity: resultAndObj.severity
1092
+ });
1093
+ this.peerManager.penalizePeer(source, resultAndObj.severity);
1094
+ } else {
1095
+ this.logger.trace(`Message ${topicType} ignored by validator`, {
1096
+ msgId,
1097
+ source: source.toString(),
1098
+ topicType
1099
+ });
1061
1100
  }
1062
1101
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
1063
1102
  return resultAndObj;
1064
1103
  }
1104
+ tryDeserialize(deserializeFunc, msgId, source) {
1105
+ try {
1106
+ return deserializeFunc();
1107
+ } catch (err) {
1108
+ this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
1109
+ err,
1110
+ msgId,
1111
+ source: source.toString()
1112
+ });
1113
+ return undefined;
1114
+ }
1115
+ }
1065
1116
  async handleGossipedTx(payloadData, msgId, source) {
1066
1117
  const validationFunc = async ()=>{
1067
- const tx = Tx.fromBuffer(payloadData);
1068
- const isValid = await this.validatePropagatedTx(tx, source);
1069
- if (!isValid) {
1070
- this.logger.trace(`Rejecting invalid propagated tx`, {
1071
- [Attributes.P2P_ID]: source.toString()
1118
+ const tx = this.tryDeserialize(()=>Tx.fromBuffer(payloadData), msgId, source);
1119
+ if (!tx) {
1120
+ return {
1121
+ result: TopicValidatorResult.Reject,
1122
+ severity: PeerErrorSeverity.LowToleranceError
1123
+ };
1124
+ }
1125
+ const currentBlockNumber = await this.archiver.getBlockNumber();
1126
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1127
+ // Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
1128
+ const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
1129
+ const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
1130
+ if (!firstStageOutcome.allPassed) {
1131
+ const { name } = firstStageOutcome.failure;
1132
+ let { severity } = firstStageOutcome.failure;
1133
+ // Double spend validator has a special case handler. We perform more detailed examination
1134
+ // as to how recently the nullifier was entered into the tree and if the transaction should
1135
+ // have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
1136
+ if (name === 'doubleSpendValidator') {
1137
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1);
1138
+ severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1139
+ }
1140
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
1141
+ validator: name,
1142
+ severity,
1143
+ source: source.toString()
1072
1144
  });
1073
1145
  return {
1074
- result: TopicValidatorResult.Reject
1146
+ result: TopicValidatorResult.Reject,
1147
+ severity
1075
1148
  };
1076
1149
  }
1077
- // Propagate only on pool acceptance
1150
+ // Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
1151
+ const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
1152
+ if (canAdd === 'ignored') {
1153
+ this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
1154
+ source: source.toString()
1155
+ });
1156
+ return {
1157
+ result: TopicValidatorResult.Ignore,
1158
+ obj: tx
1159
+ };
1160
+ }
1161
+ // Stage 2: expensive proof verification
1162
+ const secondStageValidators = this.createSecondStageMessageValidators();
1163
+ const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
1164
+ if (!secondStageOutcome.allPassed) {
1165
+ const { severity, name } = secondStageOutcome.failure;
1166
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
1167
+ validator: name,
1168
+ severity,
1169
+ source: source.toString()
1170
+ });
1171
+ return {
1172
+ result: TopicValidatorResult.Reject,
1173
+ severity
1174
+ };
1175
+ }
1176
+ // Pool add: persist the tx
1078
1177
  const txHash = tx.getTxHash();
1079
1178
  const addResult = await this.mempools.txPool.addPendingTxs([
1080
1179
  tx
@@ -1083,8 +1182,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1083
1182
  });
1084
1183
  const wasAccepted = addResult.accepted.some((h)=>h.equals(txHash));
1085
1184
  const wasIgnored = addResult.ignored.some((h)=>h.equals(txHash));
1086
- this.logger.trace(`Validate propagated tx`, {
1087
- isValid,
1185
+ this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
1088
1186
  wasAccepted,
1089
1187
  wasIgnored,
1090
1188
  [Attributes.P2P_ID]: source.toString()
@@ -1100,8 +1198,13 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1100
1198
  obj: tx
1101
1199
  };
1102
1200
  } else {
1201
+ this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
1202
+ source: source.toString(),
1203
+ txHash: txHash.toString()
1204
+ });
1103
1205
  return {
1104
- result: TopicValidatorResult.Reject
1206
+ result: TopicValidatorResult.Reject,
1207
+ severity: PeerErrorSeverity.HighToleranceError
1105
1208
  };
1106
1209
  }
1107
1210
  };
@@ -1122,7 +1225,16 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1122
1225
  * Process a checkpoint attestation from a peer.
1123
1226
  * Validates the attestation and adds it to the pool.
1124
1227
  */ async processCheckpointAttestationFromPeer(payloadData, msgId, source) {
1125
- const { result, obj: attestation } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_attestation);
1228
+ const { result, obj: attestation } = await this.validateReceivedMessage(()=>{
1229
+ const attestation = this.tryDeserialize(()=>CheckpointAttestation.fromBuffer(payloadData), msgId, source);
1230
+ if (!attestation) {
1231
+ return Promise.resolve({
1232
+ result: TopicValidatorResult.Reject,
1233
+ severity: PeerErrorSeverity.LowToleranceError
1234
+ });
1235
+ }
1236
+ return this.validateAndStoreCheckpointAttestation(source, attestation);
1237
+ }, msgId, source, TopicType.checkpoint_attestation);
1126
1238
  if (result !== TopicValidatorResult.Accept || !attestation) {
1127
1239
  return;
1128
1240
  }
@@ -1137,9 +1249,9 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1137
1249
  const validationResult = await this.checkpointAttestationValidator.validate(attestation);
1138
1250
  if (validationResult.result === 'reject') {
1139
1251
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1140
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1141
1252
  return {
1142
- result: TopicValidatorResult.Reject
1253
+ result: TopicValidatorResult.Reject,
1254
+ severity: validationResult.severity
1143
1255
  };
1144
1256
  }
1145
1257
  if (validationResult.result === 'ignore') {
@@ -1166,9 +1278,9 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1166
1278
  obj: attestation
1167
1279
  };
1168
1280
  }
1169
- // Could not add (cap reached for signer), no need to re-broadcast
1281
+ // Could not add (cap reached for signer), penalize and do not re-broadcast
1170
1282
  if (!added) {
1171
- this.logger.warn(`Dropping checkpoint attestation due to cap`, {
1283
+ this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
1172
1284
  slot: slot.toString(),
1173
1285
  archive: attestation.archive.toString(),
1174
1286
  source: peerId.toString(),
@@ -1176,8 +1288,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1176
1288
  count
1177
1289
  });
1178
1290
  return {
1179
- result: TopicValidatorResult.Ignore,
1180
- obj: attestation
1291
+ result: TopicValidatorResult.Reject,
1292
+ severity: PeerErrorSeverity.HighToleranceError
1181
1293
  };
1182
1294
  }
1183
1295
  // Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
@@ -1215,9 +1327,9 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1215
1327
  const validationResult = await this.blockProposalValidator.validate(block);
1216
1328
  if (validationResult.result === 'reject') {
1217
1329
  this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
1218
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1219
1330
  return {
1220
- result: TopicValidatorResult.Reject
1331
+ result: TopicValidatorResult.Reject,
1332
+ severity: validationResult.severity
1221
1333
  };
1222
1334
  }
1223
1335
  if (validationResult.result === 'ignore') {
@@ -1247,7 +1359,6 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1247
1359
  }
1248
1360
  // Too many blocks received for this slot and index, penalize peer and do not re-broadcast
1249
1361
  if (!added) {
1250
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1251
1362
  this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1252
1363
  ...block.toBlockInfo(),
1253
1364
  indexWithinCheckpoint: block.indexWithinCheckpoint,
@@ -1259,7 +1370,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1259
1370
  result: TopicValidatorResult.Reject,
1260
1371
  metadata: {
1261
1372
  isEquivocated
1262
- }
1373
+ },
1374
+ severity: PeerErrorSeverity.HighToleranceError
1263
1375
  };
1264
1376
  }
1265
1377
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1308,7 +1420,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1308
1420
  // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1309
1421
  const isValid = await this.blockReceivedCallback(block, sender);
1310
1422
  if (!isValid) {
1311
- this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1423
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1312
1424
  }
1313
1425
  }
1314
1426
  /**
@@ -1333,9 +1445,9 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1333
1445
  const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
1334
1446
  if (validationResult.result === 'reject') {
1335
1447
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1336
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1337
1448
  return {
1338
- result: TopicValidatorResult.Reject
1449
+ result: TopicValidatorResult.Reject,
1450
+ severity: validationResult.severity
1339
1451
  };
1340
1452
  }
1341
1453
  if (validationResult.result === 'ignore') {
@@ -1352,18 +1464,20 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1352
1464
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1353
1465
  [Attributes.P2P_ID]: peerId.toString()
1354
1466
  });
1355
- const { result, obj, metadata: { isEquivocated } = {} } = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1356
- if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1467
+ const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1468
+ const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
1469
+ if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1357
1470
  this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
1358
1471
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1359
1472
  [Attributes.P2P_ID]: peerId.toString(),
1360
1473
  isEquivocated,
1361
- result
1474
+ result: blockProposalResult.result
1362
1475
  });
1363
1476
  return {
1364
- result: TopicValidatorResult.Reject
1477
+ result: TopicValidatorResult.Reject,
1478
+ severity: 'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError
1365
1479
  };
1366
- } else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1480
+ } else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1367
1481
  processBlock = true;
1368
1482
  }
1369
1483
  }
@@ -1390,7 +1504,6 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1390
1504
  // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
1391
1505
  // Note: We still return the checkpoint obj so the lastBlock can be processed if valid
1392
1506
  if (!added) {
1393
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1394
1507
  this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1395
1508
  ...checkpoint.toCheckpointInfo(),
1396
1509
  count,
@@ -1402,7 +1515,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1402
1515
  metadata: {
1403
1516
  isEquivocated,
1404
1517
  processBlock
1405
- }
1518
+ },
1519
+ severity: PeerErrorSeverity.HighToleranceError
1406
1520
  };
1407
1521
  }
1408
1522
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1626,33 +1740,11 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1626
1740
  }
1627
1741
  }
1628
1742
  createRequestedTxValidator() {
1629
- return createTxReqRespValidator(this.proofVerifier, {
1743
+ return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
1630
1744
  l1ChainId: this.config.l1ChainId,
1631
1745
  rollupVersion: this.config.rollupVersion
1632
1746
  });
1633
1747
  }
1634
- async validatePropagatedTx(tx, peerId) {
1635
- const currentBlockNumber = await this.archiver.getBlockNumber();
1636
- // We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
1637
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1638
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1639
- for (const validator of messageValidators){
1640
- const outcome = await this.runValidations(tx, validator);
1641
- if (outcome.allPassed) {
1642
- continue;
1643
- }
1644
- const { name } = outcome.failure;
1645
- let { severity } = outcome.failure;
1646
- // Double spend validator has a special case handler
1647
- if (name === 'doubleSpendValidator') {
1648
- const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
1649
- severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1650
- }
1651
- this.peerManager.penalizePeer(peerId, severity);
1652
- return false;
1653
- }
1654
- return true;
1655
- }
1656
1748
  async getGasFees(blockNumber) {
1657
1749
  if (blockNumber === this.feesCache?.blockNumber) {
1658
1750
  return this.feesCache.gasFees;
@@ -1679,38 +1771,35 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1679
1771
  peerScoring: this.peerManager
1680
1772
  };
1681
1773
  }
1682
- async validate(txs) {
1683
- const currentBlockNumber = await this.archiver.getBlockNumber();
1684
- // We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
1685
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1686
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1687
- await Promise.all(txs.map(async (tx)=>{
1688
- for (const validator of messageValidators){
1689
- const outcome = await this.runValidations(tx, validator);
1690
- if (!outcome.allPassed) {
1691
- throw new Error('Invalid tx detected', {
1692
- cause: {
1693
- outcome
1694
- }
1695
- });
1696
- }
1697
- }
1774
+ async validateTxsReceivedInBlockProposal(txs) {
1775
+ const validator = createTxValidatorForBlockProposalReceivedTxs(this.proofVerifier, {
1776
+ l1ChainId: this.config.l1ChainId,
1777
+ rollupVersion: this.config.rollupVersion
1778
+ }, this.logger.getBindings());
1779
+ const results = await Promise.all(txs.map(async (tx)=>{
1780
+ const result = await validator.validateTx(tx);
1781
+ return result.result !== 'invalid';
1698
1782
  }));
1783
+ if (results.some((value)=>value === false)) {
1784
+ throw new Error('Invalid tx detected');
1785
+ }
1699
1786
  }
1700
- /**
1701
- * Create message validators for the given block number and timestamp.
1702
- *
1703
- * Each validator is a pair of a validator and a severity.
1704
- * If a validator fails, the peer is penalized with the severity of the validator.
1705
- *
1706
- * @param currentBlockNumber - The current synced block number.
1707
- * @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
1708
- * @returns The message validators.
1709
- */ async createMessageValidators(currentBlockNumber, nextSlotTimestamp) {
1787
+ /** Creates the first stage (fast) validators for gossiped transactions. */ async createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp) {
1710
1788
  const gasFees = await this.getGasFees(currentBlockNumber);
1711
- const allowedInSetup = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
1712
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1713
- return createTxMessageValidators(nextSlotTimestamp, blockNumberInWhichTheTxIsConsideredToBeIncluded, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, this.proofVerifier, !this.config.disableTransactions, allowedInSetup, this.logger.getBindings());
1789
+ const allowedInSetup = [
1790
+ ...await getDefaultAllowedSetupFunctions(),
1791
+ ...this.config.txPublicSetupAllowListExtend ?? []
1792
+ ];
1793
+ const blockNumber = BlockNumber(currentBlockNumber + 1);
1794
+ const l1Constants = await this.archiver.getL1Constants();
1795
+ return createFirstStageTxValidationsForGossipedTransactions(nextSlotTimestamp, blockNumber, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, !this.config.disableTransactions, allowedInSetup, this.logger.getBindings(), {
1796
+ rollupManaLimit: l1Constants.rollupManaLimit,
1797
+ maxBlockL2Gas: this.config.validateMaxL2BlockGas,
1798
+ maxBlockDAGas: this.config.validateMaxDABlockGas
1799
+ });
1800
+ }
1801
+ /** Creates the second stage (expensive proof verification) validators for gossiped transactions. */ createSecondStageMessageValidators() {
1802
+ return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
1714
1803
  }
1715
1804
  /**
1716
1805
  * Run validations on a tx.
@@ -1728,8 +1817,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1728
1817
  });
1729
1818
  // A promise that resolves when all validations have been run
1730
1819
  const allValidations = await Promise.all(validationPromises);
1731
- const failed = allValidations.find((x)=>!x.isValid);
1732
- if (failed) {
1820
+ const failures = allValidations.filter((x)=>!x.isValid);
1821
+ if (failures.length > 0) {
1822
+ // Pick the most severe failure (lowest tolerance = harshest penalty)
1823
+ const failed = maxBy(failures, (f)=>PeerErrorSeverityByHarshness.indexOf(f.severity));
1733
1824
  return {
1734
1825
  allPassed: false,
1735
1826
  failure: {
@@ -1776,19 +1867,6 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
1776
1867
  }
1777
1868
  return PeerErrorSeverity.HighToleranceError;
1778
1869
  }
1779
- /**
1780
- * Validate a checkpoint attestation.
1781
- *
1782
- * @param attestation - The checkpoint attestation to validate.
1783
- * @returns True if the checkpoint attestation is valid, false otherwise.
1784
- */ async validateCheckpointAttestation(peerId, attestation) {
1785
- const result = await this.checkpointAttestationValidator.validate(attestation);
1786
- if (result.result === 'reject') {
1787
- this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1788
- this.peerManager.penalizePeer(peerId, result.severity);
1789
- }
1790
- return result;
1791
- }
1792
1870
  getPeerScore(peerId) {
1793
1871
  return this.node.services.pubsub.score.score(peerId.toString());
1794
1872
  }