@aztec/simulator 0.30.1 → 0.32.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 +1 -1
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +3 -3
- package/dest/acvm/oracle/typed_oracle.d.ts +1 -1
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +2 -2
- package/dest/avm/avm_execution_environment.d.ts +7 -0
- package/dest/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/avm/avm_execution_environment.js +16 -1
- package/dest/avm/avm_gas_cost.d.ts +322 -0
- package/dest/avm/avm_gas_cost.d.ts.map +1 -0
- package/dest/avm/avm_gas_cost.js +118 -0
- package/dest/avm/avm_machine_state.d.ts +12 -1
- package/dest/avm/avm_machine_state.d.ts.map +1 -1
- package/dest/avm/avm_machine_state.js +31 -2
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +2 -1
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +2 -2
- package/dest/avm/errors.d.ts +4 -0
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +8 -1
- package/dest/avm/fixtures/index.d.ts +7 -1
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +20 -6
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +7 -2
- package/dest/avm/opcodes/addressing_mode.d.ts +1 -1
- package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
- package/dest/avm/opcodes/addressing_mode.js +1 -1
- package/dest/avm/opcodes/arithmetic.d.ts +15 -12
- package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
- package/dest/avm/opcodes/arithmetic.js +25 -36
- package/dest/avm/opcodes/hashing.d.ts +12 -12
- package/dest/avm/opcodes/hashing.d.ts.map +1 -1
- package/dest/avm/opcodes/hashing.js +24 -23
- package/dest/avm/opcodes/instruction.d.ts +24 -2
- package/dest/avm/opcodes/instruction.d.ts.map +1 -1
- package/dest/avm/opcodes/instruction.js +45 -2
- package/dest/avm/opcodes/memory.d.ts +3 -0
- package/dest/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/avm/opcodes/memory.js +8 -1
- package/dest/avm/temporary_executor_migration.js +3 -3
- 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 +5 -5
- package/dest/client/execution_result.d.ts +5 -5
- package/dest/client/execution_result.d.ts.map +1 -1
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +4 -5
- package/dest/client/unconstrained_execution.js +2 -2
- package/dest/client/view_data_oracle.d.ts +8 -5
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +9 -6
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -1
- package/dest/public/db.d.ts +7 -5
- package/dest/public/db.d.ts.map +1 -1
- package/dest/public/execution.d.ts +3 -3
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +6 -4
- package/dest/public/public_execution_context.d.ts +9 -6
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +11 -8
- package/dest/simulator/acvm_native.d.ts +20 -0
- package/dest/simulator/acvm_native.d.ts.map +1 -0
- package/dest/simulator/acvm_native.js +96 -0
- package/dest/simulator/acvm_wasm.d.ts +7 -0
- package/dest/simulator/acvm_wasm.d.ts.map +1 -0
- package/dest/simulator/acvm_wasm.js +23 -0
- package/dest/simulator/index.d.ts +4 -0
- package/dest/simulator/index.d.ts.map +1 -0
- package/dest/simulator/index.js +4 -0
- package/dest/simulator/simulation_provider.d.ts +9 -0
- package/dest/simulator/simulation_provider.d.ts.map +1 -0
- package/dest/simulator/simulation_provider.js +2 -0
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +4 -5
- package/dest/utils.js +2 -2
- package/package.json +6 -5
- package/src/acvm/oracle/oracle.ts +10 -2
- package/src/acvm/oracle/typed_oracle.ts +5 -1
- package/src/avm/avm_execution_environment.ts +17 -1
- package/src/avm/avm_gas_cost.ts +132 -0
- package/src/avm/avm_machine_state.ts +34 -1
- package/src/avm/avm_memory_types.ts +1 -0
- package/src/avm/avm_simulator.ts +1 -2
- package/src/avm/errors.ts +8 -0
- package/src/avm/fixtures/index.ts +21 -5
- package/src/avm/journal/journal.ts +10 -1
- package/src/avm/opcodes/addressing_mode.ts +1 -1
- package/src/avm/opcodes/arithmetic.ts +34 -47
- package/src/avm/opcodes/hashing.ts +27 -20
- package/src/avm/opcodes/instruction.ts +49 -2
- package/src/avm/opcodes/memory.ts +9 -0
- package/src/avm/temporary_executor_migration.ts +2 -2
- package/src/client/client_execution_context.ts +7 -5
- package/src/client/execution_result.ts +5 -5
- package/src/client/private_execution.ts +3 -4
- package/src/client/unconstrained_execution.ts +1 -1
- package/src/client/view_data_oracle.ts +8 -5
- package/src/index.ts +1 -0
- package/src/public/db.ts +11 -5
- package/src/public/execution.ts +3 -3
- package/src/public/executor.ts +5 -3
- package/src/public/public_execution_context.ts +10 -7
- package/src/simulator/acvm_native.ts +112 -0
- package/src/simulator/acvm_wasm.ts +31 -0
- package/src/simulator/index.ts +3 -0
- package/src/simulator/simulation_provider.ts +10 -0
- package/src/test/utils.ts +2 -4
- package/src/utils.ts +1 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthWitness,
|
|
3
3
|
AztecNode,
|
|
4
|
-
|
|
4
|
+
EncryptedFunctionL2Logs,
|
|
5
|
+
EncryptedL2Log,
|
|
5
6
|
L1NotePayload,
|
|
6
7
|
Note,
|
|
7
8
|
NoteStatus,
|
|
8
9
|
TaggedNote,
|
|
10
|
+
UnencryptedFunctionL2Logs,
|
|
9
11
|
UnencryptedL2Log,
|
|
10
12
|
} from '@aztec/circuit-types';
|
|
11
13
|
import {
|
|
@@ -56,7 +58,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
56
58
|
* They should act as references for the read requests output by an app circuit via public inputs.
|
|
57
59
|
*/
|
|
58
60
|
private gotNotes: Map<bigint, bigint> = new Map();
|
|
59
|
-
private encryptedLogs:
|
|
61
|
+
private encryptedLogs: EncryptedL2Log[] = [];
|
|
60
62
|
private unencryptedLogs: UnencryptedL2Log[] = [];
|
|
61
63
|
private nestedExecutions: ExecutionResult[] = [];
|
|
62
64
|
private enqueuedPublicFunctionCalls: PublicCallRequest[] = [];
|
|
@@ -144,14 +146,14 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
144
146
|
* Return the encrypted logs emitted during this execution.
|
|
145
147
|
*/
|
|
146
148
|
public getEncryptedLogs() {
|
|
147
|
-
return new
|
|
149
|
+
return new EncryptedFunctionL2Logs(this.encryptedLogs);
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
/**
|
|
151
153
|
* Return the encrypted logs emitted during this execution.
|
|
152
154
|
*/
|
|
153
155
|
public getUnencryptedLogs() {
|
|
154
|
-
return new
|
|
156
|
+
return new UnencryptedFunctionL2Logs(this.unencryptedLogs);
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
/**
|
|
@@ -304,7 +306,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
304
306
|
const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
|
|
305
307
|
const taggedNote = new TaggedNote(l1NotePayload);
|
|
306
308
|
const encryptedNote = taggedNote.toEncryptedBuffer(publicKey, this.curve);
|
|
307
|
-
this.encryptedLogs.push(encryptedNote);
|
|
309
|
+
this.encryptedLogs.push(new EncryptedL2Log(encryptedNote));
|
|
308
310
|
}
|
|
309
311
|
|
|
310
312
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EncryptedFunctionL2Logs, Note, UnencryptedFunctionL2Logs } from '@aztec/circuit-types';
|
|
2
2
|
import { NoteHashReadRequestMembershipWitness, PrivateCallStackItem, PublicCallRequest } from '@aztec/circuits.js';
|
|
3
3
|
import { DecodedReturn } from '@aztec/foundation/abi';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -46,12 +46,12 @@ export interface ExecutionResult {
|
|
|
46
46
|
* Encrypted logs emitted during execution of this function call.
|
|
47
47
|
* Note: These are preimages to `encryptedLogsHash`.
|
|
48
48
|
*/
|
|
49
|
-
encryptedLogs:
|
|
49
|
+
encryptedLogs: EncryptedFunctionL2Logs;
|
|
50
50
|
/**
|
|
51
51
|
* Unencrypted logs emitted during execution of this function call.
|
|
52
52
|
* Note: These are preimages to `unencryptedLogsHash`.
|
|
53
53
|
*/
|
|
54
|
-
unencryptedLogs:
|
|
54
|
+
unencryptedLogs: UnencryptedFunctionL2Logs;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -59,7 +59,7 @@ export interface ExecutionResult {
|
|
|
59
59
|
* @param execResult - The topmost execution result.
|
|
60
60
|
* @returns All encrypted logs.
|
|
61
61
|
*/
|
|
62
|
-
export function collectEncryptedLogs(execResult: ExecutionResult):
|
|
62
|
+
export function collectEncryptedLogs(execResult: ExecutionResult): EncryptedFunctionL2Logs[] {
|
|
63
63
|
// without the .reverse(), the logs will be in a queue like fashion which is wrong as the kernel processes it like a stack.
|
|
64
64
|
return [execResult.encryptedLogs, ...[...execResult.nestedExecutions].reverse().flatMap(collectEncryptedLogs)];
|
|
65
65
|
}
|
|
@@ -69,7 +69,7 @@ export function collectEncryptedLogs(execResult: ExecutionResult): FunctionL2Log
|
|
|
69
69
|
* @param execResult - The topmost execution result.
|
|
70
70
|
* @returns All unencrypted logs.
|
|
71
71
|
*/
|
|
72
|
-
export function collectUnencryptedLogs(execResult: ExecutionResult):
|
|
72
|
+
export function collectUnencryptedLogs(execResult: ExecutionResult): UnencryptedFunctionL2Logs[] {
|
|
73
73
|
// without the .reverse(), the logs will be in a queue like fashion which is wrong as the kernel processes it like a stack.
|
|
74
74
|
return [execResult.unencryptedLogs, ...[...execResult.nestedExecutions].reverse().flatMap(collectUnencryptedLogs)];
|
|
75
75
|
}
|
|
@@ -3,7 +3,6 @@ import { FunctionArtifactWithDebugMetadata, decodeReturnValues } from '@aztec/fo
|
|
|
3
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
5
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
6
|
-
import { to2Fields } from '@aztec/foundation/serialize';
|
|
7
6
|
|
|
8
7
|
import { extractReturnWitness } from '../acvm/deserialize.js';
|
|
9
8
|
import { Oracle, acvm, extractCallStack } from '../acvm/index.js';
|
|
@@ -24,7 +23,7 @@ export async function executePrivateFunction(
|
|
|
24
23
|
): Promise<ExecutionResult> {
|
|
25
24
|
const functionSelector = functionData.selector;
|
|
26
25
|
log(`Executing external function ${contractAddress}:${functionSelector}(${artifact.name})`);
|
|
27
|
-
const acir =
|
|
26
|
+
const acir = artifact.bytecode;
|
|
28
27
|
const initialWitness = context.getInitialWitness(artifact);
|
|
29
28
|
const acvmCallback = new Oracle(context);
|
|
30
29
|
const { partialWitness } = await acvm(await AcirSimulator.getSolver(), acir, initialWitness, acvmCallback).catch(
|
|
@@ -47,9 +46,9 @@ export async function executePrivateFunction(
|
|
|
47
46
|
const encryptedLogs = context.getEncryptedLogs();
|
|
48
47
|
const unencryptedLogs = context.getUnencryptedLogs();
|
|
49
48
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) --> set this in Noir
|
|
50
|
-
publicInputs.encryptedLogsHash =
|
|
49
|
+
publicInputs.encryptedLogsHash = Fr.fromBuffer(encryptedLogs.hash());
|
|
51
50
|
publicInputs.encryptedLogPreimagesLength = new Fr(encryptedLogs.getSerializedLength());
|
|
52
|
-
publicInputs.unencryptedLogsHash =
|
|
51
|
+
publicInputs.unencryptedLogsHash = Fr.fromBuffer(unencryptedLogs.hash());
|
|
53
52
|
publicInputs.unencryptedLogPreimagesLength = new Fr(unencryptedLogs.getSerializedLength());
|
|
54
53
|
|
|
55
54
|
const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs);
|
|
@@ -25,7 +25,7 @@ export async function executeUnconstrainedFunction(
|
|
|
25
25
|
const functionSelector = functionData.selector;
|
|
26
26
|
log(`Executing unconstrained function ${contractAddress}:${functionSelector}`);
|
|
27
27
|
|
|
28
|
-
const acir =
|
|
28
|
+
const acir = artifact.bytecode;
|
|
29
29
|
const initialWitness = toACVMWitness(0, args);
|
|
30
30
|
const { partialWitness } = await acvm(
|
|
31
31
|
await AcirSimulator.getSolver(),
|
|
@@ -225,12 +225,15 @@ export class ViewDataOracle extends TypedOracle {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
/**
|
|
228
|
-
* Fetches
|
|
229
|
-
* @param
|
|
230
|
-
* @
|
|
228
|
+
* Fetches a message from the db, given its key.
|
|
229
|
+
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
230
|
+
* @param messageHash - Hash of the message.
|
|
231
|
+
* @param secret - Secret used to compute a nullifier.
|
|
232
|
+
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
|
|
233
|
+
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
|
|
231
234
|
*/
|
|
232
|
-
public async getL1ToL2MembershipWitness(
|
|
233
|
-
return await this.db.getL1ToL2MembershipWitness(
|
|
235
|
+
public async getL1ToL2MembershipWitness(contractAddress: AztecAddress, messageHash: Fr, secret: Fr) {
|
|
236
|
+
return await this.db.getL1ToL2MembershipWitness(contractAddress, messageHash, secret);
|
|
234
237
|
}
|
|
235
238
|
|
|
236
239
|
/**
|
package/src/index.ts
CHANGED
package/src/public/db.ts
CHANGED
|
@@ -79,12 +79,18 @@ export interface PublicContractsDB {
|
|
|
79
79
|
/** Database interface for providing access to commitment tree, l1 to l2 message tree, and nullifier tree. */
|
|
80
80
|
export interface CommitmentsDB {
|
|
81
81
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* @param
|
|
85
|
-
* @
|
|
82
|
+
* Fetches a message from the db, given its key.
|
|
83
|
+
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
84
|
+
* @param messageHash - Hash of the message.
|
|
85
|
+
* @param secret - Secret used to compute a nullifier.
|
|
86
|
+
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
|
|
87
|
+
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
|
|
86
88
|
*/
|
|
87
|
-
getL1ToL2MembershipWitness(
|
|
89
|
+
getL1ToL2MembershipWitness(
|
|
90
|
+
contractAddress: AztecAddress,
|
|
91
|
+
messageHash: Fr,
|
|
92
|
+
secret: Fr,
|
|
93
|
+
): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;
|
|
88
94
|
|
|
89
95
|
/**
|
|
90
96
|
* Gets the index of a commitment in the note hash tree.
|
package/src/public/execution.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SimulationError, UnencryptedFunctionL2Logs } from '@aztec/circuit-types';
|
|
2
2
|
import {
|
|
3
3
|
AztecAddress,
|
|
4
4
|
ContractStorageRead,
|
|
@@ -46,7 +46,7 @@ export interface PublicExecutionResult {
|
|
|
46
46
|
* Unencrypted logs emitted during execution of this function call.
|
|
47
47
|
* Note: These are preimages to `unencryptedLogsHash`.
|
|
48
48
|
*/
|
|
49
|
-
unencryptedLogs:
|
|
49
|
+
unencryptedLogs: UnencryptedFunctionL2Logs;
|
|
50
50
|
/**
|
|
51
51
|
* Whether the execution reverted.
|
|
52
52
|
*/
|
|
@@ -154,7 +154,7 @@ export function checkValidStaticCall(
|
|
|
154
154
|
newNullifiers: SideEffectLinkedToNoteHash[],
|
|
155
155
|
contractStorageUpdateRequests: ContractStorageUpdateRequest[],
|
|
156
156
|
newL2ToL1Messages: L2ToL1Message[],
|
|
157
|
-
unencryptedLogs:
|
|
157
|
+
unencryptedLogs: UnencryptedFunctionL2Logs,
|
|
158
158
|
) {
|
|
159
159
|
if (
|
|
160
160
|
contractStorageUpdateRequests.length > 0 ||
|
package/src/public/executor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UnencryptedFunctionL2Logs } from '@aztec/circuit-types';
|
|
2
2
|
import { Fr, GlobalVariables, Header, PublicCircuitPublicInputs } from '@aztec/circuits.js';
|
|
3
3
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
4
|
|
|
@@ -92,7 +92,7 @@ export async function executePublicFunction(
|
|
|
92
92
|
contractStorageReads: [],
|
|
93
93
|
contractStorageUpdateRequests: [],
|
|
94
94
|
nestedExecutions: [],
|
|
95
|
-
unencryptedLogs:
|
|
95
|
+
unencryptedLogs: UnencryptedFunctionL2Logs.empty(),
|
|
96
96
|
reverted,
|
|
97
97
|
revertReason,
|
|
98
98
|
};
|
|
@@ -229,13 +229,15 @@ export class PublicExecutor {
|
|
|
229
229
|
const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb);
|
|
230
230
|
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
|
|
231
231
|
const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
|
|
232
|
-
|
|
232
|
+
// TODO(@spalladino) Load initial gas from the public execution request
|
|
233
|
+
const machineState = new AvmMachineState(100_000, 100_000, 100_000);
|
|
233
234
|
|
|
234
235
|
const context = new AvmContext(worldStateJournal, executionEnv, machineState);
|
|
235
236
|
const simulator = new AvmSimulator(context);
|
|
236
237
|
|
|
237
238
|
const result = await simulator.execute();
|
|
238
239
|
const newWorldState = context.persistableState.flush();
|
|
240
|
+
// TODO(@spalladino) Read gas left from machineState and return it
|
|
239
241
|
return temporaryConvertAvmResults(execution, newWorldState, result);
|
|
240
242
|
}
|
|
241
243
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NullifierMembershipWitness, UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types';
|
|
2
2
|
import { CallContext, FunctionData, FunctionSelector, GlobalVariables, Header } from '@aztec/circuits.js';
|
|
3
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -72,7 +72,7 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
72
72
|
* Return the encrypted logs emitted during this execution.
|
|
73
73
|
*/
|
|
74
74
|
public getUnencryptedLogs() {
|
|
75
|
-
return new
|
|
75
|
+
return new UnencryptedFunctionL2Logs(this.unencryptedLogs);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
@@ -92,12 +92,15 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
|
-
* Fetches
|
|
96
|
-
* @param
|
|
97
|
-
* @
|
|
95
|
+
* Fetches a message from the db, given its key.
|
|
96
|
+
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
97
|
+
* @param messageHash - Hash of the message.
|
|
98
|
+
* @param secret - Secret used to compute a nullifier.
|
|
99
|
+
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
|
|
100
|
+
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
|
|
98
101
|
*/
|
|
99
|
-
public async getL1ToL2MembershipWitness(
|
|
100
|
-
return await this.commitmentsDb.getL1ToL2MembershipWitness(
|
|
102
|
+
public async getL1ToL2MembershipWitness(contractAddress: AztecAddress, messageHash: Fr, secret: Fr) {
|
|
103
|
+
return await this.commitmentsDb.getL1ToL2MembershipWitness(contractAddress, messageHash, secret);
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
/**
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { randomBytes } from '@aztec/foundation/crypto';
|
|
2
|
+
import { NoirCompiledCircuit } from '@aztec/types/noir';
|
|
3
|
+
|
|
4
|
+
import { WitnessMap } from '@noir-lang/types';
|
|
5
|
+
import * as proc from 'child_process';
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
|
|
8
|
+
import { SimulationProvider } from './simulation_provider.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parses a TOML format witness map string into a Map structure
|
|
12
|
+
* @param outputString - The witness map in TOML format
|
|
13
|
+
* @returns The parsed witness map
|
|
14
|
+
*/
|
|
15
|
+
function parseIntoWitnessMap(outputString: string) {
|
|
16
|
+
const lines = outputString.split('\n');
|
|
17
|
+
return new Map<number, string>(
|
|
18
|
+
lines
|
|
19
|
+
.filter((line: string) => line.length)
|
|
20
|
+
.map((line: string) => {
|
|
21
|
+
const pair = line.replaceAll(' ', '').split('=');
|
|
22
|
+
return [Number(pair[0]), pair[1].replaceAll('"', '')];
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param inputWitness - The circuit's input witness
|
|
30
|
+
* @param bytecode - The circuit bytecode
|
|
31
|
+
* @param workingDirectory - A directory to use for temporary files by the ACVM
|
|
32
|
+
* @param pathToAcvm - The path to the ACVm binary
|
|
33
|
+
* @returns The completed partial witness outputted from the circuit
|
|
34
|
+
*/
|
|
35
|
+
export async function executeNativeCircuit(
|
|
36
|
+
inputWitness: WitnessMap,
|
|
37
|
+
bytecode: Buffer,
|
|
38
|
+
workingDirectory: string,
|
|
39
|
+
pathToAcvm: string,
|
|
40
|
+
) {
|
|
41
|
+
const bytecodeFilename = 'bytecode';
|
|
42
|
+
const witnessFilename = 'input_witness.toml';
|
|
43
|
+
|
|
44
|
+
// convert the witness map to TOML format
|
|
45
|
+
let witnessMap = '';
|
|
46
|
+
inputWitness.forEach((value: string, key: number) => {
|
|
47
|
+
witnessMap = witnessMap.concat(`${key} = '${value}'\n`);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// In case the directory is still around from some time previously, remove it
|
|
51
|
+
await fs.rm(workingDirectory, { recursive: true, force: true });
|
|
52
|
+
// Create the new working directory
|
|
53
|
+
await fs.mkdir(workingDirectory, { recursive: true });
|
|
54
|
+
// Write the bytecode and input witness to the working directory
|
|
55
|
+
await fs.writeFile(`${workingDirectory}/${bytecodeFilename}`, bytecode);
|
|
56
|
+
await fs.writeFile(`${workingDirectory}/${witnessFilename}`, witnessMap);
|
|
57
|
+
|
|
58
|
+
// Execute the ACVM using the given args
|
|
59
|
+
const args = [
|
|
60
|
+
`execute`,
|
|
61
|
+
`--working-directory`,
|
|
62
|
+
`${workingDirectory}`,
|
|
63
|
+
`--bytecode`,
|
|
64
|
+
`${bytecodeFilename}`,
|
|
65
|
+
`--input-witness`,
|
|
66
|
+
`${witnessFilename}`,
|
|
67
|
+
`--print`,
|
|
68
|
+
];
|
|
69
|
+
const processPromise = new Promise<string>((resolve, reject) => {
|
|
70
|
+
let outputWitness = Buffer.alloc(0);
|
|
71
|
+
let errorBuffer = Buffer.alloc(0);
|
|
72
|
+
const acvm = proc.spawn(pathToAcvm, args);
|
|
73
|
+
acvm.stdout.on('data', data => {
|
|
74
|
+
outputWitness = Buffer.concat([outputWitness, data]);
|
|
75
|
+
});
|
|
76
|
+
acvm.stderr.on('data', data => {
|
|
77
|
+
errorBuffer = Buffer.concat([errorBuffer, data]);
|
|
78
|
+
});
|
|
79
|
+
acvm.on('close', code => {
|
|
80
|
+
if (code === 0) {
|
|
81
|
+
resolve(outputWitness.toString('utf-8'));
|
|
82
|
+
} else {
|
|
83
|
+
reject(errorBuffer.toString('utf-8'));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const output = await processPromise;
|
|
90
|
+
return parseIntoWitnessMap(output);
|
|
91
|
+
} finally {
|
|
92
|
+
// Clean up the working directory before we leave
|
|
93
|
+
await fs.rm(workingDirectory, { recursive: true, force: true });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export class NativeACVMSimulator implements SimulationProvider {
|
|
98
|
+
constructor(private workingDirectory: string, private pathToAcvm: string) {}
|
|
99
|
+
async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap> {
|
|
100
|
+
// Execute the circuit on those initial witness values
|
|
101
|
+
|
|
102
|
+
// Decode the bytecode from base64 since the acvm does not know about base64 encoding
|
|
103
|
+
const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
|
|
104
|
+
|
|
105
|
+
// Provide a unique working directory so we don't get clashes with parallel executions
|
|
106
|
+
const directory = `${this.workingDirectory}/${randomBytes(32).toString('hex')}`;
|
|
107
|
+
// Execute the circuit
|
|
108
|
+
const _witnessMap = await executeNativeCircuit(input, decodedBytecode, directory, this.pathToAcvm);
|
|
109
|
+
|
|
110
|
+
return _witnessMap;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NoirCompiledCircuit } from '@aztec/types/noir';
|
|
2
|
+
|
|
3
|
+
import { WasmBlackBoxFunctionSolver, createBlackBoxSolver, executeCircuitWithBlackBoxSolver } from '@noir-lang/acvm_js';
|
|
4
|
+
import { WitnessMap } from '@noir-lang/types';
|
|
5
|
+
|
|
6
|
+
import { SimulationProvider } from './simulation_provider.js';
|
|
7
|
+
|
|
8
|
+
let solver: Promise<WasmBlackBoxFunctionSolver>;
|
|
9
|
+
|
|
10
|
+
const getSolver = (): Promise<WasmBlackBoxFunctionSolver> => {
|
|
11
|
+
if (!solver) {
|
|
12
|
+
solver = createBlackBoxSolver();
|
|
13
|
+
}
|
|
14
|
+
return solver;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export class WASMSimulator implements SimulationProvider {
|
|
18
|
+
async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap> {
|
|
19
|
+
// Execute the circuit on those initial witness values
|
|
20
|
+
//
|
|
21
|
+
// Decode the bytecode from base64 since the acvm does not know about base64 encoding
|
|
22
|
+
const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
|
|
23
|
+
//
|
|
24
|
+
// Execute the circuit
|
|
25
|
+
const _witnessMap = await executeCircuitWithBlackBoxSolver(await getSolver(), decodedBytecode, input, () => {
|
|
26
|
+
throw Error('unexpected oracle during execution');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return _witnessMap;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NoirCompiledCircuit } from '@aztec/types/noir';
|
|
2
|
+
|
|
3
|
+
import { WitnessMap } from '@noir-lang/types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Low level simulation interface
|
|
7
|
+
*/
|
|
8
|
+
export interface SimulationProvider {
|
|
9
|
+
simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap>;
|
|
10
|
+
}
|
package/src/test/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { L1Actor, L1ToL2Message, L2Actor } from '@aztec/circuit-types';
|
|
2
2
|
import { AztecAddress, EthAddress, Fr } from '@aztec/circuits.js';
|
|
3
3
|
import { computeMessageSecretHash } from '@aztec/circuits.js/hash';
|
|
4
|
-
import {
|
|
4
|
+
import { sha256ToField } from '@aztec/foundation/crypto';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Test utility function to craft an L1 to L2 message.
|
|
@@ -20,9 +20,7 @@ export const buildL1ToL2Message = (
|
|
|
20
20
|
// Write the selector into a buffer.
|
|
21
21
|
const selectorBuf = Buffer.from(selector, 'hex');
|
|
22
22
|
|
|
23
|
-
const
|
|
24
|
-
const content = Fr.fromBufferReduce(sha256(contentBuf));
|
|
25
|
-
|
|
23
|
+
const content = sha256ToField([selectorBuf, ...contentPreimage]);
|
|
26
24
|
const secretHash = computeMessageSecretHash(secret);
|
|
27
25
|
|
|
28
26
|
// Eventually the kernel will need to prove the kernel portal pair exists within the contract tree,
|
package/src/utils.ts
CHANGED