@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
@@ -4,9 +4,10 @@ import { FifoMemoryQueue, type ISemaphore, Semaphore } from '@aztec/foundation/q
4
4
  import { sleep } from '@aztec/foundation/sleep';
5
5
  import { DateProvider } from '@aztec/foundation/timer';
6
6
  import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
7
- import { Tx, TxArray, TxHash } from '@aztec/stdlib/tx';
7
+ import { Tx, TxArray, TxHash, type TxValidator } from '@aztec/stdlib/tx';
8
8
 
9
9
  import type { PeerId } from '@libp2p/interface';
10
+ import { strict as assert } from 'assert';
10
11
 
11
12
  import type { IRequestTracker } from '../../tx_collection/request_tracker.js';
12
13
  import { ReqRespSubProtocol } from '.././interface.js';
@@ -21,7 +22,7 @@ import {
21
22
  import type { BatchTxRequesterLibP2PService, BatchTxRequesterOptions, ITxMetadataCollection } from './interface.js';
22
23
  import { MissingTxMetadataCollection } from './missing_txs.js';
23
24
  import { type IPeerCollection, PeerCollection } from './peer_collection.js';
24
- import { BatchRequestTxValidator, type IBatchRequestTxValidator } from './tx_validator.js';
25
+ import { createBatchRequestTxValidator } from './tx_validator.js';
25
26
 
26
27
  /*
27
28
  * Tries to fetch all missing transaction until deadline is hit.
@@ -51,7 +52,7 @@ export class BatchTxRequester {
51
52
  private readonly txsMetadata: ITxMetadataCollection;
52
53
  private readonly smartRequesterSemaphore: ISemaphore;
53
54
  private readonly txQueue: FifoMemoryQueue<Tx>;
54
- private readonly txValidator: IBatchRequestTxValidator;
55
+ private readonly txValidator: TxValidator;
55
56
  private readonly smartParallelWorkerCount: number;
56
57
  private readonly dumbParallelWorkerCount: number;
57
58
  private readonly txBatchSize: number;
@@ -78,7 +79,7 @@ export class BatchTxRequester {
78
79
  this.opts.dumbParallelWorkerCount ?? DEFAULT_BATCH_TX_REQUESTER_DUMB_PARALLEL_WORKER_COUNT;
79
80
  this.txBatchSize = this.opts.txBatchSize ?? DEFAULT_BATCH_TX_REQUESTER_TX_BATCH_SIZE;
80
81
  this.txQueue = new FifoMemoryQueue(this.logger);
81
- this.txValidator = this.opts.txValidator ?? new BatchRequestTxValidator(this.p2pService.txValidatorConfig);
82
+ this.txValidator = this.opts.txValidator ?? createBatchRequestTxValidator(this.p2pService.txValidatorConfig);
82
83
 
83
84
  if (this.opts.peerCollection) {
84
85
  this.peers = this.opts.peerCollection;
@@ -97,7 +98,7 @@ export class BatchTxRequester {
97
98
  }
98
99
 
99
100
  /*
100
- * Fetches all missing transactions and yields them one by one
101
+ * Fetches all missing transactions and yields them one by one
101
102
  * */
102
103
  public async *run(): AsyncGenerator<Tx, Tx | undefined, unknown> {
103
104
  try {
@@ -428,6 +429,15 @@ export class BatchTxRequester {
428
429
  }
429
430
 
430
431
  const blockResponse = BlockTxsResponse.fromBuffer(response.data);
432
+
433
+ // Validate response. Peers will be penalised by the validator if they send invalid response.
434
+ const isValid = await this.p2pService.validateRequestedBlockTxsConsistency(request, blockResponse, peerId);
435
+ if (!isValid) {
436
+ this.logger.debug(`Peer ${peerId.toString()} sent invalid response`);
437
+ this.handleFailResponseFromPeer(peerId, ReqRespStatus.INTERNAL_ERROR);
438
+ return;
439
+ }
440
+
431
441
  await this.handleSuccessResponseFromPeer(peerId, blockResponse);
432
442
  } catch (err: any) {
433
443
  this.logger.error(`Failed to get valid response from peer ${peerId.toString()}: ${err.message}`, {
@@ -445,27 +455,24 @@ export class BatchTxRequester {
445
455
  * Handles failed response form the peer
446
456
  * There are 3 scenarios
447
457
  * - RATE_LIMIT_EXCEEDED: We mark this and don't query this peer again for some_time
458
+ * - INTERNAL_ERROR: We use this to cover cases where the request-response consistency validation fails.
448
459
  * - FAILURE and UNKNOWN: We penalise this, if peer has been penalised this way N times they are not queried again
449
460
  * this implies we will query these peers couple of more times and give them a chance to "redeem" themselves before completely ignoring them
450
461
  */
451
462
  private handleFailResponseFromPeer(peerId: PeerId, responseStatus: ReqRespStatus) {
452
- if (responseStatus === ReqRespStatus.FAILURE || responseStatus === ReqRespStatus.UNKNOWN) {
453
- this.peers.penalisePeer(peerId, PeerErrorSeverity.HighToleranceError);
454
- this.peers.markPeerDumb(peerId);
455
- this.txsMetadata.clearPeerData(peerId);
456
- return;
457
- }
458
-
459
- // NOT_FOUND means the peer pruned its block proposal — it can no longer serve
460
- // index-based requests, but this is a legitimate state so we don't penalize.
461
- if (responseStatus === ReqRespStatus.NOT_FOUND) {
462
- this.peers.markPeerDumb(peerId);
463
- this.txsMetadata.clearPeerData(peerId);
464
- return;
465
- }
466
-
467
- if (responseStatus === ReqRespStatus.RATE_LIMIT_EXCEEDED) {
468
- this.peers.markPeerRateLimitExceeded(peerId);
463
+ switch (responseStatus) {
464
+ case ReqRespStatus.RATE_LIMIT_EXCEEDED:
465
+ this.peers.markPeerRateLimitExceeded(peerId);
466
+ return;
467
+ case ReqRespStatus.INTERNAL_ERROR:
468
+ this.peers.markPeerDumb(peerId);
469
+ this.txsMetadata.clearPeerData(peerId);
470
+ return;
471
+ default: // includes FAILURE, UNKNOWN
472
+ this.peers.penalisePeer(peerId, PeerErrorSeverity.HighToleranceError);
473
+ this.peers.markPeerDumb(peerId);
474
+ this.txsMetadata.clearPeerData(peerId);
475
+ return;
469
476
  }
470
477
  }
471
478
 
@@ -485,7 +492,7 @@ export class BatchTxRequester {
485
492
  * Handles received txs.
486
493
  * Transactions are validated and then put on async queue
487
494
  * to be yielded by main running loop
488
- * */
495
+ */
489
496
  private async handleReceivedTxs(peerId: PeerId, txs: TxArray) {
490
497
  const newTxs = txs.filter(tx => !this.txsMetadata.alreadyFetched(tx.txHash));
491
498
 
@@ -493,12 +500,12 @@ export class BatchTxRequester {
493
500
  return;
494
501
  }
495
502
 
496
- //TODO: this validation can be slow, maybe spawn worker just for validation
503
+ // TODO: this validation can be slow, maybe spawn worker just for validation
497
504
  // We could use the async queue for communication.
498
505
  const validationResults = await Promise.allSettled(
499
506
  newTxs.map(async tx => ({
500
507
  tx,
501
- isValid: (await this.txValidator.validateRequestedTx(tx)).result === 'valid',
508
+ isValid: (await this.txValidator.validateTx(tx)).result === 'valid',
502
509
  })),
503
510
  );
504
511
 
@@ -553,9 +560,10 @@ export class BatchTxRequester {
553
560
  return;
554
561
  }
555
562
 
556
- const hasArchiveRootMismatch = this.blockTxsSource.archive.toString() !== response.archiveRoot.toString();
557
- if (hasArchiveRootMismatch) {
558
- this.handleArchiveRootMismatch(peerId, response);
563
+ // If the peer doesn't have the block, we mark them as dumb.
564
+ if (!response.peerHasBlock()) {
565
+ this.peers.markPeerDumb(peerId);
566
+ this.txsMetadata.clearPeerData(peerId);
559
567
  return;
560
568
  }
561
569
 
@@ -573,21 +581,6 @@ export class BatchTxRequester {
573
581
  this.smartRequesterSemaphore.release();
574
582
  }
575
583
 
576
- /**
577
- * Handles an archive root mismatch between local state and peer response.
578
- *
579
- * - Response archive is Fr.ZERO (peer pruned proposal, legitimate): marks peer dumb.
580
- * - Non-zero archive mismatch (malicious response): penalises + marks dumb.
581
- */
582
- private handleArchiveRootMismatch(peerId: PeerId, response: BlockTxsResponse): void {
583
- if (!response.archiveRoot.isZero()) {
584
- this.peers.penalisePeer(peerId, PeerErrorSeverity.LowToleranceError);
585
- }
586
-
587
- this.peers.markPeerDumb(peerId);
588
- this.txsMetadata.clearPeerData(peerId);
589
- }
590
-
591
584
  private peerHasSomeTxsWeAreMissing(_peerId: PeerId, response: BlockTxsResponse): boolean {
592
585
  if (response.txIndices.isEmpty()) {
593
586
  return false;
@@ -603,15 +596,9 @@ export class BatchTxRequester {
603
596
  }
604
597
 
605
598
  private extractHashesPeerHasFromResponse(response: BlockTxsResponse): Array<TxHash> {
606
- const hashes: TxHash[] = [];
607
- const indicesOfHashesPeerHas = new Set(response.txIndices.getTrueIndices());
608
- this.blockTxsSource.txHashes.forEach((hash, idx) => {
609
- if (indicesOfHashesPeerHas.has(idx)) {
610
- hashes.push(hash);
611
- }
612
- });
613
-
614
- return hashes;
599
+ // Should already have been validated, but just in case.
600
+ assert(response.txIndices.getLength() === this.blockTxsSource.txHashes.length);
601
+ return response.txIndices.getTrueIndices().map(idx => this.blockTxsSource.txHashes[idx]);
615
602
  }
616
603
 
617
604
  /*
@@ -1,13 +1,14 @@
1
1
  import type { ISemaphore } from '@aztec/foundation/queue';
2
2
  import type { PeerErrorSeverity } from '@aztec/stdlib/p2p';
3
- import type { Tx, TxHash } from '@aztec/stdlib/tx';
3
+ import type { Tx, TxHash, TxValidator } from '@aztec/stdlib/tx';
4
4
 
5
5
  import type { PeerId } from '@libp2p/interface';
6
6
 
7
7
  import type { ConnectionSampler } from '../connection-sampler/connection_sampler.js';
8
+ import type { BlockTxsRequest, BlockTxsResponse } from '../index.js';
8
9
  import type { ReqRespInterface } from '../interface.js';
9
10
  import type { IPeerCollection } from './peer_collection.js';
10
- import type { BatchRequestTxValidatorConfig, IBatchRequestTxValidator } from './tx_validator.js';
11
+ import type { BatchRequestTxValidatorConfig } from './tx_validator.js';
11
12
 
12
13
  export interface IPeerPenalizer {
13
14
  penalizePeer(peerId: PeerId, penalty: PeerErrorSeverity): void;
@@ -32,13 +33,19 @@ export interface ITxMetadataCollection {
32
33
  */
33
34
  export interface BatchTxRequesterLibP2PService {
34
35
  /** ReqResp interface for sending requests to peers */
35
- reqResp: Pick<ReqRespInterface, 'sendBatchRequest' | 'sendRequestToPeer'>;
36
+ reqResp: Pick<ReqRespInterface, 'sendRequestToPeer'>;
36
37
  /** Connection sampler for getting peer lists */
37
38
  connectionSampler: Pick<ConnectionSampler, 'getPeerListSortedByConnectionCountAsc'>;
38
39
  /** Configuration needed for transaction validation */
39
40
  txValidatorConfig: BatchRequestTxValidatorConfig;
40
41
  /** Peer scoring for penalizing peers */
41
42
  peerScoring: IPeerPenalizer;
43
+ /** Validate the requested block transactions request-response consistency */
44
+ validateRequestedBlockTxsConsistency: (
45
+ request: BlockTxsRequest,
46
+ response: BlockTxsResponse,
47
+ peerId: PeerId,
48
+ ) => Promise<boolean>;
42
49
  }
43
50
 
44
51
  export interface BatchTxRequesterOptions {
@@ -50,5 +57,5 @@ export interface BatchTxRequesterOptions {
50
57
  semaphore?: ISemaphore;
51
58
  peerCollection?: IPeerCollection;
52
59
  /** Optional tx validator for testing - if not provided, one is created from p2pService.txValidatorConfig */
53
- txValidator?: IBatchRequestTxValidator;
60
+ txValidator?: TxValidator;
54
61
  }
@@ -1,37 +1,24 @@
1
1
  import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
2
- import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
2
+ import type { TxValidator } from '@aztec/stdlib/tx';
3
3
 
4
- import { createTxValidatorForReqResponseReceivedTxs } from '../../../msg_validators/index.js';
4
+ import { createTxValidatorForOnDemandReceivedTxs } from '../../../msg_validators/index.js';
5
+ import type { TxValidationCache } from '../../../msg_validators/tx_validator/tx_validation_cache.js';
5
6
 
6
7
  export interface BatchRequestTxValidatorConfig {
7
8
  l1ChainId: number;
8
9
  rollupVersion: number;
9
10
  proofVerifier: ClientProtocolCircuitVerifier;
11
+ txValidationCache?: TxValidationCache;
10
12
  }
11
13
 
12
- export interface IBatchRequestTxValidator {
13
- validateRequestedTx(tx: Tx): Promise<TxValidationResult>;
14
- validateRequestedTxs(txs: Tx[]): Promise<TxValidationResult[]>;
15
- }
16
-
17
- export class BatchRequestTxValidator implements IBatchRequestTxValidator {
18
- readonly txValidator: TxValidator;
19
- constructor(private readonly config: BatchRequestTxValidatorConfig) {
20
- this.txValidator = BatchRequestTxValidator.createRequestedTxValidator(this.config);
21
- }
22
-
23
- public async validateRequestedTx(tx: Tx): Promise<TxValidationResult> {
24
- return await this.txValidator.validateTx(tx);
25
- }
26
-
27
- public async validateRequestedTxs(txs: Tx[]): Promise<TxValidationResult[]> {
28
- return await Promise.all(txs.map(tx => this.validateRequestedTx(tx)));
29
- }
30
-
31
- static createRequestedTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
32
- return createTxValidatorForReqResponseReceivedTxs(config.proofVerifier, {
14
+ export function createBatchRequestTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
15
+ return createTxValidatorForOnDemandReceivedTxs(
16
+ config.proofVerifier,
17
+ {
33
18
  l1ChainId: config.l1ChainId,
34
19
  rollupVersion: config.rollupVersion,
35
- });
36
- }
20
+ },
21
+ /*bindings=*/ undefined,
22
+ config.txValidationCache,
23
+ );
37
24
  }
@@ -78,23 +78,11 @@ export interface ProtocolRateLimitQuota {
78
78
  globalLimit: RateLimitQuota;
79
79
  }
80
80
 
81
- export const noopValidator = () => Promise.resolve(true);
82
-
83
81
  /**
84
82
  * A type mapping from supprotocol to it's handling function
85
83
  */
86
84
  export type ReqRespSubProtocolHandlers = Record<ReqRespSubProtocol, ReqRespSubProtocolHandler>;
87
85
 
88
- type ResponseValidator<RequestIdentifier, Response> = (
89
- request: RequestIdentifier,
90
- response: Response,
91
- peerId: PeerId,
92
- ) => Promise<boolean>;
93
-
94
- export type ReqRespSubProtocolValidators = {
95
- [S in ReqRespSubProtocol]: ResponseValidator<any, any>;
96
- };
97
-
98
86
  /**
99
87
  * Protocols that are always allowed without authentication, even when p2pAllowOnlyValidators is enabled.
100
88
  * These are needed for the handshake and connection management flow.
@@ -113,15 +101,6 @@ export const UNAUTHENTICATED_ALLOWED_PROTOCOLS: ReadonlySet<ReqRespSubProtocol>
113
101
  */
114
102
  export type ShouldRejectPeer = (peerId: string) => boolean;
115
103
 
116
- export const DEFAULT_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
117
- [ReqRespSubProtocol.PING]: noopValidator,
118
- [ReqRespSubProtocol.STATUS]: noopValidator,
119
- [ReqRespSubProtocol.TX]: noopValidator,
120
- [ReqRespSubProtocol.GOODBYE]: noopValidator,
121
- [ReqRespSubProtocol.AUTH]: noopValidator,
122
- [ReqRespSubProtocol.BLOCK_TXS]: noopValidator,
123
- };
124
-
125
104
  /*
126
105
  * Helper class to sub-protocol validation error*/
127
106
  export class ValidationError extends Error {
@@ -244,24 +223,9 @@ export const subProtocolSizeCalculators: Record<ReqRespSubProtocol, ExpectedResp
244
223
  };
245
224
 
246
225
  export interface ReqRespInterface {
247
- start(
248
- subProtocolHandlers: Partial<ReqRespSubProtocolHandlers>,
249
- subProtocolValidators: ReqRespSubProtocolValidators,
250
- ): Promise<void>;
251
- addSubProtocol(
252
- subProtocol: ReqRespSubProtocol,
253
- handler: ReqRespSubProtocolHandler,
254
- validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
255
- ): Promise<void>;
226
+ start(subProtocolHandlers: Partial<ReqRespSubProtocolHandlers>): Promise<void>;
227
+ addSubProtocol(subProtocol: ReqRespSubProtocol, handler: ReqRespSubProtocolHandler): Promise<void>;
256
228
  stop(): Promise<void>;
257
- sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
258
- subProtocol: SubProtocol,
259
- requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
260
- pinnedPeer: PeerId | undefined,
261
- timeoutMs?: number,
262
- maxPeers?: number,
263
- maxRetryAttempts?: number,
264
- ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]>;
265
229
  sendRequestToPeer(
266
230
  peerId: PeerId,
267
231
  subProtocol: ReqRespSubProtocol,
@@ -58,8 +58,9 @@ export class BitVector {
58
58
  }
59
59
 
60
60
  /**
61
- * Returns all indices which are set to true
62
- * */
61
+ * Returns all indices which are set to true.
62
+ * Ordered by index. No duplicates.
63
+ */
63
64
  getTrueIndices(): number[] {
64
65
  return Array.from({ length: this.length }, (_, i) => i).filter(i => this.isSet(i));
65
66
  }
@@ -1,6 +1,5 @@
1
- import { Fr } from '@aztec/foundation/curves/bn254';
2
1
  import type { L2BlockSource } from '@aztec/stdlib/block';
3
- import { TxArray } from '@aztec/stdlib/tx';
2
+ import { TxArray, TxHash } from '@aztec/stdlib/tx';
4
3
 
5
4
  import type { PeerId } from '@libp2p/interface';
6
5
 
@@ -36,40 +35,45 @@ export function reqRespBlockTxsHandler(
36
35
  } catch (err: any) {
37
36
  throw new ReqRespStatusError(ReqRespStatus.BADLY_FORMED_REQUEST, { cause: err });
38
37
  }
39
- // First try attestation pool, then fall back to archiver
40
- let txHashes = (await attestationPool.getBlockProposal(request.archiveRoot.toString()))?.txHashes;
41
- if (!txHashes) {
42
- txHashes = (await archiver.getL2BlockByArchive(request.archiveRoot))?.body.txEffects.map(effect => effect.txHash);
43
- }
44
38
 
45
- let requestedTxsHashes;
46
- if (request.txHashes.length > 0) {
47
- requestedTxsHashes = request.txHashes;
48
- }
39
+ // In principle assume we haven't found the block. This is how that is signaled to the requester.
40
+ let availableIndicesBitVector: BitVector = BitVector.init(0, []);
41
+ // We always try to service the explicitly requested tx hashes, even if we don't have the block.
42
+ const requestedTxsHashes: Set<string> = new Set(request.txHashes.map(h => h.toString()));
49
43
 
50
- // This is scenario in which we don't have this block the peer is requesting from us
51
- // But peer has sent requested tx hashes, so we can send them the transactions
52
- if (!txHashes && requestedTxsHashes !== undefined) {
53
- const responseTxs = (await txPool.getTxsByHash(requestedTxsHashes)).filter(tx => !!tx);
54
- const response = new BlockTxsResponse(Fr.zero(), new TxArray(...responseTxs), BitVector.init(0, []));
55
- return response.toBuffer();
44
+ // First try attestation pool, then fall back to archiver.
45
+ let blockTxHashes = (await attestationPool.getBlockProposalByArchive(request.archiveRoot.toString()))?.txHashes;
46
+ if (!blockTxHashes) {
47
+ blockTxHashes = (await archiver.getBlock({ archive: request.archiveRoot }))?.body.txEffects.map(
48
+ effect => effect.txHash,
49
+ );
56
50
  }
57
51
 
58
- // If we don't have this block and peer has not sent requested tx hashes
59
- if (!txHashes) {
60
- throw new ReqRespStatusError(ReqRespStatus.NOT_FOUND);
61
- }
52
+ // If we have found the block,
53
+ if (blockTxHashes) {
54
+ // First confirm that we are talking about the same block (up to tx hashes and order).
55
+ // If we are not, then we can't:
56
+ // 1. Use the indices from the request to get the txs from the pool.
57
+ // 2. Respond to the peer with the txs we have using indices.
58
+ const blockTxHashesCommitment = BlockTxsRequest.computeBlockTxHashesCommitment(blockTxHashes);
59
+ if (blockTxHashesCommitment.equals(request.blockTxHashesCommitment)) {
60
+ // In that case, we can also get the available indices from the pool.
61
+ const txsAvailableInPool = await txPool.hasTxs(blockTxHashes);
62
+ // Map txs in the pool to their indices in the block
63
+ const availableIndices = txsAvailableInPool.map((hasTx, idx) => (hasTx ? idx : -1)).filter(idx => idx !== -1);
64
+ availableIndicesBitVector = BitVector.init(blockTxHashes.length, availableIndices);
62
65
 
63
- const txsAvailableInPool = await txPool.hasTxs(txHashes);
64
- // Map txs in the pool to their indices in the block
65
- const availableIndices = txsAvailableInPool.map((hasTx, idx) => (hasTx ? idx : -1)).filter(idx => idx !== -1);
66
- const responseBitVector = BitVector.init(txHashes.length, availableIndices);
67
-
68
- const requestedIndices = new Set(request.txIndices.getTrueIndices());
69
- requestedTxsHashes = txHashes.filter((_, idx) => requestedIndices.has(idx));
66
+ // We add the requested tx hashes (by index) to the list of tx hashes we are sending to the peer.
67
+ const requestedIndices = new Set(request.txIndices.getTrueIndices());
68
+ blockTxHashes.filter((_, idx) => requestedIndices.has(idx)).forEach(h => requestedTxsHashes.add(h.toString()));
69
+ }
70
+ }
70
71
 
71
- const responseTxs = (await txPool.getTxsByHash(requestedTxsHashes)).filter(tx => !!tx);
72
- const response = new BlockTxsResponse(request.archiveRoot, new TxArray(...responseTxs), responseBitVector);
72
+ // Finally, get the txs from the pool and create the response.
73
+ const responseTxs = (
74
+ await txPool.getTxsByHash(Array.from(requestedTxsHashes).map(h => TxHash.fromString(h)))
75
+ ).filter(tx => !!tx);
76
+ const response = new BlockTxsResponse(new TxArray(...responseTxs), availableIndicesBitVector);
73
77
 
74
78
  return response.toBuffer();
75
79
  };
@@ -1,8 +1,11 @@
1
+ import { Buffer32 } from '@aztec/foundation/buffer';
1
2
  import { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
3
4
  import { MAX_TX_SIZE_KB } from '@aztec/stdlib/p2p';
4
5
  import { TxArray, type TxHash, TxHashArray } from '@aztec/stdlib/tx';
5
6
 
7
+ import { createHash } from 'node:crypto';
8
+
6
9
  import { BitVector } from './bitvector.js';
7
10
 
8
11
  /** Minimal interface for a block source that provides tx hashes and an archive root. */
@@ -16,17 +19,27 @@ export interface BlockTxsSource {
16
19
  */
17
20
  export class BlockTxsRequest {
18
21
  constructor(
19
- // Archive root after the proposed block is applied (proposal identifier)
22
+ // Archive root after the proposed block is applied (proposal identifier).
20
23
  readonly archiveRoot: Fr,
21
- // Hashes of txs we are requesting
22
- readonly txHashes: TxHashArray,
23
- // BitVector indicating which txs from the proposal we are requesting
24
- // 1 means we want the tx, 0 means we don't
25
- // If we know peer has the Block Proposal then we can use this BitVector
26
- // Otherwise we can use this optimization
24
+ // BitVector indicating which txs from the block (proposal) we are requesting
25
+ // 1 means we want the tx, 0 means we don't.
26
+ // This will only return txs in the response if the peer has the block (proposal).
27
27
  readonly txIndices: BitVector,
28
+ // If we ask for txs via indices, the responder needs to be sure that we are talking about the same block.
29
+ // Unfortunately, the archive root is not enough, since it's possible for the peer to have seen a different
30
+ // block (proposal) with the same archive root but different txs. We include a commitment to the tx hashes
31
+ // so that the responder can verify this (for its own sake, and not be penalized).
32
+ readonly blockTxHashesCommitment: Buffer32,
33
+ // Explicit hashes of txs we are requesting (optional). The peer will try to serve these txs even if
34
+ // it doesn't have the block. If the requester lists txs from the block here, this serves as a fallback.
35
+ // Note: if a hash here is NOT part of the block (proposal), the peer can decide to return it or not.
36
+ readonly txHashes: TxHashArray,
28
37
  ) {}
29
38
 
39
+ static computeBlockTxHashesCommitment(blockTxHashes: TxHash[]): Buffer32 {
40
+ return Buffer32.fromBuffer(createHash('sha256').update(serializeToBuffer(blockTxHashes)).digest());
41
+ }
42
+
30
43
  /**
31
44
  * Creates new BlockTxsRequest given a block txs source and missing tx hashes.
32
45
  *
@@ -59,8 +72,9 @@ export class BlockTxsRequest {
59
72
 
60
73
  const requestBitVector = BitVector.init(blockTxsSource.txHashes.length, missingIndices);
61
74
  const hashes = includeFullTxHashes ? new TxHashArray(...missingTxHashes) : new TxHashArray();
75
+ const commitment = BlockTxsRequest.computeBlockTxHashesCommitment(blockTxsSource.txHashes);
62
76
 
63
- return new BlockTxsRequest(blockTxsSource.archive, hashes, requestBitVector);
77
+ return new BlockTxsRequest(blockTxsSource.archive, requestBitVector, commitment, hashes);
64
78
  }
65
79
 
66
80
  /**
@@ -71,10 +85,11 @@ export class BlockTxsRequest {
71
85
  static fromBuffer(buffer: Buffer | BufferReader): BlockTxsRequest {
72
86
  const reader = BufferReader.asReader(buffer);
73
87
  const archiveRoot = Fr.fromBuffer(reader);
74
- const txHashes = TxHashArray.fromBuffer(reader);
75
88
  const txIndices = BitVector.fromBuffer(reader);
89
+ const commitment = Buffer32.fromBuffer(reader);
90
+ const txHashes = TxHashArray.fromBuffer(reader);
76
91
 
77
- return new BlockTxsRequest(archiveRoot, txHashes, txIndices);
92
+ return new BlockTxsRequest(archiveRoot, txIndices, commitment, txHashes);
78
93
  }
79
94
 
80
95
  /**
@@ -82,7 +97,12 @@ export class BlockTxsRequest {
82
97
  * @returns Buffer representation of the BlockTxRequest object
83
98
  */
84
99
  toBuffer(): Buffer {
85
- return serializeToBuffer([this.archiveRoot, this.txHashes.toBuffer(), this.txIndices.toBuffer()]);
100
+ return serializeToBuffer([
101
+ this.archiveRoot,
102
+ this.txIndices.toBuffer(),
103
+ this.blockTxHashesCommitment.toBuffer(),
104
+ this.txHashes.toBuffer(),
105
+ ]);
86
106
  }
87
107
  }
88
108
 
@@ -91,13 +111,23 @@ export class BlockTxsRequest {
91
111
  */
92
112
  export class BlockTxsResponse {
93
113
  constructor(
94
- readonly archiveRoot: Fr,
95
- readonly txs: TxArray, // List of transactions we requested and peer has
114
+ // List of transactions we requested and peer has.
115
+ readonly txs: TxArray,
96
116
  // BitVector indicating which txs from the proposal are available at the peer
97
- // 1 means the tx is available, 0 means it is not
117
+ // 1 means the tx is available, 0 means it is not.
118
+ // The vector should be empty to signal that the peer doesn't have the block.
119
+ // Otherwise, it should be a subset of the indices of the block tx hashes.
98
120
  readonly txIndices: BitVector,
99
121
  ) {}
100
122
 
123
+ /**
124
+ * Whether the response indicates that the peer has the block.
125
+ * @returns True if the peer has the block, false otherwise.
126
+ */
127
+ peerHasBlock(): boolean {
128
+ return this.txIndices.getLength() > 0;
129
+ }
130
+
101
131
  /**
102
132
  * Deserializes the BlockTxResponse object from a Buffer
103
133
  * @param buffer - Buffer or BufferReader object to deserialize
@@ -105,25 +135,22 @@ export class BlockTxsResponse {
105
135
  */
106
136
  static fromBuffer(buffer: Buffer | BufferReader): BlockTxsResponse {
107
137
  const reader = BufferReader.asReader(buffer);
108
- const archiveRoot = Fr.fromBuffer(reader);
109
138
  const txs = TxArray.fromBuffer(reader);
110
139
  const txIndices = BitVector.fromBuffer(reader);
111
140
 
112
- return new BlockTxsResponse(archiveRoot, txs, txIndices);
141
+ return new BlockTxsResponse(txs, txIndices);
113
142
  }
114
143
 
115
144
  /**
116
145
  * Serializes the BlockTxResponse object into a Buffer
117
- * @dev: In current implementation, txIndices is serialized as Buffer of unknown length,
118
- * thus we serialize it last
119
146
  * @returns Buffer representation of the BlockTxResponse object
120
147
  */
121
148
  toBuffer(): Buffer {
122
- return serializeToBuffer([this.archiveRoot, this.txs.toBuffer(), this.txIndices.toBuffer()]);
149
+ return serializeToBuffer([this.txs.toBuffer(), this.txIndices.toBuffer()]);
123
150
  }
124
151
 
125
152
  static empty(): BlockTxsResponse {
126
- return new BlockTxsResponse(Fr.ZERO, new TxArray(), BitVector.init(0, []));
153
+ return new BlockTxsResponse(new TxArray(), BitVector.init(0, []));
127
154
  }
128
155
  }
129
156