@aztec/simulator 0.82.2 → 0.82.3-nightly.20250330

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.
Files changed (113) hide show
  1. package/README.md +6 -0
  2. package/dest/private/acvm/oracle/oracle.d.ts +2 -1
  3. package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
  4. package/dest/private/acvm/oracle/oracle.js +7 -4
  5. package/dest/private/acvm/oracle/typed_oracle.d.ts +3 -2
  6. package/dest/private/acvm/oracle/typed_oracle.d.ts.map +1 -1
  7. package/dest/private/acvm/oracle/typed_oracle.js +3 -0
  8. package/dest/private/execution_data_provider.d.ts +12 -2
  9. package/dest/private/execution_data_provider.d.ts.map +1 -1
  10. package/dest/private/unconstrained_execution_oracle.d.ts +3 -1
  11. package/dest/private/unconstrained_execution_oracle.d.ts.map +1 -1
  12. package/dest/private/unconstrained_execution_oracle.js +3 -0
  13. package/dest/public/avm/avm_contract_call_result.d.ts +4 -2
  14. package/dest/public/avm/avm_contract_call_result.d.ts.map +1 -1
  15. package/dest/public/avm/avm_contract_call_result.js +9 -5
  16. package/dest/public/avm/avm_machine_state.d.ts +2 -0
  17. package/dest/public/avm/avm_machine_state.d.ts.map +1 -1
  18. package/dest/public/avm/avm_machine_state.js +2 -0
  19. package/dest/public/avm/avm_simulator.d.ts.map +1 -1
  20. package/dest/public/avm/avm_simulator.js +5 -6
  21. package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
  22. package/dest/public/avm/fixtures/avm_simulation_tester.js +1 -2
  23. package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts +1 -2
  24. package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -1
  25. package/dest/public/avm/fixtures/base_avm_simulation_tester.js +0 -5
  26. package/dest/public/avm/fixtures/index.d.ts +1 -0
  27. package/dest/public/avm/fixtures/index.d.ts.map +1 -1
  28. package/dest/public/avm/fixtures/index.js +1 -1
  29. package/dest/public/avm/fixtures/simple_contract_data_source.d.ts +3 -2
  30. package/dest/public/avm/fixtures/simple_contract_data_source.d.ts.map +1 -1
  31. package/dest/public/avm/fixtures/simple_contract_data_source.js +30 -6
  32. package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
  33. package/dest/public/avm/opcodes/external_calls.js +2 -0
  34. package/dest/public/avm/opcodes/memory.d.ts.map +1 -1
  35. package/dest/public/avm/opcodes/memory.js +8 -10
  36. package/dest/public/avm/serialization/instruction_serialization.d.ts +5 -2
  37. package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -1
  38. package/dest/public/avm/serialization/instruction_serialization.js +25 -7
  39. package/dest/public/executor_metrics.d.ts +11 -3
  40. package/dest/public/executor_metrics.d.ts.map +1 -1
  41. package/dest/public/executor_metrics.js +40 -6
  42. package/dest/public/executor_metrics_interface.d.ts +10 -0
  43. package/dest/public/executor_metrics_interface.d.ts.map +1 -0
  44. package/dest/public/executor_metrics_interface.js +1 -0
  45. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +12 -6
  46. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  47. package/dest/public/fixtures/public_tx_simulation_tester.js +39 -19
  48. package/dest/public/hinting_db_sources.d.ts +26 -3
  49. package/dest/public/hinting_db_sources.d.ts.map +1 -1
  50. package/dest/public/hinting_db_sources.js +102 -1
  51. package/dest/public/index.d.ts +1 -1
  52. package/dest/public/index.d.ts.map +1 -1
  53. package/dest/public/index.js +1 -1
  54. package/dest/public/public_db_sources.d.ts +2 -3
  55. package/dest/public/public_db_sources.d.ts.map +1 -1
  56. package/dest/public/public_db_sources.js +26 -16
  57. package/dest/public/public_processor/public_processor.d.ts +4 -4
  58. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  59. package/dest/public/public_processor/public_processor.js +7 -28
  60. package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts +9 -0
  61. package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts.map +1 -0
  62. package/dest/public/public_tx_simulator/apps_tests/amm_test.js +237 -0
  63. package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts +7 -0
  64. package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts.map +1 -0
  65. package/dest/public/public_tx_simulator/apps_tests/token_test.js +109 -0
  66. package/dest/public/public_tx_simulator/index.d.ts +3 -0
  67. package/dest/public/public_tx_simulator/index.d.ts.map +1 -0
  68. package/dest/public/public_tx_simulator/index.js +2 -0
  69. package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts +23 -0
  70. package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts.map +1 -0
  71. package/dest/public/public_tx_simulator/measured_public_tx_simulator.js +58 -0
  72. package/dest/public/public_tx_simulator/public_tx_context.d.ts +2 -2
  73. package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
  74. package/dest/public/public_tx_simulator/public_tx_context.js +9 -7
  75. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +16 -16
  76. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
  77. package/dest/public/public_tx_simulator/public_tx_simulator.js +24 -64
  78. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts +19 -0
  79. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts.map +1 -0
  80. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.js +39 -0
  81. package/dest/public/test_executor_metrics.d.ts +43 -0
  82. package/dest/public/test_executor_metrics.d.ts.map +1 -0
  83. package/dest/public/test_executor_metrics.js +158 -0
  84. package/package.json +14 -14
  85. package/src/private/acvm/oracle/oracle.ts +24 -3
  86. package/src/private/acvm/oracle/typed_oracle.ts +13 -2
  87. package/src/private/execution_data_provider.ts +25 -2
  88. package/src/private/unconstrained_execution_oracle.ts +20 -1
  89. package/src/public/avm/avm_contract_call_result.ts +15 -3
  90. package/src/public/avm/avm_machine_state.ts +5 -0
  91. package/src/public/avm/avm_simulator.ts +18 -7
  92. package/src/public/avm/fixtures/avm_simulation_tester.ts +1 -1
  93. package/src/public/avm/fixtures/base_avm_simulation_tester.ts +1 -7
  94. package/src/public/avm/fixtures/index.ts +1 -1
  95. package/src/public/avm/fixtures/simple_contract_data_source.ts +33 -6
  96. package/src/public/avm/opcodes/external_calls.ts +3 -0
  97. package/src/public/avm/opcodes/memory.ts +8 -10
  98. package/src/public/avm/serialization/instruction_serialization.ts +24 -9
  99. package/src/public/executor_metrics.ts +54 -6
  100. package/src/public/executor_metrics_interface.ts +15 -0
  101. package/src/public/fixtures/public_tx_simulation_tester.ts +74 -18
  102. package/src/public/hinting_db_sources.ts +184 -3
  103. package/src/public/index.ts +1 -1
  104. package/src/public/public_db_sources.ts +36 -23
  105. package/src/public/public_processor/public_processor.ts +8 -28
  106. package/src/public/public_tx_simulator/apps_tests/amm_test.ts +316 -0
  107. package/src/public/public_tx_simulator/apps_tests/token_test.ts +138 -0
  108. package/src/public/public_tx_simulator/index.ts +2 -0
  109. package/src/public/public_tx_simulator/measured_public_tx_simulator.ts +111 -0
  110. package/src/public/public_tx_simulator/public_tx_context.ts +9 -13
  111. package/src/public/public_tx_simulator/public_tx_simulator.ts +31 -76
  112. package/src/public/public_tx_simulator/telemetry_public_tx_simulator.ts +62 -0
  113. package/src/public/test_executor_metrics.ts +222 -0
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/simulator",
3
- "version": "0.82.2",
3
+ "version": "0.82.3-nightly.20250330",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./server": "./dest/server.js",
@@ -60,16 +60,16 @@
60
60
  ]
61
61
  },
62
62
  "dependencies": {
63
- "@aztec/constants": "0.82.2",
64
- "@aztec/foundation": "0.82.2",
65
- "@aztec/noir-acvm_js": "0.82.2",
66
- "@aztec/noir-noirc_abi": "0.82.2",
67
- "@aztec/noir-protocol-circuits-types": "0.82.2",
68
- "@aztec/noir-types": "0.82.2",
69
- "@aztec/protocol-contracts": "0.82.2",
70
- "@aztec/stdlib": "0.82.2",
71
- "@aztec/telemetry-client": "0.82.2",
72
- "@aztec/world-state": "0.82.2",
63
+ "@aztec/constants": "0.82.3-nightly.20250330",
64
+ "@aztec/foundation": "0.82.3-nightly.20250330",
65
+ "@aztec/noir-acvm_js": "0.82.3-nightly.20250330",
66
+ "@aztec/noir-noirc_abi": "0.82.3-nightly.20250330",
67
+ "@aztec/noir-protocol-circuits-types": "0.82.3-nightly.20250330",
68
+ "@aztec/noir-types": "0.82.3-nightly.20250330",
69
+ "@aztec/protocol-contracts": "0.82.3-nightly.20250330",
70
+ "@aztec/stdlib": "0.82.3-nightly.20250330",
71
+ "@aztec/telemetry-client": "0.82.3-nightly.20250330",
72
+ "@aztec/world-state": "0.82.3-nightly.20250330",
73
73
  "levelup": "^5.1.1",
74
74
  "lodash.clonedeep": "^4.5.0",
75
75
  "lodash.merge": "^4.6.2",
@@ -77,9 +77,9 @@
77
77
  "tslib": "^2.4.0"
78
78
  },
79
79
  "devDependencies": {
80
- "@aztec/kv-store": "0.82.2",
81
- "@aztec/merkle-tree": "0.82.2",
82
- "@aztec/noir-contracts.js": "0.82.2",
80
+ "@aztec/kv-store": "0.82.3-nightly.20250330",
81
+ "@aztec/merkle-tree": "0.82.3-nightly.20250330",
82
+ "@aztec/noir-contracts.js": "0.82.3-nightly.20250330",
83
83
  "@jest/globals": "^29.5.0",
84
84
  "@types/jest": "^29.5.0",
85
85
  "@types/levelup": "^5.1.3",
@@ -1,8 +1,9 @@
1
1
  import { Fr, Point } from '@aztec/foundation/fields';
2
- import { FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
2
+ import { EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
3
3
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
4
4
  import { ContractClassLog, LogWithTxData } from '@aztec/stdlib/logs';
5
5
  import { MerkleTreeId } from '@aztec/stdlib/trees';
6
+ import { TxHash } from '@aztec/stdlib/tx';
6
7
 
7
8
  import type { ACVMField } from '../acvm_types.js';
8
9
  import { fromBoundedVec, fromUintArray, fromUintBoundedVec } from '../deserialize.js';
@@ -355,12 +356,12 @@ export class Oracle {
355
356
  return Promise.resolve([]);
356
357
  }
357
358
 
358
- async getIndexedTaggingSecretAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise<ACVMField[][]> {
359
+ async getIndexedTaggingSecretAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise<ACVMField[]> {
359
360
  const taggingSecret = await this.typedOracle.getIndexedTaggingSecretAsSender(
360
361
  AztecAddress.fromString(sender),
361
362
  AztecAddress.fromString(recipient),
362
363
  );
363
- return [taggingSecret.toFields().map(toACVMField)];
364
+ return taggingSecret.toFields().map(toACVMField);
364
365
  }
365
366
 
366
367
  async incrementAppTaggingSecretIndexAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise<ACVMField[]> {
@@ -490,4 +491,24 @@ export class Oracle {
490
491
  );
491
492
  return secret.toFields().map(toACVMField);
492
493
  }
494
+
495
+ async storePrivateEventLog(
496
+ [contractAddress]: ACVMField[],
497
+ [recipient]: ACVMField[],
498
+ [eventSelector]: ACVMField[],
499
+ logContentBVecStorage: ACVMField[],
500
+ [logContentLength]: ACVMField[],
501
+ [txHash]: ACVMField[],
502
+ [logIndexInTx]: ACVMField[],
503
+ ) {
504
+ await this.typedOracle.storePrivateEventLog(
505
+ AztecAddress.fromField(Fr.fromString(contractAddress)),
506
+ AztecAddress.fromField(Fr.fromString(recipient)),
507
+ EventSelector.fromField(Fr.fromString(eventSelector)),
508
+ fromBoundedVec(logContentBVecStorage, logContentLength),
509
+ new TxHash(Fr.fromString(txHash)),
510
+ Fr.fromString(logIndexInTx).toNumber(),
511
+ );
512
+ return [];
513
+ }
493
514
  }
@@ -1,13 +1,13 @@
1
1
  import type { L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/constants';
2
2
  import { Fr, Point } from '@aztec/foundation/fields';
3
- import type { FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
3
+ import type { EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
4
4
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
5
  import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
6
6
  import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
7
7
  import type { ContractClassLog, IndexedTaggingSecret, LogWithTxData } from '@aztec/stdlib/logs';
8
8
  import type { Note, NoteStatus } from '@aztec/stdlib/note';
9
9
  import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
10
- import type { BlockHeader } from '@aztec/stdlib/tx';
10
+ import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
11
11
 
12
12
  import type { MessageLoadOracleInputs } from '../../../common/message_load_oracle_inputs.js';
13
13
 
@@ -258,4 +258,15 @@ export abstract class TypedOracle {
258
258
  getSharedSecret(_address: AztecAddress, _ephPk: Point): Promise<Point> {
259
259
  return Promise.reject(new OracleMethodNotAvailableError('getSharedSecret'));
260
260
  }
261
+
262
+ storePrivateEventLog(
263
+ _contractAddress: AztecAddress,
264
+ _recipient: AztecAddress,
265
+ _eventSelector: EventSelector,
266
+ _logContent: Fr[],
267
+ _txHash: TxHash,
268
+ _logIndexInTx: number,
269
+ ): Promise<void> {
270
+ return Promise.reject(new OracleMethodNotAvailableError('storePrivateEventLog'));
271
+ }
261
272
  }
@@ -1,5 +1,10 @@
1
1
  import type { Fr, Point } from '@aztec/foundation/fields';
2
- import type { FunctionArtifact, FunctionArtifactWithContractName, FunctionSelector } from '@aztec/stdlib/abi';
2
+ import type {
3
+ EventSelector,
4
+ FunctionArtifact,
5
+ FunctionArtifactWithContractName,
6
+ FunctionSelector,
7
+ } from '@aztec/stdlib/abi';
3
8
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
9
  import type { L2Block } from '@aztec/stdlib/block';
5
10
  import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
@@ -7,7 +12,7 @@ import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
7
12
  import { IndexedTaggingSecret, LogWithTxData, TxScopedL2Log } from '@aztec/stdlib/logs';
8
13
  import type { NoteStatus } from '@aztec/stdlib/note';
9
14
  import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
10
- import type { BlockHeader } from '@aztec/stdlib/tx';
15
+ import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
11
16
 
12
17
  import type { CommitmentsDBInterface } from '../common/db_interfaces.js';
13
18
  import type { NoteData } from './acvm/index.js';
@@ -325,4 +330,22 @@ export interface ExecutionDataProvider extends CommitmentsDBInterface {
325
330
  * @returns The secret for the given address.
326
331
  */
327
332
  getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point>;
333
+
334
+ /**
335
+ * Stores an event log in the database.
336
+ * @param contractAddress - The address of the contract that emitted the log.
337
+ * @param recipient - The address of the recipient.
338
+ * @param eventSelector - The event selector of the event.
339
+ * @param logContent - The content of the private event log.
340
+ * @param txHash - The hash of the transaction that emitted the log.
341
+ * @param logIndexInTx - The index of the log within the transaction.
342
+ */
343
+ storePrivateEventLog(
344
+ contractAddress: AztecAddress,
345
+ recipient: AztecAddress,
346
+ eventSelector: EventSelector,
347
+ logContent: Fr[],
348
+ txHash: TxHash,
349
+ logIndexInTx: number,
350
+ ): Promise<void>;
328
351
  }
@@ -1,6 +1,7 @@
1
1
  import { Aes128 } from '@aztec/foundation/crypto';
2
2
  import { Fr, Point } from '@aztec/foundation/fields';
3
3
  import { applyStringFormatting, createLogger } from '@aztec/foundation/log';
4
+ import type { EventSelector } from '@aztec/stdlib/abi';
4
5
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
5
6
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
6
7
  import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
@@ -9,7 +10,7 @@ import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
9
10
  import { IndexedTaggingSecret, LogWithTxData } from '@aztec/stdlib/logs';
10
11
  import type { NoteStatus } from '@aztec/stdlib/note';
11
12
  import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
12
- import type { BlockHeader, Capsule } from '@aztec/stdlib/tx';
13
+ import type { BlockHeader, Capsule, TxHash } from '@aztec/stdlib/tx';
13
14
 
14
15
  import { type NoteData, TypedOracle } from './acvm/index.js';
15
16
  import type { ExecutionDataProvider } from './execution_data_provider.js';
@@ -376,4 +377,22 @@ export class UnconstrainedExecutionOracle extends TypedOracle {
376
377
  public override getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
377
378
  return this.executionDataProvider.getSharedSecret(address, ephPk);
378
379
  }
380
+
381
+ public override storePrivateEventLog(
382
+ contractAddress: AztecAddress,
383
+ recipient: AztecAddress,
384
+ eventSelector: EventSelector,
385
+ logContent: Fr[],
386
+ txHash: TxHash,
387
+ logIndexInTx: number,
388
+ ): Promise<void> {
389
+ return this.executionDataProvider.storePrivateEventLog(
390
+ contractAddress,
391
+ recipient,
392
+ eventSelector,
393
+ logContent,
394
+ txHash,
395
+ logIndexInTx,
396
+ );
397
+ }
379
398
  }
@@ -17,10 +17,13 @@ export class AvmContractCallResult {
17
17
  public output: Fr[],
18
18
  public gasLeft: AvmGas,
19
19
  public revertReason?: AvmRevertReason,
20
+ public totalInstructions: number = 0, // including nested calls
20
21
  ) {}
21
22
 
22
23
  toString(): string {
23
- let resultsStr = `reverted: ${this.reverted}, output: ${this.output}, gasLeft: ${inspect(this.gasLeft)}`;
24
+ let resultsStr = `reverted: ${this.reverted}, output: ${this.output}, gasLeft: ${inspect(
25
+ this.gasLeft,
26
+ )}, totalInstructions: ${this.totalInstructions}`;
24
27
  if (this.revertReason) {
25
28
  resultsStr += `, revertReason: ${this.revertReason}`;
26
29
  }
@@ -29,7 +32,13 @@ export class AvmContractCallResult {
29
32
 
30
33
  finalize(): AvmFinalizedCallResult {
31
34
  const revertReason = this.revertReason ? createSimulationError(this.revertReason, this.output) : undefined;
32
- return new AvmFinalizedCallResult(this.reverted, this.output, Gas.from(this.gasLeft), revertReason);
35
+ return new AvmFinalizedCallResult(
36
+ this.reverted,
37
+ this.output,
38
+ Gas.from(this.gasLeft),
39
+ revertReason,
40
+ this.totalInstructions,
41
+ );
33
42
  }
34
43
  }
35
44
 
@@ -43,10 +52,13 @@ export class AvmFinalizedCallResult {
43
52
  public output: Fr[],
44
53
  public gasLeft: Gas,
45
54
  public revertReason?: SimulationError,
55
+ public totalInstructions: number = 0, // including nested calls
46
56
  ) {}
47
57
 
48
58
  toString(): string {
49
- let resultsStr = `reverted: ${this.reverted}, output: ${this.output}, gasLeft: ${inspect(this.gasLeft)}`;
59
+ let resultsStr = `reverted: ${this.reverted}, output: ${this.output}, gasLeft: ${inspect(
60
+ this.gasLeft,
61
+ )}, totalInstructions: ${this.totalInstructions}`;
50
62
  if (this.revertReason) {
51
63
  resultsStr += `, revertReason: ${this.revertReason}`;
52
64
  }
@@ -68,6 +68,11 @@ export class AvmMachineState {
68
68
  /** Output data must NOT be modified once it is set */
69
69
  private output: Fr[] = [];
70
70
 
71
+ // Metrics only - not needed for execution
72
+ /** instruction counter, including nested calls */
73
+ public instrCounter: number = 0;
74
+ // End metrics only
75
+
71
76
  constructor(gasLeft: Gas);
72
77
  constructor(l2GasLeft: number, daGasLeft: number);
73
78
  constructor(gasLeftOrL2GasLeft: Gas | number, daGasLeft?: number) {
@@ -147,7 +147,6 @@ export class AvmSimulator {
147
147
  try {
148
148
  // Execute instruction pointed to by the current program counter
149
149
  // continuing until the machine state signifies a halt
150
- let instrCounter = 0;
151
150
  while (!machineState.getHalted()) {
152
151
  // Get the instruction from cache, or deserialize for the first time
153
152
  let cachedInstruction = this.deserializedInstructionsCache.get(machineState.pc);
@@ -163,13 +162,11 @@ export class AvmSimulator {
163
162
  if (this.log.isLevelEnabled('trace')) {
164
163
  // Skip this entirely to avoid toStringing etc if trace is not enabled
165
164
  this.log.trace(
166
- `[PC:${machineState.pc}] [IC:${instrCounter}] ${instruction.toString()} (gasLeft l2=${
165
+ `[PC:${machineState.pc}] [IC:${machineState.instrCounter}] ${instruction.toString()} (gasLeft l2=${
167
166
  machineState.l2GasLeft
168
167
  } da=${machineState.daGasLeft})`,
169
168
  );
170
169
  }
171
- instrCounter++;
172
-
173
170
  machineState.nextPc = machineState.pc + bytesRead;
174
171
 
175
172
  // Execute the instruction.
@@ -181,6 +178,8 @@ export class AvmSimulator {
181
178
  machineState.pc += bytesRead;
182
179
  }
183
180
 
181
+ machineState.instrCounter++;
182
+
184
183
  // gas used by this instruction - used for profiling/tallying
185
184
  const gasUsed: Gas = {
186
185
  l2Gas: instrStartGas.l2Gas - machineState.l2GasLeft,
@@ -197,13 +196,19 @@ export class AvmSimulator {
197
196
  const output = machineState.getOutput();
198
197
  const reverted = machineState.getReverted();
199
198
  const revertReason = reverted ? await revertReasonFromExplicitRevert(output, this.context) : undefined;
200
- const results = new AvmContractCallResult(reverted, output, machineState.gasLeft, revertReason);
199
+ const results = new AvmContractCallResult(
200
+ reverted,
201
+ output,
202
+ machineState.gasLeft,
203
+ revertReason,
204
+ machineState.instrCounter,
205
+ );
201
206
  this.log.debug(`Context execution results: ${results.toString()}`);
202
207
  const totalGasUsed: Gas = {
203
208
  l2Gas: callStartGas.l2Gas - machineState.l2GasLeft,
204
209
  daGas: callStartGas.daGas - machineState.daGasLeft,
205
210
  };
206
- this.log.debug(`Executed ${instrCounter} instructions and consumed ${totalGasUsed.l2Gas} L2 Gas`);
211
+ this.log.debug(`Executed ${machineState.instrCounter} instructions and consumed ${totalGasUsed.l2Gas} L2 Gas`);
207
212
 
208
213
  this.tallyPrintFunction();
209
214
 
@@ -233,7 +238,13 @@ export class AvmSimulator {
233
238
  // Exceptional halts consume all allocated gas
234
239
  const noGasLeft = { l2Gas: 0, daGas: 0 };
235
240
  // Note: "exceptional halts" cannot return data, hence [].
236
- const results = new AvmContractCallResult(/*reverted=*/ true, /*output=*/ [], noGasLeft, revertReason);
241
+ const results = new AvmContractCallResult(
242
+ /*reverted=*/ true,
243
+ /*output=*/ [],
244
+ noGasLeft,
245
+ revertReason,
246
+ machineState.instrCounter,
247
+ );
237
248
  this.log.debug(`Context execution results: ${results.toString()}`);
238
249
 
239
250
  this.tallyPrintFunction();
@@ -9,6 +9,7 @@ import { NativeWorldStateService } from '@aztec/world-state';
9
9
  import { SideEffectTrace } from '../../../public/side_effect_trace.js';
10
10
  import type { AvmContractCallResult } from '../../avm/avm_contract_call_result.js';
11
11
  import {
12
+ DEFAULT_BLOCK_NUMBER,
12
13
  getContractFunctionAbi,
13
14
  getFunctionSelector,
14
15
  initContext,
@@ -16,7 +17,6 @@ import {
16
17
  resolveContractAssertionMessage,
17
18
  } from '../../avm/fixtures/index.js';
18
19
  import { AvmPersistableStateManager } from '../../avm/journal/journal.js';
19
- import { DEFAULT_BLOCK_NUMBER } from '../../fixtures/public_tx_simulation_tester.js';
20
20
  import { PublicContractsDB, PublicTreesDB } from '../../public_db_sources.js';
21
21
  import { AvmSimulator } from '../avm_simulator.js';
22
22
  import { BaseAvmSimulationTester } from './base_avm_simulation_tester.js';
@@ -6,7 +6,7 @@ import { computeFeePayerBalanceStorageSlot, getCanonicalFeeJuice } from '@aztec/
6
6
  import type { ContractArtifact } from '@aztec/stdlib/abi';
7
7
  import { PublicDataWrite } from '@aztec/stdlib/avm';
8
8
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
9
- import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
9
+ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
10
10
  import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec/stdlib/hash';
11
11
  import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
12
12
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -86,12 +86,6 @@ export abstract class BaseAvmSimulationTester {
86
86
  return feeJuice.instance;
87
87
  }
88
88
 
89
- addContractClass(contractClass: ContractClassPublic, contractArtifact: ContractArtifact): Promise<void> {
90
- this.logger.debug(`Adding contract class with Id ${contractClass.id}`);
91
- this.contractDataSource.addContractArtifact(contractClass.id, contractArtifact);
92
- return this.contractDataSource.addContractClass(contractClass);
93
- }
94
-
95
89
  async addContractInstance(contractInstance: ContractInstanceWithAddress, skipNullifierInsertion = false) {
96
90
  if (!skipNullifierInsertion) {
97
91
  await this.insertContractAddressNullifier(contractInstance.address);
@@ -28,7 +28,6 @@ import { mock } from 'jest-mock-extended';
28
28
  import merge from 'lodash.merge';
29
29
 
30
30
  import { resolveAssertionMessageFromRevertData, traverseCauseChain } from '../../../common/index.js';
31
- import { DEFAULT_BLOCK_NUMBER } from '../../fixtures/public_tx_simulation_tester.js';
32
31
  import type { PublicContractsDB, PublicTreesDB } from '../../public_db_sources.js';
33
32
  import type { PublicSideEffectTraceInterface } from '../../side_effect_trace_interface.js';
34
33
  import { AvmContext } from '../avm_context.js';
@@ -42,6 +41,7 @@ import { NullifierManager } from '../journal/nullifiers.js';
42
41
  import { PublicStorage } from '../journal/public_storage.js';
43
42
 
44
43
  export const PUBLIC_DISPATCH_FN_NAME = 'public_dispatch';
44
+ export const DEFAULT_BLOCK_NUMBER = 42;
45
45
 
46
46
  /**
47
47
  * Create a new AVM context with default values.