@aztec/p2p 0.71.0 → 0.73.0

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 (153) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +2 -2
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +1 -1
  4. package/dest/client/factory.js +4 -4
  5. package/dest/client/p2p_client.d.ts +13 -16
  6. package/dest/client/p2p_client.d.ts.map +1 -1
  7. package/dest/client/p2p_client.js +55 -67
  8. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  9. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +11 -19
  10. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +6 -13
  11. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  12. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +74 -80
  13. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  14. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +5 -5
  15. package/dest/mem_pools/attestation_pool/mocks.d.ts +3 -2
  16. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  17. package/dest/mem_pools/attestation_pool/mocks.js +3 -3
  18. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +9 -9
  19. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  20. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +60 -54
  21. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +7 -7
  22. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  23. package/dest/mem_pools/tx_pool/memory_tx_pool.js +17 -18
  24. package/dest/mem_pools/tx_pool/tx_pool.d.ts +7 -7
  25. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  26. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  27. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +48 -47
  28. package/dest/mocks/index.d.ts +3 -3
  29. package/dest/mocks/index.d.ts.map +1 -1
  30. package/dest/mocks/index.js +19 -18
  31. package/dest/msg_validators/attestation_validator/attestation_validator.js +2 -2
  32. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +2 -2
  33. package/dest/msg_validators/tx_validator/block_header_validator.js +3 -3
  34. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  35. package/dest/msg_validators/tx_validator/data_validator.js +7 -7
  36. package/dest/msg_validators/tx_validator/double_spend_validator.js +3 -3
  37. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  38. package/dest/msg_validators/tx_validator/metadata_validator.js +9 -9
  39. package/dest/services/data_store.d.ts +4 -4
  40. package/dest/services/data_store.d.ts.map +1 -1
  41. package/dest/services/data_store.js +7 -7
  42. package/dest/services/dummy_service.d.ts +7 -0
  43. package/dest/services/dummy_service.d.ts.map +1 -1
  44. package/dest/services/dummy_service.js +10 -1
  45. package/dest/services/libp2p/libp2p_service.d.ts +19 -15
  46. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  47. package/dest/services/libp2p/libp2p_service.js +163 -134
  48. package/dest/services/peer-manager/metrics.d.ts +12 -0
  49. package/dest/services/peer-manager/metrics.d.ts.map +1 -0
  50. package/dest/services/peer-manager/metrics.js +26 -0
  51. package/dest/services/{peer_manager.d.ts → peer-manager/peer_manager.d.ts} +24 -8
  52. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -0
  53. package/dest/services/peer-manager/peer_manager.js +395 -0
  54. package/dest/services/{peer-scoring → peer-manager}/peer_scoring.d.ts +3 -0
  55. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -0
  56. package/dest/services/peer-manager/peer_scoring.js +84 -0
  57. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +45 -0
  58. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -0
  59. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +81 -0
  60. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +61 -0
  61. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -0
  62. package/dest/services/reqresp/connection-sampler/connection_sampler.js +175 -0
  63. package/dest/services/reqresp/interface.d.ts +17 -4
  64. package/dest/services/reqresp/interface.d.ts.map +1 -1
  65. package/dest/services/reqresp/interface.js +34 -11
  66. package/dest/services/reqresp/metrics.d.ts +15 -0
  67. package/dest/services/reqresp/metrics.d.ts.map +1 -0
  68. package/dest/services/reqresp/metrics.js +42 -0
  69. package/dest/services/reqresp/protocols/block.d.ts +4 -0
  70. package/dest/services/reqresp/protocols/block.d.ts.map +1 -0
  71. package/dest/services/reqresp/protocols/block.js +9 -0
  72. package/dest/services/reqresp/protocols/goodbye.d.ts +51 -0
  73. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -0
  74. package/dest/services/reqresp/protocols/goodbye.js +92 -0
  75. package/dest/services/reqresp/protocols/index.d.ts +9 -0
  76. package/dest/services/reqresp/protocols/index.d.ts.map +1 -0
  77. package/dest/services/reqresp/protocols/index.js +9 -0
  78. package/dest/services/reqresp/protocols/ping.d.ts +9 -0
  79. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -0
  80. package/dest/services/reqresp/protocols/ping.js +9 -0
  81. package/dest/services/reqresp/{handlers.d.ts → protocols/status.d.ts} +1 -7
  82. package/dest/services/reqresp/protocols/status.d.ts.map +1 -0
  83. package/dest/services/reqresp/protocols/status.js +9 -0
  84. package/dest/services/reqresp/protocols/tx.d.ts +13 -0
  85. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -0
  86. package/dest/services/reqresp/protocols/tx.js +23 -0
  87. package/dest/services/reqresp/rate-limiter/index.d.ts.map +1 -0
  88. package/dest/services/reqresp/{rate_limiter → rate-limiter}/index.js +1 -1
  89. package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.d.ts +3 -3
  90. package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.d.ts.map +1 -1
  91. package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.js +4 -4
  92. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -0
  93. package/dest/services/reqresp/rate-limiter/rate_limits.js +55 -0
  94. package/dest/services/reqresp/reqresp.d.ts +33 -6
  95. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  96. package/dest/services/reqresp/reqresp.js +414 -249
  97. package/dest/services/service.d.ts +8 -0
  98. package/dest/services/service.d.ts.map +1 -1
  99. package/dest/util.d.ts +6 -2
  100. package/dest/util.d.ts.map +1 -1
  101. package/dest/util.js +2 -2
  102. package/package.json +8 -8
  103. package/src/bootstrap/bootstrap.ts +2 -2
  104. package/src/client/factory.ts +3 -3
  105. package/src/client/p2p_client.ts +68 -80
  106. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +14 -22
  107. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +100 -94
  108. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +4 -4
  109. package/src/mem_pools/attestation_pool/mocks.ts +5 -5
  110. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +84 -73
  111. package/src/mem_pools/tx_pool/memory_tx_pool.ts +26 -23
  112. package/src/mem_pools/tx_pool/tx_pool.ts +7 -7
  113. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +50 -47
  114. package/src/mocks/index.ts +19 -20
  115. package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
  116. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +1 -1
  117. package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
  118. package/src/msg_validators/tx_validator/data_validator.ts +12 -9
  119. package/src/msg_validators/tx_validator/double_spend_validator.ts +2 -2
  120. package/src/msg_validators/tx_validator/metadata_validator.ts +8 -8
  121. package/src/services/data_store.ts +9 -9
  122. package/src/services/dummy_service.ts +13 -0
  123. package/src/services/libp2p/libp2p_service.ts +212 -163
  124. package/src/services/peer-manager/metrics.ts +41 -0
  125. package/src/services/{peer_manager.ts → peer-manager/peer_manager.ts} +73 -23
  126. package/src/services/{peer-scoring → peer-manager}/peer_scoring.ts +16 -3
  127. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +94 -0
  128. package/src/services/reqresp/connection-sampler/connection_sampler.ts +211 -0
  129. package/src/services/reqresp/interface.ts +39 -16
  130. package/src/services/reqresp/metrics.ts +57 -0
  131. package/src/services/reqresp/protocols/block.ts +15 -0
  132. package/src/services/reqresp/protocols/goodbye.ts +101 -0
  133. package/src/services/reqresp/protocols/index.ts +8 -0
  134. package/src/services/reqresp/protocols/ping.ts +8 -0
  135. package/src/services/reqresp/{handlers.ts → protocols/status.ts} +0 -9
  136. package/src/services/reqresp/protocols/tx.ts +29 -0
  137. package/src/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.ts +3 -3
  138. package/src/services/reqresp/{rate_limiter → rate-limiter}/rate_limits.ts +24 -4
  139. package/src/services/reqresp/reqresp.ts +231 -26
  140. package/src/services/service.ts +12 -0
  141. package/src/util.ts +11 -4
  142. package/dest/services/peer-scoring/peer_scoring.d.ts.map +0 -1
  143. package/dest/services/peer-scoring/peer_scoring.js +0 -75
  144. package/dest/services/peer_manager.d.ts.map +0 -1
  145. package/dest/services/peer_manager.js +0 -358
  146. package/dest/services/reqresp/handlers.d.ts.map +0 -1
  147. package/dest/services/reqresp/handlers.js +0 -17
  148. package/dest/services/reqresp/rate_limiter/index.d.ts.map +0 -1
  149. package/dest/services/reqresp/rate_limiter/rate_limits.d.ts.map +0 -1
  150. package/dest/services/reqresp/rate_limiter/rate_limits.js +0 -35
  151. /package/dest/services/reqresp/{rate_limiter → rate-limiter}/index.d.ts +0 -0
  152. /package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limits.d.ts +0 -0
  153. /package/src/services/reqresp/{rate_limiter → rate-limiter}/index.ts +0 -0
@@ -2,6 +2,7 @@
2
2
  import { PeerErrorSeverity } from '@aztec/circuit-types';
3
3
  import { type Logger, createLogger } from '@aztec/foundation/log';
4
4
  import { executeTimeout } from '@aztec/foundation/timer';
5
+ import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
5
6
 
6
7
  import { type IncomingStreamData, type PeerId, type Stream } from '@libp2p/interface';
7
8
  import { pipe } from 'it-pipe';
@@ -14,8 +15,10 @@ import {
14
15
  InvalidResponseError,
15
16
  } from '../../errors/reqresp.error.js';
16
17
  import { SnappyTransform } from '../encoding.js';
17
- import { type PeerManager } from '../peer_manager.js';
18
+ import { type PeerScoring } from '../peer-manager/peer_scoring.js';
18
19
  import { type P2PReqRespConfig } from './config.js';
20
+ import { BatchConnectionSampler } from './connection-sampler/batch_connection_sampler.js';
21
+ import { ConnectionSampler } from './connection-sampler/connection_sampler.js';
19
22
  import {
20
23
  DEFAULT_SUB_PROTOCOL_HANDLERS,
21
24
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
@@ -25,7 +28,8 @@ import {
25
28
  type SubProtocolMap,
26
29
  subProtocolMap,
27
30
  } from './interface.js';
28
- import { RequestResponseRateLimiter } from './rate_limiter/rate_limiter.js';
31
+ import { ReqRespMetrics } from './metrics.js';
32
+ import { RequestResponseRateLimiter } from './rate-limiter/rate_limiter.js';
29
33
 
30
34
  /**
31
35
  * The Request Response Service
@@ -51,18 +55,35 @@ export class ReqResp {
51
55
  private subProtocolHandlers: ReqRespSubProtocolHandlers = DEFAULT_SUB_PROTOCOL_HANDLERS;
52
56
  private subProtocolValidators: ReqRespSubProtocolValidators = DEFAULT_SUB_PROTOCOL_VALIDATORS;
53
57
 
58
+ private connectionSampler: ConnectionSampler;
54
59
  private rateLimiter: RequestResponseRateLimiter;
55
60
 
56
61
  private snappyTransform: SnappyTransform;
57
62
 
58
- constructor(config: P2PReqRespConfig, protected readonly libp2p: Libp2p, private peerManager: PeerManager) {
63
+ private metrics: ReqRespMetrics;
64
+
65
+ constructor(
66
+ config: P2PReqRespConfig,
67
+ private libp2p: Libp2p,
68
+ private peerScoring: PeerScoring,
69
+ telemetryClient: TelemetryClient = getTelemetryClient(),
70
+ ) {
59
71
  this.logger = createLogger('p2p:reqresp');
60
72
 
61
73
  this.overallRequestTimeoutMs = config.overallRequestTimeoutMs;
62
74
  this.individualRequestTimeoutMs = config.individualRequestTimeoutMs;
63
75
 
64
- this.rateLimiter = new RequestResponseRateLimiter(peerManager);
76
+ this.rateLimiter = new RequestResponseRateLimiter(peerScoring);
77
+
78
+ // Connection sampler is used to sample our connected peers
79
+ this.connectionSampler = new ConnectionSampler(libp2p);
80
+
65
81
  this.snappyTransform = new SnappyTransform();
82
+ this.metrics = new ReqRespMetrics(telemetryClient);
83
+ }
84
+
85
+ get tracer() {
86
+ return this.metrics.tracer;
66
87
  }
67
88
 
68
89
  /**
@@ -74,7 +95,13 @@ export class ReqResp {
74
95
 
75
96
  // Register all protocol handlers
76
97
  for (const subProtocol of Object.keys(this.subProtocolHandlers)) {
77
- await this.libp2p.handle(subProtocol, this.streamHandler.bind(this, subProtocol as ReqRespSubProtocol));
98
+ await this.libp2p.handle(
99
+ subProtocol,
100
+ (data: IncomingStreamData) =>
101
+ void this.streamHandler(subProtocol as ReqRespSubProtocol, data).catch(err =>
102
+ this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err),
103
+ ),
104
+ );
78
105
  }
79
106
  this.rateLimiter.start();
80
107
  }
@@ -83,12 +110,15 @@ export class ReqResp {
83
110
  * Stop the reqresp service
84
111
  */
85
112
  async stop() {
86
- // Unregister all handlers
87
- for (const protocol of Object.keys(this.subProtocolHandlers)) {
88
- await this.libp2p.unhandle(protocol);
89
- }
113
+ // Unregister handlers in parallel
114
+ const unregisterPromises = Object.keys(this.subProtocolHandlers).map(protocol => this.libp2p.unhandle(protocol));
115
+ await Promise.all(unregisterPromises);
90
116
 
91
- // Close all active connections
117
+ // Close connection sampler
118
+ await this.connectionSampler.stop();
119
+ this.logger.debug('ReqResp: Connection sampler stopped');
120
+
121
+ // Close streams in parallel
92
122
  const closeStreamPromises = this.libp2p.getConnections().map(connection => connection.close());
93
123
  await Promise.all(closeStreamPromises);
94
124
  this.logger.debug('ReqResp: All active streams closed');
@@ -113,8 +143,8 @@ export class ReqResp {
113
143
  * If no response is received from any peer, it returns undefined.
114
144
  *
115
145
  * The method performs the following steps:
116
- * - Iterates over all active peers.
117
- * - Opens a stream with each peer using the specified sub-protocol.
146
+ * - Sample a peer to send the request to.
147
+ * - Opens a stream with the peer using the specified sub-protocol.
118
148
  *
119
149
  * When a response is received, it is validated using the given sub protocols response validator.
120
150
  * To see the interface for the response validator - see `interface.ts`
@@ -132,15 +162,32 @@ export class ReqResp {
132
162
  subProtocol: SubProtocol,
133
163
  request: InstanceType<SubProtocolMap[SubProtocol]['request']>,
134
164
  ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined> {
165
+ const responseValidator = this.subProtocolValidators[subProtocol];
166
+ const requestBuffer = request.toBuffer();
167
+
135
168
  const requestFunction = async () => {
136
- const responseValidator = this.subProtocolValidators[subProtocol];
137
- const requestBuffer = request.toBuffer();
169
+ // Attempt to ask all of our peers, but sampled in a random order
170
+ // This function is wrapped in a timeout, so we will exit the loop if we have not received a response
171
+ const numberOfPeers = this.libp2p.getPeers().length;
172
+
173
+ if (numberOfPeers === 0) {
174
+ this.logger.debug('No active peers to send requests to');
175
+ return undefined;
176
+ }
177
+
178
+ const attemptedPeers: Map<string, boolean> = new Map();
179
+ for (let i = 0; i < numberOfPeers; i++) {
180
+ // Sample a peer to make a request to
181
+ const peer = this.connectionSampler.getPeer(attemptedPeers);
182
+ this.logger.trace(`Attempting to send request to peer: ${peer?.toString()}`);
183
+ if (!peer) {
184
+ this.logger.debug('No peers available to send requests to');
185
+ return undefined;
186
+ }
138
187
 
139
- // Get active peers
140
- const peers = this.libp2p.getPeers();
188
+ attemptedPeers.set(peer.toString(), true);
141
189
 
142
- // Attempt to ask all of our peers
143
- for (const peer of peers) {
190
+ this.logger.trace(`Sending request to peer: ${peer.toString()}`);
144
191
  const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffer);
145
192
 
146
193
  // If we get a response, return it, otherwise we iterate onto the next peer
@@ -155,7 +202,6 @@ export class ReqResp {
155
202
  return object;
156
203
  }
157
204
  }
158
- return undefined;
159
205
  };
160
206
 
161
207
  try {
@@ -170,6 +216,152 @@ export class ReqResp {
170
216
  }
171
217
  }
172
218
 
219
+ /**
220
+ * Request multiple messages over the same sub protocol, balancing the requests across peers.
221
+ *
222
+ * @devnote
223
+ * - The function prioritizes sending requests to free peers using a batch sampling strategy.
224
+ * - If a peer fails to respond or returns an invalid response, it is removed from the sampling pool and replaced.
225
+ * - The function stops retrying once all requests are processed, no active peers remain, or the maximum retry attempts are reached.
226
+ * - Responses are validated using a custom validator for the sub-protocol.*
227
+ *
228
+ * Requests are sent in parallel to each peer, but multiple requests are sent to the same peer in series
229
+ * - If a peer fails to respond or returns an invalid response, it is removed from the sampling pool and replaced.
230
+ * - The function stops retrying once all requests are processed, no active peers remain, or the maximum retry attempts are reached.
231
+ * - Responses are validated using a custom validator for the sub-protocol.*
232
+ *
233
+ * @param subProtocol
234
+ * @param requests
235
+ * @param timeoutMs
236
+ * @param maxPeers
237
+ * @returns
238
+ *
239
+ * @throws {CollectiveReqRespTimeoutError} - If the request batch exceeds the specified timeout (`timeoutMs`).
240
+ */
241
+ @trackSpan(
242
+ 'ReqResp.sendBatchRequest',
243
+ (subProtocol: ReqRespSubProtocol, requests: InstanceType<SubProtocolMap[ReqRespSubProtocol]['request']>[]) => ({
244
+ [Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol,
245
+ [Attributes.P2P_REQ_RESP_BATCH_REQUESTS_COUNT]: requests.length,
246
+ }),
247
+ )
248
+ async sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
249
+ subProtocol: SubProtocol,
250
+ requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
251
+ timeoutMs = 10000,
252
+ maxPeers = Math.min(10, requests.length),
253
+ maxRetryAttempts = 3,
254
+ ): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]> {
255
+ const responseValidator = this.subProtocolValidators[subProtocol];
256
+ const responses: InstanceType<SubProtocolMap[SubProtocol]['response']>[] = new Array(requests.length);
257
+ const requestBuffers = requests.map(req => req.toBuffer());
258
+
259
+ const requestFunction = async () => {
260
+ // Track which requests still need to be processed
261
+ const pendingRequestIndices = new Set(requestBuffers.map((_, i) => i));
262
+
263
+ // Create batch sampler with the total number of requests and max peers
264
+ const batchSampler = new BatchConnectionSampler(this.connectionSampler, requests.length, maxPeers);
265
+
266
+ if (batchSampler.activePeerCount === 0) {
267
+ this.logger.debug('No active peers to send requests to');
268
+ return [];
269
+ }
270
+
271
+ // This is where it gets fun
272
+ // The outer loop is the retry loop, we will continue to retry until we process all indices we have
273
+ // not received a response for, or we have reached the max retry attempts
274
+
275
+ // The inner loop is the batch loop, we will process all requests for each peer in parallel
276
+ // We will then process the results of the requests, and resample any peers that failed to respond
277
+ // We will continue to retry until we have processed all indices, or we have reached the max retry attempts
278
+
279
+ let retryAttempts = 0;
280
+ while (pendingRequestIndices.size > 0 && batchSampler.activePeerCount > 0 && retryAttempts < maxRetryAttempts) {
281
+ // Process requests in parallel for each available peer
282
+ const requestBatches = new Map<PeerId, number[]>();
283
+
284
+ // Group requests by peer
285
+ for (const requestIndex of pendingRequestIndices) {
286
+ const peer = batchSampler.getPeerForRequest(requestIndex);
287
+ if (!peer) {
288
+ break;
289
+ }
290
+
291
+ if (!requestBatches.has(peer)) {
292
+ requestBatches.set(peer, []);
293
+ }
294
+ requestBatches.get(peer)!.push(requestIndex);
295
+ }
296
+
297
+ // Make parallel requests for each peer's batch
298
+ // A batch entry will look something like this:
299
+ // PeerId0: [0, 1, 2, 3]
300
+ // PeerId1: [4, 5, 6, 7]
301
+
302
+ // Peer Id 0 will send requests 0, 1, 2, 3 in serial
303
+ // while simultaneously Peer Id 1 will send requests 4, 5, 6, 7 in serial
304
+
305
+ const batchResults = await Promise.all(
306
+ Array.from(requestBatches.entries()).map(async ([peer, indices]) => {
307
+ try {
308
+ // Requests all going to the same peer are sent synchronously
309
+ const peerResults: { index: number; response: InstanceType<SubProtocolMap[SubProtocol]['response']> }[] =
310
+ [];
311
+ for (const index of indices) {
312
+ const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffers[index]);
313
+
314
+ if (response && response.length > 0) {
315
+ const object = subProtocolMap[subProtocol].response.fromBuffer(response);
316
+ const isValid = await responseValidator(requests[index], object, peer);
317
+
318
+ if (isValid) {
319
+ peerResults.push({ index, response: object });
320
+ }
321
+ }
322
+ }
323
+
324
+ return { peer, results: peerResults };
325
+ } catch (error) {
326
+ this.logger.debug(`Failed batch request to peer ${peer.toString()}:`, error);
327
+ batchSampler.removePeerAndReplace(peer);
328
+ return { peer, results: [] };
329
+ }
330
+ }),
331
+ );
332
+
333
+ // Process results
334
+ for (const { results } of batchResults) {
335
+ for (const { index, response } of results) {
336
+ if (response) {
337
+ responses[index] = response;
338
+ pendingRequestIndices.delete(index);
339
+ }
340
+ }
341
+ }
342
+
343
+ retryAttempts++;
344
+ }
345
+
346
+ if (retryAttempts >= maxRetryAttempts) {
347
+ this.logger.debug(`Max retry attempts ${maxRetryAttempts} reached for batch request`);
348
+ }
349
+
350
+ return responses;
351
+ };
352
+
353
+ try {
354
+ return await executeTimeout<InstanceType<SubProtocolMap[SubProtocol]['response']>[]>(
355
+ requestFunction,
356
+ timeoutMs,
357
+ () => new CollectiveReqRespTimeoutError(),
358
+ );
359
+ } catch (e: any) {
360
+ this.logger.debug(`${e.message} | subProtocol: ${subProtocol}`);
361
+ return [];
362
+ }
363
+ }
364
+
173
365
  /**
174
366
  * Sends a request to a specific peer
175
367
  *
@@ -194,15 +386,20 @@ export class ReqResp {
194
386
  * If the stream is not closed by the dialled peer, and a timeout occurs, then
195
387
  * the stream is closed on the requester's end and sender (us) updates its peer score
196
388
  */
197
- async sendRequestToPeer(
389
+ @trackSpan('ReqResp.sendRequestToPeer', (peerId: PeerId, subProtocol: ReqRespSubProtocol, _: Buffer) => ({
390
+ [Attributes.P2P_ID]: peerId.toString(),
391
+ [Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol,
392
+ }))
393
+ public async sendRequestToPeer(
198
394
  peerId: PeerId,
199
395
  subProtocol: ReqRespSubProtocol,
200
396
  payload: Buffer,
201
397
  ): Promise<Buffer | undefined> {
202
398
  let stream: Stream | undefined;
203
399
  try {
204
- stream = await this.libp2p.dialProtocol(peerId, subProtocol);
205
- this.logger.trace(`Stream opened with ${peerId.toString()} for ${subProtocol}`);
400
+ this.metrics.recordRequestSent(subProtocol);
401
+
402
+ stream = await this.connectionSampler.dialProtocol(peerId, subProtocol);
206
403
 
207
404
  // Open the stream with a timeout
208
405
  const result = await executeTimeout<Buffer>(
@@ -213,12 +410,13 @@ export class ReqResp {
213
410
 
214
411
  return result;
215
412
  } catch (e: any) {
413
+ this.metrics.recordRequestError(subProtocol);
216
414
  this.handleResponseError(e, peerId, subProtocol);
217
415
  } finally {
416
+ // Only close the stream if we created it
218
417
  if (stream) {
219
418
  try {
220
- await stream.close();
221
- this.logger.trace(`Stream closed with ${peerId.toString()} for ${subProtocol}`);
419
+ await this.connectionSampler.close(stream.id);
222
420
  } catch (closeError) {
223
421
  this.logger.error(
224
422
  `Error closing stream: ${closeError instanceof Error ? closeError.message : 'Unknown error'}`,
@@ -241,7 +439,7 @@ export class ReqResp {
241
439
  private handleResponseError(e: any, peerId: PeerId, subProtocol: ReqRespSubProtocol): void {
242
440
  const severity = this.categorizeError(e, peerId, subProtocol);
243
441
  if (severity) {
244
- this.peerManager.penalizePeer(peerId, severity);
442
+ this.peerScoring.penalizePeer(peerId, severity);
245
443
  }
246
444
  }
247
445
 
@@ -320,7 +518,13 @@ export class ReqResp {
320
518
  * We check rate limits for each peer, note the peer will be penalised within the rate limiter implementation
321
519
  * if they exceed their peer specific limits.
322
520
  */
521
+ @trackSpan('ReqResp.streamHandler', (protocol: ReqRespSubProtocol, { connection }: IncomingStreamData) => ({
522
+ [Attributes.P2P_REQ_RESP_PROTOCOL]: protocol,
523
+ [Attributes.P2P_ID]: connection.remotePeer.toString(),
524
+ }))
323
525
  private async streamHandler(protocol: ReqRespSubProtocol, { stream, connection }: IncomingStreamData) {
526
+ this.metrics.recordRequestReceived(protocol);
527
+
324
528
  // Store a reference to from this for the async generator
325
529
  if (!this.rateLimiter.allow(protocol, connection.remotePeer)) {
326
530
  this.logger.warn(`Rate limit exceeded for ${protocol} from ${connection.remotePeer}`);
@@ -339,7 +543,7 @@ export class ReqResp {
339
543
  async function* (source: any) {
340
544
  for await (const chunkList of source) {
341
545
  const msg = Buffer.from(chunkList.subarray());
342
- const response = await handler(msg);
546
+ const response = await handler(connection.remotePeer, msg);
343
547
  yield new Uint8Array(transform.outboundTransformNoTopic(response));
344
548
  }
345
549
  },
@@ -347,6 +551,7 @@ export class ReqResp {
347
551
  );
348
552
  } catch (e: any) {
349
553
  this.logger.warn(e);
554
+ this.metrics.recordResponseError(protocol);
350
555
  } finally {
351
556
  await stream.close();
352
557
  }
@@ -45,6 +45,18 @@ export interface P2PService {
45
45
  request: InstanceType<SubProtocolMap[Protocol]['request']>,
46
46
  ): Promise<InstanceType<SubProtocolMap[Protocol]['response']> | undefined>;
47
47
 
48
+ /**
49
+ * Send a batch of requests to peers, and return the responses
50
+ *
51
+ * @param protocol - The request response protocol to use
52
+ * @param requests - The requests to send to the peers
53
+ * @returns The responses to the requests
54
+ */
55
+ sendBatchRequest<Protocol extends ReqRespSubProtocol>(
56
+ protocol: Protocol,
57
+ requests: InstanceType<SubProtocolMap[Protocol]['request']>[],
58
+ ): Promise<InstanceType<SubProtocolMap[Protocol]['response']>[] | undefined>;
59
+
48
60
  // Leaky abstraction: fix https://github.com/AztecProtocol/aztec-packages/issues/7963
49
61
  registerBlockReceivedCallback(callback: (block: BlockProposal) => Promise<BlockAttestation | undefined>): void;
50
62
 
package/src/util.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { type AztecKVStore, type AztecSingleton } from '@aztec/kv-store';
1
+ import { type AztecAsyncKVStore } from '@aztec/kv-store';
2
2
  import { type DataStoreConfig } from '@aztec/kv-store/config';
3
3
 
4
4
  import type { GossipSub } from '@chainsafe/libp2p-gossipsub';
5
5
  import { generateKeyPair, marshalPrivateKey, unmarshalPrivateKey } from '@libp2p/crypto/keys';
6
6
  import { type PeerId, type PrivateKey } from '@libp2p/interface';
7
+ import { type ConnectionManager } from '@libp2p/interface-internal';
7
8
  import { createFromPrivKey } from '@libp2p/peer-id-factory';
8
9
  import { resolve } from 'dns/promises';
9
10
  import type { Libp2p } from 'libp2p';
@@ -13,6 +14,9 @@ import { type P2PConfig } from './config.js';
13
14
  export interface PubSubLibp2p extends Libp2p {
14
15
  services: {
15
16
  pubsub: GossipSub;
17
+ components: {
18
+ connectionManager: ConnectionManager;
19
+ };
16
20
  };
17
21
  }
18
22
 
@@ -153,14 +157,17 @@ export async function configureP2PClientAddresses(
153
157
  * 3. If not, create a new one, then persist it in the node
154
158
  *
155
159
  */
156
- export async function getPeerIdPrivateKey(config: { peerIdPrivateKey?: string }, store: AztecKVStore): Promise<string> {
157
- const peerIdPrivateKeySingleton: AztecSingleton<string> = store.openSingleton('peerIdPrivateKey');
160
+ export async function getPeerIdPrivateKey(
161
+ config: { peerIdPrivateKey?: string },
162
+ store: AztecAsyncKVStore,
163
+ ): Promise<string> {
164
+ const peerIdPrivateKeySingleton = store.openSingleton<string>('peerIdPrivateKey');
158
165
  if (config.peerIdPrivateKey) {
159
166
  await peerIdPrivateKeySingleton.set(config.peerIdPrivateKey);
160
167
  return config.peerIdPrivateKey;
161
168
  }
162
169
 
163
- const storedPeerIdPrivateKey = peerIdPrivateKeySingleton.get();
170
+ const storedPeerIdPrivateKey = await peerIdPrivateKeySingleton.getAsync();
164
171
  if (storedPeerIdPrivateKey) {
165
172
  return storedPeerIdPrivateKey;
166
173
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"peer_scoring.d.ts","sourceRoot":"","sources":["../../../src/services/peer-scoring/peer_scoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjD,oBAAY,cAAc;IACxB,MAAM,IAAA;IACN,UAAU,IAAA;IACV,OAAO,IAAA;CACR;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,WAAW,CAAO;IAC1B,aAAa,EAAE;SAAG,GAAG,IAAI,iBAAiB,GAAG,MAAM;KAAE,CAAC;gBAE1C,MAAM,EAAE,SAAS;IAY7B,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAmBvD,cAAc,IAAI,IAAI;IActB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIhC,aAAa,CAAC,MAAM,EAAE,MAAM;IAW5B,QAAQ,IAAI;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE;CAGpC"}
@@ -1,75 +0,0 @@
1
- import { PeerErrorSeverity } from '@aztec/circuit-types';
2
- import { median } from '@aztec/foundation/collection';
3
- const DefaultPeerPenalties = {
4
- [PeerErrorSeverity.LowToleranceError]: 50,
5
- [PeerErrorSeverity.MidToleranceError]: 10,
6
- [PeerErrorSeverity.HighToleranceError]: 2,
7
- };
8
- export var PeerScoreState;
9
- (function (PeerScoreState) {
10
- PeerScoreState[PeerScoreState["Banned"] = 0] = "Banned";
11
- PeerScoreState[PeerScoreState["Disconnect"] = 1] = "Disconnect";
12
- PeerScoreState[PeerScoreState["Healthy"] = 2] = "Healthy";
13
- })(PeerScoreState || (PeerScoreState = {}));
14
- // TODO: move into config / constants
15
- const MIN_SCORE_BEFORE_BAN = -100;
16
- const MIN_SCORE_BEFORE_DISCONNECT = -50;
17
- export class PeerScoring {
18
- constructor(config) {
19
- this.scores = new Map();
20
- this.lastUpdateTime = new Map();
21
- this.decayInterval = 1000 * 60; // 1 minute
22
- this.decayFactor = 0.9;
23
- const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
24
- this.peerPenalties = {
25
- [PeerErrorSeverity.HighToleranceError]: orderedValues?.[0] ?? DefaultPeerPenalties[PeerErrorSeverity.HighToleranceError],
26
- [PeerErrorSeverity.MidToleranceError]: orderedValues?.[1] ?? DefaultPeerPenalties[PeerErrorSeverity.MidToleranceError],
27
- [PeerErrorSeverity.LowToleranceError]: orderedValues?.[2] ?? DefaultPeerPenalties[PeerErrorSeverity.LowToleranceError],
28
- };
29
- }
30
- updateScore(peerId, scoreDelta) {
31
- const currentTime = Date.now();
32
- const lastUpdate = this.lastUpdateTime.get(peerId) || currentTime;
33
- const timePassed = currentTime - lastUpdate;
34
- const decayPeriods = Math.floor(timePassed / this.decayInterval);
35
- let currentScore = this.scores.get(peerId) || 0;
36
- // Apply decay
37
- currentScore *= Math.pow(this.decayFactor, decayPeriods);
38
- // Apply new score delta
39
- currentScore += scoreDelta;
40
- this.scores.set(peerId, currentScore);
41
- this.lastUpdateTime.set(peerId, currentTime);
42
- return currentScore;
43
- }
44
- decayAllScores() {
45
- const currentTime = Date.now();
46
- for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
47
- const timePassed = currentTime - lastUpdate;
48
- const decayPeriods = Math.floor(timePassed / this.decayInterval);
49
- if (decayPeriods > 0) {
50
- let score = this.scores.get(peerId) || 0;
51
- score *= Math.pow(this.decayFactor, decayPeriods);
52
- this.scores.set(peerId, score);
53
- this.lastUpdateTime.set(peerId, currentTime);
54
- }
55
- }
56
- }
57
- getScore(peerId) {
58
- return this.scores.get(peerId) || 0;
59
- }
60
- getScoreState(peerId) {
61
- // TODO: permanently store banned peers???
62
- const score = this.getScore(peerId);
63
- if (score < MIN_SCORE_BEFORE_BAN) {
64
- return PeerScoreState.Banned;
65
- }
66
- else if (score < MIN_SCORE_BEFORE_DISCONNECT) {
67
- return PeerScoreState.Disconnect;
68
- }
69
- return PeerScoreState.Healthy;
70
- }
71
- getStats() {
72
- return { medianScore: median(Array.from(this.scores.values())) ?? 0 };
73
- }
74
- }
75
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVlcl9zY29yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3BlZXItc2NvcmluZy9wZWVyX3Njb3JpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBSXRELE1BQU0sb0JBQW9CLEdBQUc7SUFDM0IsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUU7SUFDekMsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUU7SUFDekMsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7Q0FDMUMsQ0FBQztBQUVGLE1BQU0sQ0FBTixJQUFZLGNBSVg7QUFKRCxXQUFZLGNBQWM7SUFDeEIsdURBQU0sQ0FBQTtJQUNOLCtEQUFVLENBQUE7SUFDVix5REFBTyxDQUFBO0FBQ1QsQ0FBQyxFQUpXLGNBQWMsS0FBZCxjQUFjLFFBSXpCO0FBRUQscUNBQXFDO0FBQ3JDLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxHQUFHLENBQUM7QUFDbEMsTUFBTSwyQkFBMkIsR0FBRyxDQUFDLEVBQUUsQ0FBQztBQUV4QyxNQUFNLE9BQU8sV0FBVztJQU90QixZQUFZLE1BQWlCO1FBTnJCLFdBQU0sR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN4QyxtQkFBYyxHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2hELGtCQUFhLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVc7UUFDdEMsZ0JBQVcsR0FBRyxHQUFHLENBQUM7UUFJeEIsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFD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
@@ -1 +0,0 @@
1
- {"version":3,"file":"peer_manager.d.ts","sourceRoot":"","sources":["../../src/services/peer_manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE7E,OAAO,EAAE,KAAK,eAAe,EAAE,UAAU,EAAa,MAAM,yBAAyB,CAAC;AAGtF,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIjE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAqBzD,qBAAa,WAAY,SAAQ,UAAU;IAQvC,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,oBAAoB;IAC5B,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,MAAM;IAXhB,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,8BAA8B,CAAa;IACnD,OAAO,CAAC,aAAa,CAAwC;gBAGnD,UAAU,EAAE,YAAY,EACxB,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,SAAS,EACzB,eAAe,EAAE,eAAe,EACxB,MAAM,yCAAmC;IAkB5C,SAAS;IAShB;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAShC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAS5B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB;IAOvD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIpC,QAAQ,CAAC,cAAc,UAAQ,GAAG,QAAQ,EAAE;IAiCnD;;OAEG;IACH,OAAO,CAAC,QAAQ;IA6DhB,OAAO,CAAC,mBAAmB;YAoBb,cAAc;IAK5B;;;OAGG;YACW,oBAAoB;YA8DpB,QAAQ;IA2BtB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,gBAAgB;IAiBxB;;;OAGG;IACI,IAAI;CAKZ"}