@aztec/simulator 0.33.0 → 0.34.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.js +2 -2
- package/dest/acvm/oracle/oracle.d.ts +1 -1
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +3 -3
- package/dest/avm/avm_execution_environment.d.ts +4 -3
- package/dest/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/avm/avm_execution_environment.js +8 -7
- package/dest/avm/avm_memory_types.js +5 -5
- package/dest/avm/avm_simulator.js +6 -6
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +3 -3
- package/dest/avm/journal/journal.d.ts +14 -13
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +5 -5
- package/dest/avm/journal/trace.d.ts +8 -19
- package/dest/avm/journal/trace.d.ts.map +1 -1
- package/dest/avm/journal/trace.js +48 -116
- package/dest/avm/journal/trace_types.d.ts +23 -4
- package/dest/avm/journal/trace_types.d.ts.map +1 -1
- package/dest/avm/opcodes/accrued_substate.js +2 -2
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +20 -5
- package/dest/client/client_execution_context.d.ts +2 -2
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +6 -6
- package/dest/client/private_execution.d.ts +1 -1
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +3 -3
- package/dest/client/unconstrained_execution.d.ts +1 -1
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +2 -2
- package/dest/client/view_data_oracle.d.ts +2 -2
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +2 -2
- package/dest/public/executor.d.ts +1 -15
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +70 -77
- package/dest/public/public_execution_context.d.ts +6 -6
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +8 -12
- package/dest/public/transitional_adaptors.d.ts +32 -0
- package/dest/public/transitional_adaptors.d.ts.map +1 -0
- package/dest/public/transitional_adaptors.js +161 -0
- package/package.json +5 -5
- package/src/acvm/acvm.ts +1 -1
- package/src/acvm/oracle/oracle.ts +2 -2
- package/src/avm/avm_execution_environment.ts +9 -17
- package/src/avm/avm_memory_types.ts +4 -4
- package/src/avm/avm_simulator.ts +5 -5
- package/src/avm/fixtures/index.ts +2 -1
- package/src/avm/journal/journal.ts +24 -17
- package/src/avm/journal/trace.ts +59 -121
- package/src/avm/journal/trace_types.ts +39 -39
- package/src/avm/opcodes/accrued_substate.ts +1 -1
- package/src/avm/opcodes/external_calls.ts +24 -4
- package/src/client/client_execution_context.ts +5 -5
- package/src/client/private_execution.ts +2 -2
- package/src/client/unconstrained_execution.ts +1 -1
- package/src/client/view_data_oracle.ts +1 -1
- package/src/public/executor.ts +82 -87
- package/src/public/public_execution_context.ts +14 -19
- package/src/public/transitional_adaptors.ts +240 -0
- package/dest/avm/temporary_executor_migration.d.ts +0 -27
- package/dest/avm/temporary_executor_migration.d.ts.map +0 -1
- package/dest/avm/temporary_executor_migration.js +0 -94
- package/src/avm/temporary_executor_migration.ts +0 -136
package/src/public/executor.ts
CHANGED
|
@@ -12,11 +12,6 @@ import { AvmMachineState } from '../avm/avm_machine_state.js';
|
|
|
12
12
|
import { AvmSimulator } from '../avm/avm_simulator.js';
|
|
13
13
|
import { HostStorage } from '../avm/journal/host_storage.js';
|
|
14
14
|
import { AvmPersistableStateManager } from '../avm/journal/index.js';
|
|
15
|
-
import {
|
|
16
|
-
isAvmBytecode,
|
|
17
|
-
temporaryConvertAvmResults,
|
|
18
|
-
temporaryCreateAvmExecutionEnvironment,
|
|
19
|
-
} from '../avm/temporary_executor_migration.js';
|
|
20
15
|
import { AcirSimulator } from '../client/simulator.js';
|
|
21
16
|
import { ExecutionError, createSimulationError } from '../common/errors.js';
|
|
22
17
|
import { SideEffectCounter } from '../common/index.js';
|
|
@@ -24,35 +19,92 @@ import { PackedArgsCache } from '../common/packed_args_cache.js';
|
|
|
24
19
|
import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db.js';
|
|
25
20
|
import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js';
|
|
26
21
|
import { PublicExecutionContext } from './public_execution_context.js';
|
|
22
|
+
import { convertAvmResults, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';
|
|
27
23
|
|
|
28
24
|
/**
|
|
29
25
|
* Execute a public function and return the execution result.
|
|
30
26
|
*/
|
|
31
27
|
export async function executePublicFunction(
|
|
28
|
+
context: PublicExecutionContext,
|
|
29
|
+
nested: boolean,
|
|
30
|
+
): Promise<PublicExecutionResult> {
|
|
31
|
+
const bytecode = await context.contractsDb.getBytecode(
|
|
32
|
+
context.execution.contractAddress,
|
|
33
|
+
context.execution.functionData.selector,
|
|
34
|
+
);
|
|
35
|
+
if (!bytecode) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Bytecode not found for ${context.execution.contractAddress}:${context.execution.functionData.selector}`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isAvmBytecode(bytecode)) {
|
|
42
|
+
return await executePublicFunctionAvm(context);
|
|
43
|
+
} else {
|
|
44
|
+
return await executePublicFunctionAcvm(context, bytecode, nested);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function executePublicFunctionAvm(executionContext: PublicExecutionContext): Promise<PublicExecutionResult> {
|
|
49
|
+
const address = executionContext.execution.contractAddress;
|
|
50
|
+
const selector = executionContext.execution.functionData.selector;
|
|
51
|
+
const log = createDebugLogger('aztec:simulator:public_execution');
|
|
52
|
+
log.verbose(`[AVM] Executing public external function ${address.toString()}:${selector}.`);
|
|
53
|
+
|
|
54
|
+
// Temporary code to construct the AVM context
|
|
55
|
+
// These data structures will permeate across the simulator when the public executor is phased out
|
|
56
|
+
const hostStorage = new HostStorage(
|
|
57
|
+
executionContext.stateDb,
|
|
58
|
+
executionContext.contractsDb,
|
|
59
|
+
executionContext.commitmentsDb,
|
|
60
|
+
);
|
|
61
|
+
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
|
|
62
|
+
|
|
63
|
+
const executionEnv = createAvmExecutionEnvironment(
|
|
64
|
+
executionContext.execution,
|
|
65
|
+
executionContext.header,
|
|
66
|
+
executionContext.globalVariables,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// TODO(@spalladino) Load initial gas from the public execution request
|
|
70
|
+
const machineState = new AvmMachineState(1e7, 1e7, 1e7);
|
|
71
|
+
|
|
72
|
+
const context = new AvmContext(worldStateJournal, executionEnv, machineState);
|
|
73
|
+
const simulator = new AvmSimulator(context);
|
|
74
|
+
|
|
75
|
+
const result = await simulator.execute();
|
|
76
|
+
const newWorldState = context.persistableState.flush();
|
|
77
|
+
|
|
78
|
+
log.verbose(`[AVM] ${address.toString()}:${selector} returned, reverted: ${result.reverted}.`);
|
|
79
|
+
|
|
80
|
+
// TODO(@spalladino) Read gas left from machineState and return it
|
|
81
|
+
return await convertAvmResults(executionContext, newWorldState, result);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function executePublicFunctionAcvm(
|
|
32
85
|
context: PublicExecutionContext,
|
|
33
86
|
acir: Buffer,
|
|
34
87
|
nested: boolean,
|
|
35
|
-
log = createDebugLogger('aztec:simulator:public_execution'),
|
|
36
88
|
): Promise<PublicExecutionResult> {
|
|
37
89
|
const execution = context.execution;
|
|
38
90
|
const { contractAddress, functionData } = execution;
|
|
39
91
|
const selector = functionData.selector;
|
|
40
|
-
log
|
|
92
|
+
const log = createDebugLogger('aztec:simulator:public_execution');
|
|
93
|
+
log.verbose(`[ACVM] Executing public external function ${contractAddress.toString()}:${selector}.`);
|
|
41
94
|
|
|
42
95
|
const initialWitness = context.getInitialWitness();
|
|
43
96
|
const acvmCallback = new Oracle(context);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
.catch((err: Error) => {
|
|
97
|
+
|
|
98
|
+
const { partialWitness, reverted, revertReason } = await (async () => {
|
|
99
|
+
try {
|
|
100
|
+
const result = await acvm(await AcirSimulator.getSolver(), acir, initialWitness, acvmCallback);
|
|
101
|
+
return {
|
|
102
|
+
partialWitness: result.partialWitness,
|
|
103
|
+
reverted: false,
|
|
104
|
+
revertReason: undefined,
|
|
105
|
+
};
|
|
106
|
+
} catch (err_) {
|
|
107
|
+
const err = err_ as Error;
|
|
56
108
|
const ee = new ExecutionError(
|
|
57
109
|
err.message,
|
|
58
110
|
{
|
|
@@ -73,7 +125,9 @@ export async function executePublicFunction(
|
|
|
73
125
|
revertReason: createSimulationError(ee),
|
|
74
126
|
};
|
|
75
127
|
}
|
|
76
|
-
}
|
|
128
|
+
}
|
|
129
|
+
})();
|
|
130
|
+
|
|
77
131
|
if (reverted) {
|
|
78
132
|
if (!revertReason) {
|
|
79
133
|
throw new Error('Reverted but no revert reason');
|
|
@@ -123,12 +177,12 @@ export async function executePublicFunction(
|
|
|
123
177
|
|
|
124
178
|
const { contractStorageReads, contractStorageUpdateRequests } = context.getStorageActionData();
|
|
125
179
|
|
|
126
|
-
log(
|
|
180
|
+
log.debug(
|
|
127
181
|
`Contract storage reads: ${contractStorageReads
|
|
128
182
|
.map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
|
|
129
183
|
.join(', ')}`,
|
|
130
184
|
);
|
|
131
|
-
log(
|
|
185
|
+
log.debug(
|
|
132
186
|
`Contract storage update requests: ${contractStorageUpdateRequests
|
|
133
187
|
.map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
|
|
134
188
|
.join(', ')}`,
|
|
@@ -179,36 +233,6 @@ export class PublicExecutor {
|
|
|
179
233
|
globalVariables: GlobalVariables,
|
|
180
234
|
sideEffectCounter: number = 0,
|
|
181
235
|
): Promise<PublicExecutionResult> {
|
|
182
|
-
const selector = execution.functionData.selector;
|
|
183
|
-
const bytecode = await this.contractsDb.getBytecode(execution.contractAddress, selector);
|
|
184
|
-
if (!bytecode) {
|
|
185
|
-
throw new Error(`Bytecode not found for ${execution.contractAddress}:${selector}`);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (isAvmBytecode(bytecode)) {
|
|
189
|
-
return await this.simulateAvm(execution, globalVariables, sideEffectCounter);
|
|
190
|
-
} else {
|
|
191
|
-
return await this.simulateAcvm(execution, globalVariables, sideEffectCounter);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Executes a public execution request with the ACVM.
|
|
197
|
-
* @param execution - The execution to run.
|
|
198
|
-
* @param globalVariables - The global variables to use.
|
|
199
|
-
* @returns The result of the run plus all nested runs.
|
|
200
|
-
*/
|
|
201
|
-
private async simulateAcvm(
|
|
202
|
-
execution: PublicExecution,
|
|
203
|
-
globalVariables: GlobalVariables,
|
|
204
|
-
sideEffectCounter: number = 0,
|
|
205
|
-
): Promise<PublicExecutionResult> {
|
|
206
|
-
const selector = execution.functionData.selector;
|
|
207
|
-
const acir = await this.contractsDb.getBytecode(execution.contractAddress, selector);
|
|
208
|
-
if (!acir) {
|
|
209
|
-
throw new Error(`Bytecode not found for ${execution.contractAddress}:${selector}`);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
236
|
// Functions can request to pack arguments before calling other functions.
|
|
213
237
|
// We use this cache to hold the packed arguments.
|
|
214
238
|
const packedArgs = PackedArgsCache.create([]);
|
|
@@ -224,7 +248,7 @@ export class PublicExecutor {
|
|
|
224
248
|
this.commitmentsDb,
|
|
225
249
|
);
|
|
226
250
|
|
|
227
|
-
const executionResult = await executePublicFunction(context,
|
|
251
|
+
const executionResult = await executePublicFunction(context, /*nested=*/ false);
|
|
228
252
|
|
|
229
253
|
if (executionResult.execution.callContext.isStaticCall) {
|
|
230
254
|
checkValidStaticCall(
|
|
@@ -239,35 +263,6 @@ export class PublicExecutor {
|
|
|
239
263
|
return executionResult;
|
|
240
264
|
}
|
|
241
265
|
|
|
242
|
-
/**
|
|
243
|
-
* Executes a public execution request in the AVM.
|
|
244
|
-
* @param execution - The execution to run.
|
|
245
|
-
* @param globalVariables - The global variables to use.
|
|
246
|
-
* @returns The result of the run plus all nested runs.
|
|
247
|
-
*/
|
|
248
|
-
private async simulateAvm(
|
|
249
|
-
execution: PublicExecution,
|
|
250
|
-
globalVariables: GlobalVariables,
|
|
251
|
-
_sideEffectCounter = 0,
|
|
252
|
-
): Promise<PublicExecutionResult> {
|
|
253
|
-
// Temporary code to construct the AVM context
|
|
254
|
-
// These data structures will permeate across the simulator when the public executor is phased out
|
|
255
|
-
const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb);
|
|
256
|
-
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
|
|
257
|
-
const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
|
|
258
|
-
// TODO(@spalladino) Load initial gas from the public execution request
|
|
259
|
-
const machineState = new AvmMachineState(1e10, 1e10, 1e10);
|
|
260
|
-
|
|
261
|
-
const context = new AvmContext(worldStateJournal, executionEnv, machineState);
|
|
262
|
-
const simulator = new AvmSimulator(context);
|
|
263
|
-
|
|
264
|
-
const result = await simulator.execute();
|
|
265
|
-
const newWorldState = context.persistableState.flush();
|
|
266
|
-
|
|
267
|
-
// TODO(@spalladino) Read gas left from machineState and return it
|
|
268
|
-
return temporaryConvertAvmResults(execution, newWorldState, result);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
266
|
/**
|
|
272
267
|
* These functions are currently housed in the temporary executor as it relies on access to
|
|
273
268
|
* oracles like the contractsDB and this is the least intrusive way to achieve this.
|
|
@@ -305,7 +300,7 @@ export class PublicExecutor {
|
|
|
305
300
|
|
|
306
301
|
const bbExec = path.join(bbPath, 'build', 'bin', 'bb');
|
|
307
302
|
const bbArgs = ['avm_prove', '-b', bytecodePath, '-d', calldataPath, '-o', proofPath];
|
|
308
|
-
this.log(`calling '${bbExec} ${bbArgs.join(' ')}'`);
|
|
303
|
+
this.log.debug(`calling '${bbExec} ${bbArgs.join(' ')}'`);
|
|
309
304
|
const bbBinary = spawn(bbExec, bbArgs);
|
|
310
305
|
|
|
311
306
|
// The binary writes the proof and the verification key to the write path.
|
|
@@ -314,7 +309,7 @@ export class PublicExecutor {
|
|
|
314
309
|
let stderr: string = '';
|
|
315
310
|
|
|
316
311
|
bbBinary.on('close', () => {
|
|
317
|
-
this.log(`Proof generation complete. Reading proof and vk from ${proofPath}.`);
|
|
312
|
+
this.log.verbose(`Proof generation complete. Reading proof and vk from ${proofPath}.`);
|
|
318
313
|
return resolve(Promise.all([fs.readFile(proofPath), fs.readFile(path.join(artifactsPath, 'vk'))]));
|
|
319
314
|
});
|
|
320
315
|
|
|
@@ -324,7 +319,7 @@ export class PublicExecutor {
|
|
|
324
319
|
});
|
|
325
320
|
bbBinary.stdout.on('end', () => {
|
|
326
321
|
if (stdout.length > 0) {
|
|
327
|
-
this.log(`stdout: ${stdout}`);
|
|
322
|
+
this.log.debug(`stdout: ${stdout}`);
|
|
328
323
|
}
|
|
329
324
|
});
|
|
330
325
|
|
|
@@ -334,7 +329,7 @@ export class PublicExecutor {
|
|
|
334
329
|
});
|
|
335
330
|
bbBinary.stderr.on('end', () => {
|
|
336
331
|
if (stderr.length > 0) {
|
|
337
|
-
this.log(`stderr: ${stderr}`);
|
|
332
|
+
this.log.warn(`stderr: ${stderr}`);
|
|
338
333
|
}
|
|
339
334
|
});
|
|
340
335
|
|
|
@@ -366,7 +361,7 @@ export class PublicExecutor {
|
|
|
366
361
|
|
|
367
362
|
const bbExec = path.join(bbPath, 'build', 'bin', 'bb');
|
|
368
363
|
const bbArgs = ['avm_verify', '-p', proofPath];
|
|
369
|
-
this.log(`calling '${bbPath} ${bbArgs.join(' ')}'`);
|
|
364
|
+
this.log.debug(`calling '${bbPath} ${bbArgs.join(' ')}'`);
|
|
370
365
|
const bbBinary = spawn(bbExec, bbArgs);
|
|
371
366
|
|
|
372
367
|
// The binary prints to stdout 1 if the proof is valid and 0 if it is not.
|
|
@@ -36,13 +36,13 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
36
36
|
* Data for this execution.
|
|
37
37
|
*/
|
|
38
38
|
public readonly execution: PublicExecution,
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
public readonly header: Header,
|
|
40
|
+
public readonly globalVariables: GlobalVariables,
|
|
41
41
|
private readonly packedArgsCache: PackedArgsCache,
|
|
42
42
|
private readonly sideEffectCounter: SideEffectCounter,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
public readonly stateDb: PublicStateDB,
|
|
44
|
+
public readonly contractsDb: PublicContractsDB,
|
|
45
|
+
public readonly commitmentsDb: CommitmentsDB,
|
|
46
46
|
private log = createDebugLogger('aztec:simulator:public_execution_context'),
|
|
47
47
|
) {
|
|
48
48
|
super();
|
|
@@ -120,7 +120,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
120
120
|
public emitUnencryptedLog(log: UnencryptedL2Log) {
|
|
121
121
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/885)
|
|
122
122
|
this.unencryptedLogs.push(log);
|
|
123
|
-
this.log(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
|
|
123
|
+
this.log.verbose(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/**
|
|
@@ -144,7 +144,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
144
144
|
const storageSlot = new Fr(startStorageSlot.value + BigInt(i));
|
|
145
145
|
const sideEffectCounter = this.sideEffectCounter.count();
|
|
146
146
|
const value = await this.storageActions.read(storageSlot, sideEffectCounter);
|
|
147
|
-
this.log(`Oracle storage read: slot=${storageSlot.toString()} value=${value.toString()}`);
|
|
147
|
+
this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value.toString()}`);
|
|
148
148
|
values.push(value);
|
|
149
149
|
}
|
|
150
150
|
return values;
|
|
@@ -163,7 +163,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
163
163
|
const sideEffectCounter = this.sideEffectCounter.count();
|
|
164
164
|
this.storageActions.write(storageSlot, newValue, sideEffectCounter);
|
|
165
165
|
await this.stateDb.storageWrite(this.execution.callContext.storageContractAddress, storageSlot, newValue);
|
|
166
|
-
this.log(`Oracle storage write: slot=${storageSlot.toString()} value=${newValue.toString()}`);
|
|
166
|
+
this.log.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${newValue.toString()}`);
|
|
167
167
|
newValues.push(newValue);
|
|
168
168
|
}
|
|
169
169
|
return newValues;
|
|
@@ -187,17 +187,12 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
187
187
|
isStaticCall = isStaticCall || this.execution.callContext.isStaticCall;
|
|
188
188
|
|
|
189
189
|
const args = this.packedArgsCache.unpack(argsHash);
|
|
190
|
-
this.log
|
|
190
|
+
this.log.verbose(
|
|
191
|
+
`Public function call: addr=${targetContractAddress} selector=${functionSelector} args=${args.join(',')}`,
|
|
192
|
+
);
|
|
191
193
|
|
|
192
194
|
const portalAddress = (await this.contractsDb.getPortalContractAddress(targetContractAddress)) ?? EthAddress.ZERO;
|
|
193
|
-
|
|
194
|
-
const acir = await this.contractsDb.getBytecode(targetContractAddress, functionSelector);
|
|
195
|
-
if (!acir) {
|
|
196
|
-
throw new Error(`Bytecode not found for ${targetContractAddress}:${functionSelector}`);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const functionData = new FunctionData(functionSelector, false);
|
|
200
|
-
|
|
195
|
+
const functionData = new FunctionData(functionSelector, /*isPrivate=*/ false);
|
|
201
196
|
const callContext = CallContext.from({
|
|
202
197
|
msgSender: isDelegateCall ? this.execution.callContext.msgSender : this.execution.contractAddress,
|
|
203
198
|
storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress,
|
|
@@ -227,7 +222,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
227
222
|
this.log,
|
|
228
223
|
);
|
|
229
224
|
|
|
230
|
-
const childExecutionResult = await executePublicFunction(context,
|
|
225
|
+
const childExecutionResult = await executePublicFunction(context, /*nested=*/ true);
|
|
231
226
|
|
|
232
227
|
if (isStaticCall) {
|
|
233
228
|
checkValidStaticCall(
|
|
@@ -240,7 +235,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
240
235
|
}
|
|
241
236
|
|
|
242
237
|
this.nestedExecutions.push(childExecutionResult);
|
|
243
|
-
this.log(`Returning from nested call: ret=${childExecutionResult.returnValues.join(', ')}`);
|
|
238
|
+
this.log.debug(`Returning from nested call: ret=${childExecutionResult.returnValues.join(', ')}`);
|
|
244
239
|
|
|
245
240
|
return childExecutionResult.returnValues;
|
|
246
241
|
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// All code in this file needs to die once the public executor is phased out in favor of the AVM.
|
|
2
|
+
import { UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types';
|
|
3
|
+
import {
|
|
4
|
+
CallContext,
|
|
5
|
+
ContractStorageRead,
|
|
6
|
+
ContractStorageUpdateRequest,
|
|
7
|
+
FunctionData,
|
|
8
|
+
type GlobalVariables,
|
|
9
|
+
type Header,
|
|
10
|
+
L2ToL1Message,
|
|
11
|
+
ReadRequest,
|
|
12
|
+
SideEffect,
|
|
13
|
+
SideEffectLinkedToNoteHash,
|
|
14
|
+
} from '@aztec/circuits.js';
|
|
15
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
16
|
+
|
|
17
|
+
import { type AvmContext } from '../avm/avm_context.js';
|
|
18
|
+
import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
|
|
19
|
+
import { AvmContractCallResults } from '../avm/avm_message_call_result.js';
|
|
20
|
+
import { type JournalData } from '../avm/journal/journal.js';
|
|
21
|
+
import { Mov } from '../avm/opcodes/memory.js';
|
|
22
|
+
import { createSimulationError } from '../common/errors.js';
|
|
23
|
+
import { PackedArgsCache, SideEffectCounter } from '../index.js';
|
|
24
|
+
import { type PublicExecution, type PublicExecutionResult } from './execution.js';
|
|
25
|
+
import { PublicExecutionContext } from './public_execution_context.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Convert a PublicExecution(Environment) object to an AvmExecutionEnvironment
|
|
29
|
+
*
|
|
30
|
+
* @param current
|
|
31
|
+
* @param globalVariables
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
export function createAvmExecutionEnvironment(
|
|
35
|
+
current: PublicExecution,
|
|
36
|
+
header: Header,
|
|
37
|
+
globalVariables: GlobalVariables,
|
|
38
|
+
): AvmExecutionEnvironment {
|
|
39
|
+
return new AvmExecutionEnvironment(
|
|
40
|
+
current.contractAddress,
|
|
41
|
+
current.callContext.storageContractAddress,
|
|
42
|
+
current.callContext.msgSender, // TODO: origin is not available
|
|
43
|
+
current.callContext.msgSender,
|
|
44
|
+
current.callContext.portalContractAddress,
|
|
45
|
+
/*feePerL1Gas=*/ Fr.zero(),
|
|
46
|
+
/*feePerL2Gas=*/ Fr.zero(),
|
|
47
|
+
/*feePerDaGas=*/ Fr.zero(),
|
|
48
|
+
/*contractCallDepth=*/ Fr.zero(),
|
|
49
|
+
header,
|
|
50
|
+
globalVariables,
|
|
51
|
+
current.callContext.isStaticCall,
|
|
52
|
+
current.callContext.isDelegateCall,
|
|
53
|
+
current.args,
|
|
54
|
+
current.functionData.selector,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function createPublicExecutionContext(avmContext: AvmContext, calldata: Fr[]): PublicExecutionContext {
|
|
59
|
+
const sideEffectCounter = avmContext.persistableState.trace.accessCounter;
|
|
60
|
+
const callContext = CallContext.from({
|
|
61
|
+
msgSender: avmContext.environment.sender,
|
|
62
|
+
storageContractAddress: avmContext.environment.storageAddress,
|
|
63
|
+
portalContractAddress: avmContext.environment.portal,
|
|
64
|
+
functionSelector: avmContext.environment.temporaryFunctionSelector,
|
|
65
|
+
isDelegateCall: avmContext.environment.isDelegateCall,
|
|
66
|
+
isStaticCall: avmContext.environment.isStaticCall,
|
|
67
|
+
sideEffectCounter: sideEffectCounter,
|
|
68
|
+
});
|
|
69
|
+
const functionData = new FunctionData(avmContext.environment.temporaryFunctionSelector, /*isPrivate=*/ false);
|
|
70
|
+
const execution: PublicExecution = {
|
|
71
|
+
contractAddress: avmContext.environment.address,
|
|
72
|
+
callContext,
|
|
73
|
+
args: calldata,
|
|
74
|
+
functionData,
|
|
75
|
+
};
|
|
76
|
+
const packedArgs = PackedArgsCache.create([]);
|
|
77
|
+
|
|
78
|
+
const context = new PublicExecutionContext(
|
|
79
|
+
execution,
|
|
80
|
+
avmContext.environment.header,
|
|
81
|
+
avmContext.environment.globals,
|
|
82
|
+
packedArgs,
|
|
83
|
+
new SideEffectCounter(sideEffectCounter),
|
|
84
|
+
avmContext.persistableState.hostStorage.publicStateDb,
|
|
85
|
+
avmContext.persistableState.hostStorage.contractsDb,
|
|
86
|
+
avmContext.persistableState.hostStorage.commitmentsDb,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
return context;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Convert the result of an AVM contract call to a PublicExecutionResult for the public kernel
|
|
94
|
+
*
|
|
95
|
+
* @param execution
|
|
96
|
+
* @param newWorldState
|
|
97
|
+
* @param result
|
|
98
|
+
* @returns
|
|
99
|
+
*/
|
|
100
|
+
export async function convertAvmResults(
|
|
101
|
+
executionContext: PublicExecutionContext,
|
|
102
|
+
newWorldState: JournalData,
|
|
103
|
+
result: AvmContractCallResults,
|
|
104
|
+
): Promise<PublicExecutionResult> {
|
|
105
|
+
const execution = executionContext.execution;
|
|
106
|
+
|
|
107
|
+
const contractStorageReads: ContractStorageRead[] = newWorldState.storageReads.map(
|
|
108
|
+
read => new ContractStorageRead(read.slot, read.value, read.counter.toNumber()),
|
|
109
|
+
);
|
|
110
|
+
const contractStorageUpdateRequests: ContractStorageUpdateRequest[] = newWorldState.storageWrites.map(
|
|
111
|
+
write => new ContractStorageUpdateRequest(write.slot, write.value, write.counter.toNumber()),
|
|
112
|
+
);
|
|
113
|
+
// We need to write the storage updates to the DB, because that's what the ACVM expects.
|
|
114
|
+
// Assumes the updates are in the right order.
|
|
115
|
+
for (const write of newWorldState.storageWrites) {
|
|
116
|
+
await executionContext.stateDb.storageWrite(write.storageAddress, write.slot, write.value);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const newNoteHashes = newWorldState.newNoteHashes.map(
|
|
120
|
+
noteHash => new SideEffect(noteHash.noteHash, noteHash.counter),
|
|
121
|
+
);
|
|
122
|
+
const nullifierReadRequests: ReadRequest[] = newWorldState.nullifierChecks
|
|
123
|
+
.filter(nullifierCheck => nullifierCheck.exists)
|
|
124
|
+
.map(nullifierCheck => new ReadRequest(nullifierCheck.nullifier, nullifierCheck.counter.toNumber()));
|
|
125
|
+
const nullifierNonExistentReadRequests: ReadRequest[] = newWorldState.nullifierChecks
|
|
126
|
+
.filter(nullifierCheck => !nullifierCheck.exists)
|
|
127
|
+
.map(nullifierCheck => new ReadRequest(nullifierCheck.nullifier, nullifierCheck.counter.toNumber()));
|
|
128
|
+
const newNullifiers: SideEffectLinkedToNoteHash[] = newWorldState.newNullifiers.map(
|
|
129
|
+
tracedNullifier =>
|
|
130
|
+
new SideEffectLinkedToNoteHash(
|
|
131
|
+
/*value=*/ tracedNullifier.nullifier,
|
|
132
|
+
/*noteHash=*/ Fr.ZERO, // NEEDED?
|
|
133
|
+
tracedNullifier.counter,
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
const unencryptedLogs: UnencryptedFunctionL2Logs = new UnencryptedFunctionL2Logs(
|
|
137
|
+
newWorldState.newLogs.map(log => new UnencryptedL2Log(log.contractAddress, log.selector, log.data)),
|
|
138
|
+
);
|
|
139
|
+
const newL2ToL1Messages = newWorldState.newL1Messages.map(m => new L2ToL1Message(m.recipient, m.content));
|
|
140
|
+
|
|
141
|
+
const returnValues = result.output;
|
|
142
|
+
|
|
143
|
+
// TODO: Support nested executions.
|
|
144
|
+
const nestedExecutions: PublicExecutionResult[] = [];
|
|
145
|
+
// TODO keep track of side effect counters
|
|
146
|
+
const startSideEffectCounter = Fr.ZERO;
|
|
147
|
+
const endSideEffectCounter = Fr.ZERO;
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
execution,
|
|
151
|
+
nullifierReadRequests,
|
|
152
|
+
nullifierNonExistentReadRequests,
|
|
153
|
+
newNoteHashes,
|
|
154
|
+
newL2ToL1Messages,
|
|
155
|
+
startSideEffectCounter,
|
|
156
|
+
endSideEffectCounter,
|
|
157
|
+
newNullifiers,
|
|
158
|
+
contractStorageReads,
|
|
159
|
+
contractStorageUpdateRequests,
|
|
160
|
+
returnValues,
|
|
161
|
+
nestedExecutions,
|
|
162
|
+
unencryptedLogs,
|
|
163
|
+
reverted: result.reverted,
|
|
164
|
+
revertReason: result.revertReason ? createSimulationError(result.revertReason) : undefined,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function convertPublicExecutionResult(res: PublicExecutionResult): AvmContractCallResults {
|
|
169
|
+
return new AvmContractCallResults(res.reverted, res.returnValues, res.revertReason);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function updateAvmContextFromPublicExecutionResult(ctx: AvmContext, result: PublicExecutionResult): void {
|
|
173
|
+
// We have to push these manually and not use the trace* functions
|
|
174
|
+
// so that we respect the side effect counters.
|
|
175
|
+
for (const readRequest of result.contractStorageReads) {
|
|
176
|
+
ctx.persistableState.trace.publicStorageReads.push({
|
|
177
|
+
storageAddress: ctx.environment.storageAddress,
|
|
178
|
+
exists: true, // FIXME
|
|
179
|
+
slot: readRequest.storageSlot,
|
|
180
|
+
value: readRequest.currentValue,
|
|
181
|
+
counter: new Fr(readRequest.sideEffectCounter ?? Fr.ZERO),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
for (const updateRequest of result.contractStorageUpdateRequests) {
|
|
186
|
+
ctx.persistableState.trace.publicStorageWrites.push({
|
|
187
|
+
storageAddress: ctx.environment.storageAddress,
|
|
188
|
+
slot: updateRequest.storageSlot,
|
|
189
|
+
value: updateRequest.newValue,
|
|
190
|
+
counter: new Fr(updateRequest.sideEffectCounter ?? Fr.ZERO),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// We need to manually populate the cache.
|
|
194
|
+
ctx.persistableState.publicStorage.write(
|
|
195
|
+
ctx.environment.storageAddress,
|
|
196
|
+
updateRequest.storageSlot,
|
|
197
|
+
updateRequest.newValue,
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
for (const nullifier of result.newNullifiers) {
|
|
202
|
+
ctx.persistableState.trace.newNullifiers.push({
|
|
203
|
+
storageAddress: ctx.environment.storageAddress,
|
|
204
|
+
nullifier: nullifier.value,
|
|
205
|
+
counter: nullifier.counter,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
for (const noteHash of result.newNoteHashes) {
|
|
210
|
+
ctx.persistableState.trace.newNoteHashes.push({
|
|
211
|
+
storageAddress: ctx.environment.storageAddress,
|
|
212
|
+
noteHash: noteHash.value,
|
|
213
|
+
counter: noteHash.counter,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
for (const message of result.newL2ToL1Messages) {
|
|
218
|
+
ctx.persistableState.newL1Messages.push(message);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
for (const log of result.unencryptedLogs.logs) {
|
|
222
|
+
ctx.persistableState.newLogs.push(new UnencryptedL2Log(log.contractAddress, log.selector, log.data));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const AVM_MAGIC_SUFFIX = Buffer.from([
|
|
227
|
+
Mov.opcode, // opcode
|
|
228
|
+
0x00, // indirect
|
|
229
|
+
...Buffer.from('000018ca', 'hex'), // srcOffset
|
|
230
|
+
...Buffer.from('000018ca', 'hex'), // dstOffset
|
|
231
|
+
]);
|
|
232
|
+
|
|
233
|
+
export function markBytecodeAsAvm(bytecode: Buffer): Buffer {
|
|
234
|
+
return Buffer.concat([bytecode, AVM_MAGIC_SUFFIX]);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function isAvmBytecode(bytecode: Buffer): boolean {
|
|
238
|
+
const magicSize = AVM_MAGIC_SUFFIX.length;
|
|
239
|
+
return bytecode.subarray(-magicSize).equals(AVM_MAGIC_SUFFIX);
|
|
240
|
+
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import { type GlobalVariables } from '@aztec/circuits.js';
|
|
3
|
-
import { type PublicExecution, type PublicExecutionResult } from '../public/execution.js';
|
|
4
|
-
import { AvmExecutionEnvironment } from './avm_execution_environment.js';
|
|
5
|
-
import { type AvmContractCallResults } from './avm_message_call_result.js';
|
|
6
|
-
import { type JournalData } from './journal/journal.js';
|
|
7
|
-
/** Temporary Method
|
|
8
|
-
*
|
|
9
|
-
* Convert a PublicExecution(Environment) object to an AvmExecutionEnvironment
|
|
10
|
-
*
|
|
11
|
-
* @param current
|
|
12
|
-
* @param globalVariables
|
|
13
|
-
* @returns
|
|
14
|
-
*/
|
|
15
|
-
export declare function temporaryCreateAvmExecutionEnvironment(current: PublicExecution, globalVariables: GlobalVariables): AvmExecutionEnvironment;
|
|
16
|
-
/** Temporary Method
|
|
17
|
-
*
|
|
18
|
-
* Convert the result of an AVM contract call to a PublicExecutionResult for the public kernel
|
|
19
|
-
*
|
|
20
|
-
* @param execution
|
|
21
|
-
* @param newWorldState
|
|
22
|
-
* @param result
|
|
23
|
-
* @returns
|
|
24
|
-
*/
|
|
25
|
-
export declare function temporaryConvertAvmResults(execution: PublicExecution, newWorldState: JournalData, result: AvmContractCallResults): PublicExecutionResult;
|
|
26
|
-
export declare function isAvmBytecode(bytecode: Buffer): boolean;
|
|
27
|
-
//# sourceMappingURL=temporary_executor_migration.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"temporary_executor_migration.d.ts","sourceRoot":"","sources":["../../src/avm/temporary_executor_migration.ts"],"names":[],"mappings":";AAEA,OAAO,EAGL,KAAK,eAAe,EAKrB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD;;;;;;;GAOG;AACH,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,eAAe,EACxB,eAAe,EAAE,eAAe,GAC/B,uBAAuB,CAkBzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,eAAe,EAC1B,aAAa,EAAE,WAAW,EAC1B,MAAM,EAAE,sBAAsB,GAC7B,qBAAqB,CA4DvB;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CASvD"}
|