@aztec/simulator 0.61.0 → 0.63.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 +2 -16
- package/dest/acvm/acvm.d.ts.map +1 -1
- package/dest/acvm/acvm.js +2 -70
- package/dest/acvm/oracle/oracle.d.ts +4 -3
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +11 -9
- package/dest/acvm/oracle/typed_oracle.d.ts +5 -4
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +9 -6
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +4 -3
- package/dest/avm/avm_machine_state.d.ts +27 -8
- package/dest/avm/avm_machine_state.d.ts.map +1 -1
- package/dest/avm/avm_machine_state.js +6 -10
- package/dest/avm/avm_memory_types.d.ts +8 -0
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +5 -1
- package/dest/avm/avm_simulator.d.ts +2 -19
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +12 -14
- package/dest/avm/avm_tree.d.ts +249 -0
- package/dest/avm/avm_tree.d.ts.map +1 -0
- package/dest/avm/avm_tree.js +637 -0
- package/dest/avm/errors.d.ts +4 -17
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +21 -50
- package/dest/avm/fixtures/index.d.ts +7 -2
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +12 -12
- package/dest/avm/index.d.ts +1 -0
- package/dest/avm/index.d.ts.map +1 -1
- package/dest/avm/index.js +2 -1
- package/dest/avm/journal/journal.d.ts +43 -24
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +172 -39
- package/dest/avm/journal/nullifiers.d.ts +5 -4
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +2 -3
- package/dest/avm/journal/public_storage.d.ts +6 -5
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.js +1 -1
- package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/avm/opcodes/accrued_substate.js +4 -10
- package/dest/avm/opcodes/arithmetic.d.ts +4 -1
- package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
- package/dest/avm/opcodes/arithmetic.js +18 -4
- package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
- package/dest/avm/opcodes/bitwise.js +1 -3
- package/dest/avm/opcodes/comparators.d.ts.map +1 -1
- package/dest/avm/opcodes/comparators.js +1 -2
- package/dest/avm/opcodes/contract.d.ts.map +1 -1
- package/dest/avm/opcodes/contract.js +2 -3
- package/dest/avm/opcodes/control_flow.d.ts +4 -0
- package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
- package/dest/avm/opcodes/control_flow.js +26 -11
- package/dest/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/avm/opcodes/conversion.js +1 -2
- package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
- package/dest/avm/opcodes/ec_add.js +5 -11
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +1 -2
- package/dest/avm/opcodes/external_calls.d.ts +4 -2
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +38 -22
- package/dest/avm/opcodes/hashing.d.ts.map +1 -1
- package/dest/avm/opcodes/hashing.js +1 -4
- package/dest/avm/opcodes/instruction.d.ts +4 -0
- package/dest/avm/opcodes/instruction.d.ts.map +1 -1
- package/dest/avm/opcodes/instruction.js +7 -1
- package/dest/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/avm/opcodes/memory.js +1 -7
- package/dest/avm/opcodes/misc.js +3 -3
- package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
- package/dest/avm/opcodes/multi_scalar_mul.js +6 -5
- package/dest/avm/opcodes/storage.d.ts.map +1 -1
- package/dest/avm/opcodes/storage.js +2 -4
- package/dest/avm/serialization/bytecode_serialization.d.ts +1 -6
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +24 -20
- package/dest/avm/serialization/instruction_serialization.d.ts +2 -2
- package/dest/avm/serialization/instruction_serialization.js +2 -2
- package/dest/client/client_execution_context.d.ts +7 -10
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +19 -18
- package/dest/client/db_oracle.d.ts +22 -8
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/db_oracle.js +1 -1
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +5 -4
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +3 -2
- package/dest/client/view_data_oracle.d.ts +6 -12
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +10 -12
- package/dest/common/errors.d.ts +15 -2
- package/dest/common/errors.d.ts.map +1 -1
- package/dest/common/errors.js +85 -4
- package/dest/mocks/fixtures.d.ts +9 -28
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +12 -57
- package/dest/public/dual_side_effect_trace.d.ts +34 -26
- package/dest/public/dual_side_effect_trace.d.ts.map +1 -1
- package/dest/public/dual_side_effect_trace.js +48 -36
- package/dest/public/enqueued_call_side_effect_trace.d.ts +96 -33
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +212 -138
- package/dest/public/execution.d.ts +50 -17
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -29
- package/dest/public/executor.d.ts +28 -11
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +33 -33
- package/dest/public/index.d.ts +4 -5
- package/dest/public/index.d.ts.map +1 -1
- package/dest/public/index.js +4 -5
- package/dest/public/public_db_sources.d.ts +1 -0
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +21 -19
- package/dest/public/public_processor.d.ts +7 -11
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +60 -42
- package/dest/public/public_processor_metrics.d.ts +3 -3
- package/dest/public/public_processor_metrics.d.ts.map +1 -1
- package/dest/public/public_processor_metrics.js +1 -1
- package/dest/public/public_tx_context.d.ts +130 -0
- package/dest/public/public_tx_context.d.ts.map +1 -0
- package/dest/public/public_tx_context.js +293 -0
- package/dest/public/public_tx_simulator.d.ts +36 -0
- package/dest/public/public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator.js +148 -0
- package/dest/public/side_effect_trace.d.ts +30 -15
- package/dest/public/side_effect_trace.d.ts.map +1 -1
- package/dest/public/side_effect_trace.js +70 -16
- package/dest/public/side_effect_trace_interface.d.ts +43 -12
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/public/transitional_adapters.d.ts +9 -0
- package/dest/public/transitional_adapters.d.ts.map +1 -0
- package/dest/public/transitional_adapters.js +127 -0
- package/dest/public/utils.d.ts +5 -0
- package/dest/public/utils.d.ts.map +1 -0
- package/dest/public/utils.js +30 -0
- package/dest/test/utils.d.ts +2 -2
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +4 -4
- package/package.json +12 -9
- package/src/acvm/acvm.ts +3 -94
- package/src/acvm/oracle/oracle.ts +14 -12
- package/src/acvm/oracle/typed_oracle.ts +10 -6
- package/src/avm/avm_gas.ts +3 -2
- package/src/avm/avm_machine_state.ts +28 -12
- package/src/avm/avm_memory_types.ts +5 -0
- package/src/avm/avm_simulator.ts +13 -16
- package/src/avm/avm_tree.ts +785 -0
- package/src/avm/errors.ts +25 -48
- package/src/avm/fixtures/index.ts +16 -12
- package/src/avm/index.ts +1 -0
- package/src/avm/journal/journal.ts +291 -52
- package/src/avm/journal/nullifiers.ts +7 -7
- package/src/avm/journal/public_storage.ts +5 -5
- package/src/avm/opcodes/accrued_substate.ts +3 -9
- package/src/avm/opcodes/arithmetic.ts +26 -4
- package/src/avm/opcodes/bitwise.ts +0 -2
- package/src/avm/opcodes/comparators.ts +0 -1
- package/src/avm/opcodes/contract.ts +1 -2
- package/src/avm/opcodes/control_flow.ts +29 -10
- package/src/avm/opcodes/conversion.ts +0 -1
- package/src/avm/opcodes/ec_add.ts +6 -9
- package/src/avm/opcodes/environment_getters.ts +0 -1
- package/src/avm/opcodes/external_calls.ts +39 -21
- package/src/avm/opcodes/hashing.ts +0 -3
- package/src/avm/opcodes/instruction.ts +7 -0
- package/src/avm/opcodes/memory.ts +0 -6
- package/src/avm/opcodes/misc.ts +2 -2
- package/src/avm/opcodes/multi_scalar_mul.ts +5 -4
- package/src/avm/opcodes/storage.ts +1 -3
- package/src/avm/serialization/bytecode_serialization.ts +31 -22
- package/src/avm/serialization/instruction_serialization.ts +2 -2
- package/src/client/client_execution_context.ts +24 -21
- package/src/client/db_oracle.ts +31 -8
- package/src/client/private_execution.ts +5 -4
- package/src/client/unconstrained_execution.ts +2 -1
- package/src/client/view_data_oracle.ts +14 -13
- package/src/common/errors.ts +119 -3
- package/src/mocks/fixtures.ts +15 -106
- package/src/public/dual_side_effect_trace.ts +138 -50
- package/src/public/enqueued_call_side_effect_trace.ts +352 -212
- package/src/public/execution.ts +58 -42
- package/src/public/executor.ts +52 -67
- package/src/public/index.ts +7 -5
- package/src/public/public_db_sources.ts +22 -19
- package/src/public/public_processor.ts +111 -73
- package/src/public/public_processor_metrics.ts +3 -3
- package/src/public/public_tx_context.ts +411 -0
- package/src/public/public_tx_simulator.ts +232 -0
- package/src/public/side_effect_trace.ts +154 -28
- package/src/public/side_effect_trace_interface.ts +92 -14
- package/src/public/transitional_adapters.ts +347 -0
- package/src/public/utils.ts +32 -0
- package/src/test/utils.ts +9 -2
- package/dest/public/enqueued_call_simulator.d.ts +0 -43
- package/dest/public/enqueued_call_simulator.d.ts.map +0 -1
- package/dest/public/enqueued_call_simulator.js +0 -156
- package/dest/public/enqueued_calls_processor.d.ts +0 -43
- package/dest/public/enqueued_calls_processor.d.ts.map +0 -1
- package/dest/public/enqueued_calls_processor.js +0 -209
- package/dest/public/hints_builder.d.ts +0 -29
- package/dest/public/hints_builder.d.ts.map +0 -1
- package/dest/public/hints_builder.js +0 -75
- package/dest/public/public_kernel.d.ts +0 -30
- package/dest/public/public_kernel.d.ts.map +0 -1
- package/dest/public/public_kernel.js +0 -67
- package/dest/public/public_kernel_circuit_simulator.d.ts +0 -25
- package/dest/public/public_kernel_circuit_simulator.d.ts.map +0 -1
- package/dest/public/public_kernel_circuit_simulator.js +0 -2
- package/dest/public/public_kernel_tail_simulator.d.ts +0 -15
- package/dest/public/public_kernel_tail_simulator.d.ts.map +0 -1
- package/dest/public/public_kernel_tail_simulator.js +0 -39
- package/src/public/enqueued_call_simulator.ts +0 -360
- package/src/public/enqueued_calls_processor.ts +0 -372
- package/src/public/hints_builder.ts +0 -168
- package/src/public/public_kernel.ts +0 -100
- package/src/public/public_kernel_circuit_simulator.ts +0 -32
- package/src/public/public_kernel_tail_simulator.ts +0 -97
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AvmProvingRequest,
|
|
3
|
+
type MerkleTreeReadOperations,
|
|
4
|
+
type PublicExecutionRequest,
|
|
5
|
+
type SimulationError,
|
|
6
|
+
type Tx,
|
|
7
|
+
TxExecutionPhase,
|
|
8
|
+
TxHash,
|
|
9
|
+
} from '@aztec/circuit-types';
|
|
10
|
+
import {
|
|
11
|
+
type AvmCircuitPublicInputs,
|
|
12
|
+
Fr,
|
|
13
|
+
Gas,
|
|
14
|
+
type GasSettings,
|
|
15
|
+
type GlobalVariables,
|
|
16
|
+
type Header,
|
|
17
|
+
type PrivateToPublicAccumulatedData,
|
|
18
|
+
type PublicCallRequest,
|
|
19
|
+
RevertCode,
|
|
20
|
+
type StateReference,
|
|
21
|
+
countAccumulatedItems,
|
|
22
|
+
} from '@aztec/circuits.js';
|
|
23
|
+
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
24
|
+
|
|
25
|
+
import { strict as assert } from 'assert';
|
|
26
|
+
import { inspect } from 'util';
|
|
27
|
+
|
|
28
|
+
import { AvmPersistableStateManager } from '../avm/index.js';
|
|
29
|
+
import { DualSideEffectTrace } from './dual_side_effect_trace.js';
|
|
30
|
+
import { PublicEnqueuedCallSideEffectTrace, SideEffectArrayLengths } from './enqueued_call_side_effect_trace.js';
|
|
31
|
+
import { type EnqueuedPublicCallExecutionResult } from './execution.js';
|
|
32
|
+
import { type WorldStateDB } from './public_db_sources.js';
|
|
33
|
+
import { PublicSideEffectTrace } from './side_effect_trace.js';
|
|
34
|
+
import { generateAvmCircuitPublicInputs, generateAvmProvingRequest } from './transitional_adapters.js';
|
|
35
|
+
import { getCallRequestsByPhase, getExecutionRequestsByPhase } from './utils.js';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The transaction-level context for public execution.
|
|
39
|
+
*/
|
|
40
|
+
export class PublicTxContext {
|
|
41
|
+
private log: DebugLogger;
|
|
42
|
+
|
|
43
|
+
/* Gas used including private, teardown gas _limit_, setup and app logic */
|
|
44
|
+
private gasUsed: Gas;
|
|
45
|
+
/* Gas actually used during teardown (different from limit) */
|
|
46
|
+
public teardownGasUsed: Gas = Gas.empty();
|
|
47
|
+
|
|
48
|
+
/* Entire transaction execution is done. */
|
|
49
|
+
private halted = false;
|
|
50
|
+
/* Where did reverts happen (if at all)? */
|
|
51
|
+
private revertCode: RevertCode = RevertCode.OK;
|
|
52
|
+
/* What caused a revert (if one occurred)? */
|
|
53
|
+
public revertReason: SimulationError | undefined;
|
|
54
|
+
|
|
55
|
+
public avmProvingRequest: AvmProvingRequest | undefined; // FIXME(dbanks12): remove
|
|
56
|
+
|
|
57
|
+
constructor(
|
|
58
|
+
public readonly state: PhaseStateManager,
|
|
59
|
+
private readonly globalVariables: GlobalVariables,
|
|
60
|
+
private readonly historicalHeader: Header, // FIXME(dbanks12): remove
|
|
61
|
+
private readonly startStateReference: StateReference,
|
|
62
|
+
private readonly startGasUsed: Gas,
|
|
63
|
+
private readonly gasSettings: GasSettings,
|
|
64
|
+
private readonly setupCallRequests: PublicCallRequest[],
|
|
65
|
+
private readonly appLogicCallRequests: PublicCallRequest[],
|
|
66
|
+
private readonly teardownCallRequests: PublicCallRequest[],
|
|
67
|
+
private readonly setupExecutionRequests: PublicExecutionRequest[],
|
|
68
|
+
private readonly appLogicExecutionRequests: PublicExecutionRequest[],
|
|
69
|
+
private readonly teardownExecutionRequests: PublicExecutionRequest[],
|
|
70
|
+
private readonly nonRevertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData,
|
|
71
|
+
private readonly revertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData,
|
|
72
|
+
public trace: PublicEnqueuedCallSideEffectTrace, // FIXME(dbanks12): should be private
|
|
73
|
+
) {
|
|
74
|
+
this.log = createDebugLogger(`aztec:public_tx_context`);
|
|
75
|
+
this.gasUsed = startGasUsed;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public static async create(
|
|
79
|
+
db: MerkleTreeReadOperations,
|
|
80
|
+
worldStateDB: WorldStateDB,
|
|
81
|
+
tx: Tx,
|
|
82
|
+
globalVariables: GlobalVariables,
|
|
83
|
+
) {
|
|
84
|
+
const nonRevertibleAccumulatedDataFromPrivate = tx.data.forPublic!.nonRevertibleAccumulatedData;
|
|
85
|
+
const revertibleAccumulatedDataFromPrivate = tx.data.forPublic!.revertibleAccumulatedData;
|
|
86
|
+
const nonRevertibleNullifiersFromPrivate = nonRevertibleAccumulatedDataFromPrivate.nullifiers.filter(
|
|
87
|
+
n => !n.isEmpty(),
|
|
88
|
+
);
|
|
89
|
+
const _revertibleNullifiersFromPrivate = revertibleAccumulatedDataFromPrivate.nullifiers.filter(n => !n.isEmpty());
|
|
90
|
+
|
|
91
|
+
const innerCallTrace = new PublicSideEffectTrace();
|
|
92
|
+
|
|
93
|
+
const previousAccumulatedDataArrayLengths = new SideEffectArrayLengths(
|
|
94
|
+
/*publicDataReads*/ 0,
|
|
95
|
+
/*publicDataWrites*/ 0,
|
|
96
|
+
/*noteHashReadRequests*/ 0,
|
|
97
|
+
countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.noteHashes),
|
|
98
|
+
/*nullifierReadRequests*/ 0,
|
|
99
|
+
/*nullifierNonExistentReadRequests*/ 0,
|
|
100
|
+
countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.nullifiers),
|
|
101
|
+
/*l1ToL2MsgReadRequests*/ 0,
|
|
102
|
+
countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.l2ToL1Msgs),
|
|
103
|
+
/*unencryptedLogsHashes*/ 0,
|
|
104
|
+
);
|
|
105
|
+
const enqueuedCallTrace = new PublicEnqueuedCallSideEffectTrace(
|
|
106
|
+
/*startSideEffectCounter=*/ 0,
|
|
107
|
+
previousAccumulatedDataArrayLengths,
|
|
108
|
+
);
|
|
109
|
+
const trace = new DualSideEffectTrace(innerCallTrace, enqueuedCallTrace);
|
|
110
|
+
|
|
111
|
+
// Transaction level state manager that will be forked for revertible phases.
|
|
112
|
+
const txStateManager = AvmPersistableStateManager.newWithPendingSiloedNullifiers(
|
|
113
|
+
worldStateDB,
|
|
114
|
+
trace,
|
|
115
|
+
nonRevertibleNullifiersFromPrivate,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
return new PublicTxContext(
|
|
119
|
+
new PhaseStateManager(txStateManager),
|
|
120
|
+
globalVariables,
|
|
121
|
+
tx.data.constants.historicalHeader,
|
|
122
|
+
await db.getStateReference(),
|
|
123
|
+
tx.data.gasUsed,
|
|
124
|
+
tx.data.constants.txContext.gasSettings,
|
|
125
|
+
getCallRequestsByPhase(tx, TxExecutionPhase.SETUP),
|
|
126
|
+
getCallRequestsByPhase(tx, TxExecutionPhase.APP_LOGIC),
|
|
127
|
+
getCallRequestsByPhase(tx, TxExecutionPhase.TEARDOWN),
|
|
128
|
+
getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP),
|
|
129
|
+
getExecutionRequestsByPhase(tx, TxExecutionPhase.APP_LOGIC),
|
|
130
|
+
getExecutionRequestsByPhase(tx, TxExecutionPhase.TEARDOWN),
|
|
131
|
+
tx.data.forPublic!.nonRevertibleAccumulatedData,
|
|
132
|
+
tx.data.forPublic!.revertibleAccumulatedData,
|
|
133
|
+
enqueuedCallTrace,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Signal that the entire transaction execution is done.
|
|
139
|
+
* All phases have been processed.
|
|
140
|
+
* Actual transaction fee and actual total consumed gas can now be queried.
|
|
141
|
+
*/
|
|
142
|
+
halt() {
|
|
143
|
+
this.halted = true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Revert execution a phase. Populate revertReason & revertCode.
|
|
148
|
+
* If in setup, throw an error (transaction will be thrown out).
|
|
149
|
+
* NOTE: this does not "halt" the entire transaction execution.
|
|
150
|
+
*/
|
|
151
|
+
revert(phase: TxExecutionPhase, revertReason: SimulationError | undefined = undefined, culprit = '') {
|
|
152
|
+
this.log.debug(`${TxExecutionPhase[phase]} phase reverted! ${culprit} failed with reason: ${revertReason}`);
|
|
153
|
+
|
|
154
|
+
if (revertReason && !this.revertReason) {
|
|
155
|
+
// don't override revertReason
|
|
156
|
+
// (if app logic and teardown both revert, we want app logic's reason)
|
|
157
|
+
this.revertReason = revertReason;
|
|
158
|
+
}
|
|
159
|
+
if (phase === TxExecutionPhase.SETUP) {
|
|
160
|
+
this.log.debug(`Setup phase reverted! The transaction will be thrown out.`);
|
|
161
|
+
if (revertReason) {
|
|
162
|
+
throw revertReason;
|
|
163
|
+
} else {
|
|
164
|
+
throw new Error(`Setup phase reverted! The transaction will be thrown out. ${culprit} failed`);
|
|
165
|
+
}
|
|
166
|
+
} else if (phase === TxExecutionPhase.APP_LOGIC) {
|
|
167
|
+
this.revertCode = RevertCode.APP_LOGIC_REVERTED;
|
|
168
|
+
} else if (phase === TxExecutionPhase.TEARDOWN) {
|
|
169
|
+
if (this.revertCode.equals(RevertCode.APP_LOGIC_REVERTED)) {
|
|
170
|
+
this.revertCode = RevertCode.BOTH_REVERTED;
|
|
171
|
+
} else {
|
|
172
|
+
this.revertCode = RevertCode.TEARDOWN_REVERTED;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Get the revert code.
|
|
179
|
+
* @returns The revert code.
|
|
180
|
+
*/
|
|
181
|
+
getFinalRevertCode(): RevertCode {
|
|
182
|
+
assert(this.halted, 'Cannot know the final revert code until tx execution ends');
|
|
183
|
+
return this.revertCode;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Construct & return transaction hash.
|
|
188
|
+
* @returns The transaction's hash.
|
|
189
|
+
*/
|
|
190
|
+
getTxHash(): TxHash {
|
|
191
|
+
// Private kernel functions are executed client side and for this reason tx hash is already set as first nullifier
|
|
192
|
+
const firstNullifier = this.nonRevertibleAccumulatedDataFromPrivate.nullifiers[0];
|
|
193
|
+
if (!firstNullifier || firstNullifier.isZero()) {
|
|
194
|
+
throw new Error(`Cannot get tx hash since first nullifier is missing`);
|
|
195
|
+
}
|
|
196
|
+
return new TxHash(firstNullifier.toBuffer());
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Are there any call requests for the speciiied phase?
|
|
201
|
+
*/
|
|
202
|
+
hasPhase(phase: TxExecutionPhase): boolean {
|
|
203
|
+
if (phase === TxExecutionPhase.SETUP) {
|
|
204
|
+
return this.setupCallRequests.length > 0;
|
|
205
|
+
} else if (phase === TxExecutionPhase.APP_LOGIC) {
|
|
206
|
+
return this.appLogicCallRequests.length > 0;
|
|
207
|
+
} else {
|
|
208
|
+
// phase === TxExecutionPhase.TEARDOWN
|
|
209
|
+
return this.teardownCallRequests.length > 0;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get the call requests for the specified phase (including args hashes).
|
|
215
|
+
*/
|
|
216
|
+
getCallRequestsForPhase(phase: TxExecutionPhase): PublicCallRequest[] {
|
|
217
|
+
switch (phase) {
|
|
218
|
+
case TxExecutionPhase.SETUP:
|
|
219
|
+
return this.setupCallRequests;
|
|
220
|
+
case TxExecutionPhase.APP_LOGIC:
|
|
221
|
+
return this.appLogicCallRequests;
|
|
222
|
+
case TxExecutionPhase.TEARDOWN:
|
|
223
|
+
return this.teardownCallRequests;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get the call requests for the specified phase (including actual args).
|
|
229
|
+
*/
|
|
230
|
+
getExecutionRequestsForPhase(phase: TxExecutionPhase): PublicExecutionRequest[] {
|
|
231
|
+
switch (phase) {
|
|
232
|
+
case TxExecutionPhase.SETUP:
|
|
233
|
+
return this.setupExecutionRequests;
|
|
234
|
+
case TxExecutionPhase.APP_LOGIC:
|
|
235
|
+
return this.appLogicExecutionRequests;
|
|
236
|
+
case TxExecutionPhase.TEARDOWN:
|
|
237
|
+
return this.teardownExecutionRequests;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* How much gas is left for the specified phase?
|
|
243
|
+
*/
|
|
244
|
+
getGasLeftForPhase(phase: TxExecutionPhase): Gas {
|
|
245
|
+
if (phase === TxExecutionPhase.TEARDOWN) {
|
|
246
|
+
return this.gasSettings.teardownGasLimits;
|
|
247
|
+
} else {
|
|
248
|
+
return this.gasSettings.gasLimits.sub(this.gasUsed);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Consume gas. Track gas for teardown phase separately.
|
|
254
|
+
*/
|
|
255
|
+
consumeGas(phase: TxExecutionPhase, gas: Gas) {
|
|
256
|
+
if (phase === TxExecutionPhase.TEARDOWN) {
|
|
257
|
+
this.teardownGasUsed = this.teardownGasUsed.add(gas);
|
|
258
|
+
} else {
|
|
259
|
+
this.gasUsed = this.gasUsed.add(gas);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Compute the gas used using the actual gas used during teardown instead
|
|
265
|
+
* of the teardown gas limit.
|
|
266
|
+
* Note that this.gasUsed is initialized from private's gasUsed which includes
|
|
267
|
+
* teardown gas limit.
|
|
268
|
+
*/
|
|
269
|
+
getActualGasUsed(): Gas {
|
|
270
|
+
assert(this.halted, 'Can only compute actual gas used after tx execution ends');
|
|
271
|
+
const requireTeardown = this.teardownCallRequests.length > 0;
|
|
272
|
+
const teardownGasLimits = requireTeardown ? this.gasSettings.teardownGasLimits : Gas.empty();
|
|
273
|
+
return this.gasUsed.sub(teardownGasLimits).add(this.teardownGasUsed);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* The gasUsed as if the entire teardown gas limit was consumed.
|
|
278
|
+
*/
|
|
279
|
+
getGasUsedForFee(): Gas {
|
|
280
|
+
return this.gasUsed;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get the transaction fee as is available to the specified phase.
|
|
285
|
+
* Only teardown should have access to the actual transaction fee.
|
|
286
|
+
*/
|
|
287
|
+
getTransactionFee(phase: TxExecutionPhase): Fr {
|
|
288
|
+
if (phase === TxExecutionPhase.TEARDOWN) {
|
|
289
|
+
return this.getTransactionFeeUnsafe();
|
|
290
|
+
} else {
|
|
291
|
+
return Fr.zero();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Compute the transaction fee.
|
|
297
|
+
* Should only be called during or after teardown.
|
|
298
|
+
*/
|
|
299
|
+
private getTransactionFeeUnsafe(): Fr {
|
|
300
|
+
const txFee = this.gasUsed.computeFee(this.globalVariables.gasFees);
|
|
301
|
+
this.log.debug(`Computed tx fee`, {
|
|
302
|
+
txFee,
|
|
303
|
+
gasUsed: inspect(this.gasUsed),
|
|
304
|
+
gasFees: inspect(this.globalVariables.gasFees),
|
|
305
|
+
});
|
|
306
|
+
return txFee;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Generate the public inputs for the AVM circuit.
|
|
311
|
+
*/
|
|
312
|
+
private generateAvmCircuitPublicInputs(endStateReference: StateReference): AvmCircuitPublicInputs {
|
|
313
|
+
assert(this.halted, 'Can only get AvmCircuitPublicInputs after tx execution ends');
|
|
314
|
+
return generateAvmCircuitPublicInputs(
|
|
315
|
+
this.trace,
|
|
316
|
+
this.globalVariables,
|
|
317
|
+
this.startStateReference,
|
|
318
|
+
this.startGasUsed,
|
|
319
|
+
this.gasSettings,
|
|
320
|
+
this.setupCallRequests,
|
|
321
|
+
this.appLogicCallRequests,
|
|
322
|
+
this.teardownCallRequests,
|
|
323
|
+
this.nonRevertibleAccumulatedDataFromPrivate,
|
|
324
|
+
this.revertibleAccumulatedDataFromPrivate,
|
|
325
|
+
endStateReference,
|
|
326
|
+
/*endGasUsed=*/ this.gasUsed,
|
|
327
|
+
this.getTransactionFeeUnsafe(),
|
|
328
|
+
this.revertCode,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Generate the proving request for the AVM circuit.
|
|
334
|
+
*/
|
|
335
|
+
generateProvingRequest(endStateReference: StateReference): AvmProvingRequest {
|
|
336
|
+
// TODO(dbanks12): Once we actually have tx-level proving, this will generate the entire
|
|
337
|
+
// proving request for the first time
|
|
338
|
+
this.avmProvingRequest!.inputs.output = this.generateAvmCircuitPublicInputs(endStateReference);
|
|
339
|
+
return this.avmProvingRequest!;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// TODO(dbanks12): remove once AVM proves entire public tx
|
|
343
|
+
async updateProvingRequest(
|
|
344
|
+
real: boolean,
|
|
345
|
+
phase: TxExecutionPhase,
|
|
346
|
+
worldStateDB: WorldStateDB,
|
|
347
|
+
stateManager: AvmPersistableStateManager,
|
|
348
|
+
executionRequest: PublicExecutionRequest,
|
|
349
|
+
result: EnqueuedPublicCallExecutionResult,
|
|
350
|
+
allocatedGas: Gas,
|
|
351
|
+
) {
|
|
352
|
+
if (this.avmProvingRequest === undefined) {
|
|
353
|
+
// Propagate the very first avmProvingRequest of the tx for now.
|
|
354
|
+
// Eventually this will be the proof for the entire public portion of the transaction.
|
|
355
|
+
this.avmProvingRequest = await generateAvmProvingRequest(
|
|
356
|
+
real,
|
|
357
|
+
worldStateDB,
|
|
358
|
+
stateManager,
|
|
359
|
+
this.historicalHeader,
|
|
360
|
+
this.globalVariables,
|
|
361
|
+
executionRequest,
|
|
362
|
+
result,
|
|
363
|
+
allocatedGas,
|
|
364
|
+
this.getTransactionFee(phase),
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Thin wrapper around the state manager to handle forking and merging for phases.
|
|
372
|
+
*
|
|
373
|
+
* This lets us keep track of whether the state has already been forked
|
|
374
|
+
* so that we can conditionally fork at the start of a phase.
|
|
375
|
+
*
|
|
376
|
+
* There is a state manager that lives at the level of the entire transaction,
|
|
377
|
+
* but for setup and teardown the active state manager will be a fork of the
|
|
378
|
+
* transaction level one.
|
|
379
|
+
*/
|
|
380
|
+
class PhaseStateManager {
|
|
381
|
+
private currentlyActiveStateManager: AvmPersistableStateManager | undefined;
|
|
382
|
+
|
|
383
|
+
constructor(private readonly txStateManager: AvmPersistableStateManager) {}
|
|
384
|
+
|
|
385
|
+
fork() {
|
|
386
|
+
assert(!this.currentlyActiveStateManager, 'Cannot fork when already forked');
|
|
387
|
+
this.currentlyActiveStateManager = this.txStateManager.fork();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
getActiveStateManager() {
|
|
391
|
+
return this.currentlyActiveStateManager || this.txStateManager;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
isForked() {
|
|
395
|
+
return !!this.currentlyActiveStateManager;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
mergeForkedState() {
|
|
399
|
+
assert(this.currentlyActiveStateManager, 'No forked state to merge');
|
|
400
|
+
this.txStateManager.merge(this.currentlyActiveStateManager!);
|
|
401
|
+
// Drop the forked state manager now that it is merged
|
|
402
|
+
this.currentlyActiveStateManager = undefined;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
discardForkedState() {
|
|
406
|
+
assert(this.currentlyActiveStateManager, 'No forked state to discard');
|
|
407
|
+
this.txStateManager.reject(this.currentlyActiveStateManager!);
|
|
408
|
+
// Drop the forked state manager. We don't want it!
|
|
409
|
+
this.currentlyActiveStateManager = undefined;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AvmProvingRequest,
|
|
3
|
+
type GasUsed,
|
|
4
|
+
type MerkleTreeReadOperations,
|
|
5
|
+
NestedProcessReturnValues,
|
|
6
|
+
type SimulationError,
|
|
7
|
+
type Tx,
|
|
8
|
+
TxExecutionPhase,
|
|
9
|
+
UnencryptedFunctionL2Logs,
|
|
10
|
+
} from '@aztec/circuit-types';
|
|
11
|
+
import { Gas, type GlobalVariables, MAX_L2_GAS_PER_ENQUEUED_CALL, type RevertCode } from '@aztec/circuits.js';
|
|
12
|
+
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
13
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
14
|
+
|
|
15
|
+
import { type EnqueuedPublicCallExecutionResult } from './execution.js';
|
|
16
|
+
import { type PublicExecutor } from './executor.js';
|
|
17
|
+
import { type WorldStateDB } from './public_db_sources.js';
|
|
18
|
+
import { PublicTxContext } from './public_tx_context.js';
|
|
19
|
+
|
|
20
|
+
export type ProcessedPhase = {
|
|
21
|
+
phase: TxExecutionPhase;
|
|
22
|
+
durationMs: number;
|
|
23
|
+
returnValues: NestedProcessReturnValues[];
|
|
24
|
+
reverted: boolean;
|
|
25
|
+
revertReason?: SimulationError;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type PublicTxResult = {
|
|
29
|
+
avmProvingRequest: AvmProvingRequest;
|
|
30
|
+
/** Gas used during the execution of this tx */
|
|
31
|
+
gasUsed: GasUsed;
|
|
32
|
+
revertCode: RevertCode;
|
|
33
|
+
/** Revert reason, if any */
|
|
34
|
+
revertReason?: SimulationError;
|
|
35
|
+
processedPhases: ProcessedPhase[];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export class PublicTxSimulator {
|
|
39
|
+
private log: DebugLogger;
|
|
40
|
+
|
|
41
|
+
constructor(
|
|
42
|
+
private db: MerkleTreeReadOperations,
|
|
43
|
+
private globalVariables: GlobalVariables,
|
|
44
|
+
private worldStateDB: WorldStateDB,
|
|
45
|
+
private publicExecutor: PublicExecutor,
|
|
46
|
+
private realAvmProvingRequests: boolean = true,
|
|
47
|
+
) {
|
|
48
|
+
this.log = createDebugLogger(`aztec:public_tx_simulator`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static create(
|
|
52
|
+
db: MerkleTreeReadOperations,
|
|
53
|
+
publicExecutor: PublicExecutor,
|
|
54
|
+
globalVariables: GlobalVariables,
|
|
55
|
+
worldStateDB: WorldStateDB,
|
|
56
|
+
realAvmProvingRequests: boolean = true,
|
|
57
|
+
) {
|
|
58
|
+
return new PublicTxSimulator(db, globalVariables, worldStateDB, publicExecutor, realAvmProvingRequests);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async simulate(tx: Tx): Promise<PublicTxResult> {
|
|
62
|
+
this.log.verbose(`Processing tx ${tx.getTxHash()}`);
|
|
63
|
+
|
|
64
|
+
const context = await PublicTxContext.create(this.db, this.worldStateDB, tx, this.globalVariables);
|
|
65
|
+
|
|
66
|
+
// add new contracts to the contracts db so that their functions may be found and called
|
|
67
|
+
// TODO(#4073): This is catching only private deployments, when we add public ones, we'll
|
|
68
|
+
// have to capture contracts emitted in that phase as well.
|
|
69
|
+
// TODO(@spalladino): Should we allow emitting contracts in the fee preparation phase?
|
|
70
|
+
// TODO(#6464): Should we allow emitting contracts in the private setup phase?
|
|
71
|
+
// if so, this should only add contracts that were deployed during private app logic.
|
|
72
|
+
// FIXME: we shouldn't need to directly modify worldStateDb here!
|
|
73
|
+
await this.worldStateDB.addNewContracts(tx);
|
|
74
|
+
|
|
75
|
+
const processedPhases: ProcessedPhase[] = [];
|
|
76
|
+
if (context.hasPhase(TxExecutionPhase.SETUP)) {
|
|
77
|
+
const setupResult: ProcessedPhase = await this.simulateSetupPhase(context);
|
|
78
|
+
processedPhases.push(setupResult);
|
|
79
|
+
}
|
|
80
|
+
if (context.hasPhase(TxExecutionPhase.APP_LOGIC)) {
|
|
81
|
+
const appLogicResult: ProcessedPhase = await this.simulateAppLogicPhase(context);
|
|
82
|
+
processedPhases.push(appLogicResult);
|
|
83
|
+
}
|
|
84
|
+
if (context.hasPhase(TxExecutionPhase.TEARDOWN)) {
|
|
85
|
+
const teardownResult: ProcessedPhase = await this.simulateTeardownPhase(context);
|
|
86
|
+
processedPhases.push(teardownResult);
|
|
87
|
+
}
|
|
88
|
+
context.halt();
|
|
89
|
+
|
|
90
|
+
const endStateReference = await this.db.getStateReference();
|
|
91
|
+
|
|
92
|
+
const avmProvingRequest = context.generateProvingRequest(endStateReference);
|
|
93
|
+
const avmCircuitPublicInputs = avmProvingRequest.inputs.output!;
|
|
94
|
+
|
|
95
|
+
const revertCode = context.getFinalRevertCode();
|
|
96
|
+
if (!revertCode.isOK()) {
|
|
97
|
+
// TODO(#6464): Should we allow emitting contracts in the private setup phase?
|
|
98
|
+
// if so, this is removing contracts deployed in private setup
|
|
99
|
+
// You can't submit contracts in public, so this is only relevant for private-created side effects
|
|
100
|
+
// FIXME: we shouldn't need to directly modify worldStateDb here!
|
|
101
|
+
await this.worldStateDB.removeNewContracts(tx);
|
|
102
|
+
// FIXME(dbanks12): should not be changing immutable tx
|
|
103
|
+
tx.filterRevertedLogs(
|
|
104
|
+
tx.data.forPublic!.nonRevertibleAccumulatedData,
|
|
105
|
+
avmCircuitPublicInputs.accumulatedData.unencryptedLogsHashes,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
// FIXME(dbanks12): should not be changing immutable tx
|
|
109
|
+
tx.unencryptedLogs.addFunctionLogs([new UnencryptedFunctionL2Logs(context.trace.getUnencryptedLogs())]);
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
avmProvingRequest,
|
|
113
|
+
gasUsed: { totalGas: context.getActualGasUsed(), teardownGas: context.teardownGasUsed },
|
|
114
|
+
revertCode,
|
|
115
|
+
revertReason: context.revertReason,
|
|
116
|
+
processedPhases: processedPhases,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private async simulateSetupPhase(context: PublicTxContext): Promise<ProcessedPhase> {
|
|
121
|
+
return await this.simulatePhase(TxExecutionPhase.SETUP, context);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private async simulateAppLogicPhase(context: PublicTxContext): Promise<ProcessedPhase> {
|
|
125
|
+
// Fork the state manager so that we can rollback state if app logic or teardown reverts.
|
|
126
|
+
// Don't need to fork for setup since it's non-revertible (if setup fails, transaction is thrown out).
|
|
127
|
+
context.state.fork();
|
|
128
|
+
|
|
129
|
+
const result = await this.simulatePhase(TxExecutionPhase.APP_LOGIC, context);
|
|
130
|
+
|
|
131
|
+
if (result.reverted) {
|
|
132
|
+
// Drop the currently active forked state manager and rollback to end of setup.
|
|
133
|
+
context.state.discardForkedState();
|
|
134
|
+
} else {
|
|
135
|
+
if (!context.hasPhase(TxExecutionPhase.TEARDOWN)) {
|
|
136
|
+
// Nothing to do after this (no teardown), so merge state updates now instead of letting teardown handle it.
|
|
137
|
+
context.state.mergeForkedState();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private async simulateTeardownPhase(context: PublicTxContext): Promise<ProcessedPhase> {
|
|
145
|
+
if (!context.state.isForked()) {
|
|
146
|
+
// If state isn't forked (app logic was empty or reverted), fork now
|
|
147
|
+
// so we can rollback to the end of setup if teardown reverts.
|
|
148
|
+
context.state.fork();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const result = await this.simulatePhase(TxExecutionPhase.TEARDOWN, context);
|
|
152
|
+
|
|
153
|
+
if (result.reverted) {
|
|
154
|
+
// Drop the currently active forked state manager and rollback to end of setup.
|
|
155
|
+
context.state.discardForkedState();
|
|
156
|
+
} else {
|
|
157
|
+
// Merge state updates from teardown,
|
|
158
|
+
context.state.mergeForkedState();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private async simulatePhase(phase: TxExecutionPhase, context: PublicTxContext): Promise<ProcessedPhase> {
|
|
165
|
+
const callRequests = context.getCallRequestsForPhase(phase);
|
|
166
|
+
const executionRequests = context.getExecutionRequestsForPhase(phase);
|
|
167
|
+
const txStateManager = context.state.getActiveStateManager();
|
|
168
|
+
|
|
169
|
+
this.log.debug(`Beginning processing in phase ${TxExecutionPhase[phase]} for tx ${context.getTxHash()}`);
|
|
170
|
+
|
|
171
|
+
const returnValues: NestedProcessReturnValues[] = [];
|
|
172
|
+
let reverted = false;
|
|
173
|
+
let revertReason: SimulationError | undefined;
|
|
174
|
+
const phaseTimer = new Timer();
|
|
175
|
+
for (let i = callRequests.length - 1; i >= 0; i--) {
|
|
176
|
+
if (reverted) {
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const callRequest = callRequests[i];
|
|
181
|
+
const executionRequest = executionRequests[i];
|
|
182
|
+
|
|
183
|
+
const availableGas = context.getGasLeftForPhase(phase);
|
|
184
|
+
// Gas allocated to an enqueued call can be different from the available gas
|
|
185
|
+
// if there is more gas available than the max allocation per enqueued call.
|
|
186
|
+
const allocatedGas = new Gas(
|
|
187
|
+
/*daGas=*/ availableGas.daGas,
|
|
188
|
+
/*l2Gas=*/ Math.min(availableGas.l2Gas, MAX_L2_GAS_PER_ENQUEUED_CALL),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const enqueuedCallResult = (await this.publicExecutor.simulate(
|
|
192
|
+
txStateManager,
|
|
193
|
+
executionRequest,
|
|
194
|
+
this.globalVariables, // todo get from context
|
|
195
|
+
allocatedGas,
|
|
196
|
+
context.getTransactionFee(phase),
|
|
197
|
+
)) as EnqueuedPublicCallExecutionResult;
|
|
198
|
+
|
|
199
|
+
// TODO(dbanks12): remove once AVM proves entire public tx
|
|
200
|
+
await context.updateProvingRequest(
|
|
201
|
+
this.realAvmProvingRequests,
|
|
202
|
+
phase,
|
|
203
|
+
this.worldStateDB,
|
|
204
|
+
txStateManager,
|
|
205
|
+
executionRequest,
|
|
206
|
+
enqueuedCallResult,
|
|
207
|
+
allocatedGas,
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
txStateManager.traceEnqueuedCall(callRequest, executionRequest.args, enqueuedCallResult.reverted!);
|
|
211
|
+
|
|
212
|
+
const gasUsed = allocatedGas.sub(Gas.from(enqueuedCallResult.endGasLeft));
|
|
213
|
+
context.consumeGas(phase, gasUsed);
|
|
214
|
+
returnValues.push(new NestedProcessReturnValues(enqueuedCallResult.returnValues));
|
|
215
|
+
|
|
216
|
+
if (enqueuedCallResult.reverted) {
|
|
217
|
+
reverted = true;
|
|
218
|
+
const culprit = `${executionRequest.callContext.contractAddress}:${executionRequest.callContext.functionSelector}`;
|
|
219
|
+
revertReason = enqueuedCallResult.revertReason;
|
|
220
|
+
context.revert(phase, enqueuedCallResult.revertReason, culprit); // throws if in setup (non-revertible) phase
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
phase,
|
|
226
|
+
durationMs: phaseTimer.ms(),
|
|
227
|
+
returnValues,
|
|
228
|
+
reverted,
|
|
229
|
+
revertReason,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|