@aztec/simulator 0.47.0 → 0.48.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/oracle/oracle.d.ts +5 -5
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +13 -16
- package/dest/acvm/oracle/typed_oracle.d.ts +12 -9
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +6 -6
- package/dest/acvm/serialize.d.ts +0 -11
- package/dest/acvm/serialize.d.ts.map +1 -1
- package/dest/acvm/serialize.js +1 -26
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +2 -1
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +2 -2
- package/dest/avm/opcodes/commitment.d.ts +16 -0
- package/dest/avm/opcodes/commitment.d.ts.map +1 -0
- package/dest/avm/opcodes/commitment.js +50 -0
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +3 -1
- package/dest/avm/serialization/instruction_serialization.d.ts +4 -3
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +6 -5
- package/dest/client/client_execution_context.d.ts +20 -17
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +42 -45
- package/dest/client/db_oracle.d.ts +4 -3
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/execution_note_cache.d.ts +17 -13
- package/dest/client/execution_note_cache.d.ts.map +1 -1
- package/dest/client/execution_note_cache.js +65 -26
- package/dest/client/execution_result.d.ts +15 -8
- package/dest/client/execution_result.d.ts.map +1 -1
- package/dest/client/execution_result.js +40 -16
- package/dest/client/private_execution.js +3 -3
- package/dest/client/simulator.d.ts +7 -6
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +14 -12
- package/dest/client/test_utils.d.ts +9 -0
- package/dest/client/test_utils.d.ts.map +1 -0
- package/dest/client/test_utils.js +21 -0
- package/dest/client/view_data_oracle.d.ts +2 -1
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +4 -3
- package/dest/index.d.ts +0 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -2
- package/dest/mocks/fixtures.d.ts +5 -5
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +6 -9
- package/dest/public/abstract_phase_manager.d.ts +4 -5
- package/dest/public/abstract_phase_manager.d.ts.map +1 -1
- package/dest/public/abstract_phase_manager.js +17 -84
- package/dest/public/execution.d.ts +8 -10
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +10 -1
- package/dest/public/executor.d.ts +6 -2
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +12 -4
- package/dest/public/executor_metrics.d.ts +10 -0
- package/dest/public/executor_metrics.d.ts.map +1 -0
- package/dest/public/executor_metrics.js +32 -0
- package/dest/public/fee_payment.d.ts +2 -2
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +9 -10
- package/dest/public/hints_builder.d.ts.map +1 -1
- package/dest/public/hints_builder.js +1 -1
- package/dest/public/index.d.ts +1 -1
- package/dest/public/index.d.ts.map +1 -1
- package/dest/public/index.js +1 -1
- package/dest/public/public_processor.d.ts +3 -3
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +33 -14
- package/dest/public/public_processor_metrics.d.ts +19 -0
- package/dest/public/public_processor_metrics.d.ts.map +1 -0
- package/dest/public/public_processor_metrics.js +57 -0
- package/dest/public/side_effect_trace.d.ts +1 -0
- package/dest/public/side_effect_trace.d.ts.map +1 -1
- package/dest/public/side_effect_trace.js +9 -9
- package/package.json +9 -9
- package/src/acvm/acvm.ts +1 -1
- package/src/acvm/oracle/oracle.ts +13 -30
- package/src/acvm/oracle/typed_oracle.ts +12 -31
- package/src/acvm/serialize.ts +0 -29
- package/src/avm/avm_gas.ts +1 -0
- package/src/avm/fixtures/index.ts +1 -0
- package/src/avm/opcodes/commitment.ts +66 -0
- package/src/avm/serialization/bytecode_serialization.ts +2 -0
- package/src/avm/serialization/instruction_serialization.ts +2 -1
- package/src/client/client_execution_context.ts +51 -49
- package/src/client/db_oracle.ts +9 -3
- package/src/client/execution_note_cache.ts +76 -25
- package/src/client/execution_result.ts +54 -19
- package/src/client/private_execution.ts +2 -2
- package/src/client/simulator.ts +18 -14
- package/src/client/test_utils.ts +30 -0
- package/src/client/view_data_oracle.ts +2 -1
- package/src/index.ts +0 -1
- package/src/mocks/fixtures.ts +13 -11
- package/src/public/abstract_phase_manager.ts +23 -104
- package/src/public/execution.ts +30 -14
- package/src/public/executor.ts +18 -4
- package/src/public/executor_metrics.ts +48 -0
- package/src/public/fee_payment.ts +8 -10
- package/src/public/hints_builder.ts +2 -2
- package/src/public/index.ts +1 -1
- package/src/public/public_processor.ts +46 -15
- package/src/public/public_processor_metrics.ts +90 -0
- package/src/public/side_effect_trace.ts +13 -7
- package/dest/utils.d.ts +0 -12
- package/dest/utils.d.ts.map +0 -1
- package/dest/utils.js +0 -11
- package/src/utils.ts +0 -18
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type AvmProvingRequest,
|
|
4
4
|
MerkleTreeId,
|
|
5
5
|
type NestedProcessReturnValues,
|
|
6
|
+
type PublicExecutionRequest,
|
|
6
7
|
type PublicKernelNonTailRequest,
|
|
7
8
|
PublicKernelType,
|
|
8
9
|
type PublicProvingRequest,
|
|
@@ -13,8 +14,6 @@ import {
|
|
|
13
14
|
import {
|
|
14
15
|
type AvmExecutionHints,
|
|
15
16
|
AztecAddress,
|
|
16
|
-
CallRequest,
|
|
17
|
-
ClientIvcProof,
|
|
18
17
|
ContractStorageRead,
|
|
19
18
|
ContractStorageUpdateRequest,
|
|
20
19
|
Fr,
|
|
@@ -40,7 +39,7 @@ import {
|
|
|
40
39
|
NoteHash,
|
|
41
40
|
Nullifier,
|
|
42
41
|
PublicCallData,
|
|
43
|
-
|
|
42
|
+
PublicCallRequest,
|
|
44
43
|
PublicCallStackItem,
|
|
45
44
|
PublicCircuitPublicInputs,
|
|
46
45
|
PublicKernelCircuitPrivateInputs,
|
|
@@ -62,7 +61,6 @@ import {
|
|
|
62
61
|
getVKSiblingPath,
|
|
63
62
|
} from '@aztec/noir-protocol-circuits-types';
|
|
64
63
|
import {
|
|
65
|
-
type PublicExecutionRequest,
|
|
66
64
|
type PublicExecutionResult,
|
|
67
65
|
type PublicExecutor,
|
|
68
66
|
accumulateReturnValues,
|
|
@@ -165,76 +163,18 @@ export abstract class AbstractPhaseManager {
|
|
|
165
163
|
previousKernelArtifact: ProtocolArtifact,
|
|
166
164
|
): Promise<PhaseResult>;
|
|
167
165
|
|
|
168
|
-
public static extractEnqueuedPublicCallsByPhase(tx: Tx): Record<PublicKernelType,
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
const publicCallsStack = tx.enqueuedPublicFunctionCalls.slice().reverse();
|
|
180
|
-
const nonRevertibleCallStack = data.endNonRevertibleData.publicCallStack.filter(i => !i.isEmpty());
|
|
181
|
-
const revertibleCallStack = data.end.publicCallStack.filter(i => !i.isEmpty());
|
|
182
|
-
|
|
183
|
-
const callRequestsStack = publicCallsStack
|
|
184
|
-
.map(call => call.toCallRequest())
|
|
185
|
-
.filter(
|
|
186
|
-
// filter out enqueued calls that are not in the public call stack
|
|
187
|
-
// TODO mitch left a question about whether this is only needed when unit testing
|
|
188
|
-
// with mock data
|
|
189
|
-
call => revertibleCallStack.find(p => p.equals(call)) || nonRevertibleCallStack.find(p => p.equals(call)),
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
const teardownCallStack = tx.publicTeardownFunctionCall.isEmpty() ? [] : [tx.publicTeardownFunctionCall];
|
|
193
|
-
|
|
194
|
-
if (callRequestsStack.length === 0) {
|
|
195
|
-
return {
|
|
196
|
-
[PublicKernelType.NON_PUBLIC]: [],
|
|
197
|
-
[PublicKernelType.SETUP]: [],
|
|
198
|
-
[PublicKernelType.APP_LOGIC]: [],
|
|
199
|
-
[PublicKernelType.TEARDOWN]: teardownCallStack,
|
|
200
|
-
[PublicKernelType.TAIL]: [],
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// find the first call that is revertible
|
|
205
|
-
const firstRevertibleCallIndex = callRequestsStack.findIndex(
|
|
206
|
-
c => revertibleCallStack.findIndex(p => p.equals(c)) !== -1,
|
|
207
|
-
);
|
|
208
|
-
|
|
209
|
-
if (firstRevertibleCallIndex === 0) {
|
|
210
|
-
return {
|
|
211
|
-
[PublicKernelType.NON_PUBLIC]: [],
|
|
212
|
-
[PublicKernelType.SETUP]: [],
|
|
213
|
-
[PublicKernelType.APP_LOGIC]: publicCallsStack,
|
|
214
|
-
[PublicKernelType.TEARDOWN]: teardownCallStack,
|
|
215
|
-
[PublicKernelType.TAIL]: [],
|
|
216
|
-
};
|
|
217
|
-
} else if (firstRevertibleCallIndex === -1) {
|
|
218
|
-
// there's no app logic, split the functions between setup (many) and teardown (just one function call)
|
|
219
|
-
return {
|
|
220
|
-
[PublicKernelType.NON_PUBLIC]: [],
|
|
221
|
-
[PublicKernelType.SETUP]: publicCallsStack,
|
|
222
|
-
[PublicKernelType.APP_LOGIC]: [],
|
|
223
|
-
[PublicKernelType.TEARDOWN]: teardownCallStack,
|
|
224
|
-
[PublicKernelType.TAIL]: [],
|
|
225
|
-
};
|
|
226
|
-
} else {
|
|
227
|
-
return {
|
|
228
|
-
[PublicKernelType.NON_PUBLIC]: [],
|
|
229
|
-
[PublicKernelType.SETUP]: publicCallsStack.slice(0, firstRevertibleCallIndex),
|
|
230
|
-
[PublicKernelType.APP_LOGIC]: publicCallsStack.slice(firstRevertibleCallIndex),
|
|
231
|
-
[PublicKernelType.TEARDOWN]: teardownCallStack,
|
|
232
|
-
[PublicKernelType.TAIL]: [],
|
|
233
|
-
};
|
|
234
|
-
}
|
|
166
|
+
public static extractEnqueuedPublicCallsByPhase(tx: Tx): Record<PublicKernelType, PublicExecutionRequest[]> {
|
|
167
|
+
const teardownRequest = tx.getPublicTeardownExecutionRequest();
|
|
168
|
+
return {
|
|
169
|
+
[PublicKernelType.NON_PUBLIC]: [],
|
|
170
|
+
[PublicKernelType.SETUP]: tx.getNonRevertiblePublicExecutionRequests(),
|
|
171
|
+
[PublicKernelType.APP_LOGIC]: tx.getRevertiblePublicExecutionRequests(),
|
|
172
|
+
[PublicKernelType.TEARDOWN]: teardownRequest ? [teardownRequest] : [],
|
|
173
|
+
[PublicKernelType.TAIL]: [],
|
|
174
|
+
};
|
|
235
175
|
}
|
|
236
176
|
|
|
237
|
-
protected extractEnqueuedPublicCalls(tx: Tx):
|
|
177
|
+
protected extractEnqueuedPublicCalls(tx: Tx): PublicExecutionRequest[] {
|
|
238
178
|
const calls = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx)[this.phase];
|
|
239
179
|
|
|
240
180
|
return calls;
|
|
@@ -245,7 +185,7 @@ export abstract class AbstractPhaseManager {
|
|
|
245
185
|
previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
|
|
246
186
|
previousKernelArtifact: ProtocolArtifact,
|
|
247
187
|
): Promise<TxPublicCallsResult> {
|
|
248
|
-
const enqueuedCalls = this.extractEnqueuedPublicCalls(tx);
|
|
188
|
+
const enqueuedCalls = [...this.extractEnqueuedPublicCalls(tx)].reverse();
|
|
249
189
|
|
|
250
190
|
if (!enqueuedCalls || !enqueuedCalls.length) {
|
|
251
191
|
return {
|
|
@@ -299,7 +239,7 @@ export abstract class AbstractPhaseManager {
|
|
|
299
239
|
|
|
300
240
|
// Sanity check for a current upstream assumption.
|
|
301
241
|
// Consumers of the result seem to expect "reverted <=> revertReason !== undefined".
|
|
302
|
-
const functionSelector = result.executionRequest.functionSelector.toString();
|
|
242
|
+
const functionSelector = result.executionRequest.callContext.functionSelector.toString();
|
|
303
243
|
if (result.reverted && !result.revertReason) {
|
|
304
244
|
throw new Error(
|
|
305
245
|
`Simulation of ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${
|
|
@@ -420,7 +360,7 @@ export abstract class AbstractPhaseManager {
|
|
|
420
360
|
const previousKernel = this.getPreviousKernelData(previousOutput, previousCircuit);
|
|
421
361
|
|
|
422
362
|
// We take a deep copy (clone) of these inputs to be passed to the prover
|
|
423
|
-
const inputs = new PublicKernelCircuitPrivateInputs(previousKernel,
|
|
363
|
+
const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData);
|
|
424
364
|
switch (this.phase) {
|
|
425
365
|
case PublicKernelType.SETUP:
|
|
426
366
|
return [inputs.clone(), await this.publicKernel.publicKernelCircuitSetup(inputs), 'PublicKernelSetupArtifact'];
|
|
@@ -460,13 +400,6 @@ export abstract class AbstractPhaseManager {
|
|
|
460
400
|
const publicDataTreeInfo = await this.db.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE);
|
|
461
401
|
this.historicalHeader.state.partial.publicDataTree.root = Fr.fromBuffer(publicDataTreeInfo.root);
|
|
462
402
|
|
|
463
|
-
const callStackPreimages = await this.getPublicCallStackPreimages(result);
|
|
464
|
-
const publicCallStackHashes = padArrayEnd(
|
|
465
|
-
callStackPreimages.map(c => c.getCompressed().hash()),
|
|
466
|
-
Fr.ZERO,
|
|
467
|
-
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
|
|
468
|
-
);
|
|
469
|
-
|
|
470
403
|
const publicCircuitPublicInputs = PublicCircuitPublicInputs.from({
|
|
471
404
|
callContext: result.executionRequest.callContext,
|
|
472
405
|
proverAddress: AztecAddress.ZERO,
|
|
@@ -507,7 +440,11 @@ export abstract class AbstractPhaseManager {
|
|
|
507
440
|
ContractStorageUpdateRequest.empty(),
|
|
508
441
|
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
|
|
509
442
|
),
|
|
510
|
-
|
|
443
|
+
publicCallRequests: padArrayEnd(
|
|
444
|
+
result.publicCallRequests,
|
|
445
|
+
PublicCallRequest.empty(),
|
|
446
|
+
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
|
|
447
|
+
),
|
|
511
448
|
unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL),
|
|
512
449
|
historicalHeader: this.historicalHeader,
|
|
513
450
|
globalVariables: this.globalVariables,
|
|
@@ -520,23 +457,12 @@ export abstract class AbstractPhaseManager {
|
|
|
520
457
|
|
|
521
458
|
return new PublicCallStackItem(
|
|
522
459
|
result.executionRequest.contractAddress,
|
|
523
|
-
new FunctionData(result.executionRequest.functionSelector, false),
|
|
460
|
+
new FunctionData(result.executionRequest.callContext.functionSelector, false),
|
|
524
461
|
publicCircuitPublicInputs,
|
|
525
462
|
isExecutionRequest,
|
|
526
463
|
);
|
|
527
464
|
}
|
|
528
465
|
|
|
529
|
-
protected async getPublicCallStackPreimages(result: PublicExecutionResult): Promise<PublicCallStackItem[]> {
|
|
530
|
-
const nested = result.nestedExecutions;
|
|
531
|
-
if (nested.length > MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL) {
|
|
532
|
-
throw new Error(
|
|
533
|
-
`Public call stack size exceeded (max ${MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}, got ${nested.length})`,
|
|
534
|
-
);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
return await Promise.all(nested.map(n => this.getPublicCallStackItem(n)));
|
|
538
|
-
}
|
|
539
|
-
|
|
540
466
|
/**
|
|
541
467
|
* Looks at the side effects of a transaction and returns the highest counter
|
|
542
468
|
* @param tx - A transaction
|
|
@@ -562,10 +488,7 @@ export abstract class AbstractPhaseManager {
|
|
|
562
488
|
|
|
563
489
|
let max = 0;
|
|
564
490
|
for (const sideEffect of sideEffectCounters) {
|
|
565
|
-
if ('
|
|
566
|
-
// look at both start and end counters because for enqueued public calls start > 0 while end === 0
|
|
567
|
-
max = Math.max(max, sideEffect.startSideEffectCounter.toNumber(), sideEffect.endSideEffectCounter.toNumber());
|
|
568
|
-
} else if ('counter' in sideEffect) {
|
|
491
|
+
if ('counter' in sideEffect) {
|
|
569
492
|
max = Math.max(max, sideEffect.counter);
|
|
570
493
|
} else {
|
|
571
494
|
throw new Error('Unknown side effect type');
|
|
@@ -593,10 +516,6 @@ export abstract class AbstractPhaseManager {
|
|
|
593
516
|
protected async getPublicCallData(result: PublicExecutionResult, isExecutionRequest = false) {
|
|
594
517
|
const bytecodeHash = await this.getBytecodeHash(result);
|
|
595
518
|
const callStackItem = await this.getPublicCallStackItem(result, isExecutionRequest);
|
|
596
|
-
|
|
597
|
-
c.toCallRequest(callStackItem.publicInputs.callContext),
|
|
598
|
-
);
|
|
599
|
-
const publicCallStack = padArrayEnd(publicCallRequests, CallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL);
|
|
600
|
-
return new PublicCallData(callStackItem, publicCallStack, makeEmptyProof(), bytecodeHash);
|
|
519
|
+
return new PublicCallData(callStackItem, makeEmptyProof(), bytecodeHash);
|
|
601
520
|
}
|
|
602
521
|
}
|
package/src/public/execution.ts
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type PublicExecutionRequest,
|
|
3
|
+
type SimulationError,
|
|
4
|
+
type UnencryptedFunctionL2Logs,
|
|
5
|
+
} from '@aztec/circuit-types';
|
|
2
6
|
import {
|
|
3
7
|
type AvmExecutionHints,
|
|
4
8
|
type ContractStorageRead,
|
|
5
9
|
type ContractStorageUpdateRequest,
|
|
6
10
|
type Fr,
|
|
11
|
+
Gas,
|
|
7
12
|
type L2ToL1Message,
|
|
8
13
|
type LogHash,
|
|
9
14
|
type NoteHash,
|
|
10
15
|
type Nullifier,
|
|
11
|
-
|
|
16
|
+
PublicCallRequest,
|
|
17
|
+
PublicCallStackItemCompressed,
|
|
12
18
|
type ReadRequest,
|
|
19
|
+
RevertCode,
|
|
13
20
|
} from '@aztec/circuits.js';
|
|
21
|
+
import { computeVarArgsHash } from '@aztec/circuits.js/hash';
|
|
14
22
|
|
|
15
|
-
import { type Gas } from '../avm/avm_gas.js';
|
|
23
|
+
import { type Gas as AvmGas } from '../avm/avm_gas.js';
|
|
16
24
|
|
|
17
25
|
/**
|
|
18
26
|
* The public function execution result.
|
|
@@ -26,9 +34,9 @@ export interface PublicExecutionResult {
|
|
|
26
34
|
/** The side effect counter after executing this function call */
|
|
27
35
|
endSideEffectCounter: Fr;
|
|
28
36
|
/** How much gas was available for this public execution. */
|
|
29
|
-
startGasLeft:
|
|
37
|
+
startGasLeft: AvmGas;
|
|
30
38
|
/** How much gas was left after this public execution. */
|
|
31
|
-
endGasLeft:
|
|
39
|
+
endGasLeft: AvmGas;
|
|
32
40
|
/** Transaction fee set for this tx. */
|
|
33
41
|
transactionFee: Fr;
|
|
34
42
|
|
|
@@ -79,6 +87,8 @@ export interface PublicExecutionResult {
|
|
|
79
87
|
|
|
80
88
|
// TODO(dbanks12): add contract instance read requests
|
|
81
89
|
|
|
90
|
+
/** The requests to call public functions made by this call. */
|
|
91
|
+
publicCallRequests: PublicCallRequest[];
|
|
82
92
|
/** The results of nested calls. */
|
|
83
93
|
nestedExecutions: this[];
|
|
84
94
|
|
|
@@ -89,15 +99,6 @@ export interface PublicExecutionResult {
|
|
|
89
99
|
functionName: string;
|
|
90
100
|
}
|
|
91
101
|
|
|
92
|
-
/**
|
|
93
|
-
* The execution request of a public function.
|
|
94
|
-
* A subset of PublicCallRequest
|
|
95
|
-
*/
|
|
96
|
-
export type PublicExecutionRequest = Pick<
|
|
97
|
-
PublicCallRequest,
|
|
98
|
-
'contractAddress' | 'functionSelector' | 'callContext' | 'args'
|
|
99
|
-
>;
|
|
100
|
-
|
|
101
102
|
/**
|
|
102
103
|
* Returns if the input is a public execution result and not just a public execution.
|
|
103
104
|
* @param input - Public execution or public execution result.
|
|
@@ -131,3 +132,18 @@ export function checkValidStaticCall(
|
|
|
131
132
|
throw new Error('Static call cannot update the state, emit L2->L1 messages or generate logs');
|
|
132
133
|
}
|
|
133
134
|
}
|
|
135
|
+
|
|
136
|
+
export function resultToPublicCallRequest(result: PublicExecutionResult) {
|
|
137
|
+
const request = result.executionRequest;
|
|
138
|
+
const item = new PublicCallStackItemCompressed(
|
|
139
|
+
request.contractAddress,
|
|
140
|
+
request.callContext,
|
|
141
|
+
computeVarArgsHash(request.args),
|
|
142
|
+
computeVarArgsHash(result.returnValues),
|
|
143
|
+
// TODO(@just-mitch): need better mapping from simulator to revert code.
|
|
144
|
+
result.reverted ? RevertCode.APP_LOGIC_REVERTED : RevertCode.OK,
|
|
145
|
+
Gas.from(result.startGasLeft),
|
|
146
|
+
Gas.from(result.endGasLeft),
|
|
147
|
+
);
|
|
148
|
+
return new PublicCallRequest(item, result.startSideEffectCounter.toNumber());
|
|
149
|
+
}
|
package/src/public/executor.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { type PublicExecutionRequest } from '@aztec/circuit-types';
|
|
1
2
|
import { type AvmSimulationStats } from '@aztec/circuit-types/stats';
|
|
2
3
|
import { Fr, Gas, type GlobalVariables, type Header, type Nullifier, type TxContext } from '@aztec/circuits.js';
|
|
3
4
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
5
|
import { Timer } from '@aztec/foundation/timer';
|
|
6
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
5
7
|
|
|
6
8
|
import { AvmContext } from '../avm/avm_context.js';
|
|
7
9
|
import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
|
|
@@ -10,19 +12,25 @@ import { AvmSimulator } from '../avm/avm_simulator.js';
|
|
|
10
12
|
import { HostStorage } from '../avm/journal/host_storage.js';
|
|
11
13
|
import { AvmPersistableStateManager } from '../avm/journal/index.js';
|
|
12
14
|
import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db_interfaces.js';
|
|
13
|
-
import { type
|
|
15
|
+
import { type PublicExecutionResult } from './execution.js';
|
|
16
|
+
import { ExecutorMetrics } from './executor_metrics.js';
|
|
14
17
|
import { PublicSideEffectTrace } from './side_effect_trace.js';
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* Handles execution of public functions.
|
|
18
21
|
*/
|
|
19
22
|
export class PublicExecutor {
|
|
23
|
+
metrics: ExecutorMetrics;
|
|
24
|
+
|
|
20
25
|
constructor(
|
|
21
26
|
private readonly publicStorageDB: PublicStateDB,
|
|
22
27
|
private readonly contractsDb: PublicContractsDB,
|
|
23
28
|
private readonly commitmentsDb: CommitmentsDB,
|
|
24
29
|
private readonly header: Header,
|
|
25
|
-
|
|
30
|
+
client: TelemetryClient,
|
|
31
|
+
) {
|
|
32
|
+
this.metrics = new ExecutorMetrics(client, 'PublicExecutor');
|
|
33
|
+
}
|
|
26
34
|
|
|
27
35
|
static readonly log = createDebugLogger('aztec:simulator:public_executor');
|
|
28
36
|
|
|
@@ -47,7 +55,7 @@ export class PublicExecutor {
|
|
|
47
55
|
startSideEffectCounter: number = 0,
|
|
48
56
|
): Promise<PublicExecutionResult> {
|
|
49
57
|
const address = executionRequest.contractAddress;
|
|
50
|
-
const selector = executionRequest.functionSelector;
|
|
58
|
+
const selector = executionRequest.callContext.functionSelector;
|
|
51
59
|
const fnName = (await this.contractsDb.getDebugFunctionName(address, selector)) ?? `${address}:${selector}`;
|
|
52
60
|
|
|
53
61
|
PublicExecutor.log.verbose(`[AVM] Executing public external function ${fnName}.`);
|
|
@@ -101,6 +109,12 @@ export class PublicExecutor {
|
|
|
101
109
|
fnName,
|
|
102
110
|
);
|
|
103
111
|
|
|
112
|
+
if (publicExecutionResult.reverted) {
|
|
113
|
+
this.metrics.recordFunctionSimulationFailure();
|
|
114
|
+
} else {
|
|
115
|
+
this.metrics.recordFunctionSimulation(bytecode.length, timer.ms());
|
|
116
|
+
}
|
|
117
|
+
|
|
104
118
|
return publicExecutionResult;
|
|
105
119
|
}
|
|
106
120
|
}
|
|
@@ -122,7 +136,7 @@ function createAvmExecutionEnvironment(
|
|
|
122
136
|
executionRequest.contractAddress,
|
|
123
137
|
executionRequest.callContext.storageContractAddress,
|
|
124
138
|
executionRequest.callContext.msgSender,
|
|
125
|
-
executionRequest.functionSelector,
|
|
139
|
+
executionRequest.callContext.functionSelector,
|
|
126
140
|
/*contractCallDepth=*/ Fr.zero(),
|
|
127
141
|
transactionFee,
|
|
128
142
|
header,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Attributes,
|
|
3
|
+
type Histogram,
|
|
4
|
+
Metrics,
|
|
5
|
+
type TelemetryClient,
|
|
6
|
+
type UpDownCounter,
|
|
7
|
+
ValueType,
|
|
8
|
+
} from '@aztec/telemetry-client';
|
|
9
|
+
|
|
10
|
+
export class ExecutorMetrics {
|
|
11
|
+
private fnCount: UpDownCounter;
|
|
12
|
+
private fnDuration: Histogram;
|
|
13
|
+
private bytecodeSize: Histogram;
|
|
14
|
+
|
|
15
|
+
constructor(client: TelemetryClient, name = 'PublicExecutor') {
|
|
16
|
+
const meter = client.getMeter(name);
|
|
17
|
+
|
|
18
|
+
this.fnCount = meter.createUpDownCounter(Metrics.PUBLIC_EXECUTOR_SIMULATION_COUNT, {
|
|
19
|
+
description: 'Number of functions executed',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
this.fnDuration = meter.createHistogram(Metrics.PUBLIC_EXECUTOR_SIMULATION_DURATION, {
|
|
23
|
+
description: 'How long it takes to execute a function',
|
|
24
|
+
unit: 'ms',
|
|
25
|
+
valueType: ValueType.INT,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
this.bytecodeSize = meter.createHistogram(Metrics.PUBLIC_EXECUTION_SIMULATION_BYTECODE_SIZE, {
|
|
29
|
+
description: 'Size of the function bytecode',
|
|
30
|
+
unit: 'By',
|
|
31
|
+
valueType: ValueType.INT,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
recordFunctionSimulation(bytecodeSize: number, durationMs: number) {
|
|
36
|
+
this.fnCount.add(1, {
|
|
37
|
+
[Attributes.OK]: true,
|
|
38
|
+
});
|
|
39
|
+
this.bytecodeSize.record(bytecodeSize);
|
|
40
|
+
this.fnDuration.record(Math.ceil(durationMs));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
recordFunctionSimulationFailure() {
|
|
44
|
+
this.fnCount.add(1, {
|
|
45
|
+
[Attributes.OK]: false,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash';
|
|
1
|
+
import { FEE_JUICE_ADDRESS } from '@aztec/circuits.js';
|
|
2
|
+
import { computePublicDataTreeLeafSlot, deriveStorageSlotInMap } from '@aztec/circuits.js/hash';
|
|
3
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import { computeSlotForMapping } from '../utils.js';
|
|
5
|
+
import { FeeJuiceArtifact } from '@aztec/protocol-contracts/fee-juice';
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
|
-
* Computes the storage slot within the
|
|
8
|
+
* Computes the storage slot within the Fee Juice contract for the balance of the fee payer.
|
|
11
9
|
*/
|
|
12
10
|
export function computeFeePayerBalanceStorageSlot(feePayer: AztecAddress) {
|
|
13
|
-
return
|
|
11
|
+
return deriveStorageSlotInMap(FeeJuiceArtifact.storageLayout.balances.slot, feePayer);
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
/**
|
|
17
|
-
* Computes the leaf slot in the public data tree for the balance of the fee payer in the
|
|
15
|
+
* Computes the leaf slot in the public data tree for the balance of the fee payer in the Fee Juice.
|
|
18
16
|
*/
|
|
19
17
|
export function computeFeePayerBalanceLeafSlot(feePayer: AztecAddress): Fr {
|
|
20
18
|
if (feePayer.isZero()) {
|
|
21
19
|
return Fr.ZERO;
|
|
22
20
|
}
|
|
23
|
-
const
|
|
21
|
+
const feeJuice = AztecAddress.fromBigInt(FEE_JUICE_ADDRESS);
|
|
24
22
|
const balanceSlot = computeFeePayerBalanceStorageSlot(feePayer);
|
|
25
|
-
return computePublicDataTreeLeafSlot(
|
|
23
|
+
return computePublicDataTreeLeafSlot(feeJuice, balanceSlot);
|
|
26
24
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MerkleTreeId } from '@aztec/circuit-types';
|
|
1
|
+
import { type IndexedTreeId, MerkleTreeId } from '@aztec/circuit-types';
|
|
2
2
|
import {
|
|
3
3
|
type Fr,
|
|
4
4
|
type MAX_NULLIFIERS_PER_TX,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
buildSiloedNullifierReadRequestHints,
|
|
24
24
|
} from '@aztec/circuits.js';
|
|
25
25
|
import { type Tuple } from '@aztec/foundation/serialize';
|
|
26
|
-
import { type
|
|
26
|
+
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
27
27
|
|
|
28
28
|
export class HintsBuilder {
|
|
29
29
|
constructor(private db: MerkleTreeOperations) {}
|
package/src/public/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from './abstract_phase_manager.js';
|
|
2
2
|
export * from './db_interfaces.js';
|
|
3
|
-
export { isPublicExecutionResult, type
|
|
3
|
+
export { isPublicExecutionResult, type PublicExecutionResult } from './execution.js';
|
|
4
4
|
export { PublicExecutor } from './executor.js';
|
|
5
5
|
export * from './fee_payment.js';
|
|
6
6
|
export { HintsBuilder } from './hints_builder.js';
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
} from '@aztec/circuit-types';
|
|
14
14
|
import {
|
|
15
15
|
AztecAddress,
|
|
16
|
-
|
|
16
|
+
ContractClassRegisteredEvent,
|
|
17
|
+
FEE_JUICE_ADDRESS,
|
|
17
18
|
type GlobalVariables,
|
|
18
19
|
type Header,
|
|
19
20
|
type KernelCircuitPublicInputs,
|
|
@@ -23,7 +24,9 @@ import {
|
|
|
23
24
|
} from '@aztec/circuits.js';
|
|
24
25
|
import { times } from '@aztec/foundation/collection';
|
|
25
26
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
27
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
26
28
|
import { type ProtocolArtifact } from '@aztec/noir-protocol-circuits-types';
|
|
29
|
+
import { ClassRegistererAddress } from '@aztec/protocol-contracts/class-registerer';
|
|
27
30
|
import {
|
|
28
31
|
PublicExecutor,
|
|
29
32
|
type PublicStateDB,
|
|
@@ -40,6 +43,7 @@ import { PhaseManagerFactory } from './phase_manager_factory.js';
|
|
|
40
43
|
import { ContractsDataSourcePublicDB, WorldStateDB, WorldStatePublicDB } from './public_db_sources.js';
|
|
41
44
|
import { RealPublicKernelCircuitSimulator } from './public_kernel.js';
|
|
42
45
|
import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js';
|
|
46
|
+
import { PublicProcessorMetrics } from './public_processor_metrics.js';
|
|
43
47
|
|
|
44
48
|
/**
|
|
45
49
|
* Creates new instances of PublicProcessor given the provided merkle tree db and contract data source.
|
|
@@ -56,18 +60,24 @@ export class PublicProcessorFactory {
|
|
|
56
60
|
* Creates a new instance of a PublicProcessor.
|
|
57
61
|
* @param historicalHeader - The header of a block previous to the one in which the tx is included.
|
|
58
62
|
* @param globalVariables - The global variables for the block being processed.
|
|
59
|
-
* @param newContracts - Provides access to contract bytecode for public executions.
|
|
60
63
|
* @returns A new instance of a PublicProcessor.
|
|
61
64
|
*/
|
|
62
|
-
public create(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
public create(maybeHistoricalHeader: Header | undefined, globalVariables: GlobalVariables): PublicProcessor {
|
|
66
|
+
const { merkleTree, telemetryClient } = this;
|
|
67
|
+
const historicalHeader = maybeHistoricalHeader ?? merkleTree.getInitialHeader();
|
|
65
68
|
const publicContractsDB = new ContractsDataSourcePublicDB(this.contractDataSource);
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
+
|
|
70
|
+
const worldStatePublicDB = new WorldStatePublicDB(merkleTree);
|
|
71
|
+
const worldStateDB = new WorldStateDB(merkleTree);
|
|
72
|
+
const publicExecutor = new PublicExecutor(
|
|
73
|
+
worldStatePublicDB,
|
|
74
|
+
publicContractsDB,
|
|
75
|
+
worldStateDB,
|
|
76
|
+
historicalHeader,
|
|
77
|
+
telemetryClient,
|
|
78
|
+
);
|
|
69
79
|
return new PublicProcessor(
|
|
70
|
-
|
|
80
|
+
merkleTree,
|
|
71
81
|
publicExecutor,
|
|
72
82
|
new RealPublicKernelCircuitSimulator(this.simulator),
|
|
73
83
|
globalVariables,
|
|
@@ -84,7 +94,7 @@ export class PublicProcessorFactory {
|
|
|
84
94
|
* any public function calls in them. Txs with private calls only are unaffected.
|
|
85
95
|
*/
|
|
86
96
|
export class PublicProcessor {
|
|
87
|
-
|
|
97
|
+
private metrics: PublicProcessorMetrics;
|
|
88
98
|
constructor(
|
|
89
99
|
protected db: MerkleTreeOperations,
|
|
90
100
|
protected publicExecutor: PublicExecutor,
|
|
@@ -96,7 +106,11 @@ export class PublicProcessor {
|
|
|
96
106
|
telemetryClient: TelemetryClient,
|
|
97
107
|
private log = createDebugLogger('aztec:sequencer:public-processor'),
|
|
98
108
|
) {
|
|
99
|
-
this.
|
|
109
|
+
this.metrics = new PublicProcessorMetrics(telemetryClient, 'PublicProcessor');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
get tracer(): Tracer {
|
|
113
|
+
return this.metrics.tracer;
|
|
100
114
|
}
|
|
101
115
|
|
|
102
116
|
/**
|
|
@@ -188,12 +202,12 @@ export class PublicProcessor {
|
|
|
188
202
|
return finalPublicDataUpdateRequests;
|
|
189
203
|
}
|
|
190
204
|
|
|
191
|
-
const
|
|
205
|
+
const feeJuiceAddress = AztecAddress.fromBigInt(FEE_JUICE_ADDRESS);
|
|
192
206
|
const balanceSlot = computeFeePayerBalanceStorageSlot(feePayer);
|
|
193
207
|
const leafSlot = computeFeePayerBalanceLeafSlot(feePayer);
|
|
194
208
|
const txFee = tx.data.getTransactionFee(this.globalVariables.gasFees);
|
|
195
209
|
|
|
196
|
-
this.log.debug(`Deducting ${txFee} balance in
|
|
210
|
+
this.log.debug(`Deducting ${txFee} balance in Fee Juice for ${feePayer}`);
|
|
197
211
|
|
|
198
212
|
const existingBalanceWriteIndex = finalPublicDataUpdateRequests.findIndex(request =>
|
|
199
213
|
request.leafSlot.equals(leafSlot),
|
|
@@ -202,14 +216,14 @@ export class PublicProcessor {
|
|
|
202
216
|
const balance =
|
|
203
217
|
existingBalanceWriteIndex > -1
|
|
204
218
|
? finalPublicDataUpdateRequests[existingBalanceWriteIndex].newValue
|
|
205
|
-
: await this.publicStateDB.storageRead(
|
|
219
|
+
: await this.publicStateDB.storageRead(feeJuiceAddress, balanceSlot);
|
|
206
220
|
|
|
207
221
|
if (balance.lt(txFee)) {
|
|
208
222
|
throw new Error(`Not enough balance for fee payer to pay for transaction (got ${balance} needs ${txFee})`);
|
|
209
223
|
}
|
|
210
224
|
|
|
211
225
|
const updatedBalance = balance.sub(txFee);
|
|
212
|
-
await this.publicStateDB.storageWrite(
|
|
226
|
+
await this.publicStateDB.storageWrite(feeJuiceAddress, balanceSlot, updatedBalance);
|
|
213
227
|
|
|
214
228
|
finalPublicDataUpdateRequests[
|
|
215
229
|
existingBalanceWriteIndex > -1 ? existingBalanceWriteIndex : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
|
|
@@ -222,6 +236,7 @@ export class PublicProcessor {
|
|
|
222
236
|
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
223
237
|
}))
|
|
224
238
|
private async processTxWithPublicCalls(tx: Tx): Promise<[ProcessedTx, NestedProcessReturnValues[]]> {
|
|
239
|
+
const timer = new Timer();
|
|
225
240
|
let returnValues: NestedProcessReturnValues[] = [];
|
|
226
241
|
const publicProvingRequests: PublicProvingRequest[] = [];
|
|
227
242
|
let phase: AbstractPhaseManager | undefined = PhaseManagerFactory.phaseFromTx(
|
|
@@ -240,8 +255,18 @@ export class PublicProcessor {
|
|
|
240
255
|
let finalKernelOutput: KernelCircuitPublicInputs | undefined;
|
|
241
256
|
let revertReason: SimulationError | undefined;
|
|
242
257
|
const gasUsed: ProcessedTx['gasUsed'] = {};
|
|
258
|
+
let phaseCount = 0;
|
|
243
259
|
while (phase) {
|
|
260
|
+
phaseCount++;
|
|
261
|
+
const phaseTimer = new Timer();
|
|
244
262
|
const output = await phase.handle(tx, publicKernelPublicInput, lastKernelArtifact);
|
|
263
|
+
|
|
264
|
+
if (output.revertReason) {
|
|
265
|
+
this.metrics.recordRevertedPhase(phase.phase);
|
|
266
|
+
} else {
|
|
267
|
+
this.metrics.recordPhaseDuration(phase.phase, phaseTimer.ms());
|
|
268
|
+
}
|
|
269
|
+
|
|
245
270
|
gasUsed[phase.phase] = output.gasUsed;
|
|
246
271
|
if (phase.phase === PublicKernelType.APP_LOGIC) {
|
|
247
272
|
returnValues = output.returnValues;
|
|
@@ -265,9 +290,15 @@ export class PublicProcessor {
|
|
|
265
290
|
}
|
|
266
291
|
|
|
267
292
|
if (!finalKernelOutput) {
|
|
293
|
+
this.metrics.recordFailedTx();
|
|
268
294
|
throw new Error('Final public kernel was not executed.');
|
|
269
295
|
}
|
|
270
296
|
|
|
297
|
+
this.metrics.recordClassRegistration(
|
|
298
|
+
...ContractClassRegisteredEvent.fromLogs(tx.unencryptedLogs.unrollLogs(), ClassRegistererAddress),
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
this.metrics.recordTx(phaseCount, timer.ms());
|
|
271
302
|
const processedTx = makeProcessedTx(tx, finalKernelOutput, publicProvingRequests, revertReason, gasUsed);
|
|
272
303
|
return [processedTx, returnValues];
|
|
273
304
|
}
|