@aztec/simulator 0.82.2 → 0.82.3-nightly.20250403
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 +3 -2
- package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/oracle.js +9 -6
- package/dest/private/acvm/oracle/typed_oracle.d.ts +4 -3
- package/dest/private/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/typed_oracle.js +4 -1
- package/dest/private/execution_data_provider.d.ts +20 -16
- package/dest/private/execution_data_provider.d.ts.map +1 -1
- package/dest/private/private_execution_oracle.d.ts +1 -1
- package/dest/private/private_execution_oracle.d.ts.map +1 -1
- package/dest/private/private_execution_oracle.js +2 -6
- package/dest/private/unconstrained_execution_oracle.d.ts +4 -2
- package/dest/private/unconstrained_execution_oracle.d.ts.map +1 -1
- package/dest/private/unconstrained_execution_oracle.js +5 -6
- package/dest/public/avm/avm_context.d.ts +3 -3
- package/dest/public/avm/avm_context.d.ts.map +1 -1
- 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 +2 -2
- 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 +2 -2
- package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/avm_simulation_tester.js +3 -4
- 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 +6 -5
- package/dest/public/avm/fixtures/index.d.ts.map +1 -1
- package/dest/public/avm/fixtures/index.js +3 -3
- 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/index.d.ts +0 -1
- package/dest/public/avm/index.d.ts.map +1 -1
- package/dest/public/avm/index.js +0 -1
- package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/public/avm/opcodes/accrued_substate.js +1 -1
- 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 +25 -7
- package/dest/public/avm/test_utils.d.ts +1 -1
- package/dest/public/avm/test_utils.d.ts.map +1 -1
- 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 +134 -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 +4 -4
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +7 -28
- 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 +5 -5
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +10 -8
- 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 +25 -65
- 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/state_manager/index.d.ts +2 -0
- package/dest/public/state_manager/index.d.ts.map +1 -0
- package/dest/public/state_manager/index.js +1 -0
- package/dest/public/{avm/journal → state_manager}/nullifiers.d.ts +1 -1
- package/dest/public/state_manager/nullifiers.d.ts.map +1 -0
- package/dest/public/{avm/journal → state_manager}/public_storage.d.ts +1 -1
- package/dest/public/state_manager/public_storage.d.ts.map +1 -0
- package/dest/public/{avm/journal/journal.d.ts → state_manager/state_manager.d.ts} +10 -10
- package/dest/public/state_manager/state_manager.d.ts.map +1 -0
- package/dest/public/{avm/journal/journal.js → state_manager/state_manager.js} +5 -5
- 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 +26 -5
- package/src/private/acvm/oracle/typed_oracle.ts +14 -3
- package/src/private/execution_data_provider.ts +34 -18
- package/src/private/private_execution_oracle.ts +2 -13
- package/src/private/unconstrained_execution_oracle.ts +22 -15
- package/src/public/avm/avm_context.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 +20 -9
- package/src/public/avm/fixtures/avm_simulation_tester.ts +4 -4
- package/src/public/avm/fixtures/base_avm_simulation_tester.ts +1 -7
- package/src/public/avm/fixtures/index.ts +7 -7
- package/src/public/avm/fixtures/simple_contract_data_source.ts +33 -6
- package/src/public/avm/index.ts +0 -1
- package/src/public/avm/opcodes/accrued_substate.ts +1 -1
- 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 +24 -9
- package/src/public/avm/test_utils.ts +1 -1
- 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 +228 -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 +8 -28
- 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 +13 -17
- package/src/public/public_tx_simulator/public_tx_simulator.ts +35 -79
- package/src/public/public_tx_simulator/telemetry_public_tx_simulator.ts +62 -0
- package/src/public/state_manager/index.ts +1 -0
- package/src/public/{avm/journal → state_manager}/nullifiers.ts +1 -1
- package/src/public/{avm/journal → state_manager}/public_storage.ts +1 -1
- package/src/public/{avm/journal/journal.ts → state_manager/state_manager.ts} +20 -13
- package/src/public/test_executor_metrics.ts +222 -0
- package/dest/public/avm/journal/index.d.ts +0 -2
- package/dest/public/avm/journal/index.d.ts.map +0 -1
- package/dest/public/avm/journal/index.js +0 -1
- package/dest/public/avm/journal/journal.d.ts.map +0 -1
- package/dest/public/avm/journal/nullifiers.d.ts.map +0 -1
- package/dest/public/avm/journal/public_storage.d.ts.map +0 -1
- package/src/public/avm/journal/index.ts +0 -1
- /package/dest/public/{avm/journal → state_manager}/nullifiers.js +0 -0
- /package/dest/public/{avm/journal → state_manager}/public_storage.js +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import { Timer } from '@aztec/foundation/timer';
|
|
4
3
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
4
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
6
5
|
import {
|
|
@@ -14,7 +13,6 @@ import {
|
|
|
14
13
|
import { SimulationError } from '@aztec/stdlib/errors';
|
|
15
14
|
import type { Gas, GasUsed } from '@aztec/stdlib/gas';
|
|
16
15
|
import { ProvingRequestType } from '@aztec/stdlib/proofs';
|
|
17
|
-
import type { AvmSimulationStats } from '@aztec/stdlib/stats';
|
|
18
16
|
import {
|
|
19
17
|
type GlobalVariables,
|
|
20
18
|
NestedProcessReturnValues,
|
|
@@ -22,21 +20,20 @@ import {
|
|
|
22
20
|
Tx,
|
|
23
21
|
TxExecutionPhase,
|
|
24
22
|
} from '@aztec/stdlib/tx';
|
|
25
|
-
import { Attributes, type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
26
23
|
|
|
27
24
|
import { strict as assert } from 'assert';
|
|
28
25
|
|
|
29
26
|
import { getPublicFunctionDebugName } from '../../common/debug_fn_name.js';
|
|
30
27
|
import type { AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js';
|
|
31
|
-
import {
|
|
32
|
-
import { NullifierCollisionError } from '../avm/journal/nullifiers.js';
|
|
33
|
-
import { ExecutorMetrics } from '../executor_metrics.js';
|
|
28
|
+
import { AvmSimulator } from '../avm/index.js';
|
|
34
29
|
import type { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
|
|
30
|
+
import { NullifierCollisionError } from '../state_manager/nullifiers.js';
|
|
31
|
+
import type { PublicPersistableStateManager } from '../state_manager/state_manager.js';
|
|
35
32
|
import { PublicTxContext } from './public_tx_context.js';
|
|
36
33
|
|
|
37
34
|
export type ProcessedPhase = {
|
|
38
35
|
phase: TxExecutionPhase;
|
|
39
|
-
durationMs
|
|
36
|
+
durationMs?: number;
|
|
40
37
|
returnValues: NestedProcessReturnValues[];
|
|
41
38
|
reverted: boolean;
|
|
42
39
|
revertReason?: SimulationError;
|
|
@@ -53,25 +50,18 @@ export type PublicTxResult = {
|
|
|
53
50
|
};
|
|
54
51
|
|
|
55
52
|
export class PublicTxSimulator {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
private log: Logger;
|
|
53
|
+
protected log: Logger;
|
|
59
54
|
|
|
60
55
|
constructor(
|
|
61
56
|
private treesDB: PublicTreesDB,
|
|
62
|
-
|
|
57
|
+
protected contractsDB: PublicContractsDB,
|
|
63
58
|
private globalVariables: GlobalVariables,
|
|
64
59
|
private doMerkleOperations: boolean = false,
|
|
65
60
|
private skipFeeEnforcement: boolean = false,
|
|
66
|
-
telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
67
61
|
) {
|
|
68
62
|
this.log = createLogger(`simulator:public_tx_simulator`);
|
|
69
|
-
this.metrics = new ExecutorMetrics(telemetryClient, 'PublicTxSimulator');
|
|
70
63
|
}
|
|
71
64
|
|
|
72
|
-
get tracer(): Tracer {
|
|
73
|
-
return this.metrics.tracer;
|
|
74
|
-
}
|
|
75
65
|
/**
|
|
76
66
|
* Simulate a transaction's public portion including all of its phases.
|
|
77
67
|
* @param tx - The transaction to simulate.
|
|
@@ -79,11 +69,9 @@ export class PublicTxSimulator {
|
|
|
79
69
|
*/
|
|
80
70
|
public async simulate(tx: Tx): Promise<PublicTxResult> {
|
|
81
71
|
try {
|
|
82
|
-
const
|
|
72
|
+
const txHash = await this.computeTxHash(tx);
|
|
83
73
|
|
|
84
|
-
const txHash = await tx.getTxHash();
|
|
85
74
|
this.log.debug(`Simulating ${tx.publicFunctionCalldata.length} public calls for tx ${txHash}`, { txHash });
|
|
86
|
-
|
|
87
75
|
const context = await PublicTxContext.create(
|
|
88
76
|
this.treesDB,
|
|
89
77
|
this.contractsDB,
|
|
@@ -92,13 +80,7 @@ export class PublicTxSimulator {
|
|
|
92
80
|
this.doMerkleOperations,
|
|
93
81
|
);
|
|
94
82
|
|
|
95
|
-
|
|
96
|
-
await this.insertNonRevertiblesFromPrivate(context);
|
|
97
|
-
// add new contracts to the contracts db so that their functions may be found and called
|
|
98
|
-
// TODO(#6464): Should we allow emitting contracts in the private setup phase?
|
|
99
|
-
await this.contractsDB.addNewNonRevertibleContracts(tx);
|
|
100
|
-
const nonRevertEnd = process.hrtime.bigint();
|
|
101
|
-
this.metrics.recordPrivateEffectsInsertion(Number(nonRevertEnd - nonRevertStart) / 1_000, 'non-revertible');
|
|
83
|
+
await this.insertNonRevertiblesFromPrivate(context, tx);
|
|
102
84
|
|
|
103
85
|
const processedPhases: ProcessedPhase[] = [];
|
|
104
86
|
if (context.hasPhase(TxExecutionPhase.SETUP)) {
|
|
@@ -106,14 +88,8 @@ export class PublicTxSimulator {
|
|
|
106
88
|
processedPhases.push(setupResult);
|
|
107
89
|
}
|
|
108
90
|
|
|
109
|
-
const
|
|
110
|
-
const success = await this.insertRevertiblesFromPrivate(context);
|
|
91
|
+
const success = await this.insertRevertiblesFromPrivate(context, tx);
|
|
111
92
|
if (success) {
|
|
112
|
-
// add new contracts to the contracts db so that their functions may be found and called
|
|
113
|
-
await this.contractsDB.addNewRevertibleContracts(tx);
|
|
114
|
-
const revertEnd = process.hrtime.bigint();
|
|
115
|
-
this.metrics.recordPrivateEffectsInsertion(Number(revertEnd - revertStart) / 1_000, 'revertible');
|
|
116
|
-
|
|
117
93
|
// Only proceed with app logic if there was no revert during revertible insertion
|
|
118
94
|
if (context.hasPhase(TxExecutionPhase.APP_LOGIC)) {
|
|
119
95
|
const appLogicResult: ProcessedPhase = await this.simulateAppLogicPhase(context);
|
|
@@ -131,7 +107,7 @@ export class PublicTxSimulator {
|
|
|
131
107
|
await context.halt();
|
|
132
108
|
await this.payFee(context);
|
|
133
109
|
|
|
134
|
-
const publicInputs = await context.generateAvmCircuitPublicInputs(
|
|
110
|
+
const publicInputs = await context.generateAvmCircuitPublicInputs();
|
|
135
111
|
const avmProvingRequest = PublicTxSimulator.generateProvingRequest(publicInputs, context.hints);
|
|
136
112
|
|
|
137
113
|
const revertCode = context.getFinalRevertCode();
|
|
@@ -142,11 +118,10 @@ export class PublicTxSimulator {
|
|
|
142
118
|
// Commit contracts from this TX to the block-level cache and clear tx cache
|
|
143
119
|
// If the tx reverted, only commit non-revertible contracts
|
|
144
120
|
// NOTE: You can't create contracts in public, so this is only relevant for private-created contracts
|
|
121
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
122
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
145
123
|
this.contractsDB.commitContractsForTx(/*onlyNonRevertibles=*/ !revertCode.isOK());
|
|
146
124
|
|
|
147
|
-
const endTime = process.hrtime.bigint();
|
|
148
|
-
this.log.debug(`Public TX simulator took ${Number(endTime - startTime) / 1_000_000} ms\n`);
|
|
149
|
-
|
|
150
125
|
return {
|
|
151
126
|
avmProvingRequest,
|
|
152
127
|
gasUsed: {
|
|
@@ -162,10 +137,16 @@ export class PublicTxSimulator {
|
|
|
162
137
|
} finally {
|
|
163
138
|
// Make sure there are no new contracts in the tx-level cache.
|
|
164
139
|
// They should either be committed to block-level cache or cleared.
|
|
140
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
141
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
165
142
|
this.contractsDB.clearContractsForTx();
|
|
166
143
|
}
|
|
167
144
|
}
|
|
168
145
|
|
|
146
|
+
protected async computeTxHash(tx: Tx) {
|
|
147
|
+
return await tx.getTxHash();
|
|
148
|
+
}
|
|
149
|
+
|
|
169
150
|
/**
|
|
170
151
|
* Simulate the setup phase of a transaction's public execution.
|
|
171
152
|
* @param context - WILL BE MUTATED. The context of the currently executing public transaction portion
|
|
@@ -229,7 +210,7 @@ export class PublicTxSimulator {
|
|
|
229
210
|
* @param context - WILL BE MUTATED. The context of the currently executing public transaction portion
|
|
230
211
|
* @returns The phase result.
|
|
231
212
|
*/
|
|
232
|
-
|
|
213
|
+
protected async simulatePhase(phase: TxExecutionPhase, context: PublicTxContext): Promise<ProcessedPhase> {
|
|
233
214
|
const callRequests = context.getCallRequestsForPhase(phase);
|
|
234
215
|
|
|
235
216
|
this.log.debug(`Processing phase ${TxExecutionPhase[phase]} for tx ${context.txHash}`, {
|
|
@@ -241,7 +222,6 @@ export class PublicTxSimulator {
|
|
|
241
222
|
const returnValues: NestedProcessReturnValues[] = [];
|
|
242
223
|
let reverted = false;
|
|
243
224
|
let revertReason: SimulationError | undefined;
|
|
244
|
-
const phaseTimer = new Timer();
|
|
245
225
|
for (let i = callRequests.length - 1; i >= 0; i--) {
|
|
246
226
|
if (reverted) {
|
|
247
227
|
break;
|
|
@@ -261,7 +241,6 @@ export class PublicTxSimulator {
|
|
|
261
241
|
|
|
262
242
|
return {
|
|
263
243
|
phase,
|
|
264
|
-
durationMs: phaseTimer.ms(),
|
|
265
244
|
returnValues,
|
|
266
245
|
reverted,
|
|
267
246
|
revertReason,
|
|
@@ -275,13 +254,7 @@ export class PublicTxSimulator {
|
|
|
275
254
|
* @param callRequest - The public function call request, including the calldata.
|
|
276
255
|
* @returns The result of execution.
|
|
277
256
|
*/
|
|
278
|
-
|
|
279
|
-
[Attributes.TX_HASH]: context.txHash.toString(),
|
|
280
|
-
[Attributes.TARGET_ADDRESS]: callRequest.request.contractAddress.toString(),
|
|
281
|
-
[Attributes.SENDER_ADDRESS]: callRequest.request.msgSender.toString(),
|
|
282
|
-
[Attributes.SIMULATOR_PHASE]: TxExecutionPhase[phase].toString(),
|
|
283
|
-
}))
|
|
284
|
-
private async simulateEnqueuedCall(
|
|
257
|
+
protected async simulateEnqueuedCall(
|
|
285
258
|
phase: TxExecutionPhase,
|
|
286
259
|
context: PublicTxContext,
|
|
287
260
|
callRequest: PublicCallRequestWithCalldata,
|
|
@@ -335,20 +308,13 @@ export class PublicTxSimulator {
|
|
|
335
308
|
* while still simulating phases and generating a proving request.
|
|
336
309
|
*
|
|
337
310
|
* @param stateManager - The state manager for AvmSimulation
|
|
338
|
-
* @param context - The context of the currently executing public transaction portion
|
|
339
311
|
* @param callRequest - The public function call request, including the calldata.
|
|
340
312
|
* @param allocatedGas - The gas allocated to the enqueued call
|
|
341
313
|
* @param fnName - The name of the function
|
|
342
314
|
* @returns The result of execution.
|
|
343
315
|
*/
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
(_stateManager, _callRequest, _allocatedGas, _transactionFee, fnName) => ({
|
|
347
|
-
[Attributes.APP_CIRCUIT_NAME]: fnName,
|
|
348
|
-
}),
|
|
349
|
-
)
|
|
350
|
-
private async simulateEnqueuedCallInternal(
|
|
351
|
-
stateManager: AvmPersistableStateManager,
|
|
316
|
+
protected async simulateEnqueuedCallInternal(
|
|
317
|
+
stateManager: PublicPersistableStateManager,
|
|
352
318
|
{ request, calldata }: PublicCallRequestWithCalldata,
|
|
353
319
|
allocatedGas: Gas,
|
|
354
320
|
transactionFee: Fr,
|
|
@@ -360,7 +326,6 @@ export class PublicTxSimulator {
|
|
|
360
326
|
this.log.debug(
|
|
361
327
|
`Executing enqueued public call to external function ${fnName}@${address} with ${allocatedGas.l2Gas} allocated L2 gas.`,
|
|
362
328
|
);
|
|
363
|
-
const timer = new Timer();
|
|
364
329
|
|
|
365
330
|
const simulator = await AvmSimulator.create(
|
|
366
331
|
stateManager,
|
|
@@ -373,32 +338,13 @@ export class PublicTxSimulator {
|
|
|
373
338
|
allocatedGas,
|
|
374
339
|
);
|
|
375
340
|
const avmCallResult = await simulator.execute();
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
this.log.verbose(
|
|
379
|
-
result.reverted
|
|
380
|
-
? `Simulation of enqueued public call ${fnName} reverted with reason ${result.revertReason}.`
|
|
381
|
-
: `Simulation of enqueued public call ${fnName} completed successfully.`,
|
|
382
|
-
{
|
|
383
|
-
eventName: 'avm-simulation',
|
|
384
|
-
appCircuitName: fnName,
|
|
385
|
-
duration: timer.ms(),
|
|
386
|
-
} satisfies AvmSimulationStats,
|
|
387
|
-
);
|
|
388
|
-
|
|
389
|
-
if (result.reverted) {
|
|
390
|
-
this.metrics.recordFunctionSimulationFailure();
|
|
391
|
-
} else {
|
|
392
|
-
this.metrics.recordFunctionSimulation(timer.ms(), allocatedGas.sub(result.gasLeft).l2Gas, fnName);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
return result;
|
|
341
|
+
return avmCallResult.finalize();
|
|
396
342
|
}
|
|
397
343
|
|
|
398
344
|
/**
|
|
399
345
|
* Insert the non-revertible accumulated data from private into the public state.
|
|
400
346
|
*/
|
|
401
|
-
|
|
347
|
+
protected async insertNonRevertiblesFromPrivate(context: PublicTxContext, tx: Tx) {
|
|
402
348
|
const stateManager = context.state.getActiveStateManager();
|
|
403
349
|
try {
|
|
404
350
|
await stateManager.writeSiloedNullifiersFromPrivate(context.nonRevertibleAccumulatedDataFromPrivate.nullifiers);
|
|
@@ -414,13 +360,18 @@ export class PublicTxSimulator {
|
|
|
414
360
|
await stateManager.writeUniqueNoteHash(noteHash);
|
|
415
361
|
}
|
|
416
362
|
}
|
|
363
|
+
// add new contracts to the contracts db so that their functions may be found and called
|
|
364
|
+
// TODO(#6464): Should we allow emitting contracts in the private setup phase?
|
|
365
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
366
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
367
|
+
await this.contractsDB.addNewNonRevertibleContracts(tx);
|
|
417
368
|
}
|
|
418
369
|
|
|
419
370
|
/**
|
|
420
371
|
* Insert the revertible accumulated data from private into the public state.
|
|
421
372
|
* Start by forking state so we can rollback to the end of setup if app logic or teardown reverts.
|
|
422
373
|
*/
|
|
423
|
-
|
|
374
|
+
protected async insertRevertiblesFromPrivate(context: PublicTxContext, tx: Tx): /*success=*/ Promise<boolean> {
|
|
424
375
|
// Fork the state manager so we can rollback to end of setup if app logic reverts.
|
|
425
376
|
await context.state.fork();
|
|
426
377
|
const stateManager = context.state.getActiveStateManager();
|
|
@@ -448,6 +399,11 @@ export class PublicTxSimulator {
|
|
|
448
399
|
await stateManager.writeSiloedNoteHash(noteHash);
|
|
449
400
|
}
|
|
450
401
|
}
|
|
402
|
+
// add new contracts to the contracts db so that their functions may be found and called
|
|
403
|
+
// FIXME(fcarreiro): this should conceptually use the hinted contracts db.
|
|
404
|
+
// However things should work as they are now because the hinted db would still pick up the new contracts.
|
|
405
|
+
await this.contractsDB.addNewRevertibleContracts(tx);
|
|
406
|
+
|
|
451
407
|
return /*success=*/ true;
|
|
452
408
|
}
|
|
453
409
|
|
|
@@ -0,0 +1,62 @@
|
|
|
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 { Attributes, type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
5
|
+
|
|
6
|
+
import type { AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js';
|
|
7
|
+
import { ExecutorMetrics } from '../executor_metrics.js';
|
|
8
|
+
import type { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
|
|
9
|
+
import type { PublicPersistableStateManager } from '../state_manager/state_manager.js';
|
|
10
|
+
import { MeasuredPublicTxSimulator } from './measured_public_tx_simulator.js';
|
|
11
|
+
import { PublicTxContext } from './public_tx_context.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A public tx simulator that tracks runtime/production metrics with telemetry.
|
|
15
|
+
*/
|
|
16
|
+
export class TelemetryPublicTxSimulator extends MeasuredPublicTxSimulator {
|
|
17
|
+
/* tracer needed by trackSpans */
|
|
18
|
+
public readonly tracer: Tracer;
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
treesDB: PublicTreesDB,
|
|
22
|
+
contractsDB: PublicContractsDB,
|
|
23
|
+
globalVariables: GlobalVariables,
|
|
24
|
+
doMerkleOperations: boolean = false,
|
|
25
|
+
skipFeeEnforcement: boolean = false,
|
|
26
|
+
telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
27
|
+
) {
|
|
28
|
+
const metrics = new ExecutorMetrics(telemetryClient, 'PublicTxSimulator');
|
|
29
|
+
super(treesDB, contractsDB, globalVariables, doMerkleOperations, skipFeeEnforcement, metrics);
|
|
30
|
+
this.tracer = metrics.tracer;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@trackSpan('PublicTxSimulator.simulateEnqueuedCall', (phase, context, callRequest) => ({
|
|
34
|
+
[Attributes.TX_HASH]: context.txHash.toString(),
|
|
35
|
+
[Attributes.TARGET_ADDRESS]: callRequest.request.contractAddress.toString(),
|
|
36
|
+
[Attributes.SENDER_ADDRESS]: callRequest.request.msgSender.toString(),
|
|
37
|
+
[Attributes.SIMULATOR_PHASE]: TxExecutionPhase[phase].toString(),
|
|
38
|
+
}))
|
|
39
|
+
protected override async simulateEnqueuedCall(
|
|
40
|
+
phase: TxExecutionPhase,
|
|
41
|
+
context: PublicTxContext,
|
|
42
|
+
callRequest: PublicCallRequestWithCalldata,
|
|
43
|
+
): Promise<AvmFinalizedCallResult> {
|
|
44
|
+
return await super.simulateEnqueuedCall(phase, context, callRequest);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@trackSpan(
|
|
48
|
+
'PublicTxSimulator.simulateEnqueuedCallInternal',
|
|
49
|
+
(_stateManager, _callRequest, _allocatedGas, _transactionFee, fnName) => ({
|
|
50
|
+
[Attributes.APP_CIRCUIT_NAME]: fnName,
|
|
51
|
+
}),
|
|
52
|
+
)
|
|
53
|
+
protected override async simulateEnqueuedCallInternal(
|
|
54
|
+
stateManager: PublicPersistableStateManager,
|
|
55
|
+
callRequest: PublicCallRequestWithCalldata,
|
|
56
|
+
allocatedGas: Gas,
|
|
57
|
+
transactionFee: Fr,
|
|
58
|
+
fnName: string,
|
|
59
|
+
): Promise<AvmFinalizedCallResult> {
|
|
60
|
+
return await super.simulateEnqueuedCallInternal(stateManager, callRequest, allocatedGas, transactionFee, fnName);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './state_manager.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
|
|
3
|
-
import type { PublicTreesDB } from '
|
|
3
|
+
import type { PublicTreesDB } from '../public_db_sources.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A class to manage new nullifier staging and existence checks during a contract call's AVM simulation.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
3
|
|
|
4
|
-
import type { PublicStateDBInterface } from '
|
|
4
|
+
import type { PublicStateDBInterface } from '../../common/db_interfaces.js';
|
|
5
5
|
|
|
6
6
|
type PublicStorageReadResult = {
|
|
7
7
|
value: Fr;
|
|
@@ -28,11 +28,11 @@ import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
|
28
28
|
|
|
29
29
|
import { strict as assert } from 'assert';
|
|
30
30
|
|
|
31
|
-
import { getPublicFunctionDebugName } from '
|
|
32
|
-
import type {
|
|
33
|
-
import type {
|
|
34
|
-
import type {
|
|
35
|
-
import type {
|
|
31
|
+
import { getPublicFunctionDebugName } from '../../common/debug_fn_name.js';
|
|
32
|
+
import type { PublicContractsDBInterface } from '../../server.js';
|
|
33
|
+
import type { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
|
|
34
|
+
import type { PublicTreesDB } from '../public_db_sources.js';
|
|
35
|
+
import type { PublicSideEffectTraceInterface } from '../side_effect_trace_interface.js';
|
|
36
36
|
import { NullifierCollisionError, NullifierManager } from './nullifiers.js';
|
|
37
37
|
import { PublicStorage } from './public_storage.js';
|
|
38
38
|
|
|
@@ -45,8 +45,8 @@ import { PublicStorage } from './public_storage.js';
|
|
|
45
45
|
*
|
|
46
46
|
* Manages merging of successful/reverted child state into current state.
|
|
47
47
|
*/
|
|
48
|
-
export class
|
|
49
|
-
private readonly log = createLogger('simulator:
|
|
48
|
+
export class PublicPersistableStateManager {
|
|
49
|
+
private readonly log = createLogger('simulator:state_manager');
|
|
50
50
|
|
|
51
51
|
/** Make sure a forked state is never merged twice. */
|
|
52
52
|
private alreadyMergedIntoParent = false;
|
|
@@ -72,8 +72,15 @@ export class AvmPersistableStateManager {
|
|
|
72
72
|
doMerkleOperations: boolean = false,
|
|
73
73
|
firstNullifier: Fr,
|
|
74
74
|
blockNumber: number,
|
|
75
|
-
):
|
|
76
|
-
return new
|
|
75
|
+
): PublicPersistableStateManager {
|
|
76
|
+
return new PublicPersistableStateManager(
|
|
77
|
+
treesDB,
|
|
78
|
+
contractsDB,
|
|
79
|
+
trace,
|
|
80
|
+
firstNullifier,
|
|
81
|
+
blockNumber,
|
|
82
|
+
doMerkleOperations,
|
|
83
|
+
);
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
// DO NOT USE!
|
|
@@ -87,7 +94,7 @@ export class AvmPersistableStateManager {
|
|
|
87
94
|
*/
|
|
88
95
|
public async fork() {
|
|
89
96
|
await this.treesDB.createCheckpoint();
|
|
90
|
-
return new
|
|
97
|
+
return new PublicPersistableStateManager(
|
|
91
98
|
this.treesDB,
|
|
92
99
|
this.contractsDB,
|
|
93
100
|
this.trace.fork(),
|
|
@@ -102,18 +109,18 @@ export class AvmPersistableStateManager {
|
|
|
102
109
|
/**
|
|
103
110
|
* Accept forked world state modifications & traced side effects / hints
|
|
104
111
|
*/
|
|
105
|
-
public async merge(forkedState:
|
|
112
|
+
public async merge(forkedState: PublicPersistableStateManager) {
|
|
106
113
|
await this._merge(forkedState, /*reverted=*/ false);
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
/**
|
|
110
117
|
* Reject forked world state modifications & traced side effects, keep traced hints
|
|
111
118
|
*/
|
|
112
|
-
public async reject(forkedState:
|
|
119
|
+
public async reject(forkedState: PublicPersistableStateManager) {
|
|
113
120
|
await this._merge(forkedState, /*reverted=*/ true);
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
private async _merge(forkedState:
|
|
123
|
+
private async _merge(forkedState: PublicPersistableStateManager, reverted: boolean) {
|
|
117
124
|
// sanity check to avoid merging the same forked trace twice
|
|
118
125
|
assert(
|
|
119
126
|
!forkedState.alreadyMergedIntoParent,
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { sum } from '@aztec/foundation/collection';
|
|
2
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
4
|
+
import type { RevertCode } from '@aztec/stdlib/avm';
|
|
5
|
+
|
|
6
|
+
import { strict as assert } from 'assert';
|
|
7
|
+
|
|
8
|
+
import type { ExecutorMetricsInterface } from './executor_metrics_interface.js';
|
|
9
|
+
|
|
10
|
+
export interface PublicEnqueuedCallMetrics {
|
|
11
|
+
fnName: string;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
manaUsed: number;
|
|
14
|
+
totalInstructions: number;
|
|
15
|
+
reverted: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PublicTxMetrics {
|
|
19
|
+
totalDurationMs: number;
|
|
20
|
+
manaUsed: number;
|
|
21
|
+
totalInstructions: number;
|
|
22
|
+
txHashMs: number | undefined;
|
|
23
|
+
nonRevertiblePrivateInsertionsUs: number | undefined;
|
|
24
|
+
revertiblePrivateInsertionsUs: number | undefined;
|
|
25
|
+
enqueuedCalls: PublicEnqueuedCallMetrics[];
|
|
26
|
+
revertedCode: RevertCode | undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const NUM_SPACES = 4;
|
|
30
|
+
const H1 = '# ';
|
|
31
|
+
const H2 = '\n## ';
|
|
32
|
+
const INDENT = ' '.repeat(NUM_SPACES);
|
|
33
|
+
const INDENT0 = '- ';
|
|
34
|
+
const INDENT1 = INDENT + '- ';
|
|
35
|
+
const INDENT2 = INDENT + INDENT + '- ';
|
|
36
|
+
const H_LINE = '\n---------------------------------------------------------------------';
|
|
37
|
+
|
|
38
|
+
export enum PublicTxMetricsFilter {
|
|
39
|
+
ALL,
|
|
40
|
+
TOTALS,
|
|
41
|
+
DURATIONS,
|
|
42
|
+
INSTRUCTIONS,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class TestExecutorMetrics implements ExecutorMetricsInterface {
|
|
46
|
+
private logger: Logger;
|
|
47
|
+
// tx label -> tx metrics
|
|
48
|
+
private txMetrics: Map<string, PublicTxMetrics> = new Map();
|
|
49
|
+
private currentTxLabel: string | undefined;
|
|
50
|
+
private txTimer: Timer | undefined;
|
|
51
|
+
|
|
52
|
+
constructor() {
|
|
53
|
+
this.logger = createLogger(`simulator:test_executor_metrics`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
startRecordingTxSimulation(txLabel: string) {
|
|
57
|
+
assert(!this.currentTxLabel, 'Cannot start recording tx simulation when another is live');
|
|
58
|
+
assert(!this.txMetrics.has(txLabel), 'Cannot start recording metrics for tx with duplicate label');
|
|
59
|
+
this.txMetrics.set(txLabel, {
|
|
60
|
+
totalDurationMs: 0,
|
|
61
|
+
manaUsed: 0,
|
|
62
|
+
totalInstructions: 0,
|
|
63
|
+
txHashMs: undefined,
|
|
64
|
+
nonRevertiblePrivateInsertionsUs: undefined,
|
|
65
|
+
revertiblePrivateInsertionsUs: undefined,
|
|
66
|
+
enqueuedCalls: [],
|
|
67
|
+
revertedCode: undefined,
|
|
68
|
+
});
|
|
69
|
+
this.currentTxLabel = txLabel;
|
|
70
|
+
this.txTimer = new Timer();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
stopRecordingTxSimulation(txLabel: string, revertedCode?: RevertCode) {
|
|
74
|
+
assert(this.currentTxLabel === txLabel, 'Cannot stop recording metrics for tx when another is live');
|
|
75
|
+
|
|
76
|
+
const txMetrics = this.txMetrics.get(txLabel)!;
|
|
77
|
+
|
|
78
|
+
// total duration of tx
|
|
79
|
+
txMetrics.totalDurationMs = this.txTimer!.ms();
|
|
80
|
+
this.logger.debug(`Public TX simulation of ${txLabel} took ${txMetrics.totalDurationMs}ms`);
|
|
81
|
+
|
|
82
|
+
// add manaUsed across all enqueued calls
|
|
83
|
+
txMetrics.manaUsed = sum(txMetrics.enqueuedCalls.map(call => call.manaUsed));
|
|
84
|
+
// add totalInstructions across all enqueued calls
|
|
85
|
+
txMetrics.totalInstructions = sum(txMetrics.enqueuedCalls.map(call => call.totalInstructions));
|
|
86
|
+
txMetrics.revertedCode = revertedCode;
|
|
87
|
+
|
|
88
|
+
this.currentTxLabel = undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
recordEnqueuedCallSimulation(fnName: string, durationMs: number, manaUsed: number, totalInstructions: number) {
|
|
92
|
+
this.#recordEnqueuedCallSimulation(fnName, durationMs, manaUsed, totalInstructions, false);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
recordEnqueuedCallSimulationFailure(fnName: string, durationMs: number, manaUsed: number, totalInstructions: number) {
|
|
96
|
+
this.#recordEnqueuedCallSimulation(fnName, durationMs, manaUsed, totalInstructions, true);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#recordEnqueuedCallSimulation(
|
|
100
|
+
fnName: string,
|
|
101
|
+
durationMs: number,
|
|
102
|
+
manaUsed: number,
|
|
103
|
+
totalInstructions: number,
|
|
104
|
+
reverted: boolean,
|
|
105
|
+
) {
|
|
106
|
+
assert(this.currentTxLabel, 'Cannot record enqueued call simulation when no tx is live');
|
|
107
|
+
const txMetrics = this.txMetrics.get(this.currentTxLabel)!;
|
|
108
|
+
txMetrics.enqueuedCalls.push({
|
|
109
|
+
fnName,
|
|
110
|
+
durationMs,
|
|
111
|
+
manaUsed,
|
|
112
|
+
totalInstructions,
|
|
113
|
+
reverted,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
recordTxHashComputation(durationMs: number) {
|
|
118
|
+
assert(this.currentTxLabel, 'Cannot record tx hash computation time when no tx is live');
|
|
119
|
+
const txMetrics = this.txMetrics.get(this.currentTxLabel)!;
|
|
120
|
+
assert(txMetrics.txHashMs === undefined, 'Cannot RE-record tx hash computation time');
|
|
121
|
+
txMetrics.txHashMs = durationMs;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
recordPrivateEffectsInsertion(durationUs: number, type: 'revertible' | 'non-revertible') {
|
|
125
|
+
assert(this.currentTxLabel, 'Cannot record private effects insertion when no tx is live');
|
|
126
|
+
const txMetrics = this.txMetrics.get(this.currentTxLabel)!;
|
|
127
|
+
if (type === 'revertible') {
|
|
128
|
+
assert(
|
|
129
|
+
txMetrics.revertiblePrivateInsertionsUs === undefined,
|
|
130
|
+
'Cannot RE-record revertible insertions of private effects',
|
|
131
|
+
);
|
|
132
|
+
txMetrics.revertiblePrivateInsertionsUs = durationUs;
|
|
133
|
+
} else {
|
|
134
|
+
assert(
|
|
135
|
+
txMetrics.nonRevertiblePrivateInsertionsUs === undefined,
|
|
136
|
+
'Cannot RE-record non-revertible insertions of private effects',
|
|
137
|
+
);
|
|
138
|
+
txMetrics.nonRevertiblePrivateInsertionsUs = durationUs;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
prettyPrint(filter: PublicTxMetricsFilter = PublicTxMetricsFilter.ALL) {
|
|
143
|
+
this.logger.info(this.toPrettyString(filter));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
toPrettyString(filter: PublicTxMetricsFilter = PublicTxMetricsFilter.ALL) {
|
|
147
|
+
let pretty = '';
|
|
148
|
+
//pretty += H_LINE + '\n';
|
|
149
|
+
pretty += `${H1}Public TX Simulation Metrics (${PublicTxMetricsFilter[filter]})\n`;
|
|
150
|
+
for (const [txLabel, txMetrics] of this.txMetrics.entries()) {
|
|
151
|
+
//pretty += H_LINE + '\n';
|
|
152
|
+
pretty += `${H2}TX Label: ${txLabel}\n`;
|
|
153
|
+
if (
|
|
154
|
+
filter == PublicTxMetricsFilter.DURATIONS ||
|
|
155
|
+
filter === PublicTxMetricsFilter.TOTALS ||
|
|
156
|
+
filter === PublicTxMetricsFilter.ALL
|
|
157
|
+
) {
|
|
158
|
+
pretty += `${INDENT0}Total duration: ${fmtNum(txMetrics.totalDurationMs, 'ms')}\n`;
|
|
159
|
+
}
|
|
160
|
+
if (filter === PublicTxMetricsFilter.TOTALS || filter === PublicTxMetricsFilter.ALL) {
|
|
161
|
+
pretty += `${INDENT0}Total mana used: ${fmtNum(txMetrics.manaUsed)}\n`;
|
|
162
|
+
const manaPerSecond = Math.round((txMetrics.manaUsed * 1000) / txMetrics.totalDurationMs);
|
|
163
|
+
pretty += `${INDENT0}Mana per second: ${fmtNum(manaPerSecond)}\n`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (
|
|
167
|
+
filter === PublicTxMetricsFilter.INSTRUCTIONS ||
|
|
168
|
+
filter === PublicTxMetricsFilter.TOTALS ||
|
|
169
|
+
filter === PublicTxMetricsFilter.ALL
|
|
170
|
+
) {
|
|
171
|
+
pretty += `${INDENT0}Total instructions executed: ${fmtNum(txMetrics.totalInstructions)}\n`;
|
|
172
|
+
}
|
|
173
|
+
if (filter === PublicTxMetricsFilter.DURATIONS || filter === PublicTxMetricsFilter.ALL) {
|
|
174
|
+
pretty += `${INDENT0}Tx hash computation: ${fmtNum(txMetrics.txHashMs!, 'ms')}\n`;
|
|
175
|
+
pretty += `${INDENT0}Private insertions:\n`;
|
|
176
|
+
pretty += `${INDENT1}Non-revertible: ${fmtNum(txMetrics.nonRevertiblePrivateInsertionsUs! / 1_000, 'ms')}\n`;
|
|
177
|
+
pretty += `${INDENT1}Revertible: ${fmtNum(txMetrics.revertiblePrivateInsertionsUs! / 1_000, 'ms')}\n`;
|
|
178
|
+
}
|
|
179
|
+
if (filter !== PublicTxMetricsFilter.TOTALS) {
|
|
180
|
+
// totals exclude enqueued calls
|
|
181
|
+
pretty += this.#enqueuedCallsToPrettyString(txMetrics, filter);
|
|
182
|
+
}
|
|
183
|
+
if (txMetrics.revertedCode !== undefined && !txMetrics.revertedCode.isOK()) {
|
|
184
|
+
pretty += `${INDENT0}Reverted code: ${txMetrics.revertedCode?.getDescription()}\n`;
|
|
185
|
+
}
|
|
186
|
+
pretty += H_LINE + '\n';
|
|
187
|
+
}
|
|
188
|
+
return pretty;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
#enqueuedCallsToPrettyString(txMetrics: PublicTxMetrics, filter: PublicTxMetricsFilter) {
|
|
192
|
+
let pretty = '';
|
|
193
|
+
pretty += `${INDENT0}Enqueued public calls:\n`;
|
|
194
|
+
for (const enqueuedCall of txMetrics.enqueuedCalls) {
|
|
195
|
+
pretty += `${INDENT1}**Fn: ${enqueuedCall.fnName}**\n`;
|
|
196
|
+
if (filter === PublicTxMetricsFilter.DURATIONS || filter === PublicTxMetricsFilter.ALL) {
|
|
197
|
+
pretty += `${INDENT2}Duration: ${fmtNum(enqueuedCall.durationMs, 'ms')}\n`;
|
|
198
|
+
}
|
|
199
|
+
if (filter === PublicTxMetricsFilter.ALL) {
|
|
200
|
+
pretty += `${INDENT2}Mana used: ${fmtNum(enqueuedCall.manaUsed)}\n`;
|
|
201
|
+
const manaPerSecond = Math.round((enqueuedCall.manaUsed * 1000) / enqueuedCall.durationMs);
|
|
202
|
+
pretty += `${INDENT2}Mana per second: ${fmtNum(manaPerSecond)}\n`;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (filter === PublicTxMetricsFilter.INSTRUCTIONS || filter === PublicTxMetricsFilter.ALL) {
|
|
206
|
+
pretty += `${INDENT2}Instructions executed: ${fmtNum(enqueuedCall.totalInstructions)}\n`;
|
|
207
|
+
}
|
|
208
|
+
if (enqueuedCall.reverted) {
|
|
209
|
+
pretty += `${INDENT2}Reverted!\n`;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return pretty;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
toJSON(indent = 2) {
|
|
216
|
+
return JSON.stringify(Object.fromEntries(this.txMetrics.entries()), null, indent);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function fmtNum(num: number, unit?: string) {
|
|
221
|
+
return `\`${num.toLocaleString()}${unit ? ` ${unit}` : ''}\``;
|
|
222
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/public/avm/journal/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './journal.js';
|