@aztec/p2p 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a

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 (243) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +1 -1
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +9 -1
  4. package/dest/client/factory.d.ts +3 -3
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +12 -9
  7. package/dest/client/interface.d.ts +6 -4
  8. package/dest/client/interface.d.ts.map +1 -1
  9. package/dest/client/p2p_client.d.ts +11 -8
  10. package/dest/client/p2p_client.d.ts.map +1 -1
  11. package/dest/client/p2p_client.js +53 -17
  12. package/dest/config.d.ts +43 -17
  13. package/dest/config.d.ts.map +1 -1
  14. package/dest/config.js +48 -8
  15. package/dest/errors/reqresp.error.d.ts +1 -20
  16. package/dest/errors/reqresp.error.d.ts.map +1 -1
  17. package/dest/errors/reqresp.error.js +0 -21
  18. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +93 -55
  19. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  20. package/dest/mem_pools/attestation_pool/attestation_pool.js +258 -195
  21. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  22. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  23. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +175 -59
  24. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
  25. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  26. package/dest/mem_pools/attestation_pool/mocks.js +6 -4
  27. package/dest/mem_pools/instrumentation.d.ts +1 -1
  28. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  29. package/dest/mem_pools/instrumentation.js +17 -1
  30. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -5
  31. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
  32. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +1 -7
  33. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
  34. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  35. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +73 -83
  36. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +5 -2
  37. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  38. package/dest/msg_validators/attestation_validator/attestation_validator.js +18 -2
  39. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -3
  40. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  41. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +3 -4
  42. package/dest/msg_validators/clock_tolerance.d.ts +1 -1
  43. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  44. package/dest/msg_validators/clock_tolerance.js +13 -11
  45. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +5 -2
  46. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  47. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +5 -2
  48. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  49. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +8 -2
  50. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  51. package/dest/msg_validators/proposal_validator/proposal_validator.js +28 -2
  52. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  53. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  54. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
  55. package/dest/msg_validators/tx_validator/allowed_public_setup.js +3 -3
  56. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  57. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  58. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  59. package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
  60. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  61. package/dest/msg_validators/tx_validator/data_validator.js +1 -0
  62. package/dest/msg_validators/tx_validator/factory.d.ts +5 -4
  63. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  64. package/dest/msg_validators/tx_validator/factory.js +11 -7
  65. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  66. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  67. package/dest/msg_validators/tx_validator/index.js +2 -0
  68. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
  69. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  70. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
  71. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  72. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  73. package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
  74. package/dest/services/discv5/discV5_service.d.ts +2 -1
  75. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  76. package/dest/services/discv5/discV5_service.js +35 -8
  77. package/dest/services/dummy_service.d.ts +10 -17
  78. package/dest/services/dummy_service.d.ts.map +1 -1
  79. package/dest/services/dummy_service.js +9 -18
  80. package/dest/services/libp2p/libp2p_service.d.ts +19 -21
  81. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  82. package/dest/services/libp2p/libp2p_service.js +147 -148
  83. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  84. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  85. package/dest/services/peer-manager/peer_manager.js +1 -0
  86. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +1 -8
  87. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  88. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +35 -44
  89. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +8 -5
  90. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  91. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
  92. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
  93. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
  94. package/dest/services/reqresp/interface.d.ts +3 -10
  95. package/dest/services/reqresp/interface.d.ts.map +1 -1
  96. package/dest/services/reqresp/interface.js +0 -9
  97. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
  98. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  99. package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
  100. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  101. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  102. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
  103. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
  104. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  105. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +42 -24
  106. package/dest/services/reqresp/reqresp.d.ts +5 -29
  107. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  108. package/dest/services/reqresp/reqresp.js +16 -206
  109. package/dest/services/service.d.ts +7 -13
  110. package/dest/services/service.d.ts.map +1 -1
  111. package/dest/services/tx_collection/config.d.ts +2 -23
  112. package/dest/services/tx_collection/config.d.ts.map +1 -1
  113. package/dest/services/tx_collection/config.js +2 -55
  114. package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
  115. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
  116. package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
  117. package/dest/services/tx_collection/index.d.ts +2 -3
  118. package/dest/services/tx_collection/index.d.ts.map +1 -1
  119. package/dest/services/tx_collection/index.js +0 -1
  120. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  121. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  122. package/dest/services/tx_collection/instrumentation.js +0 -2
  123. package/dest/services/tx_collection/tx_collection.d.ts +35 -51
  124. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  125. package/dest/services/tx_collection/tx_collection.js +275 -119
  126. package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
  127. package/dest/services/tx_collection/tx_collection_sink.js +2 -2
  128. package/dest/services/tx_file_store/tx_file_store.d.ts +1 -3
  129. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  130. package/dest/services/tx_file_store/tx_file_store.js +4 -14
  131. package/dest/services/tx_provider.d.ts +3 -1
  132. package/dest/services/tx_provider.d.ts.map +1 -1
  133. package/dest/services/tx_provider.js +3 -0
  134. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  135. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  136. package/dest/test-helpers/make-test-p2p-clients.js +1 -1
  137. package/dest/test-helpers/mock-pubsub.d.ts +13 -7
  138. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  139. package/dest/test-helpers/mock-pubsub.js +12 -37
  140. package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
  141. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  142. package/dest/test-helpers/reqresp-nodes.js +11 -15
  143. package/dest/test-helpers/test_tx_provider.d.ts +3 -1
  144. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
  145. package/dest/test-helpers/test_tx_provider.js +3 -0
  146. package/dest/test-helpers/testbench-utils.d.ts +12 -14
  147. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  148. package/dest/test-helpers/testbench-utils.js +19 -14
  149. package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
  150. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  151. package/dest/testbench/p2p_client_testbench_worker.js +13 -24
  152. package/dest/testbench/worker_client_manager.d.ts +3 -6
  153. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  154. package/dest/testbench/worker_client_manager.js +2 -8
  155. package/dest/util.d.ts +11 -6
  156. package/dest/util.d.ts.map +1 -1
  157. package/dest/util.js +35 -14
  158. package/dest/versioning.d.ts +3 -6
  159. package/dest/versioning.d.ts.map +1 -1
  160. package/dest/versioning.js +3 -24
  161. package/package.json +15 -14
  162. package/src/bootstrap/bootstrap.ts +9 -1
  163. package/src/client/factory.ts +20 -5
  164. package/src/client/interface.ts +6 -10
  165. package/src/client/p2p_client.ts +61 -36
  166. package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
  167. package/src/config.ts +94 -6
  168. package/src/errors/reqresp.error.ts +0 -25
  169. package/src/mem_pools/attestation_pool/attestation_pool.ts +309 -238
  170. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +198 -62
  171. package/src/mem_pools/attestation_pool/mocks.ts +13 -8
  172. package/src/mem_pools/instrumentation.ts +5 -1
  173. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
  174. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +73 -90
  175. package/src/msg_validators/attestation_validator/attestation_validator.ts +21 -1
  176. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +11 -7
  177. package/src/msg_validators/clock_tolerance.ts +13 -12
  178. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +9 -2
  179. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +14 -2
  180. package/src/msg_validators/proposal_validator/proposal_validator.ts +39 -2
  181. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
  182. package/src/msg_validators/tx_validator/allowed_public_setup.ts +3 -3
  183. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  184. package/src/msg_validators/tx_validator/data_validator.ts +2 -0
  185. package/src/msg_validators/tx_validator/factory.ts +15 -6
  186. package/src/msg_validators/tx_validator/index.ts +2 -0
  187. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
  188. package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
  189. package/src/services/discv5/discV5_service.ts +38 -5
  190. package/src/services/dummy_service.ts +12 -43
  191. package/src/services/libp2p/libp2p_service.ts +169 -167
  192. package/src/services/peer-manager/peer_manager.ts +1 -0
  193. package/src/services/reqresp/README.md +0 -14
  194. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +39 -52
  195. package/src/services/reqresp/batch-tx-requester/interface.ts +11 -4
  196. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
  197. package/src/services/reqresp/interface.ts +2 -38
  198. package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
  199. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
  200. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
  201. package/src/services/reqresp/reqresp.ts +11 -251
  202. package/src/services/service.ts +9 -30
  203. package/src/services/tx_collection/config.ts +3 -80
  204. package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
  205. package/src/services/tx_collection/index.ts +1 -6
  206. package/src/services/tx_collection/instrumentation.ts +1 -7
  207. package/src/services/tx_collection/tx_collection.ts +330 -173
  208. package/src/services/tx_collection/tx_collection_sink.ts +2 -2
  209. package/src/services/tx_file_store/tx_file_store.ts +5 -17
  210. package/src/services/tx_provider.ts +5 -0
  211. package/src/test-helpers/make-test-p2p-clients.ts +1 -0
  212. package/src/test-helpers/mock-pubsub.ts +17 -60
  213. package/src/test-helpers/reqresp-nodes.ts +8 -20
  214. package/src/test-helpers/test_tx_provider.ts +5 -0
  215. package/src/test-helpers/testbench-utils.ts +23 -27
  216. package/src/testbench/p2p_client_testbench_worker.ts +16 -42
  217. package/src/testbench/worker_client_manager.ts +4 -19
  218. package/src/util.ts +32 -17
  219. package/src/versioning.ts +3 -33
  220. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
  221. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
  222. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -318
  223. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
  224. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
  225. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
  226. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
  227. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  228. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
  229. package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -51
  230. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
  231. package/dest/services/tx_collection/fast_tx_collection.js +0 -311
  232. package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -48
  233. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
  234. package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
  235. package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
  236. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
  237. package/dest/services/tx_collection/slow_tx_collection.js +0 -211
  238. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -357
  239. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
  240. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
  241. package/src/services/tx_collection/fast_tx_collection.ts +0 -361
  242. package/src/services/tx_collection/proposal_tx_collector.ts +0 -108
  243. package/src/services/tx_collection/slow_tx_collection.ts +0 -266
@@ -1,6 +1,6 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
- import { maxBy } from '@aztec/foundation/collection';
3
+ import { maxBy, merge } from '@aztec/foundation/collection';
4
4
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
5
5
  import { RunningPromise } from '@aztec/foundation/running-promise';
6
6
  import { Timer } from '@aztec/foundation/timer';
@@ -25,7 +25,7 @@ import {
25
25
  metricsTopicStrToLabels,
26
26
  } from '@aztec/stdlib/p2p';
27
27
  import { MerkleTreeId } from '@aztec/stdlib/trees';
28
- import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
28
+ import { Tx, type TxValidationResult } from '@aztec/stdlib/tx';
29
29
  import type { UInt64 } from '@aztec/stdlib/types';
30
30
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
31
31
  import {
@@ -50,9 +50,10 @@ import { yamux } from '@chainsafe/libp2p-yamux';
50
50
  import { bootstrap } from '@libp2p/bootstrap';
51
51
  import { identify } from '@libp2p/identify';
52
52
  import { type Message, type MultiaddrConnection, type PeerId, TopicValidatorResult } from '@libp2p/interface';
53
- import type { ConnectionManager } from '@libp2p/interface-internal';
53
+ import type { AddressManager, ConnectionManager } from '@libp2p/interface-internal';
54
54
  import { mplex } from '@libp2p/mplex';
55
55
  import { tcp } from '@libp2p/tcp';
56
+ import { multiaddr } from '@multiformats/multiaddr';
56
57
  import { ENR } from '@nethermindeth/enr';
57
58
  import { createLibp2p } from 'libp2p';
58
59
 
@@ -73,8 +74,8 @@ import {
73
74
  createFirstStageTxValidationsForGossipedTransactions,
74
75
  createSecondStageTxValidationsForGossipedTransactions,
75
76
  createTxValidatorForBlockProposalReceivedTxs,
76
- createTxValidatorForReqResponseReceivedTxs,
77
77
  } from '../../msg_validators/tx_validator/factory.js';
78
+ import { TxValidationCache } from '../../msg_validators/tx_validator/tx_validation_cache.js';
78
79
  import { GossipSubEvent } from '../../types/index.js';
79
80
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
80
81
  import { getVersions } from '../../versioning.js';
@@ -92,15 +93,12 @@ import {
92
93
  AuthRequest,
93
94
  BlockTxsRequest,
94
95
  BlockTxsResponse,
95
- DEFAULT_SUB_PROTOCOL_VALIDATORS,
96
96
  type ReqRespInterface,
97
97
  type ReqRespResponse,
98
98
  ReqRespSubProtocol,
99
99
  type ReqRespSubProtocolHandler,
100
100
  type ReqRespSubProtocolHandlers,
101
- type ReqRespSubProtocolValidators,
102
101
  StatusMessage,
103
- type SubProtocolMap,
104
102
  ValidationError,
105
103
  pingHandler,
106
104
  reqGoodbyeHandler,
@@ -111,6 +109,7 @@ import {
111
109
  import { ReqResp } from '../reqresp/reqresp.js';
112
110
  import type {
113
111
  P2PBlockReceivedCallback,
112
+ P2PCheckpointAttestationCallback,
114
113
  P2PCheckpointReceivedCallback,
115
114
  P2PDuplicateAttestationCallback,
116
115
  P2PService,
@@ -156,6 +155,9 @@ export class LibP2PService extends WithTracer implements P2PService {
156
155
  /** Callback invoked when a duplicate attestation is detected (triggers slashing). */
157
156
  private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
158
157
 
158
+ /** Callback invoked when a valid checkpoint attestation is accepted into the pool. */
159
+ private checkpointAttestationCallback?: P2PCheckpointAttestationCallback;
160
+
159
161
  /**
160
162
  * Callback for when a block is received from a peer.
161
163
  * @param block - The block received from the peer.
@@ -178,6 +180,9 @@ export class LibP2PService extends WithTracer implements P2PService {
178
180
 
179
181
  private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
180
182
 
183
+ private ipChangedHandler?: (ip: string) => void;
184
+ private discoveredP2pIp?: string;
185
+
181
186
  private instrumentation: P2PInstrumentation;
182
187
 
183
188
  private telemetry: TelemetryClient;
@@ -198,6 +203,7 @@ export class LibP2PService extends WithTracer implements P2PService {
198
203
  private blockMinFeesProvider: BlockMinFeesProvider,
199
204
  telemetry: TelemetryClient,
200
205
  logger: Logger = createLogger('p2p:libp2p_service'),
206
+ private txValidationCache?: TxValidationCache,
201
207
  ) {
202
208
  super(telemetry, 'LibP2PService');
203
209
  this.telemetry = telemetry;
@@ -231,15 +237,24 @@ export class LibP2PService extends WithTracer implements P2PService {
231
237
  const proposalValidatorOpts = {
232
238
  txsPermitted: !config.disableTransactions,
233
239
  maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
240
+ maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
234
241
  p2pPropagationTime,
242
+ skipSlotValidation: config.skipProposalSlotValidation,
243
+ signatureContext: {
244
+ chainId: config.l1ChainId,
245
+ rollupAddress: config.rollupAddress,
246
+ },
235
247
  };
236
248
  this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
237
249
  this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
250
+ const attestationValidatorOpts = {
251
+ l1PublishingTime: config.l1PublishingTime,
252
+ p2pPropagationTime,
253
+ signatureContext: proposalValidatorOpts.signatureContext,
254
+ };
238
255
  this.checkpointAttestationValidator = config.fishermanMode
239
- ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, {
240
- l1PublishingTime: config.l1PublishingTime,
241
- })
242
- : new CheckpointAttestationValidator(epochCache, { l1PublishingTime: config.l1PublishingTime });
256
+ ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, attestationValidatorOpts)
257
+ : new CheckpointAttestationValidator(epochCache, attestationValidatorOpts);
243
258
 
244
259
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
245
260
 
@@ -264,8 +279,9 @@ export class LibP2PService extends WithTracer implements P2PService {
264
279
  };
265
280
  }
266
281
 
267
- public updateConfig(config: Partial<P2PReqRespConfig>) {
282
+ public updateConfig(config: Partial<P2PReqRespConfig & Pick<P2PConfig, 'skipIncomingProposals'>>) {
268
283
  this.reqresp.updateConfig(config);
284
+ this.config = merge(this.config, config);
269
285
  }
270
286
 
271
287
  /**
@@ -288,6 +304,7 @@ export class LibP2PService extends WithTracer implements P2PService {
288
304
  telemetry: TelemetryClient;
289
305
  logger: Logger;
290
306
  packageVersion: string;
307
+ txValidationCache?: TxValidationCache;
291
308
  },
292
309
  ) {
293
310
  const {
@@ -301,6 +318,7 @@ export class LibP2PService extends WithTracer implements P2PService {
301
318
  telemetry,
302
319
  logger,
303
320
  packageVersion,
321
+ txValidationCache,
304
322
  } = deps;
305
323
  const { p2pPort, maxPeerCount, listenAddress } = config;
306
324
  const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
@@ -458,8 +476,9 @@ export class LibP2PService extends WithTracer implements P2PService {
458
476
  topics: topicScoreParams,
459
477
  }),
460
478
  }) as (components: GossipSubComponents) => GossipSub,
461
- components: (components: { connectionManager: ConnectionManager }) => ({
479
+ components: (components: { connectionManager: ConnectionManager; addressManager: AddressManager }) => ({
462
480
  connectionManager: components.connectionManager,
481
+ addressManager: components.addressManager,
463
482
  }),
464
483
  },
465
484
  logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
@@ -507,6 +526,7 @@ export class LibP2PService extends WithTracer implements P2PService {
507
526
  blockMinFeesProvider,
508
527
  telemetry,
509
528
  logger,
529
+ txValidationCache,
510
530
  );
511
531
  }
512
532
 
@@ -520,12 +540,11 @@ export class LibP2PService extends WithTracer implements P2PService {
520
540
  throw new Error('P2P service already started');
521
541
  }
522
542
 
523
- // Get listen & announce addresses for logging
524
543
  const { p2pIp, p2pPort } = this.config;
525
- if (!p2pIp) {
526
- throw new Error('Announce address not provided.');
544
+ if (!p2pIp && !this.config.queryForIp) {
545
+ throw new Error('Announce address not provided and queryForIp is not enabled.');
527
546
  }
528
- const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
547
+ const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
529
548
 
530
549
  // Create request response protocol handlers
531
550
  const txHandler = reqRespTxHandler(this.mempools);
@@ -551,16 +570,9 @@ export class LibP2PService extends WithTracer implements P2PService {
551
570
  requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
552
571
  }
553
572
 
554
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
555
- const reqrespSubProtocolValidators = {
556
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
557
- [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
558
- [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
559
- };
560
-
561
573
  await this.peerManager.initializePeers();
562
574
 
563
- await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
575
+ await this.reqresp.start(requestResponseHandlers);
564
576
 
565
577
  await this.node.start();
566
578
 
@@ -576,6 +588,38 @@ export class LibP2PService extends WithTracer implements P2PService {
576
588
  if (!this.config.p2pDiscoveryDisabled) {
577
589
  await this.peerDiscoveryService.start();
578
590
  }
591
+
592
+ // Bridge discv5 IP changes to libp2p's AddressManager so peers see the updated address
593
+ if (this.config.queryForIp) {
594
+ this.discoveredP2pIp = this.config.p2pIp;
595
+ this.logger.info('IP change tracking enabled, bridging discv5 IP updates to libp2p AddressManager');
596
+ this.ipChangedHandler = (ip: string) => {
597
+ const addressManager = this.node.services.components.addressManager;
598
+ const newAddr = multiaddr(convertToMultiaddr(ip, this.config.p2pPort, 'tcp'));
599
+ const previousIp = this.discoveredP2pIp;
600
+
601
+ if (previousIp) {
602
+ const oldAddr = multiaddr(convertToMultiaddr(previousIp, this.config.p2pPort, 'tcp'));
603
+ addressManager.removeObservedAddr(oldAddr);
604
+ this.logger.info('Libp2p announce address updated due to IP change', {
605
+ previousIp,
606
+ newIp: ip,
607
+ newMultiaddr: newAddr.toString(),
608
+ });
609
+ } else {
610
+ this.logger.info('Libp2p announce address set from initial discv5 IP discovery', {
611
+ ip,
612
+ multiaddr: newAddr.toString(),
613
+ });
614
+ }
615
+
616
+ addressManager.addObservedAddr(newAddr);
617
+ addressManager.confirmObservedAddr(newAddr);
618
+ this.discoveredP2pIp = ip;
619
+ };
620
+ this.peerDiscoveryService.on('ip:changed', this.ipChangedHandler);
621
+ }
622
+
579
623
  this.discoveryRunningPromise = new RunningPromise(
580
624
  async () => {
581
625
  await this.peerManager.heartbeat();
@@ -601,6 +645,11 @@ export class LibP2PService extends WithTracer implements P2PService {
601
645
  // Remove gossip sub listener
602
646
  this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
603
647
 
648
+ if (this.ipChangedHandler) {
649
+ this.peerDiscoveryService.removeListener('ip:changed', this.ipChangedHandler);
650
+ this.ipChangedHandler = undefined;
651
+ }
652
+
604
653
  // Stop peer manager
605
654
  this.logger.debug('Stopping peer manager...');
606
655
  await this.peerManager.stop();
@@ -615,12 +664,8 @@ export class LibP2PService extends WithTracer implements P2PService {
615
664
  this.logger.info('LibP2P service stopped');
616
665
  }
617
666
 
618
- addReqRespSubProtocol(
619
- subProtocol: ReqRespSubProtocol,
620
- handler: ReqRespSubProtocolHandler,
621
- validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
622
- ): Promise<void> {
623
- return this.reqresp.addSubProtocol(subProtocol, handler, validator);
667
+ addReqRespSubProtocol(subProtocol: ReqRespSubProtocol, handler: ReqRespSubProtocolHandler): Promise<void> {
668
+ return this.reqresp.addSubProtocol(subProtocol, handler);
624
669
  }
625
670
 
626
671
  public registerThisValidatorAddresses(address: EthAddress[]): void {
@@ -648,20 +693,6 @@ export class LibP2PService extends WithTracer implements P2PService {
648
693
  setImmediate(() => void safeJob());
649
694
  }
650
695
 
651
- /**
652
- * Send a batch of requests to peers, and return the responses
653
- * @param protocol - The request response protocol to use
654
- * @param requests - The requests to send to the peers
655
- * @returns The responses to the requests
656
- */
657
- sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
658
- protocol: SubProtocol,
659
- requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
660
- pinnedPeerId: PeerId | undefined,
661
- ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]> {
662
- return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
663
- }
664
-
665
696
  public sendRequestToPeer(
666
697
  peerId: PeerId,
667
698
  subProtocol: ReqRespSubProtocol,
@@ -691,10 +722,6 @@ export class LibP2PService extends WithTracer implements P2PService {
691
722
  this.allNodesCheckpointReceivedCallback = callback;
692
723
  }
693
724
 
694
- public async notifyOwnCheckpointProposal(checkpoint: CheckpointProposalCore): Promise<void> {
695
- await this.allNodesCheckpointReceivedCallback(checkpoint, this.node.peerId);
696
- }
697
-
698
725
  /**
699
726
  * Registers a callback to be invoked when a duplicate proposal is detected.
700
727
  * This callback is triggered on the first duplicate (when count goes from 1 to 2).
@@ -714,6 +741,10 @@ export class LibP2PService extends WithTracer implements P2PService {
714
741
  this.duplicateAttestationCallback = callback;
715
742
  }
716
743
 
744
+ public registerCheckpointAttestationCallback(callback: P2PCheckpointAttestationCallback): void {
745
+ this.checkpointAttestationCallback = callback;
746
+ }
747
+
717
748
  /**
718
749
  * Subscribes to a topic.
719
750
  * @param topic - The topic to subscribe to.
@@ -842,6 +873,15 @@ export class LibP2PService extends WithTracer implements P2PService {
842
873
 
843
874
  // Process the message, optionally within a linked span for trace propagation
844
875
  const processMessage = async () => {
876
+ if (
877
+ this.config.skipIncomingProposals &&
878
+ (msg.topic === this.topicStrings[TopicType.block_proposal] ||
879
+ msg.topic === this.topicStrings[TopicType.checkpoint_proposal])
880
+ ) {
881
+ this.logger.warn(`Ignoring incoming proposal (skipIncomingProposals is set)`, { topic: msg.topic });
882
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
883
+ return;
884
+ }
845
885
  if (msg.topic === this.topicStrings[TopicType.tx]) {
846
886
  await this.handleGossipedTx(p2pMessage.payload, msgId, source);
847
887
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
@@ -1165,6 +1205,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1165
1205
  }
1166
1206
 
1167
1207
  // Attestation was added successfully - accept it so other nodes can also detect the equivocation
1208
+ this.checkpointAttestationCallback?.(attestation);
1168
1209
  return { result: TopicValidatorResult.Accept, obj: attestation };
1169
1210
  }
1170
1211
 
@@ -1301,17 +1342,33 @@ export class LibP2PService extends WithTracer implements P2PService {
1301
1342
  TopicType.checkpoint_proposal,
1302
1343
  );
1303
1344
 
1345
+ // Process checkpoint proposal if valid and not equivocated.
1346
+ const processCheckpointFn = () =>
1347
+ result === TopicValidatorResult.Accept && checkpoint && !isEquivocated
1348
+ ? this.processValidCheckpointProposal(checkpoint.toCore(), source)
1349
+ : Promise.resolve();
1350
+
1304
1351
  // If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
1305
1352
  // TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
1306
- if (processBlock && checkpoint?.getBlockProposal()) {
1307
- await this.processValidBlockProposal(checkpoint.getBlockProposal()!, source);
1308
- }
1309
-
1310
- if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
1353
+ const processBlockFn = () =>
1354
+ processBlock && checkpoint && checkpoint.getBlockProposal()
1355
+ ? this.processValidBlockProposal(checkpoint.getBlockProposal()!, source)
1356
+ : Promise.resolve();
1357
+
1358
+ // A node that skips checkpoint validation attests without re-executing the embedded last block, so run
1359
+ // the checkpoint callback first: this creates and broadcasts the attestation before the block is
1360
+ // processed. Otherwise the block's re-execution — which can stall until the re-execution deadline
1361
+ // waiting for a parent that may never arrive — would delay the attestation past the slot's attestation
1362
+ // window, after which peers reject it as stale.
1363
+ if (this.config.skipCheckpointProposalValidation) {
1364
+ await processCheckpointFn();
1365
+ await processBlockFn();
1311
1366
  return;
1312
1367
  }
1313
1368
 
1314
- await this.processValidCheckpointProposal(checkpoint.toCore(), source);
1369
+ // Process the block first, since it's required for the checkpoint proposal validation.
1370
+ await processBlockFn();
1371
+ await processCheckpointFn();
1315
1372
  }
1316
1373
 
1317
1374
  /**
@@ -1467,82 +1524,87 @@ export class LibP2PService extends WithTracer implements P2PService {
1467
1524
  }
1468
1525
 
1469
1526
  /**
1470
- * Validate the requested block transactions. Allow partial returns.
1527
+ * Validate the requested block transactions request-response consistency.
1528
+ * It does NOT validate the transactions themselves.
1471
1529
  * @param request - The block transactions request.
1472
1530
  * @param response - The block transactions response.
1473
1531
  * @param peerId - The ID of the peer that made the request.
1474
- * @returns True if the requested block transactions are valid, false otherwise.
1532
+ * @returns True if the request-response is consistent, false otherwise.
1475
1533
  */
1476
- @trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
1534
+ @trackSpan('Libp2pService.validateRequestedBlockTxsConsistency', request => ({
1477
1535
  [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
1478
1536
  }))
1479
- protected async validateRequestedBlockTxs(
1537
+ protected async validateRequestedBlockTxsConsistency(
1480
1538
  request: BlockTxsRequest,
1481
1539
  response: BlockTxsResponse,
1482
1540
  peerId: PeerId,
1483
1541
  ): Promise<boolean> {
1484
- const requestedTxValidator = this.createRequestedTxValidator();
1485
-
1486
1542
  try {
1487
- if (!response.archiveRoot.equals(request.archiveRoot)) {
1543
+ // Check for duplicates txs (or hashes) in the response.
1544
+ const returnedHashes = response.txs.map(tx => tx.getTxHash().toString());
1545
+ const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
1546
+ if (uniqueReturned.size !== returnedHashes.length) {
1488
1547
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1489
- throw new ValidationError(
1490
- `Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`,
1548
+ throw new ValidationError(`Received duplicate txs in block txs response`);
1549
+ }
1550
+
1551
+ // We get the block tx hashes from the proposal or the archiver.
1552
+ const proposal = await this.mempools.attestationPool.getBlockProposalByArchive(request.archiveRoot.toString());
1553
+ const blockTxHashes =
1554
+ proposal?.txHashes ??
1555
+ (await this.archiver.getBlock({ archive: request.archiveRoot }))?.body.txEffects.map(e => e.txHash);
1556
+
1557
+ // If we don't have the block, we can't verify membership/order of the returned txs.
1558
+ if (!blockTxHashes) {
1559
+ // This shouldn't happen, since we asked for the block (proposal).
1560
+ // Neither a local proposal nor an archived block: we cannot verify membership/order of the
1561
+ // returned txs. This is a local-state gap, not a peer fault, so we do not penalize.
1562
+ this.logger.warn(
1563
+ `Block ${request.archiveRoot.toString()} not found in attestation pool or archiver; cannot validate membership/order of returned txs`,
1491
1564
  );
1565
+ // NOTE: We mark the response as invalid, given the limitations of a true/false return value.
1566
+ return false;
1492
1567
  }
1493
1568
 
1494
- if (response.txIndices.getLength() !== request.txIndices.getLength()) {
1495
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1569
+ // Verify that the returned tx hashes are a subset of (tx hashes by index) U (explicitly requested tx hashes).
1570
+ const uniqueRequestedHashes = new Set([
1571
+ // tx hashes requested by index.
1572
+ ...request.txIndices.getTrueIndices().map(i => blockTxHashes[i].toString()),
1573
+ // explicitly requested tx hashes.
1574
+ ...request.txHashes.map(h => h.toString()),
1575
+ ]);
1576
+ if (!returnedHashes.every(h => uniqueRequestedHashes.has(h))) {
1577
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1496
1578
  throw new ValidationError(
1497
- `Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`,
1579
+ 'Returned txs should be a subset of (tx hashes by index) U (explicitly requested tx hashes)',
1498
1580
  );
1499
1581
  }
1500
1582
 
1501
- // Check no duplicates and not exceeding returnable count
1502
- const requestedIndices = new Set(request.txIndices.getTrueIndices());
1503
- const availableIndices = new Set(response.txIndices.getTrueIndices());
1504
- const maxReturnable = [...requestedIndices].filter(i => availableIndices.has(i)).length;
1505
-
1506
- const returnedHashes = await Promise.all(response.txs.map(tx => tx.getTxHash().toString()));
1507
- const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
1508
- if (uniqueReturned.size !== returnedHashes.length) {
1509
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1510
- throw new ValidationError(`Received duplicate txs in block txs response`);
1583
+ // Tx indices information is optional, but if present, we need to verify a few things.
1584
+ if (!response.peerHasBlock()) {
1585
+ this.logger.debug(`Peer ${peerId.toString()} signalled missing block`);
1586
+ return true;
1511
1587
  }
1512
- if (response.txs.length > maxReturnable) {
1588
+
1589
+ // If the response has a non-empty bitvector, it needs to be consistent with the number of txs in the block.
1590
+ if (response.txIndices.getLength() !== blockTxHashes.length) {
1513
1591
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1514
1592
  throw new ValidationError(
1515
- `Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`,
1593
+ `Received block txs with mismatched bitvector length: expected ${blockTxHashes.length}, got ${response.txIndices.getLength()}`,
1516
1594
  );
1517
1595
  }
1518
1596
 
1519
- // Given proposal (should have locally), ensure returned txs are valid subset and match request indices
1520
- const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
1521
- if (proposal) {
1522
- // Build intersected indices
1523
- const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
1524
-
1525
- // Enforce subset membership and preserve increasing order by index.
1526
- const hashToIndexInProposal = new Map<string, number>(
1527
- proposal.txHashes.map((h, i) => [h.toString(), i] as [string, number]),
1528
- );
1529
- const allowedIndexSet = new Set(intersectIdx);
1530
- const indices = returnedHashes.map(h => hashToIndexInProposal.get(h));
1531
- const allAllowed = indices.every(idx => idx !== undefined && allowedIndexSet.has(idx));
1532
- const strictlyIncreasing = indices.every((idx, i) => (i === 0 ? idx !== undefined : idx! > indices[i - 1]!));
1533
- if (!allAllowed || !strictlyIncreasing) {
1534
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1535
- throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
1536
- }
1537
- } else {
1538
- // No local proposal, cannot check the membership/order of the returned txs
1539
- this.logger.warn(
1540
- `Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`,
1541
- );
1542
- return false;
1597
+ // For every index we requested that the peer claims to have (per its bitvector), the
1598
+ // corresponding tx must be present in the response. A peer advertising availability but
1599
+ // withholding the tx is inconsistent.
1600
+ const returnedHashSet = new Set(returnedHashes);
1601
+ const expectedIndices = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
1602
+ const missingExpected = expectedIndices.some(i => !returnedHashSet.has(blockTxHashes[i].toString()));
1603
+ if (missingExpected) {
1604
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1605
+ throw new ValidationError('Peer advertised requested txs via indices but did not return them');
1543
1606
  }
1544
1607
 
1545
- await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
1546
1608
  return true;
1547
1609
  } catch (e: any) {
1548
1610
  if (e instanceof ValidationError) {
@@ -1555,69 +1617,6 @@ export class LibP2PService extends WithTracer implements P2PService {
1555
1617
  }
1556
1618
  }
1557
1619
 
1558
- /**
1559
- * Validate a collection of txs that has been requested from a peer.
1560
- *
1561
- * The core component of this validator is that each tx hash MUST match the requested tx hash,
1562
- * In order to perform this check, the tx proof must be verified.
1563
- *
1564
- * Note: This function is called from within `ReqResp.sendRequest` as part of the
1565
- * ReqRespSubProtocol.TX subprotocol validation.
1566
- *
1567
- * @param requestedTxHash - The collection of the txs that was requested.
1568
- * @param responseTx - The collection of txs that was received as a response to the request.
1569
- * @param peerId - The peer ID of the peer that sent the tx.
1570
- * @returns True if the whole collection of txs is valid, false otherwise.
1571
- */
1572
- @trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx) => ({
1573
- [Attributes.TX_HASH]: requestedTxHash.toString(),
1574
- }))
1575
- private async validateRequestedTxs(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
1576
- const requested = new Set(requestedTxHash.map(h => h.toString()));
1577
- const requestedTxValidator = this.createRequestedTxValidator();
1578
-
1579
- //TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
1580
- // I think we should still extract the valid txs and return them, so that we can still use the response.
1581
- try {
1582
- await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
1583
- return true;
1584
- } catch (e: any) {
1585
- if (e instanceof ValidationError) {
1586
- this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
1587
- } else {
1588
- this.logger.error(`Error during validation of requested txs`, e);
1589
- }
1590
-
1591
- return false;
1592
- }
1593
- }
1594
-
1595
- protected async validateRequestedTx(
1596
- tx: Tx,
1597
- peerId: PeerId,
1598
- txValidator: TxValidator,
1599
- requested?: Set<`0x${string}`>,
1600
- ) {
1601
- const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
1602
- if (requested && !requested.has(tx.getTxHash().toString())) {
1603
- penalize(PeerErrorSeverity.MidToleranceError);
1604
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
1605
- }
1606
-
1607
- const { result } = await txValidator.validateTx(tx);
1608
- if (result === 'invalid') {
1609
- penalize(PeerErrorSeverity.LowToleranceError);
1610
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
1611
- }
1612
- }
1613
-
1614
- protected createRequestedTxValidator(): TxValidator {
1615
- return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
1616
- l1ChainId: this.config.l1ChainId,
1617
- rollupVersion: this.config.rollupVersion,
1618
- });
1619
- }
1620
-
1621
1620
  private getGasFees(): Promise<GasFees> {
1622
1621
  return this.blockMinFeesProvider.getCurrentMinFees();
1623
1622
  }
@@ -1633,8 +1632,10 @@ export class LibP2PService extends WithTracer implements P2PService {
1633
1632
  l1ChainId: this.config.l1ChainId,
1634
1633
  rollupVersion: this.config.rollupVersion,
1635
1634
  proofVerifier: this.proofVerifier,
1635
+ txValidationCache: this.txValidationCache,
1636
1636
  },
1637
1637
  peerScoring: this.peerManager,
1638
+ validateRequestedBlockTxsConsistency: this.validateRequestedBlockTxsConsistency.bind(this),
1638
1639
  };
1639
1640
  }
1640
1641
 
@@ -1643,6 +1644,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1643
1644
  this.proofVerifier,
1644
1645
  { l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
1645
1646
  this.logger.getBindings(),
1647
+ this.txValidationCache,
1646
1648
  );
1647
1649
 
1648
1650
  const results = await Promise.all(
@@ -527,6 +527,7 @@ export class PeerManager implements PeerManagerInterface {
527
527
  protectedConnections: protectedPeerCount,
528
528
  maxPeerCount: this.config.maxPeerCount,
529
529
  cachedPeers: this.cachedPeers.size,
530
+ discv5KadPeers: this.peerDiscoveryService.getKadValues().length,
530
531
  ...this.peerScoring.getStats(),
531
532
  });
532
533
 
@@ -46,7 +46,6 @@ Per-protocol size limits checked via preamble before decompression.
46
46
  | Error Type | Severity |
47
47
  |------------|----------|
48
48
  | GOODBYE subprotocol errors | None |
49
- | `CollectiveReqRespTimeoutError` / `InvalidResponseError` | None |
50
49
  | `AbortError` / connection close / muxer closed | None |
51
50
  | `ECONNRESET` / `EPIPE` / `ECONNREFUSED` / `ERR_UNEXPECTED_EOF` | HighToleranceError |
52
51
  | `ERR_UNSUPPORTED_PROTOCOL` | HighToleranceError |
@@ -183,19 +182,6 @@ Protected peers (private/trusted/preferred) are always considered "authenticated
183
182
 
184
183
  Conditional registration: BLOCK_TXS handler only registered when `config.disableTransactions` is false. Otherwise peers get `ERR_UNSUPPORTED_PROTOCOL`.
185
184
 
186
- **Requester side via `sendBatchRequest`** (Snappy limit: `max(N, 1) * 512 + 1` KB):
187
-
188
- | Rule | Consequence | File |
189
- |------|-------------|------|
190
- | Archive root must match request | MidToleranceError | `libp2p_service.ts` (`validateRequestedBlockTxs`) |
191
- | BitVector length must match request | MidToleranceError | same |
192
- | No duplicate tx hashes | MidToleranceError | same |
193
- | Tx count within bounds | MidToleranceError | same |
194
- | Local block proposal must exist for archive root | Rejected (no penalty) | same |
195
- | All tx hashes must be in proposal's tx list at allowed indices | LowToleranceError | same |
196
- | Txs in strictly increasing index order | LowToleranceError | same |
197
- | Each tx passes well-formedness (Metadata [4 fields], Size, Data, Proof) | LowToleranceError | same |
198
-
199
185
  **Requester side via `BatchTxRequester`** (separate validation path):
200
186
 
201
187
  | Rule | Consequence | File |