@aztec/simulator 0.0.1-commit.2eb6648a → 0.0.1-commit.343b43af6

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 (66) hide show
  1. package/README.md +4 -4
  2. package/dest/private/circuit_recording/circuit_recorder.js +2 -2
  3. package/dest/public/avm/avm_gas.js +3 -3
  4. package/dest/public/avm/fixtures/account_proof_fetcher.d.ts +2 -0
  5. package/dest/public/avm/fixtures/account_proof_fetcher.d.ts.map +1 -0
  6. package/dest/public/avm/fixtures/account_proof_fetcher.js +152 -0
  7. package/dest/public/avm/opcodes/accrued_substate.d.ts +2 -2
  8. package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
  9. package/dest/public/avm/opcodes/accrued_substate.js +3 -4
  10. package/dest/public/avm/serialization/bytecode_serialization.js +3 -3
  11. package/dest/public/avm/serialization/instruction_serialization.d.ts +2 -2
  12. package/dest/public/avm/serialization/instruction_serialization.d.ts.map +1 -1
  13. package/dest/public/avm/serialization/instruction_serialization.js +1 -1
  14. package/dest/public/fixtures/amm_test.js +2 -2
  15. package/dest/public/fixtures/opcode_spammer.d.ts +1 -1
  16. package/dest/public/fixtures/opcode_spammer.d.ts.map +1 -1
  17. package/dest/public/fixtures/opcode_spammer.js +6 -6
  18. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +6 -5
  19. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  20. package/dest/public/fixtures/public_tx_simulation_tester.js +36 -9
  21. package/dest/public/fixtures/utils.d.ts +2 -2
  22. package/dest/public/fixtures/utils.d.ts.map +1 -1
  23. package/dest/public/fixtures/utils.js +6 -6
  24. package/dest/public/hinting_db_sources.d.ts +2 -2
  25. package/dest/public/hinting_db_sources.d.ts.map +1 -1
  26. package/dest/public/hinting_db_sources.js +1 -1
  27. package/dest/public/public_processor/guarded_merkle_tree.d.ts +2 -2
  28. package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
  29. package/dest/public/public_processor/guarded_merkle_tree.js +1 -1
  30. package/dest/public/public_processor/public_processor.d.ts +5 -3
  31. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  32. package/dest/public/public_processor/public_processor.js +43 -31
  33. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts +1 -1
  34. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts.map +1 -1
  35. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.js +2 -3
  36. package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.d.ts +1 -1
  37. package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.d.ts.map +1 -1
  38. package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.js +2 -2
  39. package/dest/public/public_tx_simulator/factories.d.ts +2 -2
  40. package/dest/public/public_tx_simulator/factories.d.ts.map +1 -1
  41. package/dest/public/public_tx_simulator/factories.js +2 -2
  42. package/dest/public/public_tx_simulator/public_tx_simulator.js +2 -2
  43. package/dest/public/test_executor_metrics.d.ts +6 -1
  44. package/dest/public/test_executor_metrics.d.ts.map +1 -1
  45. package/dest/public/test_executor_metrics.js +22 -0
  46. package/package.json +16 -16
  47. package/src/private/circuit_recording/circuit_recorder.ts +2 -2
  48. package/src/public/avm/avm_gas.ts +2 -2
  49. package/src/public/avm/fixtures/account_proof.json +553 -0
  50. package/src/public/avm/fixtures/account_proof_fetcher.ts +166 -0
  51. package/src/public/avm/opcodes/accrued_substate.ts +3 -4
  52. package/src/public/avm/serialization/bytecode_serialization.ts +2 -2
  53. package/src/public/avm/serialization/instruction_serialization.ts +1 -1
  54. package/src/public/fixtures/amm_test.ts +2 -2
  55. package/src/public/fixtures/opcode_spammer.ts +6 -10
  56. package/src/public/fixtures/public_tx_simulation_tester.ts +51 -5
  57. package/src/public/fixtures/utils.ts +6 -5
  58. package/src/public/fuzzing/avm_fuzzer_simulator.ts +1 -1
  59. package/src/public/hinting_db_sources.ts +1 -1
  60. package/src/public/public_processor/guarded_merkle_tree.ts +1 -1
  61. package/src/public/public_processor/public_processor.ts +57 -42
  62. package/src/public/public_tx_simulator/cpp_public_tx_simulator.ts +2 -3
  63. package/src/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.ts +2 -2
  64. package/src/public/public_tx_simulator/factories.ts +2 -1
  65. package/src/public/public_tx_simulator/public_tx_simulator.ts +3 -3
  66. package/src/public/test_executor_metrics.ts +24 -0
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Fetches an account proof from the Ethereum mainnet and saves it as account_proof.json.
3
+ * This script is not using any Aztec library code, so it's easily portable.
4
+ */
5
+ import fs from 'fs';
6
+ import { dirname, join } from 'path';
7
+ import { fileURLToPath } from 'url';
8
+ import { createPublicClient, fromRlp, hexToBytes, http } from 'viem';
9
+ import { mainnet } from 'viem/chains';
10
+
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+
13
+ const RPC_URL = process.env.RPC_URL;
14
+ const ADDRESS = (process.env.ADDRESS || '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') as `0x${string}`;
15
+ const BLOCK_TAG = process.env.BLOCK_NUMBER ? BigInt(process.env.BLOCK_NUMBER) : 'latest';
16
+ const MAX_ACCOUNT_PATH = 15;
17
+
18
+ function padTo(arr: number[], len: number) {
19
+ return [...arr, ...Array(len - arr.length).fill(0)].slice(0, len);
20
+ }
21
+
22
+ function toBytes(hex: `0x${string}`) {
23
+ return Array.from(hexToBytes(hex));
24
+ }
25
+
26
+ function bytesToU64s(bytes: number[]) {
27
+ const paddedBytes = padTo(bytes, 32);
28
+ return Array.from({ length: 4 }, (_, i) => {
29
+ let val = 0n;
30
+ for (let j = 0; j < 8; j++) {
31
+ val += BigInt(paddedBytes[i * 8 + j]) << BigInt(j * 8);
32
+ }
33
+ return val.toString();
34
+ });
35
+ }
36
+
37
+ function toBytesAndLen(val: bigint | number) {
38
+ if (val === 0n || val === 0) {
39
+ return { bytes: [0], length: 0 };
40
+ }
41
+ let hex = val.toString(16);
42
+ if (hex.length % 2) {
43
+ hex = '0' + hex;
44
+ }
45
+ const bytes = toBytes(`0x${hex}`);
46
+ return { bytes, length: bytes.length };
47
+ }
48
+
49
+ function parseNode(rlp: `0x${string}`) {
50
+ // Should be safe when working with branches and extensions without embedded children.
51
+ const decoded = fromRlp(rlp) as `0x${string}`[];
52
+ const node = {
53
+ rows: Array(16)
54
+ .fill(0)
55
+ .map(() => Array(32).fill(0)),
56
+ row_exist: Array(16).fill(false),
57
+ node_type: 0,
58
+ };
59
+
60
+ if (decoded.length === 17) {
61
+ for (let i = 0; i < 16; i++) {
62
+ if (decoded[i] !== '0x') {
63
+ node.row_exist[i] = true;
64
+ node.rows[i] = padTo(toBytes(decoded[i]), 32);
65
+ }
66
+ }
67
+ } else if (decoded.length === 2) {
68
+ const keyBytes = toBytes(decoded[0]);
69
+ const prefix = keyBytes[0];
70
+ if (prefix >> 4 >= 2) {
71
+ throw new Error('Unsupported: leaf node in proof path');
72
+ }
73
+ node.node_type = 1;
74
+ // Extension header format expected by the noir code: check out storage_proof types.nr.
75
+ node.rows[0][0] = prefix >> 4;
76
+ node.rows[0][8] = prefix & 0x0f;
77
+ node.rows[0][16] = keyBytes.length - 1;
78
+
79
+ for (let i = 1; i < keyBytes.length && i < 32; i++) {
80
+ node.rows[1][i - 1] = keyBytes[i];
81
+ }
82
+ node.rows[2] = padTo(toBytes(decoded[1]), 32);
83
+ node.row_exist[0] = node.row_exist[1] = node.row_exist[2] = true;
84
+ }
85
+ return node;
86
+ }
87
+
88
+ function parseProof(proof: `0x${string}`[], maxLen: number) {
89
+ const nodes = proof.slice(0, -1).slice(0, maxLen).map(parseNode);
90
+ while (nodes.length < maxLen) {
91
+ nodes.push({
92
+ rows: Array(16)
93
+ .fill(0)
94
+ .map(() => Array(32).fill(0)),
95
+ row_exist: Array(16).fill(false),
96
+ node_type: 0,
97
+ });
98
+ }
99
+ return nodes;
100
+ }
101
+
102
+ function nodeToLibFormat(node: { rows: number[][]; row_exist: boolean[]; node_type: number }) {
103
+ return {
104
+ rows: node.rows.map(bytesToU64s),
105
+ row_exist: node.row_exist,
106
+ node_type: String(node.node_type),
107
+ };
108
+ }
109
+
110
+ async function main() {
111
+ if (!RPC_URL) {
112
+ throw new Error('RPC_URL is not set');
113
+ }
114
+ console.log(`Fetching account proof for ${ADDRESS}`);
115
+
116
+ const client = createPublicClient({
117
+ chain: mainnet,
118
+ transport: http(RPC_URL),
119
+ });
120
+
121
+ const [blockNumber, proof, block] = await Promise.all([
122
+ client.getBlockNumber(),
123
+ client.getProof({
124
+ address: ADDRESS,
125
+ storageKeys: [],
126
+ blockNumber: BLOCK_TAG === 'latest' ? undefined : BLOCK_TAG,
127
+ }),
128
+ client.getBlock({
129
+ blockNumber: BLOCK_TAG === 'latest' ? undefined : BLOCK_TAG,
130
+ }),
131
+ ]);
132
+
133
+ console.log(`Block: ${blockNumber}, Account nodes: ${proof.accountProof.length}`);
134
+
135
+ // The -1 is because the last node in the proof is the leaf, which is excluded from path verification.
136
+ const accountPathLen = proof.accountProof.length - 1;
137
+ if (accountPathLen > MAX_ACCOUNT_PATH) {
138
+ throw new Error(
139
+ `Account proof path length ${accountPathLen} exceeds MAX_ACCOUNT_PATH ${MAX_ACCOUNT_PATH}. Increase the limit.`,
140
+ );
141
+ }
142
+
143
+ const nonce = toBytesAndLen(proof.nonce);
144
+ const balance = toBytesAndLen(proof.balance);
145
+
146
+ const data = {
147
+ block_number: String(blockNumber),
148
+ node_length: String(accountPathLen),
149
+ root: bytesToU64s(toBytes(block.stateRoot)),
150
+ nodes: parseProof(proof.accountProof, MAX_ACCOUNT_PATH).map(nodeToLibFormat),
151
+ account: {
152
+ address: toBytes(ADDRESS).map(String),
153
+ balance: padTo(balance.bytes, 32).map(String),
154
+ balance_length: String(balance.length),
155
+ code_hash: bytesToU64s(toBytes(proof.codeHash)),
156
+ nonce: padTo(nonce.bytes, 8).map(String),
157
+ nonce_length: String(nonce.length),
158
+ storage_hash: bytesToU64s(toBytes(proof.storageHash)),
159
+ },
160
+ };
161
+
162
+ fs.writeFileSync(join(__dirname, 'account_proof.json'), JSON.stringify(data, null, 2));
163
+ console.log('account_proof.json generated');
164
+ }
165
+
166
+ main().catch(console.error);
@@ -204,10 +204,9 @@ export class L1ToL2MessageExists extends Instruction {
204
204
  }
205
205
  }
206
206
 
207
- export class EmitUnencryptedLog extends Instruction {
208
- // TODO(#11124): rename unencrypted -> public
209
- static type: string = 'EMITUNENCRYPTEDLOG';
210
- static readonly opcode: Opcode = Opcode.EMITUNENCRYPTEDLOG;
207
+ export class EmitPublicLog extends Instruction {
208
+ static type: string = 'EMITPUBLICLOG';
209
+ static readonly opcode: Opcode = Opcode.EMITPUBLICLOG;
211
210
  // Informs (de)serialization. See Instruction.deserialize.
212
211
  static readonly wireFormat = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT16, OperandType.UINT16];
213
212
 
@@ -19,7 +19,7 @@ import {
19
19
  EcAdd,
20
20
  EmitNoteHash,
21
21
  EmitNullifier,
22
- EmitUnencryptedLog,
22
+ EmitPublicLog,
23
23
  Eq,
24
24
  FieldDiv,
25
25
  GetContractInstance,
@@ -129,7 +129,7 @@ export const INSTRUCTION_SET = new Map<Opcode, InstructionDeserializer>([
129
129
  [L1ToL2MessageExists.opcode, Instruction.fromBuffer.bind(L1ToL2MessageExists)], // Messages
130
130
 
131
131
  // Accrued Substate
132
- [EmitUnencryptedLog.opcode, Instruction.fromBuffer.bind(EmitUnencryptedLog)],
132
+ [EmitPublicLog.opcode, Instruction.fromBuffer.bind(EmitPublicLog)],
133
133
  [SendL2ToL1Message.opcode, Instruction.fromBuffer.bind(SendL2ToL1Message)],
134
134
  [GetContractInstance.opcode, Instruction.fromBuffer.bind(GetContractInstance)],
135
135
 
@@ -70,7 +70,7 @@ export enum Opcode {
70
70
  EMITNULLIFIER,
71
71
  L1TOL2MSGEXISTS,
72
72
  GETCONTRACTINSTANCE,
73
- EMITUNENCRYPTEDLOG,
73
+ EMITPUBLICLOG,
74
74
  SENDL2TOL1MSG,
75
75
  // External calls
76
76
  CALL,
@@ -1,4 +1,4 @@
1
- import { GeneratorIndex } from '@aztec/constants';
1
+ import { DomainSeparator } from '@aztec/constants';
2
2
  import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto/poseidon';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
4
  import type { Logger } from '@aztec/foundation/log';
@@ -326,6 +326,6 @@ async function removeLiquidity(
326
326
  async function computePartialNoteValidityCommitment(partialNote: { commitment: Fr }, completer: AztecAddress) {
327
327
  return await poseidon2HashWithSeparator(
328
328
  [partialNote.commitment, completer],
329
- GeneratorIndex.PARTIAL_NOTE_VALIDITY_COMMITMENT,
329
+ DomainSeparator.PARTIAL_NOTE_VALIDITY_COMMITMENT,
330
330
  );
331
331
  }
@@ -143,7 +143,7 @@
143
143
  * - `EMITNOTEHASH`: max 64 per TX
144
144
  * - `EMITNULLIFIER`: max 63 per TX (one reserved for TX nullifier)
145
145
  * - `SENDL2TOL1MSG`: max 8 per TX
146
- * - `EMITUNENCRYPTEDLOG`: limited by total log payload size
146
+ * - `EMITPUBLICLOG`: limited by total log payload size
147
147
  *
148
148
  * By having the inner contract REVERT after emitting side effects, those effects are discarded, allowing the outer contract to call it again. This enables thousands of opcode executions per TX instead of just the limit.
149
149
  *
@@ -182,7 +182,7 @@ import {
182
182
  EcAdd,
183
183
  EmitNoteHash,
184
184
  EmitNullifier,
185
- EmitUnencryptedLog,
185
+ EmitPublicLog,
186
186
  Eq,
187
187
  FieldDiv,
188
188
  GetContractInstance,
@@ -1242,17 +1242,15 @@ export const SPAM_CONFIGS: Partial<Record<Opcode, SpamConfig[]>> = {
1242
1242
  },
1243
1243
  ],
1244
1244
 
1245
- // EMITUNENCRYPTEDLOG - two configs: minimal (many small logs) and max-size (one large log)
1246
- [Opcode.EMITUNENCRYPTEDLOG]: [
1245
+ // EMITPUBLICLOG - two configs: minimal (many small logs) and max-size (one large log)
1246
+ [Opcode.EMITPUBLICLOG]: [
1247
1247
  {
1248
1248
  label: 'Many empty logs, revert, repeat',
1249
1249
  setup: [
1250
1250
  { offset: 0, value: new Uint32(0n) }, // logSize = 0 fields (minimal)
1251
1251
  { offset: 1, value: new Uint32(0n) }, // revertSize
1252
1252
  ],
1253
- targetInstructions: () => [
1254
- new EmitUnencryptedLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 1),
1255
- ], // logOffset doesn't matter when size is 0
1253
+ targetInstructions: () => [new EmitPublicLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 1)], // logOffset doesn't matter when size is 0
1256
1254
  cleanupInstructions: () => [
1257
1255
  new Revert(/*addressing_mode=*/ 0, /*retSizeOffset=*/ 1, /*returnOffset=*/ 0).as(
1258
1256
  Opcode.REVERT_8,
@@ -1276,9 +1274,7 @@ export const SPAM_CONFIGS: Partial<Record<Opcode, SpamConfig[]>> = {
1276
1274
  // value: new Field(0n),
1277
1275
  //})),
1278
1276
  ],
1279
- targetInstructions: () => [
1280
- new EmitUnencryptedLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 2),
1281
- ], // uses logOffset 2 (uninitialized Field(0))
1277
+ targetInstructions: () => [new EmitPublicLog(/*addressing_mode=*/ 0, /*logSizeOffset=*/ 0, /*logOffset=*/ 2)], // uses logOffset 2 (uninitialized Field(0))
1282
1278
  cleanupInstructions: () => [
1283
1279
  new Revert(/*addressing_mode=*/ 0, /*retSizeOffset=*/ 1, /*returnOffset=*/ 0).as(
1284
1280
  Opcode.REVERT_8,
@@ -1,4 +1,9 @@
1
- import { DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT } from '@aztec/constants';
1
+ import {
2
+ DEFAULT_TEARDOWN_DA_GAS_LIMIT,
3
+ DEFAULT_TEARDOWN_L2_GAS_LIMIT,
4
+ PUBLIC_TX_L2_GAS_OVERHEAD,
5
+ TX_DA_GAS_OVERHEAD,
6
+ } from '@aztec/constants';
2
7
  import { asyncMap } from '@aztec/foundation/async-map';
3
8
  import { BlockNumber } from '@aztec/foundation/branded-types';
4
9
  import { Fr } from '@aztec/foundation/curves/bn254';
@@ -112,6 +117,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
112
117
  feePayer: AztecAddress = sender,
113
118
  /* need some unique first nullifier for note-nonce computations */
114
119
  privateInsertions: TestPrivateInsertions = { nonRevertible: { nullifiers: [new Fr(420000 + this.txCount)] } },
120
+ gasLimits?: Gas,
115
121
  ): Promise<Tx> {
116
122
  const setupCallRequests = await asyncMap(setupCalls, call =>
117
123
  this.#createPubicCallRequestForCall(call, call.sender ?? sender),
@@ -131,9 +137,13 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
131
137
  teardownCallRequest,
132
138
  feePayer,
133
139
  /*gasUsedByPrivate*/ teardownCall
134
- ? new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT)
135
- : Gas.empty(),
140
+ ? new Gas(
141
+ DEFAULT_TEARDOWN_DA_GAS_LIMIT + TX_DA_GAS_OVERHEAD,
142
+ DEFAULT_TEARDOWN_L2_GAS_LIMIT + PUBLIC_TX_L2_GAS_OVERHEAD,
143
+ )
144
+ : new Gas(TX_DA_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD),
136
145
  defaultGlobals(),
146
+ gasLimits,
137
147
  );
138
148
  }
139
149
 
@@ -146,8 +156,9 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
146
156
  /* need some unique first nullifier for note-nonce computations */
147
157
  privateInsertions?: TestPrivateInsertions,
148
158
  txLabel: string = 'unlabeledTx',
159
+ gasLimits?: Gas,
149
160
  ): Promise<PublicTxResult> {
150
- const tx = await this.createTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions);
161
+ const tx = await this.createTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions, gasLimits);
151
162
 
152
163
  await this.setFeePayerBalance(feePayer);
153
164
 
@@ -161,6 +172,8 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
161
172
  }
162
173
  const avmResult = await this.simulator.simulate(tx, fullTxLabel);
163
174
 
175
+ await this.#recordBytecodeSizes(fullTxLabel, [...setupCalls, ...appCalls, ...(teardownCall ? [teardownCall] : [])]);
176
+
164
177
  // Something like this is often useful for debugging:
165
178
  //if (avmResult.revertReason) {
166
179
  // // resolve / enrich revert reason
@@ -190,8 +203,18 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
190
203
  teardownCall?: TestEnqueuedCall,
191
204
  feePayer?: AztecAddress,
192
205
  privateInsertions?: TestPrivateInsertions,
206
+ gasLimits?: Gas,
193
207
  ): Promise<PublicTxResult> {
194
- return await this.simulateTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions, txLabel);
208
+ return await this.simulateTx(
209
+ sender,
210
+ setupCalls,
211
+ appCalls,
212
+ teardownCall,
213
+ feePayer,
214
+ privateInsertions,
215
+ txLabel,
216
+ gasLimits,
217
+ );
195
218
  }
196
219
 
197
220
  /**
@@ -209,6 +232,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
209
232
  teardownCall?: TestEnqueuedCall,
210
233
  feePayer?: AztecAddress,
211
234
  privateInsertions?: TestPrivateInsertions,
235
+ gasLimits?: Gas,
212
236
  ): Promise<PublicTxResult> {
213
237
  return await this.simulateTxWithLabel(
214
238
  txLabel,
@@ -218,6 +242,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
218
242
  teardownCall,
219
243
  feePayer,
220
244
  privateInsertions,
245
+ gasLimits,
221
246
  );
222
247
  }
223
248
 
@@ -277,6 +302,27 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
277
302
 
278
303
  return new PublicCallRequestWithCalldata(request, calldata);
279
304
  }
305
+
306
+ // WARNING: Deduplicates by artifact name, so two different artifacts with the same name
307
+ // in a single tx would only record the first one's bytecode size.
308
+ async #recordBytecodeSizes(txLabel: string, calls: TestEnqueuedCall[]) {
309
+ const seenArtifactNames = new Set<string>();
310
+ for (const call of calls) {
311
+ const artifact = await this.contractDataSource.getContractArtifact(call.address);
312
+ if (!artifact || seenArtifactNames.has(artifact.name)) {
313
+ continue;
314
+ }
315
+ seenArtifactNames.add(artifact.name);
316
+ const instance = await this.contractDataSource.getContract(call.address);
317
+ if (!instance) {
318
+ continue;
319
+ }
320
+ const contractClass = await this.contractDataSource.getContractClass(instance.currentContractClassId);
321
+ if (contractClass) {
322
+ this.metrics.recordBytecodeSize(txLabel, artifact.name, contractClass.packedBytecode.length);
323
+ }
324
+ }
325
+ }
280
326
  }
281
327
 
282
328
  export function defaultGlobals() {
@@ -62,13 +62,14 @@ export async function createTxForPublicCalls(
62
62
  feePayer = AztecAddress.zero(),
63
63
  gasUsedByPrivate: Gas = Gas.empty(),
64
64
  globals: GlobalVariables = GlobalVariables.empty(),
65
+ gasLimits?: Gas,
65
66
  ): Promise<Tx> {
66
67
  assert(
67
68
  setupCallRequests.length > 0 || appCallRequests.length > 0 || teardownCallRequest !== undefined,
68
69
  "Can't create public tx with no enqueued calls",
69
70
  );
70
71
  // use max limits
71
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
72
+ gasLimits = gasLimits ?? new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
72
73
 
73
74
  const forPublic = PartialPrivateTailPublicInputsForPublic.empty();
74
75
 
@@ -134,13 +135,13 @@ export async function createTxForPublicCalls(
134
135
  const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
135
136
  const header = BlockHeader.empty({ globalVariables: globals });
136
137
  const constantData = new TxConstantData(header, txContext, Fr.zero(), Fr.zero());
137
- const includeByTimestamp = 0n; // Not used in the simulator.
138
+ const expirationTimestamp = 0n; // Not used in the simulator.
138
139
 
139
140
  const txData = new PrivateKernelTailCircuitPublicInputs(
140
141
  constantData,
141
142
  /*gasUsed=*/ gasUsedByPrivate,
142
143
  feePayer,
143
- includeByTimestamp,
144
+ expirationTimestamp,
144
145
  forPublic,
145
146
  );
146
147
 
@@ -171,13 +172,13 @@ export async function createTxForPrivateOnly(
171
172
  const gasSettings = new GasSettings(gasLimits, Gas.empty(), maxFeesPerGas, GasFees.empty());
172
173
  const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
173
174
  const constantData = new TxConstantData(BlockHeader.empty(), txContext, Fr.zero(), Fr.zero());
174
- const includeByTimestamp = 0n; // Not used in the simulator.
175
+ const expirationTimestamp = 0n; // Not used in the simulator.
175
176
 
176
177
  const txData = new PrivateKernelTailCircuitPublicInputs(
177
178
  constantData,
178
179
  /*gasUsed=*/ gasUsedByPrivate,
179
180
  feePayer,
180
- includeByTimestamp,
181
+ expirationTimestamp,
181
182
  /*forPublic=*/ undefined,
182
183
  forRollup,
183
184
  );
@@ -146,7 +146,7 @@ async function createTxFromHint(cppTx: AvmTxHint): Promise<Tx> {
146
146
  constants,
147
147
  cppTx.gasUsedByPrivate,
148
148
  cppTx.feePayer,
149
- 0n, // includeByTimestamp
149
+ 0n, // expirationTimestamp
150
150
  forPublic,
151
151
  undefined, // forRollup - not needed for public simulation
152
152
  );
@@ -572,7 +572,7 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
572
572
  return await this.db.close();
573
573
  }
574
574
 
575
- async [Symbol.dispose](): Promise<void> {
575
+ async [Symbol.asyncDispose](): Promise<void> {
576
576
  await this.close();
577
577
  }
578
578
 
@@ -82,7 +82,7 @@ export class GuardedMerkleTreeOperations implements MerkleTreeWriteOperations {
82
82
  return this.guardAndPush(() => this.target.close());
83
83
  }
84
84
 
85
- async [Symbol.dispose](): Promise<void> {
85
+ async [Symbol.asyncDispose](): Promise<void> {
86
86
  await this.close();
87
87
  }
88
88
  getTreeInfo(treeId: MerkleTreeId): Promise<TreeInfo> {