@aztec/simulator 0.36.0 → 0.38.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 -1
- package/dest/acvm/acvm.d.ts.map +1 -1
- package/dest/acvm/acvm.js +2 -2
- package/dest/acvm/oracle/oracle.d.ts +6 -4
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +39 -8
- package/dest/acvm/oracle/typed_oracle.d.ts +5 -3
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +9 -3
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +2 -1
- package/dest/avm/avm_memory_types.d.ts +1 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +3 -1
- package/dest/avm/journal/journal.d.ts +20 -1
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +69 -9
- package/dest/avm/journal/nullifiers.d.ts +3 -1
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +14 -6
- package/dest/avm/journal/public_storage.d.ts +10 -1
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.js +17 -2
- package/dest/avm/journal/trace.d.ts +1 -4
- package/dest/avm/journal/trace.d.ts.map +1 -1
- package/dest/avm/journal/trace.js +4 -5
- package/dest/avm/journal/trace_types.d.ts +1 -0
- package/dest/avm/journal/trace_types.d.ts.map +1 -1
- package/dest/avm/journal/trace_types.js +1 -1
- package/dest/avm/opcodes/bitwise.d.ts +4 -1
- package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
- package/dest/avm/opcodes/bitwise.js +14 -2
- package/dest/avm/opcodes/environment_getters.d.ts +5 -0
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +8 -1
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +14 -13
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +3 -2
- package/dest/avm/serialization/instruction_serialization.d.ts +39 -38
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +40 -39
- package/dest/client/client_execution_context.d.ts +31 -18
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +48 -31
- package/dest/client/db_oracle.d.ts +11 -4
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/execution_result.d.ts +19 -15
- package/dest/client/execution_result.d.ts.map +1 -1
- package/dest/client/execution_result.js +45 -12
- package/dest/client/logs_cache.d.ts +33 -0
- package/dest/client/logs_cache.d.ts.map +1 -0
- package/dest/client/logs_cache.js +59 -0
- package/dest/client/private_execution.d.ts +2 -2
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +3 -7
- package/dest/client/simulator.d.ts +3 -3
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +3 -2
- package/dest/client/unconstrained_execution.d.ts +2 -2
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +1 -1
- package/dest/client/view_data_oracle.d.ts +7 -0
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +10 -1
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +3 -1
- package/dest/public/abstract_phase_manager.d.ts +2 -0
- package/dest/public/abstract_phase_manager.d.ts.map +1 -1
- package/dest/public/abstract_phase_manager.js +13 -6
- package/dest/public/execution.d.ts +9 -0
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor.d.ts +2 -2
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +34 -14
- package/dest/public/public_execution_context.d.ts +10 -4
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +19 -6
- package/dest/public/tail_phase_manager.d.ts +0 -1
- package/dest/public/tail_phase_manager.d.ts.map +1 -1
- package/dest/public/tail_phase_manager.js +3 -26
- package/dest/public/transitional_adaptors.d.ts +4 -17
- package/dest/public/transitional_adaptors.d.ts.map +1 -1
- package/dest/public/transitional_adaptors.js +27 -119
- package/package.json +8 -8
- package/src/acvm/acvm.ts +2 -2
- package/src/acvm/oracle/oracle.ts +63 -10
- package/src/acvm/oracle/typed_oracle.ts +12 -3
- package/src/avm/avm_gas.ts +1 -0
- package/src/avm/avm_memory_types.ts +1 -1
- package/src/avm/avm_simulator.ts +2 -0
- package/src/avm/journal/journal.ts +133 -9
- package/src/avm/journal/nullifiers.ts +19 -8
- package/src/avm/journal/public_storage.ts +23 -2
- package/src/avm/journal/trace.ts +3 -4
- package/src/avm/journal/trace_types.ts +1 -0
- package/src/avm/opcodes/bitwise.ts +18 -7
- package/src/avm/opcodes/environment_getters.ts +9 -0
- package/src/avm/opcodes/external_calls.ts +21 -16
- package/src/avm/serialization/bytecode_serialization.ts +2 -0
- package/src/avm/serialization/instruction_serialization.ts +1 -0
- package/src/client/client_execution_context.ts +55 -31
- package/src/client/db_oracle.ts +12 -10
- package/src/client/execution_result.ts +55 -24
- package/src/client/logs_cache.ts +65 -0
- package/src/client/private_execution.ts +4 -10
- package/src/client/simulator.ts +6 -4
- package/src/client/unconstrained_execution.ts +2 -2
- package/src/client/view_data_oracle.ts +10 -0
- package/src/mocks/fixtures.ts +2 -0
- package/src/public/abstract_phase_manager.ts +13 -5
- package/src/public/execution.ts +9 -0
- package/src/public/executor.ts +47 -10
- package/src/public/public_execution_context.ts +18 -4
- package/src/public/tail_phase_manager.ts +2 -34
- package/src/public/transitional_adaptors.ts +39 -178
package/src/public/executor.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
Gas,
|
|
5
5
|
type GlobalVariables,
|
|
6
6
|
type Header,
|
|
7
|
+
type Nullifier,
|
|
7
8
|
PublicCircuitPublicInputs,
|
|
8
9
|
type TxContext,
|
|
9
10
|
} from '@aztec/circuits.js';
|
|
@@ -26,7 +27,7 @@ import { PackedValuesCache } from '../common/packed_values_cache.js';
|
|
|
26
27
|
import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db.js';
|
|
27
28
|
import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js';
|
|
28
29
|
import { PublicExecutionContext } from './public_execution_context.js';
|
|
29
|
-
import {
|
|
30
|
+
import { convertAvmResultsToPxResult, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Execute a public function and return the execution result.
|
|
@@ -46,15 +47,23 @@ export async function executePublicFunction(
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
if (isAvmBytecode(bytecode)) {
|
|
49
|
-
return await
|
|
50
|
+
return await executeTopLevelPublicFunctionAvm(context, bytecode);
|
|
50
51
|
} else {
|
|
51
52
|
return await executePublicFunctionAcvm(context, bytecode, nested);
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Execute a top-level public function call (the first call in an enqueued-call/execution-request) in the AVM.
|
|
58
|
+
* Translate the results back to the PublicExecutionResult format.
|
|
59
|
+
*/
|
|
60
|
+
async function executeTopLevelPublicFunctionAvm(
|
|
61
|
+
executionContext: PublicExecutionContext,
|
|
62
|
+
bytecode: Buffer,
|
|
63
|
+
): Promise<PublicExecutionResult> {
|
|
56
64
|
const address = executionContext.execution.contractAddress;
|
|
57
65
|
const selector = executionContext.execution.functionData.selector;
|
|
66
|
+
const startGas = executionContext.availableGas;
|
|
58
67
|
const log = createDebugLogger('aztec:simulator:public_execution');
|
|
59
68
|
log.verbose(`[AVM] Executing public external function ${address.toString()}:${selector}.`);
|
|
60
69
|
|
|
@@ -65,7 +74,15 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
|
|
|
65
74
|
executionContext.contractsDb,
|
|
66
75
|
executionContext.commitmentsDb,
|
|
67
76
|
);
|
|
77
|
+
|
|
78
|
+
// TODO(6207): add sideEffectCounter to persistableState construction
|
|
79
|
+
// or modify the PersistableStateManager to manage rollbacks across enqueued-calls and transactions.
|
|
68
80
|
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
|
|
81
|
+
const startSideEffectCounter = executionContext.execution.callContext.sideEffectCounter;
|
|
82
|
+
for (const nullifier of executionContext.pendingNullifiers) {
|
|
83
|
+
worldStateJournal.nullifiers.cache.appendSiloed(nullifier.value);
|
|
84
|
+
}
|
|
85
|
+
worldStateJournal.trace.accessCounter = startSideEffectCounter;
|
|
69
86
|
|
|
70
87
|
const executionEnv = createAvmExecutionEnvironment(
|
|
71
88
|
executionContext.execution,
|
|
@@ -75,18 +92,30 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
|
|
|
75
92
|
executionContext.transactionFee,
|
|
76
93
|
);
|
|
77
94
|
|
|
78
|
-
const machineState = new AvmMachineState(
|
|
79
|
-
const
|
|
80
|
-
const simulator = new AvmSimulator(
|
|
95
|
+
const machineState = new AvmMachineState(startGas);
|
|
96
|
+
const avmContext = new AvmContext(worldStateJournal, executionEnv, machineState);
|
|
97
|
+
const simulator = new AvmSimulator(avmContext);
|
|
81
98
|
|
|
82
|
-
const
|
|
83
|
-
|
|
99
|
+
const avmResult = await simulator.executeBytecode(bytecode);
|
|
100
|
+
|
|
101
|
+
// Commit the journals state to the DBs since this is a top-level execution.
|
|
102
|
+
// Observe that this will write all the state changes to the DBs, not only the latest for each slot.
|
|
103
|
+
// However, the underlying DB keep a cache and will only write the latest state to disk.
|
|
104
|
+
await avmContext.persistableState.publicStorage.commitToDB();
|
|
84
105
|
|
|
85
106
|
log.verbose(
|
|
86
|
-
`[AVM] ${address.toString()}:${selector} returned, reverted: ${
|
|
107
|
+
`[AVM] ${address.toString()}:${selector} returned, reverted: ${avmResult.reverted}, reason: ${
|
|
108
|
+
avmResult.revertReason
|
|
109
|
+
}.`,
|
|
87
110
|
);
|
|
88
111
|
|
|
89
|
-
return
|
|
112
|
+
return convertAvmResultsToPxResult(
|
|
113
|
+
avmResult,
|
|
114
|
+
startSideEffectCounter,
|
|
115
|
+
executionContext.execution,
|
|
116
|
+
startGas,
|
|
117
|
+
avmContext,
|
|
118
|
+
);
|
|
90
119
|
}
|
|
91
120
|
|
|
92
121
|
async function executePublicFunctionAcvm(
|
|
@@ -159,6 +188,8 @@ async function executePublicFunctionAcvm(
|
|
|
159
188
|
nestedExecutions: [],
|
|
160
189
|
unencryptedLogsHashes: [],
|
|
161
190
|
unencryptedLogs: UnencryptedFunctionL2Logs.empty(),
|
|
191
|
+
unencryptedLogPreimagesLength: new Fr(4n), // empty logs have len 4
|
|
192
|
+
allUnencryptedLogs: UnencryptedFunctionL2Logs.empty(),
|
|
162
193
|
reverted,
|
|
163
194
|
revertReason,
|
|
164
195
|
startGasLeft: context.availableGas,
|
|
@@ -182,6 +213,7 @@ async function executePublicFunctionAcvm(
|
|
|
182
213
|
startSideEffectCounter,
|
|
183
214
|
endSideEffectCounter,
|
|
184
215
|
unencryptedLogsHashes: unencryptedLogsHashesPadded,
|
|
216
|
+
unencryptedLogPreimagesLength,
|
|
185
217
|
} = PublicCircuitPublicInputs.fromFields(returnWitness);
|
|
186
218
|
const returnValues = await context.unpackReturns(returnsHash);
|
|
187
219
|
|
|
@@ -207,6 +239,7 @@ async function executePublicFunctionAcvm(
|
|
|
207
239
|
|
|
208
240
|
const nestedExecutions = context.getNestedExecutions();
|
|
209
241
|
const unencryptedLogs = context.getUnencryptedLogs();
|
|
242
|
+
const allUnencryptedLogs = context.getAllUnencryptedLogs();
|
|
210
243
|
|
|
211
244
|
// TODO(palla/gas): We should be loading these values from the returned PublicCircuitPublicInputs
|
|
212
245
|
const startGasLeft = context.availableGas;
|
|
@@ -227,6 +260,8 @@ async function executePublicFunctionAcvm(
|
|
|
227
260
|
nestedExecutions,
|
|
228
261
|
unencryptedLogsHashes,
|
|
229
262
|
unencryptedLogs,
|
|
263
|
+
unencryptedLogPreimagesLength,
|
|
264
|
+
allUnencryptedLogs,
|
|
230
265
|
reverted: false,
|
|
231
266
|
revertReason: undefined,
|
|
232
267
|
startGasLeft,
|
|
@@ -258,6 +293,7 @@ export class PublicExecutor {
|
|
|
258
293
|
globalVariables: GlobalVariables,
|
|
259
294
|
availableGas: Gas,
|
|
260
295
|
txContext: TxContext,
|
|
296
|
+
pendingNullifiers: Nullifier[],
|
|
261
297
|
transactionFee: Fr = Fr.ZERO,
|
|
262
298
|
sideEffectCounter: number = 0,
|
|
263
299
|
): Promise<PublicExecutionResult> {
|
|
@@ -277,6 +313,7 @@ export class PublicExecutor {
|
|
|
277
313
|
availableGas,
|
|
278
314
|
transactionFee,
|
|
279
315
|
txContext.gasSettings,
|
|
316
|
+
pendingNullifiers,
|
|
280
317
|
);
|
|
281
318
|
|
|
282
319
|
const executionResult = await executePublicFunction(context, /*nested=*/ false);
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type GasSettings,
|
|
8
8
|
type GlobalVariables,
|
|
9
9
|
type Header,
|
|
10
|
+
type Nullifier,
|
|
10
11
|
PublicContextInputs,
|
|
11
12
|
} from '@aztec/circuits.js';
|
|
12
13
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
@@ -37,13 +38,18 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
37
38
|
public readonly header: Header,
|
|
38
39
|
public readonly globalVariables: GlobalVariables,
|
|
39
40
|
private readonly packedValuesCache: PackedValuesCache,
|
|
40
|
-
|
|
41
|
+
// TRANSITIONAL: once AVM-ACVM interoperability is removed (fully functional AVM), sideEffectCounter can be made private
|
|
42
|
+
public readonly sideEffectCounter: SideEffectCounter,
|
|
41
43
|
public readonly stateDb: PublicStateDB,
|
|
42
44
|
public readonly contractsDb: PublicContractsDB,
|
|
43
45
|
public readonly commitmentsDb: CommitmentsDB,
|
|
44
46
|
public readonly availableGas: Gas,
|
|
45
47
|
public readonly transactionFee: Fr,
|
|
46
48
|
public readonly gasSettings: GasSettings,
|
|
49
|
+
public readonly pendingNullifiers: Nullifier[],
|
|
50
|
+
// Unencrypted logs emitted during this call AND any nested calls
|
|
51
|
+
// Useful for maintaining correct ordering in ts
|
|
52
|
+
private allUnencryptedLogs: UnencryptedL2Log[] = [],
|
|
47
53
|
private log = createDebugLogger('aztec:simulator:public_execution_context'),
|
|
48
54
|
) {
|
|
49
55
|
super();
|
|
@@ -87,6 +93,13 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
87
93
|
return new UnencryptedFunctionL2Logs(this.unencryptedLogs);
|
|
88
94
|
}
|
|
89
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Return the encrypted logs emitted during this execution, including nested calls.
|
|
98
|
+
*/
|
|
99
|
+
public getAllUnencryptedLogs() {
|
|
100
|
+
return new UnencryptedFunctionL2Logs(this.allUnencryptedLogs);
|
|
101
|
+
}
|
|
102
|
+
|
|
90
103
|
/**
|
|
91
104
|
* Return the data read and updated during this execution.
|
|
92
105
|
*/
|
|
@@ -135,11 +148,10 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
135
148
|
* Emit an unencrypted log.
|
|
136
149
|
* @param log - The unencrypted log to be emitted.
|
|
137
150
|
*/
|
|
138
|
-
public override emitUnencryptedLog(log: UnencryptedL2Log) {
|
|
139
|
-
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/885)
|
|
151
|
+
public override emitUnencryptedLog(log: UnencryptedL2Log, _counter: number) {
|
|
140
152
|
this.unencryptedLogs.push(log);
|
|
153
|
+
this.allUnencryptedLogs.push(log);
|
|
141
154
|
this.log.verbose(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
|
|
142
|
-
return Fr.fromBuffer(log.hash());
|
|
143
155
|
}
|
|
144
156
|
|
|
145
157
|
/**
|
|
@@ -229,6 +241,8 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
229
241
|
this.availableGas,
|
|
230
242
|
this.transactionFee,
|
|
231
243
|
this.gasSettings,
|
|
244
|
+
/*pendingNullifiers=*/ [],
|
|
245
|
+
this.allUnencryptedLogs,
|
|
232
246
|
this.log,
|
|
233
247
|
);
|
|
234
248
|
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type PublicKernelRequest,
|
|
3
|
-
PublicKernelType,
|
|
4
|
-
type Tx,
|
|
5
|
-
UnencryptedFunctionL2Logs,
|
|
6
|
-
type UnencryptedL2Log,
|
|
7
|
-
} from '@aztec/circuit-types';
|
|
1
|
+
import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types';
|
|
8
2
|
import {
|
|
9
3
|
Fr,
|
|
10
4
|
type GlobalVariables,
|
|
@@ -57,8 +51,6 @@ export class TailPhaseManager extends AbstractPhaseManager {
|
|
|
57
51
|
throw err;
|
|
58
52
|
},
|
|
59
53
|
);
|
|
60
|
-
// Temporary hack. Should sort them in the tail circuit.
|
|
61
|
-
this.patchLogsOrdering(tx, previousPublicKernelOutput);
|
|
62
54
|
// commit the state updates from this transaction
|
|
63
55
|
await this.publicStateDB.commit();
|
|
64
56
|
|
|
@@ -163,33 +155,9 @@ export class TailPhaseManager extends AbstractPhaseManager {
|
|
|
163
155
|
}
|
|
164
156
|
|
|
165
157
|
private sortLogsHashes<N extends number>(unencryptedLogsHashes: Tuple<SideEffect, N>): Tuple<SideEffect, N> {
|
|
158
|
+
// TODO(6052): logs here may have duplicate counters from nested calls
|
|
166
159
|
return sortByCounter(
|
|
167
160
|
unencryptedLogsHashes.map(n => ({ ...n, counter: n.counter.toNumber(), isEmpty: () => n.isEmpty() })),
|
|
168
161
|
).map(h => new SideEffect(h.value, new Fr(h.counter))) as Tuple<SideEffect, N>;
|
|
169
162
|
}
|
|
170
|
-
|
|
171
|
-
// As above, this is a hack for unencrypted logs ordering, now they are sorted. Since the public kernel
|
|
172
|
-
// cannot keep track of side effects that happen after or before a nested call, we override the gathered logs.
|
|
173
|
-
// As a sanity check, we at least verify that the elements are the same, so we are only tweaking their ordering.
|
|
174
|
-
// See same fn in pxe_service.ts
|
|
175
|
-
// Added as part of resolving #5017
|
|
176
|
-
private patchLogsOrdering(tx: Tx, publicInputs: PublicKernelCircuitPublicInputs) {
|
|
177
|
-
const unencLogs = tx.unencryptedLogs.unrollLogs();
|
|
178
|
-
const sortedUnencLogs = publicInputs.end.unencryptedLogsHashes;
|
|
179
|
-
|
|
180
|
-
const finalUnencLogs: UnencryptedL2Log[] = [];
|
|
181
|
-
sortedUnencLogs.forEach((sideEffect: SideEffect) => {
|
|
182
|
-
if (!sideEffect.isEmpty()) {
|
|
183
|
-
const isLog = (log: UnencryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value);
|
|
184
|
-
const thisLogIndex = unencLogs.findIndex(isLog);
|
|
185
|
-
finalUnencLogs.push(unencLogs[thisLogIndex]);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
const unencryptedLogs = new UnencryptedFunctionL2Logs(finalUnencLogs);
|
|
189
|
-
|
|
190
|
-
tx.unencryptedLogs.functionLogs[0] = unencryptedLogs;
|
|
191
|
-
for (let i = 1; i < tx.unencryptedLogs.functionLogs.length; i++) {
|
|
192
|
-
tx.unencryptedLogs.functionLogs[i] = UnencryptedFunctionL2Logs.empty();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
163
|
}
|
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
// All code in this file needs to die once the public executor is phased out in favor of the AVM.
|
|
2
|
-
import { UnencryptedFunctionL2Logs
|
|
2
|
+
import { UnencryptedFunctionL2Logs } from '@aztec/circuit-types';
|
|
3
3
|
import {
|
|
4
4
|
CallContext,
|
|
5
|
-
ContractStorageRead,
|
|
6
|
-
ContractStorageUpdateRequest,
|
|
7
5
|
FunctionData,
|
|
8
|
-
Gas,
|
|
6
|
+
type Gas,
|
|
9
7
|
type GasSettings,
|
|
10
8
|
type GlobalVariables,
|
|
11
9
|
type Header,
|
|
12
|
-
L2ToL1Message,
|
|
13
|
-
NoteHash,
|
|
14
|
-
Nullifier,
|
|
15
|
-
ReadRequest,
|
|
16
|
-
SideEffect,
|
|
17
10
|
} from '@aztec/circuits.js';
|
|
18
11
|
import { Fr } from '@aztec/foundation/fields';
|
|
19
12
|
|
|
20
13
|
import { type AvmContext } from '../avm/avm_context.js';
|
|
21
14
|
import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
|
|
22
|
-
import { type
|
|
23
|
-
import { AvmContractCallResults } from '../avm/avm_message_call_result.js';
|
|
24
|
-
import { type JournalData } from '../avm/journal/journal.js';
|
|
15
|
+
import { type AvmContractCallResults } from '../avm/avm_message_call_result.js';
|
|
25
16
|
import { Mov } from '../avm/opcodes/memory.js';
|
|
26
17
|
import { createSimulationError } from '../common/errors.js';
|
|
27
|
-
import { PackedValuesCache, SideEffectCounter } from '../index.js';
|
|
28
18
|
import { type PublicExecution, type PublicExecutionResult } from './execution.js';
|
|
29
|
-
import { PublicExecutionContext } from './public_execution_context.js';
|
|
30
19
|
|
|
31
20
|
/**
|
|
32
21
|
* Convert a PublicExecution(Environment) object to an AvmExecutionEnvironment
|
|
@@ -60,184 +49,56 @@ export function createAvmExecutionEnvironment(
|
|
|
60
49
|
);
|
|
61
50
|
}
|
|
62
51
|
|
|
63
|
-
export function
|
|
64
|
-
|
|
52
|
+
export function createPublicExecution(
|
|
53
|
+
startSideEffectCounter: number,
|
|
54
|
+
avmEnvironment: AvmExecutionEnvironment,
|
|
55
|
+
calldata: Fr[],
|
|
56
|
+
): PublicExecution {
|
|
65
57
|
const callContext = CallContext.from({
|
|
66
|
-
msgSender:
|
|
67
|
-
storageContractAddress:
|
|
68
|
-
functionSelector:
|
|
69
|
-
isDelegateCall:
|
|
70
|
-
isStaticCall:
|
|
71
|
-
sideEffectCounter:
|
|
58
|
+
msgSender: avmEnvironment.sender,
|
|
59
|
+
storageContractAddress: avmEnvironment.storageAddress,
|
|
60
|
+
functionSelector: avmEnvironment.temporaryFunctionSelector,
|
|
61
|
+
isDelegateCall: avmEnvironment.isDelegateCall,
|
|
62
|
+
isStaticCall: avmEnvironment.isStaticCall,
|
|
63
|
+
sideEffectCounter: startSideEffectCounter,
|
|
72
64
|
});
|
|
73
|
-
const functionData = new FunctionData(
|
|
65
|
+
const functionData = new FunctionData(avmEnvironment.temporaryFunctionSelector, /*isPrivate=*/ false);
|
|
74
66
|
const execution: PublicExecution = {
|
|
75
|
-
contractAddress:
|
|
67
|
+
contractAddress: avmEnvironment.address,
|
|
76
68
|
callContext,
|
|
77
69
|
args: calldata,
|
|
78
70
|
functionData,
|
|
79
71
|
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const context = new PublicExecutionContext(
|
|
83
|
-
execution,
|
|
84
|
-
avmContext.environment.header,
|
|
85
|
-
avmContext.environment.globals,
|
|
86
|
-
packedArgs,
|
|
87
|
-
new SideEffectCounter(sideEffectCounter),
|
|
88
|
-
avmContext.persistableState.hostStorage.publicStateDb,
|
|
89
|
-
avmContext.persistableState.hostStorage.contractsDb,
|
|
90
|
-
avmContext.persistableState.hostStorage.commitmentsDb,
|
|
91
|
-
Gas.from(avmContext.machineState.gasLeft),
|
|
92
|
-
avmContext.environment.transactionFee,
|
|
93
|
-
avmContext.environment.gasSettings,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
return context;
|
|
72
|
+
return execution;
|
|
97
73
|
}
|
|
98
74
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
executionContext: PublicExecutionContext,
|
|
109
|
-
newWorldState: JournalData,
|
|
110
|
-
result: AvmContractCallResults,
|
|
111
|
-
endMachineState: AvmMachineState,
|
|
112
|
-
): Promise<PublicExecutionResult> {
|
|
113
|
-
const execution = executionContext.execution;
|
|
114
|
-
|
|
115
|
-
const contractStorageReads: ContractStorageRead[] = newWorldState.storageReads.map(
|
|
116
|
-
read => new ContractStorageRead(read.slot, read.value, read.counter.toNumber(), read.storageAddress),
|
|
117
|
-
);
|
|
118
|
-
const contractStorageUpdateRequests: ContractStorageUpdateRequest[] = newWorldState.storageWrites.map(
|
|
119
|
-
write => new ContractStorageUpdateRequest(write.slot, write.value, write.counter.toNumber(), write.storageAddress),
|
|
120
|
-
);
|
|
121
|
-
// We need to write the storage updates to the DB, because that's what the ACVM expects.
|
|
122
|
-
// Assumes the updates are in the right order.
|
|
123
|
-
for (const write of newWorldState.storageWrites) {
|
|
124
|
-
await executionContext.stateDb.storageWrite(write.storageAddress, write.slot, write.value);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const newNoteHashes = newWorldState.newNoteHashes.map(
|
|
128
|
-
noteHash => new NoteHash(noteHash.noteHash, noteHash.counter.toNumber()),
|
|
129
|
-
);
|
|
130
|
-
const nullifierReadRequests: ReadRequest[] = newWorldState.nullifierChecks
|
|
131
|
-
.filter(nullifierCheck => nullifierCheck.exists)
|
|
132
|
-
.map(nullifierCheck => new ReadRequest(nullifierCheck.nullifier, nullifierCheck.counter.toNumber()));
|
|
133
|
-
const nullifierNonExistentReadRequests: ReadRequest[] = newWorldState.nullifierChecks
|
|
134
|
-
.filter(nullifierCheck => !nullifierCheck.exists)
|
|
135
|
-
.map(nullifierCheck => new ReadRequest(nullifierCheck.nullifier, nullifierCheck.counter.toNumber()));
|
|
136
|
-
const newNullifiers: Nullifier[] = newWorldState.newNullifiers.map(
|
|
137
|
-
tracedNullifier =>
|
|
138
|
-
new Nullifier(
|
|
139
|
-
/*value=*/ tracedNullifier.nullifier,
|
|
140
|
-
tracedNullifier.counter.toNumber(),
|
|
141
|
-
/*noteHash=*/ Fr.ZERO, // NEEDED?
|
|
142
|
-
),
|
|
143
|
-
);
|
|
144
|
-
const unencryptedLogs: UnencryptedFunctionL2Logs = new UnencryptedFunctionL2Logs(
|
|
145
|
-
newWorldState.newLogs.map(log => new UnencryptedL2Log(log.contractAddress, log.selector, log.data)),
|
|
146
|
-
);
|
|
147
|
-
const unencryptedLogsHashes = newWorldState.newLogsHashes.map(
|
|
148
|
-
logHash => new SideEffect(logHash.logHash, logHash.counter),
|
|
149
|
-
);
|
|
150
|
-
const newL2ToL1Messages = newWorldState.newL1Messages.map(m => new L2ToL1Message(m.recipient, m.content));
|
|
151
|
-
|
|
152
|
-
const returnValues = result.output;
|
|
153
|
-
|
|
154
|
-
// TODO: Support nested executions.
|
|
155
|
-
const nestedExecutions: PublicExecutionResult[] = [];
|
|
156
|
-
// TODO keep track of side effect counters
|
|
157
|
-
const startSideEffectCounter = Fr.ZERO;
|
|
158
|
-
const endSideEffectCounter = Fr.ZERO;
|
|
159
|
-
|
|
75
|
+
export function convertAvmResultsToPxResult(
|
|
76
|
+
avmResult: AvmContractCallResults,
|
|
77
|
+
startSideEffectCounter: number,
|
|
78
|
+
fromPx: PublicExecution,
|
|
79
|
+
startGas: Gas,
|
|
80
|
+
endAvmContext: AvmContext,
|
|
81
|
+
): PublicExecutionResult {
|
|
82
|
+
const endPersistableState = endAvmContext.persistableState;
|
|
83
|
+
const endMachineState = endAvmContext.machineState;
|
|
160
84
|
return {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
unencryptedLogsHashes,
|
|
174
|
-
unencryptedLogs,
|
|
175
|
-
reverted: result.reverted,
|
|
176
|
-
revertReason: result.revertReason ? createSimulationError(result.revertReason) : undefined,
|
|
177
|
-
startGasLeft: executionContext.availableGas,
|
|
85
|
+
...endPersistableState.transitionalExecutionResult, // includes nestedExecutions
|
|
86
|
+
execution: fromPx,
|
|
87
|
+
returnValues: avmResult.output,
|
|
88
|
+
startSideEffectCounter: new Fr(startSideEffectCounter),
|
|
89
|
+
endSideEffectCounter: new Fr(endPersistableState.trace.accessCounter),
|
|
90
|
+
unencryptedLogs: new UnencryptedFunctionL2Logs(endPersistableState.transitionalExecutionResult.unencryptedLogs),
|
|
91
|
+
allUnencryptedLogs: new UnencryptedFunctionL2Logs(
|
|
92
|
+
endPersistableState.transitionalExecutionResult.allUnencryptedLogs,
|
|
93
|
+
),
|
|
94
|
+
reverted: avmResult.reverted,
|
|
95
|
+
revertReason: avmResult.revertReason ? createSimulationError(avmResult.revertReason) : undefined,
|
|
96
|
+
startGasLeft: startGas,
|
|
178
97
|
endGasLeft: endMachineState.gasLeft,
|
|
179
|
-
transactionFee:
|
|
98
|
+
transactionFee: endAvmContext.environment.transactionFee,
|
|
180
99
|
};
|
|
181
100
|
}
|
|
182
101
|
|
|
183
|
-
export function convertPublicExecutionResult(res: PublicExecutionResult): AvmContractCallResults {
|
|
184
|
-
return new AvmContractCallResults(res.reverted, res.returnValues, res.revertReason);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export function updateAvmContextFromPublicExecutionResult(ctx: AvmContext, result: PublicExecutionResult): void {
|
|
188
|
-
// We have to push these manually and not use the trace* functions
|
|
189
|
-
// so that we respect the side effect counters.
|
|
190
|
-
for (const readRequest of result.contractStorageReads) {
|
|
191
|
-
ctx.persistableState.trace.publicStorageReads.push({
|
|
192
|
-
storageAddress: ctx.environment.storageAddress,
|
|
193
|
-
exists: true, // FIXME
|
|
194
|
-
slot: readRequest.storageSlot,
|
|
195
|
-
value: readRequest.currentValue,
|
|
196
|
-
counter: new Fr(readRequest.sideEffectCounter ?? Fr.ZERO),
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
for (const updateRequest of result.contractStorageUpdateRequests) {
|
|
201
|
-
ctx.persistableState.trace.publicStorageWrites.push({
|
|
202
|
-
storageAddress: ctx.environment.storageAddress,
|
|
203
|
-
slot: updateRequest.storageSlot,
|
|
204
|
-
value: updateRequest.newValue,
|
|
205
|
-
counter: new Fr(updateRequest.sideEffectCounter ?? Fr.ZERO),
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
// We need to manually populate the cache.
|
|
209
|
-
ctx.persistableState.publicStorage.write(
|
|
210
|
-
ctx.environment.storageAddress,
|
|
211
|
-
updateRequest.storageSlot,
|
|
212
|
-
updateRequest.newValue,
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
for (const nullifier of result.newNullifiers) {
|
|
217
|
-
ctx.persistableState.trace.newNullifiers.push({
|
|
218
|
-
storageAddress: ctx.environment.storageAddress,
|
|
219
|
-
nullifier: nullifier.value,
|
|
220
|
-
counter: new Fr(nullifier.counter),
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
for (const noteHash of result.newNoteHashes) {
|
|
225
|
-
ctx.persistableState.trace.newNoteHashes.push({
|
|
226
|
-
storageAddress: ctx.environment.storageAddress,
|
|
227
|
-
noteHash: noteHash.value,
|
|
228
|
-
counter: new Fr(noteHash.counter),
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
for (const message of result.newL2ToL1Messages) {
|
|
233
|
-
ctx.persistableState.newL1Messages.push(message);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
for (const log of result.unencryptedLogs.logs) {
|
|
237
|
-
ctx.persistableState.newLogs.push(new UnencryptedL2Log(log.contractAddress, log.selector, log.data));
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
102
|
const AVM_MAGIC_SUFFIX = Buffer.from([
|
|
242
103
|
Mov.opcode, // opcode
|
|
243
104
|
0x00, // indirect
|