@aztec/simulator 0.66.0 → 0.67.1-devnet
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/acvm/acvm.js +3 -3
- package/dest/acvm/oracle/oracle.d.ts +2 -2
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +5 -5
- package/dest/acvm/oracle/typed_oracle.d.ts +3 -3
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +5 -5
- package/dest/acvm/serialize.js +2 -2
- package/dest/avm/avm_context.d.ts +2 -2
- package/dest/avm/avm_context.d.ts.map +1 -1
- package/dest/avm/avm_context.js +3 -4
- package/dest/avm/avm_execution_environment.d.ts +4 -6
- package/dest/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/avm/avm_execution_environment.js +8 -13
- package/dest/avm/avm_memory_types.d.ts +3 -3
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +29 -29
- package/dest/avm/avm_simulator.d.ts +3 -3
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +27 -15
- package/dest/avm/avm_tree.d.ts +2 -1
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +6 -2
- package/dest/avm/errors.d.ts +3 -3
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +8 -15
- package/dest/avm/fixtures/index.d.ts +2 -0
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +7 -7
- package/dest/avm/journal/journal.d.ts +31 -8
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +139 -42
- package/dest/avm/opcodes/conversion.d.ts +4 -4
- package/dest/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/avm/opcodes/conversion.js +22 -18
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +4 -11
- package/dest/avm/opcodes/misc.d.ts.map +1 -1
- package/dest/avm/opcodes/misc.js +3 -3
- package/dest/avm/test_utils.d.ts +1 -0
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +4 -1
- package/dest/client/client_execution_context.d.ts +3 -3
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +15 -8
- package/dest/client/db_oracle.d.ts +9 -5
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/execution_note_cache.d.ts +9 -1
- package/dest/client/execution_note_cache.d.ts.map +1 -1
- package/dest/client/execution_note_cache.js +10 -3
- package/dest/client/index.d.ts +1 -0
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +2 -1
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +4 -4
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +4 -4
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +3 -3
- package/dest/client/view_data_oracle.d.ts +4 -4
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +9 -9
- package/dest/common/debug_fn_name.d.ts +2 -2
- package/dest/common/debug_fn_name.d.ts.map +1 -1
- package/dest/common/debug_fn_name.js +8 -14
- package/dest/providers/acvm_native.js +4 -4
- package/dest/providers/acvm_wasm.js +2 -2
- package/dest/providers/factory.d.ts +2 -2
- package/dest/providers/factory.d.ts.map +1 -1
- package/dest/providers/factory.js +4 -4
- package/dest/providers/index.d.ts +0 -1
- package/dest/providers/index.d.ts.map +1 -1
- package/dest/providers/index.js +1 -2
- package/dest/public/enqueued_call_side_effect_trace.d.ts +15 -26
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +42 -62
- package/dest/public/execution.d.ts +2 -2
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +2 -5
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +4 -3
- package/dest/public/fixtures/index.d.ts +24 -1
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +17 -11
- package/dest/public/index.d.ts +0 -1
- package/dest/public/index.d.ts.map +1 -1
- package/dest/public/index.js +1 -2
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +10 -9
- package/dest/public/public_processor.d.ts +12 -12
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +80 -68
- package/dest/public/public_processor_metrics.d.ts +1 -1
- package/dest/public/public_processor_metrics.d.ts.map +1 -1
- package/dest/public/public_tx_context.d.ts +13 -10
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +72 -45
- package/dest/public/public_tx_simulator.d.ts +2 -2
- package/dest/public/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator.js +54 -23
- package/dest/public/side_effect_trace_interface.d.ts +6 -18
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/public/transitional_adapters.d.ts +2 -2
- package/dest/public/transitional_adapters.d.ts.map +1 -1
- package/dest/public/transitional_adapters.js +10 -39
- package/package.json +16 -9
- package/src/acvm/acvm.ts +2 -2
- package/src/acvm/oracle/oracle.ts +4 -4
- package/src/acvm/oracle/typed_oracle.ts +5 -5
- package/src/acvm/serialize.ts +1 -1
- package/src/avm/avm_context.ts +2 -3
- package/src/avm/avm_execution_environment.ts +6 -31
- package/src/avm/avm_memory_types.ts +31 -29
- package/src/avm/avm_simulator.ts +28 -22
- package/src/avm/avm_tree.ts +6 -1
- package/src/avm/errors.ts +12 -14
- package/src/avm/fixtures/index.ts +6 -5
- package/src/avm/journal/journal.ts +230 -71
- package/src/avm/opcodes/conversion.ts +21 -16
- package/src/avm/opcodes/external_calls.ts +3 -19
- package/src/avm/opcodes/misc.ts +2 -2
- package/src/avm/test_utils.ts +4 -0
- package/src/client/client_execution_context.ts +19 -9
- package/src/client/db_oracle.ts +10 -5
- package/src/client/execution_note_cache.ts +13 -3
- package/src/client/index.ts +1 -0
- package/src/client/private_execution.ts +3 -3
- package/src/client/simulator.ts +4 -4
- package/src/client/unconstrained_execution.ts +2 -2
- package/src/client/view_data_oracle.ts +11 -9
- package/src/common/debug_fn_name.ts +7 -13
- package/src/providers/acvm_native.ts +3 -3
- package/src/providers/acvm_wasm.ts +2 -2
- package/src/providers/factory.ts +3 -3
- package/src/providers/index.ts +0 -1
- package/src/public/enqueued_call_side_effect_trace.ts +62 -86
- package/src/public/execution.ts +1 -2
- package/src/public/executor_metrics.ts +0 -4
- package/src/public/fee_payment.ts +3 -2
- package/src/public/fixtures/index.ts +25 -12
- package/src/public/index.ts +0 -1
- package/src/public/public_db_sources.ts +9 -8
- package/src/public/public_processor.ts +109 -105
- package/src/public/public_processor_metrics.ts +1 -1
- package/src/public/public_tx_context.ts +97 -50
- package/src/public/public_tx_simulator.ts +69 -38
- package/src/public/side_effect_trace_interface.ts +10 -16
- package/src/public/transitional_adapters.ts +12 -48
- package/dest/public/dual_side_effect_trace.d.ts +0 -77
- package/dest/public/dual_side_effect_trace.d.ts.map +0 -1
- package/dest/public/dual_side_effect_trace.js +0 -119
- package/dest/public/side_effect_trace.d.ts +0 -96
- package/dest/public/side_effect_trace.d.ts.map +0 -1
- package/dest/public/side_effect_trace.js +0 -309
- package/src/public/dual_side_effect_trace.ts +0 -242
- package/src/public/side_effect_trace.ts +0 -536
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { isNoirCallStackUnresolved } from '@aztec/circuit-types';
|
|
2
|
-
import { GasFees, GlobalVariables,
|
|
1
|
+
import { TxHash, isNoirCallStackUnresolved } from '@aztec/circuit-types';
|
|
2
|
+
import { GasFees, GlobalVariables, MAX_L2_GAS_PER_TX_PUBLIC_PORTION } from '@aztec/circuits.js';
|
|
3
3
|
import { type FunctionArtifact, FunctionSelector } from '@aztec/foundation/abi';
|
|
4
4
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
5
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
6
|
import { Fr } from '@aztec/foundation/fields';
|
|
7
|
-
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js';
|
|
7
|
+
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest';
|
|
8
8
|
|
|
9
9
|
import { strict as assert } from 'assert';
|
|
10
10
|
import { mock } from 'jest-mock-extended';
|
|
@@ -45,6 +45,7 @@ export function initPersistableStateManager(overrides?: {
|
|
|
45
45
|
nullifiers?: NullifierManager;
|
|
46
46
|
doMerkleOperations?: boolean;
|
|
47
47
|
merkleTrees?: AvmEphemeralForest;
|
|
48
|
+
txHash?: TxHash;
|
|
48
49
|
}): AvmPersistableStateManager {
|
|
49
50
|
const worldStateDB = overrides?.worldStateDB || mock<WorldStateDB>();
|
|
50
51
|
return new AvmPersistableStateManager(
|
|
@@ -54,6 +55,7 @@ export function initPersistableStateManager(overrides?: {
|
|
|
54
55
|
overrides?.nullifiers || new NullifierManager(worldStateDB),
|
|
55
56
|
overrides?.doMerkleOperations || false,
|
|
56
57
|
overrides?.merkleTrees || mock<AvmEphemeralForest>(),
|
|
58
|
+
overrides?.txHash || new TxHash(new Fr(27).toBuffer()),
|
|
57
59
|
);
|
|
58
60
|
}
|
|
59
61
|
|
|
@@ -64,7 +66,6 @@ export function initExecutionEnvironment(overrides?: Partial<AvmExecutionEnviron
|
|
|
64
66
|
return new AvmExecutionEnvironment(
|
|
65
67
|
overrides?.address ?? AztecAddress.zero(),
|
|
66
68
|
overrides?.sender ?? AztecAddress.zero(),
|
|
67
|
-
overrides?.functionSelector ?? FunctionSelector.empty(),
|
|
68
69
|
overrides?.contractCallDepth ?? Fr.zero(),
|
|
69
70
|
overrides?.transactionFee ?? Fr.zero(),
|
|
70
71
|
overrides?.globals ?? GlobalVariables.empty(),
|
|
@@ -94,7 +95,7 @@ export function initGlobalVariables(overrides?: Partial<GlobalVariables>): Globa
|
|
|
94
95
|
*/
|
|
95
96
|
export function initMachineState(overrides?: Partial<AvmMachineState>): AvmMachineState {
|
|
96
97
|
return AvmMachineState.fromState({
|
|
97
|
-
l2GasLeft: overrides?.l2GasLeft ??
|
|
98
|
+
l2GasLeft: overrides?.l2GasLeft ?? MAX_L2_GAS_PER_TX_PUBLIC_PORTION,
|
|
98
99
|
daGasLeft: overrides?.daGasLeft ?? 1e8,
|
|
99
100
|
});
|
|
100
101
|
}
|
|
@@ -1,23 +1,33 @@
|
|
|
1
|
-
import { MerkleTreeId } from '@aztec/circuit-types';
|
|
1
|
+
import { MerkleTreeId, type TxHash } from '@aztec/circuit-types';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
AztecAddress,
|
|
4
|
+
CANONICAL_AUTH_REGISTRY_ADDRESS,
|
|
5
|
+
DEPLOYER_CONTRACT_ADDRESS,
|
|
6
|
+
FEE_JUICE_ADDRESS,
|
|
7
|
+
MULTI_CALL_ENTRYPOINT_ADDRESS,
|
|
8
|
+
NullifierLeafPreimage,
|
|
6
9
|
type PublicCallRequest,
|
|
7
10
|
type PublicDataTreeLeafPreimage,
|
|
11
|
+
REGISTERER_CONTRACT_ADDRESS,
|
|
12
|
+
ROUTER_ADDRESS,
|
|
8
13
|
SerializableContractInstance,
|
|
9
14
|
} from '@aztec/circuits.js';
|
|
10
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
computeNoteHashNonce,
|
|
17
|
+
computePublicDataTreeLeafSlot,
|
|
18
|
+
computeUniqueNoteHash,
|
|
19
|
+
siloNoteHash,
|
|
20
|
+
siloNullifier,
|
|
21
|
+
} from '@aztec/circuits.js/hash';
|
|
11
22
|
import { Fr } from '@aztec/foundation/fields';
|
|
12
23
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
13
|
-
import {
|
|
24
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
14
25
|
|
|
15
26
|
import { strict as assert } from 'assert';
|
|
16
27
|
|
|
17
28
|
import { getPublicFunctionDebugName } from '../../common/debug_fn_name.js';
|
|
18
29
|
import { type WorldStateDB } from '../../public/public_db_sources.js';
|
|
19
30
|
import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js';
|
|
20
|
-
import { type AvmContractCallResult } from '../avm_contract_call_result.js';
|
|
21
31
|
import { type AvmExecutionEnvironment } from '../avm_execution_environment.js';
|
|
22
32
|
import { AvmEphemeralForest } from '../avm_tree.js';
|
|
23
33
|
import { NullifierCollisionError, NullifierManager } from './nullifiers.js';
|
|
@@ -33,7 +43,7 @@ import { PublicStorage } from './public_storage.js';
|
|
|
33
43
|
* Manages merging of successful/reverted child state into current state.
|
|
34
44
|
*/
|
|
35
45
|
export class AvmPersistableStateManager {
|
|
36
|
-
private readonly log =
|
|
46
|
+
private readonly log = createLogger('simulator:avm:state_manager');
|
|
37
47
|
|
|
38
48
|
/** Make sure a forked state is never merged twice. */
|
|
39
49
|
private alreadyMergedIntoParent = false;
|
|
@@ -51,6 +61,7 @@ export class AvmPersistableStateManager {
|
|
|
51
61
|
private readonly doMerkleOperations: boolean = false,
|
|
52
62
|
/** Ephmeral forest for merkle tree operations */
|
|
53
63
|
public merkleTrees: AvmEphemeralForest,
|
|
64
|
+
public readonly txHash: TxHash,
|
|
54
65
|
) {}
|
|
55
66
|
|
|
56
67
|
/**
|
|
@@ -61,6 +72,7 @@ export class AvmPersistableStateManager {
|
|
|
61
72
|
trace: PublicSideEffectTraceInterface,
|
|
62
73
|
pendingSiloedNullifiers: Fr[],
|
|
63
74
|
doMerkleOperations: boolean = false,
|
|
75
|
+
txHash: TxHash,
|
|
64
76
|
) {
|
|
65
77
|
const parentNullifiers = NullifierManager.newWithPendingSiloedNullifiers(worldStateDB, pendingSiloedNullifiers);
|
|
66
78
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
@@ -71,6 +83,7 @@ export class AvmPersistableStateManager {
|
|
|
71
83
|
/*nullifiers=*/ parentNullifiers.fork(),
|
|
72
84
|
doMerkleOperations,
|
|
73
85
|
ephemeralForest,
|
|
86
|
+
txHash,
|
|
74
87
|
);
|
|
75
88
|
}
|
|
76
89
|
|
|
@@ -81,6 +94,7 @@ export class AvmPersistableStateManager {
|
|
|
81
94
|
worldStateDB: WorldStateDB,
|
|
82
95
|
trace: PublicSideEffectTraceInterface,
|
|
83
96
|
doMerkleOperations: boolean = false,
|
|
97
|
+
txHash: TxHash,
|
|
84
98
|
) {
|
|
85
99
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
86
100
|
return new AvmPersistableStateManager(
|
|
@@ -90,6 +104,7 @@ export class AvmPersistableStateManager {
|
|
|
90
104
|
/*nullifiers=*/ new NullifierManager(worldStateDB),
|
|
91
105
|
/*doMerkleOperations=*/ doMerkleOperations,
|
|
92
106
|
ephemeralForest,
|
|
107
|
+
txHash,
|
|
93
108
|
);
|
|
94
109
|
}
|
|
95
110
|
|
|
@@ -104,6 +119,7 @@ export class AvmPersistableStateManager {
|
|
|
104
119
|
this.nullifiers.fork(),
|
|
105
120
|
this.doMerkleOperations,
|
|
106
121
|
this.merkleTrees.fork(),
|
|
122
|
+
this.txHash,
|
|
107
123
|
);
|
|
108
124
|
}
|
|
109
125
|
|
|
@@ -148,14 +164,16 @@ export class AvmPersistableStateManager {
|
|
|
148
164
|
* @param slot - the slot in the contract's storage being written to
|
|
149
165
|
* @param value - the value being written to the slot
|
|
150
166
|
*/
|
|
151
|
-
public async writeStorage(contractAddress: AztecAddress, slot: Fr, value: Fr): Promise<void> {
|
|
167
|
+
public async writeStorage(contractAddress: AztecAddress, slot: Fr, value: Fr, protocolWrite = false): Promise<void> {
|
|
152
168
|
this.log.debug(`Storage write (address=${contractAddress}, slot=${slot}): value=${value}`);
|
|
169
|
+
const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
170
|
+
this.log.debug(`leafSlot=${leafSlot}`);
|
|
153
171
|
// Cache storage writes for later reference/reads
|
|
154
172
|
this.publicStorage.write(contractAddress, slot, value);
|
|
155
|
-
|
|
173
|
+
|
|
156
174
|
if (this.doMerkleOperations) {
|
|
157
175
|
const result = await this.merkleTrees.writePublicStorage(leafSlot, value);
|
|
158
|
-
assert(result !== undefined, 'Public data tree insertion error. You might want to disable
|
|
176
|
+
assert(result !== undefined, 'Public data tree insertion error. You might want to disable doMerkleOperations.');
|
|
159
177
|
this.log.debug(`Inserted public data tree leaf at leafSlot ${leafSlot}, value: ${value}`);
|
|
160
178
|
|
|
161
179
|
const lowLeafInfo = result.lowWitness;
|
|
@@ -164,16 +182,20 @@ export class AvmPersistableStateManager {
|
|
|
164
182
|
const lowLeafPath = lowLeafInfo.siblingPath;
|
|
165
183
|
|
|
166
184
|
const newLeafPreimage = result.element as PublicDataTreeLeafPreimage;
|
|
167
|
-
let insertionPath;
|
|
168
|
-
|
|
185
|
+
let insertionPath: Fr[] | undefined;
|
|
169
186
|
if (!result.update) {
|
|
170
187
|
insertionPath = result.insertionPath;
|
|
188
|
+
assert(
|
|
189
|
+
newLeafPreimage.value.equals(value),
|
|
190
|
+
`Value mismatch when performing public data write (got value: ${value}, value in ephemeral tree: ${newLeafPreimage.value})`,
|
|
191
|
+
);
|
|
171
192
|
}
|
|
172
193
|
|
|
173
194
|
this.trace.tracePublicStorageWrite(
|
|
174
195
|
contractAddress,
|
|
175
196
|
slot,
|
|
176
197
|
value,
|
|
198
|
+
protocolWrite,
|
|
177
199
|
lowLeafPreimage,
|
|
178
200
|
new Fr(lowLeafIndex),
|
|
179
201
|
lowLeafPath,
|
|
@@ -181,7 +203,7 @@ export class AvmPersistableStateManager {
|
|
|
181
203
|
insertionPath,
|
|
182
204
|
);
|
|
183
205
|
} else {
|
|
184
|
-
this.trace.tracePublicStorageWrite(contractAddress, slot, value);
|
|
206
|
+
this.trace.tracePublicStorageWrite(contractAddress, slot, value, protocolWrite);
|
|
185
207
|
}
|
|
186
208
|
}
|
|
187
209
|
|
|
@@ -195,8 +217,8 @@ export class AvmPersistableStateManager {
|
|
|
195
217
|
public async readStorage(contractAddress: AztecAddress, slot: Fr): Promise<Fr> {
|
|
196
218
|
const { value, cached } = await this.publicStorage.read(contractAddress, slot);
|
|
197
219
|
this.log.debug(`Storage read (address=${contractAddress}, slot=${slot}): value=${value}, cached=${cached}`);
|
|
198
|
-
|
|
199
220
|
const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
221
|
+
this.log.debug(`leafSlot=${leafSlot}`);
|
|
200
222
|
|
|
201
223
|
if (this.doMerkleOperations) {
|
|
202
224
|
// Get leaf if present, low leaf if absent
|
|
@@ -211,12 +233,18 @@ export class AvmPersistableStateManager {
|
|
|
211
233
|
const leafPath = await this.merkleTrees.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex);
|
|
212
234
|
const leafPreimage = preimage as PublicDataTreeLeafPreimage;
|
|
213
235
|
|
|
236
|
+
this.log.debug(`leafPreimage.slot: ${leafPreimage.slot}, leafPreimage.value: ${leafPreimage.value}`);
|
|
214
237
|
this.log.debug(
|
|
215
238
|
`leafPreimage.nextSlot: ${leafPreimage.nextSlot}, leafPreimage.nextIndex: ${Number(leafPreimage.nextIndex)}`,
|
|
216
239
|
);
|
|
217
|
-
this.log.debug(`leafPreimage.slot: ${leafPreimage.slot}, leafPreimage.value: ${leafPreimage.value}`);
|
|
218
240
|
|
|
219
|
-
if (
|
|
241
|
+
if (alreadyPresent) {
|
|
242
|
+
assert(
|
|
243
|
+
leafPreimage.value.equals(value),
|
|
244
|
+
`Value mismatch when performing public data read (got value: ${value}, value in ephemeral tree: ${leafPreimage.value})`,
|
|
245
|
+
);
|
|
246
|
+
} else {
|
|
247
|
+
this.log.debug(`Slot has never been written before!`);
|
|
220
248
|
// Sanity check that the leaf slot is skipped by low leaf when it doesn't exist
|
|
221
249
|
assert(
|
|
222
250
|
leafPreimage.slot.toBigInt() < leafSlot.toBigInt() &&
|
|
@@ -224,9 +252,6 @@ export class AvmPersistableStateManager {
|
|
|
224
252
|
'Public data tree low leaf should skip the target leaf slot when the target leaf does not exist or is the max value.',
|
|
225
253
|
);
|
|
226
254
|
}
|
|
227
|
-
this.log.debug(
|
|
228
|
-
`Tracing storage leaf preimage slot=${slot}, leafSlot=${leafSlot}, value=${value}, nextKey=${leafPreimage.nextSlot}, nextIndex=${leafPreimage.nextIndex}`,
|
|
229
|
-
);
|
|
230
255
|
// On non-existence, AVM circuit will need to recognize that leafPreimage.slot != leafSlot,
|
|
231
256
|
// prove that this is a low leaf that skips leafSlot, and then prove membership of the leaf.
|
|
232
257
|
this.trace.tracePublicStorageRead(contractAddress, slot, value, leafPreimage, new Fr(leafIndex), leafPath);
|
|
@@ -277,20 +302,41 @@ export class AvmPersistableStateManager {
|
|
|
277
302
|
}
|
|
278
303
|
|
|
279
304
|
/**
|
|
280
|
-
* Write a note hash, trace the write.
|
|
305
|
+
* Write a raw note hash, silo it and make it unique, then trace the write.
|
|
281
306
|
* @param noteHash - the unsiloed note hash to write
|
|
282
307
|
*/
|
|
283
308
|
public writeNoteHash(contractAddress: AztecAddress, noteHash: Fr): void {
|
|
284
|
-
|
|
309
|
+
const siloedNoteHash = siloNoteHash(contractAddress, noteHash);
|
|
310
|
+
|
|
311
|
+
this.writeSiloedNoteHash(siloedNoteHash);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Write a note hash, make it unique, trace the write.
|
|
316
|
+
* @param noteHash - the non unique note hash to write
|
|
317
|
+
*/
|
|
318
|
+
public writeSiloedNoteHash(noteHash: Fr): void {
|
|
319
|
+
const txHash = Fr.fromBuffer(this.txHash.toBuffer());
|
|
320
|
+
const nonce = computeNoteHashNonce(txHash, this.trace.getNoteHashCount());
|
|
321
|
+
const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash);
|
|
322
|
+
|
|
323
|
+
this.writeUniqueNoteHash(uniqueNoteHash);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Write a note hash, trace the write.
|
|
328
|
+
* @param noteHash - the siloed unique hash to write
|
|
329
|
+
*/
|
|
330
|
+
public writeUniqueNoteHash(noteHash: Fr): void {
|
|
331
|
+
this.log.debug(`noteHashes += @${noteHash}.`);
|
|
285
332
|
|
|
286
333
|
if (this.doMerkleOperations) {
|
|
287
334
|
// Should write a helper for this
|
|
288
335
|
const leafIndex = new Fr(this.merkleTrees.treeMap.get(MerkleTreeId.NOTE_HASH_TREE)!.leafCount);
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
this.trace.traceNewNoteHash(contractAddress, noteHash, leafIndex, insertionPath);
|
|
336
|
+
const insertionPath = this.merkleTrees.appendNoteHash(noteHash);
|
|
337
|
+
this.trace.traceNewNoteHash(noteHash, leafIndex, insertionPath);
|
|
292
338
|
} else {
|
|
293
|
-
this.trace.traceNewNoteHash(
|
|
339
|
+
this.trace.traceNewNoteHash(noteHash);
|
|
294
340
|
}
|
|
295
341
|
}
|
|
296
342
|
|
|
@@ -303,8 +349,47 @@ export class AvmPersistableStateManager {
|
|
|
303
349
|
public async checkNullifierExists(contractAddress: AztecAddress, nullifier: Fr): Promise<boolean> {
|
|
304
350
|
this.log.debug(`Checking existence of nullifier (address=${contractAddress}, nullifier=${nullifier})`);
|
|
305
351
|
const siloedNullifier = siloNullifier(contractAddress, nullifier);
|
|
352
|
+
const [exists, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
|
|
353
|
+
siloedNullifier,
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
if (this.doMerkleOperations) {
|
|
357
|
+
this.trace.traceNullifierCheck(
|
|
358
|
+
siloedNullifier,
|
|
359
|
+
exists,
|
|
360
|
+
leafOrLowLeafPreimage,
|
|
361
|
+
leafOrLowLeafIndex,
|
|
362
|
+
leafOrLowLeafPath,
|
|
363
|
+
);
|
|
364
|
+
} else {
|
|
365
|
+
this.trace.traceNullifierCheck(siloedNullifier, exists);
|
|
366
|
+
}
|
|
367
|
+
return Promise.resolve(exists);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Helper to get membership information for a siloed nullifier when checking its existence.
|
|
372
|
+
* Optionally trace the nullifier check.
|
|
373
|
+
*
|
|
374
|
+
* @param siloedNullifier - the siloed nullifier to get membership information for
|
|
375
|
+
* @returns
|
|
376
|
+
* - exists - whether the nullifier exists in the nullifier set
|
|
377
|
+
* - leafOrLowLeafPreimage - the preimage of the nullifier leaf or its low-leaf if it doesn't exist
|
|
378
|
+
* - leafOrLowLeafIndex - the leaf index of the nullifier leaf or its low-leaf if it doesn't exist
|
|
379
|
+
* - leafOrLowLeafPath - the sibling path of the nullifier leaf or its low-leaf if it doesn't exist
|
|
380
|
+
*/
|
|
381
|
+
private async getNullifierMembership(
|
|
382
|
+
siloedNullifier: Fr,
|
|
383
|
+
): Promise<
|
|
384
|
+
[
|
|
385
|
+
/*exists=*/ boolean,
|
|
386
|
+
/*leafOrLowLeafPreimage=*/ NullifierLeafPreimage,
|
|
387
|
+
/*leafOrLowLeafIndex=*/ Fr,
|
|
388
|
+
/*leafOrLowLeafIndexPath=*/ Fr[],
|
|
389
|
+
]
|
|
390
|
+
> {
|
|
306
391
|
const [exists, isPending, _] = await this.nullifiers.checkExists(siloedNullifier);
|
|
307
|
-
this.log.debug(`Checked siloed nullifier ${siloedNullifier} (exists=${exists}, pending=${isPending}
|
|
392
|
+
this.log.debug(`Checked siloed nullifier ${siloedNullifier} (exists=${exists}), pending=${isPending}`);
|
|
308
393
|
|
|
309
394
|
if (this.doMerkleOperations) {
|
|
310
395
|
// Get leaf if present, low leaf if absent
|
|
@@ -319,7 +404,7 @@ export class AvmPersistableStateManager {
|
|
|
319
404
|
|
|
320
405
|
assert(
|
|
321
406
|
alreadyPresent == exists,
|
|
322
|
-
'WorldStateDB contains nullifier leaf, but merkle tree does not.... This is a bug!',
|
|
407
|
+
'WorldStateDB contains nullifier leaf, but merkle tree does not (or vice versa).... This is a bug!',
|
|
323
408
|
);
|
|
324
409
|
|
|
325
410
|
if (exists) {
|
|
@@ -327,17 +412,15 @@ export class AvmPersistableStateManager {
|
|
|
327
412
|
} else {
|
|
328
413
|
// Sanity check that the leaf value is skipped by low leaf when it doesn't exist
|
|
329
414
|
assert(
|
|
330
|
-
|
|
331
|
-
|
|
415
|
+
leafPreimage.nullifier.toBigInt() < siloedNullifier.toBigInt() &&
|
|
416
|
+
(leafPreimage.nextIndex === 0n || leafPreimage.nextNullifier.toBigInt() > siloedNullifier.toBigInt()),
|
|
332
417
|
'Nullifier tree low leaf should skip the target leaf nullifier when the target leaf does not exist.',
|
|
333
418
|
);
|
|
334
419
|
}
|
|
335
|
-
|
|
336
|
-
this.trace.traceNullifierCheck(siloedNullifier, exists, leafPreimage, new Fr(leafIndex), leafPath);
|
|
420
|
+
return [exists, leafPreimage, new Fr(leafIndex), leafPath];
|
|
337
421
|
} else {
|
|
338
|
-
|
|
422
|
+
return [exists, NullifierLeafPreimage.empty(), Fr.ZERO, []];
|
|
339
423
|
}
|
|
340
|
-
return Promise.resolve(exists);
|
|
341
424
|
}
|
|
342
425
|
|
|
343
426
|
/**
|
|
@@ -484,18 +567,59 @@ export class AvmPersistableStateManager {
|
|
|
484
567
|
const instanceWithAddress = await this.worldStateDB.getContractInstance(contractAddress);
|
|
485
568
|
const exists = instanceWithAddress !== undefined;
|
|
486
569
|
|
|
487
|
-
|
|
570
|
+
let [existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = [
|
|
571
|
+
exists,
|
|
572
|
+
NullifierLeafPreimage.empty(),
|
|
573
|
+
Fr.ZERO,
|
|
574
|
+
new Array<Fr>(),
|
|
575
|
+
];
|
|
576
|
+
if (!contractAddressIsCanonical(contractAddress)) {
|
|
577
|
+
const contractAddressNullifier = siloNullifier(
|
|
578
|
+
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
579
|
+
contractAddress.toField(),
|
|
580
|
+
);
|
|
581
|
+
[existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
|
|
582
|
+
/*siloedNullifier=*/ contractAddressNullifier,
|
|
583
|
+
);
|
|
584
|
+
assert(
|
|
585
|
+
exists == existsInTree,
|
|
586
|
+
'WorldStateDB contains contract instance, but nullifier tree does not contain contract address (or vice versa).... This is a bug!',
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
|
|
488
590
|
if (exists) {
|
|
489
591
|
const instance = new SerializableContractInstance(instanceWithAddress);
|
|
490
592
|
this.log.debug(
|
|
491
593
|
`Got contract instance (address=${contractAddress}): exists=${exists}, instance=${jsonStringify(instance)}`,
|
|
492
594
|
);
|
|
493
|
-
this.
|
|
595
|
+
if (this.doMerkleOperations) {
|
|
596
|
+
this.trace.traceGetContractInstance(
|
|
597
|
+
contractAddress,
|
|
598
|
+
exists,
|
|
599
|
+
instance,
|
|
600
|
+
leafOrLowLeafPreimage,
|
|
601
|
+
leafOrLowLeafIndex,
|
|
602
|
+
leafOrLowLeafPath,
|
|
603
|
+
);
|
|
604
|
+
} else {
|
|
605
|
+
this.trace.traceGetContractInstance(contractAddress, exists, instance);
|
|
606
|
+
}
|
|
494
607
|
|
|
495
608
|
return Promise.resolve(instance);
|
|
496
609
|
} else {
|
|
497
610
|
this.log.debug(`Contract instance NOT FOUND (address=${contractAddress})`);
|
|
498
|
-
this.
|
|
611
|
+
if (this.doMerkleOperations) {
|
|
612
|
+
this.trace.traceGetContractInstance(
|
|
613
|
+
contractAddress,
|
|
614
|
+
exists,
|
|
615
|
+
/*instance=*/ undefined,
|
|
616
|
+
leafOrLowLeafPreimage,
|
|
617
|
+
leafOrLowLeafIndex,
|
|
618
|
+
leafOrLowLeafPath,
|
|
619
|
+
);
|
|
620
|
+
} else {
|
|
621
|
+
this.trace.traceGetContractInstance(contractAddress, exists);
|
|
622
|
+
}
|
|
499
623
|
return Promise.resolve(undefined);
|
|
500
624
|
}
|
|
501
625
|
}
|
|
@@ -508,6 +632,26 @@ export class AvmPersistableStateManager {
|
|
|
508
632
|
const instanceWithAddress = await this.worldStateDB.getContractInstance(contractAddress);
|
|
509
633
|
const exists = instanceWithAddress !== undefined;
|
|
510
634
|
|
|
635
|
+
let [existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = [
|
|
636
|
+
exists,
|
|
637
|
+
NullifierLeafPreimage.empty(),
|
|
638
|
+
Fr.ZERO,
|
|
639
|
+
new Array<Fr>(),
|
|
640
|
+
];
|
|
641
|
+
if (!contractAddressIsCanonical(contractAddress)) {
|
|
642
|
+
const contractAddressNullifier = siloNullifier(
|
|
643
|
+
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
644
|
+
contractAddress.toField(),
|
|
645
|
+
);
|
|
646
|
+
[existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
|
|
647
|
+
/*siloedNullifier=*/ contractAddressNullifier,
|
|
648
|
+
);
|
|
649
|
+
assert(
|
|
650
|
+
exists == existsInTree,
|
|
651
|
+
'WorldStateDB contains contract instance, but nullifier tree does not contain contract address (or vice versa).... This is a bug!',
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
|
|
511
655
|
if (exists) {
|
|
512
656
|
const instance = new SerializableContractInstance(instanceWithAddress);
|
|
513
657
|
const contractClass = await this.worldStateDB.getContractClass(instance.contractClassId);
|
|
@@ -529,51 +673,66 @@ export class AvmPersistableStateManager {
|
|
|
529
673
|
publicBytecodeCommitment: bytecodeCommitment,
|
|
530
674
|
};
|
|
531
675
|
|
|
532
|
-
this.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
676
|
+
if (this.doMerkleOperations) {
|
|
677
|
+
this.trace.traceGetBytecode(
|
|
678
|
+
contractAddress,
|
|
679
|
+
exists,
|
|
680
|
+
contractClass.packedBytecode,
|
|
681
|
+
instance,
|
|
682
|
+
contractClassPreimage,
|
|
683
|
+
leafOrLowLeafPreimage,
|
|
684
|
+
leafOrLowLeafIndex,
|
|
685
|
+
leafOrLowLeafPath,
|
|
686
|
+
);
|
|
687
|
+
} else {
|
|
688
|
+
this.trace.traceGetBytecode(
|
|
689
|
+
contractAddress,
|
|
690
|
+
exists,
|
|
691
|
+
contractClass.packedBytecode,
|
|
692
|
+
instance,
|
|
693
|
+
contractClassPreimage,
|
|
694
|
+
);
|
|
695
|
+
}
|
|
539
696
|
|
|
540
697
|
return contractClass.packedBytecode;
|
|
541
698
|
} else {
|
|
542
699
|
// If the contract instance is not found, we assume it has not been deployed.
|
|
543
700
|
// It doesnt matter what the values of the contract instance are in this case, as long as we tag it with exists=false.
|
|
544
701
|
// This will hint to the avm circuit to just perform the non-membership check on the address and disregard the bytecode hash
|
|
545
|
-
this.
|
|
702
|
+
if (this.doMerkleOperations) {
|
|
703
|
+
this.trace.traceGetBytecode(
|
|
704
|
+
contractAddress,
|
|
705
|
+
exists,
|
|
706
|
+
/*instance=*/ undefined,
|
|
707
|
+
/*contractClass=*/ undefined,
|
|
708
|
+
/*bytecode=*/ undefined,
|
|
709
|
+
leafOrLowLeafPreimage,
|
|
710
|
+
leafOrLowLeafIndex,
|
|
711
|
+
leafOrLowLeafPath,
|
|
712
|
+
);
|
|
713
|
+
} else {
|
|
714
|
+
this.trace.traceGetBytecode(contractAddress, exists); // bytecode, instance, class undefined
|
|
715
|
+
}
|
|
546
716
|
return undefined;
|
|
547
717
|
}
|
|
548
718
|
}
|
|
549
719
|
|
|
550
|
-
public async traceNestedCall(
|
|
551
|
-
forkedState: AvmPersistableStateManager,
|
|
552
|
-
nestedEnvironment: AvmExecutionEnvironment,
|
|
553
|
-
startGasLeft: Gas,
|
|
554
|
-
bytecode: Buffer,
|
|
555
|
-
avmCallResults: AvmContractCallResult,
|
|
556
|
-
) {
|
|
557
|
-
const functionName = await getPublicFunctionDebugName(
|
|
558
|
-
this.worldStateDB,
|
|
559
|
-
nestedEnvironment.address,
|
|
560
|
-
nestedEnvironment.functionSelector,
|
|
561
|
-
nestedEnvironment.calldata,
|
|
562
|
-
);
|
|
563
|
-
|
|
564
|
-
this.log.verbose(`[AVM] Tracing nested external contract call ${functionName}`);
|
|
565
|
-
|
|
566
|
-
this.trace.traceNestedCall(
|
|
567
|
-
forkedState.trace,
|
|
568
|
-
nestedEnvironment,
|
|
569
|
-
startGasLeft,
|
|
570
|
-
bytecode,
|
|
571
|
-
avmCallResults,
|
|
572
|
-
functionName,
|
|
573
|
-
);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
720
|
public traceEnqueuedCall(publicCallRequest: PublicCallRequest, calldata: Fr[], reverted: boolean) {
|
|
577
721
|
this.trace.traceEnqueuedCall(publicCallRequest, calldata, reverted);
|
|
578
722
|
}
|
|
723
|
+
|
|
724
|
+
public async getPublicFunctionDebugName(avmEnvironment: AvmExecutionEnvironment): Promise<string> {
|
|
725
|
+
return await getPublicFunctionDebugName(this.worldStateDB, avmEnvironment.address, avmEnvironment.calldata);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
function contractAddressIsCanonical(contractAddress: AztecAddress): boolean {
|
|
730
|
+
return (
|
|
731
|
+
contractAddress.equals(AztecAddress.fromNumber(CANONICAL_AUTH_REGISTRY_ADDRESS)) ||
|
|
732
|
+
contractAddress.equals(AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS)) ||
|
|
733
|
+
contractAddress.equals(AztecAddress.fromNumber(REGISTERER_CONTRACT_ADDRESS)) ||
|
|
734
|
+
contractAddress.equals(AztecAddress.fromNumber(MULTI_CALL_ENTRYPOINT_ADDRESS)) ||
|
|
735
|
+
contractAddress.equals(AztecAddress.fromNumber(FEE_JUICE_ADDRESS)) ||
|
|
736
|
+
contractAddress.equals(AztecAddress.fromNumber(ROUTER_ADDRESS))
|
|
737
|
+
);
|
|
579
738
|
}
|
|
@@ -12,57 +12,62 @@ export class ToRadixBE extends Instruction {
|
|
|
12
12
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
13
13
|
static readonly wireFormat: OperandType[] = [
|
|
14
14
|
OperandType.UINT8, // Opcode
|
|
15
|
-
OperandType.
|
|
15
|
+
OperandType.UINT16, // Indirect
|
|
16
16
|
OperandType.UINT16, // src memory address
|
|
17
|
-
OperandType.UINT16, // dst memory address
|
|
18
17
|
OperandType.UINT16, // radix memory address
|
|
19
|
-
OperandType.UINT16, // number of limbs
|
|
20
|
-
OperandType.
|
|
18
|
+
OperandType.UINT16, // number of limbs address
|
|
19
|
+
OperandType.UINT16, // output is in "bits" mode memory address (boolean/Uint1 is stored)
|
|
20
|
+
OperandType.UINT16, // dst memory address
|
|
21
21
|
];
|
|
22
22
|
|
|
23
23
|
constructor(
|
|
24
24
|
private indirect: number,
|
|
25
25
|
private srcOffset: number,
|
|
26
|
-
private dstOffset: number,
|
|
27
26
|
private radixOffset: number,
|
|
28
|
-
private
|
|
29
|
-
private
|
|
27
|
+
private numLimbsOffset: number,
|
|
28
|
+
private outputBitsOffset: number,
|
|
29
|
+
private dstOffset: number,
|
|
30
30
|
) {
|
|
31
31
|
super();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
public async execute(context: AvmContext): Promise<void> {
|
|
35
35
|
const memory = context.machineState.memory.track(this.type);
|
|
36
|
-
const operands = [this.srcOffset, this.
|
|
36
|
+
const operands = [this.srcOffset, this.radixOffset, this.numLimbsOffset, this.outputBitsOffset, this.dstOffset];
|
|
37
37
|
const addressing = Addressing.fromWire(this.indirect, operands.length);
|
|
38
|
-
const [srcOffset,
|
|
39
|
-
context.machineState.consumeGas(this.gasCost(this.numLimbs));
|
|
38
|
+
const [srcOffset, radixOffset, numLimbsOffset, outputBitsOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
40
39
|
|
|
41
40
|
// The radix gadget only takes in a Field
|
|
42
41
|
memory.checkTag(TypeTag.FIELD, srcOffset);
|
|
43
42
|
memory.checkTag(TypeTag.UINT32, radixOffset);
|
|
43
|
+
memory.checkTag(TypeTag.UINT32, numLimbsOffset);
|
|
44
|
+
memory.checkTag(TypeTag.UINT1, outputBitsOffset);
|
|
45
|
+
|
|
46
|
+
const numLimbs = memory.get(numLimbsOffset).toNumber();
|
|
47
|
+
context.machineState.consumeGas(this.gasCost(numLimbs));
|
|
48
|
+
const outputBits = memory.get(outputBitsOffset).toNumber();
|
|
44
49
|
|
|
45
50
|
let value: bigint = memory.get(srcOffset).toBigInt();
|
|
46
51
|
const radix: bigint = memory.get(radixOffset).toBigInt();
|
|
47
|
-
if (
|
|
48
|
-
throw new InstructionExecutionError(`ToRadixBE instruction's numLimbs should be > 0 (was ${
|
|
52
|
+
if (numLimbs < 1) {
|
|
53
|
+
throw new InstructionExecutionError(`ToRadixBE instruction's numLimbs should be > 0 (was ${numLimbs})`);
|
|
49
54
|
}
|
|
50
55
|
if (radix > 256) {
|
|
51
56
|
throw new InstructionExecutionError(`ToRadixBE instruction's radix should be <= 256 (was ${radix})`);
|
|
52
57
|
}
|
|
53
58
|
const radixBN: bigint = BigInt(radix);
|
|
54
|
-
const limbArray = new Array(
|
|
59
|
+
const limbArray = new Array(numLimbs);
|
|
55
60
|
|
|
56
|
-
for (let i =
|
|
61
|
+
for (let i = numLimbs - 1; i >= 0; i--) {
|
|
57
62
|
const limb = value % radixBN;
|
|
58
63
|
limbArray[i] = limb;
|
|
59
64
|
value /= radixBN;
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
const outputType =
|
|
67
|
+
const outputType = outputBits != 0 ? Uint1 : Uint8;
|
|
63
68
|
const res = limbArray.map(byte => new outputType(byte));
|
|
64
69
|
memory.setSlice(dstOffset, res);
|
|
65
70
|
|
|
66
|
-
memory.assert({ reads:
|
|
71
|
+
memory.assert({ reads: 4, writes: numLimbs, addressing });
|
|
67
72
|
}
|
|
68
73
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Fr, FunctionSelector, Gas, PUBLIC_DISPATCH_SELECTOR } from '@aztec/circuits.js';
|
|
2
|
-
|
|
3
1
|
import type { AvmContext } from '../avm_context.js';
|
|
4
2
|
import { type AvmContractCallResult } from '../avm_contract_call_result.js';
|
|
5
3
|
import { type Field, TypeTag, Uint1 } from '../avm_memory_types.js';
|
|
@@ -45,7 +43,6 @@ abstract class ExternalCall extends Instruction {
|
|
|
45
43
|
|
|
46
44
|
const callAddress = memory.getAs<Field>(addrOffset);
|
|
47
45
|
const calldata = memory.getSlice(argsOffset, calldataSize).map(f => f.toFr());
|
|
48
|
-
const functionSelector = new Fr(PUBLIC_DISPATCH_SELECTOR);
|
|
49
46
|
// If we are already in a static call, we propagate the environment.
|
|
50
47
|
const callType = context.environment.isStaticCall ? 'STATICCALL' : this.type;
|
|
51
48
|
|
|
@@ -62,15 +59,10 @@ abstract class ExternalCall extends Instruction {
|
|
|
62
59
|
const allocatedGas = { l2Gas: allocatedL2Gas, daGas: allocatedDaGas };
|
|
63
60
|
context.machineState.consumeGas(allocatedGas);
|
|
64
61
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
calldata,
|
|
68
|
-
allocatedGas,
|
|
69
|
-
callType,
|
|
70
|
-
FunctionSelector.fromField(functionSelector),
|
|
71
|
-
);
|
|
62
|
+
const aztecAddress = callAddress.toAztecAddress();
|
|
63
|
+
const nestedContext = context.createNestedContractCallContext(aztecAddress, calldata, allocatedGas, callType);
|
|
72
64
|
|
|
73
|
-
const simulator =
|
|
65
|
+
const simulator = await AvmSimulator.build(nestedContext);
|
|
74
66
|
const nestedCallResults: AvmContractCallResult = await simulator.execute();
|
|
75
67
|
const success = !nestedCallResults.reverted;
|
|
76
68
|
|
|
@@ -102,14 +94,6 @@ abstract class ExternalCall extends Instruction {
|
|
|
102
94
|
} else {
|
|
103
95
|
context.persistableState.reject(nestedContext.persistableState);
|
|
104
96
|
}
|
|
105
|
-
await context.persistableState.traceNestedCall(
|
|
106
|
-
/*nestedState=*/ nestedContext.persistableState,
|
|
107
|
-
/*nestedEnvironment=*/ nestedContext.environment,
|
|
108
|
-
/*startGasLeft=*/ Gas.from(allocatedGas),
|
|
109
|
-
/*bytecode=*/ simulator.getBytecode()!,
|
|
110
|
-
/*avmCallResults=*/ nestedCallResults,
|
|
111
|
-
);
|
|
112
|
-
|
|
113
97
|
memory.assert({ reads: calldataSize + 4, writes: 1, addressing });
|
|
114
98
|
}
|
|
115
99
|
|