@aztec/simulator 0.38.0 → 0.40.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 +3 -5
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +13 -32
- 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 +7 -7
- package/dest/avm/avm_execution_environment.d.ts +4 -3
- package/dest/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/avm/avm_execution_environment.js +17 -11
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +5 -1
- package/dest/avm/avm_machine_state.d.ts +5 -8
- package/dest/avm/avm_machine_state.d.ts.map +1 -1
- package/dest/avm/avm_machine_state.js +10 -22
- package/dest/avm/avm_message_call_result.d.ts +5 -8
- package/dest/avm/avm_message_call_result.d.ts.map +1 -1
- package/dest/avm/avm_message_call_result.js +1 -4
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +17 -13
- package/dest/avm/errors.d.ts +43 -2
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +86 -4
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +4 -3
- package/dest/avm/opcodes/conversion.d.ts +16 -0
- package/dest/avm/opcodes/conversion.d.ts.map +1 -0
- package/dest/avm/opcodes/conversion.js +48 -0
- package/dest/avm/opcodes/environment_getters.d.ts +12 -13
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +13 -49
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +11 -1
- package/dest/avm/opcodes/index.d.ts +2 -0
- package/dest/avm/opcodes/index.d.ts.map +1 -1
- package/dest/avm/opcodes/index.js +3 -1
- package/dest/avm/opcodes/misc.d.ts +17 -0
- package/dest/avm/opcodes/misc.d.ts.map +1 -0
- package/dest/avm/opcodes/misc.js +45 -0
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +6 -2
- package/dest/avm/serialization/instruction_serialization.d.ts +6 -4
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +9 -5
- package/dest/client/client_execution_context.d.ts +29 -1
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +54 -16
- package/dest/client/db_oracle.d.ts +1 -8
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/execution_result.d.ts +4 -1
- package/dest/client/execution_result.d.ts.map +1 -1
- package/dest/client/execution_result.js +16 -3
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +3 -1
- package/dest/client/simulator.d.ts +1 -31
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +3 -42
- package/dest/client/view_data_oracle.d.ts +0 -7
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +1 -10
- package/dest/common/errors.d.ts +5 -0
- package/dest/common/errors.d.ts.map +1 -1
- package/dest/common/errors.js +6 -1
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -1
- package/dest/public/abstract_phase_manager.d.ts +8 -4
- package/dest/public/abstract_phase_manager.d.ts.map +1 -1
- package/dest/public/abstract_phase_manager.js +38 -14
- package/dest/public/app_logic_phase_manager.d.ts +1 -0
- package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
- package/dest/public/app_logic_phase_manager.js +3 -3
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +1 -4
- package/dest/public/hints_builder.d.ts +3 -3
- package/dest/public/hints_builder.d.ts.map +1 -1
- package/dest/public/hints_builder.js +3 -3
- package/dest/public/public_execution_context.d.ts +1 -0
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +6 -2
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +5 -3
- package/dest/public/setup_phase_manager.d.ts +1 -0
- package/dest/public/setup_phase_manager.d.ts.map +1 -1
- package/dest/public/setup_phase_manager.js +3 -2
- package/dest/public/tail_phase_manager.d.ts +1 -0
- package/dest/public/tail_phase_manager.d.ts.map +1 -1
- package/dest/public/tail_phase_manager.js +2 -1
- package/dest/public/teardown_phase_manager.d.ts +1 -0
- package/dest/public/teardown_phase_manager.d.ts.map +1 -1
- package/dest/public/teardown_phase_manager.js +3 -2
- package/dest/public/transitional_adaptors.d.ts.map +1 -1
- package/dest/public/transitional_adaptors.js +1 -1
- package/dest/rollup/index.d.ts +2 -0
- package/dest/rollup/index.d.ts.map +1 -0
- package/dest/rollup/index.js +2 -0
- package/dest/rollup/rollup.d.ts +77 -0
- package/dest/rollup/rollup.d.ts.map +1 -0
- package/dest/rollup/rollup.js +78 -0
- package/dest/stats/index.d.ts +2 -0
- package/dest/stats/index.d.ts.map +1 -0
- package/dest/stats/index.js +2 -0
- package/dest/stats/stats.d.ts +4 -0
- package/dest/stats/stats.d.ts.map +1 -0
- package/dest/stats/stats.js +11 -0
- package/package.json +8 -8
- package/src/acvm/oracle/oracle.ts +27 -35
- package/src/acvm/oracle/typed_oracle.ts +16 -9
- package/src/avm/avm_execution_environment.ts +34 -42
- package/src/avm/avm_gas.ts +4 -0
- package/src/avm/avm_machine_state.ts +14 -25
- package/src/avm/avm_message_call_result.ts +3 -14
- package/src/avm/avm_simulator.ts +22 -12
- package/src/avm/errors.ts +94 -4
- package/src/avm/journal/journal.ts +3 -2
- package/src/avm/opcodes/conversion.ts +59 -0
- package/src/avm/opcodes/environment_getters.ts +13 -66
- package/src/avm/opcodes/external_calls.ts +11 -0
- package/src/avm/opcodes/index.ts +2 -0
- package/src/avm/opcodes/misc.ts +63 -0
- package/src/avm/serialization/bytecode_serialization.ts +7 -0
- package/src/avm/serialization/instruction_serialization.ts +4 -0
- package/src/client/client_execution_context.ts +92 -16
- package/src/client/db_oracle.ts +1 -9
- package/src/client/execution_result.ts +21 -2
- package/src/client/private_execution.ts +2 -0
- package/src/client/simulator.ts +2 -80
- package/src/client/view_data_oracle.ts +0 -10
- package/src/common/errors.ts +5 -0
- package/src/index.ts +1 -0
- package/src/public/abstract_phase_manager.ts +46 -18
- package/src/public/app_logic_phase_manager.ts +2 -1
- package/src/public/executor.ts +0 -4
- package/src/public/hints_builder.ts +5 -5
- package/src/public/public_execution_context.ts +6 -1
- package/src/public/public_processor.ts +8 -2
- package/src/public/setup_phase_manager.ts +16 -8
- package/src/public/tail_phase_manager.ts +6 -1
- package/src/public/teardown_phase_manager.ts +16 -8
- package/src/public/transitional_adaptors.ts +1 -0
- package/src/rollup/index.ts +1 -0
- package/src/rollup/rollup.ts +160 -0
- package/src/stats/index.ts +1 -0
- package/src/stats/stats.ts +20 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types';
|
|
2
|
-
import { type PartialAddress, acvmFieldMessageToString, oracleDebugCallToFormattedStr } from '@aztec/circuits.js';
|
|
3
2
|
import { EventSelector, FunctionSelector } from '@aztec/foundation/abi';
|
|
4
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
5
4
|
import { Fr, Point } from '@aztec/foundation/fields';
|
|
6
|
-
import { createDebugLogger } from '@aztec/foundation/log';
|
|
7
5
|
|
|
8
6
|
import { type ACVMField } from '../acvm_types.js';
|
|
9
7
|
import { frToBoolean, frToNumber, fromACVMField } from '../deserialize.js';
|
|
@@ -14,7 +12,7 @@ import { type TypedOracle } from './typed_oracle.js';
|
|
|
14
12
|
* A data source that has all the apis required by Aztec.nr.
|
|
15
13
|
*/
|
|
16
14
|
export class Oracle {
|
|
17
|
-
constructor(private typedOracle: TypedOracle
|
|
15
|
+
constructor(private typedOracle: TypedOracle) {}
|
|
18
16
|
|
|
19
17
|
getRandomField(): ACVMField {
|
|
20
18
|
const val = this.typedOracle.getRandomField();
|
|
@@ -53,14 +51,6 @@ export class Oracle {
|
|
|
53
51
|
];
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
// TODO: #5834 Nuke this
|
|
57
|
-
async getPublicKeyAndPartialAddress([address]: ACVMField[]) {
|
|
58
|
-
const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddress(
|
|
59
|
-
AztecAddress.fromField(fromACVMField(address)),
|
|
60
|
-
);
|
|
61
|
-
return [publicKey.x, publicKey.y, partialAddress].map(toACVMField);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
54
|
async getContractInstance([address]: ACVMField[]) {
|
|
65
55
|
const instance = await this.typedOracle.getContractInstance(AztecAddress.fromField(fromACVMField(address)));
|
|
66
56
|
|
|
@@ -173,25 +163,10 @@ export class Oracle {
|
|
|
173
163
|
}
|
|
174
164
|
|
|
175
165
|
async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise<ACVMField[]> {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
// TODO #5834: This should be reworked to return the public keys as well
|
|
180
|
-
try {
|
|
181
|
-
({ partialAddress } = await this.typedOracle.getCompleteAddress(AztecAddress.fromField(fromACVMField(address))));
|
|
182
|
-
} catch (err) {
|
|
183
|
-
partialAddress = Fr.ZERO;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
publicKeys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address)));
|
|
188
|
-
} catch (err) {
|
|
189
|
-
publicKeys = Array(4).fill(Point.ZERO);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const acvmPublicKeys = publicKeys.flatMap(key => key.toFields());
|
|
166
|
+
const parsedAddress = AztecAddress.fromField(fromACVMField(address));
|
|
167
|
+
const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedAddress);
|
|
193
168
|
|
|
194
|
-
return [...
|
|
169
|
+
return [...publicKeys.toFields(), partialAddress].map(toACVMField);
|
|
195
170
|
}
|
|
196
171
|
|
|
197
172
|
async getNotes(
|
|
@@ -373,12 +348,10 @@ export class Oracle {
|
|
|
373
348
|
return toACVMField(logHash);
|
|
374
349
|
}
|
|
375
350
|
|
|
376
|
-
debugLog(
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
debugLogWithPrefix(arg0: ACVMField[], ...args: ACVMField[][]): void {
|
|
381
|
-
this.log.verbose(`${acvmFieldMessageToString(arg0)}: ${oracleDebugCallToFormattedStr(args)}`);
|
|
351
|
+
debugLog(message: ACVMField[], _ignoredFieldsSize: ACVMField[], fields: ACVMField[]): void {
|
|
352
|
+
const messageStr = message.map(acvmField => String.fromCharCode(fromACVMField(acvmField).toNumber())).join('');
|
|
353
|
+
const fieldsFr = fields.map(fromACVMField);
|
|
354
|
+
this.typedOracle.debugLog(messageStr, fieldsFr);
|
|
382
355
|
}
|
|
383
356
|
|
|
384
357
|
async callPrivateFunction(
|
|
@@ -438,6 +411,25 @@ export class Oracle {
|
|
|
438
411
|
return toAcvmEnqueuePublicFunctionResult(enqueuedRequest);
|
|
439
412
|
}
|
|
440
413
|
|
|
414
|
+
async setPublicTeardownFunctionCall(
|
|
415
|
+
[contractAddress]: ACVMField[],
|
|
416
|
+
[functionSelector]: ACVMField[],
|
|
417
|
+
[argsHash]: ACVMField[],
|
|
418
|
+
[sideEffectCounter]: ACVMField[],
|
|
419
|
+
[isStaticCall]: ACVMField[],
|
|
420
|
+
[isDelegateCall]: ACVMField[],
|
|
421
|
+
) {
|
|
422
|
+
const teardownRequest = await this.typedOracle.setPublicTeardownFunctionCall(
|
|
423
|
+
AztecAddress.fromString(contractAddress),
|
|
424
|
+
FunctionSelector.fromField(fromACVMField(functionSelector)),
|
|
425
|
+
fromACVMField(argsHash),
|
|
426
|
+
frToNumber(fromACVMField(sideEffectCounter)),
|
|
427
|
+
frToBoolean(fromACVMField(isStaticCall)),
|
|
428
|
+
frToBoolean(fromACVMField(isDelegateCall)),
|
|
429
|
+
);
|
|
430
|
+
return toAcvmEnqueuePublicFunctionResult(teardownRequest);
|
|
431
|
+
}
|
|
432
|
+
|
|
441
433
|
aes128Encrypt(input: ACVMField[], initializationVector: ACVMField[], key: ACVMField[]): ACVMField[] {
|
|
442
434
|
// Convert each field to a number and then to a buffer (1 byte is stored in 1 field)
|
|
443
435
|
const processedInput = Buffer.from(input.map(fromACVMField).map(f => f.toNumber()));
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from '@aztec/circuits.js';
|
|
18
18
|
import { type FunctionSelector } from '@aztec/foundation/abi';
|
|
19
19
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
20
|
-
import { Fr
|
|
20
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
21
21
|
import { type ContractInstance } from '@aztec/types/contracts';
|
|
22
22
|
|
|
23
23
|
/** Nullifier keys which both correspond to the same master nullifier secret key. */
|
|
@@ -93,10 +93,6 @@ export abstract class TypedOracle {
|
|
|
93
93
|
throw new OracleMethodNotAvailableError('getNullifierKeys');
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
getPublicKeyAndPartialAddress(_address: AztecAddress): Promise<Fr[] | undefined> {
|
|
97
|
-
throw new OracleMethodNotAvailableError('getPublicKeyAndPartialAddress');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
96
|
getContractInstance(_address: AztecAddress): Promise<ContractInstance> {
|
|
101
97
|
throw new OracleMethodNotAvailableError('getContractInstance');
|
|
102
98
|
}
|
|
@@ -140,10 +136,6 @@ export abstract class TypedOracle {
|
|
|
140
136
|
throw new OracleMethodNotAvailableError('popCapsule');
|
|
141
137
|
}
|
|
142
138
|
|
|
143
|
-
getPublicKeysForAddress(_address: AztecAddress): Promise<Point[]> {
|
|
144
|
-
throw new OracleMethodNotAvailableError('getPublicKeysForAddress');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
139
|
getNotes(
|
|
148
140
|
_storageSlot: Fr,
|
|
149
141
|
_numSelects: number,
|
|
@@ -243,7 +235,22 @@ export abstract class TypedOracle {
|
|
|
243
235
|
throw new OracleMethodNotAvailableError('enqueuePublicFunctionCall');
|
|
244
236
|
}
|
|
245
237
|
|
|
238
|
+
setPublicTeardownFunctionCall(
|
|
239
|
+
_targetContractAddress: AztecAddress,
|
|
240
|
+
_functionSelector: FunctionSelector,
|
|
241
|
+
_argsHash: Fr,
|
|
242
|
+
_sideEffectCounter: number,
|
|
243
|
+
_isStaticCall: boolean,
|
|
244
|
+
_isDelegateCall: boolean,
|
|
245
|
+
): Promise<PublicCallRequest> {
|
|
246
|
+
throw new OracleMethodNotAvailableError('setPublicTeardownFunctionCall');
|
|
247
|
+
}
|
|
248
|
+
|
|
246
249
|
aes128Encrypt(_input: Buffer, _initializationVector: Buffer, _key: Buffer): Buffer {
|
|
247
250
|
throw new OracleMethodNotAvailableError('encrypt');
|
|
248
251
|
}
|
|
252
|
+
|
|
253
|
+
debugLog(_message: string, _fields: Fr[]): void {
|
|
254
|
+
throw new OracleMethodNotAvailableError('debugLog');
|
|
255
|
+
}
|
|
249
256
|
}
|
|
@@ -45,72 +45,64 @@ export class AvmExecutionEnvironment {
|
|
|
45
45
|
this.calldata = [...inputs.toFields(), ...calldata];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
private deriveEnvironmentForNestedCallInternal(
|
|
49
49
|
targetAddress: AztecAddress,
|
|
50
50
|
calldata: Fr[],
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
functionSelector: FunctionSelector,
|
|
52
|
+
isStaticCall: boolean,
|
|
53
|
+
isDelegateCall: boolean,
|
|
54
|
+
) {
|
|
53
55
|
return new AvmExecutionEnvironment(
|
|
54
|
-
targetAddress,
|
|
56
|
+
/*address=*/ targetAddress,
|
|
55
57
|
/*storageAddress=*/ targetAddress,
|
|
56
|
-
this.address,
|
|
58
|
+
/*sender=*/ this.address,
|
|
57
59
|
this.feePerL2Gas,
|
|
58
60
|
this.feePerDaGas,
|
|
59
61
|
this.contractCallDepth,
|
|
60
62
|
this.header,
|
|
61
63
|
this.globals,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
isStaticCall,
|
|
65
|
+
isDelegateCall,
|
|
64
66
|
calldata,
|
|
65
67
|
this.gasSettings,
|
|
66
68
|
this.transactionFee,
|
|
67
|
-
|
|
69
|
+
functionSelector,
|
|
68
70
|
);
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
public
|
|
72
|
-
|
|
73
|
+
public deriveEnvironmentForNestedCall(
|
|
74
|
+
targetAddress: AztecAddress,
|
|
73
75
|
calldata: Fr[],
|
|
74
|
-
|
|
76
|
+
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
75
77
|
): AvmExecutionEnvironment {
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
/*storageAddress=*/ address,
|
|
79
|
-
this.sender,
|
|
80
|
-
this.feePerL2Gas,
|
|
81
|
-
this.feePerDaGas,
|
|
82
|
-
this.contractCallDepth,
|
|
83
|
-
this.header,
|
|
84
|
-
this.globals,
|
|
85
|
-
/*isStaticCall=*/ true,
|
|
86
|
-
this.isDelegateCall,
|
|
78
|
+
return this.deriveEnvironmentForNestedCallInternal(
|
|
79
|
+
targetAddress,
|
|
87
80
|
calldata,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
functionSelector,
|
|
82
|
+
/*isStaticCall=*/ false,
|
|
83
|
+
/*isDelegateCall=*/ false,
|
|
91
84
|
);
|
|
92
85
|
}
|
|
93
86
|
|
|
94
|
-
public
|
|
95
|
-
|
|
87
|
+
public deriveEnvironmentForNestedStaticCall(
|
|
88
|
+
targetAddress: AztecAddress,
|
|
96
89
|
calldata: Fr[],
|
|
97
|
-
|
|
90
|
+
functionSelector: FunctionSelector,
|
|
98
91
|
): AvmExecutionEnvironment {
|
|
99
|
-
return
|
|
100
|
-
|
|
101
|
-
this.storageAddress,
|
|
102
|
-
this.sender,
|
|
103
|
-
this.feePerL2Gas,
|
|
104
|
-
this.feePerDaGas,
|
|
105
|
-
this.contractCallDepth,
|
|
106
|
-
this.header,
|
|
107
|
-
this.globals,
|
|
108
|
-
this.isStaticCall,
|
|
109
|
-
/*isDelegateCall=*/ true,
|
|
92
|
+
return this.deriveEnvironmentForNestedCallInternal(
|
|
93
|
+
targetAddress,
|
|
110
94
|
calldata,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
95
|
+
functionSelector,
|
|
96
|
+
/*isStaticCall=*/ true,
|
|
97
|
+
/*isDelegateCall=*/ false,
|
|
114
98
|
);
|
|
115
99
|
}
|
|
100
|
+
|
|
101
|
+
public newDelegateCall(
|
|
102
|
+
_targetAddress: AztecAddress,
|
|
103
|
+
_calldata: Fr[],
|
|
104
|
+
_functionSelector: FunctionSelector,
|
|
105
|
+
): AvmExecutionEnvironment {
|
|
106
|
+
throw new Error('Delegate calls not supported!');
|
|
107
|
+
}
|
|
116
108
|
}
|
package/src/avm/avm_gas.ts
CHANGED
|
@@ -118,11 +118,15 @@ export const GasCosts: Record<Opcode, Gas | typeof DynamicGasCost> = {
|
|
|
118
118
|
[Opcode.DELEGATECALL]: TemporaryDefaultGasCost,
|
|
119
119
|
[Opcode.RETURN]: TemporaryDefaultGasCost,
|
|
120
120
|
[Opcode.REVERT]: TemporaryDefaultGasCost,
|
|
121
|
+
// Misc
|
|
122
|
+
[Opcode.DEBUGLOG]: TemporaryDefaultGasCost,
|
|
121
123
|
// Gadgets
|
|
122
124
|
[Opcode.KECCAK]: TemporaryDefaultGasCost,
|
|
123
125
|
[Opcode.POSEIDON2]: TemporaryDefaultGasCost,
|
|
124
126
|
[Opcode.SHA256]: TemporaryDefaultGasCost, // temp - may be removed, but alot of contracts rely on i: TemporaryDefaultGasCost,
|
|
125
127
|
[Opcode.PEDERSEN]: TemporaryDefaultGasCost, // temp - may be removed, but alot of contracts rely on i: TemporaryDefaultGasCost,t
|
|
128
|
+
// Conversions
|
|
129
|
+
[Opcode.TORADIXLE]: TemporaryDefaultGasCost,
|
|
126
130
|
};
|
|
127
131
|
|
|
128
132
|
/** Returns the fixed base gas cost for a given opcode, or throws if set to dynamic. */
|
|
@@ -2,7 +2,6 @@ import { type Fr } from '@aztec/circuits.js';
|
|
|
2
2
|
|
|
3
3
|
import { type Gas, GasDimensions } from './avm_gas.js';
|
|
4
4
|
import { TaggedMemory } from './avm_memory_types.js';
|
|
5
|
-
import { AvmContractCallResults } from './avm_message_call_result.js';
|
|
6
5
|
import { OutOfGasError } from './errors.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -36,7 +35,7 @@ export class AvmMachineState {
|
|
|
36
35
|
* Signals that execution should end.
|
|
37
36
|
* AvmContext execution continues executing instructions until the machine state signals "halted"
|
|
38
37
|
*/
|
|
39
|
-
|
|
38
|
+
private halted: boolean = false;
|
|
40
39
|
/** Signals that execution has reverted normally (this does not cover exceptional halts) */
|
|
41
40
|
private reverted: boolean = false;
|
|
42
41
|
/** Output data must NOT be modified once it is set */
|
|
@@ -118,34 +117,24 @@ export class AvmMachineState {
|
|
|
118
117
|
this.output = output;
|
|
119
118
|
}
|
|
120
119
|
|
|
120
|
+
public getHalted(): boolean {
|
|
121
|
+
return this.halted;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public getReverted(): boolean {
|
|
125
|
+
return this.reverted;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public getOutput(): Fr[] {
|
|
129
|
+
return this.output;
|
|
130
|
+
}
|
|
131
|
+
|
|
121
132
|
/**
|
|
122
133
|
* Flag an exceptional halt. Clears gas left and sets the reverted flag. No output data.
|
|
123
134
|
*/
|
|
124
|
-
|
|
135
|
+
private exceptionalHalt() {
|
|
125
136
|
GasDimensions.forEach(dimension => (this[`${dimension}Left`] = 0));
|
|
126
137
|
this.reverted = true;
|
|
127
138
|
this.halted = true;
|
|
128
139
|
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Get a summary of execution results for a halted machine state
|
|
132
|
-
* @returns summary of execution results
|
|
133
|
-
*/
|
|
134
|
-
public getResults(): AvmContractCallResults {
|
|
135
|
-
if (!this.halted) {
|
|
136
|
-
throw new Error('Execution results are not ready! Execution is ongoing.');
|
|
137
|
-
}
|
|
138
|
-
let revertReason = undefined;
|
|
139
|
-
if (this.reverted && this.output.length > 0) {
|
|
140
|
-
try {
|
|
141
|
-
// Try to interpret the output as a text string.
|
|
142
|
-
revertReason = new Error(
|
|
143
|
-
'Reverted with output: ' + String.fromCharCode(...this.output.slice(1).map(fr => fr.toNumber())),
|
|
144
|
-
);
|
|
145
|
-
} catch (e) {
|
|
146
|
-
revertReason = new Error('Reverted with non-string output');
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return new AvmContractCallResults(this.reverted, this.output, revertReason);
|
|
150
|
-
}
|
|
151
140
|
}
|
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
import { type Fr } from '@aztec/foundation/fields';
|
|
2
2
|
|
|
3
|
+
import { type AvmRevertReason } from './errors.js';
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Results of an contract call's execution in the AVM.
|
|
5
7
|
*/
|
|
6
8
|
export class AvmContractCallResults {
|
|
7
|
-
public
|
|
8
|
-
public readonly output: Fr[];
|
|
9
|
-
|
|
10
|
-
/** For exceptional halts */
|
|
11
|
-
public readonly revertReason: Error | undefined;
|
|
12
|
-
|
|
13
|
-
constructor(reverted: boolean, output: Fr[], revertReason?: Error) {
|
|
14
|
-
this.reverted = reverted;
|
|
15
|
-
this.output = output;
|
|
16
|
-
this.revertReason = revertReason;
|
|
17
|
-
}
|
|
9
|
+
constructor(public reverted: boolean, public output: Fr[], public revertReason?: AvmRevertReason) {}
|
|
18
10
|
|
|
19
|
-
/**
|
|
20
|
-
* Generate a string representation of call results.
|
|
21
|
-
*/
|
|
22
11
|
toString(): string {
|
|
23
12
|
let resultsStr = `reverted: ${this.reverted}, output: ${this.output}`;
|
|
24
13
|
if (this.revertReason) {
|
package/src/avm/avm_simulator.ts
CHANGED
|
@@ -5,7 +5,13 @@ import { strict as assert } from 'assert';
|
|
|
5
5
|
import { isAvmBytecode } from '../public/transitional_adaptors.js';
|
|
6
6
|
import type { AvmContext } from './avm_context.js';
|
|
7
7
|
import { AvmContractCallResults } from './avm_message_call_result.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
AvmExecutionError,
|
|
10
|
+
InvalidProgramCounterError,
|
|
11
|
+
NoBytecodeForContractError,
|
|
12
|
+
revertReasonFromExceptionalHalt,
|
|
13
|
+
revertReasonFromExplicitRevert,
|
|
14
|
+
} from './errors.js';
|
|
9
15
|
import type { Instruction } from './opcodes/index.js';
|
|
10
16
|
import { decodeFromBytecode } from './serialization/bytecode_serialization.js';
|
|
11
17
|
|
|
@@ -56,7 +62,7 @@ export class AvmSimulator {
|
|
|
56
62
|
try {
|
|
57
63
|
// Execute instruction pointed to by the current program counter
|
|
58
64
|
// continuing until the machine state signifies a halt
|
|
59
|
-
while (!machineState.
|
|
65
|
+
while (!machineState.getHalted()) {
|
|
60
66
|
const instruction = instructions[machineState.pc];
|
|
61
67
|
assert(
|
|
62
68
|
!!instruction,
|
|
@@ -76,21 +82,25 @@ export class AvmSimulator {
|
|
|
76
82
|
}
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
const
|
|
85
|
+
const output = machineState.getOutput();
|
|
86
|
+
const reverted = machineState.getReverted();
|
|
87
|
+
const revertReason = reverted ? revertReasonFromExplicitRevert(output, this.context) : undefined;
|
|
88
|
+
const results = new AvmContractCallResults(reverted, output, revertReason);
|
|
81
89
|
this.log.debug(`Context execution results: ${results.toString()}`);
|
|
90
|
+
// Return results for processing by calling context
|
|
82
91
|
return results;
|
|
83
|
-
} catch (
|
|
84
|
-
this.log.verbose('Exceptional halt');
|
|
85
|
-
if (!(
|
|
86
|
-
this.log.verbose(`Unknown error thrown by
|
|
87
|
-
throw
|
|
92
|
+
} catch (err: any) {
|
|
93
|
+
this.log.verbose('Exceptional halt (revert by something other than REVERT opcode)');
|
|
94
|
+
if (!(err instanceof AvmExecutionError)) {
|
|
95
|
+
this.log.verbose(`Unknown error thrown by AVM: ${err}`);
|
|
96
|
+
throw err;
|
|
88
97
|
}
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
// Note: "exceptional halts" cannot return data
|
|
92
|
-
const results = new AvmContractCallResults(/*reverted=*/ true, /*output=*/ [],
|
|
99
|
+
const revertReason = revertReasonFromExceptionalHalt(err, this.context);
|
|
100
|
+
// Note: "exceptional halts" cannot return data, hence []
|
|
101
|
+
const results = new AvmContractCallResults(/*reverted=*/ true, /*output=*/ [], revertReason);
|
|
93
102
|
this.log.debug(`Context execution results: ${results.toString()}`);
|
|
103
|
+
// Return results for processing by calling context
|
|
94
104
|
return results;
|
|
95
105
|
}
|
|
96
106
|
}
|
package/src/avm/errors.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type FailingFunction, type NoirCallStack } from '@aztec/circuit-types';
|
|
2
|
+
import { type AztecAddress, type Fr } from '@aztec/circuits.js';
|
|
3
|
+
|
|
4
|
+
import { ExecutionError } from '../common/errors.js';
|
|
5
|
+
import { type AvmContext } from './avm_context.js';
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
8
|
* Avm-specific errors should derive from this
|
|
5
9
|
*/
|
|
6
10
|
export abstract class AvmExecutionError extends Error {
|
|
7
|
-
constructor(message: string
|
|
8
|
-
super(message
|
|
9
|
-
this.name = '
|
|
11
|
+
constructor(message: string) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'AvmExecutionError';
|
|
10
14
|
}
|
|
11
15
|
}
|
|
12
16
|
|
|
@@ -63,3 +67,89 @@ export class OutOfGasError extends AvmExecutionError {
|
|
|
63
67
|
this.name = 'OutOfGasError';
|
|
64
68
|
}
|
|
65
69
|
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Error thrown to propagate a nested call's revert.
|
|
73
|
+
* @param message - the error's message
|
|
74
|
+
* @param nestedError - the revert reason of the nested call
|
|
75
|
+
*/
|
|
76
|
+
export class RethrownError extends AvmExecutionError {
|
|
77
|
+
constructor(message: string, public nestedError: AvmRevertReason) {
|
|
78
|
+
super(message);
|
|
79
|
+
this.name = 'RethrownError';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Meaningfully named alias for ExecutionError when used in the context of the AVM.
|
|
85
|
+
* Maintains a recursive structure reflecting the AVM's external callstack/errorstack, where
|
|
86
|
+
* options.cause is the error that caused this error (if this is not the root-cause itself).
|
|
87
|
+
*/
|
|
88
|
+
export class AvmRevertReason extends ExecutionError {
|
|
89
|
+
constructor(message: string, failingFunction: FailingFunction, noirCallStack: NoirCallStack, options?: ErrorOptions) {
|
|
90
|
+
super(message, failingFunction, noirCallStack, options);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Helper to create a "revert reason" error optionally with a nested error cause.
|
|
96
|
+
*
|
|
97
|
+
* @param message - the error message
|
|
98
|
+
* @param context - the context of the AVM execution used to extract the failingFunction and noirCallStack
|
|
99
|
+
* @param nestedError - the error that caused this one (if this is not the root-cause itself)
|
|
100
|
+
*/
|
|
101
|
+
function createRevertReason(message: string, context: AvmContext, nestedError?: AvmRevertReason): AvmRevertReason {
|
|
102
|
+
return new AvmRevertReason(
|
|
103
|
+
message,
|
|
104
|
+
/*failingFunction=*/ {
|
|
105
|
+
contractAddress: context.environment.address,
|
|
106
|
+
functionSelector: context.environment.temporaryFunctionSelector,
|
|
107
|
+
},
|
|
108
|
+
/*noirCallStack=*/ [...context.machineState.internalCallStack, context.machineState.pc].map(pc => `0.${pc}`),
|
|
109
|
+
/*options=*/ { cause: nestedError },
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Create a "revert reason" error for an exceptional halt,
|
|
115
|
+
* creating the recursive structure if the halt was a RethrownError.
|
|
116
|
+
*
|
|
117
|
+
* @param haltingError - the lower-level error causing the exceptional halt
|
|
118
|
+
* @param context - the context of the AVM execution used to extract the failingFunction and noirCallStack
|
|
119
|
+
*/
|
|
120
|
+
export function revertReasonFromExceptionalHalt(haltingError: AvmExecutionError, context: AvmContext): AvmRevertReason {
|
|
121
|
+
// A RethrownError has a nested/child AvmRevertReason
|
|
122
|
+
const nestedError = haltingError instanceof RethrownError ? haltingError.nestedError : undefined;
|
|
123
|
+
return createRevertReason(haltingError.message, context, nestedError);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Create a "revert reason" error for an explicit revert (a root cause).
|
|
128
|
+
*
|
|
129
|
+
* @param revertData - output data of the explicit REVERT instruction
|
|
130
|
+
* @param context - the context of the AVM execution used to extract the failingFunction and noirCallStack
|
|
131
|
+
*/
|
|
132
|
+
export function revertReasonFromExplicitRevert(revertData: Fr[], context: AvmContext): AvmRevertReason {
|
|
133
|
+
const revertMessage = decodeRevertDataAsMessage(revertData);
|
|
134
|
+
return createRevertReason(revertMessage, context);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Interpret revert data as a message string.
|
|
139
|
+
*
|
|
140
|
+
* @param revertData - output data of an explicit REVERT instruction
|
|
141
|
+
*/
|
|
142
|
+
export function decodeRevertDataAsMessage(revertData: Fr[]): string {
|
|
143
|
+
if (revertData.length === 0) {
|
|
144
|
+
return 'Assertion failed.';
|
|
145
|
+
} else {
|
|
146
|
+
try {
|
|
147
|
+
// We remove the first element which is the 'error selector'.
|
|
148
|
+
const revertOutput = revertData.slice(1);
|
|
149
|
+
// Try to interpret the output as a text string.
|
|
150
|
+
return 'Assertion failed: ' + String.fromCharCode(...revertOutput.map(fr => fr.toNumber()));
|
|
151
|
+
} catch (e) {
|
|
152
|
+
return 'Assertion failed: <cannot interpret as string>';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -119,7 +119,8 @@ export class AvmPersistableStateManager {
|
|
|
119
119
|
contractStorageUpdateRequests: [],
|
|
120
120
|
unencryptedLogsHashes: [],
|
|
121
121
|
unencryptedLogs: [],
|
|
122
|
-
|
|
122
|
+
// The length starts at 4 because it will always include the size.
|
|
123
|
+
unencryptedLogPreimagesLength: new Fr(4),
|
|
123
124
|
allUnencryptedLogs: [],
|
|
124
125
|
nestedExecutions: [],
|
|
125
126
|
};
|
|
@@ -285,7 +286,7 @@ export class AvmPersistableStateManager {
|
|
|
285
286
|
public writeL1Message(recipient: EthAddress | Fr, content: Fr) {
|
|
286
287
|
this.log.debug(`L1Messages(${recipient}) += ${content}.`);
|
|
287
288
|
const recipientAddress = recipient instanceof EthAddress ? recipient : EthAddress.fromField(recipient);
|
|
288
|
-
const message = new L2ToL1Message(recipientAddress, content);
|
|
289
|
+
const message = new L2ToL1Message(recipientAddress, content, 0);
|
|
289
290
|
this.newL1Messages.push(message);
|
|
290
291
|
|
|
291
292
|
// TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { strict as assert } from 'assert';
|
|
2
|
+
|
|
3
|
+
import { type AvmContext } from '../avm_context.js';
|
|
4
|
+
import { TypeTag, Uint8 } from '../avm_memory_types.js';
|
|
5
|
+
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
6
|
+
import { Addressing } from './addressing_mode.js';
|
|
7
|
+
import { Instruction } from './instruction.js';
|
|
8
|
+
|
|
9
|
+
export class ToRadixLE extends Instruction {
|
|
10
|
+
static type: string = 'TORADIXLE';
|
|
11
|
+
static readonly opcode: Opcode = Opcode.TORADIXLE;
|
|
12
|
+
|
|
13
|
+
// Informs (de)serialization. See Instruction.deserialize.
|
|
14
|
+
static readonly wireFormat: OperandType[] = [
|
|
15
|
+
OperandType.UINT8, // Opcode
|
|
16
|
+
OperandType.UINT8, // Indirect
|
|
17
|
+
OperandType.UINT32, // src memory address
|
|
18
|
+
OperandType.UINT32, // dst memory address
|
|
19
|
+
OperandType.UINT32, // radix (immediate)
|
|
20
|
+
OperandType.UINT32, // number of limbs (Immediate)
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
private indirect: number,
|
|
25
|
+
private srcOffset: number,
|
|
26
|
+
private dstOffset: number,
|
|
27
|
+
private radix: number,
|
|
28
|
+
private numLimbs: number,
|
|
29
|
+
) {
|
|
30
|
+
assert(radix <= 256, 'Radix cannot be greater than 256');
|
|
31
|
+
super();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public async execute(context: AvmContext): Promise<void> {
|
|
35
|
+
const memory = context.machineState.memory.track(this.type);
|
|
36
|
+
const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.srcOffset, this.dstOffset], memory);
|
|
37
|
+
const memoryOperations = { reads: 1, writes: this.numLimbs, indirect: this.indirect };
|
|
38
|
+
context.machineState.consumeGas(this.gasCost(memoryOperations));
|
|
39
|
+
|
|
40
|
+
// The radix gadget only takes in a Field
|
|
41
|
+
memory.checkTag(TypeTag.FIELD, srcOffset);
|
|
42
|
+
|
|
43
|
+
let value: bigint = memory.get(srcOffset).toBigInt();
|
|
44
|
+
const radixBN: bigint = BigInt(this.radix);
|
|
45
|
+
const limbArray = [];
|
|
46
|
+
|
|
47
|
+
for (let i = 0; i < this.numLimbs; i++) {
|
|
48
|
+
const limb = value % radixBN;
|
|
49
|
+
limbArray.push(limb);
|
|
50
|
+
value /= radixBN;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const res = [...limbArray].map(byte => new Uint8(byte));
|
|
54
|
+
memory.setSlice(dstOffset, res);
|
|
55
|
+
|
|
56
|
+
memory.assert(memoryOperations);
|
|
57
|
+
context.machineState.incrementPc();
|
|
58
|
+
}
|
|
59
|
+
}
|