@aztec/pxe 0.0.1-commit.e310a4c8 → 0.0.1-commit.e558bd1c

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 (57) hide show
  1. package/dest/block_synchronizer/block_synchronizer.d.ts +4 -2
  2. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  3. package/dest/block_synchronizer/block_synchronizer.js +7 -1
  4. package/dest/contract_function_simulator/contract_function_simulator.d.ts +4 -2
  5. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  6. package/dest/contract_function_simulator/contract_function_simulator.js +4 -2
  7. package/dest/contract_function_simulator/oracle/interfaces.d.ts +2 -2
  8. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  9. package/dest/contract_function_simulator/oracle/oracle.d.ts +2 -2
  10. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  11. package/dest/contract_function_simulator/oracle/oracle.js +20 -8
  12. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +4 -2
  13. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  14. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +6 -6
  15. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +5 -5
  16. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +20 -18
  18. package/dest/contract_sync/contract_sync_service.d.ts +41 -0
  19. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -0
  20. package/dest/contract_sync/contract_sync_service.js +82 -0
  21. package/dest/contract_sync/helpers.d.ts +28 -0
  22. package/dest/contract_sync/helpers.d.ts.map +1 -0
  23. package/dest/contract_sync/{index.js → helpers.js} +13 -12
  24. package/dest/debug/pxe_debug_utils.d.ts +12 -7
  25. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  26. package/dest/debug/pxe_debug_utils.js +16 -12
  27. package/dest/entrypoints/server/index.d.ts +2 -2
  28. package/dest/entrypoints/server/index.d.ts.map +1 -1
  29. package/dest/entrypoints/server/index.js +1 -1
  30. package/dest/logs/log_service.d.ts +2 -2
  31. package/dest/logs/log_service.d.ts.map +1 -1
  32. package/dest/logs/log_service.js +2 -4
  33. package/dest/oracle_version.d.ts +2 -2
  34. package/dest/oracle_version.js +2 -2
  35. package/dest/pxe.d.ts +2 -1
  36. package/dest/pxe.d.ts.map +1 -1
  37. package/dest/pxe.js +23 -12
  38. package/dest/storage/note_store/note_store.d.ts +1 -1
  39. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  40. package/dest/storage/note_store/note_store.js +3 -0
  41. package/package.json +25 -16
  42. package/src/block_synchronizer/block_synchronizer.ts +6 -0
  43. package/src/contract_function_simulator/contract_function_simulator.ts +3 -0
  44. package/src/contract_function_simulator/oracle/interfaces.ts +1 -1
  45. package/src/contract_function_simulator/oracle/oracle.ts +11 -4
  46. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +6 -5
  47. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +22 -19
  48. package/src/contract_sync/contract_sync_service.ts +129 -0
  49. package/src/contract_sync/{index.ts → helpers.ts} +15 -20
  50. package/src/debug/pxe_debug_utils.ts +46 -13
  51. package/src/entrypoints/server/index.ts +1 -1
  52. package/src/logs/log_service.ts +2 -2
  53. package/src/oracle_version.ts +2 -2
  54. package/src/pxe.ts +33 -13
  55. package/src/storage/note_store/note_store.ts +4 -0
  56. package/dest/contract_sync/index.d.ts +0 -23
  57. package/dest/contract_sync/index.d.ts.map +0 -1
@@ -1,10 +1,12 @@
1
- import { randomBytes } from '@aztec/foundation/crypto/random';
1
+ import type { FunctionCall } from '@aztec/stdlib/abi';
2
+ import type { AuthWitness } from '@aztec/stdlib/auth-witness';
3
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
2
4
  import type { NoteDao, NotesFilter } from '@aztec/stdlib/note';
3
- import type { BlockHeader } from '@aztec/stdlib/tx';
5
+ import type { BlockHeader, ContractOverrides } from '@aztec/stdlib/tx';
4
6
 
5
7
  import type { BlockSynchronizer } from '../block_synchronizer/block_synchronizer.js';
6
- import type { PXE } from '../pxe.js';
7
- import type { ContractStore } from '../storage/contract_store/contract_store.js';
8
+ import type { ContractFunctionSimulator } from '../contract_function_simulator/contract_function_simulator.js';
9
+ import type { ContractSyncService } from '../contract_sync/contract_sync_service.js';
8
10
  import type { AnchorBlockStore } from '../storage/index.js';
9
11
  import type { NoteStore } from '../storage/note_store/note_store.js';
10
12
 
@@ -13,20 +15,38 @@ import type { NoteStore } from '../storage/note_store/note_store.js';
13
15
  * No backwards compatibility or API stability should be expected. Use at your own risk.
14
16
  */
15
17
  export class PXEDebugUtils {
16
- #pxe!: PXE;
17
18
  #putJobInQueue!: <T>(job: (jobId: string) => Promise<T>) => Promise<T>;
19
+ #getSimulatorForTx!: (overrides?: { contracts?: ContractOverrides }) => ContractFunctionSimulator;
20
+ #simulateUtility!: (
21
+ contractFunctionSimulator: ContractFunctionSimulator,
22
+ call: FunctionCall,
23
+ authWitnesses: AuthWitness[] | undefined,
24
+ scopes: AztecAddress[] | undefined,
25
+ jobId: string,
26
+ ) => Promise<any>;
18
27
 
19
28
  constructor(
20
- private contractStore: ContractStore,
29
+ private contractSyncService: ContractSyncService,
21
30
  private noteStore: NoteStore,
22
31
  private blockStateSynchronizer: BlockSynchronizer,
23
32
  private anchorBlockStore: AnchorBlockStore,
24
33
  ) {}
25
34
 
26
35
  /** Not injected through constructor since they're are co-dependant */
27
- public setPXE(pxe: PXE, putJobInQueue: <T>(job: (jobId: string) => Promise<T>) => Promise<T>) {
28
- this.#pxe = pxe;
36
+ public setPXEHelpers(
37
+ putJobInQueue: <T>(job: (jobId: string) => Promise<T>) => Promise<T>,
38
+ getSimulatorForTx: (overrides?: { contracts?: ContractOverrides }) => ContractFunctionSimulator,
39
+ simulateUtility: (
40
+ contractFunctionSimulator: ContractFunctionSimulator,
41
+ call: FunctionCall,
42
+ authWitnesses: AuthWitness[] | undefined,
43
+ scopes: AztecAddress[] | undefined,
44
+ jobId: string,
45
+ ) => Promise<any>,
46
+ ) {
29
47
  this.#putJobInQueue = putJobInQueue;
48
+ this.#getSimulatorForTx = getSimulatorForTx;
49
+ this.#simulateUtility = simulateUtility;
30
50
  }
31
51
 
32
52
  /**
@@ -40,12 +60,25 @@ export class PXEDebugUtils {
40
60
  * @param filter - The filter to apply to the notes.
41
61
  * @returns The requested notes.
42
62
  */
43
- public async getNotes(filter: NotesFilter): Promise<NoteDao[]> {
44
- // We need to manually trigger private state sync to have a guarantee that all the notes are available.
45
- const call = await this.contractStore.getFunctionCall('sync_state', [], filter.contractAddress);
46
- await this.#pxe.simulateUtility(call);
63
+ public getNotes(filter: NotesFilter): Promise<NoteDao[]> {
64
+ return this.#putJobInQueue(async (jobId: string) => {
65
+ await this.blockStateSynchronizer.sync();
47
66
 
48
- return this.noteStore.getNotes(filter, randomBytes(8).toString('hex'));
67
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
68
+
69
+ const contractFunctionSimulator = this.#getSimulatorForTx();
70
+
71
+ await this.contractSyncService.ensureContractSynced(
72
+ filter.contractAddress,
73
+ null,
74
+ async privateSyncCall =>
75
+ await this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
76
+ anchorBlockHeader,
77
+ jobId,
78
+ );
79
+
80
+ return this.noteStore.getNotes(filter, jobId);
81
+ });
49
82
  }
50
83
 
51
84
  /** Returns the block header up to which the PXE has synced. */
@@ -7,4 +7,4 @@ export { NoteService } from '../../notes/note_service.js';
7
7
  export { ORACLE_VERSION } from '../../oracle_version.js';
8
8
  export { type PXECreationOptions } from '../pxe_creation_options.js';
9
9
  export { JobCoordinator } from '../../job_coordinator/job_coordinator.js';
10
- export { syncState } from '../../contract_sync/index.js';
10
+ export { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
@@ -108,12 +108,12 @@ export class LogService {
108
108
  );
109
109
  }
110
110
 
111
- public async syncTaggedLogs(
111
+ public async fetchTaggedLogs(
112
112
  contractAddress: AztecAddress,
113
113
  pendingTaggedLogArrayBaseSlot: Fr,
114
114
  scopes?: AztecAddress[],
115
115
  ) {
116
- this.log.verbose('Searching for tagged logs', { contract: contractAddress });
116
+ this.log.verbose(`Fetching tagged logs for ${contractAddress.toString()}`);
117
117
 
118
118
  // We only load logs from block up to and including the anchor block number
119
119
  const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
@@ -4,9 +4,9 @@
4
4
  ///
5
5
  /// @dev Whenever a contract function or Noir test is run, the `utilityAssertCompatibleOracleVersion` oracle is called
6
6
  /// and if the oracle version is incompatible an error is thrown.
7
- export const ORACLE_VERSION = 10;
7
+ export const ORACLE_VERSION = 11;
8
8
 
9
9
  /// This hash is computed as by hashing the Oracle interface and it is used to detect when the Oracle interface changes,
10
10
  /// which in turn implies that you need to update the ORACLE_VERSION constant in this file and in
11
11
  /// `noir-projects/aztec-nr/aztec/src/oracle/version.nr`.
12
- export const ORACLE_INTERFACE_HASH = 'a3b284ee5abff0509986d6d2fa78a3e6e2ec212325674de78355c5e70b05784c';
12
+ export const ORACLE_INTERFACE_HASH = '20c4d02d8cd5e448c11001a5f72ea2e0927630aeda75e537550872a9627bf40b';
package/src/pxe.ts CHANGED
@@ -59,7 +59,8 @@ import {
59
59
  generateSimulatedProvingResult,
60
60
  } from './contract_function_simulator/contract_function_simulator.js';
61
61
  import { ProxiedContractStoreFactory } from './contract_function_simulator/proxied_contract_data_source.js';
62
- import { ensureContractSynced, readCurrentClassId } from './contract_sync/index.js';
62
+ import { ContractSyncService } from './contract_sync/contract_sync_service.js';
63
+ import { readCurrentClassId } from './contract_sync/helpers.js';
63
64
  import { PXEDebugUtils } from './debug/pxe_debug_utils.js';
64
65
  import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
65
66
  import { PrivateEventFilterValidator } from './events/private_event_filter_validator.js';
@@ -102,6 +103,7 @@ export class PXE {
102
103
  private recipientTaggingStore: RecipientTaggingStore,
103
104
  private addressStore: AddressStore,
104
105
  private privateEventStore: PrivateEventStore,
106
+ private contractSyncService: ContractSyncService,
105
107
  private simulator: CircuitSimulator,
106
108
  private proverEnabled: boolean,
107
109
  private proofCreator: PrivateKernelProver,
@@ -149,6 +151,12 @@ export class PXE {
149
151
  const capsuleStore = new CapsuleStore(store);
150
152
  const keyStore = new KeyStore(store);
151
153
  const tipsStore = new L2TipsKVStore(store, 'pxe');
154
+ const contractSyncService = new ContractSyncService(
155
+ node,
156
+ contractStore,
157
+ noteStore,
158
+ createLogger('pxe:contract_sync', bindings),
159
+ );
152
160
  const synchronizer = new BlockSynchronizer(
153
161
  node,
154
162
  store,
@@ -156,6 +164,7 @@ export class PXE {
156
164
  noteStore,
157
165
  privateEventStore,
158
166
  tipsStore,
167
+ contractSyncService,
159
168
  config,
160
169
  bindings,
161
170
  );
@@ -167,9 +176,10 @@ export class PXE {
167
176
  recipientTaggingStore,
168
177
  privateEventStore,
169
178
  noteStore,
179
+ contractSyncService,
170
180
  ]);
171
181
 
172
- const debugUtils = new PXEDebugUtils(contractStore, noteStore, synchronizer, anchorBlockStore);
182
+ const debugUtils = new PXEDebugUtils(contractSyncService, noteStore, synchronizer, anchorBlockStore);
173
183
 
174
184
  const jobQueue = new SerialQueue();
175
185
 
@@ -186,6 +196,7 @@ export class PXE {
186
196
  recipientTaggingStore,
187
197
  addressStore,
188
198
  privateEventStore,
199
+ contractSyncService,
189
200
  simulator,
190
201
  proverEnabled,
191
202
  proofCreator,
@@ -196,7 +207,11 @@ export class PXE {
196
207
  debugUtils,
197
208
  );
198
209
 
199
- debugUtils.setPXE(pxe, pxe.#putInJobQueue.bind(pxe));
210
+ debugUtils.setPXEHelpers(
211
+ pxe.#putInJobQueue.bind(pxe),
212
+ pxe.#getSimulatorForTx.bind(pxe),
213
+ pxe.#simulateUtility.bind(pxe),
214
+ );
200
215
 
201
216
  pxe.jobQueue.start();
202
217
 
@@ -223,6 +238,7 @@ export class PXE {
223
238
  this.capsuleStore,
224
239
  this.privateEventStore,
225
240
  this.simulator,
241
+ this.contractSyncService,
226
242
  );
227
243
  }
228
244
 
@@ -297,13 +313,12 @@ export class PXE {
297
313
  try {
298
314
  const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
299
315
 
300
- await ensureContractSynced(
316
+ await this.contractSyncService.ensureContractSynced(
301
317
  contractAddress,
302
318
  functionSelector,
303
319
  privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
304
- this.node,
305
- this.contractStore,
306
320
  anchorBlockHeader,
321
+ jobId,
307
322
  );
308
323
 
309
324
  const result = await contractFunctionSimulator.run(
@@ -848,7 +863,14 @@ export class PXE {
848
863
  // Temporary: in case there are overrides, we have to skip the kernels or validations
849
864
  // will fail. Consider handing control to the user/wallet on whether they want to run them
850
865
  // or not.
851
- const skipKernels = overrides?.contracts !== undefined && Object.keys(overrides.contracts ?? {}).length > 0;
866
+ const overriddenContracts = overrides?.contracts ? new Set(Object.keys(overrides.contracts)) : undefined;
867
+ const hasOverriddenContracts = overriddenContracts !== undefined && overriddenContracts.size > 0;
868
+ const skipKernels = hasOverriddenContracts;
869
+
870
+ // Set overridden contracts on the sync service so it knows to skip syncing them
871
+ if (hasOverriddenContracts) {
872
+ this.contractSyncService.setOverriddenContracts(jobId, overriddenContracts);
873
+ }
852
874
 
853
875
  // Execution of private functions only; no proving, and no kernel logic.
854
876
  const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
@@ -970,13 +992,12 @@ export class PXE {
970
992
  const contractFunctionSimulator = this.#getSimulatorForTx();
971
993
 
972
994
  const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
973
- await ensureContractSynced(
995
+ await this.contractSyncService.ensureContractSynced(
974
996
  call.to,
975
997
  call.selector,
976
998
  privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
977
- this.node,
978
- this.contractStore,
979
999
  anchorBlockHeader,
1000
+ jobId,
980
1001
  );
981
1002
 
982
1003
  const executionResult = await this.#simulateUtility(
@@ -1040,14 +1061,13 @@ export class PXE {
1040
1061
 
1041
1062
  const contractFunctionSimulator = this.#getSimulatorForTx();
1042
1063
 
1043
- await ensureContractSynced(
1064
+ await this.contractSyncService.ensureContractSynced(
1044
1065
  filter.contractAddress,
1045
1066
  null,
1046
1067
  async privateSyncCall =>
1047
1068
  await this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
1048
- this.node,
1049
- this.contractStore,
1050
1069
  anchorBlockHeader,
1070
+ jobId,
1051
1071
  );
1052
1072
  });
1053
1073
 
@@ -220,6 +220,10 @@ export class NoteStore implements StagedStore {
220
220
  return Promise.resolve([]);
221
221
  }
222
222
 
223
+ if (nullifiers.some(n => n.l2BlockNumber === 0)) {
224
+ return Promise.reject(new Error('applyNullifiers: nullifiers cannot have been emitted at block 0'));
225
+ }
226
+
223
227
  return this.#withJobLock(jobId, () =>
224
228
  this.#store.transactionAsync(async () => {
225
229
  const notesToNullify = await Promise.all(
@@ -1,23 +0,0 @@
1
- import type { FunctionCall, FunctionSelector } from '@aztec/stdlib/abi';
2
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
- import type { ContractInstance } from '@aztec/stdlib/contract';
4
- import type { AztecNode } from '@aztec/stdlib/interfaces/client';
5
- import type { BlockHeader } from '@aztec/stdlib/tx';
6
- import type { ContractStore } from '../storage/contract_store/contract_store.js';
7
- /**
8
- * Read the current class id of a contract from the execution data provider or AztecNode. If not found, class id
9
- * from the instance is used.
10
- * @param contractAddress - The address of the contract to read the class id for.
11
- * @param instance - The instance of the contract.
12
- * @param aztecNode - The Aztec node to query for storage.
13
- * @param header - The header of the block at which to load the DelayedPublicMutable storing the class id.
14
- * @returns The current class id.
15
- */
16
- export declare function readCurrentClassId(contractAddress: AztecAddress, instance: ContractInstance, aztecNode: AztecNode, header: BlockHeader): Promise<import("@aztec/foundation/schemas").Fr>;
17
- export declare function syncState(contractAddress: AztecAddress, contractStore: ContractStore, functionToInvokeAfterSync: FunctionSelector | null, utilityExecutor: (privateSyncCall: FunctionCall) => Promise<any>): Promise<any>;
18
- /**
19
- * Ensures the contract's private state is synchronized and that the PXE holds the current class artifact for
20
- * the contract.
21
- */
22
- export declare function ensureContractSynced(contractAddress: AztecAddress, functionToInvokeAfterSync: FunctionSelector | null, utilityExecutor: (call: FunctionCall) => Promise<any>, aztecNode: AztecNode, contractStore: ContractStore, header: BlockHeader): Promise<void>;
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb250cmFjdF9zeW5jL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3hFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFL0QsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFcEQsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFFakY7Ozs7Ozs7O0dBUUc7QUFDSCx3QkFBc0Isa0JBQWtCLENBQ3RDLGVBQWUsRUFBRSxZQUFZLEVBQzdCLFFBQVEsRUFBRSxnQkFBZ0IsRUFDMUIsU0FBUyxFQUFFLFNBQVMsRUFDcEIsTUFBTSxFQUFFLFdBQVcsbURBYXBCO0FBRUQsd0JBQXNCLFNBQVMsQ0FDN0IsZUFBZSxFQUFFLFlBQVksRUFDN0IsYUFBYSxFQUFFLGFBQWEsRUFDNUIseUJBQXlCLEVBQUUsZ0JBQWdCLEdBQUcsSUFBSSxFQUNsRCxlQUFlLEVBQUUsQ0FBQyxlQUFlLEVBQUUsWUFBWSxLQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBYWpFO0FBMEJEOzs7R0FHRztBQUNILHdCQUFzQixvQkFBb0IsQ0FDeEMsZUFBZSxFQUFFLFlBQVksRUFDN0IseUJBQXlCLEVBQUUsZ0JBQWdCLEdBQUcsSUFBSSxFQUNsRCxlQUFlLEVBQUUsQ0FBQyxJQUFJLEVBQUUsWUFBWSxLQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFDckQsU0FBUyxFQUFFLFNBQVMsRUFDcEIsYUFBYSxFQUFFLGFBQWEsRUFDNUIsTUFBTSxFQUFFLFdBQVcsR0FDbEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUtmIn0=
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract_sync/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAEjF;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,eAAe,EAAE,YAAY,EAC7B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,WAAW,mDAapB;AAED,wBAAsB,SAAS,CAC7B,eAAe,EAAE,YAAY,EAC7B,aAAa,EAAE,aAAa,EAC5B,yBAAyB,EAAE,gBAAgB,GAAG,IAAI,EAClD,eAAe,EAAE,CAAC,eAAe,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,gBAajE;AA0BD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,eAAe,EAAE,YAAY,EAC7B,yBAAyB,EAAE,gBAAgB,GAAG,IAAI,EAClD,eAAe,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,EACrD,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAKf"}