@aztec/simulator 0.69.1 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/acvm/acvm.d.ts +1 -2
- package/dest/acvm/acvm.d.ts.map +1 -1
- package/dest/acvm/acvm.js +12 -2
- package/dest/acvm/index.d.ts +1 -1
- package/dest/acvm/index.d.ts.map +1 -1
- package/dest/acvm/index.js +2 -2
- package/dest/acvm/oracle/oracle.d.ts +13 -5
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +46 -21
- package/dest/acvm/oracle/typed_oracle.d.ts +8 -17
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +16 -23
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +7 -1
- package/dest/avm/fixtures/index.d.ts +2 -3
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +4 -4
- package/dest/avm/journal/journal.d.ts +3 -4
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +11 -10
- package/dest/avm/journal/nullifiers.d.ts +1 -1
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.d.ts +1 -1
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/client/client_execution_context.d.ts +29 -18
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +42 -29
- package/dest/client/db_oracle.d.ts +24 -16
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/db_oracle.js +1 -1
- package/dest/client/execution_note_cache.d.ts +27 -4
- package/dest/client/execution_note_cache.d.ts.map +1 -1
- package/dest/client/execution_note_cache.js +62 -12
- package/dest/client/index.d.ts +11 -3
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +11 -4
- package/dest/client/private_execution.d.ts +3 -2
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +9 -7
- package/dest/client/simulator.d.ts +4 -2
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +13 -8
- package/dest/client/unconstrained_execution.d.ts +2 -1
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +6 -4
- package/dest/client/view_data_oracle.d.ts +4 -10
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +17 -19
- package/dest/common/hashed_values_cache.d.ts +28 -0
- package/dest/common/hashed_values_cache.d.ts.map +1 -0
- package/dest/common/{packed_values_cache.js → hashed_values_cache.js} +22 -22
- package/dest/common/index.d.ts +1 -1
- package/dest/common/index.js +1 -1
- package/dest/common/message_load_oracle_inputs.d.ts +15 -0
- package/dest/common/message_load_oracle_inputs.d.ts.map +1 -0
- package/dest/common/message_load_oracle_inputs.js +15 -0
- package/dest/common/simulation_provider.d.ts +19 -0
- package/dest/common/simulation_provider.d.ts.map +1 -0
- package/dest/common/simulation_provider.js +27 -0
- package/dest/common.d.ts +2 -0
- package/dest/common.d.ts.map +1 -0
- package/dest/common.js +2 -0
- package/dest/providers/acvm_native.d.ts +5 -2
- package/dest/providers/acvm_native.d.ts.map +1 -1
- package/dest/providers/acvm_native.js +5 -2
- package/dest/providers/acvm_wasm.d.ts +8 -2
- package/dest/providers/acvm_wasm.d.ts.map +1 -1
- package/dest/providers/acvm_wasm.js +31 -5
- package/dest/providers/acvm_wasm_with_blobs.d.ts +14 -2
- package/dest/providers/acvm_wasm_with_blobs.d.ts.map +1 -1
- package/dest/providers/acvm_wasm_with_blobs.js +25 -5
- package/dest/providers/factory.d.ts +1 -1
- package/dest/providers/factory.d.ts.map +1 -1
- package/dest/providers/factory.js +1 -1
- package/dest/providers/index.d.ts +1 -1
- package/dest/providers/index.d.ts.map +1 -1
- package/dest/providers/index.js +2 -2
- package/dest/public/db_interfaces.d.ts +1 -1
- package/dest/public/db_interfaces.d.ts.map +1 -1
- package/dest/public/fixtures/index.d.ts +3 -3
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +48 -18
- package/dest/public/public_db_sources.d.ts +2 -1
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +2 -2
- package/dest/public/public_processor.js +2 -2
- package/dest/public/public_tx_context.d.ts +3 -7
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +7 -20
- package/dest/public/public_tx_simulator.js +5 -5
- package/{src/index.ts → dest/server.d.ts} +1 -2
- package/dest/server.d.ts.map +1 -0
- package/dest/server.js +6 -0
- package/package.json +11 -12
- package/src/acvm/acvm.ts +20 -3
- package/src/acvm/index.ts +1 -1
- package/src/acvm/oracle/oracle.ts +48 -27
- package/src/acvm/oracle/typed_oracle.ts +20 -24
- package/src/avm/avm_simulator.ts +6 -0
- package/src/avm/fixtures/index.ts +5 -4
- package/src/avm/journal/journal.ts +9 -9
- package/src/avm/journal/nullifiers.ts +1 -1
- package/src/avm/journal/public_storage.ts +1 -1
- package/src/client/client_execution_context.ts +47 -30
- package/src/client/db_oracle.ts +25 -17
- package/src/client/execution_note_cache.ts +67 -14
- package/src/client/index.ts +11 -3
- package/src/client/private_execution.ts +21 -17
- package/src/client/simulator.ts +20 -7
- package/src/client/unconstrained_execution.ts +17 -13
- package/src/client/view_data_oracle.ts +23 -19
- package/src/common/hashed_values_cache.ts +55 -0
- package/src/common/index.ts +1 -1
- package/src/common/message_load_oracle_inputs.ts +15 -0
- package/src/common/simulation_provider.ts +45 -0
- package/src/common.ts +1 -0
- package/src/providers/acvm_native.ts +12 -2
- package/src/providers/acvm_wasm.ts +36 -9
- package/src/providers/acvm_wasm_with_blobs.ts +35 -10
- package/src/providers/factory.ts +1 -1
- package/src/providers/index.ts +1 -1
- package/src/public/db_interfaces.ts +1 -1
- package/src/public/fixtures/index.ts +62 -26
- package/src/public/public_db_sources.ts +3 -6
- package/src/public/public_processor.ts +1 -1
- package/src/public/public_tx_context.ts +6 -19
- package/src/public/public_tx_simulator.ts +4 -4
- package/{dest/index.d.ts → src/server.ts} +0 -3
- package/dest/common/packed_values_cache.d.ts +0 -28
- package/dest/common/packed_values_cache.d.ts.map +0 -1
- package/dest/index.d.ts.map +0 -1
- package/dest/index.js +0 -8
- package/dest/providers/simulation_provider.d.ts +0 -9
- package/dest/providers/simulation_provider.d.ts.map +0 -1
- package/dest/providers/simulation_provider.js +0 -2
- package/src/common/packed_values_cache.ts +0 -55
- package/src/providers/simulation_provider.ts +0 -10
|
@@ -2,12 +2,15 @@ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types';
|
|
|
2
2
|
import { FunctionSelector, NoteSelector } from '@aztec/foundation/abi';
|
|
3
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
5
6
|
|
|
6
7
|
import { type ACVMField } from '../acvm_types.js';
|
|
7
8
|
import { frToBoolean, frToNumber, fromACVMField } from '../deserialize.js';
|
|
8
9
|
import { toACVMField } from '../serialize.js';
|
|
9
10
|
import { type TypedOracle } from './typed_oracle.js';
|
|
10
11
|
|
|
12
|
+
const logger = createLogger('simulator:acvm:oracle');
|
|
13
|
+
|
|
11
14
|
/**
|
|
12
15
|
* A data source that has all the apis required by Aztec.nr.
|
|
13
16
|
*/
|
|
@@ -19,25 +22,20 @@ export class Oracle {
|
|
|
19
22
|
return toACVMField(val);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
async
|
|
23
|
-
const
|
|
24
|
-
return toACVMField(
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async packArguments(_length: ACVMField[], values: ACVMField[]): Promise<ACVMField> {
|
|
28
|
-
const packed = await this.typedOracle.packArgumentsArray(values.map(fromACVMField));
|
|
29
|
-
return toACVMField(packed);
|
|
25
|
+
async storeArrayInExecutionCache(values: ACVMField[]): Promise<ACVMField> {
|
|
26
|
+
const hash = await this.typedOracle.storeArrayInExecutionCache(values.map(fromACVMField));
|
|
27
|
+
return toACVMField(hash);
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
// Since the argument is a slice, noir automatically adds a length field to oracle call.
|
|
33
|
-
async
|
|
34
|
-
const
|
|
35
|
-
return toACVMField(
|
|
31
|
+
async storeInExecutionCache(_length: ACVMField[], values: ACVMField[]): Promise<ACVMField> {
|
|
32
|
+
const hash = await this.typedOracle.storeInExecutionCache(values.map(fromACVMField));
|
|
33
|
+
return toACVMField(hash);
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
async
|
|
39
|
-
const
|
|
40
|
-
return
|
|
36
|
+
async loadFromExecutionCache([returnsHash]: ACVMField[]): Promise<ACVMField[]> {
|
|
37
|
+
const values = await this.typedOracle.loadFromExecutionCache(fromACVMField(returnsHash));
|
|
38
|
+
return values.map(toACVMField);
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
async getBlockNumber(): Promise<ACVMField> {
|
|
@@ -92,19 +90,6 @@ export class Oracle {
|
|
|
92
90
|
return witness.map(toACVMField);
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
async getSiblingPath(
|
|
96
|
-
[blockNumber]: ACVMField[],
|
|
97
|
-
[treeId]: ACVMField[],
|
|
98
|
-
[leafIndex]: ACVMField[],
|
|
99
|
-
): Promise<ACVMField[]> {
|
|
100
|
-
const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
|
|
101
|
-
const parsedTreeId = frToNumber(fromACVMField(treeId));
|
|
102
|
-
const parsedLeafIndex = fromACVMField(leafIndex);
|
|
103
|
-
|
|
104
|
-
const path = await this.typedOracle.getSiblingPath(parsedBlockNumber, parsedTreeId, parsedLeafIndex);
|
|
105
|
-
return path.map(toACVMField);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
93
|
async getNullifierMembershipWitness(
|
|
109
94
|
[blockNumber]: ACVMField[],
|
|
110
95
|
[nullifier]: ACVMField[], // nullifier, we try to find the witness for (to prove inclusion)
|
|
@@ -268,6 +253,11 @@ export class Oracle {
|
|
|
268
253
|
return toACVMField(0);
|
|
269
254
|
}
|
|
270
255
|
|
|
256
|
+
async notifyCreatedNullifier([innerNullifier]: ACVMField[]): Promise<ACVMField> {
|
|
257
|
+
await this.typedOracle.notifyCreatedNullifier(fromACVMField(innerNullifier));
|
|
258
|
+
return toACVMField(0);
|
|
259
|
+
}
|
|
260
|
+
|
|
271
261
|
async checkNullifierExists([innerNullifier]: ACVMField[]): Promise<ACVMField> {
|
|
272
262
|
const exists = await this.typedOracle.checkNullifierExists(fromACVMField(innerNullifier));
|
|
273
263
|
return toACVMField(exists);
|
|
@@ -393,4 +383,35 @@ export class Oracle {
|
|
|
393
383
|
async syncNotes() {
|
|
394
384
|
await this.typedOracle.syncNotes();
|
|
395
385
|
}
|
|
386
|
+
|
|
387
|
+
async store([contract]: ACVMField[], [key]: ACVMField[], values: ACVMField[]) {
|
|
388
|
+
const processedContract = AztecAddress.fromField(fromACVMField(contract));
|
|
389
|
+
const processedKey = fromACVMField(key);
|
|
390
|
+
const processedValues = values.map(fromACVMField);
|
|
391
|
+
logger.debug(`Storing data for key ${processedKey} in contract ${processedContract}. Data: [${processedValues}]`);
|
|
392
|
+
await this.typedOracle.store(processedContract, processedKey, processedValues);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Load data from pxe db.
|
|
397
|
+
* @param contract - The contract address.
|
|
398
|
+
* @param key - The key to load.
|
|
399
|
+
* @param tSize - The size of the serialized object to return.
|
|
400
|
+
* @returns The data found flag and the serialized object concatenated in one array.
|
|
401
|
+
*/
|
|
402
|
+
async load([contract]: ACVMField[], [key]: ACVMField[], [tSize]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> {
|
|
403
|
+
const processedContract = AztecAddress.fromField(fromACVMField(contract));
|
|
404
|
+
const processedKey = fromACVMField(key);
|
|
405
|
+
const values = await this.typedOracle.load(processedContract, processedKey);
|
|
406
|
+
if (values === null) {
|
|
407
|
+
// No data was found so we set the data-found flag to 0 and we pad with zeros get the correct return size.
|
|
408
|
+
const processedTSize = frToNumber(fromACVMField(tSize));
|
|
409
|
+
logger.debug(`No data found for key ${processedKey} in contract ${processedContract}`);
|
|
410
|
+
return [toACVMField(0), Array(processedTSize).fill(toACVMField(0))];
|
|
411
|
+
} else {
|
|
412
|
+
// Data was found so we set the data-found flag to 1 and return it along with the data.
|
|
413
|
+
logger.debug(`Returning data for key ${processedKey} in contract ${processedContract}. Data: [${values}]`);
|
|
414
|
+
return [toACVMField(1), values.map(toACVMField)];
|
|
415
|
+
}
|
|
416
|
+
}
|
|
396
417
|
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
type NoteStatus,
|
|
6
6
|
type NullifierMembershipWitness,
|
|
7
7
|
type PublicDataWitness,
|
|
8
|
-
type SiblingPath,
|
|
9
8
|
type UnencryptedL2Log,
|
|
10
9
|
} from '@aztec/circuit-types';
|
|
11
10
|
import {
|
|
@@ -19,6 +18,8 @@ import { type FunctionSelector, type NoteSelector } from '@aztec/foundation/abi'
|
|
|
19
18
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
20
19
|
import { Fr } from '@aztec/foundation/fields';
|
|
21
20
|
|
|
21
|
+
import { type MessageLoadOracleInputs } from '../../common/message_load_oracle_inputs.js';
|
|
22
|
+
|
|
22
23
|
/**
|
|
23
24
|
* Information about a note needed during execution.
|
|
24
25
|
*/
|
|
@@ -39,19 +40,6 @@ export interface NoteData {
|
|
|
39
40
|
index?: bigint;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
export class MessageLoadOracleInputs<N extends number> {
|
|
43
|
-
constructor(
|
|
44
|
-
/** The index of the message commitment in the merkle tree. */
|
|
45
|
-
public index: bigint,
|
|
46
|
-
/** The path in the merkle tree to the message. */
|
|
47
|
-
public siblingPath: SiblingPath<N>,
|
|
48
|
-
) {}
|
|
49
|
-
|
|
50
|
-
toFields(): Fr[] {
|
|
51
|
-
return [new Fr(this.index), ...this.siblingPath.toFields()];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
43
|
class OracleMethodNotAvailableError extends Error {
|
|
56
44
|
constructor(methodName: string) {
|
|
57
45
|
super(`Oracle method ${methodName} is not available.`);
|
|
@@ -68,16 +56,16 @@ export abstract class TypedOracle {
|
|
|
68
56
|
return Fr.random();
|
|
69
57
|
}
|
|
70
58
|
|
|
71
|
-
|
|
72
|
-
throw new OracleMethodNotAvailableError('
|
|
59
|
+
storeArrayInExecutionCache(_args: Fr[]): Promise<Fr> {
|
|
60
|
+
throw new OracleMethodNotAvailableError('storeArrayInExecutionCache');
|
|
73
61
|
}
|
|
74
62
|
|
|
75
|
-
|
|
76
|
-
throw new OracleMethodNotAvailableError('
|
|
63
|
+
storeInExecutionCache(_values: Fr[]): Promise<Fr> {
|
|
64
|
+
throw new OracleMethodNotAvailableError('storeInExecutionCache');
|
|
77
65
|
}
|
|
78
66
|
|
|
79
|
-
|
|
80
|
-
throw new OracleMethodNotAvailableError('
|
|
67
|
+
loadFromExecutionCache(_hash: Fr): Promise<Fr[]> {
|
|
68
|
+
throw new OracleMethodNotAvailableError('loadFromExecutionCache');
|
|
81
69
|
}
|
|
82
70
|
|
|
83
71
|
getBlockNumber(): Promise<number> {
|
|
@@ -108,10 +96,6 @@ export abstract class TypedOracle {
|
|
|
108
96
|
throw new OracleMethodNotAvailableError('getMembershipWitness');
|
|
109
97
|
}
|
|
110
98
|
|
|
111
|
-
getSiblingPath(_blockNumber: number, _treeId: MerkleTreeId, _leafIndex: Fr): Promise<Fr[]> {
|
|
112
|
-
throw new OracleMethodNotAvailableError('getSiblingPath');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
99
|
getNullifierMembershipWitness(_blockNumber: number, _nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
|
|
116
100
|
throw new OracleMethodNotAvailableError('getNullifierMembershipWitness');
|
|
117
101
|
}
|
|
@@ -170,6 +154,10 @@ export abstract class TypedOracle {
|
|
|
170
154
|
throw new OracleMethodNotAvailableError('notifyNullifiedNote');
|
|
171
155
|
}
|
|
172
156
|
|
|
157
|
+
notifyCreatedNullifier(_innerNullifier: Fr): Promise<void> {
|
|
158
|
+
throw new OracleMethodNotAvailableError('notifyCreatedNullifier');
|
|
159
|
+
}
|
|
160
|
+
|
|
173
161
|
checkNullifierExists(_innerNullifier: Fr): Promise<boolean> {
|
|
174
162
|
throw new OracleMethodNotAvailableError('checkNullifierExists');
|
|
175
163
|
}
|
|
@@ -248,4 +236,12 @@ export abstract class TypedOracle {
|
|
|
248
236
|
syncNotes(): Promise<void> {
|
|
249
237
|
throw new OracleMethodNotAvailableError('syncNotes');
|
|
250
238
|
}
|
|
239
|
+
|
|
240
|
+
store(_contract: AztecAddress, _key: Fr, _values: Fr[]): Promise<void> {
|
|
241
|
+
throw new OracleMethodNotAvailableError('store');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
load(_contract: AztecAddress, _key: Fr): Promise<Fr[] | null> {
|
|
245
|
+
throw new OracleMethodNotAvailableError('load');
|
|
246
|
+
}
|
|
251
247
|
}
|
package/src/avm/avm_simulator.ts
CHANGED
|
@@ -137,6 +137,7 @@ export class AvmSimulator {
|
|
|
137
137
|
this.bytecode = bytecode;
|
|
138
138
|
|
|
139
139
|
const { machineState } = this.context;
|
|
140
|
+
const callStartGas = machineState.gasLeft; // Save gas before executing instruction (for profiling)
|
|
140
141
|
try {
|
|
141
142
|
// Execute instruction pointed to by the current program counter
|
|
142
143
|
// continuing until the machine state signifies a halt
|
|
@@ -180,6 +181,11 @@ export class AvmSimulator {
|
|
|
180
181
|
const revertReason = reverted ? await revertReasonFromExplicitRevert(output, this.context) : undefined;
|
|
181
182
|
const results = new AvmContractCallResult(reverted, output, machineState.gasLeft, revertReason);
|
|
182
183
|
this.log.debug(`Context execution results: ${results.toString()}`);
|
|
184
|
+
const totalGasUsed: Gas = {
|
|
185
|
+
l2Gas: callStartGas.l2Gas - machineState.l2GasLeft,
|
|
186
|
+
daGas: callStartGas.daGas - machineState.daGasLeft,
|
|
187
|
+
};
|
|
188
|
+
this.log.debug(`Executed ${instrCounter} instructions and consumed ${totalGasUsed.l2Gas} L2 Gas`);
|
|
183
189
|
|
|
184
190
|
this.tallyPrintFunction();
|
|
185
191
|
// Return results for processing by calling context
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNoirCallStackUnresolved } from '@aztec/circuit-types';
|
|
2
2
|
import { GasFees, GlobalVariables, MAX_L2_GAS_PER_TX_PUBLIC_PORTION } from '@aztec/circuits.js';
|
|
3
3
|
import { type FunctionArtifact, FunctionSelector } from '@aztec/foundation/abi';
|
|
4
4
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
@@ -10,8 +10,9 @@ import { strict as assert } from 'assert';
|
|
|
10
10
|
import { mock } from 'jest-mock-extended';
|
|
11
11
|
import merge from 'lodash.merge';
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { resolveAssertionMessageFromRevertData, traverseCauseChain } from '../../common.js';
|
|
14
14
|
import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js';
|
|
15
|
+
import { type WorldStateDB } from '../../server.js';
|
|
15
16
|
import { AvmContext } from '../avm_context.js';
|
|
16
17
|
import { AvmExecutionEnvironment } from '../avm_execution_environment.js';
|
|
17
18
|
import { AvmMachineState } from '../avm_machine_state.js';
|
|
@@ -45,7 +46,7 @@ export function initPersistableStateManager(overrides?: {
|
|
|
45
46
|
nullifiers?: NullifierManager;
|
|
46
47
|
doMerkleOperations?: boolean;
|
|
47
48
|
merkleTrees?: AvmEphemeralForest;
|
|
48
|
-
|
|
49
|
+
firstNullifier?: Fr;
|
|
49
50
|
}): AvmPersistableStateManager {
|
|
50
51
|
const worldStateDB = overrides?.worldStateDB || mock<WorldStateDB>();
|
|
51
52
|
return new AvmPersistableStateManager(
|
|
@@ -55,7 +56,7 @@ export function initPersistableStateManager(overrides?: {
|
|
|
55
56
|
overrides?.nullifiers || new NullifierManager(worldStateDB),
|
|
56
57
|
overrides?.doMerkleOperations || false,
|
|
57
58
|
overrides?.merkleTrees || mock<AvmEphemeralForest>(),
|
|
58
|
-
overrides?.
|
|
59
|
+
overrides?.firstNullifier || new Fr(27),
|
|
59
60
|
);
|
|
60
61
|
}
|
|
61
62
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MerkleTreeId
|
|
1
|
+
import { MerkleTreeId } from '@aztec/circuit-types';
|
|
2
2
|
import {
|
|
3
3
|
AztecAddress,
|
|
4
4
|
CANONICAL_AUTH_REGISTRY_ADDRESS,
|
|
@@ -61,7 +61,7 @@ export class AvmPersistableStateManager {
|
|
|
61
61
|
private readonly doMerkleOperations: boolean = false,
|
|
62
62
|
/** Ephmeral forest for merkle tree operations */
|
|
63
63
|
public merkleTrees: AvmEphemeralForest,
|
|
64
|
-
public readonly
|
|
64
|
+
public readonly firstNullifier: Fr,
|
|
65
65
|
) {}
|
|
66
66
|
|
|
67
67
|
/**
|
|
@@ -71,7 +71,7 @@ export class AvmPersistableStateManager {
|
|
|
71
71
|
worldStateDB: WorldStateDB,
|
|
72
72
|
trace: PublicSideEffectTraceInterface,
|
|
73
73
|
doMerkleOperations: boolean = false,
|
|
74
|
-
|
|
74
|
+
firstNullifier: Fr,
|
|
75
75
|
) {
|
|
76
76
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
77
77
|
return new AvmPersistableStateManager(
|
|
@@ -81,7 +81,7 @@ export class AvmPersistableStateManager {
|
|
|
81
81
|
/*nullifiers=*/ new NullifierManager(worldStateDB),
|
|
82
82
|
/*doMerkleOperations=*/ doMerkleOperations,
|
|
83
83
|
ephemeralForest,
|
|
84
|
-
|
|
84
|
+
firstNullifier,
|
|
85
85
|
);
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -96,7 +96,7 @@ export class AvmPersistableStateManager {
|
|
|
96
96
|
this.nullifiers.fork(),
|
|
97
97
|
this.doMerkleOperations,
|
|
98
98
|
this.merkleTrees.fork(),
|
|
99
|
-
this.
|
|
99
|
+
this.firstNullifier,
|
|
100
100
|
);
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -124,13 +124,14 @@ export class AvmPersistableStateManager {
|
|
|
124
124
|
this.publicStorage.acceptAndMerge(forkedState.publicStorage);
|
|
125
125
|
this.nullifiers.acceptAndMerge(forkedState.nullifiers);
|
|
126
126
|
this.trace.merge(forkedState.trace, reverted);
|
|
127
|
-
if (
|
|
128
|
-
this.merkleTrees = forkedState.merkleTrees;
|
|
127
|
+
if (reverted) {
|
|
129
128
|
if (this.doMerkleOperations) {
|
|
130
129
|
this.log.debug(
|
|
131
130
|
`Rolled back nullifier tree to root ${this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE)!.getRoot()}`,
|
|
132
131
|
);
|
|
133
132
|
}
|
|
133
|
+
} else {
|
|
134
|
+
this.merkleTrees = forkedState.merkleTrees;
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
|
|
@@ -293,8 +294,7 @@ export class AvmPersistableStateManager {
|
|
|
293
294
|
* @param noteHash - the non unique note hash to write
|
|
294
295
|
*/
|
|
295
296
|
public writeSiloedNoteHash(noteHash: Fr): void {
|
|
296
|
-
const
|
|
297
|
-
const nonce = computeNoteHashNonce(txHash, this.trace.getNoteHashCount());
|
|
297
|
+
const nonce = computeNoteHashNonce(this.firstNullifier, this.trace.getNoteHashCount());
|
|
298
298
|
const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash);
|
|
299
299
|
|
|
300
300
|
this.writeUniqueNoteHash(uniqueNoteHash);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
|
|
3
|
-
import type { CommitmentsDB } from '../../
|
|
3
|
+
import type { CommitmentsDB } from '../../server.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A class to manage new nullifier staging and existence checks during a contract call's AVM simulation.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AztecAddress } from '@aztec/circuits.js';
|
|
2
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
3
|
|
|
4
|
-
import type { PublicStateDB } from '../../
|
|
4
|
+
import type { PublicStateDB } from '../../server.js';
|
|
5
5
|
|
|
6
6
|
type PublicStorageReadResult = {
|
|
7
7
|
value: Fr;
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
Note,
|
|
7
7
|
NoteAndSlot,
|
|
8
8
|
type NoteStatus,
|
|
9
|
-
type
|
|
9
|
+
type PrivateCallExecutionResult,
|
|
10
10
|
PublicExecutionRequest,
|
|
11
11
|
type UnencryptedL2Log,
|
|
12
12
|
} from '@aztec/circuit-types';
|
|
@@ -26,7 +26,8 @@ import { Fr } from '@aztec/foundation/fields';
|
|
|
26
26
|
import { createLogger } from '@aztec/foundation/log';
|
|
27
27
|
|
|
28
28
|
import { type NoteData, toACVMWitness } from '../acvm/index.js';
|
|
29
|
-
import { type
|
|
29
|
+
import { type HashedValuesCache } from '../common/hashed_values_cache.js';
|
|
30
|
+
import { type SimulationProvider } from '../server.js';
|
|
30
31
|
import { type DBOracle } from './db_oracle.js';
|
|
31
32
|
import { type ExecutionNoteCache } from './execution_note_cache.js';
|
|
32
33
|
import { pickNotes } from './pick_notes.js';
|
|
@@ -57,7 +58,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
57
58
|
private noteHashLeafIndexMap: Map<bigint, bigint> = new Map();
|
|
58
59
|
private noteHashNullifierCounterMap: Map<number, number> = new Map();
|
|
59
60
|
private contractClassLogs: CountedContractClassLog[] = [];
|
|
60
|
-
private nestedExecutions:
|
|
61
|
+
private nestedExecutions: PrivateCallExecutionResult[] = [];
|
|
61
62
|
private enqueuedPublicFunctionCalls: CountedPublicExecutionRequest[] = [];
|
|
62
63
|
private publicTeardownFunctionCall: PublicExecutionRequest = PublicExecutionRequest.empty();
|
|
63
64
|
|
|
@@ -69,10 +70,11 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
69
70
|
protected readonly historicalHeader: BlockHeader,
|
|
70
71
|
/** List of transient auth witnesses to be used during this simulation */
|
|
71
72
|
authWitnesses: AuthWitness[],
|
|
72
|
-
private readonly
|
|
73
|
+
private readonly executionCache: HashedValuesCache,
|
|
73
74
|
private readonly noteCache: ExecutionNoteCache,
|
|
74
75
|
db: DBOracle,
|
|
75
76
|
private node: AztecNode,
|
|
77
|
+
private provider: SimulationProvider,
|
|
76
78
|
protected sideEffectCounter: number = 0,
|
|
77
79
|
log = createLogger('simulator:client_execution_context'),
|
|
78
80
|
scopes?: AztecAddress[],
|
|
@@ -90,7 +92,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
90
92
|
public getInitialWitness(abi: FunctionAbi) {
|
|
91
93
|
const argumentsSize = countArgumentsSize(abi);
|
|
92
94
|
|
|
93
|
-
const args = this.
|
|
95
|
+
const args = this.executionCache.getPreimage(this.argsHash);
|
|
94
96
|
|
|
95
97
|
if (args.length !== argumentsSize) {
|
|
96
98
|
throw new Error('Invalid arguments size');
|
|
@@ -159,27 +161,29 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
/**
|
|
162
|
-
*
|
|
163
|
-
* @param
|
|
164
|
+
* Store values in the execution cache.
|
|
165
|
+
* @param values - Values to store.
|
|
164
166
|
*/
|
|
165
|
-
public override
|
|
166
|
-
return Promise.resolve(this.
|
|
167
|
+
public override storeArrayInExecutionCache(args: Fr[]): Promise<Fr> {
|
|
168
|
+
return Promise.resolve(this.executionCache.store(args));
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
/**
|
|
170
|
-
*
|
|
171
|
-
* @param
|
|
172
|
+
* Store values in the execution cache.
|
|
173
|
+
* @param values - Values to store.
|
|
174
|
+
* @returns The hash of the values.
|
|
172
175
|
*/
|
|
173
|
-
public override
|
|
174
|
-
return Promise.resolve(this.
|
|
176
|
+
public override storeInExecutionCache(values: Fr[]): Promise<Fr> {
|
|
177
|
+
return Promise.resolve(this.executionCache.store(values));
|
|
175
178
|
}
|
|
176
179
|
|
|
177
180
|
/**
|
|
178
|
-
*
|
|
179
|
-
* @param
|
|
181
|
+
* Gets values from the execution cache.
|
|
182
|
+
* @param hash - Hash of the values.
|
|
183
|
+
* @returns The values.
|
|
180
184
|
*/
|
|
181
|
-
public override
|
|
182
|
-
return Promise.resolve(this.
|
|
185
|
+
public override loadFromExecutionCache(hash: Fr): Promise<Fr[]> {
|
|
186
|
+
return Promise.resolve(this.executionCache.getPreimage(hash));
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
/**
|
|
@@ -307,6 +311,17 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
307
311
|
return Promise.resolve();
|
|
308
312
|
}
|
|
309
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Adding a siloed nullifier into the current set of all pending nullifiers created
|
|
316
|
+
* within the current transaction/execution.
|
|
317
|
+
* @param innerNullifier - The pending nullifier to add in the list (not yet siloed by contract address).
|
|
318
|
+
* @param noteHash - A hash of the new note.
|
|
319
|
+
*/
|
|
320
|
+
public override notifyCreatedNullifier(innerNullifier: Fr) {
|
|
321
|
+
this.noteCache.nullifierCreated(this.callContext.contractAddress, innerNullifier);
|
|
322
|
+
return Promise.resolve();
|
|
323
|
+
}
|
|
324
|
+
|
|
310
325
|
/**
|
|
311
326
|
* Emit a contract class unencrypted log.
|
|
312
327
|
* This fn exists because sha hashing the preimage
|
|
@@ -323,7 +338,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
323
338
|
return Fr.fromBuffer(log.hash());
|
|
324
339
|
}
|
|
325
340
|
|
|
326
|
-
#checkValidStaticCall(childExecutionResult:
|
|
341
|
+
#checkValidStaticCall(childExecutionResult: PrivateCallExecutionResult) {
|
|
327
342
|
if (
|
|
328
343
|
childExecutionResult.publicInputs.noteHashes.some(item => !item.isEmpty()) ||
|
|
329
344
|
childExecutionResult.publicInputs.nullifiers.some(item => !item.isEmpty()) ||
|
|
@@ -339,7 +354,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
339
354
|
* Calls a private function as a nested execution.
|
|
340
355
|
* @param targetContractAddress - The address of the contract to call.
|
|
341
356
|
* @param functionSelector - The function selector of the function to call.
|
|
342
|
-
* @param argsHash - The
|
|
357
|
+
* @param argsHash - The arguments hash to pass to the function.
|
|
343
358
|
* @param sideEffectCounter - The side effect counter at the start of the call.
|
|
344
359
|
* @param isStaticCall - Whether the call is a static call.
|
|
345
360
|
* @returns The execution result.
|
|
@@ -369,16 +384,18 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
369
384
|
derivedCallContext,
|
|
370
385
|
this.historicalHeader,
|
|
371
386
|
this.authWitnesses,
|
|
372
|
-
this.
|
|
387
|
+
this.executionCache,
|
|
373
388
|
this.noteCache,
|
|
374
389
|
this.db,
|
|
375
390
|
this.node,
|
|
391
|
+
this.provider,
|
|
376
392
|
sideEffectCounter,
|
|
377
393
|
this.log,
|
|
378
394
|
this.scopes,
|
|
379
395
|
);
|
|
380
396
|
|
|
381
397
|
const childExecutionResult = await executePrivateFunction(
|
|
398
|
+
this.provider,
|
|
382
399
|
context,
|
|
383
400
|
targetArtifact,
|
|
384
401
|
targetContractAddress,
|
|
@@ -402,7 +419,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
402
419
|
* Creates a PublicExecutionRequest object representing the request to call a public function.
|
|
403
420
|
* @param targetContractAddress - The address of the contract to call.
|
|
404
421
|
* @param functionSelector - The function selector of the function to call.
|
|
405
|
-
* @param argsHash - The
|
|
422
|
+
* @param argsHash - The arguments hash to pass to the function.
|
|
406
423
|
* @param sideEffectCounter - The side effect counter at the start of the call.
|
|
407
424
|
* @param isStaticCall - Whether the call is a static call.
|
|
408
425
|
* @returns The public call stack item with the request information.
|
|
@@ -417,7 +434,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
417
434
|
) {
|
|
418
435
|
const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
419
436
|
const derivedCallContext = this.deriveCallContext(targetContractAddress, targetArtifact, isStaticCall);
|
|
420
|
-
const args = this.
|
|
437
|
+
const args = this.executionCache.getPreimage(argsHash);
|
|
421
438
|
|
|
422
439
|
this.log.verbose(
|
|
423
440
|
`Created ${callType} public execution request to ${targetArtifact.name}@${targetContractAddress}`,
|
|
@@ -448,7 +465,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
448
465
|
* of the execution are empty.
|
|
449
466
|
* @param targetContractAddress - The address of the contract to call.
|
|
450
467
|
* @param functionSelector - The function selector of the function to call.
|
|
451
|
-
* @param argsHash - The
|
|
468
|
+
* @param argsHash - The arguments hash to pass to the function.
|
|
452
469
|
* @param sideEffectCounter - The side effect counter at the start of the call.
|
|
453
470
|
* @param isStaticCall - Whether the call is a static call.
|
|
454
471
|
* @returns The public call stack item with the request information.
|
|
@@ -462,13 +479,13 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
462
479
|
): Promise<Fr> {
|
|
463
480
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
|
|
464
481
|
// WARNING: This is insecure and should be temporary!
|
|
465
|
-
// The oracle
|
|
482
|
+
// The oracle re-hashes the arguments and returns a new args_hash.
|
|
466
483
|
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
|
|
467
484
|
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
|
|
468
485
|
// b) this is only temporary.
|
|
469
|
-
const newArgsHash = this.
|
|
486
|
+
const newArgsHash = this.executionCache.store([
|
|
470
487
|
functionSelector.toField(),
|
|
471
|
-
...this.
|
|
488
|
+
...this.executionCache.getPreimage(argsHash),
|
|
472
489
|
]);
|
|
473
490
|
await this.createPublicExecutionRequest(
|
|
474
491
|
'enqueued',
|
|
@@ -487,7 +504,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
487
504
|
* of the execution are empty.
|
|
488
505
|
* @param targetContractAddress - The address of the contract to call.
|
|
489
506
|
* @param functionSelector - The function selector of the function to call.
|
|
490
|
-
* @param argsHash - The
|
|
507
|
+
* @param argsHash - The arguments hash to pass to the function.
|
|
491
508
|
* @param sideEffectCounter - The side effect counter at the start of the call.
|
|
492
509
|
* @param isStaticCall - Whether the call is a static call.
|
|
493
510
|
* @returns The public call stack item with the request information.
|
|
@@ -501,13 +518,13 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
501
518
|
): Promise<Fr> {
|
|
502
519
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
|
|
503
520
|
// WARNING: This is insecure and should be temporary!
|
|
504
|
-
// The oracle
|
|
521
|
+
// The oracle rehashes the arguments and returns a new args_hash.
|
|
505
522
|
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
|
|
506
523
|
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
|
|
507
524
|
// b) this is only temporary.
|
|
508
|
-
const newArgsHash = this.
|
|
525
|
+
const newArgsHash = this.executionCache.store([
|
|
509
526
|
functionSelector.toField(),
|
|
510
|
-
...this.
|
|
527
|
+
...this.executionCache.getPreimage(argsHash),
|
|
511
528
|
]);
|
|
512
529
|
await this.createPublicExecutionRequest(
|
|
513
530
|
'teardown',
|
package/src/client/db_oracle.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type L2Block,
|
|
3
|
-
type L2BlockNumber,
|
|
4
3
|
type MerkleTreeId,
|
|
5
4
|
type NoteStatus,
|
|
6
5
|
type NullifierMembershipWitness,
|
|
@@ -141,22 +140,13 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
141
140
|
getBlockHeader(): Promise<BlockHeader>;
|
|
142
141
|
|
|
143
142
|
/**
|
|
144
|
-
*
|
|
145
|
-
* @param blockNumber - The block number at which to get the
|
|
146
|
-
* @param treeId -
|
|
147
|
-
* @param leafValue - The leaf value
|
|
148
|
-
* @returns
|
|
143
|
+
* Fetches the index and sibling path of a leaf at a given block from a given tree.
|
|
144
|
+
* @param blockNumber - The block number at which to get the membership witness.
|
|
145
|
+
* @param treeId - Id of the tree to get the sibling path from.
|
|
146
|
+
* @param leafValue - The leaf value
|
|
147
|
+
* @returns The index and sibling path concatenated [index, sibling_path]
|
|
149
148
|
*/
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Fetch the sibling path of the leaf in the respective tree
|
|
154
|
-
* @param blockNumber - The block number at which to get the sibling path.
|
|
155
|
-
* @param treeId - The id of the tree to search.
|
|
156
|
-
* @param leafIndex - The index of the leaf.
|
|
157
|
-
* @returns - The sibling path of the leaf.
|
|
158
|
-
*/
|
|
159
|
-
getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: bigint): Promise<Fr[]>;
|
|
149
|
+
getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]>;
|
|
160
150
|
|
|
161
151
|
/**
|
|
162
152
|
* Returns a nullifier membership witness for a given nullifier at a given block.
|
|
@@ -224,7 +214,7 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
224
214
|
): Promise<void>;
|
|
225
215
|
|
|
226
216
|
/**
|
|
227
|
-
* Synchronizes the logs tagged with the recipient's address and all the senders in the
|
|
217
|
+
* Synchronizes the logs tagged with the recipient's address and all the senders in the address book.
|
|
228
218
|
* Returns the unsynched logs and updates the indexes of the secrets used to tag them until there are no more logs to sync.
|
|
229
219
|
* @param contractAddress - The address of the contract that the logs are tagged for
|
|
230
220
|
* @param recipient - The address of the recipient
|
|
@@ -247,4 +237,22 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
247
237
|
* Removes all of a contract's notes that have been nullified from the note database.
|
|
248
238
|
*/
|
|
249
239
|
removeNullifiedNotes(contractAddress: AztecAddress): Promise<void>;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Used by contracts during execution to store arbitrary data in the local PXE database. The data is siloed/scoped
|
|
243
|
+
* to a specific `contract`.
|
|
244
|
+
* @param contract - An address of a contract that is requesting to store the data.
|
|
245
|
+
* @param key - A field element representing the key to store the data under.
|
|
246
|
+
* @param values - An array of field elements representing the data to store.
|
|
247
|
+
*/
|
|
248
|
+
store(contract: AztecAddress, key: Fr, values: Fr[]): Promise<void>;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Used by contracts during execution to load arbitrary data from the local PXE database. The data is siloed/scoped
|
|
252
|
+
* to a specific `contract`.
|
|
253
|
+
* @param contract - An address of a contract that is requesting to load the data.
|
|
254
|
+
* @param key - A field element representing the key under which to load the data..
|
|
255
|
+
* @returns An array of field elements representing the stored data or `null` if no data is stored under the key.
|
|
256
|
+
*/
|
|
257
|
+
load(contract: AztecAddress, key: Fr): Promise<Fr[] | null>;
|
|
250
258
|
}
|