@aztec/p2p 1.2.1 → 2.0.0-nightly.20250813

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 (221) hide show
  1. package/dest/client/factory.d.ts +5 -1
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +29 -12
  4. package/dest/client/interface.d.ts +8 -13
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +18 -22
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +86 -83
  9. package/dest/config.d.ts +30 -1
  10. package/dest/config.d.ts.map +1 -1
  11. package/dest/config.js +34 -1
  12. package/dest/index.d.ts +1 -0
  13. package/dest/index.d.ts.map +1 -1
  14. package/dest/index.js +1 -0
  15. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +13 -1
  16. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  17. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  18. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +117 -10
  19. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +4 -1
  20. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  21. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +22 -1
  22. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +4 -1
  23. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +21 -1
  25. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -2
  26. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/mocks.js +2 -10
  28. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +8 -3
  29. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  30. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +64 -37
  31. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +8 -3
  32. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  33. package/dest/mem_pools/tx_pool/memory_tx_pool.js +18 -10
  34. package/dest/mem_pools/tx_pool/tx_pool.d.ts +11 -2
  35. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  36. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  37. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +73 -44
  38. package/dest/msg_validators/attestation_validator/attestation_validator.js +1 -1
  39. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  40. package/dest/msg_validators/tx_validator/block_header_validator.js +2 -2
  41. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  42. package/dest/msg_validators/tx_validator/data_validator.js +35 -59
  43. package/dest/msg_validators/tx_validator/double_spend_validator.js +2 -2
  44. package/dest/msg_validators/tx_validator/gas_validator.js +4 -4
  45. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  46. package/dest/msg_validators/tx_validator/metadata_validator.js +21 -21
  47. package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
  48. package/dest/msg_validators/tx_validator/tx_proof_validator.js +3 -3
  49. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  50. package/dest/services/discv5/discV5_service.js +4 -1
  51. package/dest/services/dummy_service.d.ts +13 -3
  52. package/dest/services/dummy_service.d.ts.map +1 -1
  53. package/dest/services/dummy_service.js +26 -3
  54. package/dest/services/index.d.ts +3 -1
  55. package/dest/services/index.d.ts.map +1 -1
  56. package/dest/services/index.js +3 -1
  57. package/dest/services/libp2p/libp2p_service.d.ts +13 -20
  58. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  59. package/dest/services/libp2p/libp2p_service.js +123 -46
  60. package/dest/services/peer-manager/interface.d.ts +8 -1
  61. package/dest/services/peer-manager/interface.d.ts.map +1 -1
  62. package/dest/services/peer-manager/peer_manager.d.ts +70 -3
  63. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  64. package/dest/services/peer-manager/peer_manager.js +369 -39
  65. package/dest/services/reqresp/config.d.ts +3 -3
  66. package/dest/services/reqresp/config.d.ts.map +1 -1
  67. package/dest/services/reqresp/config.js +3 -3
  68. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +3 -4
  69. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  70. package/dest/services/reqresp/connection-sampler/connection_sampler.js +35 -52
  71. package/dest/services/reqresp/index.d.ts +2 -1
  72. package/dest/services/reqresp/index.d.ts.map +1 -1
  73. package/dest/services/reqresp/index.js +2 -1
  74. package/dest/services/reqresp/interface.d.ts +61 -10
  75. package/dest/services/reqresp/interface.d.ts.map +1 -1
  76. package/dest/services/reqresp/interface.js +41 -6
  77. package/dest/services/reqresp/protocols/auth.d.ts +43 -0
  78. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
  79. package/dest/services/reqresp/protocols/auth.js +71 -0
  80. package/dest/services/reqresp/protocols/block.d.ts +5 -0
  81. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  82. package/dest/services/reqresp/protocols/block.js +28 -5
  83. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
  84. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
  85. package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -0
  86. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
  87. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
  88. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +39 -0
  89. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +49 -0
  90. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
  91. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +75 -0
  92. package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
  93. package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
  94. package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
  95. package/dest/services/reqresp/protocols/goodbye.js +3 -5
  96. package/dest/services/reqresp/protocols/index.d.ts +2 -0
  97. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  98. package/dest/services/reqresp/protocols/index.js +2 -0
  99. package/dest/services/reqresp/protocols/status.d.ts +2 -0
  100. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  101. package/dest/services/reqresp/protocols/status.js +7 -0
  102. package/dest/services/reqresp/protocols/tx.d.ts +12 -1
  103. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  104. package/dest/services/reqresp/protocols/tx.js +34 -6
  105. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  106. package/dest/services/reqresp/rate-limiter/rate_limits.js +20 -0
  107. package/dest/services/reqresp/reqresp.d.ts +37 -39
  108. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  109. package/dest/services/reqresp/reqresp.js +220 -220
  110. package/dest/services/reqresp/status.d.ts +8 -3
  111. package/dest/services/reqresp/status.d.ts.map +1 -1
  112. package/dest/services/reqresp/status.js +6 -2
  113. package/dest/services/service.d.ts +10 -10
  114. package/dest/services/service.d.ts.map +1 -1
  115. package/dest/services/tx_collection/config.d.ts +25 -0
  116. package/dest/services/tx_collection/config.d.ts.map +1 -0
  117. package/dest/services/tx_collection/config.js +58 -0
  118. package/dest/services/tx_collection/fast_tx_collection.d.ts +56 -0
  119. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
  120. package/dest/services/tx_collection/fast_tx_collection.js +295 -0
  121. package/dest/services/tx_collection/index.d.ts +3 -0
  122. package/dest/services/tx_collection/index.d.ts.map +1 -0
  123. package/dest/services/tx_collection/index.js +2 -0
  124. package/dest/services/tx_collection/instrumentation.d.ts +10 -0
  125. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
  126. package/dest/services/tx_collection/instrumentation.js +34 -0
  127. package/dest/services/tx_collection/slow_tx_collection.d.ts +54 -0
  128. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
  129. package/dest/services/tx_collection/slow_tx_collection.js +176 -0
  130. package/dest/services/tx_collection/tx_collection.d.ts +109 -0
  131. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
  132. package/dest/services/tx_collection/tx_collection.js +127 -0
  133. package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
  134. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
  135. package/dest/services/tx_collection/tx_collection_sink.js +81 -0
  136. package/dest/services/tx_collection/tx_source.d.ts +18 -0
  137. package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
  138. package/dest/services/tx_collection/tx_source.js +31 -0
  139. package/dest/services/tx_provider.d.ts +49 -0
  140. package/dest/services/tx_provider.d.ts.map +1 -0
  141. package/dest/services/tx_provider.js +206 -0
  142. package/dest/services/{tx_collect_instrumentation.d.ts → tx_provider_instrumentation.d.ts} +2 -2
  143. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
  144. package/dest/services/{tx_collect_instrumentation.js → tx_provider_instrumentation.js} +5 -5
  145. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  146. package/dest/test-helpers/make-test-p2p-clients.js +4 -3
  147. package/dest/test-helpers/mock-pubsub.d.ts +2 -1
  148. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  149. package/dest/test-helpers/mock-pubsub.js +2 -1
  150. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  151. package/dest/test-helpers/reqresp-nodes.js +8 -4
  152. package/dest/testbench/p2p_client_testbench_worker.js +11 -5
  153. package/dest/util.d.ts +1 -1
  154. package/dest/util.d.ts.map +1 -1
  155. package/package.json +14 -15
  156. package/src/client/factory.ts +87 -12
  157. package/src/client/interface.ts +19 -15
  158. package/src/client/p2p_client.ts +108 -92
  159. package/src/config.ts +52 -1
  160. package/src/index.ts +1 -0
  161. package/src/mem_pools/attestation_pool/attestation_pool.ts +15 -1
  162. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +155 -4
  163. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +28 -1
  164. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +28 -2
  165. package/src/mem_pools/attestation_pool/mocks.ts +1 -3
  166. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +59 -41
  167. package/src/mem_pools/tx_pool/memory_tx_pool.ts +19 -9
  168. package/src/mem_pools/tx_pool/tx_pool.ts +7 -2
  169. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +63 -40
  170. package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
  171. package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
  172. package/src/msg_validators/tx_validator/data_validator.ts +36 -27
  173. package/src/msg_validators/tx_validator/double_spend_validator.ts +2 -2
  174. package/src/msg_validators/tx_validator/gas_validator.ts +4 -4
  175. package/src/msg_validators/tx_validator/metadata_validator.ts +22 -28
  176. package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
  177. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -2
  178. package/src/services/discv5/discV5_service.ts +4 -1
  179. package/src/services/dummy_service.ts +44 -4
  180. package/src/services/index.ts +3 -1
  181. package/src/services/libp2p/libp2p_service.ts +147 -55
  182. package/src/services/peer-manager/interface.ts +10 -1
  183. package/src/services/peer-manager/peer_manager.ts +441 -41
  184. package/src/services/reqresp/config.ts +3 -3
  185. package/src/services/reqresp/connection-sampler/connection_sampler.ts +38 -63
  186. package/src/services/reqresp/index.ts +2 -0
  187. package/src/services/reqresp/interface.ts +63 -17
  188. package/src/services/reqresp/protocols/auth.ts +83 -0
  189. package/src/services/reqresp/protocols/block.ts +24 -3
  190. package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
  191. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
  192. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -0
  193. package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
  194. package/src/services/reqresp/protocols/goodbye.ts +3 -3
  195. package/src/services/reqresp/protocols/index.ts +2 -0
  196. package/src/services/reqresp/protocols/status.ts +20 -0
  197. package/src/services/reqresp/protocols/tx.ts +35 -6
  198. package/src/services/reqresp/rate-limiter/rate_limits.ts +20 -0
  199. package/src/services/reqresp/reqresp.ts +294 -264
  200. package/src/services/reqresp/status.ts +9 -3
  201. package/src/services/service.ts +23 -14
  202. package/src/services/tx_collection/config.ts +84 -0
  203. package/src/services/tx_collection/fast_tx_collection.ts +338 -0
  204. package/src/services/tx_collection/index.ts +2 -0
  205. package/src/services/tx_collection/instrumentation.ts +43 -0
  206. package/src/services/tx_collection/slow_tx_collection.ts +232 -0
  207. package/src/services/tx_collection/tx_collection.ts +214 -0
  208. package/src/services/tx_collection/tx_collection_sink.ts +98 -0
  209. package/src/services/tx_collection/tx_source.ts +37 -0
  210. package/src/services/tx_provider.ts +215 -0
  211. package/src/services/{tx_collect_instrumentation.ts → tx_provider_instrumentation.ts} +5 -5
  212. package/src/test-helpers/make-test-p2p-clients.ts +4 -2
  213. package/src/test-helpers/mock-pubsub.ts +1 -0
  214. package/src/test-helpers/reqresp-nodes.ts +7 -1
  215. package/src/testbench/p2p_client_testbench_worker.ts +9 -2
  216. package/src/util.ts +1 -1
  217. package/dest/services/tx_collect_instrumentation.d.ts.map +0 -1
  218. package/dest/services/tx_collector.d.ts +0 -23
  219. package/dest/services/tx_collector.d.ts.map +0 -1
  220. package/dest/services/tx_collector.js +0 -95
  221. package/src/services/tx_collector.ts +0 -134
@@ -34,7 +34,7 @@ export class PhasesTxValidator implements TxValidator<Tx> {
34
34
 
35
35
  if (!tx.data.forPublic) {
36
36
  this.#log.debug(
37
- `Tx ${await Tx.getHash(tx)} does not contain enqueued public functions. Skipping phases validation.`,
37
+ `Tx ${tx.getTxHash().toString()} does not contain enqueued public functions. Skipping phases validation.`,
38
38
  );
39
39
  return { result: 'valid' };
40
40
  }
@@ -43,7 +43,7 @@ export class PhasesTxValidator implements TxValidator<Tx> {
43
43
  for (const setupFn of setupFns) {
44
44
  if (!(await this.isOnAllowList(setupFn, this.setupAllowList))) {
45
45
  this.#log.verbose(
46
- `Rejecting tx ${await Tx.getHash(tx)} because it calls setup function not on allow list: ${
46
+ `Rejecting tx ${tx.getTxHash().toString()} because it calls setup function not on allow list: ${
47
47
  setupFn.request.contractAddress
48
48
  }:${setupFn.functionSelector}`,
49
49
  { allowList: this.setupAllowList },
@@ -10,10 +10,10 @@ export class TxProofValidator implements TxValidator<Tx> {
10
10
  async validateTx(tx: Tx): Promise<TxValidationResult> {
11
11
  const result = await this.verifier.verifyProof(tx);
12
12
  if (!result.valid) {
13
- this.#log.verbose(`Rejecting tx ${await Tx.getHash(tx)} for invalid proof`);
13
+ this.#log.verbose(`Rejecting tx ${tx.getTxHash().toString()} for invalid proof`);
14
14
  return { result: 'invalid', reason: [TX_ERROR_INVALID_PROOF] };
15
15
  }
16
- this.#log.trace(`Accepted ${await Tx.getHash(tx)} with valid proof`);
16
+ this.#log.trace(`Accepted ${tx.getTxHash().toString()} with valid proof`);
17
17
  return { result: 'valid' };
18
18
  }
19
19
  }
@@ -191,7 +191,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
191
191
 
192
192
  public async runRandomNodesQuery(): Promise<void> {
193
193
  if (this.currentState !== PeerDiscoveryState.RUNNING) {
194
- throw new Error('DiscV5Service not running');
194
+ return;
195
195
  }
196
196
 
197
197
  // First, wait some time before starting the peer discovery
@@ -229,6 +229,9 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
229
229
  }
230
230
 
231
231
  public async stop(): Promise<void> {
232
+ if (this.currentState !== PeerDiscoveryState.RUNNING) {
233
+ return;
234
+ }
232
235
  await this.discv5.off(Discv5Event.DISCOVERED, this.handlers.onDiscovered);
233
236
  await this.discv5.off(Discv5Event.ENR_ADDED, this.handlers.onEnrAdded);
234
237
  await this.discv5.off(Discv5Event.MULTIADDR_UPDATED, this.handlers.onMultiaddrUpdated);
@@ -1,3 +1,4 @@
1
+ import type { EthAddress } from '@aztec/foundation/eth-address';
1
2
  import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
2
3
  import type { Gossipable, PeerErrorSeverity } from '@aztec/stdlib/p2p';
3
4
  import { Tx, TxHash } from '@aztec/stdlib/tx';
@@ -8,10 +9,12 @@ import EventEmitter from 'events';
8
9
 
9
10
  import type { PeerManagerInterface } from './peer-manager/interface.js';
10
11
  import type { P2PReqRespConfig } from './reqresp/config.js';
12
+ import { type AuthRequest, StatusMessage } from './reqresp/index.js';
11
13
  import type {
12
14
  ReqRespInterface,
13
15
  ReqRespResponse,
14
16
  ReqRespSubProtocol,
17
+ ReqRespSubProtocolHandler,
15
18
  ReqRespSubProtocolHandlers,
16
19
  ReqRespSubProtocolValidators,
17
20
  SubProtocolMap,
@@ -108,6 +111,21 @@ export class DummyP2PService implements P2PService {
108
111
  validate(_txs: Tx[]): Promise<void> {
109
112
  return Promise.resolve();
110
113
  }
114
+
115
+ addReqRespSubProtocol(
116
+ _subProtocol: ReqRespSubProtocol,
117
+ _handler: ReqRespSubProtocolHandler,
118
+ _validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
119
+ ): Promise<void> {
120
+ return Promise.resolve();
121
+ }
122
+
123
+ handleAuthRequestFromPeer(_authRequest: AuthRequest, _peerId: PeerId): Promise<StatusMessage> {
124
+ return Promise.resolve(StatusMessage.random());
125
+ }
126
+
127
+ //this is no-op
128
+ registerThisValidatorAddresses(_address: EthAddress[]): void {}
111
129
  }
112
130
 
113
131
  /**
@@ -184,14 +202,28 @@ export class DummyPeerManager implements PeerManagerInterface {
184
202
  public getPeerScore(_peerId: string): number {
185
203
  return 0;
186
204
  }
205
+
206
+ public shouldDisableP2PGossip(_peerId: string): boolean {
207
+ return false;
208
+ }
209
+
187
210
  public stop(): Promise<void> {
188
211
  return Promise.resolve();
189
212
  }
190
- public heartbeat(): void {}
213
+ public heartbeat(): Promise<void> {
214
+ return Promise.resolve();
215
+ }
191
216
  public addTrustedPeer(_peerId: PeerId): void {}
192
217
  public addPrivatePeer(_peerId: PeerId): void {}
193
218
  public goodbyeReceived(_peerId: PeerId, _reason: GoodByeReason): void {}
194
219
  public penalizePeer(_peerId: PeerId, _penalty: PeerErrorSeverity): void {}
220
+ public addPreferredPeer(_peerId: PeerId): void {}
221
+ public handleAuthRequestFromPeer(_authRequest: AuthRequest, _peerId: PeerId): Promise<StatusMessage> {
222
+ return Promise.resolve(StatusMessage.random());
223
+ }
224
+
225
+ //this is no-op
226
+ registerThisValidatorAddresses(_address: EthAddress[]): void {}
195
227
  }
196
228
 
197
229
  export class DummyReqResp implements ReqRespInterface {
@@ -213,13 +245,13 @@ export class DummyReqResp implements ReqRespInterface {
213
245
  }
214
246
  sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
215
247
  _subProtocol: SubProtocol,
216
- requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
248
+ _requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
217
249
  _pinnedPeer: PeerId | undefined,
218
250
  _timeoutMs?: number,
219
251
  _maxPeers?: number,
220
252
  _maxRetryAttempts?: number,
221
- ): Promise<(InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined)[]> {
222
- return Promise.resolve(requests.map(() => undefined));
253
+ ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]> {
254
+ return Promise.resolve([]);
223
255
  }
224
256
  public sendRequestToPeer(
225
257
  _peerId: PeerId,
@@ -229,4 +261,12 @@ export class DummyReqResp implements ReqRespInterface {
229
261
  ): Promise<ReqRespResponse> {
230
262
  return Promise.resolve({ status: ReqRespStatus.SUCCESS, data: Buffer.from([]) });
231
263
  }
264
+
265
+ addSubProtocol(
266
+ _subProtocol: ReqRespSubProtocol,
267
+ _handler: ReqRespSubProtocolHandler,
268
+ _validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
269
+ ): Promise<void> {
270
+ return Promise.resolve();
271
+ }
232
272
  }
@@ -1,4 +1,6 @@
1
1
  export * from './service.js';
2
2
  export * from './libp2p/libp2p_service.js';
3
- export * from './tx_collector.js';
3
+ export * from './tx_provider.js';
4
4
  export * from './dummy_service.js';
5
+ export * from './reqresp/index.js';
6
+ export * from './tx_collection/index.js';
@@ -1,11 +1,12 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
+ import { randomInt } from '@aztec/foundation/crypto';
2
3
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
3
4
  import { SerialQueue } from '@aztec/foundation/queue';
4
5
  import { RunningPromise } from '@aztec/foundation/running-promise';
5
6
  import { Timer } from '@aztec/foundation/timer';
6
7
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
7
8
  import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
8
- import type { L2BlockSource } from '@aztec/stdlib/block';
9
+ import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
9
10
  import type { ContractDataSource } from '@aztec/stdlib/contract';
10
11
  import { GasFees } from '@aztec/stdlib/gas';
11
12
  import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
@@ -27,7 +28,7 @@ import type { UInt64 } from '@aztec/stdlib/types';
27
28
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
28
29
  import { Attributes, OtelMetricsAdapter, type TelemetryClient, WithTracer, trackSpan } from '@aztec/telemetry-client';
29
30
 
30
- import type { ENR } from '@chainsafe/enr';
31
+ import { ENR } from '@chainsafe/enr';
31
32
  import {
32
33
  type GossipSub,
33
34
  type GossipSubComponents,
@@ -40,7 +41,7 @@ import { noise } from '@chainsafe/libp2p-noise';
40
41
  import { yamux } from '@chainsafe/libp2p-yamux';
41
42
  import { bootstrap } from '@libp2p/bootstrap';
42
43
  import { identify } from '@libp2p/identify';
43
- import { type Message, type PeerId, TopicValidatorResult } from '@libp2p/interface';
44
+ import { type Message, type MultiaddrConnection, type PeerId, TopicValidatorResult } from '@libp2p/interface';
44
45
  import type { ConnectionManager } from '@libp2p/interface-internal';
45
46
  import '@libp2p/kad-dht';
46
47
  import { mplex } from '@libp2p/mplex';
@@ -69,10 +70,17 @@ import {
69
70
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
70
71
  type ReqRespInterface,
71
72
  ReqRespSubProtocol,
73
+ type ReqRespSubProtocolHandler,
74
+ type ReqRespSubProtocolHandlers,
75
+ type ReqRespSubProtocolValidators,
72
76
  type SubProtocolMap,
77
+ ValidationError,
73
78
  } from '../reqresp/interface.js';
79
+ import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
74
80
  import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
75
81
  import {
82
+ AuthRequest,
83
+ StatusMessage,
76
84
  pingHandler,
77
85
  reqRespBlockHandler,
78
86
  reqRespStatusHandler,
@@ -218,12 +226,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
218
226
  createLogger(`${logger.module}:discv5_service`),
219
227
  );
220
228
 
221
- const bootstrapNodes = peerDiscoveryService.bootstrapNodeEnrs.map(enr => enr.encodeTxt());
229
+ // Seed libp2p's bootstrap discovery with private and trusted peers
230
+ const bootstrapNodes = [...config.privatePeers, ...config.trustedPeers];
222
231
 
223
- // If trusted peers are provided, also provide them to the p2p service
224
- bootstrapNodes.push(...config.trustedPeers);
225
-
226
- // If bootstrap nodes are provided, also provide them to the p2p service
227
232
  const peerDiscovery = [];
228
233
  if (bootstrapNodes.length > 0) {
229
234
  peerDiscovery.push(bootstrap({ list: bootstrapNodes }));
@@ -236,23 +241,51 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
236
241
  const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
237
242
  const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
238
243
 
244
+ const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
245
+ const directPeers = (
246
+ await Promise.all(
247
+ preferredPeersEnrs.map(async enr => {
248
+ const peerId = await enr.peerId();
249
+ const address = enr.getLocationMultiaddr('tcp');
250
+ if (address === undefined) {
251
+ throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
252
+ }
253
+ return {
254
+ id: peerId,
255
+ addrs: [address],
256
+ };
257
+ }),
258
+ )
259
+ ).filter(peer => peer !== undefined);
260
+
261
+ const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
262
+
239
263
  const node = await createLibp2p({
240
264
  start: false,
241
265
  peerId,
242
266
  addresses: {
243
267
  listen: [bindAddrTcp],
244
- announce: [], // announce is handled by the peer discovery service
268
+ announce: announceTcpMultiaddr,
245
269
  },
246
270
  transports: [
247
271
  tcp({
248
- maxConnections: config.maxPeerCount,
272
+ // It's better to have this number a bit higher than our maxPeerCount because it's sets the limit on transport (TCP) layer
273
+ // The connection attempts to the node on TCP layer are not necessarily valid Aztec peers so we want to have a bit of leeway here
274
+ // If we hit the limit, the connection will be temporarily accepted and immediately dropped.
275
+ // Docs: https://nodejs.org/api/net.html#servermaxconnections
276
+ maxConnections: Math.ceil(maxPeerCount * 1.5),
249
277
  // socket option: the maximum length of the queue of pending connections
250
278
  // https://nodejs.org/dist/latest-v22.x/docs/api/net.html#serverlisten
251
279
  // it's not safe if we increase this number
252
280
  backlog: 5,
253
281
  closeServerOnMaxConnections: {
254
- closeAbove: maxPeerCount ?? Infinity,
255
- listenBelow: maxPeerCount ?? Infinity,
282
+ // The property `maxConnections` will protect us against the most DDOS attack
283
+ // This property protects us in case of burst of new connections where server is not able to close them quickly enough
284
+ // In case closeAbove is reached, the server stops listening altogether
285
+ // It's important that there is enough difference between closeAbove and listenAbove,
286
+ // otherwise the server.listener will flap between being closed and open potentially degrading perf even more
287
+ closeAbove: maxPeerCount * 2,
288
+ listenBelow: Math.floor(maxPeerCount * 0.9),
256
289
  },
257
290
  }),
258
291
  ],
@@ -262,16 +295,41 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
262
295
  connectionEncryption: [noise()],
263
296
  connectionManager: {
264
297
  minConnections: 0,
298
+ maxConnections: maxPeerCount,
265
299
  maxParallelDials: 100,
266
300
  dialTimeout: 30_000,
267
301
  maxPeerAddrsToDial: 5,
268
302
  maxIncomingPendingConnections: 5,
269
303
  },
304
+ connectionGater: {
305
+ denyInboundConnection: (maConn: MultiaddrConnection) => {
306
+ const allowed = peerManager.isNodeAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
307
+ if (allowed) {
308
+ return false;
309
+ }
310
+
311
+ logger.debug(`Connection gater: Denying inbound connection from ${maConn.remoteAddr.toString()}`);
312
+ return true;
313
+ },
314
+ denyInboundEncryptedConnection: (peerId: PeerId, _maConn: MultiaddrConnection) => {
315
+ //NOTE: it is not necessary to check address here because this was already done by
316
+ // denyInboundConnection
317
+ const allowed = peerManager.isNodeAllowedToConnect(peerId);
318
+ if (allowed) {
319
+ return false;
320
+ }
321
+
322
+ logger.debug(`Connection gater: Denying inbound encrypted connection from ${peerId.toString()}`);
323
+ return true;
324
+ },
325
+ },
270
326
  services: {
271
327
  identify: identify({
272
328
  protocolPrefix: 'aztec',
329
+ runOnConnectionOpen: true,
273
330
  }),
274
331
  pubsub: gossipsub({
332
+ directPeers,
275
333
  debugName: 'gossipsub',
276
334
  globalSignaturePolicy: SignaturePolicy.StrictNoSign,
277
335
  allowPublishToZeroTopicPeers: true,
@@ -334,11 +392,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
334
392
  reqresp,
335
393
  worldStateSynchronizer,
336
394
  protocolVersion,
395
+ epochCache,
337
396
  );
338
397
 
339
398
  // Update gossipsub score params
340
399
  node.services.pubsub.score.params.appSpecificWeight = 10;
341
- node.services.pubsub.score.params.appSpecificScore = (peerId: string) => peerManager.getPeerScore(peerId);
400
+ node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
401
+ peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
342
402
 
343
403
  return new LibP2PService(
344
404
  clientType,
@@ -378,7 +438,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
378
438
  this.jobQueue.start();
379
439
 
380
440
  await this.peerManager.initializePeers();
381
- await this.peerDiscoveryService.start();
441
+ if (!this.config.p2pDiscoveryDisabled) {
442
+ await this.peerDiscoveryService.start();
443
+ }
382
444
  await this.node.start();
383
445
 
384
446
  // Subscribe to standard GossipSub topics by default
@@ -391,8 +453,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
391
453
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
392
454
  const blockHandler = reqRespBlockHandler(this.archiver);
393
455
  const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
456
+ // In case P2P client doesnt'have attestation pool,
457
+ // const blockTxsHandler = this.mempools.attestationPool
458
+ // ? reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool)
459
+ // : def;
394
460
 
395
- const requestResponseHandlers = {
461
+ const requestResponseHandlers: Partial<ReqRespSubProtocolHandlers> = {
396
462
  [ReqRespSubProtocol.PING]: pingHandler,
397
463
  [ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
398
464
  [ReqRespSubProtocol.TX]: txHandler.bind(this),
@@ -400,6 +466,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
400
466
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
401
467
  };
402
468
 
469
+ // Only handle block transactions request if attestation pool is available to the client
470
+ if (this.mempools.attestationPool) {
471
+ const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
472
+ requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
473
+ }
474
+
403
475
  // add GossipSub listener
404
476
  this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
405
477
 
@@ -451,6 +523,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
451
523
  this.logger.info('LibP2P service stopped');
452
524
  }
453
525
 
526
+ addReqRespSubProtocol(
527
+ subProtocol: ReqRespSubProtocol,
528
+ handler: ReqRespSubProtocolHandler,
529
+ validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
530
+ ): Promise<void> {
531
+ return this.reqresp.addSubProtocol(subProtocol, handler, validator);
532
+ }
533
+
534
+ public registerThisValidatorAddresses(address: EthAddress[]): void {
535
+ this.peerManager.registerThisValidatorAddresses(address);
536
+ }
537
+
454
538
  public getPeers(includePending?: boolean): PeerInfo[] {
455
539
  return this.peerManager.getPeers(includePending);
456
540
  }
@@ -468,23 +552,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
468
552
  setImmediate(() => void safeJob());
469
553
  }
470
554
 
471
- /**
472
- * Send Request via the ReqResp service
473
- * The subprotocol defined will determine the request and response types
474
- *
475
- * See the subProtocolMap for the mapping of subprotocols to request/response types in `interface.ts`
476
- *
477
- * @param protocol The request response protocol to use
478
- * @param request The request type to send
479
- * @returns
480
- */
481
- sendRequest<SubProtocol extends ReqRespSubProtocol>(
482
- protocol: SubProtocol,
483
- request: InstanceType<SubProtocolMap[SubProtocol]['request']>,
484
- ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined> {
485
- return this.reqresp.sendRequest(protocol, request);
486
- }
487
-
488
555
  /**
489
556
  * Send a batch of requests to peers, and return the responses
490
557
  * @param protocol - The request response protocol to use
@@ -495,7 +562,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
495
562
  protocol: SubProtocol,
496
563
  requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
497
564
  pinnedPeerId: PeerId | undefined,
498
- ): Promise<(InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined)[]> {
565
+ ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]> {
499
566
  return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
500
567
  }
501
568
 
@@ -653,12 +720,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
653
720
  if (!result || !tx) {
654
721
  return;
655
722
  }
656
- const txHash = await tx.getTxHash();
723
+ const txHash = tx.getTxHash();
657
724
  const txHashString = txHash.toString();
658
725
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
659
726
  source: source.toString(),
660
727
  txHash: txHashString,
661
728
  });
729
+
730
+ if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
731
+ this.logger.debug(`Intentionally dropping tx ${txHashString} (probability rule)`);
732
+ return;
733
+ }
734
+
662
735
  await this.mempools.txPool.addTxs([tx]);
663
736
  }
664
737
 
@@ -752,7 +825,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
752
825
  }
753
826
 
754
827
  // Mark the txs in this proposal as non-evictable
755
- await this.mempools.txPool.markTxsAsNonEvictable(block.payload.txHashes);
828
+ await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
829
+ await this.mempools.attestationPool?.addBlockProposal(block);
756
830
  const attestations = await this.blockReceivedCallback(block, sender);
757
831
 
758
832
  // TODO: fix up this pattern - the abstraction is not nice
@@ -804,44 +878,58 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
804
878
  }
805
879
 
806
880
  /**
807
- * Validate a tx that has been requested from a peer.
881
+ * Validate a collection of txs that has been requested from a peer.
808
882
  *
809
- * The core component of this validator is that the tx hash MUST match the requested tx hash,
883
+ * The core component of this validator is that each tx hash MUST match the requested tx hash,
810
884
  * In order to perform this check, the tx proof must be verified.
811
885
  *
812
886
  * Note: This function is called from within `ReqResp.sendRequest` as part of the
813
887
  * ReqRespSubProtocol.TX subprotocol validation.
814
888
  *
815
- * @param requestedTxHash - The hash of the tx that was requested.
816
- * @param responseTx - The tx that was received as a response to the request.
889
+ * @param requestedTxHash - The collection of the txs that was requested.
890
+ * @param responseTx - The collectin of txs that was received as a response to the request.
817
891
  * @param peerId - The peer ID of the peer that sent the tx.
818
- * @returns True if the tx is valid, false otherwise.
892
+ * @returns True if the whole collection of txs is valid, false otherwise.
819
893
  */
894
+ //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
895
+ // I think we should still extract the valid txs and return them, so that we can still use the response.
820
896
  @trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx) => ({
821
897
  [Attributes.TX_HASH]: requestedTxHash.toString(),
822
898
  }))
823
- private async validateRequestedTx(requestedTxHash: TxHash, responseTx: Tx, peerId: PeerId): Promise<boolean> {
899
+ private async validateRequestedTx(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
900
+ const requested = new Set(requestedTxHash.map(h => h.toString()));
901
+
824
902
  const proofValidator = new TxProofValidator(this.proofVerifier);
825
- const validProof = await proofValidator.validateTx(responseTx);
826
903
 
827
- // If the node returns the wrong data, we penalize it
828
- if (!requestedTxHash.equals(await responseTx.getTxHash())) {
829
- // Returning the wrong data is a low tolerance error
830
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
831
- return false;
832
- }
904
+ try {
905
+ await Promise.all(
906
+ responseTx.map(async tx => {
907
+ if (!requested.has(tx.getTxHash().toString())) {
908
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
909
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
910
+ }
911
+
912
+ const { result } = await proofValidator.validateTx(tx);
913
+ if (result === 'invalid') {
914
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
915
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
916
+ }
917
+ }),
918
+ );
919
+ return true;
920
+ } catch (e: any) {
921
+ if (e instanceof ValidationError) {
922
+ this.logger.debug(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
923
+ } else {
924
+ this.logger.warn(`Error during validation of requested txs`, e);
925
+ }
833
926
 
834
- if (validProof.result === 'invalid') {
835
- // If the proof is invalid, but the txHash is correct, then this is an active attack and we severly punish
836
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
837
927
  return false;
838
928
  }
839
-
840
- return true;
841
929
  }
842
930
 
843
- @trackSpan('Libp2pService.validatePropagatedTx', async tx => ({
844
- [Attributes.TX_HASH]: (await tx.getTxHash()).toString(),
931
+ @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
932
+ [Attributes.TX_HASH]: tx.getTxHash().toString(),
845
933
  }))
846
934
  private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
847
935
  const currentBlockNumber = await this.archiver.getBlockNumber();
@@ -1048,6 +1136,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1048
1136
  return this.node.services.pubsub.score.score(peerId.toString());
1049
1137
  }
1050
1138
 
1139
+ public handleAuthRequestFromPeer(authRequest: AuthRequest, peerId: PeerId): Promise<StatusMessage> {
1140
+ return this.peerManager.handleAuthRequestFromPeer(authRequest, peerId);
1141
+ }
1142
+
1051
1143
  private async sendToPeers<T extends Gossipable>(message: T) {
1052
1144
  const parent = message.constructor as typeof Gossipable;
1053
1145
 
@@ -1,20 +1,29 @@
1
+ import type { EthAddress } from '@aztec/foundation/eth-address';
1
2
  import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
2
3
  import type { PeerErrorSeverity } from '@aztec/stdlib/p2p';
3
4
 
4
5
  import type { PeerId } from '@libp2p/interface';
5
6
 
7
+ import type { AuthRequest, StatusMessage } from '../reqresp/index.js';
6
8
  import type { GoodByeReason } from '../reqresp/protocols/goodbye.js';
7
9
 
8
10
  export interface PeerManagerInterface {
9
11
  getPeers(_includePending?: boolean): PeerInfo[];
10
12
 
11
13
  initializePeers(): Promise<void>;
12
- heartbeat(): void;
14
+ heartbeat(): Promise<void>;
13
15
  addTrustedPeer(peerId: PeerId): void;
14
16
  addPrivatePeer(peerId: PeerId): void;
17
+ addPreferredPeer(peerId: PeerId): void;
15
18
  goodbyeReceived(peerId: PeerId, reason: GoodByeReason): void;
16
19
  penalizePeer(peerId: PeerId, penalty: PeerErrorSeverity): void;
20
+ handleAuthRequestFromPeer(authRequest: AuthRequest, peerId: PeerId): Promise<StatusMessage>;
17
21
 
18
22
  getPeerScore(peerId: string): number;
23
+ shouldDisableP2PGossip(peerId: string): boolean;
24
+
19
25
  stop(): Promise<void>;
26
+
27
+ /** If node running this P2P stack is validator, passes in validator address to P2P layer */
28
+ registerThisValidatorAddresses(address: EthAddress[]): void;
20
29
  }