@aztec/simulator 3.0.0-nightly.20251211 → 3.0.0-nightly.20251213

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.
@@ -32,13 +32,5 @@ export declare class SimpleContractDataSource implements ContractDataSource {
32
32
  registerContractFunctionSignatures(_signatures: string[]): Promise<void>;
33
33
  addContractClass(contractClass: ContractClassPublic): Promise<void>;
34
34
  addContractInstance(contractInstance: ContractInstanceWithAddress): Promise<void>;
35
- /**
36
- * FIXME: This is temporary
37
- * Helper method for fuzzer: registers a contract with raw bytecode at a given address.
38
- * Creates a minimal ContractClassPublic and ContractInstanceWithAddress.
39
- * @param address - The contract address
40
- * @param bytecode - The raw AVM bytecode
41
- */
42
- addContractWithBytecode(address: AztecAddress, bytecode: Buffer): Promise<void>;
43
35
  }
44
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlX2NvbnRyYWN0X2RhdGFfc291cmNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHVibGljL2ZpeHR1cmVzL3NpbXBsZV9jb250cmFjdF9kYXRhX3NvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFcEQsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM1RSxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBS25IOzs7Ozs7R0FNRztBQUNILHFCQUFhLHdCQUF5QixZQUFXLGtCQUFrQjtJQUMxRCxNQUFNLHlDQUErQztJQUc1RCxPQUFPLENBQUMsZUFBZSxDQUErQztJQUV0RSxPQUFPLENBQUMsaUJBQWlCLENBQXVEO0lBRWhGLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBNEM7SUFFckUsT0FBTyxDQUFDLGlCQUFpQixDQUFrQztJQUkzRDs7O09BR0c7SUFDRyxjQUFjLENBQ2xCLGdCQUFnQixFQUFFLGdCQUFnQixFQUNsQyxhQUFhLEVBQUUsbUJBQW1CLEVBQ2xDLGdCQUFnQixFQUFFLDJCQUEyQixpQkFLOUM7SUFFSyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsaUJBY2hFO0lBSUQsY0FBYyxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FFckM7SUFFRCxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsR0FBRyxTQUFTLENBQUMsQ0FFakU7SUFFRCxxQkFBcUIsQ0FBQyxHQUFHLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBRXREO0lBRUQsV0FBVyxDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixHQUFHLFNBQVMsQ0FBQyxDQUVuRjtJQUVELG1CQUFtQixJQUFJLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUVuQztJQUVLLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxDQVN0RjtJQUVLLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBYXpHO0lBRUQsa0NBQWtDLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFdkU7SUFFRCxnQkFBZ0IsQ0FBQyxhQUFhLEVBQUUsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUdsRTtJQUVELG1CQUFtQixDQUFDLGdCQUFnQixFQUFFLDJCQUEyQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHaEY7SUFFRDs7Ozs7O09BTUc7SUFDRyx1QkFBdUIsQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQTZCcEY7Q0FDRiJ9
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlX2NvbnRyYWN0X2RhdGFfc291cmNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHVibGljL2ZpeHR1cmVzL3NpbXBsZV9jb250cmFjdF9kYXRhX3NvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFcEQsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM1RSxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBSW5IOzs7Ozs7R0FNRztBQUNILHFCQUFhLHdCQUF5QixZQUFXLGtCQUFrQjtJQUMxRCxNQUFNLHlDQUErQztJQUc1RCxPQUFPLENBQUMsZUFBZSxDQUErQztJQUV0RSxPQUFPLENBQUMsaUJBQWlCLENBQXVEO0lBRWhGLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBNEM7SUFFckUsT0FBTyxDQUFDLGlCQUFpQixDQUFrQztJQUkzRDs7O09BR0c7SUFDRyxjQUFjLENBQ2xCLGdCQUFnQixFQUFFLGdCQUFnQixFQUNsQyxhQUFhLEVBQUUsbUJBQW1CLEVBQ2xDLGdCQUFnQixFQUFFLDJCQUEyQixpQkFLOUM7SUFFSyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsaUJBY2hFO0lBSUQsY0FBYyxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FFckM7SUFFRCxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsR0FBRyxTQUFTLENBQUMsQ0FFakU7SUFFRCxxQkFBcUIsQ0FBQyxHQUFHLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBRXREO0lBRUQsV0FBVyxDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixHQUFHLFNBQVMsQ0FBQyxDQUVuRjtJQUVELG1CQUFtQixJQUFJLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUVuQztJQUVLLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxDQVN0RjtJQUVLLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBYXpHO0lBRUQsa0NBQWtDLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFdkU7SUFFRCxnQkFBZ0IsQ0FBQyxhQUFhLEVBQUUsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUdsRTtJQUVELG1CQUFtQixDQUFDLGdCQUFnQixFQUFFLDJCQUEyQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHaEY7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"simple_contract_data_source.d.ts","sourceRoot":"","sources":["../../../src/public/fixtures/simple_contract_data_source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAEpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAKnH;;;;;;GAMG;AACH,qBAAa,wBAAyB,YAAW,kBAAkB;IAC1D,MAAM,yCAA+C;IAG5D,OAAO,CAAC,eAAe,CAA+C;IAEtE,OAAO,CAAC,iBAAiB,CAAuD;IAEhF,OAAO,CAAC,iBAAiB,CAA4C;IAErE,OAAO,CAAC,iBAAiB,CAAkC;IAI3D;;;OAGG;IACG,cAAc,CAClB,gBAAgB,EAAE,gBAAgB,EAClC,aAAa,EAAE,mBAAmB,EAClC,gBAAgB,EAAE,2BAA2B,iBAK9C;IAEK,mBAAmB,CAAC,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,gBAAgB,iBAchE;IAID,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAErC;IAED,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAEjE;IAED,qBAAqB,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAEtD;IAED,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAEnF;IAED,mBAAmB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAEnC;IAEK,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAStF;IAEK,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAazG;IAED,kCAAkC,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;IAED,gBAAgB,CAAC,aAAa,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE;IAED,mBAAmB,CAAC,gBAAgB,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhF;IAED;;;;;;OAMG;IACG,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BpF;CACF"}
1
+ {"version":3,"file":"simple_contract_data_source.d.ts","sourceRoot":"","sources":["../../../src/public/fixtures/simple_contract_data_source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAEpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAInH;;;;;;GAMG;AACH,qBAAa,wBAAyB,YAAW,kBAAkB;IAC1D,MAAM,yCAA+C;IAG5D,OAAO,CAAC,eAAe,CAA+C;IAEtE,OAAO,CAAC,iBAAiB,CAAuD;IAEhF,OAAO,CAAC,iBAAiB,CAA4C;IAErE,OAAO,CAAC,iBAAiB,CAAkC;IAI3D;;;OAGG;IACG,cAAc,CAClB,gBAAgB,EAAE,gBAAgB,EAClC,aAAa,EAAE,mBAAmB,EAClC,gBAAgB,EAAE,2BAA2B,iBAK9C;IAEK,mBAAmB,CAAC,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,gBAAgB,iBAchE;IAID,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAErC;IAED,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAEjE;IAED,qBAAqB,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAEtD;IAED,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAEnF;IAED,mBAAmB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAEnC;IAEK,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAStF;IAEK,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAazG;IAED,kCAAkC,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;IAED,gBAAgB,CAAC,aAAa,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE;IAED,mBAAmB,CAAC,gBAAgB,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhF;CACF"}
@@ -1,6 +1,4 @@
1
- import { Fr } from '@aztec/foundation/curves/bn254';
2
1
  import { createLogger } from '@aztec/foundation/log';
3
- import { PublicKeys } from '@aztec/stdlib/keys';
4
2
  import { getFunctionSelector } from '../avm/fixtures/utils.js';
5
3
  /**
6
4
  * This class is used during public/avm testing to function as a database of
@@ -94,37 +92,4 @@ import { getFunctionSelector } from '../avm/fixtures/utils.js';
94
92
  this.contractInstances.set(contractInstance.address.toString(), contractInstance);
95
93
  return Promise.resolve();
96
94
  }
97
- /**
98
- * FIXME: This is temporary
99
- * Helper method for fuzzer: registers a contract with raw bytecode at a given address.
100
- * Creates a minimal ContractClassPublic and ContractInstanceWithAddress.
101
- * @param address - The contract address
102
- * @param bytecode - The raw AVM bytecode
103
- */ async addContractWithBytecode(address, bytecode) {
104
- // Generate a deterministic class ID from the bytecode
105
- const classId = Fr.fromBufferReduce(bytecode.subarray(0, 32));
106
- // Create minimal ContractClassPublic
107
- const contractClass = {
108
- id: classId,
109
- version: 1,
110
- artifactHash: Fr.ZERO,
111
- privateFunctionsRoot: Fr.ZERO,
112
- privateFunctions: [],
113
- utilityFunctions: [],
114
- packedBytecode: bytecode
115
- };
116
- // Create minimal ContractInstanceWithAddress
117
- const contractInstance = {
118
- address,
119
- version: 1,
120
- salt: Fr.ZERO,
121
- deployer: address,
122
- currentContractClassId: classId,
123
- originalContractClassId: classId,
124
- initializationHash: Fr.ZERO,
125
- publicKeys: PublicKeys.default()
126
- };
127
- await this.addContractClass(contractClass);
128
- await this.addContractInstance(contractInstance);
129
- }
130
95
  }
@@ -0,0 +1,46 @@
1
+ import { AvmTxHint, type PublicTxResult } from '@aztec/stdlib/avm';
2
+ import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
3
+ import { GlobalVariables } from '@aztec/stdlib/tx';
4
+ import type { NativeWorldStateService } from '@aztec/world-state';
5
+ import { BaseAvmSimulationTester } from '../avm/fixtures/base_avm_simulation_tester.js';
6
+ import { SimpleContractDataSource } from '../fixtures/simple_contract_data_source.js';
7
+ /**
8
+ * Request structure for fuzzer simulation communication from C++.
9
+ * Matches the C++ FuzzerSimulationRequest struct
10
+ */
11
+ export declare class FuzzerSimulationRequest {
12
+ readonly wsDataDir: string;
13
+ readonly wsMapSizeKb: number;
14
+ readonly tx: AvmTxHint;
15
+ readonly globals: GlobalVariables;
16
+ readonly contractClasses: any[];
17
+ readonly contractInstances: [any, any][];
18
+ constructor(wsDataDir: string, wsMapSizeKb: number, tx: AvmTxHint, globals: GlobalVariables, contractClasses: any[], contractInstances: [any, any][]);
19
+ static fromPlainObject(obj: any): FuzzerSimulationRequest;
20
+ }
21
+ /**
22
+ * A simulator class for the AVM fuzzer that extends BaseAvmSimulationTester.
23
+ * It provides methods for registering contracts from C++ msgpack data and simulating transactions.
24
+ */
25
+ export declare class AvmFuzzerSimulator extends BaseAvmSimulationTester {
26
+ private simulator;
27
+ constructor(merkleTrees: MerkleTreeWriteOperations, contractDataSource: SimpleContractDataSource, globals: GlobalVariables);
28
+ /**
29
+ * Static factory method to create an AvmFuzzerSimulator.
30
+ */
31
+ static create(worldStateService: NativeWorldStateService, globals: GlobalVariables): Promise<AvmFuzzerSimulator>;
32
+ /**
33
+ * Simulate a transaction from a C++ AvmTxHint.
34
+ */
35
+ simulate(txHint: AvmTxHint): Promise<PublicTxResult>;
36
+ /**
37
+ * Add a contract class from C++ raw msgpack data.
38
+ */
39
+ addContractClassFromCpp(rawClass: any): Promise<void>;
40
+ /**
41
+ * Add a contract instance from C++ raw msgpack data.
42
+ * This also inserts the contract address nullifier into the nullifier tree.
43
+ */
44
+ addContractInstanceFromCpp(rawAddress: any, rawInstance: any): Promise<void>;
45
+ }
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXZtX2Z1enplcl9zaW11bGF0b3IuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wdWJsaWMvZnV6emluZy9hdm1fZnV6emVyX3NpbXVsYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFTQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFZbkUsT0FBTyxLQUFLLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRSxPQUFPLEVBQWUsZUFBZSxFQUF1RCxNQUFNLGtCQUFrQixDQUFDO0FBQ3JILE9BQU8sS0FBSyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sK0NBQStDLENBQUM7QUFDeEYsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFJdEY7OztHQUdHO0FBQ0gscUJBQWEsdUJBQXVCO2FBRWhCLFNBQVMsRUFBRSxNQUFNO2FBQ2pCLFdBQVcsRUFBRSxNQUFNO2FBQ25CLEVBQUUsRUFBRSxTQUFTO2FBQ2IsT0FBTyxFQUFFLGVBQWU7YUFDeEIsZUFBZSxFQUFFLEdBQUcsRUFBRTthQUN0QixpQkFBaUIsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRTtJQU5qRCxZQUNrQixTQUFTLEVBQUUsTUFBTSxFQUNqQixXQUFXLEVBQUUsTUFBTSxFQUNuQixFQUFFLEVBQUUsU0FBUyxFQUNiLE9BQU8sRUFBRSxlQUFlLEVBQ3hCLGVBQWUsRUFBRSxHQUFHLEVBQUUsRUFDdEIsaUJBQWlCLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFDN0M7SUFFSixNQUFNLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxHQUFHLEdBQUcsdUJBQXVCLENBWXhEO0NBQ0Y7QUFtSEQ7OztHQUdHO0FBQ0gscUJBQWEsa0JBQW1CLFNBQVEsdUJBQXVCO0lBQzdELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBRXJDLFlBQ0UsV0FBVyxFQUFFLHlCQUF5QixFQUN0QyxrQkFBa0IsRUFBRSx3QkFBd0IsRUFDNUMsT0FBTyxFQUFFLGVBQWUsRUFXekI7SUFFRDs7T0FFRztJQUNILE9BQW9CLE1BQU0sQ0FDeEIsaUJBQWlCLEVBQUUsdUJBQXVCLEVBQzFDLE9BQU8sRUFBRSxlQUFlLEdBQ3ZCLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUk3QjtJQUVEOztPQUVHO0lBQ1UsUUFBUSxDQUFDLE1BQU0sRUFBRSxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUdoRTtJQUVEOztPQUVHO0lBQ1UsdUJBQXVCLENBQUMsUUFBUSxFQUFFLEdBQUcsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBR2pFO0lBRUQ7OztPQUdHO0lBQ1UsMEJBQTBCLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsR0FBRyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FJeEY7Q0FDRiJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avm_fuzzer_simulator.d.ts","sourceRoot":"","sources":["../../../src/public/fuzzing/avm_fuzzer_simulator.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAYnE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAe,eAAe,EAAuD,MAAM,kBAAkB,CAAC;AACrH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAItF;;;GAGG;AACH,qBAAa,uBAAuB;aAEhB,SAAS,EAAE,MAAM;aACjB,WAAW,EAAE,MAAM;aACnB,EAAE,EAAE,SAAS;aACb,OAAO,EAAE,eAAe;aACxB,eAAe,EAAE,GAAG,EAAE;aACtB,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;IANjD,YACkB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,eAAe,EACxB,eAAe,EAAE,GAAG,EAAE,EACtB,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAC7C;IAEJ,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,uBAAuB,CAYxD;CACF;AAmHD;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,uBAAuB;IAC7D,OAAO,CAAC,SAAS,CAAoB;IAErC,YACE,WAAW,EAAE,yBAAyB,EACtC,kBAAkB,EAAE,wBAAwB,EAC5C,OAAO,EAAE,eAAe,EAWzB;IAED;;OAEG;IACH,OAAoB,MAAM,CACxB,iBAAiB,EAAE,uBAAuB,EAC1C,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,kBAAkB,CAAC,CAI7B;IAED;;OAEG;IACU,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,CAGhE;IAED;;OAEG;IACU,uBAAuB,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE;IAED;;;OAGG;IACU,0BAA0B,CAAC,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxF;CACF"}
@@ -1,28 +1,47 @@
1
- import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX } from '@aztec/constants';
1
+ import { MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX } from '@aztec/constants';
2
2
  import { padArrayEnd } from '@aztec/foundation/collection';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
+ import { AvmTxHint } from '@aztec/stdlib/avm';
4
5
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
- import { siloNullifier } from '@aztec/stdlib/hash';
6
+ import { contractClassPublicFromPlainObject, contractInstanceWithAddressFromPlainObject } from '@aztec/stdlib/contract';
6
7
  import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
7
8
  import { PrivateLog } from '@aztec/stdlib/logs';
8
9
  import { ScopedL2ToL1Message } from '@aztec/stdlib/messaging';
9
10
  import { ChonkProof } from '@aztec/stdlib/proofs';
10
- import { MerkleTreeId } from '@aztec/stdlib/trees';
11
- import { BlockHeader, HashedValues, Tx, TxConstantData, TxContext, TxHash } from '@aztec/stdlib/tx';
12
- // Registers a contract by inserting its address nullifier into the nullifier tree
13
- export async function registerContract(merkleTrees, contractAddress) {
14
- const contractAddressNullifier = await siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), contractAddress.toField());
15
- await merkleTrees.sequentialInsert(MerkleTreeId.NULLIFIER_TREE, [
16
- contractAddressNullifier.toBuffer()
17
- ]);
11
+ import { BlockHeader, GlobalVariables, HashedValues, Tx, TxConstantData, TxContext, TxHash } from '@aztec/stdlib/tx';
12
+ import { BaseAvmSimulationTester } from '../avm/fixtures/base_avm_simulation_tester.js';
13
+ import { SimpleContractDataSource } from '../fixtures/simple_contract_data_source.js';
14
+ import { PublicContractsDB } from '../public_db_sources.js';
15
+ import { PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
16
+ /**
17
+ * Request structure for fuzzer simulation communication from C++.
18
+ * Matches the C++ FuzzerSimulationRequest struct
19
+ */ export class FuzzerSimulationRequest {
20
+ wsDataDir;
21
+ wsMapSizeKb;
22
+ tx;
23
+ globals;
24
+ contractClasses;
25
+ contractInstances;
26
+ constructor(wsDataDir, wsMapSizeKb, tx, globals, contractClasses, contractInstances){
27
+ this.wsDataDir = wsDataDir;
28
+ this.wsMapSizeKb = wsMapSizeKb;
29
+ this.tx = tx;
30
+ this.globals = globals;
31
+ this.contractClasses = contractClasses;
32
+ this.contractInstances = contractInstances;
33
+ }
34
+ static fromPlainObject(obj) {
35
+ if (obj instanceof FuzzerSimulationRequest) {
36
+ return obj;
37
+ }
38
+ return new FuzzerSimulationRequest(obj.wsDataDir, obj.wsMapSizeKb, AvmTxHint.fromPlainObject(obj.tx), GlobalVariables.fromPlainObject(obj.globals), obj.contractClasses, obj.contractInstances);
39
+ }
18
40
  }
19
41
  /**
20
42
  * Creates a TypeScript Tx object from a deserialized C++ Tx (AvmTxHint-like structure).
21
43
  * This allows using PublicTxSimulator.simulate() with fuzzer-generated transactions.
22
- *
23
- * @param cppTx - Deserialized C++ Tx from msgpack (matches AvmTxHint structure)
24
- * @returns A TypeScript Tx suitable for PublicTxSimulator
25
- */ export async function createFuzzerTx(cppTx) {
44
+ */ async function createTxFromHint(cppTx) {
26
45
  // Create TxHash from the C++ tx hash string
27
46
  if (!cppTx.hash) {
28
47
  throw new Error(`cppTx.hash is undefined. Keys: ${Object.keys(cppTx || {}).join(', ')}`);
@@ -48,8 +67,6 @@ export async function registerContract(merkleTrees, contractAddress) {
48
67
  // Build TxConstantData
49
68
  const constants = new TxConstantData(BlockHeader.empty(), txContext, Fr.ZERO, Fr.ZERO);
50
69
  const data = new PrivateKernelTailCircuitPublicInputs(constants, cppTx.gasUsedByPrivate, cppTx.feePayer, 0n, forPublic, undefined);
51
- // todo(ilyas): I don't think we need to construct this, but keeping for now - the hashing could get costly with
52
- // large number of enqueued calls or large calldata so keep an eye on this!
53
70
  // Build publicFunctionCalldata from all enqueued calls
54
71
  // Calldata is already Fr[] after AvmTxHint.fromPlainObject
55
72
  const publicFunctionCalldata = [];
@@ -73,3 +90,47 @@ export async function registerContract(merkleTrees, contractAddress) {
73
90
  // Create the Tx
74
91
  return new Tx(txHash, data, ChonkProof.empty(), contractClassLogFields, publicFunctionCalldata);
75
92
  }
93
+ /**
94
+ * A simulator class for the AVM fuzzer that extends BaseAvmSimulationTester.
95
+ * It provides methods for registering contracts from C++ msgpack data and simulating transactions.
96
+ */ export class AvmFuzzerSimulator extends BaseAvmSimulationTester {
97
+ simulator;
98
+ constructor(merkleTrees, contractDataSource, globals){
99
+ super(contractDataSource, merkleTrees);
100
+ const contractsDb = new PublicContractsDB(contractDataSource);
101
+ this.simulator = new PublicTxSimulator(merkleTrees, contractsDb, globals, {
102
+ skipFeeEnforcement: true,
103
+ collectDebugLogs: false,
104
+ collectHints: false,
105
+ collectStatistics: false,
106
+ collectCallMetadata: false
107
+ });
108
+ }
109
+ /**
110
+ * Static factory method to create an AvmFuzzerSimulator.
111
+ */ static async create(worldStateService, globals) {
112
+ const contractDataSource = new SimpleContractDataSource();
113
+ const merkleTrees = await worldStateService.fork();
114
+ return new AvmFuzzerSimulator(merkleTrees, contractDataSource, globals);
115
+ }
116
+ /**
117
+ * Simulate a transaction from a C++ AvmTxHint.
118
+ */ async simulate(txHint) {
119
+ const tx = await createTxFromHint(txHint);
120
+ return await this.simulator.simulate(tx);
121
+ }
122
+ /**
123
+ * Add a contract class from C++ raw msgpack data.
124
+ */ async addContractClassFromCpp(rawClass) {
125
+ const contractClass = contractClassPublicFromPlainObject(rawClass);
126
+ await this.contractDataSource.addContractClass(contractClass);
127
+ }
128
+ /**
129
+ * Add a contract instance from C++ raw msgpack data.
130
+ * This also inserts the contract address nullifier into the nullifier tree.
131
+ */ async addContractInstanceFromCpp(rawAddress, rawInstance) {
132
+ const address = AztecAddress.fromPlainObject(rawAddress);
133
+ const instance = contractInstanceWithAddressFromPlainObject(address, rawInstance);
134
+ await this.addContractInstance(instance);
135
+ }
136
+ }
@@ -1,13 +1,10 @@
1
1
  import { EthAddress } from '@aztec/foundation/eth-address';
2
- import { AvmTxHint, deserializeFromMessagePack } from '@aztec/stdlib/avm';
3
- import { GlobalVariables } from '@aztec/stdlib/tx';
2
+ import { deserializeFromMessagePack, serializeWithMessagePack } from '@aztec/stdlib/avm';
3
+ import { TreeSnapshots } from '@aztec/stdlib/tx';
4
4
  import { NativeWorldStateService } from '@aztec/world-state';
5
5
  import { writeSync } from 'fs';
6
6
  import { createInterface } from 'readline';
7
- import { SimpleContractDataSource } from '../fixtures/simple_contract_data_source.js';
8
- import { PublicContractsDB } from '../public_db_sources.js';
9
- import { PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
10
- import { createFuzzerTx, registerContract } from './helpers.js';
7
+ import { AvmFuzzerSimulator, FuzzerSimulationRequest } from './avm_fuzzer_simulator.js';
11
8
  // This cache holds opened world states to avoid reopening them for each invocation.
12
9
  // It's a map so that in the future we could support multiple world states (if we had multiple fuzzers).
13
10
  const worldStateCache = new Map();
@@ -26,33 +23,18 @@ async function openExistingWorldState(dataDir, mapSizeKb) {
26
23
  worldStateCache.set(dataDir, ws);
27
24
  return ws;
28
25
  }
29
- async function simulateWithPublicTxSimulator(dataDir, mapSizeKb, bytecode, cppTx, cppGlobals) {
26
+ async function simulateWithFuzzer(dataDir, mapSizeKb, txHint, globals, rawContractClasses, rawContractInstances) {
30
27
  const worldStateService = await openExistingWorldState(dataDir, mapSizeKb);
31
- const merkleTrees = await worldStateService.fork();
32
- // todo(ilyas): enable this once we can handle multiple bytecodes across multiple enqueued calls
33
- // Concat all the enqueued calls, extract the de-duplicated contract addresses so we can register them
34
- //const teardownCalls = cppTx.teardownEnqueuedCall ? [cppTx.teardownEnqueuedCall] : [];
35
- //const contractAddresses = new Set([...cppTx.setupEnqueuedCalls, ...cppTx.appLogicEnqueuedCalls, ...teardownCalls].map(
36
- // call => call.request.contractAddress,
37
- //));
38
- //await Promise.all([...contractAddresses].map(addr => registerContract(merkleTrees, addr)));
39
- //await Promise.all(
40
- // [...contractAddresses].map(addr => contractDataSource.addContractWithBytecode(addr, bytecode)),
41
- //);
42
- const contractAddress = cppTx.appLogicEnqueuedCalls[0].request.contractAddress;
43
- await registerContract(merkleTrees, contractAddress);
44
- const contractDataSource = new SimpleContractDataSource();
45
- await contractDataSource.addContractWithBytecode(contractAddress, bytecode);
46
- const contractsDb = new PublicContractsDB(contractDataSource);
47
- const publicTxSimulator = new PublicTxSimulator(merkleTrees, contractsDb, cppGlobals, {
48
- skipFeeEnforcement: true,
49
- collectDebugLogs: false,
50
- collectHints: false,
51
- collectStatistics: false,
52
- collectCallMetadata: false
53
- });
54
- const tx = await createFuzzerTx(cppTx);
55
- const result = await publicTxSimulator.simulate(tx);
28
+ const simulator = await AvmFuzzerSimulator.create(worldStateService, globals);
29
+ // Register contract classes from C++
30
+ for (const rawClass of rawContractClasses){
31
+ await simulator.addContractClassFromCpp(rawClass);
32
+ }
33
+ // Register contract instances from C++
34
+ for (const [rawAddress, rawInstance] of rawContractInstances){
35
+ await simulator.addContractInstanceFromCpp(rawAddress, rawInstance);
36
+ }
37
+ const result = await simulator.simulate(txHint);
56
38
  const output = result.getAppLogicReturnValues().flatMap((rv)=>rv?.values?.filter((v)=>v != null) ?? []);
57
39
  return {
58
40
  reverted: !result.revertCode.isOK(),
@@ -61,51 +43,30 @@ async function simulateWithPublicTxSimulator(dataDir, mapSizeKb, bytecode, cppTx
61
43
  publicInputs: result.publicInputs
62
44
  };
63
45
  }
64
- async function executeFromJson(jsonLine) {
46
+ async function execute(base64Line) {
65
47
  try {
66
- const input = JSON.parse(jsonLine.trim());
67
- if (!input.bytecode || !input.ws_data_dir || !input.ws_map_size_kb || !input.tx || !input.globals) {
68
- writeSync(process.stdout.fd, 'Error: JSON must contain "bytecode", "ws_data_dir", "ws_map_size_kb", "tx", and "globals" fields\n');
69
- return;
70
- }
71
- const bytecode = Buffer.from(input.bytecode, 'base64');
72
- const rawTx = deserializeFromMessagePack(Buffer.from(input.tx, 'base64'));
73
- const tx = AvmTxHint.fromPlainObject(rawTx);
74
- const rawGlobals = deserializeFromMessagePack(Buffer.from(input.globals, 'base64'));
75
- const globals = GlobalVariables.fromPlainObject(rawGlobals);
76
- const result = await simulateWithPublicTxSimulator(input.ws_data_dir, input.ws_map_size_kb, bytecode, tx, globals);
77
- // todo(ilyas): Would be nice to serialize entire publicInputs for comparison, but it was extremely slow.
78
- // Serialize endTreeSnapshots for comparison with C++ simulator
79
- const endTreeSnapshots = {
80
- l1ToL2MessageTree: {
81
- root: result.publicInputs.endTreeSnapshots.l1ToL2MessageTree.root.toString(),
82
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.l1ToL2MessageTree.nextAvailableLeafIndex
83
- },
84
- noteHashTree: {
85
- root: result.publicInputs.endTreeSnapshots.noteHashTree.root.toString(),
86
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.noteHashTree.nextAvailableLeafIndex
87
- },
88
- nullifierTree: {
89
- root: result.publicInputs.endTreeSnapshots.nullifierTree.root.toString(),
90
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.nullifierTree.nextAvailableLeafIndex
91
- },
92
- publicDataTree: {
93
- root: result.publicInputs.endTreeSnapshots.publicDataTree.root.toString(),
94
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.publicDataTree.nextAvailableLeafIndex
95
- }
96
- };
97
- writeSync(process.stdout.fd, JSON.stringify({
48
+ // Decode base64 and deserialize the entire request from msgpack
49
+ const buffer = Buffer.from(base64Line.trim(), 'base64');
50
+ const rawRequest = deserializeFromMessagePack(buffer);
51
+ const request = FuzzerSimulationRequest.fromPlainObject(rawRequest);
52
+ // Run the TS simulation
53
+ const result = await simulateWithFuzzer(request.wsDataDir, request.wsMapSizeKb, request.tx, request.globals, request.contractClasses, request.contractInstances);
54
+ // Serialize the result to msgpack and encode it in base64 for output
55
+ const resultBuffer = serializeWithMessagePack({
98
56
  reverted: result.reverted,
99
- output: result.output.map((v)=>v?.toString() ?? '0'),
100
- revertReason: result.revertReason,
101
- endTreeSnapshots
102
- }) + '\n');
57
+ output: result.output,
58
+ revertReason: result.revertReason ?? '',
59
+ endTreeSnapshots: result.publicInputs.endTreeSnapshots
60
+ });
61
+ writeSync(process.stdout.fd, resultBuffer.toString('base64') + '\n');
103
62
  } catch (error) {
104
- writeSync(process.stdout.fd, JSON.stringify({
63
+ const errorResult = serializeWithMessagePack({
105
64
  reverted: true,
106
65
  output: [],
107
- revertReason: error.message
108
- }) + '\n');
66
+ revertReason: `Unexpected Error ${error.message}`,
67
+ endTreeSnapshots: TreeSnapshots.empty()
68
+ });
69
+ writeSync(process.stdout.fd, errorResult.toString('base64') + '\n');
109
70
  }
110
71
  }
111
72
  function mainLoop() {
@@ -115,7 +76,7 @@ function mainLoop() {
115
76
  });
116
77
  rl.on('line', (line)=>{
117
78
  if (line.trim()) {
118
- void executeFromJson(line);
79
+ void execute(line);
119
80
  }
120
81
  });
121
82
  rl.on('close', ()=>process.exit(0));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/simulator",
3
- "version": "3.0.0-nightly.20251211",
3
+ "version": "3.0.0-nightly.20251213",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./server": "./dest/server.js",
@@ -21,7 +21,7 @@
21
21
  "build:dev": "../scripts/tsc.sh --watch",
22
22
  "clean": "rm -rf ./dest .tsbuildinfo",
23
23
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
24
- "build:fuzzer": "tsgo src/public/fuzzing/avm_simulator_bin.ts --outDir dest --rootDir src --module nodenext --moduleResolution nodenext --skipLibCheck --ignoreConfig"
24
+ "build:fuzzer": "yarn clean && ../scripts/tsc.sh"
25
25
  },
26
26
  "inherits": [
27
27
  "../package.common.json"
@@ -64,26 +64,26 @@
64
64
  ]
65
65
  },
66
66
  "dependencies": {
67
- "@aztec/constants": "3.0.0-nightly.20251211",
68
- "@aztec/foundation": "3.0.0-nightly.20251211",
69
- "@aztec/native": "3.0.0-nightly.20251211",
70
- "@aztec/noir-acvm_js": "3.0.0-nightly.20251211",
71
- "@aztec/noir-noirc_abi": "3.0.0-nightly.20251211",
72
- "@aztec/noir-protocol-circuits-types": "3.0.0-nightly.20251211",
73
- "@aztec/noir-types": "3.0.0-nightly.20251211",
74
- "@aztec/protocol-contracts": "3.0.0-nightly.20251211",
75
- "@aztec/stdlib": "3.0.0-nightly.20251211",
76
- "@aztec/telemetry-client": "3.0.0-nightly.20251211",
77
- "@aztec/world-state": "3.0.0-nightly.20251211",
67
+ "@aztec/constants": "3.0.0-nightly.20251213",
68
+ "@aztec/foundation": "3.0.0-nightly.20251213",
69
+ "@aztec/native": "3.0.0-nightly.20251213",
70
+ "@aztec/noir-acvm_js": "3.0.0-nightly.20251213",
71
+ "@aztec/noir-noirc_abi": "3.0.0-nightly.20251213",
72
+ "@aztec/noir-protocol-circuits-types": "3.0.0-nightly.20251213",
73
+ "@aztec/noir-types": "3.0.0-nightly.20251213",
74
+ "@aztec/protocol-contracts": "3.0.0-nightly.20251213",
75
+ "@aztec/stdlib": "3.0.0-nightly.20251213",
76
+ "@aztec/telemetry-client": "3.0.0-nightly.20251213",
77
+ "@aztec/world-state": "3.0.0-nightly.20251213",
78
78
  "lodash.clonedeep": "^4.5.0",
79
79
  "lodash.merge": "^4.6.2",
80
80
  "tslib": "^2.4.0"
81
81
  },
82
82
  "devDependencies": {
83
- "@aztec/kv-store": "3.0.0-nightly.20251211",
84
- "@aztec/merkle-tree": "3.0.0-nightly.20251211",
85
- "@aztec/noir-contracts.js": "3.0.0-nightly.20251211",
86
- "@aztec/noir-test-contracts.js": "3.0.0-nightly.20251211",
83
+ "@aztec/kv-store": "3.0.0-nightly.20251213",
84
+ "@aztec/merkle-tree": "3.0.0-nightly.20251213",
85
+ "@aztec/noir-contracts.js": "3.0.0-nightly.20251213",
86
+ "@aztec/noir-test-contracts.js": "3.0.0-nightly.20251213",
87
87
  "@jest/globals": "^30.0.0",
88
88
  "@types/jest": "^30.0.0",
89
89
  "@types/lodash.clonedeep": "^4.5.7",
@@ -4,7 +4,6 @@ import { createLogger } from '@aztec/foundation/log';
4
4
  import type { ContractArtifact, FunctionSelector } from '@aztec/stdlib/abi';
5
5
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
6
6
  import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
7
- import { PublicKeys } from '@aztec/stdlib/keys';
8
7
 
9
8
  import { getFunctionSelector } from '../avm/fixtures/utils.js';
10
9
 
@@ -120,42 +119,4 @@ export class SimpleContractDataSource implements ContractDataSource {
120
119
  this.contractInstances.set(contractInstance.address.toString(), contractInstance);
121
120
  return Promise.resolve();
122
121
  }
123
-
124
- /**
125
- * FIXME: This is temporary
126
- * Helper method for fuzzer: registers a contract with raw bytecode at a given address.
127
- * Creates a minimal ContractClassPublic and ContractInstanceWithAddress.
128
- * @param address - The contract address
129
- * @param bytecode - The raw AVM bytecode
130
- */
131
- async addContractWithBytecode(address: AztecAddress, bytecode: Buffer): Promise<void> {
132
- // Generate a deterministic class ID from the bytecode
133
- const classId = Fr.fromBufferReduce(bytecode.subarray(0, 32));
134
-
135
- // Create minimal ContractClassPublic
136
- const contractClass: ContractClassPublic = {
137
- id: classId,
138
- version: 1 as const,
139
- artifactHash: Fr.ZERO,
140
- privateFunctionsRoot: Fr.ZERO,
141
- privateFunctions: [],
142
- utilityFunctions: [],
143
- packedBytecode: bytecode,
144
- };
145
-
146
- // Create minimal ContractInstanceWithAddress
147
- const contractInstance: ContractInstanceWithAddress = {
148
- address,
149
- version: 1 as const,
150
- salt: Fr.ZERO,
151
- deployer: address, // Use the contract address as deployer
152
- currentContractClassId: classId,
153
- originalContractClassId: classId,
154
- initializationHash: Fr.ZERO,
155
- publicKeys: PublicKeys.default(),
156
- };
157
-
158
- await this.addContractClass(contractClass);
159
- await this.addContractInstance(contractInstance);
160
- }
161
122
  }
@@ -1,5 +1,4 @@
1
1
  import {
2
- CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
3
2
  MAX_ENQUEUED_CALLS_PER_TX,
4
3
  MAX_L2_TO_L1_MSGS_PER_TX,
5
4
  MAX_NOTE_HASHES_PER_TX,
@@ -8,9 +7,9 @@ import {
8
7
  } from '@aztec/constants';
9
8
  import { padArrayEnd } from '@aztec/foundation/collection';
10
9
  import { Fr } from '@aztec/foundation/curves/bn254';
11
- import type { AvmTxHint } from '@aztec/stdlib/avm';
10
+ import { AvmTxHint, type PublicTxResult } from '@aztec/stdlib/avm';
12
11
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
13
- import { siloNullifier } from '@aztec/stdlib/hash';
12
+ import { contractClassPublicFromPlainObject, contractInstanceWithAddressFromPlainObject } from '@aztec/stdlib/contract';
14
13
  import {
15
14
  PartialPrivateTailPublicInputsForPublic,
16
15
  PrivateKernelTailCircuitPublicInputs,
@@ -20,29 +19,49 @@ import {
20
19
  import { PrivateLog } from '@aztec/stdlib/logs';
21
20
  import { ScopedL2ToL1Message } from '@aztec/stdlib/messaging';
22
21
  import { ChonkProof } from '@aztec/stdlib/proofs';
23
- import { MerkleTreeId, type MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
24
- import { BlockHeader, HashedValues, Tx, TxConstantData, TxContext, TxHash } from '@aztec/stdlib/tx';
25
-
26
- // Registers a contract by inserting its address nullifier into the nullifier tree
27
- export async function registerContract(
28
- merkleTrees: MerkleTreeWriteOperations,
29
- contractAddress: AztecAddress,
30
- ): Promise<void> {
31
- const contractAddressNullifier = await siloNullifier(
32
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
33
- contractAddress.toField(),
34
- );
35
- await merkleTrees.sequentialInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()]);
22
+ import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
23
+ import { BlockHeader, GlobalVariables, HashedValues, Tx, TxConstantData, TxContext, TxHash } from '@aztec/stdlib/tx';
24
+ import type { NativeWorldStateService } from '@aztec/world-state';
25
+
26
+ import { BaseAvmSimulationTester } from '../avm/fixtures/base_avm_simulation_tester.js';
27
+ import { SimpleContractDataSource } from '../fixtures/simple_contract_data_source.js';
28
+ import { PublicContractsDB } from '../public_db_sources.js';
29
+ import { PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
30
+
31
+ /**
32
+ * Request structure for fuzzer simulation communication from C++.
33
+ * Matches the C++ FuzzerSimulationRequest struct
34
+ */
35
+ export class FuzzerSimulationRequest {
36
+ constructor(
37
+ public readonly wsDataDir: string,
38
+ public readonly wsMapSizeKb: number,
39
+ public readonly tx: AvmTxHint,
40
+ public readonly globals: GlobalVariables,
41
+ public readonly contractClasses: any[], // Raw, processed by addContractClassFromCpp
42
+ public readonly contractInstances: [any, any][], // Raw pairs [address, instance]
43
+ ) {}
44
+
45
+ static fromPlainObject(obj: any): FuzzerSimulationRequest {
46
+ if (obj instanceof FuzzerSimulationRequest) {
47
+ return obj;
48
+ }
49
+ return new FuzzerSimulationRequest(
50
+ obj.wsDataDir,
51
+ obj.wsMapSizeKb,
52
+ AvmTxHint.fromPlainObject(obj.tx),
53
+ GlobalVariables.fromPlainObject(obj.globals),
54
+ obj.contractClasses,
55
+ obj.contractInstances,
56
+ );
57
+ }
36
58
  }
37
59
 
38
60
  /**
39
61
  * Creates a TypeScript Tx object from a deserialized C++ Tx (AvmTxHint-like structure).
40
62
  * This allows using PublicTxSimulator.simulate() with fuzzer-generated transactions.
41
- *
42
- * @param cppTx - Deserialized C++ Tx from msgpack (matches AvmTxHint structure)
43
- * @returns A TypeScript Tx suitable for PublicTxSimulator
44
63
  */
45
- export async function createFuzzerTx(cppTx: AvmTxHint): Promise<Tx> {
64
+ async function createTxFromHint(cppTx: AvmTxHint): Promise<Tx> {
46
65
  // Create TxHash from the C++ tx hash string
47
66
  if (!cppTx.hash) {
48
67
  throw new Error(`cppTx.hash is undefined. Keys: ${Object.keys(cppTx || {}).join(', ')}`);
@@ -116,8 +135,6 @@ export async function createFuzzerTx(cppTx: AvmTxHint): Promise<Tx> {
116
135
  undefined, // forRollup - not needed for public simulation
117
136
  );
118
137
 
119
- // todo(ilyas): I don't think we need to construct this, but keeping for now - the hashing could get costly with
120
- // large number of enqueued calls or large calldata so keep an eye on this!
121
138
  // Build publicFunctionCalldata from all enqueued calls
122
139
  // Calldata is already Fr[] after AvmTxHint.fromPlainObject
123
140
  const publicFunctionCalldata: HashedValues[] = [];
@@ -152,3 +169,65 @@ export async function createFuzzerTx(cppTx: AvmTxHint): Promise<Tx> {
152
169
  publicFunctionCalldata,
153
170
  );
154
171
  }
172
+
173
+ /**
174
+ * A simulator class for the AVM fuzzer that extends BaseAvmSimulationTester.
175
+ * It provides methods for registering contracts from C++ msgpack data and simulating transactions.
176
+ */
177
+ export class AvmFuzzerSimulator extends BaseAvmSimulationTester {
178
+ private simulator: PublicTxSimulator;
179
+
180
+ constructor(
181
+ merkleTrees: MerkleTreeWriteOperations,
182
+ contractDataSource: SimpleContractDataSource,
183
+ globals: GlobalVariables,
184
+ ) {
185
+ super(contractDataSource, merkleTrees);
186
+ const contractsDb = new PublicContractsDB(contractDataSource);
187
+ this.simulator = new PublicTxSimulator(merkleTrees, contractsDb, globals, {
188
+ skipFeeEnforcement: true,
189
+ collectDebugLogs: false,
190
+ collectHints: false,
191
+ collectStatistics: false,
192
+ collectCallMetadata: false,
193
+ });
194
+ }
195
+
196
+ /**
197
+ * Static factory method to create an AvmFuzzerSimulator.
198
+ */
199
+ public static async create(
200
+ worldStateService: NativeWorldStateService,
201
+ globals: GlobalVariables,
202
+ ): Promise<AvmFuzzerSimulator> {
203
+ const contractDataSource = new SimpleContractDataSource();
204
+ const merkleTrees = await worldStateService.fork();
205
+ return new AvmFuzzerSimulator(merkleTrees, contractDataSource, globals);
206
+ }
207
+
208
+ /**
209
+ * Simulate a transaction from a C++ AvmTxHint.
210
+ */
211
+ public async simulate(txHint: AvmTxHint): Promise<PublicTxResult> {
212
+ const tx = await createTxFromHint(txHint);
213
+ return await this.simulator.simulate(tx);
214
+ }
215
+
216
+ /**
217
+ * Add a contract class from C++ raw msgpack data.
218
+ */
219
+ public async addContractClassFromCpp(rawClass: any): Promise<void> {
220
+ const contractClass = contractClassPublicFromPlainObject(rawClass);
221
+ await this.contractDataSource.addContractClass(contractClass);
222
+ }
223
+
224
+ /**
225
+ * Add a contract instance from C++ raw msgpack data.
226
+ * This also inserts the contract address nullifier into the nullifier tree.
227
+ */
228
+ public async addContractInstanceFromCpp(rawAddress: any, rawInstance: any): Promise<void> {
229
+ const address = AztecAddress.fromPlainObject(rawAddress);
230
+ const instance = contractInstanceWithAddressFromPlainObject(address, rawInstance);
231
+ await this.addContractInstance(instance);
232
+ }
233
+ }
@@ -1,16 +1,18 @@
1
1
  import { Fr } from '@aztec/foundation/curves/bn254';
2
2
  import { EthAddress } from '@aztec/foundation/eth-address';
3
- import { AvmCircuitPublicInputs, AvmTxHint, deserializeFromMessagePack } from '@aztec/stdlib/avm';
4
- import { GlobalVariables } from '@aztec/stdlib/tx';
3
+ import {
4
+ AvmCircuitPublicInputs,
5
+ type AvmTxHint,
6
+ deserializeFromMessagePack,
7
+ serializeWithMessagePack,
8
+ } from '@aztec/stdlib/avm';
9
+ import { GlobalVariables, TreeSnapshots } from '@aztec/stdlib/tx';
5
10
  import { NativeWorldStateService } from '@aztec/world-state';
6
11
 
7
12
  import { writeSync } from 'fs';
8
13
  import { createInterface } from 'readline';
9
14
 
10
- import { SimpleContractDataSource } from '../fixtures/simple_contract_data_source.js';
11
- import { PublicContractsDB } from '../public_db_sources.js';
12
- import { PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
13
- import { createFuzzerTx, registerContract } from './helpers.js';
15
+ import { AvmFuzzerSimulator, FuzzerSimulationRequest } from './avm_fuzzer_simulator.js';
14
16
 
15
17
  // This cache holds opened world states to avoid reopening them for each invocation.
16
18
  // It's a map so that in the future we could support multiple world states (if we had multiple fuzzers).
@@ -34,46 +36,33 @@ async function openExistingWorldState(dataDir: string, mapSizeKb: number): Promi
34
36
  return ws;
35
37
  }
36
38
 
37
- async function simulateWithPublicTxSimulator(
39
+ async function simulateWithFuzzer(
38
40
  dataDir: string,
39
41
  mapSizeKb: number,
40
- bytecode: Buffer,
41
- cppTx: AvmTxHint,
42
- cppGlobals: GlobalVariables,
42
+ txHint: AvmTxHint,
43
+ globals: GlobalVariables,
44
+ rawContractClasses: any[], // Replace these when we are moving contract classes to TS
45
+ rawContractInstances: [any, any][], // Replace these when we are moving contract instances to TS
43
46
  ): Promise<{ reverted: boolean; output: Fr[]; revertReason?: string; publicInputs: AvmCircuitPublicInputs }> {
44
47
  const worldStateService = await openExistingWorldState(dataDir, mapSizeKb);
45
- const merkleTrees = await worldStateService.fork();
46
-
47
- // todo(ilyas): enable this once we can handle multiple bytecodes across multiple enqueued calls
48
- // Concat all the enqueued calls, extract the de-duplicated contract addresses so we can register them
49
- //const teardownCalls = cppTx.teardownEnqueuedCall ? [cppTx.teardownEnqueuedCall] : [];
50
- //const contractAddresses = new Set([...cppTx.setupEnqueuedCalls, ...cppTx.appLogicEnqueuedCalls, ...teardownCalls].map(
51
- // call => call.request.contractAddress,
52
- //));
53
- //await Promise.all([...contractAddresses].map(addr => registerContract(merkleTrees, addr)));
54
- //await Promise.all(
55
- // [...contractAddresses].map(addr => contractDataSource.addContractWithBytecode(addr, bytecode)),
56
- //);
57
-
58
- const contractAddress = cppTx.appLogicEnqueuedCalls[0].request.contractAddress;
59
- await registerContract(merkleTrees, contractAddress);
60
- const contractDataSource = new SimpleContractDataSource();
61
- await contractDataSource.addContractWithBytecode(contractAddress, bytecode);
62
-
63
- const contractsDb = new PublicContractsDB(contractDataSource);
64
-
65
- const publicTxSimulator = new PublicTxSimulator(merkleTrees, contractsDb, cppGlobals, {
66
- skipFeeEnforcement: true,
67
- collectDebugLogs: false,
68
- collectHints: false,
69
- collectStatistics: false,
70
- collectCallMetadata: false,
71
- });
72
48
 
73
- const tx = await createFuzzerTx(cppTx);
74
- const result = await publicTxSimulator.simulate(tx);
49
+ const simulator = await AvmFuzzerSimulator.create(worldStateService, globals);
50
+
51
+ // Register contract classes from C++
52
+ for (const rawClass of rawContractClasses) {
53
+ await simulator.addContractClassFromCpp(rawClass);
54
+ }
55
+
56
+ // Register contract instances from C++
57
+ for (const [rawAddress, rawInstance] of rawContractInstances) {
58
+ await simulator.addContractInstanceFromCpp(rawAddress, rawInstance);
59
+ }
60
+
61
+ const result = await simulator.simulate(txHint);
75
62
 
76
- const output = result.getAppLogicReturnValues().flatMap(rv => rv?.values?.filter(v => v != null) ?? []);
63
+ const output = result
64
+ .getAppLogicReturnValues()
65
+ .flatMap((rv: { values?: Fr[] } | undefined) => rv?.values?.filter((v: Fr | null | undefined) => v != null) ?? []);
77
66
 
78
67
  return {
79
68
  reverted: !result.revertCode.isOK(),
@@ -83,64 +72,39 @@ async function simulateWithPublicTxSimulator(
83
72
  };
84
73
  }
85
74
 
86
- async function executeFromJson(jsonLine: string): Promise<void> {
75
+ async function execute(base64Line: string): Promise<void> {
87
76
  try {
88
- const input = JSON.parse(jsonLine.trim());
89
- if (!input.bytecode || !input.ws_data_dir || !input.ws_map_size_kb || !input.tx || !input.globals) {
90
- writeSync(
91
- process.stdout.fd,
92
- 'Error: JSON must contain "bytecode", "ws_data_dir", "ws_map_size_kb", "tx", and "globals" fields\n',
93
- );
94
- return;
95
- }
96
-
97
- const bytecode = Buffer.from(input.bytecode, 'base64');
98
- const rawTx: object = deserializeFromMessagePack(Buffer.from(input.tx, 'base64'));
99
- const tx = AvmTxHint.fromPlainObject(rawTx);
100
- const rawGlobals = deserializeFromMessagePack(Buffer.from(input.globals, 'base64'));
101
- const globals = GlobalVariables.fromPlainObject(rawGlobals);
102
-
103
- const result = await simulateWithPublicTxSimulator(input.ws_data_dir, input.ws_map_size_kb, bytecode, tx, globals);
104
-
105
- // todo(ilyas): Would be nice to serialize entire publicInputs for comparison, but it was extremely slow.
106
- // Serialize endTreeSnapshots for comparison with C++ simulator
107
- const endTreeSnapshots = {
108
- l1ToL2MessageTree: {
109
- root: result.publicInputs.endTreeSnapshots.l1ToL2MessageTree.root.toString(),
110
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.l1ToL2MessageTree.nextAvailableLeafIndex,
111
- },
112
- noteHashTree: {
113
- root: result.publicInputs.endTreeSnapshots.noteHashTree.root.toString(),
114
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.noteHashTree.nextAvailableLeafIndex,
115
- },
116
- nullifierTree: {
117
- root: result.publicInputs.endTreeSnapshots.nullifierTree.root.toString(),
118
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.nullifierTree.nextAvailableLeafIndex,
119
- },
120
- publicDataTree: {
121
- root: result.publicInputs.endTreeSnapshots.publicDataTree.root.toString(),
122
- nextAvailableLeafIndex: result.publicInputs.endTreeSnapshots.publicDataTree.nextAvailableLeafIndex,
123
- },
124
- };
125
-
126
- writeSync(
127
- process.stdout.fd,
128
- JSON.stringify({
129
- reverted: result.reverted,
130
- output: result.output.map(v => v?.toString() ?? '0'),
131
- revertReason: result.revertReason,
132
- endTreeSnapshots,
133
- }) + '\n',
77
+ // Decode base64 and deserialize the entire request from msgpack
78
+ const buffer = Buffer.from(base64Line.trim(), 'base64');
79
+ const rawRequest = deserializeFromMessagePack(buffer);
80
+ const request = FuzzerSimulationRequest.fromPlainObject(rawRequest);
81
+
82
+ // Run the TS simulation
83
+ const result = await simulateWithFuzzer(
84
+ request.wsDataDir,
85
+ request.wsMapSizeKb,
86
+ request.tx,
87
+ request.globals,
88
+ request.contractClasses,
89
+ request.contractInstances,
134
90
  );
91
+
92
+ // Serialize the result to msgpack and encode it in base64 for output
93
+ const resultBuffer = serializeWithMessagePack({
94
+ reverted: result.reverted,
95
+ output: result.output,
96
+ revertReason: result.revertReason ?? '',
97
+ endTreeSnapshots: result.publicInputs.endTreeSnapshots,
98
+ });
99
+ writeSync(process.stdout.fd, resultBuffer.toString('base64') + '\n');
135
100
  } catch (error: any) {
136
- writeSync(
137
- process.stdout.fd,
138
- JSON.stringify({
139
- reverted: true,
140
- output: [],
141
- revertReason: error.message,
142
- }) + '\n',
143
- );
101
+ const errorResult = serializeWithMessagePack({
102
+ reverted: true,
103
+ output: [] as string[],
104
+ revertReason: `Unexpected Error ${error.message}`,
105
+ endTreeSnapshots: TreeSnapshots.empty(),
106
+ });
107
+ writeSync(process.stdout.fd, errorResult.toString('base64') + '\n');
144
108
  }
145
109
  }
146
110
 
@@ -148,7 +112,7 @@ function mainLoop() {
148
112
  const rl = createInterface({ input: process.stdin, terminal: false });
149
113
  rl.on('line', (line: string) => {
150
114
  if (line.trim()) {
151
- void executeFromJson(line);
115
+ void execute(line);
152
116
  }
153
117
  });
154
118
  rl.on('close', () => process.exit(0));
@@ -1,14 +0,0 @@
1
- import type { AvmTxHint } from '@aztec/stdlib/avm';
2
- import { AztecAddress } from '@aztec/stdlib/aztec-address';
3
- import { type MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
4
- import { Tx } from '@aztec/stdlib/tx';
5
- export declare function registerContract(merkleTrees: MerkleTreeWriteOperations, contractAddress: AztecAddress): Promise<void>;
6
- /**
7
- * Creates a TypeScript Tx object from a deserialized C++ Tx (AvmTxHint-like structure).
8
- * This allows using PublicTxSimulator.simulate() with fuzzer-generated transactions.
9
- *
10
- * @param cppTx - Deserialized C++ Tx from msgpack (matches AvmTxHint structure)
11
- * @returns A TypeScript Tx suitable for PublicTxSimulator
12
- */
13
- export declare function createFuzzerTx(cppTx: AvmTxHint): Promise<Tx>;
14
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3B1YmxpYy9mdXp6aW5nL2hlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBVUEsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBVzNELE9BQU8sRUFBZ0IsS0FBSyx5QkFBeUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25GLE9BQU8sRUFBNkIsRUFBRSxFQUFxQyxNQUFNLGtCQUFrQixDQUFDO0FBR3BHLHdCQUFzQixnQkFBZ0IsQ0FDcEMsV0FBVyxFQUFFLHlCQUF5QixFQUN0QyxlQUFlLEVBQUUsWUFBWSxHQUM1QixPQUFPLENBQUMsSUFBSSxDQUFDLENBTWY7QUFFRDs7Ozs7O0dBTUc7QUFDSCx3QkFBc0IsY0FBYyxDQUFDLEtBQUssRUFBRSxTQUFTLEdBQUcsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQTZHbEUifQ==
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/public/fuzzing/helpers.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAW3D,OAAO,EAAgB,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAA6B,EAAE,EAAqC,MAAM,kBAAkB,CAAC;AAGpG,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,yBAAyB,EACtC,eAAe,EAAE,YAAY,GAC5B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,CA6GlE"}