@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.
Files changed (102) hide show
  1. package/README.md +6 -0
  2. package/dest/private/acvm/oracle/oracle.d.ts +1 -1
  3. package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
  4. package/dest/private/acvm/oracle/oracle.js +1 -3
  5. package/dest/public/avm/avm_contract_call_result.d.ts +4 -2
  6. package/dest/public/avm/avm_contract_call_result.d.ts.map +1 -1
  7. package/dest/public/avm/avm_contract_call_result.js +9 -5
  8. package/dest/public/avm/avm_machine_state.d.ts +2 -0
  9. package/dest/public/avm/avm_machine_state.d.ts.map +1 -1
  10. package/dest/public/avm/avm_machine_state.js +2 -0
  11. package/dest/public/avm/avm_simulator.d.ts.map +1 -1
  12. package/dest/public/avm/avm_simulator.js +5 -6
  13. package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
  14. package/dest/public/avm/fixtures/avm_simulation_tester.js +1 -2
  15. package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts +1 -2
  16. package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -1
  17. package/dest/public/avm/fixtures/base_avm_simulation_tester.js +0 -5
  18. package/dest/public/avm/fixtures/index.d.ts +1 -0
  19. package/dest/public/avm/fixtures/index.d.ts.map +1 -1
  20. package/dest/public/avm/fixtures/index.js +1 -1
  21. package/dest/public/avm/fixtures/simple_contract_data_source.d.ts +3 -2
  22. package/dest/public/avm/fixtures/simple_contract_data_source.d.ts.map +1 -1
  23. package/dest/public/avm/fixtures/simple_contract_data_source.js +30 -6
  24. package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
  25. package/dest/public/avm/opcodes/external_calls.js +2 -0
  26. package/dest/public/avm/opcodes/memory.d.ts.map +1 -1
  27. package/dest/public/avm/opcodes/memory.js +8 -10
  28. package/dest/public/avm/serialization/instruction_serialization.d.ts +5 -2
  29. package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -1
  30. package/dest/public/avm/serialization/instruction_serialization.js +23 -3
  31. package/dest/public/executor_metrics.d.ts +11 -3
  32. package/dest/public/executor_metrics.d.ts.map +1 -1
  33. package/dest/public/executor_metrics.js +40 -6
  34. package/dest/public/executor_metrics_interface.d.ts +10 -0
  35. package/dest/public/executor_metrics_interface.d.ts.map +1 -0
  36. package/dest/public/executor_metrics_interface.js +1 -0
  37. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +12 -6
  38. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  39. package/dest/public/fixtures/public_tx_simulation_tester.js +39 -19
  40. package/dest/public/hinting_db_sources.d.ts +26 -3
  41. package/dest/public/hinting_db_sources.d.ts.map +1 -1
  42. package/dest/public/hinting_db_sources.js +102 -1
  43. package/dest/public/index.d.ts +1 -1
  44. package/dest/public/index.d.ts.map +1 -1
  45. package/dest/public/index.js +1 -1
  46. package/dest/public/public_db_sources.d.ts +2 -3
  47. package/dest/public/public_db_sources.d.ts.map +1 -1
  48. package/dest/public/public_db_sources.js +26 -16
  49. package/dest/public/public_processor/public_processor.d.ts +1 -1
  50. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  51. package/dest/public/public_processor/public_processor.js +3 -3
  52. package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts +9 -0
  53. package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts.map +1 -0
  54. package/dest/public/public_tx_simulator/apps_tests/amm_test.js +237 -0
  55. package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts +7 -0
  56. package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts.map +1 -0
  57. package/dest/public/public_tx_simulator/apps_tests/token_test.js +109 -0
  58. package/dest/public/public_tx_simulator/index.d.ts +3 -0
  59. package/dest/public/public_tx_simulator/index.d.ts.map +1 -0
  60. package/dest/public/public_tx_simulator/index.js +2 -0
  61. package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts +23 -0
  62. package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts.map +1 -0
  63. package/dest/public/public_tx_simulator/measured_public_tx_simulator.js +58 -0
  64. package/dest/public/public_tx_simulator/public_tx_context.d.ts +2 -2
  65. package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
  66. package/dest/public/public_tx_simulator/public_tx_context.js +9 -7
  67. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +16 -16
  68. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
  69. package/dest/public/public_tx_simulator/public_tx_simulator.js +24 -64
  70. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts +19 -0
  71. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts.map +1 -0
  72. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.js +39 -0
  73. package/dest/public/test_executor_metrics.d.ts +43 -0
  74. package/dest/public/test_executor_metrics.d.ts.map +1 -0
  75. package/dest/public/test_executor_metrics.js +158 -0
  76. package/package.json +14 -14
  77. package/src/private/acvm/oracle/oracle.ts +2 -2
  78. package/src/public/avm/avm_contract_call_result.ts +15 -3
  79. package/src/public/avm/avm_machine_state.ts +5 -0
  80. package/src/public/avm/avm_simulator.ts +18 -7
  81. package/src/public/avm/fixtures/avm_simulation_tester.ts +1 -1
  82. package/src/public/avm/fixtures/base_avm_simulation_tester.ts +1 -7
  83. package/src/public/avm/fixtures/index.ts +1 -1
  84. package/src/public/avm/fixtures/simple_contract_data_source.ts +33 -6
  85. package/src/public/avm/opcodes/external_calls.ts +3 -0
  86. package/src/public/avm/opcodes/memory.ts +8 -10
  87. package/src/public/avm/serialization/instruction_serialization.ts +22 -5
  88. package/src/public/executor_metrics.ts +54 -6
  89. package/src/public/executor_metrics_interface.ts +15 -0
  90. package/src/public/fixtures/public_tx_simulation_tester.ts +74 -18
  91. package/src/public/hinting_db_sources.ts +184 -3
  92. package/src/public/index.ts +1 -1
  93. package/src/public/public_db_sources.ts +36 -23
  94. package/src/public/public_processor/public_processor.ts +4 -4
  95. package/src/public/public_tx_simulator/apps_tests/amm_test.ts +316 -0
  96. package/src/public/public_tx_simulator/apps_tests/token_test.ts +138 -0
  97. package/src/public/public_tx_simulator/index.ts +2 -0
  98. package/src/public/public_tx_simulator/measured_public_tx_simulator.ts +111 -0
  99. package/src/public/public_tx_simulator/public_tx_context.ts +9 -13
  100. package/src/public/public_tx_simulator/public_tx_simulator.ts +31 -76
  101. package/src/public/public_tx_simulator/telemetry_public_tx_simulator.ts +62 -0
  102. package/src/public/test_executor_metrics.ts +222 -0
@@ -0,0 +1,316 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import type { Logger } from '@aztec/foundation/log';
3
+ import { AMMContractArtifact } from '@aztec/noir-contracts.js/AMM';
4
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
+ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
6
+
7
+ import { PublicTxSimulationTester } from '../../fixtures/public_tx_simulation_tester.js';
8
+ import { deployToken } from './token_test.js';
9
+
10
+ const INITIAL_TOKEN_BALANCE = 1_000_000_000n;
11
+ /**
12
+ * THIS TEST IS BRITTLE! If it breaks, don't try fixing it.
13
+ * `.skip` it or literally just delete it and notify AVM team.
14
+ * You do NOT need permission to remove this test!
15
+ */
16
+ export async function ammTest(tester: PublicTxSimulationTester, logger: Logger) {
17
+ const startTime = performance.now();
18
+
19
+ const admin = AztecAddress.fromNumber(42);
20
+ const sender = AztecAddress.fromNumber(111);
21
+
22
+ logger.debug(`Deploying tokens`);
23
+ const token0 = await deployToken(tester, admin, /*seed=*/ 0);
24
+ const token1 = await deployToken(tester, admin, /*seed=*/ 1);
25
+ const liquidityToken = await deployToken(tester, admin, /*seed=*/ 2);
26
+ logger.debug(`Deploying AMM`);
27
+ const constructorArgs = [token0, token1, liquidityToken];
28
+ const amm = await tester.registerAndDeployContract(
29
+ constructorArgs,
30
+ /*deployer=*/ admin,
31
+ AMMContractArtifact,
32
+ /*skipNullifierInsertion=*/ false,
33
+ /*seed=*/ 3,
34
+ );
35
+
36
+ const ammConstructorResult = await tester.simulateTxWithLabel(
37
+ /*txLabel=*/ 'constructor',
38
+ /*sender=*/ admin,
39
+ /*setupCalls=*/ [],
40
+ /*appCalls=*/ [
41
+ {
42
+ fnName: 'constructor',
43
+ args: constructorArgs,
44
+ address: amm.address,
45
+ },
46
+ ],
47
+ );
48
+ expect(ammConstructorResult.revertCode.isOK()).toBe(true);
49
+
50
+ logger.debug(`Setting AMM as minter for liquidity token`);
51
+
52
+ // set the AMM as the minter for the liquidity token
53
+ const setMinterResult = await tester.simulateTxWithLabel(
54
+ /*txLabel=*/ 'set_minter',
55
+ /*sender=*/ admin,
56
+ /*setupCalls=*/ [],
57
+ /*appCalls=*/ [
58
+ {
59
+ fnName: 'set_minter',
60
+ args: [/*minter=*/ amm, /*approve=*/ true],
61
+ address: liquidityToken.address,
62
+ },
63
+ ],
64
+ );
65
+ expect(setMinterResult.revertCode.isOK()).toBe(true);
66
+
67
+ logger.debug(`Adding liquidity`);
68
+ const amount0Max = (INITIAL_TOKEN_BALANCE * 6n) / 10n;
69
+ const amount0Min = (INITIAL_TOKEN_BALANCE * 4n) / 10n;
70
+ const amount1Max = (INITIAL_TOKEN_BALANCE * 5n) / 10n;
71
+ const amount1Min = (INITIAL_TOKEN_BALANCE * 4n) / 10n;
72
+
73
+ const addLiquidityResult = await addLiquidity(
74
+ tester,
75
+ sender,
76
+ /*amm=*/ amm,
77
+ /*token0=*/ token0,
78
+ /*token1=*/ token1,
79
+ /*liquidityToken=*/ liquidityToken,
80
+ /*amount0Max=*/ amount0Max,
81
+ /*amount1Max=*/ amount1Max,
82
+ /*amount0Min=*/ amount0Min,
83
+ /*amount1Min=*/ amount1Min,
84
+ );
85
+ expect(addLiquidityResult.revertCode.isOK()).toBe(true);
86
+
87
+ logger.debug(`Swapping tokens`);
88
+ const swapResult = await swapExactTokensForTokens(
89
+ tester,
90
+ sender,
91
+ /*amm=*/ amm,
92
+ /*tokenIn=*/ token0,
93
+ /*tokenOut=*/ token1,
94
+ /*amountIn=*/ amount0Min / 10n, // something smaller than total liquidity
95
+ /*amountOutMin=*/ amount1Min / 100n, // something even smaller
96
+ );
97
+ expect(swapResult.revertCode.isOK()).toBe(true);
98
+
99
+ logger.debug(`Removing liquidity`);
100
+ const removeLiquidityResult = await removeLiquidity(
101
+ tester,
102
+ sender,
103
+ /*amm=*/ amm,
104
+ /*token0=*/ token0,
105
+ /*token1=*/ token1,
106
+ /*liquidityToken=*/ liquidityToken,
107
+ /*liquidity=*/ 100n,
108
+ /*amount0Min=*/ 1n, // remove some tiny amount
109
+ /*amount1Min=*/ 1n,
110
+ );
111
+ expect(removeLiquidityResult.revertCode.isOK()).toBe(true);
112
+
113
+ const endTime = performance.now();
114
+
115
+ logger.info(`AMM public tx simulator test took ${endTime - startTime}ms\n`);
116
+ }
117
+
118
+ async function addLiquidity(
119
+ tester: PublicTxSimulationTester,
120
+ sender: AztecAddress,
121
+ amm: ContractInstanceWithAddress,
122
+ token0: ContractInstanceWithAddress,
123
+ token1: ContractInstanceWithAddress,
124
+ liquidityToken: ContractInstanceWithAddress,
125
+ amount0Max: bigint,
126
+ amount1Max: bigint,
127
+ amount0Min: bigint,
128
+ amount1Min: bigint,
129
+ _nonce?: bigint,
130
+ ) {
131
+ const refundToken0PartialNote = {
132
+ commitment: new Fr(42),
133
+ };
134
+ const refundToken1PartialNote = {
135
+ commitment: new Fr(66),
136
+ };
137
+ const liquidityPartialNote = {
138
+ commitment: new Fr(99),
139
+ };
140
+
141
+ return await tester.simulateTxWithLabel(
142
+ /*txLabel=*/ 'add_liquidity',
143
+ /*sender=*/ sender,
144
+ /*setupCalls=*/ [],
145
+ /*appCalls=*/ [
146
+ // token0.transfer_to_public enqueues a call to _increase_public_balance
147
+ {
148
+ sender: token0.address, // INTERNAL FUNCTION! Sender must be 'this'.
149
+ fnName: '_increase_public_balance',
150
+ args: [/*to=*/ amm.address, /*amount=*/ amount0Max],
151
+ address: token0.address,
152
+ },
153
+ // token0.prepare_private_balance_increase enqueues a call to _store_balances_set_partial_note
154
+ {
155
+ sender: token0.address, // INTERNAL FUNCTION! Sender must be 'this'.
156
+ fnName: '_store_balances_set_partial_note',
157
+ args: [refundToken0PartialNote],
158
+ address: token0.address,
159
+ },
160
+ // token1.transfer_to_public enqueues a call to _increase_public_balance
161
+ {
162
+ sender: token1.address, // INTERNAL FUNCTION! Sender must be 'this'.
163
+ fnName: '_increase_public_balance',
164
+ args: [/*to=*/ amm.address, /*amount=*/ amount1Max],
165
+ address: token1.address,
166
+ },
167
+ // token1.prepare_private_balance_increase enqueues a call to _store_balances_set_partial_note
168
+ {
169
+ sender: token1.address, // INTERNAL FUNCTION! Sender must be 'this'.
170
+ fnName: '_store_balances_set_partial_note',
171
+ args: [refundToken1PartialNote],
172
+ address: token1.address,
173
+ },
174
+ // liquidityToken.prepare_private_balance_increase enqueues a call to _store_balances_set_partial_note
175
+ {
176
+ sender: liquidityToken.address, // INTERNAL FUNCTION! Sender must be 'this'.
177
+ fnName: '_store_balances_set_partial_note',
178
+ args: [liquidityPartialNote],
179
+ address: liquidityToken.address,
180
+ },
181
+ // amm.add_liquidity enqueues a call to _add_liquidity
182
+ {
183
+ sender: amm.address, // INTERNAL FUNCTION! Sender must be 'this'.
184
+ fnName: '_add_liquidity',
185
+ args: [
186
+ /*config=*/ {
187
+ token0: token0.address,
188
+ token1: token1.address,
189
+ // eslint-disable-next-line camelcase
190
+ liquidity_token: liquidityToken.address,
191
+ },
192
+ refundToken0PartialNote,
193
+ refundToken1PartialNote,
194
+ liquidityPartialNote,
195
+ amount0Max,
196
+ amount1Max,
197
+ amount0Min,
198
+ amount1Min,
199
+ ],
200
+ address: amm.address,
201
+ },
202
+ ],
203
+ );
204
+ }
205
+
206
+ async function swapExactTokensForTokens(
207
+ tester: PublicTxSimulationTester,
208
+ sender: AztecAddress,
209
+ amm: ContractInstanceWithAddress,
210
+ tokenIn: ContractInstanceWithAddress,
211
+ tokenOut: ContractInstanceWithAddress,
212
+ amountIn: bigint,
213
+ amountOutMin: bigint,
214
+ _nonce?: bigint,
215
+ ) {
216
+ const tokenOutPartialNote = {
217
+ commitment: new Fr(66),
218
+ };
219
+
220
+ return await tester.simulateTxWithLabel(
221
+ /*txLabel=*/ 'swap_exact_tokens_for_tokens',
222
+ /*sender=*/ sender,
223
+ /*setupCalls=*/ [],
224
+ /*appCalls=*/ [
225
+ // tokenIn.transfer_to_public enqueues a call to _increase_public_balance
226
+ {
227
+ sender: tokenIn.address, // INTERNAL FUNCTION! Sender must be 'this'.
228
+ fnName: '_increase_public_balance',
229
+ args: [/*to=*/ amm.address, /*amount=*/ amountIn],
230
+ address: tokenIn.address,
231
+ },
232
+ // tokenOut.prepare_private_balance_increase enqueues a call to _store_balances_set_partial_note
233
+ {
234
+ sender: tokenOut.address, // INTERNAL FUNCTION! Sender must be 'this'.
235
+ fnName: '_store_balances_set_partial_note',
236
+ args: [tokenOutPartialNote],
237
+ address: tokenOut.address,
238
+ },
239
+
240
+ {
241
+ sender: amm.address, // INTERNAL FUNCTION! Sender must be 'this'.
242
+ fnName: '_swap_exact_tokens_for_tokens',
243
+ args: [tokenIn.address, tokenOut.address, amountIn, amountOutMin, tokenOutPartialNote],
244
+ address: amm.address,
245
+ },
246
+ ],
247
+ );
248
+ }
249
+
250
+ async function removeLiquidity(
251
+ tester: PublicTxSimulationTester,
252
+ sender: AztecAddress,
253
+ amm: ContractInstanceWithAddress,
254
+ token0: ContractInstanceWithAddress,
255
+ token1: ContractInstanceWithAddress,
256
+ liquidityToken: ContractInstanceWithAddress,
257
+ liquidity: bigint,
258
+ amount0Min: bigint,
259
+ amount1Min: bigint,
260
+ _nonce?: bigint,
261
+ ) {
262
+ const token0PartialNote = {
263
+ commitment: new Fr(111),
264
+ };
265
+ const token1PartialNote = {
266
+ commitment: new Fr(222),
267
+ };
268
+
269
+ return await tester.simulateTxWithLabel(
270
+ /*txLabel=*/ 'remove_liquidity',
271
+ /*sender=*/ sender,
272
+ /*setupCalls=*/ [],
273
+ /*appCalls=*/ [
274
+ // liquidityToken.transfer_to_public enqueues a call to _increase_public_balance
275
+ {
276
+ sender: liquidityToken.address, // INTERNAL FUNCTION! Sender must be 'this'.
277
+ fnName: '_increase_public_balance',
278
+ args: [/*to=*/ amm.address, /*amount=*/ liquidity],
279
+ address: liquidityToken.address,
280
+ },
281
+ // token0.prepare_private_balance_increase enqueues a call to _store_balances_set_partial_note
282
+ {
283
+ sender: token0.address, // INTERNAL FUNCTION! Sender must be 'this'.
284
+ fnName: '_store_balances_set_partial_note',
285
+ args: [token0PartialNote],
286
+ address: token0.address,
287
+ },
288
+ // token1.prepare_private_balance_increase enqueues a call to _store_balances_set_partial_note
289
+ {
290
+ sender: token1.address, // INTERNAL FUNCTION! Sender must be 'this'.
291
+ fnName: '_store_balances_set_partial_note',
292
+ args: [token1PartialNote],
293
+ address: token1.address,
294
+ },
295
+ // amm.remove_liquidity enqueues a call to _remove_liquidity
296
+ {
297
+ sender: amm.address, // INTERNAL FUNCTION! Sender must be 'this'.
298
+ fnName: '_remove_liquidity',
299
+ args: [
300
+ /*config=*/ {
301
+ token0: token0.address,
302
+ token1: token1.address,
303
+ // eslint-disable-next-line camelcase
304
+ liquidity_token: liquidityToken.address,
305
+ },
306
+ liquidity,
307
+ token0PartialNote,
308
+ token1PartialNote,
309
+ amount0Min,
310
+ amount1Min,
311
+ ],
312
+ address: amm.address,
313
+ },
314
+ ],
315
+ );
316
+ }
@@ -0,0 +1,138 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import type { Logger } from '@aztec/foundation/log';
3
+ import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
4
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
+ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
6
+
7
+ import { PublicTxSimulationTester } from '../../fixtures/public_tx_simulation_tester.js';
8
+
9
+ export async function tokenTest(tester: PublicTxSimulationTester, logger: Logger) {
10
+ const startTime = performance.now();
11
+
12
+ const admin = AztecAddress.fromNumber(42);
13
+ const sender = AztecAddress.fromNumber(111);
14
+ const receiver = AztecAddress.fromNumber(222);
15
+
16
+ const token = await deployToken(tester, admin);
17
+
18
+ const mintAmount = 100n;
19
+ const mintResult = await tester.simulateTxWithLabel(
20
+ /*txLabel=*/ 'mint_to_public',
21
+ /*sender=*/ admin,
22
+ /*setupCalls=*/ [],
23
+ /*appCalls=*/ [
24
+ {
25
+ address: token.address,
26
+ fnName: 'mint_to_public',
27
+ args: [/*to=*/ sender, mintAmount],
28
+ },
29
+ ],
30
+ );
31
+ expect(mintResult.revertCode.isOK()).toBe(true);
32
+ await checkBalance(tester, token, sender, sender, mintAmount);
33
+
34
+ const nonce = new Fr(0);
35
+ const transferAmount = 50n;
36
+ const transferResult = await tester.simulateTxWithLabel(
37
+ /*txLabel=*/ 'transfer_in_public',
38
+ /*sender=*/ sender,
39
+ /*setupCalls=*/ [],
40
+ /*appCalls=*/ [
41
+ {
42
+ address: token.address,
43
+ fnName: 'transfer_in_public',
44
+ args: [/*from=*/ sender, /*to=*/ receiver, transferAmount, nonce],
45
+ },
46
+ ],
47
+ );
48
+ expect(transferResult.revertCode.isOK()).toBe(true);
49
+ await checkBalance(tester, token, sender, receiver, mintAmount - transferAmount);
50
+ await checkBalance(tester, token, sender, receiver, transferAmount);
51
+
52
+ const balResult = await tester.simulateTxWithLabel(
53
+ /*txLabel=*/ 'balance_of_public',
54
+ sender,
55
+ /*setupCalls=*/ [],
56
+ /*appCalls=*/ [
57
+ {
58
+ address: token.address,
59
+ fnName: 'balance_of_public',
60
+ args: [/*owner=*/ receiver],
61
+ isStaticCall: true,
62
+ },
63
+ ],
64
+ );
65
+ expect(balResult.revertCode.isOK()).toBe(true);
66
+
67
+ const burnResult = await tester.simulateTxWithLabel(
68
+ /*txLabel=*/ 'burn_public',
69
+ /*sender=*/ receiver,
70
+ /*setupCalls=*/ [],
71
+ /*appCalls=*/ [
72
+ {
73
+ address: token.address,
74
+ fnName: 'burn_public',
75
+ args: [/*from=*/ receiver, transferAmount, nonce],
76
+ },
77
+ ],
78
+ );
79
+ expect(burnResult.revertCode.isOK()).toBe(true);
80
+ await checkBalance(tester, token, sender, receiver, 0n);
81
+
82
+ const endTime = performance.now();
83
+
84
+ logger.info(`TokenContract public tx simulator test took ${endTime - startTime}ms\n`);
85
+ }
86
+
87
+ export async function deployToken(tester: PublicTxSimulationTester, admin: AztecAddress, seed = 0) {
88
+ const constructorArgs = [admin, /*name=*/ 'Token', /*symbol=*/ 'TOK', /*decimals=*/ new Fr(18)];
89
+ const token = await tester.registerAndDeployContract(
90
+ constructorArgs,
91
+ /*deployer=*/ admin,
92
+ TokenContractArtifact,
93
+ /*skipNullifierInsertion=*/ false,
94
+ seed,
95
+ );
96
+
97
+ const result = await tester.simulateTxWithLabel(
98
+ /*txLabel=*/ 'Token.constructor',
99
+ /*sender=*/ admin,
100
+ /*setupCalls=*/ [],
101
+ /*appCalls=*/ [
102
+ {
103
+ fnName: 'constructor',
104
+ args: constructorArgs,
105
+ address: token.address,
106
+ },
107
+ ],
108
+ );
109
+ expect(result.revertCode.isOK()).toBe(true);
110
+ return token;
111
+ }
112
+
113
+ async function checkBalance(
114
+ tester: PublicTxSimulationTester,
115
+ token: ContractInstanceWithAddress,
116
+ sender: AztecAddress,
117
+ account: AztecAddress,
118
+ expectedBalance: bigint,
119
+ ) {
120
+ const balResult = await tester.simulateTxWithLabel(
121
+ /*txLabel=*/ 'balance_of_public',
122
+ sender,
123
+ /*setupCalls=*/ [],
124
+ /*appCalls=*/ [
125
+ {
126
+ address: token.address,
127
+ fnName: 'balance_of_public',
128
+ args: [/*owner=*/ account],
129
+ isStaticCall: true,
130
+ },
131
+ ],
132
+ );
133
+ expect(balResult.revertCode.isOK()).toBe(true);
134
+ // should be 1 call with 1 return value that is expectedBalance
135
+ expect(balResult.processedPhases).toEqual([
136
+ expect.objectContaining({ returnValues: [expect.objectContaining({ values: [new Fr(expectedBalance)] })] }),
137
+ ]);
138
+ }
@@ -0,0 +1,2 @@
1
+ export * from './public_tx_simulator.js';
2
+ export { TelemetryPublicTxSimulator } from './telemetry_public_tx_simulator.js';
@@ -0,0 +1,111 @@
1
+ import type { Fr } from '@aztec/foundation/fields';
2
+ import { Timer } from '@aztec/foundation/timer';
3
+ import type { Gas } from '@aztec/stdlib/gas';
4
+ import type { AvmSimulationStats } from '@aztec/stdlib/stats';
5
+ import { type GlobalVariables, PublicCallRequestWithCalldata, Tx, TxExecutionPhase } from '@aztec/stdlib/tx';
6
+
7
+ import type { AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js';
8
+ import type { AvmPersistableStateManager } from '../avm/index.js';
9
+ import type { ExecutorMetricsInterface } from '../executor_metrics_interface.js';
10
+ import type { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
11
+ import { PublicTxContext } from './public_tx_context.js';
12
+ import { type ProcessedPhase, type PublicTxResult, PublicTxSimulator } from './public_tx_simulator.js';
13
+
14
+ /**
15
+ * A public tx simulator that tracks miscellaneous simulation metrics without telemetry.
16
+ */
17
+ export class MeasuredPublicTxSimulator extends PublicTxSimulator {
18
+ constructor(
19
+ treesDB: PublicTreesDB,
20
+ contractsDB: PublicContractsDB,
21
+ globalVariables: GlobalVariables,
22
+ doMerkleOperations: boolean = false,
23
+ skipFeeEnforcement: boolean = false,
24
+ protected readonly metrics: ExecutorMetricsInterface,
25
+ ) {
26
+ super(treesDB, contractsDB, globalVariables, doMerkleOperations, skipFeeEnforcement);
27
+ }
28
+
29
+ public override async simulate(tx: Tx, txLabel: string = 'unlabeledTx'): Promise<PublicTxResult> {
30
+ this.metrics.startRecordingTxSimulation(txLabel);
31
+ let avmResult: PublicTxResult | undefined;
32
+ try {
33
+ avmResult = await super.simulate(tx);
34
+ } finally {
35
+ this.metrics.stopRecordingTxSimulation(txLabel, avmResult?.revertCode);
36
+ }
37
+ return avmResult;
38
+ }
39
+
40
+ protected override async computeTxHash(tx: Tx) {
41
+ const timer = new Timer();
42
+ const txHash = await super.computeTxHash(tx);
43
+ this.metrics.recordTxHashComputation(timer.ms());
44
+ return txHash;
45
+ }
46
+
47
+ protected override async insertNonRevertiblesFromPrivate(context: PublicTxContext, tx: Tx) {
48
+ const timer = new Timer();
49
+ await super.insertNonRevertiblesFromPrivate(context, tx);
50
+ this.metrics.recordPrivateEffectsInsertion(timer.us(), 'non-revertible');
51
+ }
52
+
53
+ protected override async insertRevertiblesFromPrivate(context: PublicTxContext, tx: Tx): Promise<boolean> {
54
+ const timer = new Timer();
55
+ const result = await super.insertRevertiblesFromPrivate(context, tx);
56
+ this.metrics.recordPrivateEffectsInsertion(timer.us(), 'revertible');
57
+ return result;
58
+ }
59
+
60
+ protected override async simulatePhase(phase: TxExecutionPhase, context: PublicTxContext): Promise<ProcessedPhase> {
61
+ const timer = new Timer();
62
+ const result = await super.simulatePhase(phase, context);
63
+ result.durationMs = timer.ms();
64
+ return result;
65
+ }
66
+
67
+ protected override async simulateEnqueuedCallInternal(
68
+ stateManager: AvmPersistableStateManager,
69
+ callRequest: PublicCallRequestWithCalldata,
70
+ allocatedGas: Gas,
71
+ transactionFee: Fr,
72
+ fnName: string,
73
+ ): Promise<AvmFinalizedCallResult> {
74
+ const timer = new Timer();
75
+ const result = await super.simulateEnqueuedCallInternal(
76
+ stateManager,
77
+ callRequest,
78
+ allocatedGas,
79
+ transactionFee,
80
+ fnName,
81
+ );
82
+
83
+ this.log.verbose(
84
+ result.reverted
85
+ ? `Simulation of enqueued public call ${fnName} reverted with reason ${result.revertReason}.`
86
+ : `Simulation of enqueued public call ${fnName} completed successfully.`,
87
+ {
88
+ eventName: 'avm-simulation',
89
+ appCircuitName: fnName,
90
+ duration: timer.ms(),
91
+ } satisfies AvmSimulationStats,
92
+ );
93
+
94
+ if (result.reverted) {
95
+ this.metrics.recordEnqueuedCallSimulationFailure(
96
+ fnName,
97
+ timer.ms(),
98
+ allocatedGas.sub(result.gasLeft).l2Gas,
99
+ result.totalInstructions,
100
+ );
101
+ } else {
102
+ this.metrics.recordEnqueuedCallSimulation(
103
+ fnName,
104
+ timer.ms(),
105
+ allocatedGas.sub(result.gasLeft).l2Gas,
106
+ result.totalInstructions,
107
+ );
108
+ }
109
+ return result;
110
+ }
111
+ }
@@ -39,7 +39,7 @@ import { inspect } from 'util';
39
39
 
40
40
  import type { PublicContractsDBInterface } from '../../server.js';
41
41
  import { AvmPersistableStateManager } from '../avm/index.js';
42
- import { HintingPublicContractsDB } from '../hinting_db_sources.js';
42
+ import { HintingPublicContractsDB, HintingPublicTreesDB } from '../hinting_db_sources.js';
43
43
  import type { PublicTreesDB } from '../public_db_sources.js';
44
44
  import { SideEffectArrayLengths, SideEffectTrace } from '../side_effect_trace.js';
45
45
  import { getCallRequestsWithCalldataByPhase } from '../utils.js';
@@ -107,11 +107,11 @@ export class PublicTxContext {
107
107
  // We wrap the DB to collect AVM hints.
108
108
  const hints = new AvmExecutionHints();
109
109
  const hintingContractsDB = new HintingPublicContractsDB(contractsDB, hints);
110
- // TODO: Wrap merkle db.
110
+ const hintingTreesDB = new HintingPublicTreesDB(treesDB, hints);
111
111
 
112
112
  // Transaction level state manager that will be forked for revertible phases.
113
113
  const txStateManager = AvmPersistableStateManager.create(
114
- treesDB,
114
+ hintingTreesDB,
115
115
  hintingContractsDB,
116
116
  trace,
117
117
  doMerkleOperations,
@@ -308,7 +308,7 @@ export class PublicTxContext {
308
308
  /**
309
309
  * Generate the public inputs for the AVM circuit.
310
310
  */
311
- public async generateAvmCircuitPublicInputs(endStateReference: StateReference): Promise<AvmCircuitPublicInputs> {
311
+ public async generateAvmCircuitPublicInputs(): Promise<AvmCircuitPublicInputs> {
312
312
  assert(this.halted, 'Can only get AvmCircuitPublicInputs after tx execution ends');
313
313
  const stateManager = this.state.getActiveStateManager();
314
314
 
@@ -319,14 +319,10 @@ export class PublicTxContext {
319
319
  this.startStateReference.partial.publicDataTree,
320
320
  );
321
321
 
322
- // Will be patched/padded at the end of this fn
323
- const endTreeSnapshots = new TreeSnapshots(
324
- endStateReference.l1ToL2MessageTree,
325
- endStateReference.partial.noteHashTree,
326
- endStateReference.partial.nullifierTree,
327
- endStateReference.partial.publicDataTree,
328
- );
329
-
322
+ // FIXME: We are first creating the PIs with the wrong endTreeSnapshots, then patching them.
323
+ // This is because we need to know the lengths of the accumulated data arrays to pad them.
324
+ // We should refactor this to avoid this hack.
325
+ // We should just get the info we need from the trace, and create the rest of the PIs here.
330
326
  const avmCircuitPublicInputs = this.trace.toAvmCircuitPublicInputs(
331
327
  this.globalVariables,
332
328
  startTreeSnapshots,
@@ -338,7 +334,7 @@ export class PublicTxContext {
338
334
  /*teardownCallRequest=*/ this.teardownCallRequests.length
339
335
  ? this.teardownCallRequests[0].request
340
336
  : PublicCallRequest.empty(),
341
- endTreeSnapshots,
337
+ /*endTreeSnapshots=*/ TreeSnapshots.empty(), // Will be patched/padded at the end of this fn
342
338
  /*endGasUsed=*/ this.getTotalGasUsed(),
343
339
  /*transactionFee=*/ this.getTransactionFeeUnsafe(),
344
340
  /*reverted=*/ !this.revertCode.isOK(),