@aztec/simulator 0.82.2 → 0.82.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dest/private/acvm/oracle/oracle.d.ts +1 -1
- package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/oracle.js +1 -3
- package/dest/public/avm/avm_contract_call_result.d.ts +4 -2
- package/dest/public/avm/avm_contract_call_result.d.ts.map +1 -1
- package/dest/public/avm/avm_contract_call_result.js +9 -5
- package/dest/public/avm/avm_machine_state.d.ts +2 -0
- package/dest/public/avm/avm_machine_state.d.ts.map +1 -1
- package/dest/public/avm/avm_machine_state.js +2 -0
- package/dest/public/avm/avm_simulator.d.ts.map +1 -1
- package/dest/public/avm/avm_simulator.js +5 -6
- package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/avm_simulation_tester.js +1 -2
- package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts +1 -2
- package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/base_avm_simulation_tester.js +0 -5
- package/dest/public/avm/fixtures/index.d.ts +1 -0
- package/dest/public/avm/fixtures/index.d.ts.map +1 -1
- package/dest/public/avm/fixtures/index.js +1 -1
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts +3 -2
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts.map +1 -1
- package/dest/public/avm/fixtures/simple_contract_data_source.js +30 -6
- package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/public/avm/opcodes/external_calls.js +2 -0
- package/dest/public/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/public/avm/opcodes/memory.js +8 -10
- package/dest/public/avm/serialization/instruction_serialization.d.ts +5 -2
- package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/public/avm/serialization/instruction_serialization.js +23 -3
- package/dest/public/executor_metrics.d.ts +11 -3
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +40 -6
- package/dest/public/executor_metrics_interface.d.ts +10 -0
- package/dest/public/executor_metrics_interface.d.ts.map +1 -0
- package/dest/public/executor_metrics_interface.js +1 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +12 -6
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +39 -19
- package/dest/public/hinting_db_sources.d.ts +26 -3
- package/dest/public/hinting_db_sources.d.ts.map +1 -1
- package/dest/public/hinting_db_sources.js +102 -1
- package/dest/public/index.d.ts +1 -1
- package/dest/public/index.d.ts.map +1 -1
- package/dest/public/index.js +1 -1
- package/dest/public/public_db_sources.d.ts +2 -3
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +26 -16
- package/dest/public/public_processor/public_processor.d.ts +1 -1
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +3 -3
- package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts +9 -0
- package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/apps_tests/amm_test.js +237 -0
- package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts +7 -0
- package/dest/public/public_tx_simulator/apps_tests/token_test.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/apps_tests/token_test.js +109 -0
- package/dest/public/public_tx_simulator/index.d.ts +3 -0
- package/dest/public/public_tx_simulator/index.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/index.js +2 -0
- package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts +23 -0
- package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/measured_public_tx_simulator.js +58 -0
- package/dest/public/public_tx_simulator/public_tx_context.d.ts +2 -2
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +9 -7
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +16 -16
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_simulator.js +24 -64
- package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts +19 -0
- package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.js +39 -0
- package/dest/public/test_executor_metrics.d.ts +43 -0
- package/dest/public/test_executor_metrics.d.ts.map +1 -0
- package/dest/public/test_executor_metrics.js +158 -0
- package/package.json +14 -14
- package/src/private/acvm/oracle/oracle.ts +2 -2
- package/src/public/avm/avm_contract_call_result.ts +15 -3
- package/src/public/avm/avm_machine_state.ts +5 -0
- package/src/public/avm/avm_simulator.ts +18 -7
- package/src/public/avm/fixtures/avm_simulation_tester.ts +1 -1
- package/src/public/avm/fixtures/base_avm_simulation_tester.ts +1 -7
- package/src/public/avm/fixtures/index.ts +1 -1
- package/src/public/avm/fixtures/simple_contract_data_source.ts +33 -6
- package/src/public/avm/opcodes/external_calls.ts +3 -0
- package/src/public/avm/opcodes/memory.ts +8 -10
- package/src/public/avm/serialization/instruction_serialization.ts +22 -5
- package/src/public/executor_metrics.ts +54 -6
- package/src/public/executor_metrics_interface.ts +15 -0
- package/src/public/fixtures/public_tx_simulation_tester.ts +74 -18
- package/src/public/hinting_db_sources.ts +184 -3
- package/src/public/index.ts +1 -1
- package/src/public/public_db_sources.ts +36 -23
- package/src/public/public_processor/public_processor.ts +4 -4
- package/src/public/public_tx_simulator/apps_tests/amm_test.ts +316 -0
- package/src/public/public_tx_simulator/apps_tests/token_test.ts +138 -0
- package/src/public/public_tx_simulator/index.ts +2 -0
- package/src/public/public_tx_simulator/measured_public_tx_simulator.ts +111 -0
- package/src/public/public_tx_simulator/public_tx_context.ts +9 -13
- package/src/public/public_tx_simulator/public_tx_simulator.ts +31 -76
- package/src/public/public_tx_simulator/telemetry_public_tx_simulator.ts +62 -0
- package/src/public/test_executor_metrics.ts +222 -0
|
@@ -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,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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
//
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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(),
|