@aztec/simulator 0.87.7 → 1.0.0-nightly.20250605

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 (105) hide show
  1. package/dest/public/avm/avm_gas.d.ts +4 -5
  2. package/dest/public/avm/avm_gas.d.ts.map +1 -1
  3. package/dest/public/avm/avm_gas.js +29 -19
  4. package/dest/public/avm/fixtures/utils.js +1 -1
  5. package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
  6. package/dest/public/avm/opcodes/accrued_substate.js +8 -7
  7. package/dest/public/avm/opcodes/addressing_mode.d.ts +2 -0
  8. package/dest/public/avm/opcodes/addressing_mode.d.ts.map +1 -1
  9. package/dest/public/avm/opcodes/addressing_mode.js +6 -0
  10. package/dest/public/avm/opcodes/arithmetic.d.ts.map +1 -1
  11. package/dest/public/avm/opcodes/arithmetic.js +1 -1
  12. package/dest/public/avm/opcodes/bitwise.d.ts +5 -1
  13. package/dest/public/avm/opcodes/bitwise.d.ts.map +1 -1
  14. package/dest/public/avm/opcodes/bitwise.js +17 -2
  15. package/dest/public/avm/opcodes/comparators.d.ts.map +1 -1
  16. package/dest/public/avm/opcodes/comparators.js +1 -1
  17. package/dest/public/avm/opcodes/contract.d.ts.map +1 -1
  18. package/dest/public/avm/opcodes/contract.js +1 -1
  19. package/dest/public/avm/opcodes/control_flow.d.ts.map +1 -1
  20. package/dest/public/avm/opcodes/control_flow.js +4 -4
  21. package/dest/public/avm/opcodes/conversion.d.ts +1 -0
  22. package/dest/public/avm/opcodes/conversion.d.ts.map +1 -1
  23. package/dest/public/avm/opcodes/conversion.js +263 -2
  24. package/dest/public/avm/opcodes/ec_add.d.ts.map +1 -1
  25. package/dest/public/avm/opcodes/ec_add.js +1 -1
  26. package/dest/public/avm/opcodes/environment_getters.d.ts.map +1 -1
  27. package/dest/public/avm/opcodes/environment_getters.js +1 -1
  28. package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
  29. package/dest/public/avm/opcodes/external_calls.js +6 -8
  30. package/dest/public/avm/opcodes/hashing.d.ts.map +1 -1
  31. package/dest/public/avm/opcodes/hashing.js +3 -3
  32. package/dest/public/avm/opcodes/instruction.d.ts +9 -3
  33. package/dest/public/avm/opcodes/instruction.d.ts.map +1 -1
  34. package/dest/public/avm/opcodes/instruction.js +12 -7
  35. package/dest/public/avm/opcodes/memory.d.ts.map +1 -1
  36. package/dest/public/avm/opcodes/memory.js +8 -6
  37. package/dest/public/avm/opcodes/misc.js +1 -3
  38. package/dest/public/avm/opcodes/storage.d.ts.map +1 -1
  39. package/dest/public/avm/opcodes/storage.js +5 -3
  40. package/dest/public/fixtures/index.d.ts +1 -0
  41. package/dest/public/fixtures/index.d.ts.map +1 -1
  42. package/dest/public/fixtures/index.js +1 -0
  43. package/dest/public/fixtures/minimal_public_tx.d.ts +9 -0
  44. package/dest/public/fixtures/minimal_public_tx.d.ts.map +1 -0
  45. package/dest/public/fixtures/minimal_public_tx.js +43 -0
  46. package/dest/public/fixtures/utils.js +3 -3
  47. package/dest/public/hinting_db_sources.d.ts +3 -0
  48. package/dest/public/hinting_db_sources.d.ts.map +1 -1
  49. package/dest/public/hinting_db_sources.js +9 -0
  50. package/dest/public/index.d.ts +2 -1
  51. package/dest/public/index.d.ts.map +1 -1
  52. package/dest/public/index.js +2 -1
  53. package/dest/public/public_db_sources.d.ts.map +1 -1
  54. package/dest/public/public_db_sources.js +2 -2
  55. package/dest/public/public_processor/guarded_merkle_tree.d.ts +44 -0
  56. package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -0
  57. package/dest/public/public_processor/guarded_merkle_tree.js +105 -0
  58. package/dest/public/public_processor/public_processor.d.ts +6 -16
  59. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  60. package/dest/public/public_processor/public_processor.js +32 -16
  61. package/dest/public/public_tx_simulator/public_tx_context.d.ts +3 -1
  62. package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
  63. package/dest/public/public_tx_simulator/public_tx_context.js +18 -15
  64. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
  65. package/dest/public/public_tx_simulator/public_tx_simulator.js +0 -3
  66. package/dest/public/side_effect_trace.d.ts +4 -1
  67. package/dest/public/side_effect_trace.d.ts.map +1 -1
  68. package/dest/public/side_effect_trace.js +13 -2
  69. package/dest/public/side_effect_trace_interface.d.ts +1 -0
  70. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  71. package/dest/public/state_manager/state_manager.d.ts +1 -0
  72. package/dest/public/state_manager/state_manager.d.ts.map +1 -1
  73. package/dest/public/state_manager/state_manager.js +3 -0
  74. package/package.json +15 -15
  75. package/src/public/avm/avm_gas.ts +21 -15
  76. package/src/public/avm/fixtures/utils.ts +1 -1
  77. package/src/public/avm/opcodes/accrued_substate.ts +23 -7
  78. package/src/public/avm/opcodes/addressing_mode.ts +8 -0
  79. package/src/public/avm/opcodes/arithmetic.ts +3 -1
  80. package/src/public/avm/opcodes/bitwise.ts +26 -2
  81. package/src/public/avm/opcodes/comparators.ts +3 -1
  82. package/src/public/avm/opcodes/contract.ts +3 -1
  83. package/src/public/avm/opcodes/control_flow.ts +6 -4
  84. package/src/public/avm/opcodes/conversion.ts +21 -2
  85. package/src/public/avm/opcodes/ec_add.ts +3 -1
  86. package/src/public/avm/opcodes/environment_getters.ts +3 -1
  87. package/src/public/avm/opcodes/external_calls.ts +16 -8
  88. package/src/public/avm/opcodes/hashing.ts +11 -3
  89. package/src/public/avm/opcodes/instruction.ts +14 -7
  90. package/src/public/avm/opcodes/memory.ts +23 -6
  91. package/src/public/avm/opcodes/misc.ts +4 -4
  92. package/src/public/avm/opcodes/storage.ts +13 -3
  93. package/src/public/fixtures/index.ts +1 -0
  94. package/src/public/fixtures/minimal_public_tx.ts +57 -0
  95. package/src/public/fixtures/utils.ts +3 -3
  96. package/src/public/hinting_db_sources.ts +15 -0
  97. package/src/public/index.ts +2 -1
  98. package/src/public/public_db_sources.ts +3 -13
  99. package/src/public/public_processor/guarded_merkle_tree.ts +148 -0
  100. package/src/public/public_processor/public_processor.ts +47 -34
  101. package/src/public/public_tx_simulator/public_tx_context.ts +39 -20
  102. package/src/public/public_tx_simulator/public_tx_simulator.ts +0 -3
  103. package/src/public/side_effect_trace.ts +13 -0
  104. package/src/public/side_effect_trace_interface.ts +1 -0
  105. package/src/public/state_manager/state_manager.ts +4 -0
@@ -16,7 +16,7 @@ export class Jump extends Instruction {
16
16
  }
17
17
 
18
18
  public async execute(context: AvmContext): Promise<void> {
19
- context.machineState.consumeGas(this.gasCost());
19
+ context.machineState.consumeGas(this.baseGasCost(0, 0));
20
20
 
21
21
  context.machineState.pc = this.jumpOffset;
22
22
  }
@@ -50,7 +50,9 @@ export class JumpI extends Instruction {
50
50
  const memory = context.machineState.memory;
51
51
  const addressing = Addressing.fromWire(this.indirect);
52
52
 
53
- context.machineState.consumeGas(this.gasCost());
53
+ context.machineState.consumeGas(
54
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
55
+ );
54
56
 
55
57
  const operands = [this.condOffset];
56
58
  const [condOffset] = addressing.resolve(operands, memory);
@@ -79,7 +81,7 @@ export class InternalCall extends Instruction {
79
81
  }
80
82
 
81
83
  public async execute(context: AvmContext): Promise<void> {
82
- context.machineState.consumeGas(this.gasCost());
84
+ context.machineState.consumeGas(this.baseGasCost(0, 0));
83
85
 
84
86
  context.machineState.internalCallStack.push({
85
87
  callPc: context.machineState.pc,
@@ -104,7 +106,7 @@ export class InternalReturn extends Instruction {
104
106
  }
105
107
 
106
108
  public async execute(context: AvmContext): Promise<void> {
107
- context.machineState.consumeGas(this.gasCost());
109
+ context.machineState.consumeGas(this.baseGasCost(0, 0));
108
110
 
109
111
  const stackEntry = context.machineState.internalCallStack.pop();
110
112
  if (stackEntry === undefined) {
@@ -35,6 +35,10 @@ export class ToRadixBE extends Instruction {
35
35
  const memory = context.machineState.memory;
36
36
  const addressing = Addressing.fromWire(this.indirect);
37
37
 
38
+ context.machineState.consumeGas(
39
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
40
+ );
41
+
38
42
  const operands = [this.srcOffset, this.radixOffset, this.numLimbsOffset, this.outputBitsOffset, this.dstOffset];
39
43
  const [srcOffset, radixOffset, numLimbsOffset, outputBitsOffset, dstOffset] = addressing.resolve(operands, memory);
40
44
 
@@ -45,11 +49,13 @@ export class ToRadixBE extends Instruction {
45
49
  memory.checkTag(TypeTag.UINT1, outputBitsOffset);
46
50
 
47
51
  const numLimbs = memory.get(numLimbsOffset).toNumber();
48
- context.machineState.consumeGas(this.gasCost(numLimbs));
52
+ const radix: bigint = memory.get(radixOffset).toBigInt();
53
+ context.machineState.consumeGas(
54
+ this.dynamicGasCost(Math.max(numLimbs, radix > 256n ? 32 : MODULUS_LIMBS_PER_RADIX[Number(radix)])),
55
+ );
49
56
  const outputBits = memory.get(outputBitsOffset).toNumber();
50
57
 
51
58
  let value: bigint = memory.get(srcOffset).toBigInt();
52
- const radix: bigint = memory.get(radixOffset).toBigInt();
53
59
 
54
60
  if (radix < 2 || radix > 256) {
55
61
  throw new InvalidToRadixInputsError(`ToRadixBE instruction's radix should be in range [2,256] (was ${radix}).`);
@@ -79,3 +85,16 @@ export class ToRadixBE extends Instruction {
79
85
  memory.setSlice(dstOffset, res);
80
86
  }
81
87
  }
88
+
89
+ // First two are for radix = 0 and 1, which are invalid, so we have 0 limbs for those cases.
90
+ export const MODULUS_LIMBS_PER_RADIX: number[] = [
91
+ 0, 0, 254, 161, 127, 110, 99, 91, 85, 81, 77, 74, 71, 69, 67, 65, 64, 63, 61, 60, 59, 58, 57, 57, 56, 55, 54, 54, 53,
92
+ 53, 52, 52, 51, 51, 50, 50, 50, 49, 49, 48, 48, 48, 48, 47, 47, 47, 46, 46, 46, 46, 45, 45, 45, 45, 45, 44, 44, 44,
93
+ 44, 44, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40,
94
+ 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
95
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
96
+ 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
97
+ 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
98
+ 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
99
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
100
+ ];
@@ -41,7 +41,9 @@ export class EcAdd extends Instruction {
41
41
  const memory = context.machineState.memory;
42
42
  const addressing = Addressing.fromWire(this.indirect);
43
43
 
44
- context.machineState.consumeGas(this.gasCost());
44
+ context.machineState.consumeGas(
45
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
46
+ );
45
47
 
46
48
  const operands = [
47
49
  this.p1XOffset,
@@ -73,7 +73,9 @@ export class GetEnvVar extends Instruction {
73
73
  const memory = context.machineState.memory;
74
74
  const addressing = Addressing.fromWire(this.indirect);
75
75
 
76
- context.machineState.consumeGas(this.gasCost());
76
+ context.machineState.consumeGas(
77
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
78
+ );
77
79
 
78
80
  if (!(this.varEnum in EnvironmentVariable)) {
79
81
  throw new InstructionExecutionError(`Invalid GETENVVAR var enum ${this.varEnum}`);
@@ -32,11 +32,15 @@ abstract class ExternalCall extends Instruction {
32
32
  const memory = context.machineState.memory;
33
33
  const addressing = Addressing.fromWire(this.indirect);
34
34
 
35
+ context.machineState.consumeGas(
36
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
37
+ );
38
+
35
39
  const operands = [this.l2GasOffset, this.daGasOffset, this.addrOffset, this.argsSizeOffset, this.argsOffset];
36
40
  const [l2GasOffset, daGasOffset, addrOffset, argsSizeOffset, argsOffset] = addressing.resolve(operands, memory);
37
- // TODO: Should be U32
38
- memory.checkTags(TypeTag.FIELD, l2GasOffset);
39
- memory.checkTags(TypeTag.FIELD, daGasOffset);
41
+
42
+ memory.checkTags(TypeTag.UINT32, l2GasOffset);
43
+ memory.checkTags(TypeTag.UINT32, daGasOffset);
40
44
  memory.checkTag(TypeTag.FIELD, addrOffset);
41
45
  memory.checkTag(TypeTag.UINT32, argsSizeOffset);
42
46
 
@@ -48,9 +52,7 @@ abstract class ExternalCall extends Instruction {
48
52
  // If we are already in a static call, we propagate the environment.
49
53
  const callType = context.environment.isStaticCall ? 'STATICCALL' : this.type;
50
54
 
51
- // First we consume the gas for this operation.
52
- context.machineState.consumeGas(this.gasCost(calldataSize));
53
- // Then we consume the gas allocated for the nested call. The excess will be refunded later.
55
+ // We consume the gas allocated for the nested call. The excess will be refunded later.
54
56
  // Gas allocation is capped by the amount of gas left in the current context.
55
57
  // We have to do some dancing here because the gas allocation is a field,
56
58
  // but in the machine state we track gas as a number.
@@ -179,12 +181,15 @@ export class Return extends Instruction {
179
181
  const memory = context.machineState.memory;
180
182
  const addressing = Addressing.fromWire(this.indirect);
181
183
 
184
+ context.machineState.consumeGas(
185
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
186
+ );
187
+
182
188
  const operands = [this.returnSizeOffset, this.returnOffset];
183
189
  const [returnSizeOffset, returnOffset] = addressing.resolve(operands, memory);
184
190
 
185
191
  memory.checkTag(TypeTag.UINT32, returnSizeOffset);
186
192
  const returnSize = memory.get(returnSizeOffset).toNumber();
187
- context.machineState.consumeGas(this.gasCost(returnSize));
188
193
 
189
194
  const output = memory.getSlice(returnOffset, returnSize).map(word => word.toFr());
190
195
 
@@ -225,12 +230,15 @@ export class Revert extends Instruction {
225
230
  const memory = context.machineState.memory;
226
231
  const addressing = Addressing.fromWire(this.indirect);
227
232
 
233
+ context.machineState.consumeGas(
234
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
235
+ );
236
+
228
237
  const operands = [this.retSizeOffset, this.returnOffset];
229
238
  const [retSizeOffset, returnOffset] = addressing.resolve(operands, memory);
230
239
 
231
240
  memory.checkTag(TypeTag.UINT32, retSizeOffset);
232
241
  const retSize = memory.get(retSizeOffset).toNumber();
233
- context.machineState.consumeGas(this.gasCost(retSize));
234
242
  const output = memory.getSlice(returnOffset, retSize).map(word => word.toFr());
235
243
 
236
244
  context.machineState.revert(output);
@@ -31,7 +31,9 @@ export class Poseidon2 extends Instruction {
31
31
  const memory = context.machineState.memory;
32
32
  const addressing = Addressing.fromWire(this.indirect);
33
33
 
34
- context.machineState.consumeGas(this.gasCost());
34
+ context.machineState.consumeGas(
35
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
36
+ );
35
37
 
36
38
  const operands = [this.inputStateOffset, this.outputStateOffset];
37
39
 
@@ -74,9 +76,12 @@ export class KeccakF1600 extends Instruction {
74
76
  const memory = context.machineState.memory;
75
77
  const addressing = Addressing.fromWire(this.indirect);
76
78
 
79
+ context.machineState.consumeGas(
80
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
81
+ );
82
+
77
83
  const operands = [this.dstOffset, this.inputOffset];
78
84
  const [dstOffset, inputOffset] = addressing.resolve(operands, memory);
79
- context.machineState.consumeGas(this.gasCost());
80
85
 
81
86
  const stateData = memory.getSlice(inputOffset, inputSize).map(word => word.toBigInt());
82
87
  memory.checkTagsRange(TypeTag.UINT64, inputOffset, inputSize);
@@ -117,11 +122,14 @@ export class Sha256Compression extends Instruction {
117
122
  const memory = context.machineState.memory;
118
123
  const addressing = Addressing.fromWire(this.indirect);
119
124
 
125
+ context.machineState.consumeGas(
126
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
127
+ );
128
+
120
129
  const operands = [this.outputOffset, this.stateOffset, this.inputsOffset];
121
130
  const [outputOffset, stateOffset, inputsOffset] = addressing.resolve(operands, memory);
122
131
 
123
132
  // Note: size of output is same as size of state
124
- context.machineState.consumeGas(this.gasCost());
125
133
  const inputs = Uint32Array.from(memory.getSlice(inputsOffset, INPUTS_SIZE).map(word => word.toNumber()));
126
134
  const state = Uint32Array.from(memory.getSlice(stateOffset, STATE_SIZE).map(word => word.toNumber()));
127
135
 
@@ -3,7 +3,7 @@ import type { Bufferable } from '@aztec/foundation/serialize';
3
3
  import { strict as assert } from 'assert';
4
4
 
5
5
  import type { AvmContext } from '../avm_context.js';
6
- import { type Gas, getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js';
6
+ import { type Gas, computeAddressingCost, getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js';
7
7
  import type { BufferCursor } from '../serialization/buffer_cursor.js';
8
8
  import { Opcode, type OperandType, deserialize, serializeAs } from '../serialization/instruction_serialization.js';
9
9
 
@@ -92,13 +92,20 @@ export abstract class Instruction {
92
92
  }
93
93
 
94
94
  /**
95
- * Computes gas cost for the instruction based on its base cost and memory operations.
96
- * @returns Gas cost.
95
+ * Returns the base gas cost for the instruction.
96
+ * @returns The base gas cost.
97
97
  */
98
- protected gasCost(dynMultiplier: number = 0): Gas {
99
- const baseGasCost = getBaseGasCost(this.opcode);
100
- const dynGasCost = mulGas(getDynamicGasCost(this.opcode), dynMultiplier);
101
- return sumGas(baseGasCost, dynGasCost);
98
+ protected baseGasCost(indirectOperandsCount: number, relativeOperandsCount: number): Gas {
99
+ return sumGas(getBaseGasCost(this.opcode), computeAddressingCost(indirectOperandsCount, relativeOperandsCount));
100
+ }
101
+
102
+ /**
103
+ * Computes the dynamic gas cost for the instruction
104
+ * @param dynMultiplier - The multiplier for the dynamic gas cost.
105
+ * @returns The dynamic gas cost.
106
+ */
107
+ protected dynamicGasCost(dynMultiplier: number = 0): Gas {
108
+ return mulGas(getDynamicGasCost(this.opcode), dynMultiplier);
102
109
  }
103
110
 
104
111
  /**
@@ -68,7 +68,9 @@ export class Set extends Instruction {
68
68
  const memory = context.machineState.memory;
69
69
  const addressing = Addressing.fromWire(this.indirect);
70
70
 
71
- context.machineState.consumeGas(this.gasCost());
71
+ context.machineState.consumeGas(
72
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
73
+ );
72
74
 
73
75
  const operands = [this.dstOffset];
74
76
  const [dstOffset] = addressing.resolve(operands, memory);
@@ -108,7 +110,9 @@ export class Cast extends Instruction {
108
110
  const memory = context.machineState.memory;
109
111
  const addressing = Addressing.fromWire(this.indirect);
110
112
 
111
- context.machineState.consumeGas(this.gasCost());
113
+ context.machineState.consumeGas(
114
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
115
+ );
112
116
 
113
117
  const operands = [this.srcOffset, this.dstOffset];
114
118
  const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
@@ -151,7 +155,9 @@ export class Mov extends Instruction {
151
155
  const memory = context.machineState.memory;
152
156
  const addressing = Addressing.fromWire(this.indirect);
153
157
 
154
- context.machineState.consumeGas(this.gasCost());
158
+ context.machineState.consumeGas(
159
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
160
+ );
155
161
 
156
162
  const operands = [this.srcOffset, this.dstOffset];
157
163
  const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
@@ -185,13 +191,17 @@ export class CalldataCopy extends Instruction {
185
191
  const memory = context.machineState.memory;
186
192
  const addressing = Addressing.fromWire(this.indirect);
187
193
 
194
+ context.machineState.consumeGas(
195
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
196
+ );
197
+
188
198
  const operands = [this.copySizeOffset, this.cdStartOffset, this.dstOffset];
189
199
  const [copySizeOffset, cdStartOffset, dstOffset] = addressing.resolve(operands, memory);
190
200
 
191
201
  memory.checkTags(TypeTag.UINT32, cdStartOffset, copySizeOffset);
192
202
  const cdStart = memory.get(cdStartOffset).toNumber();
193
203
  const copySize = memory.get(copySizeOffset).toNumber();
194
- context.machineState.consumeGas(this.gasCost(copySize));
204
+ context.machineState.consumeGas(this.dynamicGasCost(copySize));
195
205
 
196
206
  // Values which are out-of-range of the calldata array will be set with Field(0);
197
207
  const slice = context.environment.calldata.slice(cdStart, cdStart + copySize).map(f => new Field(f));
@@ -219,9 +229,12 @@ export class ReturndataSize extends Instruction {
219
229
  const memory = context.machineState.memory;
220
230
  const addressing = Addressing.fromWire(this.indirect);
221
231
 
232
+ context.machineState.consumeGas(
233
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
234
+ );
235
+
222
236
  const operands = [this.dstOffset];
223
237
  const [dstOffset] = addressing.resolve(operands, memory);
224
- context.machineState.consumeGas(this.gasCost());
225
238
 
226
239
  memory.set(dstOffset, new Uint32(context.machineState.nestedReturndata.length));
227
240
  }
@@ -252,13 +265,17 @@ export class ReturndataCopy extends Instruction {
252
265
  const memory = context.machineState.memory;
253
266
  const addressing = Addressing.fromWire(this.indirect);
254
267
 
268
+ context.machineState.consumeGas(
269
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
270
+ );
271
+
255
272
  const operands = [this.copySizeOffset, this.rdStartOffset, this.dstOffset];
256
273
  const [copySizeOffset, rdStartOffset, dstOffset] = addressing.resolve(operands, memory);
257
274
 
258
275
  memory.checkTags(TypeTag.UINT32, rdStartOffset, copySizeOffset);
259
276
  const rdStart = memory.get(rdStartOffset).toNumber();
260
277
  const copySize = memory.get(copySizeOffset).toNumber();
261
- context.machineState.consumeGas(this.gasCost(copySize));
278
+ context.machineState.consumeGas(this.dynamicGasCost(copySize));
262
279
 
263
280
  // Values which are out-of-range of the returndata array will be set with Field(0);
264
281
  const slice = context.machineState.nestedReturndata.slice(rdStart, rdStart + copySize).map(f => new Field(f));
@@ -35,6 +35,10 @@ export class DebugLog extends Instruction {
35
35
  const memory = context.machineState.memory;
36
36
  const addressing = Addressing.fromWire(this.indirect);
37
37
 
38
+ context.machineState.consumeGas(
39
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
40
+ );
41
+
38
42
  const operands = [this.messageOffset, this.fieldsOffset, this.fieldsSizeOffset];
39
43
  const [messageOffset, fieldsOffset, fieldsSizeOffset] = addressing.resolve(operands, memory);
40
44
  memory.checkTag(TypeTag.UINT32, fieldsSizeOffset);
@@ -60,9 +64,5 @@ export class DebugLog extends Instruction {
60
64
 
61
65
  DebugLog.logger.verbose(formattedStr);
62
66
  }
63
-
64
- // Despite having dynamic "size" operands, the gas cost is fixed because
65
- // this opcode is a no-op except during client-initiated simulation
66
- context.machineState.consumeGas(this.gasCost());
67
67
  }
68
68
  }
@@ -39,14 +39,22 @@ export class SStore extends BaseStorageInstruction {
39
39
  const memory = context.machineState.memory;
40
40
  const addressing = Addressing.fromWire(this.indirect);
41
41
 
42
- context.machineState.consumeGas(this.gasCost());
42
+ context.machineState.consumeGas(
43
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
44
+ );
43
45
 
44
46
  const operands = [this.aOffset, this.bOffset];
45
47
  const [srcOffset, slotOffset] = addressing.resolve(operands, memory);
48
+ // We read before tag checking since it's needed for gas cost calculation
49
+ const slot = memory.get(slotOffset).toFr();
50
+
51
+ context.machineState.consumeGas(
52
+ this.dynamicGasCost(Number(context.persistableState.isStorageCold(context.environment.address, slot))),
53
+ );
54
+
46
55
  memory.checkTag(TypeTag.FIELD, slotOffset);
47
56
  memory.checkTag(TypeTag.FIELD, srcOffset);
48
57
 
49
- const slot = memory.get(slotOffset).toFr();
50
58
  const value = memory.get(srcOffset).toFr();
51
59
  await context.persistableState.writeStorage(context.environment.address, slot, value);
52
60
  }
@@ -64,7 +72,9 @@ export class SLoad extends BaseStorageInstruction {
64
72
  const memory = context.machineState.memory;
65
73
  const addressing = Addressing.fromWire(this.indirect);
66
74
 
67
- context.machineState.consumeGas(this.gasCost());
75
+ context.machineState.consumeGas(
76
+ this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
77
+ );
68
78
 
69
79
  const operands = [this.aOffset, this.bOffset];
70
80
  const [slotOffset, dstOffset] = addressing.resolve(operands, memory);
@@ -1,3 +1,4 @@
1
1
  export * from './public_tx_simulation_tester.js';
2
2
  export * from './utils.js';
3
3
  export * from './simple_contract_data_source.js';
4
+ export { readAvmMinimalPublicTxInputsFromFile, createAvmMinimalPublicTx } from './minimal_public_tx.js';
@@ -0,0 +1,57 @@
1
+ import { FunctionType, emptyContractArtifact, emptyFunctionArtifact } from '@aztec/stdlib/abi';
2
+ import { AvmCircuitInputs } from '@aztec/stdlib/avm';
3
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+
5
+ import avmMinimalCircuitInputsJson from '../../../artifacts/avm_minimal_inputs.json' with { type: 'json' };
6
+ import { TypeTag } from '../avm/avm_memory_types.js';
7
+ import { Add, Return, Set } from '../avm/opcodes/index.js';
8
+ import { encodeToBytecode } from '../avm/serialization/bytecode_serialization.js';
9
+ import { Opcode } from '../avm/serialization/instruction_serialization.js';
10
+ import type { PublicTxResult } from '../public_tx_simulator/public_tx_simulator.js';
11
+ import { PublicTxSimulationTester } from './public_tx_simulation_tester.js';
12
+
13
+ export async function createAvmMinimalPublicTx(): Promise<PublicTxResult> {
14
+ const deployer = AztecAddress.fromNumber(42);
15
+
16
+ const simTester = await PublicTxSimulationTester.create();
17
+
18
+ const minimalBytecode = encodeToBytecode([
19
+ new Set(/*indirect*/ 0, /*dstOffset*/ 0, TypeTag.UINT32, /*value*/ 1).as(Opcode.SET_8, Set.wireFormat8),
20
+ new Set(/*indirect*/ 0, /*dstOffset*/ 1, TypeTag.UINT32, /*value*/ 2).as(Opcode.SET_8, Set.wireFormat8),
21
+ new Add(/*indirect=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2).as(Opcode.ADD_8, Add.wireFormat8),
22
+ new Return(/*indirect=*/ 0, /*copySizeOffset=*/ 0, /*returnOffset=*/ 2),
23
+ ]);
24
+
25
+ const minimalContractArtifact = emptyContractArtifact();
26
+ minimalContractArtifact.name = 'MinimalContract';
27
+ minimalContractArtifact.functions = [emptyFunctionArtifact()];
28
+ minimalContractArtifact.functions[0].name = 'public_dispatch';
29
+ minimalContractArtifact.functions[0].functionType = FunctionType.PUBLIC;
30
+ minimalContractArtifact.functions[0].bytecode = minimalBytecode;
31
+
32
+ const minimalTestContract = await simTester.registerAndDeployContract(
33
+ /*constructorArgs=*/ [],
34
+ deployer,
35
+ /*contractArtifact=*/ minimalContractArtifact,
36
+ );
37
+
38
+ return await simTester.simulateTx(
39
+ /*sender=*/ deployer,
40
+ /*setupCalls=*/ [],
41
+ /*appCalls=*/ [
42
+ {
43
+ address: minimalTestContract.address,
44
+ fnName: 'public_dispatch',
45
+ args: [],
46
+ },
47
+ ],
48
+ );
49
+ }
50
+
51
+ /**
52
+ * Reads the AVM circuit inputs for the minimal public tx from a pre-generated JSON file.
53
+ * @returns The AvmCircuitInputs for the minimal public tx.
54
+ */
55
+ export function readAvmMinimalPublicTxInputsFromFile(): AvmCircuitInputs {
56
+ return AvmCircuitInputs.schema.parse(avmMinimalCircuitInputsJson);
57
+ }
@@ -127,10 +127,10 @@ export async function addNewContractClassToTx(
127
127
  ];
128
128
  const contractAddress = new AztecAddress(new Fr(REGISTERER_CONTRACT_ADDRESS));
129
129
  const emittedLength = contractClassLogFields.length;
130
- const log = ContractClassLogFields.fromEmittedFields(contractClassLogFields);
130
+ const logFields = ContractClassLogFields.fromEmittedFields(contractClassLogFields);
131
131
 
132
132
  const contractClassLogHash = LogHash.from({
133
- value: await log.hash(),
133
+ value: await logFields.hash(),
134
134
  length: emittedLength,
135
135
  }).scope(contractAddress);
136
136
 
@@ -143,7 +143,7 @@ export async function addNewContractClassToTx(
143
143
  const nextLogIndex = countAccumulatedItems(accumulatedData.contractClassLogsHashes);
144
144
  accumulatedData.contractClassLogsHashes[nextLogIndex] = contractClassLogHash;
145
145
 
146
- tx.contractClassLogs.push(log);
146
+ tx.contractClassLogFields.push(logFields);
147
147
  }
148
148
 
149
149
  export async function addNewContractInstanceToTx(
@@ -318,6 +318,14 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
318
318
  );
319
319
  }
320
320
 
321
+ public commitAllCheckpoints(): Promise<void> {
322
+ throw new Error('commitAllCheckpoints is not supported in HintingMerkleWriteOperations.');
323
+ }
324
+
325
+ public revertAllCheckpoints(): Promise<void> {
326
+ throw new Error('revertAllCheckpoints is not supported in HintingMerkleWriteOperations.');
327
+ }
328
+
321
329
  public async commitCheckpoint(): Promise<void> {
322
330
  const actionCounter = this.checkpointActionCounter++;
323
331
  const oldCheckpointId = this.getCurrentCheckpointId();
@@ -459,6 +467,13 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
459
467
  return await this.db.findLeafIndices(treeId, values);
460
468
  }
461
469
 
470
+ public async findSiblingPaths<ID extends MerkleTreeId, N extends number>(
471
+ treeId: ID,
472
+ values: MerkleTreeLeafType<ID>[],
473
+ ): Promise<(SiblingPath<N> | undefined)[]> {
474
+ return await this.db.findSiblingPaths(treeId, values);
475
+ }
476
+
462
477
  public async findLeafIndicesAfter<ID extends MerkleTreeId>(
463
478
  treeId: ID,
464
479
  values: MerkleTreeLeafType<ID>[],
@@ -1,4 +1,5 @@
1
1
  export { PublicContractsDB } from './public_db_sources.js';
2
- export { type PublicTxResult, PublicTxSimulator, TelemetryPublicTxSimulator } from './public_tx_simulator/index.js';
2
+ export { GuardedMerkleTreeOperations } from './public_processor/guarded_merkle_tree.js';
3
3
  export { PublicProcessor, PublicProcessorFactory } from './public_processor/public_processor.js';
4
+ export { PublicTxSimulator, TelemetryPublicTxSimulator, type PublicTxResult } from './public_tx_simulator/index.js';
4
5
  export { getCallRequestsWithCalldataByPhase } from './utils.js';
@@ -89,12 +89,8 @@ export class PublicContractsDB implements PublicContractsDBInterface {
89
89
  */
90
90
  private async addNonRevertibleContractClasses(tx: Tx) {
91
91
  const siloedContractClassLogs = tx.data.forPublic
92
- ? await tx.filterContractClassLogs(
93
- tx.data.forPublic!.nonRevertibleAccumulatedData.contractClassLogsHashes,
94
- /*siloed=*/ true,
95
- )
96
- : await tx.filterContractClassLogs(tx.data.forRollup!.end.contractClassLogsHashes, /*siloed=*/ true);
97
-
92
+ ? tx.getSplitContractClassLogs(false /* revertible */)
93
+ : tx.getContractClassLogs();
98
94
  await this.addContractClassesFromLogs(siloedContractClassLogs, this.currentTxNonRevertibleCache, 'non-revertible');
99
95
  }
100
96
 
@@ -104,13 +100,7 @@ export class PublicContractsDB implements PublicContractsDBInterface {
104
100
  * @param tx - The transaction to add revertible contract classes from.
105
101
  */
106
102
  private async addRevertibleContractClasses(tx: Tx) {
107
- const siloedContractClassLogs = tx.data.forPublic
108
- ? await tx.filterContractClassLogs(
109
- tx.data.forPublic!.revertibleAccumulatedData.contractClassLogsHashes,
110
- /*siloed=*/ true,
111
- )
112
- : [];
113
-
103
+ const siloedContractClassLogs = tx.data.forPublic ? tx.getSplitContractClassLogs(true /* revertible */) : [];
114
104
  await this.addContractClassesFromLogs(siloedContractClassLogs, this.currentTxRevertibleCache, 'revertible');
115
105
  }
116
106