@aztec/simulator 0.56.0 → 0.58.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/oracle/oracle.d.ts +2 -5
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +7 -38
- package/dest/acvm/oracle/typed_oracle.d.ts +4 -8
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +1 -10
- package/dest/avm/avm_execution_environment.d.ts +2 -3
- package/dest/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/avm/avm_execution_environment.js +3 -4
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +2 -3
- package/dest/avm/avm_memory_types.d.ts +10 -5
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +31 -16
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +5 -2
- package/dest/avm/errors.d.ts +1 -1
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +12 -3
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +4 -4
- package/dest/avm/journal/journal.d.ts +2 -1
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +8 -8
- package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/avm/opcodes/accrued_substate.js +54 -47
- package/dest/avm/opcodes/addressing_mode.d.ts +3 -2
- package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
- package/dest/avm/opcodes/addressing_mode.js +25 -21
- package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
- package/dest/avm/opcodes/arithmetic.js +7 -6
- package/dest/avm/opcodes/bitwise.d.ts +3 -3
- package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
- package/dest/avm/opcodes/bitwise.js +19 -16
- package/dest/avm/opcodes/commitment.d.ts.map +1 -1
- package/dest/avm/opcodes/commitment.js +6 -5
- package/dest/avm/opcodes/comparators.d.ts.map +1 -1
- package/dest/avm/opcodes/comparators.js +7 -6
- package/dest/avm/opcodes/contract.d.ts.map +1 -1
- package/dest/avm/opcodes/contract.js +8 -6
- package/dest/avm/opcodes/control_flow.js +7 -7
- package/dest/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/avm/opcodes/conversion.js +11 -10
- package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
- package/dest/avm/opcodes/ec_add.js +25 -15
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +6 -5
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +37 -26
- package/dest/avm/opcodes/hashing.d.ts +1 -3
- package/dest/avm/opcodes/hashing.d.ts.map +1 -1
- package/dest/avm/opcodes/hashing.js +39 -48
- package/dest/avm/opcodes/instruction.d.ts +2 -6
- package/dest/avm/opcodes/instruction.d.ts.map +1 -1
- package/dest/avm/opcodes/instruction.js +3 -9
- package/dest/avm/opcodes/instruction_impl.d.ts +1 -2
- package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
- package/dest/avm/opcodes/instruction_impl.js +2 -5
- package/dest/avm/opcodes/memory.d.ts +0 -12
- package/dest/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/avm/opcodes/memory.js +24 -54
- package/dest/avm/opcodes/misc.d.ts.map +1 -1
- package/dest/avm/opcodes/misc.js +10 -9
- package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
- package/dest/avm/opcodes/multi_scalar_mul.js +35 -20
- package/dest/avm/opcodes/storage.d.ts.map +1 -1
- package/dest/avm/opcodes/storage.js +13 -11
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +2 -3
- package/dest/avm/serialization/instruction_serialization.d.ts +32 -34
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +34 -37
- package/dest/avm/test_utils.d.ts +1 -2
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +1 -1
- package/dest/client/client_execution_context.d.ts +6 -30
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +36 -54
- package/dest/client/db_oracle.d.ts +1 -2
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/db_oracle.js +1 -1
- package/dest/client/index.d.ts +1 -1
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +2 -2
- package/dest/client/private_execution.d.ts +12 -3
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +29 -23
- package/dest/client/simulator.d.ts +2 -3
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +1 -1
- package/dest/client/view_data_oracle.d.ts +1 -2
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +1 -1
- package/dest/common/debug_fn_name.d.ts +4 -0
- package/dest/common/debug_fn_name.d.ts.map +1 -0
- package/dest/common/debug_fn_name.js +15 -0
- package/dest/common/index.d.ts +0 -1
- package/dest/common/index.d.ts.map +1 -1
- package/dest/common/index.js +1 -2
- package/dest/public/db_interfaces.d.ts +1 -2
- package/dest/public/db_interfaces.d.ts.map +1 -1
- package/dest/public/dual_side_effect_trace.d.ts +76 -0
- package/dest/public/dual_side_effect_trace.d.ts.map +1 -0
- package/dest/public/dual_side_effect_trace.js +109 -0
- package/dest/public/enqueued_call_side_effect_trace.d.ts +114 -0
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -0
- package/dest/public/enqueued_call_side_effect_trace.js +314 -0
- package/dest/public/enqueued_call_simulator.d.ts +2 -2
- package/dest/public/enqueued_call_simulator.d.ts.map +1 -1
- package/dest/public/enqueued_call_simulator.js +20 -10
- package/dest/public/enqueued_calls_processor.d.ts +2 -2
- package/dest/public/enqueued_calls_processor.d.ts.map +1 -1
- package/dest/public/enqueued_calls_processor.js +3 -5
- package/dest/public/execution.d.ts +11 -5
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +13 -1
- package/dest/public/executor.d.ts +7 -6
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +24 -15
- package/dest/public/fee_payment.d.ts +1 -1
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +4 -7
- package/dest/public/hints_builder.d.ts +2 -2
- package/dest/public/hints_builder.d.ts.map +1 -1
- package/dest/public/hints_builder.js +2 -2
- package/dest/public/public_db_sources.d.ts +4 -5
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +15 -11
- package/dest/public/public_kernel_tail_simulator.d.ts +3 -3
- package/dest/public/public_kernel_tail_simulator.d.ts.map +1 -1
- package/dest/public/public_kernel_tail_simulator.js +1 -1
- package/dest/public/public_processor.d.ts +7 -10
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +9 -10
- package/dest/public/side_effect_errors.d.ts +4 -0
- package/dest/public/side_effect_errors.d.ts.map +1 -0
- package/dest/public/side_effect_errors.js +7 -0
- package/dest/public/side_effect_trace.d.ts +3 -4
- package/dest/public/side_effect_trace.d.ts.map +1 -1
- package/dest/public/side_effect_trace.js +54 -29
- package/dest/public/side_effect_trace_interface.d.ts +1 -1
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/package.json +12 -9
- package/src/acvm/oracle/oracle.ts +8 -86
- package/src/acvm/oracle/typed_oracle.ts +8 -33
- package/src/avm/avm_execution_environment.ts +1 -3
- package/src/avm/avm_gas.ts +1 -2
- package/src/avm/avm_memory_types.ts +38 -16
- package/src/avm/avm_simulator.ts +7 -1
- package/src/avm/errors.ts +11 -3
- package/src/avm/fixtures/index.ts +2 -3
- package/src/avm/journal/journal.ts +14 -10
- package/src/avm/opcodes/accrued_substate.ts +53 -61
- package/src/avm/opcodes/addressing_mode.ts +27 -24
- package/src/avm/opcodes/arithmetic.ts +6 -8
- package/src/avm/opcodes/bitwise.ts +18 -18
- package/src/avm/opcodes/commitment.ts +6 -7
- package/src/avm/opcodes/comparators.ts +6 -8
- package/src/avm/opcodes/contract.ts +7 -8
- package/src/avm/opcodes/control_flow.ts +6 -6
- package/src/avm/opcodes/conversion.ts +10 -12
- package/src/avm/opcodes/ec_add.ts +29 -24
- package/src/avm/opcodes/environment_getters.ts +5 -4
- package/src/avm/opcodes/external_calls.ts +37 -30
- package/src/avm/opcodes/hashing.ts +38 -63
- package/src/avm/opcodes/instruction.ts +3 -10
- package/src/avm/opcodes/instruction_impl.ts +0 -3
- package/src/avm/opcodes/memory.ts +23 -67
- package/src/avm/opcodes/misc.ts +9 -11
- package/src/avm/opcodes/multi_scalar_mul.ts +31 -26
- package/src/avm/opcodes/storage.ts +12 -10
- package/src/avm/serialization/bytecode_serialization.ts +0 -2
- package/src/avm/serialization/instruction_serialization.ts +1 -4
- package/src/avm/test_utils.ts +1 -2
- package/src/client/client_execution_context.ts +46 -97
- package/src/client/db_oracle.ts +6 -2
- package/src/client/index.ts +1 -1
- package/src/client/private_execution.ts +45 -15
- package/src/client/simulator.ts +2 -3
- package/src/client/view_data_oracle.ts +1 -2
- package/src/common/debug_fn_name.ts +22 -0
- package/src/common/index.ts +0 -1
- package/src/public/db_interfaces.ts +5 -2
- package/src/public/dual_side_effect_trace.ts +173 -0
- package/src/public/enqueued_call_side_effect_trace.ts +552 -0
- package/src/public/enqueued_call_simulator.ts +35 -14
- package/src/public/enqueued_calls_processor.ts +4 -6
- package/src/public/execution.ts +15 -6
- package/src/public/executor.ts +42 -19
- package/src/public/fee_payment.ts +4 -6
- package/src/public/hints_builder.ts +9 -11
- package/src/public/public_db_sources.ts +31 -22
- package/src/public/public_kernel_tail_simulator.ts +3 -3
- package/src/public/public_processor.ts +17 -13
- package/src/public/side_effect_errors.ts +6 -0
- package/src/public/side_effect_trace.ts +74 -29
- package/src/public/side_effect_trace_interface.ts +2 -2
- package/dest/client/execution_result.d.ts +0 -104
- package/dest/client/execution_result.d.ts.map +0 -1
- package/dest/client/execution_result.js +0 -136
- package/dest/common/return_values.d.ts +0 -11
- package/dest/common/return_values.d.ts.map +0 -1
- package/dest/common/return_values.js +0 -13
- package/src/client/execution_result.ts +0 -228
- package/src/common/return_values.ts +0 -18
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
import { UnencryptedL2Log } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
AvmContractInstanceHint,
|
|
4
|
+
AvmExecutionHints,
|
|
5
|
+
AvmExternalCallHint,
|
|
6
|
+
AvmKeyValueHint,
|
|
7
|
+
AztecAddress,
|
|
8
|
+
CallContext,
|
|
9
|
+
type CombinedConstantData,
|
|
10
|
+
type ContractInstanceWithAddress,
|
|
11
|
+
ContractStorageRead,
|
|
12
|
+
ContractStorageUpdateRequest,
|
|
13
|
+
EthAddress,
|
|
14
|
+
Gas,
|
|
15
|
+
L2ToL1Message,
|
|
16
|
+
LogHash,
|
|
17
|
+
MAX_ENCRYPTED_LOGS_PER_TX,
|
|
18
|
+
MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX,
|
|
19
|
+
MAX_L2_TO_L1_MSGS_PER_TX,
|
|
20
|
+
MAX_NOTE_ENCRYPTED_LOGS_PER_TX,
|
|
21
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
22
|
+
MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
|
|
23
|
+
MAX_NULLIFIERS_PER_TX,
|
|
24
|
+
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
|
|
25
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
26
|
+
MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
|
|
27
|
+
MAX_PUBLIC_DATA_READS_PER_TX,
|
|
28
|
+
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
29
|
+
MAX_UNENCRYPTED_LOGS_PER_TX,
|
|
30
|
+
NoteHash,
|
|
31
|
+
Nullifier,
|
|
32
|
+
PublicAccumulatedData,
|
|
33
|
+
PublicAccumulatedDataArrayLengths,
|
|
34
|
+
PublicCallRequest,
|
|
35
|
+
PublicDataRead,
|
|
36
|
+
PublicDataUpdateRequest,
|
|
37
|
+
PublicInnerCallRequest,
|
|
38
|
+
PublicValidationRequestArrayLengths,
|
|
39
|
+
PublicValidationRequests,
|
|
40
|
+
ReadRequest,
|
|
41
|
+
RollupValidationRequests,
|
|
42
|
+
ScopedL2ToL1Message,
|
|
43
|
+
ScopedLogHash,
|
|
44
|
+
ScopedNoteHash,
|
|
45
|
+
type ScopedNullifier,
|
|
46
|
+
ScopedReadRequest,
|
|
47
|
+
TreeLeafReadRequest,
|
|
48
|
+
VMCircuitPublicInputs,
|
|
49
|
+
} from '@aztec/circuits.js';
|
|
50
|
+
import { computeVarArgsHash } from '@aztec/circuits.js/hash';
|
|
51
|
+
import { makeTuple } from '@aztec/foundation/array';
|
|
52
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
53
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
54
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
55
|
+
|
|
56
|
+
import { type AvmContractCallResult } from '../avm/avm_contract_call_result.js';
|
|
57
|
+
import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
|
|
58
|
+
import { SideEffectLimitReachedError } from './side_effect_errors.js';
|
|
59
|
+
import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js';
|
|
60
|
+
|
|
61
|
+
export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A struct containing just the side effects as regular arrays
|
|
65
|
+
* as opposed to "Tuple" arrays used by circuit public inputs.
|
|
66
|
+
* This struct is helpful for testing and checking array lengths.
|
|
67
|
+
**/
|
|
68
|
+
export type SideEffects = {
|
|
69
|
+
contractStorageReads: ContractStorageRead[];
|
|
70
|
+
contractStorageUpdateRequests: ContractStorageUpdateRequest[];
|
|
71
|
+
|
|
72
|
+
noteHashReadRequests: TreeLeafReadRequest[];
|
|
73
|
+
noteHashes: ScopedNoteHash[];
|
|
74
|
+
|
|
75
|
+
nullifierReadRequests: ScopedReadRequest[];
|
|
76
|
+
nullifierNonExistentReadRequests: ScopedReadRequest[];
|
|
77
|
+
nullifiers: ScopedNullifier[];
|
|
78
|
+
|
|
79
|
+
l1ToL2MsgReadRequests: TreeLeafReadRequest[];
|
|
80
|
+
l2ToL1Msgs: ScopedL2ToL1Message[];
|
|
81
|
+
|
|
82
|
+
unencryptedLogs: UnencryptedL2Log[];
|
|
83
|
+
unencryptedLogsHashes: ScopedLogHash[];
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Trace side effects for an entire enqueued call.
|
|
88
|
+
*/
|
|
89
|
+
export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceInterface {
|
|
90
|
+
public log = createDebugLogger('aztec:public_enqueued_call_side_effect_trace');
|
|
91
|
+
|
|
92
|
+
/** The side effect counter increments with every call to the trace. */
|
|
93
|
+
private sideEffectCounter: number;
|
|
94
|
+
|
|
95
|
+
// TODO(dbanks12): make contract address mandatory in ContractStorage* structs,
|
|
96
|
+
// and include it in serialization, or modify PublicData* structs for this.
|
|
97
|
+
private contractStorageReads: ContractStorageRead[] = [];
|
|
98
|
+
private contractStorageUpdateRequests: ContractStorageUpdateRequest[] = [];
|
|
99
|
+
|
|
100
|
+
private noteHashReadRequests: TreeLeafReadRequest[] = [];
|
|
101
|
+
private noteHashes: ScopedNoteHash[] = [];
|
|
102
|
+
|
|
103
|
+
private nullifierReadRequests: ScopedReadRequest[] = [];
|
|
104
|
+
private nullifierNonExistentReadRequests: ScopedReadRequest[] = [];
|
|
105
|
+
private nullifiers: ScopedNullifier[] = [];
|
|
106
|
+
|
|
107
|
+
private l1ToL2MsgReadRequests: TreeLeafReadRequest[] = [];
|
|
108
|
+
private l2ToL1Msgs: ScopedL2ToL1Message[] = [];
|
|
109
|
+
|
|
110
|
+
private unencryptedLogs: UnencryptedL2Log[] = [];
|
|
111
|
+
private unencryptedLogsHashes: ScopedLogHash[] = [];
|
|
112
|
+
|
|
113
|
+
private avmCircuitHints: AvmExecutionHints;
|
|
114
|
+
|
|
115
|
+
constructor(
|
|
116
|
+
/** The counter of this trace's first side effect. */
|
|
117
|
+
public readonly startSideEffectCounter: number = 0,
|
|
118
|
+
/** Track parent's (or previous kernel's) lengths so the AVM can properly enforce TX-wide limits,
|
|
119
|
+
* otherwise the public kernel can fail to prove because TX limits are breached.
|
|
120
|
+
*/
|
|
121
|
+
private readonly previousValidationRequestArrayLengths: PublicValidationRequestArrayLengths = PublicValidationRequestArrayLengths.empty(),
|
|
122
|
+
private readonly previousAccumulatedDataArrayLengths: PublicAccumulatedDataArrayLengths = PublicAccumulatedDataArrayLengths.empty(),
|
|
123
|
+
) {
|
|
124
|
+
this.sideEffectCounter = startSideEffectCounter;
|
|
125
|
+
this.avmCircuitHints = AvmExecutionHints.empty();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public fork() {
|
|
129
|
+
return new PublicEnqueuedCallSideEffectTrace(
|
|
130
|
+
this.sideEffectCounter,
|
|
131
|
+
new PublicValidationRequestArrayLengths(
|
|
132
|
+
this.previousValidationRequestArrayLengths.noteHashReadRequests + this.noteHashReadRequests.length,
|
|
133
|
+
this.previousValidationRequestArrayLengths.nullifierReadRequests + this.nullifierReadRequests.length,
|
|
134
|
+
this.previousValidationRequestArrayLengths.nullifierNonExistentReadRequests +
|
|
135
|
+
this.nullifierNonExistentReadRequests.length,
|
|
136
|
+
this.previousValidationRequestArrayLengths.l1ToL2MsgReadRequests + this.l1ToL2MsgReadRequests.length,
|
|
137
|
+
this.previousValidationRequestArrayLengths.publicDataReads + this.contractStorageReads.length,
|
|
138
|
+
),
|
|
139
|
+
new PublicAccumulatedDataArrayLengths(
|
|
140
|
+
this.previousAccumulatedDataArrayLengths.noteHashes + this.noteHashes.length,
|
|
141
|
+
this.previousAccumulatedDataArrayLengths.nullifiers + this.nullifiers.length,
|
|
142
|
+
this.previousAccumulatedDataArrayLengths.l2ToL1Msgs + this.l2ToL1Msgs.length,
|
|
143
|
+
this.previousAccumulatedDataArrayLengths.noteEncryptedLogsHashes,
|
|
144
|
+
this.previousAccumulatedDataArrayLengths.encryptedLogsHashes,
|
|
145
|
+
this.previousAccumulatedDataArrayLengths.unencryptedLogsHashes + this.unencryptedLogsHashes.length,
|
|
146
|
+
this.previousAccumulatedDataArrayLengths.publicDataUpdateRequests + this.contractStorageUpdateRequests.length,
|
|
147
|
+
this.previousAccumulatedDataArrayLengths.publicCallStack,
|
|
148
|
+
),
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public getCounter() {
|
|
153
|
+
return this.sideEffectCounter;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private incrementSideEffectCounter() {
|
|
157
|
+
this.sideEffectCounter++;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
public tracePublicStorageRead(storageAddress: Fr, slot: Fr, value: Fr, _exists: boolean, _cached: boolean) {
|
|
161
|
+
// NOTE: exists and cached are unused for now but may be used for optimizations or kernel hints later
|
|
162
|
+
if (
|
|
163
|
+
this.contractStorageReads.length + this.previousValidationRequestArrayLengths.publicDataReads >=
|
|
164
|
+
MAX_PUBLIC_DATA_READS_PER_TX
|
|
165
|
+
) {
|
|
166
|
+
throw new SideEffectLimitReachedError('contract storage read', MAX_PUBLIC_DATA_READS_PER_TX);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.contractStorageReads.push(
|
|
170
|
+
new ContractStorageRead(slot, value, this.sideEffectCounter, AztecAddress.fromField(storageAddress)),
|
|
171
|
+
);
|
|
172
|
+
this.avmCircuitHints.storageValues.items.push(
|
|
173
|
+
new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ value),
|
|
174
|
+
);
|
|
175
|
+
this.log.debug(`SLOAD cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`);
|
|
176
|
+
this.incrementSideEffectCounter();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public tracePublicStorageWrite(storageAddress: Fr, slot: Fr, value: Fr) {
|
|
180
|
+
if (
|
|
181
|
+
this.contractStorageUpdateRequests.length + this.previousAccumulatedDataArrayLengths.publicDataUpdateRequests >=
|
|
182
|
+
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
|
|
183
|
+
) {
|
|
184
|
+
throw new SideEffectLimitReachedError('contract storage write', MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.contractStorageUpdateRequests.push(
|
|
188
|
+
new ContractStorageUpdateRequest(slot, value, this.sideEffectCounter, storageAddress),
|
|
189
|
+
);
|
|
190
|
+
this.log.debug(`SSTORE cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`);
|
|
191
|
+
this.incrementSideEffectCounter();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// TODO(8287): _exists can be removed once we have the vm properly handling the equality check
|
|
195
|
+
public traceNoteHashCheck(_storageAddress: Fr, noteHash: Fr, leafIndex: Fr, exists: boolean) {
|
|
196
|
+
// NOTE: storageAddress is unused because noteHash is an already-siloed leaf
|
|
197
|
+
if (
|
|
198
|
+
this.noteHashReadRequests.length + this.previousValidationRequestArrayLengths.noteHashReadRequests >=
|
|
199
|
+
MAX_NOTE_HASH_READ_REQUESTS_PER_TX
|
|
200
|
+
) {
|
|
201
|
+
throw new SideEffectLimitReachedError('note hash read request', MAX_NOTE_HASH_READ_REQUESTS_PER_TX);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.noteHashReadRequests.push(new TreeLeafReadRequest(noteHash, leafIndex));
|
|
205
|
+
this.avmCircuitHints.noteHashExists.items.push(
|
|
206
|
+
new AvmKeyValueHint(/*key=*/ new Fr(leafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO),
|
|
207
|
+
);
|
|
208
|
+
// NOTE: counter does not increment for note hash checks (because it doesn't rely on pending note hashes)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public traceNewNoteHash(storageAddress: Fr, noteHash: Fr) {
|
|
212
|
+
if (this.noteHashes.length + this.previousAccumulatedDataArrayLengths.noteHashes >= MAX_NOTE_HASHES_PER_TX) {
|
|
213
|
+
throw new SideEffectLimitReachedError('note hash', MAX_NOTE_HASHES_PER_TX);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter).scope(AztecAddress.fromField(storageAddress)));
|
|
217
|
+
this.log.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`);
|
|
218
|
+
this.incrementSideEffectCounter();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public traceNullifierCheck(storageAddress: Fr, nullifier: Fr, _leafIndex: Fr, exists: boolean, _isPending: boolean) {
|
|
222
|
+
// NOTE: isPending and leafIndex are unused for now but may be used for optimizations or kernel hints later
|
|
223
|
+
this.enforceLimitOnNullifierChecks();
|
|
224
|
+
|
|
225
|
+
const readRequest = new ReadRequest(nullifier, this.sideEffectCounter).scope(
|
|
226
|
+
AztecAddress.fromField(storageAddress),
|
|
227
|
+
);
|
|
228
|
+
if (exists) {
|
|
229
|
+
this.nullifierReadRequests.push(readRequest);
|
|
230
|
+
} else {
|
|
231
|
+
this.nullifierNonExistentReadRequests.push(readRequest);
|
|
232
|
+
}
|
|
233
|
+
this.avmCircuitHints.nullifierExists.items.push(
|
|
234
|
+
new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)),
|
|
235
|
+
);
|
|
236
|
+
this.log.debug(`NULLIFIER_EXISTS cnt: ${this.sideEffectCounter}`);
|
|
237
|
+
this.incrementSideEffectCounter();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public traceNewNullifier(storageAddress: Fr, nullifier: Fr) {
|
|
241
|
+
if (this.nullifiers.length + this.previousAccumulatedDataArrayLengths.nullifiers >= MAX_NULLIFIERS_PER_TX) {
|
|
242
|
+
throw new SideEffectLimitReachedError('nullifier', MAX_NULLIFIERS_PER_TX);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
this.nullifiers.push(
|
|
246
|
+
new Nullifier(nullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO).scope(
|
|
247
|
+
AztecAddress.fromField(storageAddress),
|
|
248
|
+
),
|
|
249
|
+
);
|
|
250
|
+
this.log.debug(`NEW_NULLIFIER cnt: ${this.sideEffectCounter}`);
|
|
251
|
+
this.incrementSideEffectCounter();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// TODO(8287): _exists can be removed once we have the vm properly handling the equality check
|
|
255
|
+
public traceL1ToL2MessageCheck(_contractAddress: Fr, msgHash: Fr, msgLeafIndex: Fr, exists: boolean) {
|
|
256
|
+
// NOTE: contractAddress is unused because msgHash is an already-siloed leaf
|
|
257
|
+
if (
|
|
258
|
+
this.l1ToL2MsgReadRequests.length + this.previousValidationRequestArrayLengths.l1ToL2MsgReadRequests >=
|
|
259
|
+
MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX
|
|
260
|
+
) {
|
|
261
|
+
throw new SideEffectLimitReachedError('l1 to l2 message read request', MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
this.l1ToL2MsgReadRequests.push(new TreeLeafReadRequest(msgHash, msgLeafIndex));
|
|
265
|
+
this.avmCircuitHints.l1ToL2MessageExists.items.push(
|
|
266
|
+
new AvmKeyValueHint(/*key=*/ new Fr(msgLeafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO),
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
public traceNewL2ToL1Message(contractAddress: Fr, recipient: Fr, content: Fr) {
|
|
271
|
+
if (this.l2ToL1Msgs.length + this.previousAccumulatedDataArrayLengths.l2ToL1Msgs >= MAX_L2_TO_L1_MSGS_PER_TX) {
|
|
272
|
+
throw new SideEffectLimitReachedError('l2 to l1 message', MAX_L2_TO_L1_MSGS_PER_TX);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const recipientAddress = EthAddress.fromField(recipient);
|
|
276
|
+
this.l2ToL1Msgs.push(
|
|
277
|
+
new L2ToL1Message(recipientAddress, content, this.sideEffectCounter).scope(
|
|
278
|
+
AztecAddress.fromField(contractAddress),
|
|
279
|
+
),
|
|
280
|
+
);
|
|
281
|
+
this.log.debug(`NEW_L2_TO_L1_MSG cnt: ${this.sideEffectCounter}`);
|
|
282
|
+
this.incrementSideEffectCounter();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public traceUnencryptedLog(contractAddress: Fr, log: Fr[]) {
|
|
286
|
+
if (
|
|
287
|
+
this.unencryptedLogs.length + this.previousAccumulatedDataArrayLengths.unencryptedLogsHashes >=
|
|
288
|
+
MAX_UNENCRYPTED_LOGS_PER_TX
|
|
289
|
+
) {
|
|
290
|
+
throw new SideEffectLimitReachedError('unencrypted log', MAX_UNENCRYPTED_LOGS_PER_TX);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const ulog = new UnencryptedL2Log(
|
|
294
|
+
AztecAddress.fromField(contractAddress),
|
|
295
|
+
Buffer.concat(log.map(f => f.toBuffer())),
|
|
296
|
+
);
|
|
297
|
+
const basicLogHash = Fr.fromBuffer(ulog.hash());
|
|
298
|
+
this.unencryptedLogs.push(ulog);
|
|
299
|
+
// This length is for charging DA and is checked on-chain - has to be length of log preimage + 4 bytes.
|
|
300
|
+
// The .length call also has a +4 but that is unrelated
|
|
301
|
+
this.unencryptedLogsHashes.push(
|
|
302
|
+
new LogHash(basicLogHash, this.sideEffectCounter, new Fr(ulog.length + 4)).scope(
|
|
303
|
+
AztecAddress.fromField(contractAddress),
|
|
304
|
+
),
|
|
305
|
+
);
|
|
306
|
+
this.log.debug(`NEW_UNENCRYPTED_LOG cnt: ${this.sideEffectCounter}`);
|
|
307
|
+
this.incrementSideEffectCounter();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
public traceGetContractInstance(instance: TracedContractInstance) {
|
|
311
|
+
this.enforceLimitOnNullifierChecks('(contract address nullifier from GETCONTRACTINSTANCE)');
|
|
312
|
+
// TODO(dbanks12): should emit a nullifier read request
|
|
313
|
+
|
|
314
|
+
this.avmCircuitHints.contractInstances.items.push(
|
|
315
|
+
new AvmContractInstanceHint(
|
|
316
|
+
instance.address,
|
|
317
|
+
new Fr(instance.exists ? 1 : 0),
|
|
318
|
+
instance.salt,
|
|
319
|
+
instance.deployer,
|
|
320
|
+
instance.contractClassId,
|
|
321
|
+
instance.initializationHash,
|
|
322
|
+
instance.publicKeys,
|
|
323
|
+
),
|
|
324
|
+
);
|
|
325
|
+
this.log.debug(`CONTRACT_INSTANCE cnt: ${this.sideEffectCounter}`);
|
|
326
|
+
this.incrementSideEffectCounter();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Trace a nested call.
|
|
331
|
+
* Accept some results from a finished nested call's trace into this one.
|
|
332
|
+
*/
|
|
333
|
+
public traceNestedCall(
|
|
334
|
+
/** The trace of the nested call. */
|
|
335
|
+
nestedCallTrace: this,
|
|
336
|
+
/** The execution environment of the nested call. */
|
|
337
|
+
_nestedEnvironment: AvmExecutionEnvironment,
|
|
338
|
+
/** How much gas was available for this public execution. */
|
|
339
|
+
startGasLeft: Gas,
|
|
340
|
+
/** How much gas was left after this public execution. */
|
|
341
|
+
endGasLeft: Gas,
|
|
342
|
+
/** Bytecode used for this execution. */
|
|
343
|
+
_bytecode: Buffer,
|
|
344
|
+
/** The call's results */
|
|
345
|
+
avmCallResults: AvmContractCallResult,
|
|
346
|
+
/** Function name for logging */
|
|
347
|
+
_functionName: string = 'unknown',
|
|
348
|
+
) {
|
|
349
|
+
// Store end side effect counter before it gets updated by absorbing nested call trace
|
|
350
|
+
const endSideEffectCounter = new Fr(this.sideEffectCounter);
|
|
351
|
+
|
|
352
|
+
// TODO(4805): check if some threshold is reached for max nested calls (to unique contracts?)
|
|
353
|
+
// TODO(dbanks12): should emit a nullifier read request. There should be two thresholds.
|
|
354
|
+
// one for max unique contract calls, and another based on max nullifier reads.
|
|
355
|
+
// Since this trace function happens _after_ a nested call, such threshold limits must take
|
|
356
|
+
// place in another trace function that occurs _before_ a nested call.
|
|
357
|
+
if (avmCallResults.reverted) {
|
|
358
|
+
this.absorbRevertedNestedTrace(nestedCallTrace);
|
|
359
|
+
} else {
|
|
360
|
+
this.absorbSuccessfulNestedTrace(nestedCallTrace);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const gasUsed = new Gas(startGasLeft.daGas - endGasLeft.daGas, startGasLeft.l2Gas - endGasLeft.l2Gas);
|
|
364
|
+
|
|
365
|
+
this.avmCircuitHints.externalCalls.items.push(
|
|
366
|
+
new AvmExternalCallHint(
|
|
367
|
+
/*success=*/ new Fr(avmCallResults.reverted ? 0 : 1),
|
|
368
|
+
avmCallResults.output,
|
|
369
|
+
gasUsed,
|
|
370
|
+
endSideEffectCounter,
|
|
371
|
+
),
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
public absorbSuccessfulNestedTrace(nestedTrace: this) {
|
|
376
|
+
this.sideEffectCounter = nestedTrace.sideEffectCounter;
|
|
377
|
+
this.contractStorageReads.push(...nestedTrace.contractStorageReads);
|
|
378
|
+
this.contractStorageUpdateRequests.push(...nestedTrace.contractStorageUpdateRequests);
|
|
379
|
+
this.noteHashReadRequests.push(...nestedTrace.noteHashReadRequests);
|
|
380
|
+
this.noteHashes.push(...nestedTrace.noteHashes);
|
|
381
|
+
this.nullifierReadRequests.push(...nestedTrace.nullifierReadRequests);
|
|
382
|
+
this.nullifierNonExistentReadRequests.push(...nestedTrace.nullifierNonExistentReadRequests);
|
|
383
|
+
this.nullifiers.push(...nestedTrace.nullifiers);
|
|
384
|
+
this.l1ToL2MsgReadRequests.push(...nestedTrace.l1ToL2MsgReadRequests);
|
|
385
|
+
this.l2ToL1Msgs.push(...nestedTrace.l2ToL1Msgs);
|
|
386
|
+
this.unencryptedLogs.push(...nestedTrace.unencryptedLogs);
|
|
387
|
+
this.unencryptedLogsHashes.push(...nestedTrace.unencryptedLogsHashes);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
public absorbRevertedNestedTrace(nestedTrace: this) {
|
|
391
|
+
// All read requests, and any writes (storage & nullifiers) that
|
|
392
|
+
// require complex validation in public kernel (with end lifetimes)
|
|
393
|
+
// must be absorbed even on revert.
|
|
394
|
+
|
|
395
|
+
// TODO(dbanks12): What should happen to side effect counter on revert?
|
|
396
|
+
this.sideEffectCounter = nestedTrace.sideEffectCounter;
|
|
397
|
+
this.contractStorageReads.push(...nestedTrace.contractStorageReads);
|
|
398
|
+
this.contractStorageUpdateRequests.push(...nestedTrace.contractStorageUpdateRequests);
|
|
399
|
+
this.noteHashReadRequests.push(...nestedTrace.noteHashReadRequests);
|
|
400
|
+
// new noteHashes are tossed on revert
|
|
401
|
+
this.nullifierReadRequests.push(...nestedTrace.nullifierReadRequests);
|
|
402
|
+
this.nullifierNonExistentReadRequests.push(...nestedTrace.nullifierNonExistentReadRequests);
|
|
403
|
+
this.nullifiers.push(...nestedTrace.nullifiers);
|
|
404
|
+
this.l1ToL2MsgReadRequests.push(...nestedTrace.l1ToL2MsgReadRequests);
|
|
405
|
+
// new l2-to-l1 messages are tossed on revert
|
|
406
|
+
// new unencrypted logs are tossed on revert
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
public getSideEffects(): SideEffects {
|
|
410
|
+
return {
|
|
411
|
+
contractStorageReads: this.contractStorageReads,
|
|
412
|
+
contractStorageUpdateRequests: this.contractStorageUpdateRequests,
|
|
413
|
+
noteHashReadRequests: this.noteHashReadRequests,
|
|
414
|
+
noteHashes: this.noteHashes,
|
|
415
|
+
nullifierReadRequests: this.nullifierReadRequests,
|
|
416
|
+
nullifierNonExistentReadRequests: this.nullifierNonExistentReadRequests,
|
|
417
|
+
nullifiers: this.nullifiers,
|
|
418
|
+
l1ToL2MsgReadRequests: this.l1ToL2MsgReadRequests,
|
|
419
|
+
l2ToL1Msgs: this.l2ToL1Msgs,
|
|
420
|
+
unencryptedLogs: this.unencryptedLogs,
|
|
421
|
+
unencryptedLogsHashes: this.unencryptedLogsHashes,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
public toVMCircuitPublicInputs(
|
|
426
|
+
/** Constants. */
|
|
427
|
+
constants: CombinedConstantData,
|
|
428
|
+
/** The execution environment of the nested call. */
|
|
429
|
+
avmEnvironment: AvmExecutionEnvironment,
|
|
430
|
+
/** How much gas was available for this public execution. */
|
|
431
|
+
startGasLeft: Gas,
|
|
432
|
+
/** How much gas was left after this public execution. */
|
|
433
|
+
endGasLeft: Gas,
|
|
434
|
+
/** The call's results */
|
|
435
|
+
avmCallResults: AvmContractCallResult,
|
|
436
|
+
): VMCircuitPublicInputs {
|
|
437
|
+
return new VMCircuitPublicInputs(
|
|
438
|
+
/*constants=*/ constants,
|
|
439
|
+
/*callRequest=*/ createPublicCallRequest(avmEnvironment),
|
|
440
|
+
/*publicCallStack=*/ makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicInnerCallRequest.empty),
|
|
441
|
+
/*previousValidationRequestArrayLengths=*/ this.previousValidationRequestArrayLengths,
|
|
442
|
+
/*validationRequests=*/ this.getValidationRequests(),
|
|
443
|
+
/*previousAccumulatedDataArrayLengths=*/ this.previousAccumulatedDataArrayLengths,
|
|
444
|
+
/*accumulatedData=*/ this.getAccumulatedData(startGasLeft.sub(endGasLeft)),
|
|
445
|
+
/*startSideEffectCounter=*/ this.startSideEffectCounter,
|
|
446
|
+
/*endSideEffectCounter=*/ this.sideEffectCounter,
|
|
447
|
+
/*startGasLeft=*/ startGasLeft,
|
|
448
|
+
// TODO(dbanks12): should have endGasLeft
|
|
449
|
+
/*transactionFee=*/ avmEnvironment.transactionFee,
|
|
450
|
+
/*reverted=*/ avmCallResults.reverted,
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
public getUnencryptedLogs() {
|
|
455
|
+
return this.unencryptedLogs;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
public getAvmCircuitHints() {
|
|
459
|
+
return this.avmCircuitHints;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
private getValidationRequests() {
|
|
463
|
+
return new PublicValidationRequests(
|
|
464
|
+
RollupValidationRequests.empty(), // TODO(dbanks12): what should this be?
|
|
465
|
+
padArrayEnd(this.noteHashReadRequests, TreeLeafReadRequest.empty(), MAX_NOTE_HASH_READ_REQUESTS_PER_TX),
|
|
466
|
+
padArrayEnd(this.nullifierReadRequests, ScopedReadRequest.empty(), MAX_NULLIFIER_READ_REQUESTS_PER_TX),
|
|
467
|
+
padArrayEnd(
|
|
468
|
+
this.nullifierNonExistentReadRequests,
|
|
469
|
+
ScopedReadRequest.empty(),
|
|
470
|
+
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
|
|
471
|
+
),
|
|
472
|
+
padArrayEnd(this.l1ToL2MsgReadRequests, TreeLeafReadRequest.empty(), MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX),
|
|
473
|
+
// TODO(dbanks12): this is only necessary until VMCircuitPublicInputs uses unsiloed storage slots and pairs storage accesses with contract address
|
|
474
|
+
padArrayEnd(
|
|
475
|
+
this.contractStorageReads.map(r => new PublicDataRead(r.storageSlot, r.currentValue, r.counter)),
|
|
476
|
+
PublicDataRead.empty(),
|
|
477
|
+
MAX_PUBLIC_DATA_READS_PER_TX,
|
|
478
|
+
),
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
private getAccumulatedData(gasUsed: Gas) {
|
|
483
|
+
return new PublicAccumulatedData(
|
|
484
|
+
padArrayEnd(this.noteHashes, ScopedNoteHash.empty(), MAX_NOTE_HASHES_PER_TX),
|
|
485
|
+
// TODO(dbanks12): should be able to use ScopedNullifier here
|
|
486
|
+
padArrayEnd(
|
|
487
|
+
this.nullifiers.map(n => new Nullifier(n.nullifier.value, n.nullifier.counter, n.nullifier.noteHash)),
|
|
488
|
+
Nullifier.empty(),
|
|
489
|
+
MAX_NULLIFIERS_PER_TX,
|
|
490
|
+
),
|
|
491
|
+
padArrayEnd(this.l2ToL1Msgs, ScopedL2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_TX),
|
|
492
|
+
/*noteEncryptedLogsHashes=*/ makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash.empty),
|
|
493
|
+
/*encryptedLogsHashes=*/ makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty),
|
|
494
|
+
padArrayEnd(this.unencryptedLogsHashes, ScopedLogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX),
|
|
495
|
+
// TODO(dbanks12): this is only necessary until VMCircuitPublicInputs uses unsiloed storage slots and pairs storage accesses with contract address
|
|
496
|
+
padArrayEnd(
|
|
497
|
+
this.contractStorageUpdateRequests.map(w => new PublicDataUpdateRequest(w.storageSlot, w.newValue, w.counter)),
|
|
498
|
+
PublicDataUpdateRequest.empty(),
|
|
499
|
+
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
500
|
+
),
|
|
501
|
+
/*publicCallStack=*/ makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty),
|
|
502
|
+
/*gasUsed=*/ gasUsed,
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
private enforceLimitOnNullifierChecks(errorMsgOrigin: string = '') {
|
|
507
|
+
// NOTE: Why error if _either_ limit was reached? If user code emits either an existent or non-existent
|
|
508
|
+
// nullifier read request (NULLIFIEREXISTS, GETCONTRACTINSTANCE, *CALL), and one of the limits has been
|
|
509
|
+
// reached (MAX_NULLIFIER_NON_EXISTENT_RRS vs MAX_NULLIFIER_RRS), but not the other, we must prevent the
|
|
510
|
+
// sequencer from lying and saying "this nullifier exists, but MAX_NULLIFIER_RRS has been reached, so I'm
|
|
511
|
+
// going to skip the read request and just revert instead" when the nullifier actually doesn't exist
|
|
512
|
+
// (or vice versa). So, if either maximum has been reached, any nullifier-reading operation must error.
|
|
513
|
+
if (
|
|
514
|
+
this.nullifierReadRequests.length + this.previousValidationRequestArrayLengths.nullifierReadRequests >=
|
|
515
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_TX
|
|
516
|
+
) {
|
|
517
|
+
throw new SideEffectLimitReachedError(
|
|
518
|
+
`nullifier read request ${errorMsgOrigin}`,
|
|
519
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
if (
|
|
523
|
+
this.nullifierNonExistentReadRequests.length +
|
|
524
|
+
this.previousValidationRequestArrayLengths.nullifierNonExistentReadRequests >=
|
|
525
|
+
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX
|
|
526
|
+
) {
|
|
527
|
+
throw new SideEffectLimitReachedError(
|
|
528
|
+
`nullifier non-existent read request ${errorMsgOrigin}`,
|
|
529
|
+
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Helper function to create a public execution request from an AVM execution environment
|
|
537
|
+
*/
|
|
538
|
+
function createPublicCallRequest(avmEnvironment: AvmExecutionEnvironment): PublicCallRequest {
|
|
539
|
+
const callContext = CallContext.from({
|
|
540
|
+
msgSender: avmEnvironment.sender,
|
|
541
|
+
storageContractAddress: avmEnvironment.storageAddress,
|
|
542
|
+
functionSelector: avmEnvironment.functionSelector,
|
|
543
|
+
isDelegateCall: avmEnvironment.isDelegateCall,
|
|
544
|
+
isStaticCall: avmEnvironment.isStaticCall,
|
|
545
|
+
});
|
|
546
|
+
return new PublicCallRequest(
|
|
547
|
+
avmEnvironment.address,
|
|
548
|
+
callContext,
|
|
549
|
+
computeVarArgsHash(avmEnvironment.calldata),
|
|
550
|
+
/*counter=*/ 0,
|
|
551
|
+
);
|
|
552
|
+
}
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
L2ToL1Message,
|
|
24
24
|
LogHash,
|
|
25
25
|
MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL,
|
|
26
|
+
MAX_L2_GAS_PER_ENQUEUED_CALL,
|
|
26
27
|
MAX_L2_TO_L1_MSGS_PER_CALL,
|
|
27
28
|
MAX_NOTE_HASHES_PER_CALL,
|
|
28
29
|
MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
|
|
@@ -61,10 +62,9 @@ import { makeTuple } from '@aztec/foundation/array';
|
|
|
61
62
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
62
63
|
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
63
64
|
import { ProtocolCircuitVks } from '@aztec/noir-protocol-circuits-types';
|
|
64
|
-
import { type
|
|
65
|
+
import { type MerkleTreeReadOperations } from '@aztec/world-state';
|
|
65
66
|
|
|
66
|
-
import {
|
|
67
|
-
import { type PublicExecutionResult, collectExecutionResults } from './execution.js';
|
|
67
|
+
import { type PublicExecutionResult, accumulatePublicReturnValues, collectExecutionResults } from './execution.js';
|
|
68
68
|
import { type PublicExecutor } from './executor.js';
|
|
69
69
|
import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js';
|
|
70
70
|
|
|
@@ -103,7 +103,7 @@ export type EnqueuedCallResult = {
|
|
|
103
103
|
export class EnqueuedCallSimulator {
|
|
104
104
|
private log: DebugLogger;
|
|
105
105
|
constructor(
|
|
106
|
-
private db:
|
|
106
|
+
private db: MerkleTreeReadOperations,
|
|
107
107
|
private publicExecutor: PublicExecutor,
|
|
108
108
|
private publicKernelSimulator: PublicKernelCircuitSimulator,
|
|
109
109
|
private globalVariables: GlobalVariables,
|
|
@@ -121,39 +121,60 @@ export class EnqueuedCallSimulator {
|
|
|
121
121
|
transactionFee: Fr,
|
|
122
122
|
phase: PublicKernelPhase,
|
|
123
123
|
): Promise<EnqueuedCallResult> {
|
|
124
|
+
// Gas allocated to an enqueued call can be different from the available gas
|
|
125
|
+
// if there is more gas available than the max allocation per enqueued call.
|
|
126
|
+
const allocatedGas = new Gas(
|
|
127
|
+
/*daGas=*/ availableGas.daGas,
|
|
128
|
+
/*l2Gas=*/ Math.min(availableGas.l2Gas, MAX_L2_GAS_PER_ENQUEUED_CALL),
|
|
129
|
+
);
|
|
124
130
|
const pendingNullifiers = this.getSiloedPendingNullifiers(previousPublicKernelOutput);
|
|
125
131
|
const startSideEffectCounter = previousPublicKernelOutput.endSideEffectCounter + 1;
|
|
132
|
+
|
|
133
|
+
const prevAccumulatedData =
|
|
134
|
+
phase === PublicKernelPhase.SETUP
|
|
135
|
+
? previousPublicKernelOutput.endNonRevertibleData
|
|
136
|
+
: previousPublicKernelOutput.end;
|
|
137
|
+
const previousValidationRequestArrayLengths = PublicValidationRequestArrayLengths.new(
|
|
138
|
+
previousPublicKernelOutput.validationRequests,
|
|
139
|
+
);
|
|
140
|
+
const previousAccumulatedDataArrayLengths = PublicAccumulatedDataArrayLengths.new(prevAccumulatedData);
|
|
141
|
+
|
|
142
|
+
// If this is the first enqueued call in public, constants will be empty
|
|
143
|
+
// because private kernel does not expose them.
|
|
144
|
+
const constants = previousPublicKernelOutput.constants.clone();
|
|
145
|
+
constants.globalVariables = this.globalVariables;
|
|
146
|
+
|
|
126
147
|
const result = await this.publicExecutor.simulate(
|
|
127
148
|
executionRequest,
|
|
128
|
-
|
|
129
|
-
|
|
149
|
+
constants,
|
|
150
|
+
allocatedGas,
|
|
130
151
|
tx.data.constants.txContext,
|
|
131
152
|
pendingNullifiers,
|
|
132
153
|
transactionFee,
|
|
133
154
|
startSideEffectCounter,
|
|
155
|
+
previousValidationRequestArrayLengths,
|
|
156
|
+
previousAccumulatedDataArrayLengths,
|
|
134
157
|
);
|
|
135
158
|
|
|
136
159
|
const callStack = makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicInnerCallRequest.empty);
|
|
137
160
|
callStack[0].item.contractAddress = callRequest.contractAddress;
|
|
138
161
|
callStack[0].item.callContext = callRequest.callContext;
|
|
139
162
|
callStack[0].item.argsHash = callRequest.argsHash;
|
|
140
|
-
|
|
141
|
-
phase === PublicKernelPhase.SETUP
|
|
142
|
-
? previousPublicKernelOutput.endNonRevertibleData
|
|
143
|
-
: previousPublicKernelOutput.end;
|
|
163
|
+
|
|
144
164
|
const accumulatedData = PublicAccumulatedData.empty();
|
|
145
165
|
accumulatedData.publicCallStack[0] = callRequest;
|
|
166
|
+
|
|
146
167
|
const startVMCircuitOutput = new VMCircuitPublicInputs(
|
|
147
168
|
previousPublicKernelOutput.constants,
|
|
148
169
|
callRequest,
|
|
149
170
|
callStack,
|
|
150
|
-
|
|
171
|
+
previousValidationRequestArrayLengths,
|
|
151
172
|
PublicValidationRequests.empty(),
|
|
152
|
-
|
|
173
|
+
previousAccumulatedDataArrayLengths,
|
|
153
174
|
accumulatedData,
|
|
154
175
|
startSideEffectCounter,
|
|
155
176
|
startSideEffectCounter,
|
|
156
|
-
|
|
177
|
+
allocatedGas,
|
|
157
178
|
result.transactionFee,
|
|
158
179
|
result.reverted,
|
|
159
180
|
);
|
|
@@ -226,7 +247,7 @@ export class EnqueuedCallSimulator {
|
|
|
226
247
|
provingRequests,
|
|
227
248
|
kernelOutput,
|
|
228
249
|
newUnencryptedLogs: topResult.allUnencryptedLogs,
|
|
229
|
-
returnValues:
|
|
250
|
+
returnValues: accumulatePublicReturnValues(topResult),
|
|
230
251
|
gasUsed,
|
|
231
252
|
revertReason,
|
|
232
253
|
};
|