@aztec/simulator 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/acvm/acvm.d.ts +1 -1
- package/dest/acvm/acvm.d.ts.map +1 -1
- package/dest/acvm/acvm.js +2 -2
- package/dest/acvm/oracle/oracle.d.ts +5 -4
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +19 -8
- package/dest/acvm/oracle/typed_oracle.d.ts +3 -2
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +6 -3
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +2 -1
- package/dest/avm/avm_memory_types.d.ts +1 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +3 -1
- package/dest/avm/journal/journal.d.ts +20 -1
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +69 -9
- package/dest/avm/journal/nullifiers.d.ts +3 -1
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +14 -6
- package/dest/avm/journal/public_storage.d.ts +10 -1
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.js +17 -2
- package/dest/avm/journal/trace.d.ts +1 -4
- package/dest/avm/journal/trace.d.ts.map +1 -1
- package/dest/avm/journal/trace.js +4 -5
- package/dest/avm/journal/trace_types.d.ts +1 -0
- package/dest/avm/journal/trace_types.d.ts.map +1 -1
- package/dest/avm/journal/trace_types.js +1 -1
- package/dest/avm/opcodes/bitwise.d.ts +4 -1
- package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
- package/dest/avm/opcodes/bitwise.js +14 -2
- package/dest/avm/opcodes/environment_getters.d.ts +5 -0
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +8 -1
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +14 -13
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +3 -2
- package/dest/avm/serialization/instruction_serialization.d.ts +39 -38
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +40 -39
- package/dest/client/client_execution_context.d.ts +31 -18
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +48 -31
- package/dest/client/db_oracle.d.ts +3 -3
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/execution_result.d.ts +19 -15
- package/dest/client/execution_result.d.ts.map +1 -1
- package/dest/client/execution_result.js +45 -12
- package/dest/client/logs_cache.d.ts +33 -0
- package/dest/client/logs_cache.d.ts.map +1 -0
- package/dest/client/logs_cache.js +59 -0
- package/dest/client/private_execution.d.ts +2 -2
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +3 -7
- package/dest/client/simulator.d.ts +3 -3
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +3 -2
- package/dest/client/unconstrained_execution.d.ts +2 -2
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +1 -1
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +3 -1
- package/dest/public/abstract_phase_manager.d.ts +2 -0
- package/dest/public/abstract_phase_manager.d.ts.map +1 -1
- package/dest/public/abstract_phase_manager.js +13 -6
- package/dest/public/execution.d.ts +9 -0
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor.d.ts +2 -2
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +34 -14
- package/dest/public/public_execution_context.d.ts +10 -4
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +19 -6
- package/dest/public/tail_phase_manager.d.ts +0 -1
- package/dest/public/tail_phase_manager.d.ts.map +1 -1
- package/dest/public/tail_phase_manager.js +3 -26
- package/dest/public/transitional_adaptors.d.ts +4 -17
- package/dest/public/transitional_adaptors.d.ts.map +1 -1
- package/dest/public/transitional_adaptors.js +27 -119
- package/package.json +8 -8
- package/src/acvm/acvm.ts +2 -2
- package/src/acvm/oracle/oracle.ts +39 -9
- package/src/acvm/oracle/typed_oracle.ts +7 -2
- package/src/avm/avm_gas.ts +1 -0
- package/src/avm/avm_memory_types.ts +1 -1
- package/src/avm/avm_simulator.ts +2 -0
- package/src/avm/journal/journal.ts +133 -9
- package/src/avm/journal/nullifiers.ts +19 -8
- package/src/avm/journal/public_storage.ts +23 -2
- package/src/avm/journal/trace.ts +3 -4
- package/src/avm/journal/trace_types.ts +1 -0
- package/src/avm/opcodes/bitwise.ts +18 -7
- package/src/avm/opcodes/environment_getters.ts +9 -0
- package/src/avm/opcodes/external_calls.ts +21 -16
- package/src/avm/serialization/bytecode_serialization.ts +2 -0
- package/src/avm/serialization/instruction_serialization.ts +1 -0
- package/src/client/client_execution_context.ts +55 -31
- package/src/client/db_oracle.ts +3 -9
- package/src/client/execution_result.ts +55 -24
- package/src/client/logs_cache.ts +65 -0
- package/src/client/private_execution.ts +4 -10
- package/src/client/simulator.ts +6 -4
- package/src/client/unconstrained_execution.ts +2 -2
- package/src/mocks/fixtures.ts +2 -0
- package/src/public/abstract_phase_manager.ts +13 -5
- package/src/public/execution.ts +9 -0
- package/src/public/executor.ts +47 -10
- package/src/public/public_execution_context.ts +18 -4
- package/src/public/tail_phase_manager.ts +2 -34
- package/src/public/transitional_adaptors.ts +39 -178
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { type EncryptedFunctionL2Logs, type Note, type UnencryptedFunctionL2Logs } from '@aztec/circuit-types';
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
|
|
2
|
+
EncryptedFunctionL2Logs,
|
|
3
|
+
type EncryptedL2Log,
|
|
4
|
+
type Note,
|
|
5
|
+
UnencryptedFunctionL2Logs,
|
|
6
|
+
type UnencryptedL2Log,
|
|
7
|
+
} from '@aztec/circuit-types';
|
|
8
|
+
import { type IsEmpty, type PrivateCallStackItem, type PublicCallRequest, sortByCounter } from '@aztec/circuits.js';
|
|
7
9
|
import { type Fr } from '@aztec/foundation/fields';
|
|
8
10
|
|
|
9
11
|
import { type ACVMField } from '../acvm/index.js';
|
|
@@ -20,9 +22,12 @@ export interface NoteAndSlot {
|
|
|
20
22
|
noteTypeId: Fr;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
export class CountedLog<TLog extends UnencryptedL2Log | EncryptedL2Log> implements IsEmpty {
|
|
26
|
+
constructor(public log: TLog, public counter: number) {}
|
|
27
|
+
|
|
28
|
+
isEmpty(): boolean {
|
|
29
|
+
return !this.log.data.length && !this.counter;
|
|
30
|
+
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
/**
|
|
@@ -39,11 +44,12 @@ export interface ExecutionResult {
|
|
|
39
44
|
// Needed for the verifier (kernel)
|
|
40
45
|
/** The call stack item. */
|
|
41
46
|
callStackItem: PrivateCallStackItem;
|
|
42
|
-
/**
|
|
43
|
-
|
|
47
|
+
/** Mapping of note hash to its index in the note hash tree. Used for building hints for note hash read requests. */
|
|
48
|
+
noteHashLeafIndexMap: Map<bigint, bigint>;
|
|
44
49
|
/** The notes created in the executed function. */
|
|
45
50
|
newNotes: NoteAndSlot[];
|
|
46
|
-
|
|
51
|
+
/** Mapping of note hash counter to the counter of its nullifier. */
|
|
52
|
+
nullifiedNoteHashCounters: Map<number, number>;
|
|
47
53
|
/** The raw return values of the executed function. */
|
|
48
54
|
returnValues: Fr[];
|
|
49
55
|
/** The nested executions. */
|
|
@@ -54,19 +60,24 @@ export interface ExecutionResult {
|
|
|
54
60
|
* Encrypted logs emitted during execution of this function call.
|
|
55
61
|
* Note: These are preimages to `encryptedLogsHashes`.
|
|
56
62
|
*/
|
|
57
|
-
encryptedLogs:
|
|
63
|
+
encryptedLogs: CountedLog<EncryptedL2Log>[];
|
|
58
64
|
/**
|
|
59
65
|
* Unencrypted logs emitted during execution of this function call.
|
|
60
66
|
* Note: These are preimages to `unencryptedLogsHashes`.
|
|
61
67
|
*/
|
|
62
|
-
unencryptedLogs:
|
|
68
|
+
unencryptedLogs: CountedLog<UnencryptedL2Log>[];
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
export function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
export function collectNoteHashLeafIndexMap(execResult: ExecutionResult, accum: Map<bigint, bigint> = new Map()) {
|
|
72
|
+
execResult.noteHashLeafIndexMap.forEach((value, key) => accum.set(key, value));
|
|
73
|
+
execResult.nestedExecutions.forEach(nested => collectNoteHashLeafIndexMap(nested, accum));
|
|
74
|
+
return accum;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function collectNullifiedNoteHashCounters(execResult: ExecutionResult, accum: Map<number, number> = new Map()) {
|
|
78
|
+
execResult.nullifiedNoteHashCounters.forEach((value, key) => accum.set(key, value));
|
|
79
|
+
execResult.nestedExecutions.forEach(nested => collectNullifiedNoteHashCounters(nested, accum));
|
|
80
|
+
return accum;
|
|
70
81
|
}
|
|
71
82
|
|
|
72
83
|
/**
|
|
@@ -74,9 +85,19 @@ export function collectNullifiedNoteHashCounters(execResult: ExecutionResult): N
|
|
|
74
85
|
* @param execResult - The topmost execution result.
|
|
75
86
|
* @returns All encrypted logs.
|
|
76
87
|
*/
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
function collectEncryptedLogs(execResult: ExecutionResult): CountedLog<EncryptedL2Log>[] {
|
|
89
|
+
return [execResult.encryptedLogs, ...[...execResult.nestedExecutions].flatMap(collectEncryptedLogs)].flat();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Collect all encrypted logs across all nested executions and sorts by counter.
|
|
94
|
+
* @param execResult - The topmost execution result.
|
|
95
|
+
* @returns All encrypted logs.
|
|
96
|
+
*/
|
|
97
|
+
export function collectSortedEncryptedLogs(execResult: ExecutionResult): EncryptedFunctionL2Logs {
|
|
98
|
+
const allLogs = collectEncryptedLogs(execResult);
|
|
99
|
+
const sortedLogs = sortByCounter(allLogs);
|
|
100
|
+
return new EncryptedFunctionL2Logs(sortedLogs.map(l => l.log));
|
|
80
101
|
}
|
|
81
102
|
|
|
82
103
|
/**
|
|
@@ -84,9 +105,19 @@ export function collectEncryptedLogs(execResult: ExecutionResult): EncryptedFunc
|
|
|
84
105
|
* @param execResult - The topmost execution result.
|
|
85
106
|
* @returns All unencrypted logs.
|
|
86
107
|
*/
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
108
|
+
function collectUnencryptedLogs(execResult: ExecutionResult): CountedLog<UnencryptedL2Log>[] {
|
|
109
|
+
return [execResult.unencryptedLogs, ...[...execResult.nestedExecutions].flatMap(collectUnencryptedLogs)].flat();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Collect all unencrypted logs across all nested executions and sorts by counter.
|
|
114
|
+
* @param execResult - The topmost execution result.
|
|
115
|
+
* @returns All unencrypted logs.
|
|
116
|
+
*/
|
|
117
|
+
export function collectSortedUnencryptedLogs(execResult: ExecutionResult): UnencryptedFunctionL2Logs {
|
|
118
|
+
const allLogs = collectUnencryptedLogs(execResult);
|
|
119
|
+
const sortedLogs = sortByCounter(allLogs);
|
|
120
|
+
return new UnencryptedFunctionL2Logs(sortedLogs.map(l => l.log));
|
|
90
121
|
}
|
|
91
122
|
|
|
92
123
|
/**
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type EncryptedL2Log, type UnencryptedL2Log } from '@aztec/circuit-types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Log data that's accessible by all the function calls in an execution.
|
|
5
|
+
* This class exists to:
|
|
6
|
+
* 1. Keep track of logs emitted through nested calls in the correct order.
|
|
7
|
+
* 2. TODO(1641): Remove encrypted logs based on notes nullified in the same scope.
|
|
8
|
+
*/
|
|
9
|
+
export class LogsCache {
|
|
10
|
+
/**
|
|
11
|
+
* Logs notes created in this transaction.
|
|
12
|
+
*/
|
|
13
|
+
private encryptedLogs: EncryptedL2Log[] = [];
|
|
14
|
+
private unencryptedLogs: UnencryptedL2Log[] = [];
|
|
15
|
+
|
|
16
|
+
// TODO Separate encrypted logs linked to note hashes and arbitrary logs:
|
|
17
|
+
|
|
18
|
+
// Maps from note hash to encrypted log - useful for removing transient logs
|
|
19
|
+
// private encryptedLogsLinkedToNotes: Map<bigint, EncryptedL2Log> = new Map();
|
|
20
|
+
|
|
21
|
+
// /**
|
|
22
|
+
// * Remove the encrypted log for a nullified note.
|
|
23
|
+
// * This fn should only be called if the note's innerNoteHash != 0.
|
|
24
|
+
// * @param noteHashCounter - Side effect counter of the note.
|
|
25
|
+
// */
|
|
26
|
+
// public nullifyNote(noteHashCounter: Fr) {
|
|
27
|
+
// // Find and remove the matching new note if the emitted innerNoteHash is not empty.
|
|
28
|
+
// const log = this.encryptedLogsLinkedToNotes.get(noteHashCounter.toBigInt()) ?? false;
|
|
29
|
+
// // TODO: throw here? Will the log always be here?
|
|
30
|
+
// if (!log) {
|
|
31
|
+
// throw new Error('Attempt to remove a pending note log that does not exist.');
|
|
32
|
+
// }
|
|
33
|
+
// this.encryptedLogsLinkedToNotes.delete(noteHashCounter.toBigInt());
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Add a new encrypted log to cache.
|
|
38
|
+
* @param log - New log created during execution.
|
|
39
|
+
*/
|
|
40
|
+
public addEncryptedLog(log: EncryptedL2Log) {
|
|
41
|
+
this.encryptedLogs.push(log);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Add a new unencrypted log to cache.
|
|
46
|
+
* @param log - New log created during execution.
|
|
47
|
+
*/
|
|
48
|
+
public addUnencryptedLog(log: UnencryptedL2Log) {
|
|
49
|
+
this.unencryptedLogs.push(log);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Return the encrypted logs.
|
|
54
|
+
*/
|
|
55
|
+
public getEncryptedLogs() {
|
|
56
|
+
return this.encryptedLogs;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Return the encrypted logs.
|
|
61
|
+
*/
|
|
62
|
+
public getUnencryptedLogs() {
|
|
63
|
+
return this.unencryptedLogs;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type FunctionData, PrivateCallStackItem, PrivateCircuitPublicInputs } from '@aztec/circuits.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { type FunctionArtifact } from '@aztec/foundation/abi';
|
|
3
3
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
5
4
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
6
5
|
|
|
7
6
|
import { witnessMapToFields } from '../acvm/deserialize.js';
|
|
@@ -16,7 +15,7 @@ import { AcirSimulator } from './simulator.js';
|
|
|
16
15
|
*/
|
|
17
16
|
export async function executePrivateFunction(
|
|
18
17
|
context: ClientExecutionContext,
|
|
19
|
-
artifact:
|
|
18
|
+
artifact: FunctionArtifact,
|
|
20
19
|
contractAddress: AztecAddress,
|
|
21
20
|
functionData: FunctionData,
|
|
22
21
|
log = createDebugLogger('aztec:simulator:secret_execution'),
|
|
@@ -45,17 +44,12 @@ export async function executePrivateFunction(
|
|
|
45
44
|
|
|
46
45
|
const encryptedLogs = context.getEncryptedLogs();
|
|
47
46
|
const unencryptedLogs = context.getUnencryptedLogs();
|
|
48
|
-
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) --> set this in Noir
|
|
49
|
-
publicInputs.encryptedLogPreimagesLength = new Fr(encryptedLogs.getSerializedLength());
|
|
50
|
-
publicInputs.unencryptedLogPreimagesLength = new Fr(unencryptedLogs.getSerializedLength());
|
|
51
47
|
|
|
52
48
|
const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs);
|
|
53
49
|
|
|
54
50
|
const rawReturnValues = await context.unpackReturns(publicInputs.returnsHash);
|
|
55
51
|
|
|
56
|
-
const
|
|
57
|
-
publicInputs.noteHashReadRequests,
|
|
58
|
-
);
|
|
52
|
+
const noteHashLeafIndexMap = context.getNoteHashLeafIndexMap();
|
|
59
53
|
const newNotes = context.getNewNotes();
|
|
60
54
|
const nullifiedNoteHashCounters = context.getNullifiedNoteHashCounters();
|
|
61
55
|
const nestedExecutions = context.getNestedExecutions();
|
|
@@ -68,7 +62,7 @@ export async function executePrivateFunction(
|
|
|
68
62
|
partialWitness,
|
|
69
63
|
callStackItem,
|
|
70
64
|
returnValues: rawReturnValues,
|
|
71
|
-
|
|
65
|
+
noteHashLeafIndexMap,
|
|
72
66
|
newNotes,
|
|
73
67
|
nullifiedNoteHashCounters,
|
|
74
68
|
vk: Buffer.from(artifact.verificationKey!, 'hex'),
|
package/src/client/simulator.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type AztecNode, type FunctionCall, type Note, type TxExecutionRequest }
|
|
|
2
2
|
import { CallContext, FunctionData } from '@aztec/circuits.js';
|
|
3
3
|
import {
|
|
4
4
|
type ArrayType,
|
|
5
|
-
type
|
|
5
|
+
type FunctionArtifact,
|
|
6
6
|
FunctionSelector,
|
|
7
7
|
FunctionType,
|
|
8
8
|
encodeArguments,
|
|
@@ -19,6 +19,7 @@ import { ClientExecutionContext } from './client_execution_context.js';
|
|
|
19
19
|
import { type DBOracle } from './db_oracle.js';
|
|
20
20
|
import { ExecutionNoteCache } from './execution_note_cache.js';
|
|
21
21
|
import { type ExecutionResult } from './execution_result.js';
|
|
22
|
+
import { LogsCache } from './logs_cache.js';
|
|
22
23
|
import { executePrivateFunction } from './private_execution.js';
|
|
23
24
|
import { executeUnconstrainedFunction } from './unconstrained_execution.js';
|
|
24
25
|
import { ViewDataOracle } from './view_data_oracle.js';
|
|
@@ -64,7 +65,7 @@ export class AcirSimulator {
|
|
|
64
65
|
*/
|
|
65
66
|
public async run(
|
|
66
67
|
request: TxExecutionRequest,
|
|
67
|
-
entryPointArtifact:
|
|
68
|
+
entryPointArtifact: FunctionArtifact,
|
|
68
69
|
contractAddress: AztecAddress,
|
|
69
70
|
msgSender = AztecAddress.ZERO,
|
|
70
71
|
): Promise<ExecutionResult> {
|
|
@@ -100,6 +101,7 @@ export class AcirSimulator {
|
|
|
100
101
|
request.authWitnesses,
|
|
101
102
|
PackedValuesCache.create(request.argsOfCalls),
|
|
102
103
|
new ExecutionNoteCache(),
|
|
104
|
+
new LogsCache(),
|
|
103
105
|
this.db,
|
|
104
106
|
this.node,
|
|
105
107
|
startSideEffectCounter,
|
|
@@ -127,7 +129,7 @@ export class AcirSimulator {
|
|
|
127
129
|
*/
|
|
128
130
|
public async runUnconstrained(
|
|
129
131
|
request: FunctionCall,
|
|
130
|
-
entryPointArtifact:
|
|
132
|
+
entryPointArtifact: FunctionArtifact,
|
|
131
133
|
contractAddress: AztecAddress,
|
|
132
134
|
) {
|
|
133
135
|
if (entryPointArtifact.functionType !== FunctionType.UNCONSTRAINED) {
|
|
@@ -165,7 +167,7 @@ export class AcirSimulator {
|
|
|
165
167
|
noteTypeId: Fr,
|
|
166
168
|
note: Note,
|
|
167
169
|
) {
|
|
168
|
-
const artifact:
|
|
170
|
+
const artifact: FunctionArtifact | undefined = await this.db.getFunctionArtifactByName(
|
|
169
171
|
contractAddress,
|
|
170
172
|
'compute_note_hash_and_nullifier',
|
|
171
173
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FunctionData } from '@aztec/circuits.js';
|
|
2
|
-
import { type DecodedReturn, type
|
|
2
|
+
import { type DecodedReturn, type FunctionArtifact, decodeReturnValues } from '@aztec/foundation/abi';
|
|
3
3
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { type Fr } from '@aztec/foundation/fields';
|
|
5
5
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
@@ -16,7 +16,7 @@ import { type ViewDataOracle } from './view_data_oracle.js';
|
|
|
16
16
|
*/
|
|
17
17
|
export async function executeUnconstrainedFunction(
|
|
18
18
|
oracle: ViewDataOracle,
|
|
19
|
-
artifact:
|
|
19
|
+
artifact: FunctionArtifact,
|
|
20
20
|
contractAddress: AztecAddress,
|
|
21
21
|
functionData: FunctionData,
|
|
22
22
|
args: Fr[],
|
package/src/mocks/fixtures.ts
CHANGED
|
@@ -116,6 +116,8 @@ export class PublicExecutionResultBuilder {
|
|
|
116
116
|
contractStorageReads: [],
|
|
117
117
|
unencryptedLogsHashes: [],
|
|
118
118
|
unencryptedLogs: UnencryptedFunctionL2Logs.empty(),
|
|
119
|
+
unencryptedLogPreimagesLength: new Fr(4n), // empty logs have len 4
|
|
120
|
+
allUnencryptedLogs: UnencryptedFunctionL2Logs.empty(),
|
|
119
121
|
startSideEffectCounter: Fr.ZERO,
|
|
120
122
|
endSideEffectCounter: Fr.ZERO,
|
|
121
123
|
reverted: this._reverted,
|
|
@@ -246,8 +246,10 @@ export abstract class AbstractPhaseManager {
|
|
|
246
246
|
while (executionStack.length) {
|
|
247
247
|
const current = executionStack.pop()!;
|
|
248
248
|
const isExecutionRequest = !isPublicExecutionResult(current);
|
|
249
|
+
// TODO(6052): Extract correct new counter from nested calls
|
|
249
250
|
const sideEffectCounter = lastSideEffectCounter(tx) + 1;
|
|
250
|
-
const availableGas = this.getAvailableGas(tx,
|
|
251
|
+
const availableGas = this.getAvailableGas(tx, kernelOutput);
|
|
252
|
+
const pendingNullifiers = this.getSiloedPendingNullifiers(kernelOutput);
|
|
251
253
|
|
|
252
254
|
const result = isExecutionRequest
|
|
253
255
|
? await this.publicExecutor.simulate(
|
|
@@ -255,6 +257,7 @@ export abstract class AbstractPhaseManager {
|
|
|
255
257
|
this.globalVariables,
|
|
256
258
|
availableGas,
|
|
257
259
|
tx.data.constants.txContext,
|
|
260
|
+
pendingNullifiers,
|
|
258
261
|
transactionFee,
|
|
259
262
|
sideEffectCounter,
|
|
260
263
|
)
|
|
@@ -270,7 +273,9 @@ export abstract class AbstractPhaseManager {
|
|
|
270
273
|
throw result.revertReason;
|
|
271
274
|
}
|
|
272
275
|
|
|
273
|
-
|
|
276
|
+
if (isExecutionRequest) {
|
|
277
|
+
newUnencryptedFunctionLogs.push(result.allUnencryptedLogs);
|
|
278
|
+
}
|
|
274
279
|
|
|
275
280
|
this.log.debug(
|
|
276
281
|
`Running public kernel circuit for ${result.execution.contractAddress.toString()}:${functionSelector}`,
|
|
@@ -320,6 +325,11 @@ export abstract class AbstractPhaseManager {
|
|
|
320
325
|
return [publicKernelInputs, kernelOutput, kernelProof, newUnencryptedFunctionLogs, undefined, returns];
|
|
321
326
|
}
|
|
322
327
|
|
|
328
|
+
/** Returns all pending private and public nullifiers. */
|
|
329
|
+
private getSiloedPendingNullifiers(ko: PublicKernelCircuitPublicInputs) {
|
|
330
|
+
return [...ko.end.newNullifiers, ...ko.endNonRevertibleData.newNullifiers].filter(n => !n.isEmpty());
|
|
331
|
+
}
|
|
332
|
+
|
|
323
333
|
protected getAvailableGas(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs) {
|
|
324
334
|
return tx.data.constants.txContext.gasSettings
|
|
325
335
|
.getLimits() // No need to subtract teardown limits since they are already included in end.gasUsed
|
|
@@ -382,8 +392,6 @@ export abstract class AbstractPhaseManager {
|
|
|
382
392
|
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
|
|
383
393
|
);
|
|
384
394
|
|
|
385
|
-
const unencryptedLogPreimagesLength = new Fr(result.unencryptedLogs.getSerializedLength());
|
|
386
|
-
|
|
387
395
|
const publicCircuitPublicInputs = PublicCircuitPublicInputs.from({
|
|
388
396
|
callContext: result.execution.callContext,
|
|
389
397
|
proverAddress: AztecAddress.ZERO,
|
|
@@ -420,7 +428,7 @@ export abstract class AbstractPhaseManager {
|
|
|
420
428
|
SideEffect.empty(),
|
|
421
429
|
MAX_UNENCRYPTED_LOGS_PER_CALL,
|
|
422
430
|
),
|
|
423
|
-
unencryptedLogPreimagesLength,
|
|
431
|
+
unencryptedLogPreimagesLength: result.unencryptedLogPreimagesLength,
|
|
424
432
|
historicalHeader: this.historicalHeader,
|
|
425
433
|
globalVariables: this.globalVariables,
|
|
426
434
|
startGasLeft: Gas.from(result.startGasLeft),
|
package/src/public/execution.ts
CHANGED
|
@@ -54,6 +54,15 @@ export interface PublicExecutionResult {
|
|
|
54
54
|
* Note: These are preimages to `unencryptedLogsHashes`.
|
|
55
55
|
*/
|
|
56
56
|
unencryptedLogs: UnencryptedFunctionL2Logs;
|
|
57
|
+
/**
|
|
58
|
+
* Length of the unencrypted log preimages emitted in this function call.
|
|
59
|
+
*/
|
|
60
|
+
unencryptedLogPreimagesLength: Fr;
|
|
61
|
+
/**
|
|
62
|
+
* Unencrypted logs emitted during this call AND any nested calls.
|
|
63
|
+
* Useful for maintaining correct ordering in ts.
|
|
64
|
+
*/
|
|
65
|
+
allUnencryptedLogs: UnencryptedFunctionL2Logs;
|
|
57
66
|
/**
|
|
58
67
|
* Whether the execution reverted.
|
|
59
68
|
*/
|
package/src/public/executor.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
Gas,
|
|
5
5
|
type GlobalVariables,
|
|
6
6
|
type Header,
|
|
7
|
+
type Nullifier,
|
|
7
8
|
PublicCircuitPublicInputs,
|
|
8
9
|
type TxContext,
|
|
9
10
|
} from '@aztec/circuits.js';
|
|
@@ -26,7 +27,7 @@ import { PackedValuesCache } from '../common/packed_values_cache.js';
|
|
|
26
27
|
import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db.js';
|
|
27
28
|
import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js';
|
|
28
29
|
import { PublicExecutionContext } from './public_execution_context.js';
|
|
29
|
-
import {
|
|
30
|
+
import { convertAvmResultsToPxResult, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Execute a public function and return the execution result.
|
|
@@ -46,15 +47,23 @@ export async function executePublicFunction(
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
if (isAvmBytecode(bytecode)) {
|
|
49
|
-
return await
|
|
50
|
+
return await executeTopLevelPublicFunctionAvm(context, bytecode);
|
|
50
51
|
} else {
|
|
51
52
|
return await executePublicFunctionAcvm(context, bytecode, nested);
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Execute a top-level public function call (the first call in an enqueued-call/execution-request) in the AVM.
|
|
58
|
+
* Translate the results back to the PublicExecutionResult format.
|
|
59
|
+
*/
|
|
60
|
+
async function executeTopLevelPublicFunctionAvm(
|
|
61
|
+
executionContext: PublicExecutionContext,
|
|
62
|
+
bytecode: Buffer,
|
|
63
|
+
): Promise<PublicExecutionResult> {
|
|
56
64
|
const address = executionContext.execution.contractAddress;
|
|
57
65
|
const selector = executionContext.execution.functionData.selector;
|
|
66
|
+
const startGas = executionContext.availableGas;
|
|
58
67
|
const log = createDebugLogger('aztec:simulator:public_execution');
|
|
59
68
|
log.verbose(`[AVM] Executing public external function ${address.toString()}:${selector}.`);
|
|
60
69
|
|
|
@@ -65,7 +74,15 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
|
|
|
65
74
|
executionContext.contractsDb,
|
|
66
75
|
executionContext.commitmentsDb,
|
|
67
76
|
);
|
|
77
|
+
|
|
78
|
+
// TODO(6207): add sideEffectCounter to persistableState construction
|
|
79
|
+
// or modify the PersistableStateManager to manage rollbacks across enqueued-calls and transactions.
|
|
68
80
|
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
|
|
81
|
+
const startSideEffectCounter = executionContext.execution.callContext.sideEffectCounter;
|
|
82
|
+
for (const nullifier of executionContext.pendingNullifiers) {
|
|
83
|
+
worldStateJournal.nullifiers.cache.appendSiloed(nullifier.value);
|
|
84
|
+
}
|
|
85
|
+
worldStateJournal.trace.accessCounter = startSideEffectCounter;
|
|
69
86
|
|
|
70
87
|
const executionEnv = createAvmExecutionEnvironment(
|
|
71
88
|
executionContext.execution,
|
|
@@ -75,18 +92,30 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
|
|
|
75
92
|
executionContext.transactionFee,
|
|
76
93
|
);
|
|
77
94
|
|
|
78
|
-
const machineState = new AvmMachineState(
|
|
79
|
-
const
|
|
80
|
-
const simulator = new AvmSimulator(
|
|
95
|
+
const machineState = new AvmMachineState(startGas);
|
|
96
|
+
const avmContext = new AvmContext(worldStateJournal, executionEnv, machineState);
|
|
97
|
+
const simulator = new AvmSimulator(avmContext);
|
|
81
98
|
|
|
82
|
-
const
|
|
83
|
-
|
|
99
|
+
const avmResult = await simulator.executeBytecode(bytecode);
|
|
100
|
+
|
|
101
|
+
// Commit the journals state to the DBs since this is a top-level execution.
|
|
102
|
+
// Observe that this will write all the state changes to the DBs, not only the latest for each slot.
|
|
103
|
+
// However, the underlying DB keep a cache and will only write the latest state to disk.
|
|
104
|
+
await avmContext.persistableState.publicStorage.commitToDB();
|
|
84
105
|
|
|
85
106
|
log.verbose(
|
|
86
|
-
`[AVM] ${address.toString()}:${selector} returned, reverted: ${
|
|
107
|
+
`[AVM] ${address.toString()}:${selector} returned, reverted: ${avmResult.reverted}, reason: ${
|
|
108
|
+
avmResult.revertReason
|
|
109
|
+
}.`,
|
|
87
110
|
);
|
|
88
111
|
|
|
89
|
-
return
|
|
112
|
+
return convertAvmResultsToPxResult(
|
|
113
|
+
avmResult,
|
|
114
|
+
startSideEffectCounter,
|
|
115
|
+
executionContext.execution,
|
|
116
|
+
startGas,
|
|
117
|
+
avmContext,
|
|
118
|
+
);
|
|
90
119
|
}
|
|
91
120
|
|
|
92
121
|
async function executePublicFunctionAcvm(
|
|
@@ -159,6 +188,8 @@ async function executePublicFunctionAcvm(
|
|
|
159
188
|
nestedExecutions: [],
|
|
160
189
|
unencryptedLogsHashes: [],
|
|
161
190
|
unencryptedLogs: UnencryptedFunctionL2Logs.empty(),
|
|
191
|
+
unencryptedLogPreimagesLength: new Fr(4n), // empty logs have len 4
|
|
192
|
+
allUnencryptedLogs: UnencryptedFunctionL2Logs.empty(),
|
|
162
193
|
reverted,
|
|
163
194
|
revertReason,
|
|
164
195
|
startGasLeft: context.availableGas,
|
|
@@ -182,6 +213,7 @@ async function executePublicFunctionAcvm(
|
|
|
182
213
|
startSideEffectCounter,
|
|
183
214
|
endSideEffectCounter,
|
|
184
215
|
unencryptedLogsHashes: unencryptedLogsHashesPadded,
|
|
216
|
+
unencryptedLogPreimagesLength,
|
|
185
217
|
} = PublicCircuitPublicInputs.fromFields(returnWitness);
|
|
186
218
|
const returnValues = await context.unpackReturns(returnsHash);
|
|
187
219
|
|
|
@@ -207,6 +239,7 @@ async function executePublicFunctionAcvm(
|
|
|
207
239
|
|
|
208
240
|
const nestedExecutions = context.getNestedExecutions();
|
|
209
241
|
const unencryptedLogs = context.getUnencryptedLogs();
|
|
242
|
+
const allUnencryptedLogs = context.getAllUnencryptedLogs();
|
|
210
243
|
|
|
211
244
|
// TODO(palla/gas): We should be loading these values from the returned PublicCircuitPublicInputs
|
|
212
245
|
const startGasLeft = context.availableGas;
|
|
@@ -227,6 +260,8 @@ async function executePublicFunctionAcvm(
|
|
|
227
260
|
nestedExecutions,
|
|
228
261
|
unencryptedLogsHashes,
|
|
229
262
|
unencryptedLogs,
|
|
263
|
+
unencryptedLogPreimagesLength,
|
|
264
|
+
allUnencryptedLogs,
|
|
230
265
|
reverted: false,
|
|
231
266
|
revertReason: undefined,
|
|
232
267
|
startGasLeft,
|
|
@@ -258,6 +293,7 @@ export class PublicExecutor {
|
|
|
258
293
|
globalVariables: GlobalVariables,
|
|
259
294
|
availableGas: Gas,
|
|
260
295
|
txContext: TxContext,
|
|
296
|
+
pendingNullifiers: Nullifier[],
|
|
261
297
|
transactionFee: Fr = Fr.ZERO,
|
|
262
298
|
sideEffectCounter: number = 0,
|
|
263
299
|
): Promise<PublicExecutionResult> {
|
|
@@ -277,6 +313,7 @@ export class PublicExecutor {
|
|
|
277
313
|
availableGas,
|
|
278
314
|
transactionFee,
|
|
279
315
|
txContext.gasSettings,
|
|
316
|
+
pendingNullifiers,
|
|
280
317
|
);
|
|
281
318
|
|
|
282
319
|
const executionResult = await executePublicFunction(context, /*nested=*/ false);
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type GasSettings,
|
|
8
8
|
type GlobalVariables,
|
|
9
9
|
type Header,
|
|
10
|
+
type Nullifier,
|
|
10
11
|
PublicContextInputs,
|
|
11
12
|
} from '@aztec/circuits.js';
|
|
12
13
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
@@ -37,13 +38,18 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
37
38
|
public readonly header: Header,
|
|
38
39
|
public readonly globalVariables: GlobalVariables,
|
|
39
40
|
private readonly packedValuesCache: PackedValuesCache,
|
|
40
|
-
|
|
41
|
+
// TRANSITIONAL: once AVM-ACVM interoperability is removed (fully functional AVM), sideEffectCounter can be made private
|
|
42
|
+
public readonly sideEffectCounter: SideEffectCounter,
|
|
41
43
|
public readonly stateDb: PublicStateDB,
|
|
42
44
|
public readonly contractsDb: PublicContractsDB,
|
|
43
45
|
public readonly commitmentsDb: CommitmentsDB,
|
|
44
46
|
public readonly availableGas: Gas,
|
|
45
47
|
public readonly transactionFee: Fr,
|
|
46
48
|
public readonly gasSettings: GasSettings,
|
|
49
|
+
public readonly pendingNullifiers: Nullifier[],
|
|
50
|
+
// Unencrypted logs emitted during this call AND any nested calls
|
|
51
|
+
// Useful for maintaining correct ordering in ts
|
|
52
|
+
private allUnencryptedLogs: UnencryptedL2Log[] = [],
|
|
47
53
|
private log = createDebugLogger('aztec:simulator:public_execution_context'),
|
|
48
54
|
) {
|
|
49
55
|
super();
|
|
@@ -87,6 +93,13 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
87
93
|
return new UnencryptedFunctionL2Logs(this.unencryptedLogs);
|
|
88
94
|
}
|
|
89
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Return the encrypted logs emitted during this execution, including nested calls.
|
|
98
|
+
*/
|
|
99
|
+
public getAllUnencryptedLogs() {
|
|
100
|
+
return new UnencryptedFunctionL2Logs(this.allUnencryptedLogs);
|
|
101
|
+
}
|
|
102
|
+
|
|
90
103
|
/**
|
|
91
104
|
* Return the data read and updated during this execution.
|
|
92
105
|
*/
|
|
@@ -135,11 +148,10 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
135
148
|
* Emit an unencrypted log.
|
|
136
149
|
* @param log - The unencrypted log to be emitted.
|
|
137
150
|
*/
|
|
138
|
-
public override emitUnencryptedLog(log: UnencryptedL2Log) {
|
|
139
|
-
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/885)
|
|
151
|
+
public override emitUnencryptedLog(log: UnencryptedL2Log, _counter: number) {
|
|
140
152
|
this.unencryptedLogs.push(log);
|
|
153
|
+
this.allUnencryptedLogs.push(log);
|
|
141
154
|
this.log.verbose(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
|
|
142
|
-
return Fr.fromBuffer(log.hash());
|
|
143
155
|
}
|
|
144
156
|
|
|
145
157
|
/**
|
|
@@ -229,6 +241,8 @@ export class PublicExecutionContext extends TypedOracle {
|
|
|
229
241
|
this.availableGas,
|
|
230
242
|
this.transactionFee,
|
|
231
243
|
this.gasSettings,
|
|
244
|
+
/*pendingNullifiers=*/ [],
|
|
245
|
+
this.allUnencryptedLogs,
|
|
232
246
|
this.log,
|
|
233
247
|
);
|
|
234
248
|
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type PublicKernelRequest,
|
|
3
|
-
PublicKernelType,
|
|
4
|
-
type Tx,
|
|
5
|
-
UnencryptedFunctionL2Logs,
|
|
6
|
-
type UnencryptedL2Log,
|
|
7
|
-
} from '@aztec/circuit-types';
|
|
1
|
+
import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types';
|
|
8
2
|
import {
|
|
9
3
|
Fr,
|
|
10
4
|
type GlobalVariables,
|
|
@@ -57,8 +51,6 @@ export class TailPhaseManager extends AbstractPhaseManager {
|
|
|
57
51
|
throw err;
|
|
58
52
|
},
|
|
59
53
|
);
|
|
60
|
-
// Temporary hack. Should sort them in the tail circuit.
|
|
61
|
-
this.patchLogsOrdering(tx, previousPublicKernelOutput);
|
|
62
54
|
// commit the state updates from this transaction
|
|
63
55
|
await this.publicStateDB.commit();
|
|
64
56
|
|
|
@@ -163,33 +155,9 @@ export class TailPhaseManager extends AbstractPhaseManager {
|
|
|
163
155
|
}
|
|
164
156
|
|
|
165
157
|
private sortLogsHashes<N extends number>(unencryptedLogsHashes: Tuple<SideEffect, N>): Tuple<SideEffect, N> {
|
|
158
|
+
// TODO(6052): logs here may have duplicate counters from nested calls
|
|
166
159
|
return sortByCounter(
|
|
167
160
|
unencryptedLogsHashes.map(n => ({ ...n, counter: n.counter.toNumber(), isEmpty: () => n.isEmpty() })),
|
|
168
161
|
).map(h => new SideEffect(h.value, new Fr(h.counter))) as Tuple<SideEffect, N>;
|
|
169
162
|
}
|
|
170
|
-
|
|
171
|
-
// As above, this is a hack for unencrypted logs ordering, now they are sorted. Since the public kernel
|
|
172
|
-
// cannot keep track of side effects that happen after or before a nested call, we override the gathered logs.
|
|
173
|
-
// As a sanity check, we at least verify that the elements are the same, so we are only tweaking their ordering.
|
|
174
|
-
// See same fn in pxe_service.ts
|
|
175
|
-
// Added as part of resolving #5017
|
|
176
|
-
private patchLogsOrdering(tx: Tx, publicInputs: PublicKernelCircuitPublicInputs) {
|
|
177
|
-
const unencLogs = tx.unencryptedLogs.unrollLogs();
|
|
178
|
-
const sortedUnencLogs = publicInputs.end.unencryptedLogsHashes;
|
|
179
|
-
|
|
180
|
-
const finalUnencLogs: UnencryptedL2Log[] = [];
|
|
181
|
-
sortedUnencLogs.forEach((sideEffect: SideEffect) => {
|
|
182
|
-
if (!sideEffect.isEmpty()) {
|
|
183
|
-
const isLog = (log: UnencryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value);
|
|
184
|
-
const thisLogIndex = unencLogs.findIndex(isLog);
|
|
185
|
-
finalUnencLogs.push(unencLogs[thisLogIndex]);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
const unencryptedLogs = new UnencryptedFunctionL2Logs(finalUnencLogs);
|
|
189
|
-
|
|
190
|
-
tx.unencryptedLogs.functionLogs[0] = unencryptedLogs;
|
|
191
|
-
for (let i = 1; i < tx.unencryptedLogs.functionLogs.length; i++) {
|
|
192
|
-
tx.unencryptedLogs.functionLogs[i] = UnencryptedFunctionL2Logs.empty();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
163
|
}
|