@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,24 +1,36 @@
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, TxHashArray } from '@aztec/stdlib/tx';
6
+ import { createHash } from 'node:crypto';
5
7
  import { BitVector } from './bitvector.js';
6
8
  /**
7
9
  * Request message for requesting specific transactions from a block
8
10
  */ export class BlockTxsRequest {
9
11
  archiveRoot;
10
- txHashes;
11
12
  txIndices;
12
- constructor(// Archive root after the proposed block is applied (proposal identifier)
13
- archiveRoot, // Hashes of txs we are requesting
14
- txHashes, // BitVector indicating which txs from the proposal we are requesting
15
- // 1 means we want the tx, 0 means we don't
16
- // If we know peer has the Block Proposal then we can use this BitVector
17
- // Otherwise we can use this optimization
18
- txIndices){
13
+ blockTxHashesCommitment;
14
+ txHashes;
15
+ constructor(// Archive root after the proposed block is applied (proposal identifier).
16
+ archiveRoot, // BitVector indicating which txs from the block (proposal) we are requesting
17
+ // 1 means we want the tx, 0 means we don't.
18
+ // This will only return txs in the response if the peer has the block (proposal).
19
+ txIndices, // If we ask for txs via indices, the responder needs to be sure that we are talking about the same block.
20
+ // Unfortunately, the archive root is not enough, since it's possible for the peer to have seen a different
21
+ // block (proposal) with the same archive root but different txs. We include a commitment to the tx hashes
22
+ // so that the responder can verify this (for its own sake, and not be penalized).
23
+ blockTxHashesCommitment, // Explicit hashes of txs we are requesting (optional). The peer will try to serve these txs even if
24
+ // it doesn't have the block. If the requester lists txs from the block here, this serves as a fallback.
25
+ // Note: if a hash here is NOT part of the block (proposal), the peer can decide to return it or not.
26
+ txHashes){
19
27
  this.archiveRoot = archiveRoot;
20
- this.txHashes = txHashes;
21
28
  this.txIndices = txIndices;
29
+ this.blockTxHashesCommitment = blockTxHashesCommitment;
30
+ this.txHashes = txHashes;
31
+ }
32
+ static computeBlockTxHashesCommitment(blockTxHashes) {
33
+ return Buffer32.fromBuffer(createHash('sha256').update(serializeToBuffer(blockTxHashes)).digest());
22
34
  }
23
35
  /**
24
36
  * Creates new BlockTxsRequest given a block txs source and missing tx hashes.
@@ -41,7 +53,8 @@ import { BitVector } from './bitvector.js';
41
53
  const missingIndices = blockTxsSource.txHashes.map((hash, idx)=>missingHashesSet.has(hash.toString()) ? idx : -1).filter((i)=>i != -1);
42
54
  const requestBitVector = BitVector.init(blockTxsSource.txHashes.length, missingIndices);
43
55
  const hashes = includeFullTxHashes ? new TxHashArray(...missingTxHashes) : new TxHashArray();
44
- return new BlockTxsRequest(blockTxsSource.archive, hashes, requestBitVector);
56
+ const commitment = BlockTxsRequest.computeBlockTxHashesCommitment(blockTxsSource.txHashes);
57
+ return new BlockTxsRequest(blockTxsSource.archive, requestBitVector, commitment, hashes);
45
58
  }
46
59
  /**
47
60
  * Deserializes the BlockTxRequest object from a Buffer
@@ -50,9 +63,10 @@ import { BitVector } from './bitvector.js';
50
63
  */ static fromBuffer(buffer) {
51
64
  const reader = BufferReader.asReader(buffer);
52
65
  const archiveRoot = Fr.fromBuffer(reader);
53
- const txHashes = TxHashArray.fromBuffer(reader);
54
66
  const txIndices = BitVector.fromBuffer(reader);
55
- return new BlockTxsRequest(archiveRoot, txHashes, txIndices);
67
+ const commitment = Buffer32.fromBuffer(reader);
68
+ const txHashes = TxHashArray.fromBuffer(reader);
69
+ return new BlockTxsRequest(archiveRoot, txIndices, commitment, txHashes);
56
70
  }
57
71
  /**
58
72
  * Serializes the BlockTxRequest object into a Buffer
@@ -60,49 +74,53 @@ import { BitVector } from './bitvector.js';
60
74
  */ toBuffer() {
61
75
  return serializeToBuffer([
62
76
  this.archiveRoot,
63
- this.txHashes.toBuffer(),
64
- this.txIndices.toBuffer()
77
+ this.txIndices.toBuffer(),
78
+ this.blockTxHashesCommitment.toBuffer(),
79
+ this.txHashes.toBuffer()
65
80
  ]);
66
81
  }
67
82
  }
68
83
  /**
69
84
  * Response message containing requested transactions from a block
70
85
  */ export class BlockTxsResponse {
71
- archiveRoot;
72
86
  txs;
73
87
  txIndices;
74
- constructor(archiveRoot, txs, // BitVector indicating which txs from the proposal are available at the peer
75
- // 1 means the tx is available, 0 means it is not
88
+ constructor(// List of transactions we requested and peer has.
89
+ txs, // BitVector indicating which txs from the proposal are available at the peer
90
+ // 1 means the tx is available, 0 means it is not.
91
+ // The vector should be empty to signal that the peer doesn't have the block.
92
+ // Otherwise, it should be a subset of the indices of the block tx hashes.
76
93
  txIndices){
77
- this.archiveRoot = archiveRoot;
78
94
  this.txs = txs;
79
95
  this.txIndices = txIndices;
80
96
  }
81
97
  /**
98
+ * Whether the response indicates that the peer has the block.
99
+ * @returns True if the peer has the block, false otherwise.
100
+ */ peerHasBlock() {
101
+ return this.txIndices.getLength() > 0;
102
+ }
103
+ /**
82
104
  * Deserializes the BlockTxResponse object from a Buffer
83
105
  * @param buffer - Buffer or BufferReader object to deserialize
84
106
  * @returns An instance of BlockTxResponse
85
107
  */ static fromBuffer(buffer) {
86
108
  const reader = BufferReader.asReader(buffer);
87
- const archiveRoot = Fr.fromBuffer(reader);
88
109
  const txs = TxArray.fromBuffer(reader);
89
110
  const txIndices = BitVector.fromBuffer(reader);
90
- return new BlockTxsResponse(archiveRoot, txs, txIndices);
111
+ return new BlockTxsResponse(txs, txIndices);
91
112
  }
92
113
  /**
93
114
  * Serializes the BlockTxResponse object into a Buffer
94
- * @dev: In current implementation, txIndices is serialized as Buffer of unknown length,
95
- * thus we serialize it last
96
115
  * @returns Buffer representation of the BlockTxResponse object
97
116
  */ toBuffer() {
98
117
  return serializeToBuffer([
99
- this.archiveRoot,
100
118
  this.txs.toBuffer(),
101
119
  this.txIndices.toBuffer()
102
120
  ]);
103
121
  }
104
122
  static empty() {
105
- return new BlockTxsResponse(Fr.ZERO, new TxArray(), BitVector.init(0, []));
123
+ return new BlockTxsResponse(new TxArray(), BitVector.init(0, []));
106
124
  }
107
125
  }
108
126
  /**
@@ -4,12 +4,12 @@ import type { Libp2p } from 'libp2p';
4
4
  import type { PeerScoring } from '../peer-manager/peer_scoring.js';
5
5
  import { type P2PReqRespConfig } from './config.js';
6
6
  import { ConnectionSampler } from './connection-sampler/connection_sampler.js';
7
- import { type ReqRespInterface, type ReqRespResponse, ReqRespSubProtocol, type ReqRespSubProtocolHandler, type ReqRespSubProtocolHandlers, type ReqRespSubProtocolRateLimits, type ReqRespSubProtocolValidators, type ShouldRejectPeer, type SubProtocolMap } from './interface.js';
7
+ import { type ReqRespInterface, type ReqRespResponse, ReqRespSubProtocol, type ReqRespSubProtocolHandler, type ReqRespSubProtocolHandlers, type ReqRespSubProtocolRateLimits, type ShouldRejectPeer } from './interface.js';
8
8
  /**
9
9
  * The Request Response Service
10
10
  *
11
11
  * It allows nodes to request specific information from their peers, its use case covers recovering
12
- * information that was missed during a syncronisation or a gossip event.
12
+ * information that was missed during a synchronisation or a gossip event.
13
13
  *
14
14
  * This service implements the request response sub protocol, it is heavily inspired from
15
15
  * ethereum implementations of the same name.
@@ -26,7 +26,6 @@ export declare class ReqResp implements ReqRespInterface {
26
26
  private individualRequestTimeoutMs;
27
27
  private dialTimeoutMs;
28
28
  private subProtocolHandlers;
29
- private subProtocolValidators;
30
29
  private connectionSampler;
31
30
  private rateLimiter;
32
31
  private snappyTransform;
@@ -43,35 +42,12 @@ export declare class ReqResp implements ReqRespInterface {
43
42
  /**
44
43
  * Start the reqresp service
45
44
  */
46
- start(subProtocolHandlers: ReqRespSubProtocolHandlers, subProtocolValidators: ReqRespSubProtocolValidators): Promise<void>;
47
- addSubProtocol(subProtocol: ReqRespSubProtocol, handler: ReqRespSubProtocolHandler, validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol]): Promise<void>;
45
+ start(subProtocolHandlers: ReqRespSubProtocolHandlers): Promise<void>;
46
+ addSubProtocol(subProtocol: ReqRespSubProtocol, handler: ReqRespSubProtocolHandler): Promise<void>;
48
47
  /**
49
48
  * Stop the reqresp service
50
49
  */
51
50
  stop(): Promise<void>;
52
- /**
53
- * Request multiple messages over the same sub protocol, balancing the requests across peers.
54
- *
55
- * @devnote
56
- * - The function prioritizes sending requests to free peers using a batch sampling strategy.
57
- * - If a peer fails to respond or returns an invalid response, it is removed from the sampling pool and replaced.
58
- * - The function stops retrying once all requests are processed, no active peers remain, or the maximum retry attempts are reached.
59
- * - Responses are validated using a custom validator for the sub-protocol.*
60
- *
61
- * Requests are sent in parallel to each peer, but multiple requests are sent to the same peer in series
62
- * - If a peer fails to respond or returns an invalid response, it is removed from the sampling pool and replaced.
63
- * - The function stops retrying once all requests are processed, no active peers remain, or the maximum retry attempts are reached.
64
- * - Responses are validated using a custom validator for the sub-protocol.*
65
- *
66
- * @param subProtocol
67
- * @param requests
68
- * @param timeoutMs
69
- * @param maxPeers
70
- * @returns
71
- *
72
- * @throws {CollectiveReqRespTimeoutError} - If the request batch exceeds the specified timeout (`timeoutMs`).
73
- */
74
- sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(subProtocol: SubProtocol, requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[], pinnedPeer: PeerId | undefined, timeoutMs?: number, maxPeers?: number, maxRetryAttempts?: number): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]>;
75
51
  /**
76
52
  * Sends a request to a specific peer
77
53
  *
@@ -128,4 +104,4 @@ export declare class ReqResp implements ReqRespInterface {
128
104
  private categorizeResponseError;
129
105
  private categorizeConnectionErrors;
130
106
  }
131
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxcmVzcC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3JlcXJlc3AvcmVxcmVzcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFNQSxPQUFPLEVBQWMsS0FBSyxlQUFlLEVBQWlDLE1BQU0seUJBQXlCLENBQUM7QUFFMUcsT0FBTyxLQUFLLEVBQXNCLE1BQU0sRUFBVSxNQUFNLG1CQUFtQixDQUFDO0FBQzVFLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQztBQVVyQyxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBR0wsS0FBSyxnQkFBZ0IsRUFDdEIsTUFBTSxhQUFhLENBQUM7QUFFckIsT0FBTyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLDRDQUE0QyxDQUFDO0FBQzlGLE9BQU8sRUFFTCxLQUFLLGdCQUFnQixFQUNyQixLQUFLLGVBQWUsRUFDcEIsa0JBQWtCLEVBQ2xCLEtBQUsseUJBQXlCLEVBQzlCLEtBQUssMEJBQTBCLEVBQy9CLEtBQUssNEJBQTRCLEVBQ2pDLEtBQUssNEJBQTRCLEVBQ2pDLEtBQUssZ0JBQWdCLEVBQ3JCLEtBQUssY0FBYyxFQUlwQixNQUFNLGdCQUFnQixDQUFDO0FBU3hCOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxxQkFBYSxPQUFRLFlBQVcsZ0JBQWdCO0lBa0I1QyxPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxXQUFXO0lBQ25CLE9BQU8sQ0FBQyxNQUFNO0lBbkJoQixPQUFPLENBQUMsMEJBQTBCLENBQWlEO0lBQ25GLE9BQU8sQ0FBQyxhQUFhLENBQTJDO0lBRWhFLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBMkM7SUFDdEUsT0FBTyxDQUFDLHFCQUFxQixDQUE2QztJQUUxRSxPQUFPLENBQUMsaUJBQWlCLENBQW9CO0lBQzdDLE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBRWhELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBRXpDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBK0I7SUFFdkQsT0FBTyxDQUFDLE9BQU8sQ0FBaUI7SUFFaEMsWUFDRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQ2hCLE1BQU0sRUFBRSxNQUFNLEVBQ2QsV0FBVyxFQUFFLFdBQVcsRUFDeEIsTUFBTSx5Q0FBOEIsRUFDNUMsVUFBVSxHQUFFLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBTSxFQUN0RCxlQUFlLEdBQUUsZUFBc0MsRUFnQnhEO0lBRU0sWUFBWSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxJQUFJLENBUTNEO0lBRU0sbUJBQW1CLENBQUMsT0FBTyxFQUFFLGdCQUFnQixHQUFHLElBQUksQ0FFMUQ7SUFFRCxJQUFJLE1BQU0sNkNBRVQ7SUFFRDs7T0FFRztJQUNILG9CQUFvQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRSx1Q0FBdUMsQ0FBQyxDQUV2RjtJQUVEOztPQUVHO0lBQ0csS0FBSyxDQUFDLG1CQUFtQixFQUFFLDBCQUEwQixFQUFFLHFCQUFxQixFQUFFLDRCQUE0QixpQkFnQi9HO0lBRUssY0FBYyxDQUNsQixXQUFXLEVBQUUsa0JBQWtCLEVBQy9CLE9BQU8sRUFBRSx5QkFBeUIsRUFDbEMsU0FBUyxHQUFFLDRCQUE0QixDQUFDLGtCQUFrQixDQUFnRCxHQUN6RyxPQUFPLENBQUMsSUFBSSxDQUFDLENBV2Y7SUFFRDs7T0FFRztJQUNHLElBQUksa0JBa0JUO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQXFCRztJQVFHLGdCQUFnQixDQUFDLFdBQVcsU0FBUyxrQkFBa0IsRUFDM0QsV0FBVyxFQUFFLFdBQVcsRUFDeEIsUUFBUSxFQUFFLFlBQVksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxFQUNoRSxVQUFVLEVBQUUsTUFBTSxHQUFHLFNBQVMsRUFDOUIsU0FBUyxTQUFRLEVBQ2pCLFFBQVEsU0FBK0MsRUFDdkQsZ0JBQWdCLFNBQUksR0FDbkIsT0FBTyxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRSxDQUFDLENBcUxsRTtJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0F3Qkc7SUFLVSxpQkFBaUIsQ0FDNUIsTUFBTSxFQUFFLE1BQU0sRUFDZCxXQUFXLEVBQUUsa0JBQWtCLEVBQy9CLE9BQU8sRUFBRSxNQUFNLEVBQ2YsV0FBVyxHQUFFLE1BQTJCLEdBQ3ZDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0EyRDFCO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsT0FBTyxDQUFDLG1CQUFtQjtZQWlCYixXQUFXO1lBNERYLGFBQWE7WUEwRWIsYUFBYTtZQXdDYixZQUFZO0lBbUMxQixPQUFPLENBQUMsa0JBQWtCO0lBTzFCOzs7O09BSUc7SUFDSCxPQUFPLENBQUMsc0JBQXNCO0lBaUI5Qjs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLHVCQUF1QjtJQXVDL0IsT0FBTyxDQUFDLDBCQUEwQjtDQThEbkMifQ==
107
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxcmVzcC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3JlcXJlc3AvcmVxcmVzcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxPQUFPLEVBQWMsS0FBSyxlQUFlLEVBQWlDLE1BQU0seUJBQXlCLENBQUM7QUFFMUcsT0FBTyxLQUFLLEVBQXNCLE1BQU0sRUFBVSxNQUFNLG1CQUFtQixDQUFDO0FBQzVFLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQztBQU1yQyxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBR0wsS0FBSyxnQkFBZ0IsRUFDdEIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLDRDQUE0QyxDQUFDO0FBQzlGLE9BQU8sRUFDTCxLQUFLLGdCQUFnQixFQUNyQixLQUFLLGVBQWUsRUFDcEIsa0JBQWtCLEVBQ2xCLEtBQUsseUJBQXlCLEVBQzlCLEtBQUssMEJBQTBCLEVBQy9CLEtBQUssNEJBQTRCLEVBQ2pDLEtBQUssZ0JBQWdCLEVBR3RCLE1BQU0sZ0JBQWdCLENBQUM7QUFTeEI7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILHFCQUFhLE9BQVEsWUFBVyxnQkFBZ0I7SUFpQjVDLE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLFdBQVc7SUFDbkIsT0FBTyxDQUFDLE1BQU07SUFsQmhCLE9BQU8sQ0FBQywwQkFBMEIsQ0FBaUQ7SUFDbkYsT0FBTyxDQUFDLGFBQWEsQ0FBMkM7SUFFaEUsT0FBTyxDQUFDLG1CQUFtQixDQUEyQztJQUV0RSxPQUFPLENBQUMsaUJBQWlCLENBQW9CO0lBQzdDLE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBRWhELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBRXpDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBK0I7SUFFdkQsT0FBTyxDQUFDLE9BQU8sQ0FBaUI7SUFFaEMsWUFDRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQ2hCLE1BQU0sRUFBRSxNQUFNLEVBQ2QsV0FBVyxFQUFFLFdBQVcsRUFDeEIsTUFBTSx5Q0FBOEIsRUFDNUMsVUFBVSxHQUFFLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBTSxFQUN0RCxlQUFlLEdBQUUsZUFBc0MsRUFnQnhEO0lBRU0sWUFBWSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxJQUFJLENBUTNEO0lBRU0sbUJBQW1CLENBQUMsT0FBTyxFQUFFLGdCQUFnQixHQUFHLElBQUksQ0FFMUQ7SUFFRCxJQUFJLE1BQU0sNkNBRVQ7SUFFRDs7T0FFRztJQUNILG9CQUFvQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRSx1Q0FBdUMsQ0FBQyxDQUV2RjtJQUVEOztPQUVHO0lBQ0csS0FBSyxDQUFDLG1CQUFtQixFQUFFLDBCQUEwQixpQkFnQjFEO0lBRUssY0FBYyxDQUFDLFdBQVcsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVV2RztJQUVEOztPQUVHO0lBQ0csSUFBSSxrQkFrQlQ7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09Bd0JHO0lBS1UsaUJBQWlCLENBQzVCLE1BQU0sRUFBRSxNQUFNLEVBQ2QsV0FBVyxFQUFFLGtCQUFrQixFQUMvQixPQUFPLEVBQUUsTUFBTSxFQUNmLFdBQVcsR0FBRSxNQUEyQixHQUN2QyxPQUFPLENBQUMsZUFBZSxDQUFDLENBMkQxQjtJQUVEOzs7Ozs7Ozs7T0FTRztJQUNILE9BQU8sQ0FBQyxtQkFBbUI7WUFpQmIsV0FBVztZQTREWCxhQUFhO1lBMEViLGFBQWE7WUF3Q2IsWUFBWTtJQW1DMUIsT0FBTyxDQUFDLGtCQUFrQjtJQU8xQjs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLHNCQUFzQjtJQWlCOUI7Ozs7T0FJRztJQUNILE9BQU8sQ0FBQyx1QkFBdUI7SUFrQy9CLE9BQU8sQ0FBQywwQkFBMEI7Q0E4RG5DIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/reqresp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/reqresp.ts"],"names":[],"mappings":"AAKA,OAAO,EAAc,KAAK,eAAe,EAAiC,MAAM,yBAAyB,CAAC;AAE1G,OAAO,KAAK,EAAsB,MAAM,EAAU,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAMrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAiB,MAAM,4CAA4C,CAAC;AAC9F,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AASxB;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAQ,YAAW,gBAAgB;IAiB5C,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAlBhB,OAAO,CAAC,0BAA0B,CAAiD;IACnF,OAAO,CAAC,aAAa,CAA2C;IAEhE,OAAO,CAAC,mBAAmB,CAA2C;IAEtE,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,WAAW,CAA6B;IAEhD,OAAO,CAAC,eAAe,CAAkB;IAEzC,OAAO,CAAC,gBAAgB,CAA+B;IAEvD,OAAO,CAAC,OAAO,CAAiB;IAEhC,YACE,MAAM,EAAE,gBAAgB,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,MAAM,yCAA8B,EAC5C,UAAU,GAAE,OAAO,CAAC,4BAA4B,CAAM,EACtD,eAAe,GAAE,eAAsC,EAgBxD;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAQ3D;IAEM,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAE1D;IAED,IAAI,MAAM,6CAET;IAED;;OAEG;IACH,oBAAoB,IAAI,IAAI,CAAC,iBAAiB,EAAE,uCAAuC,CAAC,CAEvF;IAED;;OAEG;IACG,KAAK,CAAC,mBAAmB,EAAE,0BAA0B,iBAgB1D;IAEK,cAAc,CAAC,WAAW,EAAE,kBAAkB,EAAE,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUvG;IAED;;OAEG;IACG,IAAI,kBAkBT;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IAKU,iBAAiB,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAA2B,GACvC,OAAO,CAAC,eAAe,CAAC,CA2D1B;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;YAiBb,WAAW;YA4DX,aAAa;YA0Eb,aAAa;YAwCb,YAAY;IAmC1B,OAAO,CAAC,kBAAkB;IAO1B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAiB9B;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAkC/B,OAAO,CAAC,0BAA0B;CA8DnC"}
@@ -371,30 +371,25 @@ function applyDecs2203RFactory() {
371
371
  function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
372
372
  return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
373
373
  }
374
- var _dec, _dec1, _dec2, _initProto;
375
- import { compactArray } from '@aztec/foundation/collection';
374
+ var _dec, _dec1, _initProto;
376
375
  import { AbortError, TimeoutError } from '@aztec/foundation/error';
377
376
  import { createLogger } from '@aztec/foundation/log';
378
377
  import { executeTimeout } from '@aztec/foundation/timer';
379
378
  import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
380
379
  import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
381
380
  import { pipeline } from 'node:stream/promises';
382
- import { CollectiveReqRespTimeoutError, IndividualReqRespTimeoutError, InvalidResponseError } from '../../errors/reqresp.error.js';
381
+ import { IndividualReqRespTimeoutError } from '../../errors/reqresp.error.js';
383
382
  import { OversizedSnappyResponseError, SnappyTransform } from '../encoding.js';
384
383
  import { DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS, DEFAULT_REQRESP_DIAL_TIMEOUT_MS } from './config.js';
385
- import { BatchConnectionSampler } from './connection-sampler/batch_connection_sampler.js';
386
384
  import { ConnectionSampler, RandomSampler } from './connection-sampler/connection_sampler.js';
387
- import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, UNAUTHENTICATED_ALLOWED_PROTOCOLS, responseFromBuffer, subProtocolSizeCalculators } from './interface.js';
385
+ import { ReqRespSubProtocol, UNAUTHENTICATED_ALLOWED_PROTOCOLS, subProtocolSizeCalculators } from './interface.js';
388
386
  import { ReqRespMetrics } from './metrics.js';
389
387
  import { RateLimitStatus, RequestResponseRateLimiter, prettyPrintRateLimitStatus } from './rate-limiter/rate_limiter.js';
390
- import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqRespStatus } from './status.js';
391
- _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
392
- [Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol,
393
- [Attributes.P2P_REQ_RESP_BATCH_REQUESTS_COUNT]: requests.length
394
- })), _dec1 = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
388
+ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk } from './status.js';
389
+ _dec = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
395
390
  [Attributes.P2P_ID]: peerId.toString(),
396
391
  [Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol
397
- })), _dec2 = trackSpan('ReqResp.streamHandler', (protocol, { connection })=>({
392
+ })), _dec1 = trackSpan('ReqResp.streamHandler', (protocol, { connection })=>({
398
393
  [Attributes.P2P_REQ_RESP_PROTOCOL]: protocol,
399
394
  [Attributes.P2P_ID]: connection.remotePeer.toString()
400
395
  }));
@@ -402,7 +397,7 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
402
397
  * The Request Response Service
403
398
  *
404
399
  * It allows nodes to request specific information from their peers, its use case covers recovering
405
- * information that was missed during a syncronisation or a gossip event.
400
+ * information that was missed during a synchronisation or a gossip event.
406
401
  *
407
402
  * This service implements the request response sub protocol, it is heavily inspired from
408
403
  * ethereum implementations of the same name.
@@ -420,15 +415,10 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
420
415
  [
421
416
  _dec,
422
417
  2,
423
- "sendBatchRequest"
424
- ],
425
- [
426
- _dec1,
427
- 2,
428
418
  "sendRequestToPeer"
429
419
  ],
430
420
  [
431
- _dec2,
421
+ _dec1,
432
422
  2,
433
423
  "streamHandler"
434
424
  ]
@@ -437,7 +427,6 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
437
427
  individualRequestTimeoutMs;
438
428
  dialTimeoutMs;
439
429
  subProtocolHandlers;
440
- subProtocolValidators;
441
430
  connectionSampler;
442
431
  rateLimiter;
443
432
  snappyTransform;
@@ -450,7 +439,6 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
450
439
  this.individualRequestTimeoutMs = (_initProto(this), DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS);
451
440
  this.dialTimeoutMs = DEFAULT_REQRESP_DIAL_TIMEOUT_MS;
452
441
  this.subProtocolHandlers = {};
453
- this.subProtocolValidators = {};
454
442
  this.updateConfig(config);
455
443
  this.rateLimiter = new RequestResponseRateLimiter(peerScoring, rateLimits);
456
444
  // Connection sampler is used to sample our connected peers
@@ -479,19 +467,18 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
479
467
  }
480
468
  /**
481
469
  * Start the reqresp service
482
- */ async start(subProtocolHandlers, subProtocolValidators) {
470
+ */ async start(subProtocolHandlers) {
483
471
  Object.assign(this.subProtocolHandlers, subProtocolHandlers);
484
- Object.assign(this.subProtocolValidators, subProtocolValidators);
485
- // Register all protocol handlers
472
+ // Register streamHandler with libp2p.
473
+ // The streamHandler is responsible for reading the incoming stream, determining the protocol, then triggering the appropriate handler.
486
474
  for (const subProtocol of Object.keys(subProtocolHandlers)){
487
475
  this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
488
476
  await this.libp2p.handle(subProtocol, (data)=>void this.streamHandler(subProtocol, data).catch((err)=>this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err)));
489
477
  }
490
478
  this.rateLimiter.start();
491
479
  }
492
- async addSubProtocol(subProtocol, handler, validator = DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol]) {
480
+ async addSubProtocol(subProtocol, handler) {
493
481
  this.subProtocolHandlers[subProtocol] = handler;
494
- this.subProtocolValidators[subProtocol] = validator;
495
482
  this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
496
483
  await this.libp2p.handle(subProtocol, (data)=>void this.streamHandler(subProtocol, data).catch((err)=>this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err)));
497
484
  }
@@ -513,179 +500,6 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
513
500
  // NOTE: We assume libp2p instance is managed by the caller
514
501
  }
515
502
  /**
516
- * Request multiple messages over the same sub protocol, balancing the requests across peers.
517
- *
518
- * @devnote
519
- * - The function prioritizes sending requests to free peers using a batch sampling strategy.
520
- * - If a peer fails to respond or returns an invalid response, it is removed from the sampling pool and replaced.
521
- * - The function stops retrying once all requests are processed, no active peers remain, or the maximum retry attempts are reached.
522
- * - Responses are validated using a custom validator for the sub-protocol.*
523
- *
524
- * Requests are sent in parallel to each peer, but multiple requests are sent to the same peer in series
525
- * - If a peer fails to respond or returns an invalid response, it is removed from the sampling pool and replaced.
526
- * - The function stops retrying once all requests are processed, no active peers remain, or the maximum retry attempts are reached.
527
- * - Responses are validated using a custom validator for the sub-protocol.*
528
- *
529
- * @param subProtocol
530
- * @param requests
531
- * @param timeoutMs
532
- * @param maxPeers
533
- * @returns
534
- *
535
- * @throws {CollectiveReqRespTimeoutError} - If the request batch exceeds the specified timeout (`timeoutMs`).
536
- */ async sendBatchRequest(subProtocol, requests, pinnedPeer, timeoutMs = 10000, maxPeers = Math.max(10, Math.ceil(requests.length / 3)), maxRetryAttempts = 3) {
537
- const responseValidator = this.subProtocolValidators[subProtocol] ?? DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol];
538
- const responses = new Array(requests.length);
539
- const requestBuffers = requests.map((req)=>req.toBuffer());
540
- const isEmptyResponse = (value)=>{
541
- // Some responses serialize to a non-empty buffer even when they contain no items (e.g., empty TxArray).
542
- if (!value || typeof value !== 'object') {
543
- return false;
544
- }
545
- const length = value.length;
546
- return typeof length === 'number' && length === 0;
547
- };
548
- const requestFunction = async (signal)=>{
549
- // Track which requests still need to be processed
550
- const pendingRequestIndices = new Set(requestBuffers.map((_, i)=>i));
551
- // Create batch sampler with the total number of requests and max peers
552
- const batchSampler = new BatchConnectionSampler(this.connectionSampler, requests.length, maxPeers, compactArray([
553
- pinnedPeer
554
- ]), createLogger(`${this.logger.module}:batch-connection-sampler`));
555
- if (batchSampler.activePeerCount === 0 && !pinnedPeer) {
556
- this.logger.warn('No active peers to send requests to');
557
- return [];
558
- }
559
- // This is where it gets fun
560
- // The outer loop is the retry loop, we will continue to retry until we process all indices we have
561
- // not received a response for, or we have reached the max retry attempts
562
- // The inner loop is the batch loop, we will process all requests for each peer in parallel
563
- // We will then process the results of the requests, and resample any peers that failed to respond
564
- // We will continue to retry until we have processed all indices, or we have reached the max retry attempts
565
- let retryAttempts = 0;
566
- while(pendingRequestIndices.size > 0 && batchSampler.activePeerCount > 0 && retryAttempts < maxRetryAttempts){
567
- if (signal.aborted) {
568
- throw new AbortError('Batch request aborted');
569
- }
570
- const requestBatches = new Map();
571
- // Group requests by peer
572
- for (const requestIndex of pendingRequestIndices){
573
- const peer = batchSampler.getPeerForRequest(requestIndex);
574
- if (!peer) {
575
- continue;
576
- }
577
- const peerAsString = peer.toString();
578
- if (!requestBatches.has(peerAsString)) {
579
- requestBatches.set(peerAsString, {
580
- peerId: peer,
581
- indices: []
582
- });
583
- }
584
- requestBatches.get(peerAsString).indices.push(requestIndex);
585
- }
586
- // If there is a pinned peer, we will always send every request to that peer
587
- // We use the default limits for the subprotocol to avoid hitting the rate limiter
588
- if (pinnedPeer) {
589
- const limit = this.rateLimiter.getRateLimits(subProtocol).peerLimit.quotaCount;
590
- requestBatches.set(pinnedPeer.toString(), {
591
- peerId: pinnedPeer,
592
- indices: Array.from(pendingRequestIndices.values()).slice(0, limit)
593
- });
594
- }
595
- // If no requests could be assigned (all peers exhausted for all indices), exit early
596
- if (requestBatches.size === 0) {
597
- this.logger.warn('No peers available for any pending request indices, stopping batch request');
598
- break;
599
- }
600
- // Make parallel requests for each peer's batch
601
- // A batch entry will look something like this:
602
- // PeerId0: [0, 1, 2, 3]
603
- // PeerId1: [4, 5, 6, 7]
604
- // Peer Id 0 will send requests 0, 1, 2, 3 in serial
605
- // while simultaneously Peer Id 1 will send requests 4, 5, 6, 7 in serial
606
- const batchResults = await Promise.all(Array.from(requestBatches.entries()).map(async ([peerAsString, { peerId: peer, indices }])=>{
607
- try {
608
- const markIndexFailed = (index)=>batchSampler.markPeerFailedForIndex(peer, index);
609
- // Requests all going to the same peer are sent synchronously
610
- const peerResults = [];
611
- let shouldReplacePeer = false;
612
- const handleFailure = (status, index)=>{
613
- this.logger.warn(`Request to peer ${peerAsString} failed with status ${prettyPrintReqRespStatus(status)}`);
614
- markIndexFailed(index);
615
- return status === ReqRespStatus.RATE_LIMIT_EXCEEDED;
616
- };
617
- for (const index of indices){
618
- this.logger.trace(`Sending request ${index} to peer ${peerAsString}`);
619
- const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffers[index]);
620
- // Check the status of the response buffer
621
- if (response.status !== ReqRespStatus.SUCCESS) {
622
- shouldReplacePeer = handleFailure(response.status, index);
623
- if (shouldReplacePeer) {
624
- break;
625
- }
626
- continue;
627
- }
628
- if (response.data.length === 0) {
629
- markIndexFailed(index);
630
- continue;
631
- }
632
- const object = responseFromBuffer(subProtocol, response.data);
633
- if (isEmptyResponse(object)) {
634
- markIndexFailed(index);
635
- continue;
636
- }
637
- const isValid = await responseValidator(requests[index], object, peer);
638
- if (!isValid) {
639
- markIndexFailed(index);
640
- continue;
641
- }
642
- peerResults.push({
643
- index,
644
- response: object
645
- });
646
- }
647
- // If peer had a hard failure (rate limit), replace it for future iterations
648
- if (shouldReplacePeer) {
649
- this.logger.warn(`Peer ${peerAsString} hit a hard failure, removing from sampler`);
650
- batchSampler.removePeerAndReplace(peer);
651
- }
652
- return {
653
- peer,
654
- results: peerResults
655
- };
656
- } catch (error) {
657
- this.logger.warn(`Failed batch request to peer ${peerAsString}:`, error);
658
- batchSampler.removePeerAndReplace(peer);
659
- return {
660
- peer,
661
- results: []
662
- };
663
- }
664
- }));
665
- // Process results
666
- for (const { results } of batchResults){
667
- for (const { index, response } of results){
668
- if (response) {
669
- responses[index] = response;
670
- pendingRequestIndices.delete(index);
671
- }
672
- }
673
- }
674
- retryAttempts++;
675
- }
676
- if (retryAttempts >= maxRetryAttempts) {
677
- this.logger.warn(`Max retry attempts ${maxRetryAttempts} reached for batch request`);
678
- }
679
- return responses;
680
- };
681
- try {
682
- return await executeTimeout(requestFunction, timeoutMs, ()=>new CollectiveReqRespTimeoutError());
683
- } catch (e) {
684
- this.logger.warn(`${e.message} | subProtocol: ${subProtocol}`);
685
- return [];
686
- }
687
- }
688
- /**
689
503
  * Sends a request to a specific peer
690
504
  *
691
505
  * We first dial a particular protocol for the peer, this ensures that the peer knows
@@ -956,12 +770,12 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
956
770
  peerId: peerId.toString(),
957
771
  subProtocol
958
772
  };
959
- //Punishable error - peer should never send badly formed request
773
+ // Punishable error - peer should never send badly formed request
960
774
  if (e instanceof ReqRespStatusError && e.status === ReqRespStatus.BADLY_FORMED_REQUEST) {
961
775
  this.logger.debug(`Punishable error in ${subProtocol}: ${e.cause}`, logTags);
962
776
  return PeerErrorSeverity.LowToleranceError;
963
777
  }
964
- //TODO: (mralj): think if we should penalize peer here based on connection errors
778
+ // TODO: (mralj): think if we should penalize peer here based on connection errors
965
779
  return undefined;
966
780
  }
967
781
  /**
@@ -978,11 +792,6 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
978
792
  this.logger.debug('Error encountered on goodbye sub protocol, no penalty', logTags);
979
793
  return undefined;
980
794
  }
981
- // We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
982
- if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
983
- this.logger.debug(`Non-punishable error in ${subProtocol}: ${e.message}`, logTags);
984
- return undefined;
985
- }
986
795
  // Invalid status byte: the peer sent a status byte that doesn't match any known status code.
987
796
  // This is a protocol violation, penalize harshly.
988
797
  if (e instanceof ReqRespStatusError) {
@@ -999,7 +808,8 @@ _dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
999
808
  }
1000
809
  /*
1001
810
  * Errors specific to connection handling
1002
- * These can happen both when sending request and response*/ categorizeConnectionErrors(e, peerId, subProtocol) {
811
+ * These can happen both when sending request and response.
812
+ */ categorizeConnectionErrors(e, peerId, subProtocol) {
1003
813
  const logTags = {
1004
814
  peerId: peerId.toString(),
1005
815
  subProtocol
@@ -9,7 +9,7 @@ import type EventEmitter from 'events';
9
9
  import type { BatchTxRequesterLibP2PService } from './reqresp/batch-tx-requester/interface.js';
10
10
  import type { P2PReqRespConfig } from './reqresp/config.js';
11
11
  import type { StatusMessage } from './reqresp/index.js';
12
- import type { ReqRespSubProtocol, ReqRespSubProtocolHandler, ReqRespSubProtocolValidators, SubProtocolMap } from './reqresp/interface.js';
12
+ import type { ReqRespSubProtocol, ReqRespSubProtocolHandler } from './reqresp/interface.js';
13
13
  import type { AuthRequest, AuthResponse } from './reqresp/protocols/auth.js';
14
14
  export declare enum PeerDiscoveryState {
15
15
  RUNNING = "running",
@@ -51,6 +51,7 @@ export type DuplicateAttestationInfo = {
51
51
  * Invoked on the first duplicate (when count goes from 1 to 2).
52
52
  */
53
53
  export type P2PDuplicateAttestationCallback = (info: DuplicateAttestationInfo) => void;
54
+ export type P2PCheckpointAttestationCallback = (attestation: CheckpointAttestation) => void;
54
55
  /**
55
56
  * The interface for a P2P service implementation.
56
57
  */
@@ -70,19 +71,9 @@ export interface P2PService {
70
71
  * @param message - The message to be propagated.
71
72
  */
72
73
  propagate<T extends Gossipable>(message: T): Promise<void>;
73
- /**
74
- * Send a batch of requests to peers, and return the responses
75
- *
76
- * @param protocol - The request response protocol to use
77
- * @param requests - The requests to send to the peers
78
- * @returns The responses to the requests
79
- */
80
- sendBatchRequest<Protocol extends ReqRespSubProtocol>(protocol: Protocol, requests: InstanceType<SubProtocolMap[Protocol]['request']>[], pinnedPeerId?: PeerId, timeoutMs?: number, maxPeers?: number, maxRetryAttempts?: number): Promise<InstanceType<SubProtocolMap[Protocol]['response']>[]>;
81
74
  registerBlockReceivedCallback(callback: P2PBlockReceivedCallback): void;
82
75
  registerValidatorCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback): void;
83
76
  registerAllNodesCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback): void;
84
- /** Fires the all-nodes checkpoint callback for our own proposal (gossipsub doesn't deliver own messages). */
85
- notifyOwnCheckpointProposal(checkpoint: CheckpointProposalCore): Promise<void>;
86
77
  /**
87
78
  * Registers a callback invoked when a duplicate proposal is detected (equivocation).
88
79
  * The callback is triggered on the first duplicate (when count goes from 1 to 2).
@@ -94,12 +85,13 @@ export interface P2PService {
94
85
  * The callback is triggered on the first duplicate (when count goes from 1 to 2).
95
86
  */
96
87
  registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void;
88
+ registerCheckpointAttestationCallback(callback: P2PCheckpointAttestationCallback): void;
97
89
  getEnr(): ENR | undefined;
98
90
  getPeers(includePending?: boolean): PeerInfo[];
99
91
  /** Returns the number of peers in the GossipSub mesh for a given topic type. */
100
92
  getGossipMeshPeerCount(topicType: TopicType): number;
101
93
  validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void>;
102
- addReqRespSubProtocol(subProtocol: ReqRespSubProtocol, handler: ReqRespSubProtocolHandler, validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol]): Promise<void>;
94
+ addReqRespSubProtocol(subProtocol: ReqRespSubProtocol, handler: ReqRespSubProtocolHandler): Promise<void>;
103
95
  handleAuthRequestFromPeer(authRequest: AuthRequest, peerId: PeerId): Promise<StatusMessage>;
104
96
  updateConfig(config: Partial<P2PReqRespConfig>): void;
105
97
  /** If node running this P2P stack is validator, passes in validator address to P2P layer */
@@ -139,8 +131,10 @@ export interface PeerDiscoveryService extends EventEmitter {
139
131
  */
140
132
  on(event: 'peer:discovered', listener: (enr: ENR) => void): this;
141
133
  emit(event: 'peer:discovered', enr: ENR): boolean;
134
+ on(event: 'ip:changed', listener: (ip: string) => void): this;
135
+ emit(event: 'ip:changed', ip: string): boolean;
142
136
  getStatus(): PeerDiscoveryState;
143
137
  getEnr(): ENR | undefined;
144
138
  bootstrapNodeEnrs: ENR[];
145
139
  }
146
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZpY2VzL3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQ1YsYUFBYSxFQUNiLHFCQUFxQixFQUNyQixzQkFBc0IsRUFDdEIsVUFBVSxFQUNWLFNBQVMsRUFDVixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTNDLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxZQUFZLE1BQU0sUUFBUSxDQUFDO0FBRXZDLE9BQU8sS0FBSyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDL0YsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEtBQUssRUFDVixrQkFBa0IsRUFDbEIseUJBQXlCLEVBQ3pCLDRCQUE0QixFQUM1QixjQUFjLEVBQ2YsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFN0Usb0JBQVksa0JBQWtCO0lBQzVCLE9BQU8sWUFBWTtJQUNuQixPQUFPLFlBQVk7Q0FDcEI7QUFFRDs7OztHQUlHO0FB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
140
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZpY2VzL3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQ1YsYUFBYSxFQUNiLHFCQUFxQixFQUNyQixzQkFBc0IsRUFDdEIsVUFBVSxFQUNWLFNBQVMsRUFDVixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTNDLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxZQUFZLE1BQU0sUUFBUSxDQUFDO0FBRXZDLE9BQU8sS0FBSyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDL0YsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVGLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUU3RSxvQkFBWSxrQkFBa0I7SUFDNUIsT0FBTyxZQUFZO0lBQ25CLE9BQU8sWUFBWTtDQUNwQjtBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLE1BQU0sd0JBQXdCLEdBQUcs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