@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.
- package/dest/bootstrap/bootstrap.d.ts +2 -2
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +1 -1
- package/dest/client/factory.js +4 -4
- package/dest/client/p2p_client.d.ts +13 -16
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +55 -67
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +11 -19
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +6 -13
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +74 -80
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +5 -5
- package/dest/mem_pools/attestation_pool/mocks.d.ts +3 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +3 -3
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +9 -9
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +60 -54
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +7 -7
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +17 -18
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +7 -7
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +48 -47
- package/dest/mocks/index.d.ts +3 -3
- package/dest/mocks/index.d.ts.map +1 -1
- package/dest/mocks/index.js +19 -18
- package/dest/msg_validators/attestation_validator/attestation_validator.js +2 -2
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +2 -2
- package/dest/msg_validators/tx_validator/block_header_validator.js +3 -3
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +7 -7
- package/dest/msg_validators/tx_validator/double_spend_validator.js +3 -3
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +9 -9
- package/dest/services/data_store.d.ts +4 -4
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +7 -7
- package/dest/services/dummy_service.d.ts +7 -0
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +10 -1
- package/dest/services/libp2p/libp2p_service.d.ts +19 -15
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +163 -134
- package/dest/services/peer-manager/metrics.d.ts +12 -0
- package/dest/services/peer-manager/metrics.d.ts.map +1 -0
- package/dest/services/peer-manager/metrics.js +26 -0
- package/dest/services/{peer_manager.d.ts → peer-manager/peer_manager.d.ts} +24 -8
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_manager.js +395 -0
- package/dest/services/{peer-scoring → peer-manager}/peer_scoring.d.ts +3 -0
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_scoring.js +84 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +45 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +81 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +61 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +175 -0
- package/dest/services/reqresp/interface.d.ts +17 -4
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +34 -11
- package/dest/services/reqresp/metrics.d.ts +15 -0
- package/dest/services/reqresp/metrics.d.ts.map +1 -0
- package/dest/services/reqresp/metrics.js +42 -0
- package/dest/services/reqresp/protocols/block.d.ts +4 -0
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block.js +9 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts +51 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/goodbye.js +92 -0
- package/dest/services/reqresp/protocols/index.d.ts +9 -0
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/index.js +9 -0
- package/dest/services/reqresp/protocols/ping.d.ts +9 -0
- package/dest/services/reqresp/protocols/ping.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/ping.js +9 -0
- package/dest/services/reqresp/{handlers.d.ts → protocols/status.d.ts} +1 -7
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/status.js +9 -0
- package/dest/services/reqresp/protocols/tx.d.ts +13 -0
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/tx.js +23 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts.map +1 -0
- package/dest/services/reqresp/{rate_limiter → rate-limiter}/index.js +1 -1
- package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.d.ts +3 -3
- package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.js +4 -4
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.js +55 -0
- package/dest/services/reqresp/reqresp.d.ts +33 -6
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +414 -249
- package/dest/services/service.d.ts +8 -0
- package/dest/services/service.d.ts.map +1 -1
- package/dest/util.d.ts +6 -2
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +2 -2
- package/package.json +8 -8
- package/src/bootstrap/bootstrap.ts +2 -2
- package/src/client/factory.ts +3 -3
- package/src/client/p2p_client.ts +68 -80
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +14 -22
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +100 -94
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +4 -4
- package/src/mem_pools/attestation_pool/mocks.ts +5 -5
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +84 -73
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +26 -23
- package/src/mem_pools/tx_pool/tx_pool.ts +7 -7
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +50 -47
- package/src/mocks/index.ts +19 -20
- package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +1 -1
- package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
- package/src/msg_validators/tx_validator/data_validator.ts +12 -9
- package/src/msg_validators/tx_validator/double_spend_validator.ts +2 -2
- package/src/msg_validators/tx_validator/metadata_validator.ts +8 -8
- package/src/services/data_store.ts +9 -9
- package/src/services/dummy_service.ts +13 -0
- package/src/services/libp2p/libp2p_service.ts +212 -163
- package/src/services/peer-manager/metrics.ts +41 -0
- package/src/services/{peer_manager.ts → peer-manager/peer_manager.ts} +73 -23
- package/src/services/{peer-scoring → peer-manager}/peer_scoring.ts +16 -3
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +94 -0
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +211 -0
- package/src/services/reqresp/interface.ts +39 -16
- package/src/services/reqresp/metrics.ts +57 -0
- package/src/services/reqresp/protocols/block.ts +15 -0
- package/src/services/reqresp/protocols/goodbye.ts +101 -0
- package/src/services/reqresp/protocols/index.ts +8 -0
- package/src/services/reqresp/protocols/ping.ts +8 -0
- package/src/services/reqresp/{handlers.ts → protocols/status.ts} +0 -9
- package/src/services/reqresp/protocols/tx.ts +29 -0
- package/src/services/reqresp/{rate_limiter → rate-limiter}/rate_limiter.ts +3 -3
- package/src/services/reqresp/{rate_limiter → rate-limiter}/rate_limits.ts +24 -4
- package/src/services/reqresp/reqresp.ts +231 -26
- package/src/services/service.ts +12 -0
- package/src/util.ts +11 -4
- package/dest/services/peer-scoring/peer_scoring.d.ts.map +0 -1
- package/dest/services/peer-scoring/peer_scoring.js +0 -75
- package/dest/services/peer_manager.d.ts.map +0 -1
- package/dest/services/peer_manager.js +0 -358
- package/dest/services/reqresp/handlers.d.ts.map +0 -1
- package/dest/services/reqresp/handlers.js +0 -17
- package/dest/services/reqresp/rate_limiter/index.d.ts.map +0 -1
- package/dest/services/reqresp/rate_limiter/rate_limits.d.ts.map +0 -1
- package/dest/services/reqresp/rate_limiter/rate_limits.js +0 -35
- /package/dest/services/reqresp/{rate_limiter → rate-limiter}/index.d.ts +0 -0
- /package/dest/services/reqresp/{rate_limiter → rate-limiter}/rate_limits.d.ts +0 -0
- /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
|
|
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 {
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
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
|
-
* -
|
|
117
|
-
* - Opens a stream with
|
|
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
|
-
|
|
137
|
-
|
|
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
|
-
|
|
140
|
-
const peers = this.libp2p.getPeers();
|
|
188
|
+
attemptedPeers.set(peer.toString(), true);
|
|
141
189
|
|
|
142
|
-
|
|
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
|
-
|
|
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
|
-
|
|
205
|
-
|
|
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
|
|
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.
|
|
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
|
}
|
package/src/services/service.ts
CHANGED
|
@@ -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
|
|
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(
|
|
157
|
-
|
|
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.
|
|
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"}
|