@aztec/p2p 3.0.0-rc.5 → 4.0.0-nightly.20260107
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/client/factory.d.ts +2 -2
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +2 -3
- package/dest/client/p2p_client.d.ts +2 -2
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +395 -21
- package/dest/config.d.ts +4 -7
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +6 -9
- package/dest/mem_pools/instrumentation.d.ts +7 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +29 -2
- package/dest/mem_pools/interface.d.ts +3 -4
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +28 -24
- 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 +261 -323
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +18 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +56 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +83 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +5 -0
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +15 -0
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +88 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +76 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
- package/dest/mem_pools/tx_pool/index.d.ts +1 -2
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/index.js +0 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +6 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +8 -4
- 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 +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 +25 -20
- package/dest/services/libp2p/libp2p_service.d.ts +4 -4
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +447 -64
- package/dest/services/peer-manager/metrics.d.ts +6 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +17 -0
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +385 -9
- package/dest/services/reqresp/protocols/tx.d.ts +2 -3
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +402 -24
- package/dest/services/tx_provider.d.ts +2 -1
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +11 -2
- package/dest/services/tx_provider_instrumentation.d.ts +5 -2
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.js +14 -1
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -2
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +1 -0
- package/package.json +14 -14
- package/src/client/factory.ts +5 -10
- package/src/client/p2p_client.ts +12 -17
- package/src/config.ts +8 -14
- package/src/mem_pools/instrumentation.ts +33 -0
- package/src/mem_pools/interface.ts +2 -4
- package/src/mem_pools/tx_pool/README.md +255 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +308 -368
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +71 -0
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +93 -0
- package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +108 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +91 -0
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
- package/src/mem_pools/tx_pool/index.ts +0 -1
- package/src/mem_pools/tx_pool/priority.ts +8 -1
- package/src/mem_pools/tx_pool/tx_pool.ts +8 -3
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +18 -13
- package/src/services/libp2p/libp2p_service.ts +12 -17
- package/src/services/peer-manager/metrics.ts +22 -0
- package/src/services/peer-manager/peer_manager.ts +2 -0
- package/src/services/reqresp/protocols/tx.ts +1 -2
- package/src/services/tx_provider.ts +17 -2
- package/src/services/tx_provider_instrumentation.ts +19 -2
- package/src/test-helpers/mock-pubsub.ts +1 -1
- package/src/test-helpers/reqresp-nodes.ts +1 -1
- package/src/testbench/p2p_client_testbench_worker.ts +2 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -81
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -239
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -285
|
@@ -26,7 +26,7 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
it('adds txs to the pool as pending', async () => {
|
|
29
|
-
const tx1 = await mockTx();
|
|
29
|
+
const tx1 = await mockTx(1);
|
|
30
30
|
|
|
31
31
|
await pool.addTxs([tx1]);
|
|
32
32
|
const poolTx = await pool.getTxByHash(tx1.getTxHash());
|
|
@@ -37,9 +37,9 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
it('emits txs-added event with new txs', async () => {
|
|
40
|
-
const tx1 = await mockTx(); // existing and pending
|
|
41
|
-
const tx2 = await mockTx(); // mined but not known
|
|
42
|
-
const tx3 = await mockTx(); // brand new
|
|
40
|
+
const tx1 = await mockTx(1); // existing and pending
|
|
41
|
+
const tx2 = await mockTx(2); // mined but not known
|
|
42
|
+
const tx3 = await mockTx(3); // brand new
|
|
43
43
|
|
|
44
44
|
await pool.addTxs([tx1]);
|
|
45
45
|
await pool.markAsMined([tx2.getTxHash()], minedBlockHeader);
|
|
@@ -52,10 +52,11 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
52
52
|
await pool.addTxs([tx1, tx2, tx3]);
|
|
53
53
|
expect(txsFromEvent).toBeDefined();
|
|
54
54
|
expect(txsFromEvent).toHaveLength(2);
|
|
55
|
-
|
|
55
|
+
const eventHashes = txsFromEvent!.map(tx => tx.getTxHash());
|
|
56
|
+
expect(eventHashes).toEqual(expect.arrayContaining([tx2.getTxHash(), tx3.getTxHash()]));
|
|
56
57
|
});
|
|
57
58
|
|
|
58
|
-
it('
|
|
59
|
+
it('removes txs from the pool', async () => {
|
|
59
60
|
const pendingTx = await mockTx(1);
|
|
60
61
|
const minedTx = await mockTx(2);
|
|
61
62
|
|
|
@@ -83,7 +84,8 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
83
84
|
await pool.addTxs([tx1, tx2]);
|
|
84
85
|
await pool.markAsMined([tx1.getTxHash()], minedBlockHeader);
|
|
85
86
|
|
|
86
|
-
await
|
|
87
|
+
const retrievedTx = await pool.getTxByHash(tx1.getTxHash());
|
|
88
|
+
expect(retrievedTx?.getTxHash()).toEqual(tx1.getTxHash());
|
|
87
89
|
await expect(pool.getTxStatus(tx1.getTxHash())).resolves.toEqual('mined');
|
|
88
90
|
await expect(pool.getMinedTxHashes()).resolves.toEqual([[tx1.getTxHash(), 1]]);
|
|
89
91
|
await expect(pool.getPendingTxHashes()).resolves.toEqual([tx2.getTxHash()]);
|
|
@@ -97,7 +99,7 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
97
99
|
await pool.addTxs([tx1, tx2]);
|
|
98
100
|
await pool.markAsMined([tx1.getTxHash()], minedBlockHeader);
|
|
99
101
|
|
|
100
|
-
await pool.markMinedAsPending([tx1.getTxHash()]);
|
|
102
|
+
await pool.markMinedAsPending([tx1.getTxHash()], BlockNumber(1));
|
|
101
103
|
await expect(pool.getMinedTxHashes()).resolves.toEqual([]);
|
|
102
104
|
const pending = await pool.getPendingTxHashes();
|
|
103
105
|
expect(pending).toHaveLength(2);
|
|
@@ -121,7 +123,7 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
121
123
|
);
|
|
122
124
|
|
|
123
125
|
// reorg: both txs should now become available again
|
|
124
|
-
await pool.markMinedAsPending([tx1.getTxHash(), someTxHashThatThisPeerDidNotSee]);
|
|
126
|
+
await pool.markMinedAsPending([tx1.getTxHash(), someTxHashThatThisPeerDidNotSee], BlockNumber(1));
|
|
125
127
|
await expect(pool.getMinedTxHashes()).resolves.toEqual([]);
|
|
126
128
|
await expect(pool.getPendingTxHashes()).resolves.toEqual([tx1.getTxHash()]); // tx2 is not in the pool
|
|
127
129
|
await expect(pool.getPendingTxCount()).resolves.toEqual(1);
|
|
@@ -136,7 +138,8 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
136
138
|
|
|
137
139
|
const poolTxs = await pool.getAllTxs();
|
|
138
140
|
expect(poolTxs).toHaveLength(3);
|
|
139
|
-
|
|
141
|
+
const poolHashes = poolTxs.map(tx => tx.getTxHash());
|
|
142
|
+
expect(poolHashes).toEqual(expect.arrayContaining([tx1.getTxHash(), tx2.getTxHash(), tx3.getTxHash()]));
|
|
140
143
|
await expect(pool.getPendingTxCount()).resolves.toEqual(3);
|
|
141
144
|
});
|
|
142
145
|
|
|
@@ -163,17 +166,19 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
163
166
|
|
|
164
167
|
const requestedTxs = await pool.getTxsByHash([tx1.getTxHash(), tx3.getTxHash()]);
|
|
165
168
|
expect(requestedTxs).toHaveLength(2);
|
|
166
|
-
|
|
169
|
+
const requestedHashes = requestedTxs.map(tx => tx!.getTxHash());
|
|
170
|
+
expect(requestedHashes).toEqual(expect.arrayContaining([tx1.getTxHash(), tx3.getTxHash()]));
|
|
167
171
|
});
|
|
168
172
|
|
|
169
173
|
it('returns a large number of transactions by their hash', async () => {
|
|
170
|
-
const numTxs =
|
|
174
|
+
const numTxs = 1_000;
|
|
171
175
|
const txs = await Promise.all(Array.from({ length: numTxs }, (_, i) => mockTx(i)));
|
|
172
176
|
const hashes = txs.map(tx => tx.getTxHash());
|
|
173
177
|
await pool.addTxs(txs);
|
|
174
178
|
const requestedTxs = await pool.getTxsByHash(hashes);
|
|
175
179
|
expect(requestedTxs).toHaveLength(numTxs);
|
|
176
|
-
|
|
180
|
+
const requestedHashes = requestedTxs.map(tx => tx!.getTxHash());
|
|
181
|
+
expect(requestedHashes).toEqual(expect.arrayContaining(hashes));
|
|
177
182
|
});
|
|
178
183
|
|
|
179
184
|
it('returns whether or not txs exist', async () => {
|
|
@@ -153,7 +153,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
153
153
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
154
154
|
private reqresp: ReqRespInterface,
|
|
155
155
|
private peerManager: PeerManagerInterface,
|
|
156
|
-
protected mempools: MemPools
|
|
156
|
+
protected mempools: MemPools,
|
|
157
157
|
private archiver: L2BlockSource & ContractDataSource,
|
|
158
158
|
private epochCache: EpochCacheInterface,
|
|
159
159
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
@@ -185,7 +185,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
185
185
|
|
|
186
186
|
// Use FishermanAttestationValidator in fisherman mode to validate attestation payloads against proposals
|
|
187
187
|
this.attestationValidator = config.fishermanMode
|
|
188
|
-
? new FishermanAttestationValidator(epochCache, mempools.attestationPool
|
|
188
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
189
189
|
: new AttestationValidator(epochCache);
|
|
190
190
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
|
|
191
191
|
|
|
@@ -215,7 +215,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
215
215
|
config: P2PConfig,
|
|
216
216
|
peerId: PeerId,
|
|
217
217
|
deps: {
|
|
218
|
-
mempools: MemPools
|
|
218
|
+
mempools: MemPools;
|
|
219
219
|
l2BlockSource: L2BlockSource & ContractDataSource;
|
|
220
220
|
epochCache: EpochCacheInterface;
|
|
221
221
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
@@ -486,8 +486,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
486
486
|
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
|
|
487
487
|
};
|
|
488
488
|
|
|
489
|
-
|
|
490
|
-
if (this.mempools.attestationPool && !this.config.disableTransactions) {
|
|
489
|
+
if (!this.config.disableTransactions) {
|
|
491
490
|
const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
|
|
492
491
|
requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
|
|
493
492
|
}
|
|
@@ -809,7 +808,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
809
808
|
private async processAttestationFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
810
809
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockAttestation>> = async () => {
|
|
811
810
|
const attestation = BlockAttestation.fromBuffer(payloadData);
|
|
812
|
-
const pool = this.mempools.attestationPool
|
|
811
|
+
const pool = this.mempools.attestationPool;
|
|
813
812
|
const isValid = await this.validateAttestation(source, attestation);
|
|
814
813
|
const exists = isValid && (await pool.hasAttestation(attestation));
|
|
815
814
|
|
|
@@ -866,7 +865,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
866
865
|
},
|
|
867
866
|
);
|
|
868
867
|
|
|
869
|
-
await this.mempools.attestationPool
|
|
868
|
+
await this.mempools.attestationPool.addAttestations([attestation]);
|
|
870
869
|
}
|
|
871
870
|
|
|
872
871
|
private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
@@ -875,10 +874,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
875
874
|
const isValid = await this.validateBlockProposal(source, block);
|
|
876
875
|
const pool = this.mempools.attestationPool;
|
|
877
876
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const exists = isValid && (await pool?.hasBlockProposal(block));
|
|
881
|
-
const canAdd = isValid && (await pool?.canAddProposal(block));
|
|
877
|
+
const exists = isValid && (await pool.hasBlockProposal(block));
|
|
878
|
+
const canAdd = isValid && (await pool.canAddProposal(block));
|
|
882
879
|
|
|
883
880
|
this.logger.trace(`Validate propagated block proposal`, {
|
|
884
881
|
isValid,
|
|
@@ -934,14 +931,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
934
931
|
archive: block.archive.toString(),
|
|
935
932
|
source: sender.toString(),
|
|
936
933
|
});
|
|
937
|
-
const attestationsForPreviousSlot = await this.mempools.attestationPool
|
|
938
|
-
|
|
939
|
-
this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
|
|
940
|
-
}
|
|
934
|
+
const attestationsForPreviousSlot = await this.mempools.attestationPool.getAttestationsForSlot(previousSlot);
|
|
935
|
+
this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
|
|
941
936
|
|
|
942
937
|
// Attempt to add proposal, then mark the txs in this proposal as non-evictable
|
|
943
938
|
try {
|
|
944
|
-
await this.mempools.attestationPool
|
|
939
|
+
await this.mempools.attestationPool.addBlockProposal(block);
|
|
945
940
|
} catch (err: unknown) {
|
|
946
941
|
// Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
|
|
947
942
|
if (err instanceof ProposalSlotCapExceededError) {
|
|
@@ -1047,7 +1042,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1047
1042
|
}
|
|
1048
1043
|
|
|
1049
1044
|
// Given proposal (should have locally), ensure returned txs are valid subset and match request indices
|
|
1050
|
-
const proposal = await this.mempools.attestationPool
|
|
1045
|
+
const proposal = await this.mempools.attestationPool.getBlockProposal(request.blockHash.toString());
|
|
1051
1046
|
if (proposal) {
|
|
1052
1047
|
// Build intersected indices
|
|
1053
1048
|
const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Attributes,
|
|
3
3
|
type Gauge,
|
|
4
|
+
type Histogram,
|
|
4
5
|
Metrics,
|
|
5
6
|
type TelemetryClient,
|
|
6
7
|
type Tracer,
|
|
@@ -9,6 +10,8 @@ import {
|
|
|
9
10
|
getTelemetryClient,
|
|
10
11
|
} from '@aztec/telemetry-client';
|
|
11
12
|
|
|
13
|
+
import type { PeerId } from '@libp2p/interface';
|
|
14
|
+
|
|
12
15
|
import { type GoodByeReason, prettyGoodbyeReason } from '../reqresp/protocols/index.js';
|
|
13
16
|
|
|
14
17
|
export class PeerManagerMetrics {
|
|
@@ -16,6 +19,9 @@ export class PeerManagerMetrics {
|
|
|
16
19
|
private receivedGoodbyes: UpDownCounter;
|
|
17
20
|
private peerCount: Gauge;
|
|
18
21
|
private lowScoreDisconnects: UpDownCounter;
|
|
22
|
+
private peerConnectionDuration: Histogram;
|
|
23
|
+
|
|
24
|
+
private peerConnectedAt: Map<string, number> = new Map<string, number>();
|
|
19
25
|
|
|
20
26
|
public readonly tracer: Tracer;
|
|
21
27
|
|
|
@@ -46,6 +52,11 @@ export class PeerManagerMetrics {
|
|
|
46
52
|
unit: 'peers',
|
|
47
53
|
valueType: ValueType.INT,
|
|
48
54
|
});
|
|
55
|
+
this.peerConnectionDuration = meter.createHistogram(Metrics.PEER_MANAGER_PEER_CONNECTION_DURATION, {
|
|
56
|
+
description: 'Time duration between peer connection and disconnection',
|
|
57
|
+
unit: 'ms',
|
|
58
|
+
valueType: ValueType.INT,
|
|
59
|
+
});
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
public recordGoodbyeSent(reason: GoodByeReason) {
|
|
@@ -63,4 +74,15 @@ export class PeerManagerMetrics {
|
|
|
63
74
|
public recordLowScoreDisconnect(scoreState: 'Banned' | 'Disconnect') {
|
|
64
75
|
this.lowScoreDisconnects.add(1, { [Attributes.P2P_PEER_SCORE_STATE]: scoreState });
|
|
65
76
|
}
|
|
77
|
+
|
|
78
|
+
public peerConnected(id: PeerId) {
|
|
79
|
+
this.peerConnectedAt.set(id.toString(), Date.now());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public peerDisconnected(id: PeerId) {
|
|
83
|
+
const connectedAt = this.peerConnectedAt.get(id.toString());
|
|
84
|
+
if (connectedAt) {
|
|
85
|
+
this.peerConnectionDuration.record(Date.now() - connectedAt);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
66
88
|
}
|
|
@@ -278,6 +278,7 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
278
278
|
private handleConnectedPeerEvent(e: CustomEvent<PeerId>) {
|
|
279
279
|
const peerId = e.detail;
|
|
280
280
|
this.logger.verbose(`Connected to peer ${peerId.toString()}`);
|
|
281
|
+
this.metrics.peerConnected(peerId);
|
|
281
282
|
if (this.config.p2pDisableStatusHandshake) {
|
|
282
283
|
return;
|
|
283
284
|
}
|
|
@@ -303,6 +304,7 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
303
304
|
*/
|
|
304
305
|
private handleDisconnectedPeerEvent(e: CustomEvent<PeerId>) {
|
|
305
306
|
const peerId = e.detail;
|
|
307
|
+
this.metrics.peerDisconnected(peerId);
|
|
306
308
|
this.logger.verbose(`Disconnected from peer ${peerId.toString()}`);
|
|
307
309
|
const validatorAddress = this.authenticatedPeerIdToValidatorAddress.get(peerId.toString());
|
|
308
310
|
if (validatorAddress !== undefined) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { chunk } from '@aztec/foundation/collection';
|
|
2
|
-
import type { P2PClientType } from '@aztec/stdlib/p2p';
|
|
3
2
|
import { TxArray, TxHash, TxHashArray } from '@aztec/stdlib/tx';
|
|
4
3
|
|
|
5
4
|
import type { PeerId } from '@libp2p/interface';
|
|
@@ -16,7 +15,7 @@ import { ReqRespStatus, ReqRespStatusError } from '../status.js';
|
|
|
16
15
|
* @param mempools - the mempools
|
|
17
16
|
* @returns the Tx request handler
|
|
18
17
|
*/
|
|
19
|
-
export function reqRespTxHandler
|
|
18
|
+
export function reqRespTxHandler(mempools: MemPools): ReqRespSubProtocolHandler {
|
|
20
19
|
/**
|
|
21
20
|
* Handler for tx requests
|
|
22
21
|
* @param msg - the tx request message
|
|
@@ -137,6 +137,7 @@ export class TxProvider implements ITxProvider {
|
|
|
137
137
|
);
|
|
138
138
|
|
|
139
139
|
if (missingTxHashes.size === 0) {
|
|
140
|
+
this.instrumentation.incTxsFromP2P(0, txHashes.length);
|
|
140
141
|
return { txsFromMempool };
|
|
141
142
|
}
|
|
142
143
|
|
|
@@ -155,24 +156,26 @@ export class TxProvider implements ITxProvider {
|
|
|
155
156
|
|
|
156
157
|
if (missingTxHashes.size === 0) {
|
|
157
158
|
await this.processProposalTxs(txsFromProposal);
|
|
159
|
+
this.instrumentation.incTxsFromP2P(0, txHashes.length);
|
|
158
160
|
return { txsFromMempool, txsFromProposal };
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
// Start tx collection from the network if needed, while we validate the txs taken from the proposal in parallel
|
|
162
164
|
const [txsFromNetwork] = await Promise.all([
|
|
163
|
-
this.
|
|
165
|
+
this.collectFromP2P(request, [...missingTxHashes], opts),
|
|
164
166
|
this.processProposalTxs(txsFromProposal),
|
|
165
167
|
] as const);
|
|
166
168
|
|
|
167
169
|
if (txsFromNetwork.length > 0) {
|
|
168
170
|
txsFromNetwork.forEach(tx => missingTxHashes.delete(tx.txHash.toString()));
|
|
169
|
-
this.instrumentation.incTxsFromP2P(txsFromNetwork.length);
|
|
170
171
|
this.log.debug(
|
|
171
172
|
`Retrieved ${txsFromNetwork.length} txs from network for block proposal (${missingTxHashes.size} pending)`,
|
|
172
173
|
{ ...blockInfo, missingTxHashes: [...missingTxHashes] },
|
|
173
174
|
);
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
this.instrumentation.incTxsFromP2P(txsFromNetwork.length, txHashes.length);
|
|
178
|
+
|
|
176
179
|
if (missingTxHashes.size === 0) {
|
|
177
180
|
return { txsFromNetwork, txsFromMempool, txsFromProposal };
|
|
178
181
|
}
|
|
@@ -200,6 +203,18 @@ export class TxProvider implements ITxProvider {
|
|
|
200
203
|
};
|
|
201
204
|
}
|
|
202
205
|
|
|
206
|
+
private async collectFromP2P(
|
|
207
|
+
input: FastCollectionRequestInput,
|
|
208
|
+
txHashes: TxHash[] | string[],
|
|
209
|
+
opts: { deadline: Date; pinnedPeer?: PeerId },
|
|
210
|
+
): Promise<Tx[]> {
|
|
211
|
+
const requestedAt = Date.now();
|
|
212
|
+
const result = await this.txCollection.collectFastFor(input, txHashes, opts);
|
|
213
|
+
const requestProcessedAt = Date.now();
|
|
214
|
+
this.instrumentation.recordTxsRequestDelay(requestProcessedAt - requestedAt);
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
|
|
203
218
|
private extractFromProposal(proposal: BlockProposal | undefined, missingTxHashes: string[]): Tx[] {
|
|
204
219
|
if (!proposal) {
|
|
205
220
|
return [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Metrics, type TelemetryClient, type UpDownCounter } from '@aztec/telemetry-client';
|
|
1
|
+
import { type Histogram, Metrics, type TelemetryClient, type UpDownCounter } from '@aztec/telemetry-client';
|
|
2
2
|
|
|
3
3
|
export class TxProviderInstrumentation {
|
|
4
4
|
private txFromProposalCount: UpDownCounter;
|
|
@@ -6,6 +6,9 @@ export class TxProviderInstrumentation {
|
|
|
6
6
|
private txFromP2PCount: UpDownCounter;
|
|
7
7
|
private missingTxsCount: UpDownCounter;
|
|
8
8
|
|
|
9
|
+
private fractionOfTxsRequestedFromP2P: Histogram;
|
|
10
|
+
private txsRequestDelay: Histogram;
|
|
11
|
+
|
|
9
12
|
constructor(client: TelemetryClient, name: string) {
|
|
10
13
|
const meter = client.getMeter(name);
|
|
11
14
|
|
|
@@ -24,6 +27,15 @@ export class TxProviderInstrumentation {
|
|
|
24
27
|
this.missingTxsCount = meter.createUpDownCounter(Metrics.TX_PROVIDER_MISSING_TXS_COUNT, {
|
|
25
28
|
description: 'The number of txs not found anywhere',
|
|
26
29
|
});
|
|
30
|
+
|
|
31
|
+
this.fractionOfTxsRequestedFromP2P = meter.createHistogram(Metrics.TX_PROVIDER_P2P_TXS_REQUESTED_FRACTION, {
|
|
32
|
+
description: 'The fraction of transaction requested from peers',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
this.txsRequestDelay = meter.createHistogram(Metrics.TX_PROVIDER_P2P_TXS_REQUEST_DELAY, {
|
|
36
|
+
unit: 'ms',
|
|
37
|
+
description: 'The time it took to request missing transactions from p2p',
|
|
38
|
+
});
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
incTxsFromProposals(count: number) {
|
|
@@ -34,8 +46,13 @@ export class TxProviderInstrumentation {
|
|
|
34
46
|
this.txFromMempoolCount.add(count);
|
|
35
47
|
}
|
|
36
48
|
|
|
37
|
-
incTxsFromP2P(count: number) {
|
|
49
|
+
incTxsFromP2P(count: number, total: number) {
|
|
38
50
|
this.txFromP2PCount.add(count);
|
|
51
|
+
this.fractionOfTxsRequestedFromP2P.record(count / total);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
recordTxsRequestDelay(delay: number) {
|
|
55
|
+
this.txsRequestDelay.record(delay);
|
|
39
56
|
}
|
|
40
57
|
|
|
41
58
|
incMissingTxs(count: number) {
|
|
@@ -39,7 +39,7 @@ export function getMockPubSubP2PServiceFactory<T extends P2PClientType>(
|
|
|
39
39
|
peerId: PeerId,
|
|
40
40
|
deps: {
|
|
41
41
|
packageVersion: string;
|
|
42
|
-
mempools: MemPools
|
|
42
|
+
mempools: MemPools;
|
|
43
43
|
l2BlockSource: L2BlockSource & ContractDataSource;
|
|
44
44
|
epochCache: EpochCacheInterface;
|
|
45
45
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
@@ -112,7 +112,7 @@ export async function createTestLibP2PService<T extends P2PClientType>(
|
|
|
112
112
|
archiver: L2BlockSource & ContractDataSource,
|
|
113
113
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
114
114
|
epochCache: EpochCache,
|
|
115
|
-
mempools: MemPools
|
|
115
|
+
mempools: MemPools,
|
|
116
116
|
telemetry: TelemetryClient,
|
|
117
117
|
port: number = 0,
|
|
118
118
|
peerId?: PeerId,
|
|
@@ -56,6 +56,7 @@ function mockTxPool(): TxPool {
|
|
|
56
56
|
hasTx: () => Promise.resolve(false),
|
|
57
57
|
updateConfig: () => {},
|
|
58
58
|
markTxsAsNonEvictable: () => Promise.resolve(),
|
|
59
|
+
clearNonEvictableTxs: () => Promise.resolve(),
|
|
59
60
|
cleanupDeletedMinedTxs: () => Promise.resolve(0),
|
|
60
61
|
};
|
|
61
62
|
return Object.assign(new EventEmitter(), pool);
|
|
@@ -126,7 +127,7 @@ class TestLibP2PService<T extends P2PClientType = P2PClientType.Full> extends Li
|
|
|
126
127
|
peerDiscoveryService: PeerDiscoveryService,
|
|
127
128
|
reqresp: ReqResp,
|
|
128
129
|
peerManager: PeerManager,
|
|
129
|
-
mempools: MemPools
|
|
130
|
+
mempools: MemPools,
|
|
130
131
|
archiver: L2BlockSource & ContractDataSource,
|
|
131
132
|
epochCache: EpochCacheInterface,
|
|
132
133
|
proofVerifier: ClientProtocolCircuitVerifier,
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
-
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
3
|
-
import { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
|
|
4
|
-
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
5
|
-
import type { TxPool, TxPoolEvents, TxPoolOptions } from './tx_pool.js';
|
|
6
|
-
declare const InMemoryTxPool_base: new () => TypedEventEmitter<TxPoolEvents>;
|
|
7
|
-
/**
|
|
8
|
-
* In-memory implementation of the Transaction Pool.
|
|
9
|
-
*/
|
|
10
|
-
export declare class InMemoryTxPool extends InMemoryTxPool_base implements TxPool {
|
|
11
|
-
private log;
|
|
12
|
-
/**
|
|
13
|
-
* Our tx pool, stored as a Map in-memory, with K: tx hash and V: the transaction.
|
|
14
|
-
*/
|
|
15
|
-
private txs;
|
|
16
|
-
private minedTxs;
|
|
17
|
-
private pendingTxs;
|
|
18
|
-
private deletedMinedTxHashes;
|
|
19
|
-
private blockToDeletedMinedTxHash;
|
|
20
|
-
private metrics;
|
|
21
|
-
/**
|
|
22
|
-
* Class constructor for in-memory TxPool. Initiates our transaction pool as a JS Map.
|
|
23
|
-
* @param log - A logger.
|
|
24
|
-
*/
|
|
25
|
-
constructor(telemetry?: TelemetryClient, log?: import("@aztec/foundation/log").Logger);
|
|
26
|
-
private countTx;
|
|
27
|
-
isEmpty(): Promise<boolean>;
|
|
28
|
-
markAsMined(txHashes: TxHash[], blockHeader: BlockHeader): Promise<void>;
|
|
29
|
-
markMinedAsPending(txHashes: TxHash[]): Promise<void>;
|
|
30
|
-
getPendingTxHashes(): Promise<TxHash[]>;
|
|
31
|
-
getMinedTxHashes(): Promise<[TxHash, BlockNumber][]>;
|
|
32
|
-
getPendingTxCount(): Promise<number>;
|
|
33
|
-
getTxStatus(txHash: TxHash): Promise<'pending' | 'mined' | 'deleted' | undefined>;
|
|
34
|
-
/**
|
|
35
|
-
* Checks if a transaction exists in the pool and returns it.
|
|
36
|
-
* @param txHash - The generated tx hash.
|
|
37
|
-
* @returns The transaction, if found, 'undefined' otherwise.
|
|
38
|
-
*/
|
|
39
|
-
getTxByHash(txHash: TxHash): Promise<Tx | undefined>;
|
|
40
|
-
getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]>;
|
|
41
|
-
hasTxs(txHashes: TxHash[]): Promise<boolean[]>;
|
|
42
|
-
hasTx(txHash: TxHash): Promise<boolean>;
|
|
43
|
-
getArchivedTxByHash(): Promise<Tx | undefined>;
|
|
44
|
-
/**
|
|
45
|
-
* Adds a list of transactions to the pool. Duplicates are ignored.
|
|
46
|
-
* @param txs - An array of txs to be added to the pool.
|
|
47
|
-
* @returns Empty promise.
|
|
48
|
-
*/
|
|
49
|
-
addTxs(txs: Tx[], opts?: {
|
|
50
|
-
source?: string;
|
|
51
|
-
}): Promise<number>;
|
|
52
|
-
/**
|
|
53
|
-
* Deletes transactions from the pool. Tx hashes that are not present are ignored.
|
|
54
|
-
* Mined transactions are soft-deleted with a timestamp, pending transactions are permanently deleted.
|
|
55
|
-
* @param txHashes - An array of tx hashes to be deleted from the tx pool.
|
|
56
|
-
* @returns Empty promise.
|
|
57
|
-
*/
|
|
58
|
-
deleteTxs(txHashes: TxHash[], opts?: {
|
|
59
|
-
permanently?: boolean;
|
|
60
|
-
}): Promise<void>;
|
|
61
|
-
/**
|
|
62
|
-
* Gets all the transactions stored in the pool.
|
|
63
|
-
* @returns Array of tx objects in the order they were added to the pool.
|
|
64
|
-
*/
|
|
65
|
-
getAllTxs(): Promise<Tx[]>;
|
|
66
|
-
/**
|
|
67
|
-
* Gets the hashes of all transactions currently in the tx pool.
|
|
68
|
-
* @returns An array of transaction hashes found in the tx pool.
|
|
69
|
-
*/
|
|
70
|
-
getAllTxHashes(): Promise<TxHash[]>;
|
|
71
|
-
updateConfig(_config: TxPoolOptions): void;
|
|
72
|
-
markTxsAsNonEvictable(_: TxHash[]): Promise<void>;
|
|
73
|
-
/**
|
|
74
|
-
* Permanently deletes deleted mined transactions from blocks up to and including the specified block number.
|
|
75
|
-
* @param blockNumber - Block number threshold. Deleted mined txs from this block or earlier will be permanently deleted.
|
|
76
|
-
* @returns The number of transactions permanently deleted.
|
|
77
|
-
*/
|
|
78
|
-
cleanupDeletedMinedTxs(blockNumber: BlockNumber): Promise<number>;
|
|
79
|
-
}
|
|
80
|
-
export {};
|
|
81
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5X3R4X3Bvb2wuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tZW1fcG9vbHMvdHhfcG9vbC9tZW1vcnlfdHhfcG9vbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFOUQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVqRSxPQUFPLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFNbkYsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7O0FBRXhFOztHQUVHO0FBQ0gscUJBQWEsY0FBZSxTQUFRLG1CQUE0RCxZQUFXLE1BQU07SUFtQjdHLE9BQU8sQ0FBQyxHQUFHO0lBbEJiOztPQUVHO0lBQ0gsT0FBTyxDQUFDLEdBQUcsQ0FBa0I7SUFDN0IsT0FBTyxDQUFDLFFBQVEsQ0FBMkI7SUFDM0MsT0FBTyxDQUFDLFVBQVUsQ0FBYztJQUNoQyxPQUFPLENBQUMsb0JBQW9CLENBQTJCO0lBRXZELE9BQU8sQ0FBQyx5QkFBeUIsQ0FBZ0M7SUFFakUsT0FBTyxDQUFDLE9BQU8sQ0FBMEI7SUFFekM7OztPQUdHO0lBQ0gsWUFDRSxTQUFTLEdBQUUsZUFBc0MsRUFDekMsR0FBRyx5Q0FBOEIsRUFTMUM7SUFFRCxPQUFPLENBQUMsT0FBTyxDQU9iO0lBRUssT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFakM7SUFFTSxXQUFXLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQW9COUU7SUFFTSxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWdCM0Q7SUFFWSxrQkFBa0IsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FXbkQ7SUFFTSxnQkFBZ0IsSUFBSSxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUkxRDtJQUVNLGlCQUFpQixJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FHMUM7SUFFTSxXQUFXLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsU0FBUyxHQUFHLE9BQU8sR0FBRyxTQUFTLEdBQUcsU0FBUyxDQUFDLENBYXZGO0lBRUQ7Ozs7T0FJRztJQUNJLFdBQVcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBRzFEO0lBRUQsWUFBWSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUU1RDtJQUNELE1BQU0sQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBRTdDO0lBRUssS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUc1QztJQUVNLG1CQUFtQixJQUFJLE9BQU8sQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBRXBEO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxHQUFFO1FBQUUsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFBO0tBQU8sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBd0J4RTtJQUVEOzs7OztPQUtHO0lBQ0ksU0FBUyxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtRQUFFLFdBQVcsQ0FBQyxFQUFFLE9BQU8sQ0FBQTtLQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQTJCcEY7SUFFRDs7O09BR0c7SUFDSSxTQUFTLElBQUksT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBRWhDO0lBRUQ7OztPQUdHO0lBQ0ksY0FBYyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUV6QztJQUVELFlBQVksQ0FBQyxPQUFPLEVBQUUsYUFBYSxHQUFHLElBQUksQ0FBRztJQUU3QyxxQkFBcUIsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUVoRDtJQUVEOzs7O09BSUc7SUFDSSxzQkFBc0IsQ0FBQyxXQUFXLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0EwQnZFO0NBQ0YifQ==
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memory_tx_pool.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/tx_pool/memory_tx_pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAMnF,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;;AAExE;;GAEG;AACH,qBAAa,cAAe,SAAQ,mBAA4D,YAAW,MAAM;IAmB7G,OAAO,CAAC,GAAG;IAlBb;;OAEG;IACH,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,oBAAoB,CAA2B;IAEvD,OAAO,CAAC,yBAAyB,CAAgC;IAEjE,OAAO,CAAC,OAAO,CAA0B;IAEzC;;;OAGG;IACH,YACE,SAAS,GAAE,eAAsC,EACzC,GAAG,yCAA8B,EAS1C;IAED,OAAO,CAAC,OAAO,CAOb;IAEK,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAEjC;IAEM,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB9E;IAEM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB3D;IAEY,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnD;IAEM,gBAAgB,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,CAI1D;IAEM,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAG1C;IAEM,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC,CAavF;IAED;;;;OAIG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAG1D;IAED,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,CAE5D;IACD,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAE7C;IAEK,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG5C;IAEM,mBAAmB,IAAI,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAEpD;IAED;;;;OAIG;IACI,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBxE;IAED;;;;;OAKG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BpF;IAED;;;OAGG;IACI,SAAS,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAEhC;IAED;;;OAGG;IACI,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAEzC;IAED,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAG;IAE7C,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhD;IAED;;;;OAIG;IACI,sBAAsB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BvE;CACF"}
|