@aztec/simulator 0.82.2-alpha-testnet.4 → 0.82.3
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/README.md +6 -0
- package/dest/private/acvm/oracle/oracle.d.ts +1 -1
- package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/oracle.js +1 -3
- package/dest/public/avm/avm_contract_call_result.d.ts +4 -2
- package/dest/public/avm/avm_contract_call_result.d.ts.map +1 -1
- package/dest/public/avm/avm_contract_call_result.js +9 -5
- package/dest/public/avm/avm_machine_state.d.ts +2 -0
- package/dest/public/avm/avm_machine_state.d.ts.map +1 -1
- package/dest/public/avm/avm_machine_state.js +2 -0
- package/dest/public/avm/avm_simulator.d.ts.map +1 -1
- package/dest/public/avm/avm_simulator.js +5 -6
- package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/avm_simulation_tester.js +1 -2
- package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts +1 -2
- package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/base_avm_simulation_tester.js +0 -5
- package/dest/public/avm/fixtures/index.d.ts +1 -0
- package/dest/public/avm/fixtures/index.d.ts.map +1 -1
- package/dest/public/avm/fixtures/index.js +1 -1
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts +3 -2
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts.map +1 -1
- package/dest/public/avm/fixtures/simple_contract_data_source.js +30 -6
- package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/public/avm/opcodes/external_calls.js +2 -0
- package/dest/public/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/public/avm/opcodes/memory.js +8 -10
- package/dest/public/avm/serialization/instruction_serialization.d.ts +5 -2
- package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/public/avm/serialization/instruction_serialization.js +23 -3
- package/dest/public/executor_metrics.d.ts +11 -3
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +40 -6
- package/dest/public/executor_metrics_interface.d.ts +10 -0
- package/dest/public/executor_metrics_interface.d.ts.map +1 -0
- package/dest/public/executor_metrics_interface.js +1 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +12 -6
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +39 -19
- package/dest/public/hinting_db_sources.d.ts +26 -3
- package/dest/public/hinting_db_sources.d.ts.map +1 -1
- package/dest/public/hinting_db_sources.js +102 -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_db_sources.d.ts +2 -3
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +26 -16
- package/dest/public/public_processor/public_processor.d.ts +1 -1
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +3 -3
- package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts +9 -0
- package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/apps_tests/amm_test.js +237 -0
- package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts +7 -0
- package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/apps_tests/token_test.js +109 -0
- package/dest/public/public_tx_simulator/index.d.ts +3 -0
- package/dest/public/public_tx_simulator/index.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/index.js +2 -0
- package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts +23 -0
- package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/measured_public_tx_simulator.js +58 -0
- package/dest/public/public_tx_simulator/public_tx_context.d.ts +2 -2
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +9 -7
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +16 -16
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_simulator.js +24 -64
- package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts +19 -0
- package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.js +39 -0
- package/dest/public/test_executor_metrics.d.ts +43 -0
- package/dest/public/test_executor_metrics.d.ts.map +1 -0
- package/dest/public/test_executor_metrics.js +158 -0
- package/package.json +14 -14
- package/src/private/acvm/oracle/oracle.ts +2 -2
- package/src/public/avm/avm_contract_call_result.ts +15 -3
- package/src/public/avm/avm_machine_state.ts +5 -0
- package/src/public/avm/avm_simulator.ts +18 -7
- package/src/public/avm/fixtures/avm_simulation_tester.ts +1 -1
- package/src/public/avm/fixtures/base_avm_simulation_tester.ts +1 -7
- package/src/public/avm/fixtures/index.ts +1 -1
- package/src/public/avm/fixtures/simple_contract_data_source.ts +33 -6
- package/src/public/avm/opcodes/external_calls.ts +3 -0
- package/src/public/avm/opcodes/memory.ts +8 -10
- package/src/public/avm/serialization/instruction_serialization.ts +22 -5
- package/src/public/executor_metrics.ts +54 -6
- package/src/public/executor_metrics_interface.ts +15 -0
- package/src/public/fixtures/public_tx_simulation_tester.ts +74 -18
- package/src/public/hinting_db_sources.ts +184 -3
- package/src/public/index.ts +1 -1
- package/src/public/public_db_sources.ts +36 -23
- package/src/public/public_processor/public_processor.ts +4 -4
- package/src/public/public_tx_simulator/apps_tests/amm_test.ts +316 -0
- package/src/public/public_tx_simulator/apps_tests/token_test.ts +138 -0
- package/src/public/public_tx_simulator/index.ts +2 -0
- package/src/public/public_tx_simulator/measured_public_tx_simulator.ts +111 -0
- package/src/public/public_tx_simulator/public_tx_context.ts +9 -13
- package/src/public/public_tx_simulator/public_tx_simulator.ts +31 -76
- package/src/public/public_tx_simulator/telemetry_public_tx_simulator.ts +62 -0
- package/src/public/test_executor_metrics.ts +222 -0
|
@@ -12,7 +12,7 @@ import { TreeSnapshots, TxExecutionPhase } from '@aztec/stdlib/tx';
|
|
|
12
12
|
import { strict as assert } from 'assert';
|
|
13
13
|
import { inspect } from 'util';
|
|
14
14
|
import { AvmPersistableStateManager } from '../avm/index.js';
|
|
15
|
-
import { HintingPublicContractsDB } from '../hinting_db_sources.js';
|
|
15
|
+
import { HintingPublicContractsDB, HintingPublicTreesDB } from '../hinting_db_sources.js';
|
|
16
16
|
import { SideEffectArrayLengths, SideEffectTrace } from '../side_effect_trace.js';
|
|
17
17
|
import { getCallRequestsWithCalldataByPhase } from '../utils.js';
|
|
18
18
|
/**
|
|
@@ -69,9 +69,9 @@ import { getCallRequestsWithCalldataByPhase } from '../utils.js';
|
|
|
69
69
|
// We wrap the DB to collect AVM hints.
|
|
70
70
|
const hints = new AvmExecutionHints();
|
|
71
71
|
const hintingContractsDB = new HintingPublicContractsDB(contractsDB, hints);
|
|
72
|
-
|
|
72
|
+
const hintingTreesDB = new HintingPublicTreesDB(treesDB, hints);
|
|
73
73
|
// Transaction level state manager that will be forked for revertible phases.
|
|
74
|
-
const txStateManager = AvmPersistableStateManager.create(
|
|
74
|
+
const txStateManager = AvmPersistableStateManager.create(hintingTreesDB, hintingContractsDB, trace, doMerkleOperations, firstNullifier, globalVariables.blockNumber.toNumber());
|
|
75
75
|
const gasSettings = tx.data.constants.txContext.gasSettings;
|
|
76
76
|
const gasUsedByPrivate = tx.data.gasUsed;
|
|
77
77
|
// Gas allocated to public is "whatever's left" after private, but with some max applied.
|
|
@@ -215,13 +215,15 @@ import { getCallRequestsWithCalldataByPhase } from '../utils.js';
|
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
217
|
* Generate the public inputs for the AVM circuit.
|
|
218
|
-
*/ async generateAvmCircuitPublicInputs(
|
|
218
|
+
*/ async generateAvmCircuitPublicInputs() {
|
|
219
219
|
assert(this.halted, 'Can only get AvmCircuitPublicInputs after tx execution ends');
|
|
220
220
|
const stateManager = this.state.getActiveStateManager();
|
|
221
221
|
const startTreeSnapshots = new TreeSnapshots(this.startStateReference.l1ToL2MessageTree, this.startStateReference.partial.noteHashTree, this.startStateReference.partial.nullifierTree, this.startStateReference.partial.publicDataTree);
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
// FIXME: We are first creating the PIs with the wrong endTreeSnapshots, then patching them.
|
|
223
|
+
// This is because we need to know the lengths of the accumulated data arrays to pad them.
|
|
224
|
+
// We should refactor this to avoid this hack.
|
|
225
|
+
// We should just get the info we need from the trace, and create the rest of the PIs here.
|
|
226
|
+
const avmCircuitPublicInputs = this.trace.toAvmCircuitPublicInputs(this.globalVariables, startTreeSnapshots, /*startGasUsed=*/ this.gasUsedByPrivate, this.gasSettings, this.feePayer, this.setupCallRequests.map((r)=>r.request), this.appLogicCallRequests.map((r)=>r.request), /*teardownCallRequest=*/ this.teardownCallRequests.length ? this.teardownCallRequests[0].request : PublicCallRequest.empty(), /*endTreeSnapshots=*/ TreeSnapshots.empty(), /*endGasUsed=*/ this.getTotalGasUsed(), /*transactionFee=*/ this.getTransactionFeeUnsafe(), /*reverted=*/ !this.revertCode.isOK());
|
|
225
227
|
const getArrayLengths = (from)=>new PrivateToAvmAccumulatedDataArrayLengths(countAccumulatedItems(from.noteHashes), countAccumulatedItems(from.nullifiers), countAccumulatedItems(from.l2ToL1Msgs));
|
|
226
228
|
const convertAccumulatedData = (from)=>new PrivateToAvmAccumulatedData(from.noteHashes, from.nullifiers, from.l2ToL1Msgs);
|
|
227
229
|
// Temporary overrides as these entries aren't yet populated in trace
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { type Logger } from '@aztec/foundation/log';
|
|
1
3
|
import { type AvmProvingRequest, type RevertCode } from '@aztec/stdlib/avm';
|
|
2
4
|
import { SimulationError } from '@aztec/stdlib/errors';
|
|
3
|
-
import type { GasUsed } from '@aztec/stdlib/gas';
|
|
4
|
-
import { type GlobalVariables, NestedProcessReturnValues, Tx, TxExecutionPhase } from '@aztec/stdlib/tx';
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
5
|
+
import type { Gas, GasUsed } from '@aztec/stdlib/gas';
|
|
6
|
+
import { type GlobalVariables, NestedProcessReturnValues, PublicCallRequestWithCalldata, Tx, TxExecutionPhase } from '@aztec/stdlib/tx';
|
|
7
|
+
import type { AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js';
|
|
8
|
+
import { type AvmPersistableStateManager } from '../avm/index.js';
|
|
7
9
|
import type { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
|
|
8
10
|
import { PublicTxContext } from './public_tx_context.js';
|
|
9
11
|
export type ProcessedPhase = {
|
|
10
12
|
phase: TxExecutionPhase;
|
|
11
|
-
durationMs
|
|
13
|
+
durationMs?: number;
|
|
12
14
|
returnValues: NestedProcessReturnValues[];
|
|
13
15
|
reverted: boolean;
|
|
14
16
|
revertReason?: SimulationError;
|
|
@@ -24,20 +26,19 @@ export type PublicTxResult = {
|
|
|
24
26
|
};
|
|
25
27
|
export declare class PublicTxSimulator {
|
|
26
28
|
private treesDB;
|
|
27
|
-
|
|
29
|
+
protected contractsDB: PublicContractsDB;
|
|
28
30
|
private globalVariables;
|
|
29
31
|
private doMerkleOperations;
|
|
30
32
|
private skipFeeEnforcement;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
constructor(treesDB: PublicTreesDB, contractsDB: PublicContractsDB, globalVariables: GlobalVariables, doMerkleOperations?: boolean, skipFeeEnforcement?: boolean, telemetryClient?: TelemetryClient);
|
|
34
|
-
get tracer(): Tracer;
|
|
33
|
+
protected log: Logger;
|
|
34
|
+
constructor(treesDB: PublicTreesDB, contractsDB: PublicContractsDB, globalVariables: GlobalVariables, doMerkleOperations?: boolean, skipFeeEnforcement?: boolean);
|
|
35
35
|
/**
|
|
36
36
|
* Simulate a transaction's public portion including all of its phases.
|
|
37
37
|
* @param tx - The transaction to simulate.
|
|
38
38
|
* @returns The result of the transaction's public execution.
|
|
39
39
|
*/
|
|
40
40
|
simulate(tx: Tx): Promise<PublicTxResult>;
|
|
41
|
+
protected computeTxHash(tx: Tx): Promise<import("@aztec/stdlib/tx").TxHash>;
|
|
41
42
|
/**
|
|
42
43
|
* Simulate the setup phase of a transaction's public execution.
|
|
43
44
|
* @param context - WILL BE MUTATED. The context of the currently executing public transaction portion
|
|
@@ -62,7 +63,7 @@ export declare class PublicTxSimulator {
|
|
|
62
63
|
* @param context - WILL BE MUTATED. The context of the currently executing public transaction portion
|
|
63
64
|
* @returns The phase result.
|
|
64
65
|
*/
|
|
65
|
-
|
|
66
|
+
protected simulatePhase(phase: TxExecutionPhase, context: PublicTxContext): Promise<ProcessedPhase>;
|
|
66
67
|
/**
|
|
67
68
|
* Simulate an enqueued public call.
|
|
68
69
|
* @param phase - The current phase of public execution
|
|
@@ -70,7 +71,7 @@ export declare class PublicTxSimulator {
|
|
|
70
71
|
* @param callRequest - The public function call request, including the calldata.
|
|
71
72
|
* @returns The result of execution.
|
|
72
73
|
*/
|
|
73
|
-
|
|
74
|
+
protected simulateEnqueuedCall(phase: TxExecutionPhase, context: PublicTxContext, callRequest: PublicCallRequestWithCalldata): Promise<AvmFinalizedCallResult>;
|
|
74
75
|
/**
|
|
75
76
|
* Simulate an enqueued public call, without modifying the context (PublicTxContext).
|
|
76
77
|
* Resulting modifications to the context can be applied by the caller.
|
|
@@ -79,22 +80,21 @@ export declare class PublicTxSimulator {
|
|
|
79
80
|
* while still simulating phases and generating a proving request.
|
|
80
81
|
*
|
|
81
82
|
* @param stateManager - The state manager for AvmSimulation
|
|
82
|
-
* @param context - The context of the currently executing public transaction portion
|
|
83
83
|
* @param callRequest - The public function call request, including the calldata.
|
|
84
84
|
* @param allocatedGas - The gas allocated to the enqueued call
|
|
85
85
|
* @param fnName - The name of the function
|
|
86
86
|
* @returns The result of execution.
|
|
87
87
|
*/
|
|
88
|
-
|
|
88
|
+
protected simulateEnqueuedCallInternal(stateManager: AvmPersistableStateManager, { request, calldata }: PublicCallRequestWithCalldata, allocatedGas: Gas, transactionFee: Fr, fnName: string): Promise<AvmFinalizedCallResult>;
|
|
89
89
|
/**
|
|
90
90
|
* Insert the non-revertible accumulated data from private into the public state.
|
|
91
91
|
*/
|
|
92
|
-
insertNonRevertiblesFromPrivate(context: PublicTxContext): Promise<void>;
|
|
92
|
+
protected insertNonRevertiblesFromPrivate(context: PublicTxContext, tx: Tx): Promise<void>;
|
|
93
93
|
/**
|
|
94
94
|
* Insert the revertible accumulated data from private into the public state.
|
|
95
95
|
* Start by forking state so we can rollback to the end of setup if app logic or teardown reverts.
|
|
96
96
|
*/
|
|
97
|
-
insertRevertiblesFromPrivate(context: PublicTxContext): Promise<boolean>;
|
|
97
|
+
protected insertRevertiblesFromPrivate(context: PublicTxContext, tx: Tx): Promise<boolean>;
|
|
98
98
|
private payFee;
|
|
99
99
|
/**
|
|
100
100
|
* Generate the proving request for the AVM circuit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public_tx_simulator.d.ts","sourceRoot":"","sources":["../../../src/public/public_tx_simulator/public_tx_simulator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"public_tx_simulator.d.ts","sourceRoot":"","sources":["../../../src/public/public_tx_simulator/public_tx_simulator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
}
|
|
7
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
|
-
import { Timer } from '@aztec/foundation/timer';
|
|
9
2
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
10
3
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
11
4
|
import { AvmCircuitInputs, AvmEnqueuedCallHint } from '@aztec/stdlib/avm';
|
|
12
5
|
import { SimulationError } from '@aztec/stdlib/errors';
|
|
13
6
|
import { ProvingRequestType } from '@aztec/stdlib/proofs';
|
|
14
7
|
import { NestedProcessReturnValues, TxExecutionPhase } from '@aztec/stdlib/tx';
|
|
15
|
-
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
16
8
|
import { strict as assert } from 'assert';
|
|
17
9
|
import { getPublicFunctionDebugName } from '../../common/debug_fn_name.js';
|
|
18
10
|
import { AvmSimulator } from '../avm/index.js';
|
|
19
11
|
import { NullifierCollisionError } from '../avm/journal/nullifiers.js';
|
|
20
|
-
import { ExecutorMetrics } from '../executor_metrics.js';
|
|
21
12
|
import { PublicTxContext } from './public_tx_context.js';
|
|
22
13
|
export class PublicTxSimulator {
|
|
23
14
|
treesDB;
|
|
@@ -25,19 +16,14 @@ export class PublicTxSimulator {
|
|
|
25
16
|
globalVariables;
|
|
26
17
|
doMerkleOperations;
|
|
27
18
|
skipFeeEnforcement;
|
|
28
|
-
metrics;
|
|
29
19
|
log;
|
|
30
|
-
constructor(treesDB, contractsDB, globalVariables, doMerkleOperations = false, skipFeeEnforcement = false
|
|
20
|
+
constructor(treesDB, contractsDB, globalVariables, doMerkleOperations = false, skipFeeEnforcement = false){
|
|
31
21
|
this.treesDB = treesDB;
|
|
32
22
|
this.contractsDB = contractsDB;
|
|
33
23
|
this.globalVariables = globalVariables;
|
|
34
24
|
this.doMerkleOperations = doMerkleOperations;
|
|
35
25
|
this.skipFeeEnforcement = skipFeeEnforcement;
|
|
36
26
|
this.log = createLogger(`simulator:public_tx_simulator`);
|
|
37
|
-
this.metrics = new ExecutorMetrics(telemetryClient, 'PublicTxSimulator');
|
|
38
|
-
}
|
|
39
|
-
get tracer() {
|
|
40
|
-
return this.metrics.tracer;
|
|
41
27
|
}
|
|
42
28
|
/**
|
|
43
29
|
* Simulate a transaction's public portion including all of its phases.
|
|
@@ -45,31 +31,19 @@ export class PublicTxSimulator {
|
|
|
45
31
|
* @returns The result of the transaction's public execution.
|
|
46
32
|
*/ async simulate(tx) {
|
|
47
33
|
try {
|
|
48
|
-
const
|
|
49
|
-
const txHash = await tx.getTxHash();
|
|
34
|
+
const txHash = await this.computeTxHash(tx);
|
|
50
35
|
this.log.debug(`Simulating ${tx.publicFunctionCalldata.length} public calls for tx ${txHash}`, {
|
|
51
36
|
txHash
|
|
52
37
|
});
|
|
53
38
|
const context = await PublicTxContext.create(this.treesDB, this.contractsDB, tx, this.globalVariables, this.doMerkleOperations);
|
|
54
|
-
|
|
55
|
-
await this.insertNonRevertiblesFromPrivate(context);
|
|
56
|
-
// add new contracts to the contracts db so that their functions may be found and called
|
|
57
|
-
// TODO(#6464): Should we allow emitting contracts in the private setup phase?
|
|
58
|
-
await this.contractsDB.addNewNonRevertibleContracts(tx);
|
|
59
|
-
const nonRevertEnd = process.hrtime.bigint();
|
|
60
|
-
this.metrics.recordPrivateEffectsInsertion(Number(nonRevertEnd - nonRevertStart) / 1_000, 'non-revertible');
|
|
39
|
+
await this.insertNonRevertiblesFromPrivate(context, tx);
|
|
61
40
|
const processedPhases = [];
|
|
62
41
|
if (context.hasPhase(TxExecutionPhase.SETUP)) {
|
|
63
42
|
const setupResult = await this.simulateSetupPhase(context);
|
|
64
43
|
processedPhases.push(setupResult);
|
|
65
44
|
}
|
|
66
|
-
const
|
|
67
|
-
const success = await this.insertRevertiblesFromPrivate(context);
|
|
45
|
+
const success = await this.insertRevertiblesFromPrivate(context, tx);
|
|
68
46
|
if (success) {
|
|
69
|
-
// add new contracts to the contracts db so that their functions may be found and called
|
|
70
|
-
await this.contractsDB.addNewRevertibleContracts(tx);
|
|
71
|
-
const revertEnd = process.hrtime.bigint();
|
|
72
|
-
this.metrics.recordPrivateEffectsInsertion(Number(revertEnd - revertStart) / 1_000, 'revertible');
|
|
73
47
|
// Only proceed with app logic if there was no revert during revertible insertion
|
|
74
48
|
if (context.hasPhase(TxExecutionPhase.APP_LOGIC)) {
|
|
75
49
|
const appLogicResult = await this.simulateAppLogicPhase(context);
|
|
@@ -84,7 +58,7 @@ export class PublicTxSimulator {
|
|
|
84
58
|
}
|
|
85
59
|
await context.halt();
|
|
86
60
|
await this.payFee(context);
|
|
87
|
-
const publicInputs = await context.generateAvmCircuitPublicInputs(
|
|
61
|
+
const publicInputs = await context.generateAvmCircuitPublicInputs();
|
|
88
62
|
const avmProvingRequest = PublicTxSimulator.generateProvingRequest(publicInputs, context.hints);
|
|
89
63
|
const revertCode = context.getFinalRevertCode();
|
|
90
64
|
if (!revertCode.isOK()) {
|
|
@@ -93,9 +67,9 @@ export class PublicTxSimulator {
|
|
|
93
67
|
// Commit contracts from this TX to the block-level cache and clear tx cache
|
|
94
68
|
// If the tx reverted, only commit non-revertible contracts
|
|
95
69
|
// NOTE: You can't create contracts in public, so this is only relevant for private-created contracts
|
|
70
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
71
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
96
72
|
this.contractsDB.commitContractsForTx(/*onlyNonRevertibles=*/ !revertCode.isOK());
|
|
97
|
-
const endTime = process.hrtime.bigint();
|
|
98
|
-
this.log.debug(`Public TX simulator took ${Number(endTime - startTime) / 1_000_000} ms\n`);
|
|
99
73
|
return {
|
|
100
74
|
avmProvingRequest,
|
|
101
75
|
gasUsed: {
|
|
@@ -111,9 +85,14 @@ export class PublicTxSimulator {
|
|
|
111
85
|
} finally{
|
|
112
86
|
// Make sure there are no new contracts in the tx-level cache.
|
|
113
87
|
// They should either be committed to block-level cache or cleared.
|
|
88
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
89
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
114
90
|
this.contractsDB.clearContractsForTx();
|
|
115
91
|
}
|
|
116
92
|
}
|
|
93
|
+
async computeTxHash(tx) {
|
|
94
|
+
return await tx.getTxHash();
|
|
95
|
+
}
|
|
117
96
|
/**
|
|
118
97
|
* Simulate the setup phase of a transaction's public execution.
|
|
119
98
|
* @param context - WILL BE MUTATED. The context of the currently executing public transaction portion
|
|
@@ -174,7 +153,6 @@ export class PublicTxSimulator {
|
|
|
174
153
|
const returnValues = [];
|
|
175
154
|
let reverted = false;
|
|
176
155
|
let revertReason;
|
|
177
|
-
const phaseTimer = new Timer();
|
|
178
156
|
for(let i = callRequests.length - 1; i >= 0; i--){
|
|
179
157
|
if (reverted) {
|
|
180
158
|
break;
|
|
@@ -189,7 +167,6 @@ export class PublicTxSimulator {
|
|
|
189
167
|
}
|
|
190
168
|
return {
|
|
191
169
|
phase,
|
|
192
|
-
durationMs: phaseTimer.ms(),
|
|
193
170
|
returnValues,
|
|
194
171
|
reverted,
|
|
195
172
|
revertReason
|
|
@@ -229,7 +206,6 @@ export class PublicTxSimulator {
|
|
|
229
206
|
* while still simulating phases and generating a proving request.
|
|
230
207
|
*
|
|
231
208
|
* @param stateManager - The state manager for AvmSimulation
|
|
232
|
-
* @param context - The context of the currently executing public transaction portion
|
|
233
209
|
* @param callRequest - The public function call request, including the calldata.
|
|
234
210
|
* @param allocatedGas - The gas allocated to the enqueued call
|
|
235
211
|
* @param fnName - The name of the function
|
|
@@ -238,25 +214,13 @@ export class PublicTxSimulator {
|
|
|
238
214
|
const address = request.contractAddress;
|
|
239
215
|
const sender = request.msgSender;
|
|
240
216
|
this.log.debug(`Executing enqueued public call to external function ${fnName}@${address} with ${allocatedGas.l2Gas} allocated L2 gas.`);
|
|
241
|
-
const timer = new Timer();
|
|
242
217
|
const simulator = await AvmSimulator.create(stateManager, address, sender, transactionFee, this.globalVariables, request.isStaticCall, calldata, allocatedGas);
|
|
243
218
|
const avmCallResult = await simulator.execute();
|
|
244
|
-
|
|
245
|
-
this.log.verbose(result.reverted ? `Simulation of enqueued public call ${fnName} reverted with reason ${result.revertReason}.` : `Simulation of enqueued public call ${fnName} completed successfully.`, {
|
|
246
|
-
eventName: 'avm-simulation',
|
|
247
|
-
appCircuitName: fnName,
|
|
248
|
-
duration: timer.ms()
|
|
249
|
-
});
|
|
250
|
-
if (result.reverted) {
|
|
251
|
-
this.metrics.recordFunctionSimulationFailure();
|
|
252
|
-
} else {
|
|
253
|
-
this.metrics.recordFunctionSimulation(timer.ms(), allocatedGas.sub(result.gasLeft).l2Gas, fnName);
|
|
254
|
-
}
|
|
255
|
-
return result;
|
|
219
|
+
return avmCallResult.finalize();
|
|
256
220
|
}
|
|
257
221
|
/**
|
|
258
222
|
* Insert the non-revertible accumulated data from private into the public state.
|
|
259
|
-
*/ async insertNonRevertiblesFromPrivate(context) {
|
|
223
|
+
*/ async insertNonRevertiblesFromPrivate(context, tx) {
|
|
260
224
|
const stateManager = context.state.getActiveStateManager();
|
|
261
225
|
try {
|
|
262
226
|
await stateManager.writeSiloedNullifiersFromPrivate(context.nonRevertibleAccumulatedDataFromPrivate.nullifiers);
|
|
@@ -270,11 +234,16 @@ export class PublicTxSimulator {
|
|
|
270
234
|
await stateManager.writeUniqueNoteHash(noteHash);
|
|
271
235
|
}
|
|
272
236
|
}
|
|
237
|
+
// add new contracts to the contracts db so that their functions may be found and called
|
|
238
|
+
// TODO(#6464): Should we allow emitting contracts in the private setup phase?
|
|
239
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
240
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
241
|
+
await this.contractsDB.addNewNonRevertibleContracts(tx);
|
|
273
242
|
}
|
|
274
243
|
/**
|
|
275
244
|
* Insert the revertible accumulated data from private into the public state.
|
|
276
245
|
* Start by forking state so we can rollback to the end of setup if app logic or teardown reverts.
|
|
277
|
-
*/ async insertRevertiblesFromPrivate(context) {
|
|
246
|
+
*/ async insertRevertiblesFromPrivate(context, tx) {
|
|
278
247
|
// Fork the state manager so we can rollback to end of setup if app logic reverts.
|
|
279
248
|
await context.state.fork();
|
|
280
249
|
const stateManager = context.state.getActiveStateManager();
|
|
@@ -295,6 +264,10 @@ export class PublicTxSimulator {
|
|
|
295
264
|
await stateManager.writeSiloedNoteHash(noteHash);
|
|
296
265
|
}
|
|
297
266
|
}
|
|
267
|
+
// add new contracts to the contracts db so that their functions may be found and called
|
|
268
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
269
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
270
|
+
await this.contractsDB.addNewRevertibleContracts(tx);
|
|
298
271
|
return /*success=*/ true;
|
|
299
272
|
}
|
|
300
273
|
async payFee(context) {
|
|
@@ -329,16 +302,3 @@ export class PublicTxSimulator {
|
|
|
329
302
|
};
|
|
330
303
|
}
|
|
331
304
|
}
|
|
332
|
-
_ts_decorate([
|
|
333
|
-
trackSpan('PublicTxSimulator.simulateEnqueuedCall', (phase, context, callRequest)=>({
|
|
334
|
-
[Attributes.TX_HASH]: context.txHash.toString(),
|
|
335
|
-
[Attributes.TARGET_ADDRESS]: callRequest.request.contractAddress.toString(),
|
|
336
|
-
[Attributes.SENDER_ADDRESS]: callRequest.request.msgSender.toString(),
|
|
337
|
-
[Attributes.SIMULATOR_PHASE]: TxExecutionPhase[phase].toString()
|
|
338
|
-
}))
|
|
339
|
-
], PublicTxSimulator.prototype, "simulateEnqueuedCall", null);
|
|
340
|
-
_ts_decorate([
|
|
341
|
-
trackSpan('PublicTxSimulator.simulateEnqueuedCallInternal', (_stateManager, _callRequest, _allocatedGas, _transactionFee, fnName)=>({
|
|
342
|
-
[Attributes.APP_CIRCUIT_NAME]: fnName
|
|
343
|
-
}))
|
|
344
|
-
], PublicTxSimulator.prototype, "simulateEnqueuedCallInternal", null);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import type { Gas } from '@aztec/stdlib/gas';
|
|
3
|
+
import { type GlobalVariables, PublicCallRequestWithCalldata, TxExecutionPhase } from '@aztec/stdlib/tx';
|
|
4
|
+
import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
|
|
5
|
+
import type { AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js';
|
|
6
|
+
import type { AvmPersistableStateManager } from '../avm/index.js';
|
|
7
|
+
import type { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
|
|
8
|
+
import { MeasuredPublicTxSimulator } from './measured_public_tx_simulator.js';
|
|
9
|
+
import { PublicTxContext } from './public_tx_context.js';
|
|
10
|
+
/**
|
|
11
|
+
* A public tx simulator that tracks runtime/production metrics with telemetry.
|
|
12
|
+
*/
|
|
13
|
+
export declare class TelemetryPublicTxSimulator extends MeasuredPublicTxSimulator {
|
|
14
|
+
readonly tracer: Tracer;
|
|
15
|
+
constructor(treesDB: PublicTreesDB, contractsDB: PublicContractsDB, globalVariables: GlobalVariables, doMerkleOperations?: boolean, skipFeeEnforcement?: boolean, telemetryClient?: TelemetryClient);
|
|
16
|
+
protected simulateEnqueuedCall(phase: TxExecutionPhase, context: PublicTxContext, callRequest: PublicCallRequestWithCalldata): Promise<AvmFinalizedCallResult>;
|
|
17
|
+
protected simulateEnqueuedCallInternal(stateManager: AvmPersistableStateManager, callRequest: PublicCallRequestWithCalldata, allocatedGas: Gas, transactionFee: Fr, fnName: string): Promise<AvmFinalizedCallResult>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=telemetry_public_tx_simulator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry_public_tx_simulator.d.ts","sourceRoot":"","sources":["../../../src/public/public_tx_simulator/telemetry_public_tx_simulator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,KAAK,eAAe,EAAE,6BAA6B,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzG,OAAO,EAAc,KAAK,eAAe,EAAE,KAAK,MAAM,EAAiC,MAAM,yBAAyB,CAAC;AAEvH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,qBAAa,0BAA2B,SAAQ,yBAAyB;IAEvE,SAAgB,MAAM,EAAE,MAAM,CAAC;gBAG7B,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,iBAAiB,EAC9B,eAAe,EAAE,eAAe,EAChC,kBAAkB,GAAE,OAAe,EACnC,kBAAkB,GAAE,OAAe,EACnC,eAAe,GAAE,eAAsC;cAahC,oBAAoB,CAC3C,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,6BAA6B,GACzC,OAAO,CAAC,sBAAsB,CAAC;cAUT,4BAA4B,CACnD,YAAY,EAAE,0BAA0B,EACxC,WAAW,EAAE,6BAA6B,EAC1C,YAAY,EAAE,GAAG,EACjB,cAAc,EAAE,EAAE,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,sBAAsB,CAAC;CAGnC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
import { TxExecutionPhase } from '@aztec/stdlib/tx';
|
|
8
|
+
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
9
|
+
import { ExecutorMetrics } from '../executor_metrics.js';
|
|
10
|
+
import { MeasuredPublicTxSimulator } from './measured_public_tx_simulator.js';
|
|
11
|
+
/**
|
|
12
|
+
* A public tx simulator that tracks runtime/production metrics with telemetry.
|
|
13
|
+
*/ export class TelemetryPublicTxSimulator extends MeasuredPublicTxSimulator {
|
|
14
|
+
/* tracer needed by trackSpans */ tracer;
|
|
15
|
+
constructor(treesDB, contractsDB, globalVariables, doMerkleOperations = false, skipFeeEnforcement = false, telemetryClient = getTelemetryClient()){
|
|
16
|
+
const metrics = new ExecutorMetrics(telemetryClient, 'PublicTxSimulator');
|
|
17
|
+
super(treesDB, contractsDB, globalVariables, doMerkleOperations, skipFeeEnforcement, metrics);
|
|
18
|
+
this.tracer = metrics.tracer;
|
|
19
|
+
}
|
|
20
|
+
async simulateEnqueuedCall(phase, context, callRequest) {
|
|
21
|
+
return await super.simulateEnqueuedCall(phase, context, callRequest);
|
|
22
|
+
}
|
|
23
|
+
async simulateEnqueuedCallInternal(stateManager, callRequest, allocatedGas, transactionFee, fnName) {
|
|
24
|
+
return await super.simulateEnqueuedCallInternal(stateManager, callRequest, allocatedGas, transactionFee, fnName);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
_ts_decorate([
|
|
28
|
+
trackSpan('PublicTxSimulator.simulateEnqueuedCall', (phase, context, callRequest)=>({
|
|
29
|
+
[Attributes.TX_HASH]: context.txHash.toString(),
|
|
30
|
+
[Attributes.TARGET_ADDRESS]: callRequest.request.contractAddress.toString(),
|
|
31
|
+
[Attributes.SENDER_ADDRESS]: callRequest.request.msgSender.toString(),
|
|
32
|
+
[Attributes.SIMULATOR_PHASE]: TxExecutionPhase[phase].toString()
|
|
33
|
+
}))
|
|
34
|
+
], TelemetryPublicTxSimulator.prototype, "simulateEnqueuedCall", null);
|
|
35
|
+
_ts_decorate([
|
|
36
|
+
trackSpan('PublicTxSimulator.simulateEnqueuedCallInternal', (_stateManager, _callRequest, _allocatedGas, _transactionFee, fnName)=>({
|
|
37
|
+
[Attributes.APP_CIRCUIT_NAME]: fnName
|
|
38
|
+
}))
|
|
39
|
+
], TelemetryPublicTxSimulator.prototype, "simulateEnqueuedCallInternal", null);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { RevertCode } from '@aztec/stdlib/avm';
|
|
2
|
+
import type { ExecutorMetricsInterface } from './executor_metrics_interface.js';
|
|
3
|
+
export interface PublicEnqueuedCallMetrics {
|
|
4
|
+
fnName: string;
|
|
5
|
+
durationMs: number;
|
|
6
|
+
manaUsed: number;
|
|
7
|
+
totalInstructions: number;
|
|
8
|
+
reverted: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface PublicTxMetrics {
|
|
11
|
+
totalDurationMs: number;
|
|
12
|
+
manaUsed: number;
|
|
13
|
+
totalInstructions: number;
|
|
14
|
+
txHashMs: number | undefined;
|
|
15
|
+
nonRevertiblePrivateInsertionsUs: number | undefined;
|
|
16
|
+
revertiblePrivateInsertionsUs: number | undefined;
|
|
17
|
+
enqueuedCalls: PublicEnqueuedCallMetrics[];
|
|
18
|
+
revertedCode: RevertCode | undefined;
|
|
19
|
+
}
|
|
20
|
+
export declare enum PublicTxMetricsFilter {
|
|
21
|
+
ALL = 0,
|
|
22
|
+
TOTALS = 1,
|
|
23
|
+
DURATIONS = 2,
|
|
24
|
+
INSTRUCTIONS = 3
|
|
25
|
+
}
|
|
26
|
+
export declare class TestExecutorMetrics implements ExecutorMetricsInterface {
|
|
27
|
+
#private;
|
|
28
|
+
private logger;
|
|
29
|
+
private txMetrics;
|
|
30
|
+
private currentTxLabel;
|
|
31
|
+
private txTimer;
|
|
32
|
+
constructor();
|
|
33
|
+
startRecordingTxSimulation(txLabel: string): void;
|
|
34
|
+
stopRecordingTxSimulation(txLabel: string, revertedCode?: RevertCode): void;
|
|
35
|
+
recordEnqueuedCallSimulation(fnName: string, durationMs: number, manaUsed: number, totalInstructions: number): void;
|
|
36
|
+
recordEnqueuedCallSimulationFailure(fnName: string, durationMs: number, manaUsed: number, totalInstructions: number): void;
|
|
37
|
+
recordTxHashComputation(durationMs: number): void;
|
|
38
|
+
recordPrivateEffectsInsertion(durationUs: number, type: 'revertible' | 'non-revertible'): void;
|
|
39
|
+
prettyPrint(filter?: PublicTxMetricsFilter): void;
|
|
40
|
+
toPrettyString(filter?: PublicTxMetricsFilter): string;
|
|
41
|
+
toJSON(indent?: number): string;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=test_executor_metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test_executor_metrics.d.ts","sourceRoot":"","sources":["../../src/public/test_executor_metrics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,gCAAgC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrD,6BAA6B,EAAE,MAAM,GAAG,SAAS,CAAC;IAClD,aAAa,EAAE,yBAAyB,EAAE,CAAC;IAC3C,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;CACtC;AAWD,oBAAY,qBAAqB;IAC/B,GAAG,IAAA;IACH,MAAM,IAAA;IACN,SAAS,IAAA;IACT,YAAY,IAAA;CACb;AAED,qBAAa,mBAAoB,YAAW,wBAAwB;;IAClE,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,OAAO,CAAoB;;IAMnC,0BAA0B,CAAC,OAAO,EAAE,MAAM;IAiB1C,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,UAAU;IAkBpE,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;IAI5G,mCAAmC,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;IAsBnH,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAO1C,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,gBAAgB;IAkBvF,WAAW,CAAC,MAAM,GAAE,qBAAiD;IAIrE,cAAc,CAAC,MAAM,GAAE,qBAAiD;IAqExE,MAAM,CAAC,MAAM,SAAI;CAGlB"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { sum } from '@aztec/foundation/collection';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
4
|
+
import { strict as assert } from 'assert';
|
|
5
|
+
const NUM_SPACES = 4;
|
|
6
|
+
const H1 = '# ';
|
|
7
|
+
const H2 = '\n## ';
|
|
8
|
+
const INDENT = ' '.repeat(NUM_SPACES);
|
|
9
|
+
const INDENT0 = '- ';
|
|
10
|
+
const INDENT1 = INDENT + '- ';
|
|
11
|
+
const INDENT2 = INDENT + INDENT + '- ';
|
|
12
|
+
const H_LINE = '\n---------------------------------------------------------------------';
|
|
13
|
+
export var PublicTxMetricsFilter = /*#__PURE__*/ function(PublicTxMetricsFilter) {
|
|
14
|
+
PublicTxMetricsFilter[PublicTxMetricsFilter["ALL"] = 0] = "ALL";
|
|
15
|
+
PublicTxMetricsFilter[PublicTxMetricsFilter["TOTALS"] = 1] = "TOTALS";
|
|
16
|
+
PublicTxMetricsFilter[PublicTxMetricsFilter["DURATIONS"] = 2] = "DURATIONS";
|
|
17
|
+
PublicTxMetricsFilter[PublicTxMetricsFilter["INSTRUCTIONS"] = 3] = "INSTRUCTIONS";
|
|
18
|
+
return PublicTxMetricsFilter;
|
|
19
|
+
}({});
|
|
20
|
+
export class TestExecutorMetrics {
|
|
21
|
+
logger;
|
|
22
|
+
// tx label -> tx metrics
|
|
23
|
+
txMetrics = new Map();
|
|
24
|
+
currentTxLabel;
|
|
25
|
+
txTimer;
|
|
26
|
+
constructor(){
|
|
27
|
+
this.logger = createLogger(`simulator:test_executor_metrics`);
|
|
28
|
+
}
|
|
29
|
+
startRecordingTxSimulation(txLabel) {
|
|
30
|
+
assert(!this.currentTxLabel, 'Cannot start recording tx simulation when another is live');
|
|
31
|
+
assert(!this.txMetrics.has(txLabel), 'Cannot start recording metrics for tx with duplicate label');
|
|
32
|
+
this.txMetrics.set(txLabel, {
|
|
33
|
+
totalDurationMs: 0,
|
|
34
|
+
manaUsed: 0,
|
|
35
|
+
totalInstructions: 0,
|
|
36
|
+
txHashMs: undefined,
|
|
37
|
+
nonRevertiblePrivateInsertionsUs: undefined,
|
|
38
|
+
revertiblePrivateInsertionsUs: undefined,
|
|
39
|
+
enqueuedCalls: [],
|
|
40
|
+
revertedCode: undefined
|
|
41
|
+
});
|
|
42
|
+
this.currentTxLabel = txLabel;
|
|
43
|
+
this.txTimer = new Timer();
|
|
44
|
+
}
|
|
45
|
+
stopRecordingTxSimulation(txLabel, revertedCode) {
|
|
46
|
+
assert(this.currentTxLabel === txLabel, 'Cannot stop recording metrics for tx when another is live');
|
|
47
|
+
const txMetrics = this.txMetrics.get(txLabel);
|
|
48
|
+
// total duration of tx
|
|
49
|
+
txMetrics.totalDurationMs = this.txTimer.ms();
|
|
50
|
+
this.logger.debug(`Public TX simulation of ${txLabel} took ${txMetrics.totalDurationMs}ms`);
|
|
51
|
+
// add manaUsed across all enqueued calls
|
|
52
|
+
txMetrics.manaUsed = sum(txMetrics.enqueuedCalls.map((call)=>call.manaUsed));
|
|
53
|
+
// add totalInstructions across all enqueued calls
|
|
54
|
+
txMetrics.totalInstructions = sum(txMetrics.enqueuedCalls.map((call)=>call.totalInstructions));
|
|
55
|
+
txMetrics.revertedCode = revertedCode;
|
|
56
|
+
this.currentTxLabel = undefined;
|
|
57
|
+
}
|
|
58
|
+
recordEnqueuedCallSimulation(fnName, durationMs, manaUsed, totalInstructions) {
|
|
59
|
+
this.#recordEnqueuedCallSimulation(fnName, durationMs, manaUsed, totalInstructions, false);
|
|
60
|
+
}
|
|
61
|
+
recordEnqueuedCallSimulationFailure(fnName, durationMs, manaUsed, totalInstructions) {
|
|
62
|
+
this.#recordEnqueuedCallSimulation(fnName, durationMs, manaUsed, totalInstructions, true);
|
|
63
|
+
}
|
|
64
|
+
#recordEnqueuedCallSimulation(fnName, durationMs, manaUsed, totalInstructions, reverted) {
|
|
65
|
+
assert(this.currentTxLabel, 'Cannot record enqueued call simulation when no tx is live');
|
|
66
|
+
const txMetrics = this.txMetrics.get(this.currentTxLabel);
|
|
67
|
+
txMetrics.enqueuedCalls.push({
|
|
68
|
+
fnName,
|
|
69
|
+
durationMs,
|
|
70
|
+
manaUsed,
|
|
71
|
+
totalInstructions,
|
|
72
|
+
reverted
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
recordTxHashComputation(durationMs) {
|
|
76
|
+
assert(this.currentTxLabel, 'Cannot record tx hash computation time when no tx is live');
|
|
77
|
+
const txMetrics = this.txMetrics.get(this.currentTxLabel);
|
|
78
|
+
assert(txMetrics.txHashMs === undefined, 'Cannot RE-record tx hash computation time');
|
|
79
|
+
txMetrics.txHashMs = durationMs;
|
|
80
|
+
}
|
|
81
|
+
recordPrivateEffectsInsertion(durationUs, type) {
|
|
82
|
+
assert(this.currentTxLabel, 'Cannot record private effects insertion when no tx is live');
|
|
83
|
+
const txMetrics = this.txMetrics.get(this.currentTxLabel);
|
|
84
|
+
if (type === 'revertible') {
|
|
85
|
+
assert(txMetrics.revertiblePrivateInsertionsUs === undefined, 'Cannot RE-record revertible insertions of private effects');
|
|
86
|
+
txMetrics.revertiblePrivateInsertionsUs = durationUs;
|
|
87
|
+
} else {
|
|
88
|
+
assert(txMetrics.nonRevertiblePrivateInsertionsUs === undefined, 'Cannot RE-record non-revertible insertions of private effects');
|
|
89
|
+
txMetrics.nonRevertiblePrivateInsertionsUs = durationUs;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
prettyPrint(filter = 0) {
|
|
93
|
+
this.logger.info(this.toPrettyString(filter));
|
|
94
|
+
}
|
|
95
|
+
toPrettyString(filter = 0) {
|
|
96
|
+
let pretty = '';
|
|
97
|
+
//pretty += H_LINE + '\n';
|
|
98
|
+
pretty += `${H1}Public TX Simulation Metrics (${PublicTxMetricsFilter[filter]})\n`;
|
|
99
|
+
for (const [txLabel, txMetrics] of this.txMetrics.entries()){
|
|
100
|
+
//pretty += H_LINE + '\n';
|
|
101
|
+
pretty += `${H2}TX Label: ${txLabel}\n`;
|
|
102
|
+
if (filter == 2 || filter === 1 || filter === 0) {
|
|
103
|
+
pretty += `${INDENT0}Total duration: ${fmtNum(txMetrics.totalDurationMs, 'ms')}\n`;
|
|
104
|
+
}
|
|
105
|
+
if (filter === 1 || filter === 0) {
|
|
106
|
+
pretty += `${INDENT0}Total mana used: ${fmtNum(txMetrics.manaUsed)}\n`;
|
|
107
|
+
const manaPerSecond = Math.round(txMetrics.manaUsed * 1000 / txMetrics.totalDurationMs);
|
|
108
|
+
pretty += `${INDENT0}Mana per second: ${fmtNum(manaPerSecond)}\n`;
|
|
109
|
+
}
|
|
110
|
+
if (filter === 3 || filter === 1 || filter === 0) {
|
|
111
|
+
pretty += `${INDENT0}Total instructions executed: ${fmtNum(txMetrics.totalInstructions)}\n`;
|
|
112
|
+
}
|
|
113
|
+
if (filter === 2 || filter === 0) {
|
|
114
|
+
pretty += `${INDENT0}Tx hash computation: ${fmtNum(txMetrics.txHashMs, 'ms')}\n`;
|
|
115
|
+
pretty += `${INDENT0}Private insertions:\n`;
|
|
116
|
+
pretty += `${INDENT1}Non-revertible: ${fmtNum(txMetrics.nonRevertiblePrivateInsertionsUs / 1_000, 'ms')}\n`;
|
|
117
|
+
pretty += `${INDENT1}Revertible: ${fmtNum(txMetrics.revertiblePrivateInsertionsUs / 1_000, 'ms')}\n`;
|
|
118
|
+
}
|
|
119
|
+
if (filter !== 1) {
|
|
120
|
+
// totals exclude enqueued calls
|
|
121
|
+
pretty += this.#enqueuedCallsToPrettyString(txMetrics, filter);
|
|
122
|
+
}
|
|
123
|
+
if (txMetrics.revertedCode !== undefined && !txMetrics.revertedCode.isOK()) {
|
|
124
|
+
pretty += `${INDENT0}Reverted code: ${txMetrics.revertedCode?.getDescription()}\n`;
|
|
125
|
+
}
|
|
126
|
+
pretty += H_LINE + '\n';
|
|
127
|
+
}
|
|
128
|
+
return pretty;
|
|
129
|
+
}
|
|
130
|
+
#enqueuedCallsToPrettyString(txMetrics, filter) {
|
|
131
|
+
let pretty = '';
|
|
132
|
+
pretty += `${INDENT0}Enqueued public calls:\n`;
|
|
133
|
+
for (const enqueuedCall of txMetrics.enqueuedCalls){
|
|
134
|
+
pretty += `${INDENT1}**Fn: ${enqueuedCall.fnName}**\n`;
|
|
135
|
+
if (filter === 2 || filter === 0) {
|
|
136
|
+
pretty += `${INDENT2}Duration: ${fmtNum(enqueuedCall.durationMs, 'ms')}\n`;
|
|
137
|
+
}
|
|
138
|
+
if (filter === 0) {
|
|
139
|
+
pretty += `${INDENT2}Mana used: ${fmtNum(enqueuedCall.manaUsed)}\n`;
|
|
140
|
+
const manaPerSecond = Math.round(enqueuedCall.manaUsed * 1000 / enqueuedCall.durationMs);
|
|
141
|
+
pretty += `${INDENT2}Mana per second: ${fmtNum(manaPerSecond)}\n`;
|
|
142
|
+
}
|
|
143
|
+
if (filter === 3 || filter === 0) {
|
|
144
|
+
pretty += `${INDENT2}Instructions executed: ${fmtNum(enqueuedCall.totalInstructions)}\n`;
|
|
145
|
+
}
|
|
146
|
+
if (enqueuedCall.reverted) {
|
|
147
|
+
pretty += `${INDENT2}Reverted!\n`;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return pretty;
|
|
151
|
+
}
|
|
152
|
+
toJSON(indent = 2) {
|
|
153
|
+
return JSON.stringify(Object.fromEntries(this.txMetrics.entries()), null, indent);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function fmtNum(num, unit) {
|
|
157
|
+
return `\`${num.toLocaleString()}${unit ? ` ${unit}` : ''}\``;
|
|
158
|
+
}
|