@aztec/simulator 0.56.0 → 0.57.0

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 (156) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +2 -5
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +6 -37
  4. package/dest/acvm/oracle/typed_oracle.d.ts +3 -6
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +1 -10
  7. package/dest/avm/avm_execution_environment.d.ts +2 -3
  8. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  9. package/dest/avm/avm_execution_environment.js +3 -4
  10. package/dest/avm/avm_gas.d.ts.map +1 -1
  11. package/dest/avm/avm_gas.js +1 -2
  12. package/dest/avm/avm_memory_types.d.ts +3 -2
  13. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  14. package/dest/avm/avm_memory_types.js +3 -3
  15. package/dest/avm/errors.d.ts +1 -1
  16. package/dest/avm/errors.d.ts.map +1 -1
  17. package/dest/avm/errors.js +12 -3
  18. package/dest/avm/fixtures/index.d.ts.map +1 -1
  19. package/dest/avm/fixtures/index.js +3 -3
  20. package/dest/avm/journal/journal.d.ts +2 -1
  21. package/dest/avm/journal/journal.d.ts.map +1 -1
  22. package/dest/avm/journal/journal.js +7 -6
  23. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  24. package/dest/avm/opcodes/accrued_substate.js +37 -30
  25. package/dest/avm/opcodes/addressing_mode.d.ts +3 -2
  26. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
  27. package/dest/avm/opcodes/addressing_mode.js +25 -21
  28. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  29. package/dest/avm/opcodes/arithmetic.js +6 -5
  30. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  31. package/dest/avm/opcodes/bitwise.js +11 -9
  32. package/dest/avm/opcodes/commitment.d.ts.map +1 -1
  33. package/dest/avm/opcodes/commitment.js +6 -5
  34. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  35. package/dest/avm/opcodes/comparators.js +6 -5
  36. package/dest/avm/opcodes/contract.d.ts.map +1 -1
  37. package/dest/avm/opcodes/contract.js +6 -5
  38. package/dest/avm/opcodes/control_flow.js +6 -6
  39. package/dest/avm/opcodes/conversion.d.ts.map +1 -1
  40. package/dest/avm/opcodes/conversion.js +7 -6
  41. package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
  42. package/dest/avm/opcodes/ec_add.js +8 -7
  43. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  44. package/dest/avm/opcodes/environment_getters.js +6 -5
  45. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  46. package/dest/avm/opcodes/external_calls.js +27 -16
  47. package/dest/avm/opcodes/hashing.d.ts +1 -3
  48. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  49. package/dest/avm/opcodes/hashing.js +31 -40
  50. package/dest/avm/opcodes/instruction.d.ts +2 -6
  51. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  52. package/dest/avm/opcodes/instruction.js +3 -9
  53. package/dest/avm/opcodes/memory.d.ts +0 -12
  54. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  55. package/dest/avm/opcodes/memory.js +21 -51
  56. package/dest/avm/opcodes/misc.d.ts.map +1 -1
  57. package/dest/avm/opcodes/misc.js +6 -5
  58. package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
  59. package/dest/avm/opcodes/multi_scalar_mul.js +12 -12
  60. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  61. package/dest/avm/opcodes/storage.js +11 -9
  62. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  63. package/dest/avm/serialization/bytecode_serialization.js +2 -3
  64. package/dest/avm/serialization/instruction_serialization.d.ts +32 -34
  65. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  66. package/dest/avm/serialization/instruction_serialization.js +33 -36
  67. package/dest/client/client_execution_context.d.ts +6 -30
  68. package/dest/client/client_execution_context.d.ts.map +1 -1
  69. package/dest/client/client_execution_context.js +31 -53
  70. package/dest/client/index.d.ts +0 -1
  71. package/dest/client/index.d.ts.map +1 -1
  72. package/dest/client/index.js +1 -2
  73. package/dest/client/private_execution.d.ts +2 -2
  74. package/dest/client/private_execution.d.ts.map +1 -1
  75. package/dest/client/private_execution.js +5 -19
  76. package/dest/client/simulator.d.ts +2 -3
  77. package/dest/client/simulator.d.ts.map +1 -1
  78. package/dest/client/simulator.js +1 -1
  79. package/dest/common/debug_fn_name.d.ts +4 -0
  80. package/dest/common/debug_fn_name.d.ts.map +1 -0
  81. package/dest/common/debug_fn_name.js +15 -0
  82. package/dest/common/index.d.ts +0 -1
  83. package/dest/common/index.d.ts.map +1 -1
  84. package/dest/common/index.js +1 -2
  85. package/dest/public/enqueued_call_simulator.d.ts.map +1 -1
  86. package/dest/public/enqueued_call_simulator.js +3 -4
  87. package/dest/public/execution.d.ts +8 -1
  88. package/dest/public/execution.d.ts.map +1 -1
  89. package/dest/public/execution.js +13 -1
  90. package/dest/public/executor.d.ts +2 -3
  91. package/dest/public/executor.d.ts.map +1 -1
  92. package/dest/public/executor.js +8 -8
  93. package/dest/public/hints_builder.d.ts.map +1 -1
  94. package/dest/public/hints_builder.js +2 -2
  95. package/dest/public/public_processor.d.ts +1 -0
  96. package/dest/public/public_processor.d.ts.map +1 -1
  97. package/dest/public/public_processor.js +5 -2
  98. package/dest/public/side_effect_errors.d.ts +4 -0
  99. package/dest/public/side_effect_errors.d.ts.map +1 -0
  100. package/dest/public/side_effect_errors.js +7 -0
  101. package/dest/public/side_effect_trace.d.ts +2 -2
  102. package/dest/public/side_effect_trace.d.ts.map +1 -1
  103. package/dest/public/side_effect_trace.js +53 -28
  104. package/dest/public/side_effect_trace_interface.d.ts +1 -1
  105. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  106. package/package.json +12 -9
  107. package/src/acvm/oracle/oracle.ts +7 -85
  108. package/src/acvm/oracle/typed_oracle.ts +2 -31
  109. package/src/avm/avm_execution_environment.ts +1 -3
  110. package/src/avm/avm_gas.ts +0 -1
  111. package/src/avm/avm_memory_types.ts +10 -5
  112. package/src/avm/errors.ts +11 -3
  113. package/src/avm/fixtures/index.ts +1 -2
  114. package/src/avm/journal/journal.ts +11 -6
  115. package/src/avm/opcodes/accrued_substate.ts +36 -44
  116. package/src/avm/opcodes/addressing_mode.ts +27 -24
  117. package/src/avm/opcodes/arithmetic.ts +5 -7
  118. package/src/avm/opcodes/bitwise.ts +10 -11
  119. package/src/avm/opcodes/commitment.ts +6 -7
  120. package/src/avm/opcodes/comparators.ts +5 -7
  121. package/src/avm/opcodes/contract.ts +5 -7
  122. package/src/avm/opcodes/control_flow.ts +5 -5
  123. package/src/avm/opcodes/conversion.ts +6 -8
  124. package/src/avm/opcodes/ec_add.ts +14 -16
  125. package/src/avm/opcodes/environment_getters.ts +5 -4
  126. package/src/avm/opcodes/external_calls.ts +27 -20
  127. package/src/avm/opcodes/hashing.ts +30 -55
  128. package/src/avm/opcodes/instruction.ts +3 -10
  129. package/src/avm/opcodes/memory.ts +20 -64
  130. package/src/avm/opcodes/misc.ts +5 -7
  131. package/src/avm/opcodes/multi_scalar_mul.ts +11 -14
  132. package/src/avm/opcodes/storage.ts +10 -8
  133. package/src/avm/serialization/bytecode_serialization.ts +0 -2
  134. package/src/avm/serialization/instruction_serialization.ts +0 -3
  135. package/src/client/client_execution_context.ts +40 -96
  136. package/src/client/index.ts +0 -1
  137. package/src/client/private_execution.ts +9 -9
  138. package/src/client/simulator.ts +2 -3
  139. package/src/common/debug_fn_name.ts +22 -0
  140. package/src/common/index.ts +0 -1
  141. package/src/public/enqueued_call_simulator.ts +2 -3
  142. package/src/public/execution.ts +13 -2
  143. package/src/public/executor.ts +6 -12
  144. package/src/public/hints_builder.ts +7 -9
  145. package/src/public/public_processor.ts +5 -1
  146. package/src/public/side_effect_errors.ts +6 -0
  147. package/src/public/side_effect_trace.ts +72 -27
  148. package/src/public/side_effect_trace_interface.ts +2 -2
  149. package/dest/client/execution_result.d.ts +0 -104
  150. package/dest/client/execution_result.d.ts.map +0 -1
  151. package/dest/client/execution_result.js +0 -136
  152. package/dest/common/return_values.d.ts +0 -11
  153. package/dest/common/return_values.d.ts.map +0 -1
  154. package/dest/common/return_values.js +0 -13
  155. package/src/client/execution_result.ts +0 -228
  156. package/src/common/return_values.ts +0 -18
@@ -15,7 +15,7 @@ abstract class ExternalCall extends Instruction {
15
15
  // Informs (de)serialization. See Instruction.deserialize.
16
16
  static readonly wireFormat: OperandType[] = [
17
17
  OperandType.UINT8,
18
- OperandType.UINT8,
18
+ OperandType.UINT16, // Indirect
19
19
  OperandType.UINT32,
20
20
  OperandType.UINT32,
21
21
  OperandType.UINT32,
@@ -45,29 +45,34 @@ abstract class ExternalCall extends Instruction {
45
45
 
46
46
  public async execute(context: AvmContext) {
47
47
  const memory = context.machineState.memory.track(this.type);
48
- const [gasOffset, addrOffset, argsOffset, argsSizeOffset, retOffset, successOffset] = Addressing.fromWire(
49
- this.indirect,
50
- ).resolve(
51
- [this.gasOffset, this.addrOffset, this.argsOffset, this.argsSizeOffset, this.retOffset, this.successOffset],
52
- memory,
53
- );
48
+ const operands = [
49
+ this.gasOffset,
50
+ this.addrOffset,
51
+ this.argsOffset,
52
+ this.argsSizeOffset,
53
+ this.retOffset,
54
+ this.successOffset,
55
+ this.functionSelectorOffset,
56
+ ];
57
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
58
+ const [gasOffset, addrOffset, argsOffset, argsSizeOffset, retOffset, successOffset, functionSelectorOffset] =
59
+ addressing.resolve(operands, memory);
54
60
  memory.checkTags(TypeTag.FIELD, gasOffset, gasOffset + 1);
55
61
  memory.checkTag(TypeTag.FIELD, addrOffset);
56
62
  memory.checkTag(TypeTag.UINT32, argsSizeOffset);
57
- memory.checkTag(TypeTag.FIELD, this.functionSelectorOffset);
63
+ memory.checkTag(TypeTag.FIELD, functionSelectorOffset);
58
64
 
59
65
  const calldataSize = memory.get(argsSizeOffset).toNumber();
60
66
  memory.checkTagsRange(TypeTag.FIELD, argsOffset, calldataSize);
61
67
 
62
68
  const callAddress = memory.getAs<Field>(addrOffset);
63
69
  const calldata = memory.getSlice(argsOffset, calldataSize).map(f => f.toFr());
64
- const functionSelector = memory.getAs<Field>(this.functionSelectorOffset).toFr();
70
+ const functionSelector = memory.getAs<Field>(functionSelectorOffset).toFr();
65
71
  // If we are already in a static call, we propagate the environment.
66
72
  const callType = context.environment.isStaticCall ? 'STATICCALL' : this.type;
67
73
 
68
74
  // First we consume the gas for this operation.
69
- const memoryOperations = { reads: calldataSize + 5, writes: 1 + this.retSize, indirect: this.indirect };
70
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: calldataSize + this.retSize }));
75
+ context.machineState.consumeGas(this.gasCost(calldataSize + this.retSize));
71
76
  // Then we consume the gas allocated for the nested call. The excess will be refunded later.
72
77
  // Gas allocation is capped by the amount of gas left in the current context.
73
78
  // We have to do some dancing here because the gas allocation is a field,
@@ -127,7 +132,7 @@ abstract class ExternalCall extends Instruction {
127
132
  /*avmCallResults=*/ nestedCallResults,
128
133
  );
129
134
 
130
- memory.assert(memoryOperations);
135
+ memory.assert({ reads: calldataSize + 5, writes: 1 + this.retSize, addressing });
131
136
  context.machineState.incrementPc();
132
137
  }
133
138
 
@@ -168,16 +173,17 @@ export class Return extends Instruction {
168
173
  }
169
174
 
170
175
  public async execute(context: AvmContext): Promise<void> {
171
- const memoryOperations = { reads: this.copySize, indirect: this.indirect };
172
176
  const memory = context.machineState.memory.track(this.type);
173
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: this.copySize }));
177
+ context.machineState.consumeGas(this.gasCost(this.copySize));
174
178
 
175
- const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], memory);
179
+ const operands = [this.returnOffset];
180
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
181
+ const [returnOffset] = addressing.resolve(operands, memory);
176
182
 
177
183
  const output = memory.getSlice(returnOffset, this.copySize).map(word => word.toFr());
178
184
 
179
185
  context.machineState.return(output);
180
- memory.assert(memoryOperations);
186
+ memory.assert({ reads: this.copySize, addressing });
181
187
  }
182
188
  }
183
189
 
@@ -203,16 +209,17 @@ export class Revert extends Instruction {
203
209
  }
204
210
 
205
211
  public async execute(context: AvmContext): Promise<void> {
206
- const memoryOperations = { reads: this.retSize, indirect: this.indirect };
207
212
  const memory = context.machineState.memory.track(this.type);
208
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: this.retSize }));
213
+ context.machineState.consumeGas(this.gasCost(this.retSize));
209
214
 
210
- const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], memory);
215
+ const operands = [this.returnOffset];
216
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
217
+ const [returnOffset] = addressing.resolve(operands, memory);
211
218
 
212
219
  const output = memory.getSlice(returnOffset, this.retSize).map(word => word.toFr());
213
220
 
214
221
  context.machineState.revert(output);
215
- memory.assert(memoryOperations);
222
+ memory.assert({ reads: this.retSize, addressing });
216
223
  }
217
224
  }
218
225
 
@@ -10,7 +10,6 @@ import { strict as assert } from 'assert';
10
10
 
11
11
  import { type AvmContext } from '../avm_context.js';
12
12
  import { Field, TypeTag, Uint8, Uint32, Uint64 } from '../avm_memory_types.js';
13
- import { InstructionExecutionError } from '../errors.js';
14
13
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
15
14
  import { Addressing } from './addressing_mode.js';
16
15
  import { Instruction } from './instruction.js';
@@ -33,14 +32,12 @@ export class Poseidon2 extends Instruction {
33
32
  }
34
33
 
35
34
  public async execute(context: AvmContext): Promise<void> {
36
- const memoryOperations = { reads: Poseidon2.stateSize, writes: Poseidon2.stateSize, indirect: this.indirect };
37
35
  const memory = context.machineState.memory.track(this.type);
38
- context.machineState.consumeGas(this.gasCost(memoryOperations));
36
+ context.machineState.consumeGas(this.gasCost());
39
37
 
40
- const [inputOffset, outputOffset] = Addressing.fromWire(this.indirect).resolve(
41
- [this.inputStateOffset, this.outputStateOffset],
42
- memory,
43
- );
38
+ const operands = [this.inputStateOffset, this.outputStateOffset];
39
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
40
+ const [inputOffset, outputOffset] = addressing.resolve(operands, memory);
44
41
  memory.checkTagsRange(TypeTag.FIELD, inputOffset, Poseidon2.stateSize);
45
42
 
46
43
  const inputState = memory.getSlice(inputOffset, Poseidon2.stateSize);
@@ -50,7 +47,7 @@ export class Poseidon2 extends Instruction {
50
47
  outputState.map(word => new Field(word)),
51
48
  );
52
49
 
53
- memory.assert(memoryOperations);
50
+ memory.assert({ reads: Poseidon2.stateSize, writes: Poseidon2.stateSize, addressing });
54
51
  context.machineState.incrementPc();
55
52
  }
56
53
  }
@@ -80,14 +77,12 @@ export class Keccak extends Instruction {
80
77
  // pub fn keccak256(input: [u8], message_size: u32) -> [u8; 32]
81
78
  public async execute(context: AvmContext): Promise<void> {
82
79
  const memory = context.machineState.memory.track(this.type);
83
- const [dstOffset, messageOffset, messageSizeOffset] = Addressing.fromWire(this.indirect).resolve(
84
- [this.dstOffset, this.messageOffset, this.messageSizeOffset],
85
- memory,
86
- );
80
+ const operands = [this.dstOffset, this.messageOffset, this.messageSizeOffset];
81
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
82
+ const [dstOffset, messageOffset, messageSizeOffset] = addressing.resolve(operands, memory);
87
83
  memory.checkTag(TypeTag.UINT32, messageSizeOffset);
88
84
  const messageSize = memory.get(messageSizeOffset).toNumber();
89
- const memoryOperations = { reads: messageSize + 1, writes: 32, indirect: this.indirect };
90
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: messageSize }));
85
+ context.machineState.consumeGas(this.gasCost(messageSize));
91
86
 
92
87
  memory.checkTagsRange(TypeTag.UINT8, messageOffset, messageSize);
93
88
 
@@ -98,7 +93,7 @@ export class Keccak extends Instruction {
98
93
  const res = [...hashBuffer].map(byte => new Uint8(byte));
99
94
  memory.setSlice(dstOffset, res);
100
95
 
101
- memory.assert(memoryOperations);
96
+ memory.assert({ reads: messageSize + 1, writes: 32, addressing });
102
97
  context.machineState.incrementPc();
103
98
  }
104
99
  }
@@ -129,15 +124,13 @@ export class KeccakF1600 extends Instruction {
129
124
  // pub fn keccakf1600(input: [u64; 25]) -> [u64; 25]
130
125
  public async execute(context: AvmContext): Promise<void> {
131
126
  const memory = context.machineState.memory.track(this.type);
132
- const [dstOffset, stateOffset, stateSizeOffset] = Addressing.fromWire(this.indirect).resolve(
133
- [this.dstOffset, this.stateOffset, this.stateSizeOffset],
134
- memory,
135
- );
127
+ const operands = [this.dstOffset, this.stateOffset, this.stateSizeOffset];
128
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
129
+ const [dstOffset, stateOffset, stateSizeOffset] = addressing.resolve(operands, memory);
136
130
  memory.checkTag(TypeTag.UINT32, stateSizeOffset);
137
131
  const stateSize = memory.get(stateSizeOffset).toNumber();
138
132
  assert(stateSize === 25, 'Invalid state size for keccakf1600');
139
- const memoryOperations = { reads: stateSize + 1, writes: 25, indirect: this.indirect };
140
- context.machineState.consumeGas(this.gasCost(memoryOperations));
133
+ context.machineState.consumeGas(this.gasCost());
141
134
 
142
135
  memory.checkTagsRange(TypeTag.UINT64, stateOffset, stateSize);
143
136
 
@@ -147,7 +140,7 @@ export class KeccakF1600 extends Instruction {
147
140
  const res = updatedState.map(word => new Uint64(word));
148
141
  memory.setSlice(dstOffset, res);
149
142
 
150
- memory.assert(memoryOperations);
143
+ memory.assert({ reads: stateSize + 1, writes: 25, addressing });
151
144
  context.machineState.incrementPc();
152
145
  }
153
146
  }
@@ -163,17 +156,13 @@ export class Sha256Compression extends Instruction {
163
156
  OperandType.UINT32,
164
157
  OperandType.UINT32,
165
158
  OperandType.UINT32,
166
- OperandType.UINT32,
167
- OperandType.UINT32,
168
159
  ];
169
160
 
170
161
  constructor(
171
162
  private indirect: number,
172
163
  private outputOffset: number,
173
164
  private stateOffset: number,
174
- private stateSizeOffset: number,
175
165
  private inputsOffset: number,
176
- private inputsSizeOffset: number,
177
166
  ) {
178
167
  super();
179
168
  }
@@ -183,36 +172,24 @@ export class Sha256Compression extends Instruction {
183
172
  const INPUTS_SIZE = 16;
184
173
 
185
174
  const memory = context.machineState.memory.track(this.type);
186
- const [outputOffset, stateOffset, stateSizeOffset, inputsOffset, inputsSizeOffset] = Addressing.fromWire(
187
- this.indirect,
188
- ).resolve(
189
- [this.outputOffset, this.stateOffset, this.stateSizeOffset, this.inputsOffset, this.inputsSizeOffset],
190
- memory,
191
- );
192
- const stateSize = memory.get(stateSizeOffset).toNumber();
193
- const inputsSize = memory.get(inputsSizeOffset).toNumber();
194
- if (stateSize !== STATE_SIZE) {
195
- throw new InstructionExecutionError('`state` argument to SHA256 compression must be of length 8');
196
- }
197
- if (inputsSize !== INPUTS_SIZE) {
198
- throw new InstructionExecutionError('`inputs` argument to SHA256 compression must be of length 16');
199
- }
200
- // +2 to account for both size offsets (stateSizeOffset and inputsSizeOffset)
175
+ const operands = [this.outputOffset, this.stateOffset, this.inputsOffset];
176
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
177
+ const [outputOffset, stateOffset, inputsOffset] = addressing.resolve(operands, memory);
178
+
201
179
  // Note: size of output is same as size of state
202
- const memoryOperations = { reads: stateSize + inputsSize + 2, writes: stateSize, indirect: this.indirect };
203
- context.machineState.consumeGas(this.gasCost(memoryOperations));
204
- memory.checkTagsRange(TypeTag.UINT32, inputsOffset, inputsSize);
205
- memory.checkTagsRange(TypeTag.UINT32, stateOffset, stateSize);
180
+ context.machineState.consumeGas(this.gasCost());
181
+ memory.checkTagsRange(TypeTag.UINT32, inputsOffset, INPUTS_SIZE);
182
+ memory.checkTagsRange(TypeTag.UINT32, stateOffset, STATE_SIZE);
206
183
 
207
- const state = Uint32Array.from(memory.getSlice(stateOffset, stateSize).map(word => word.toNumber()));
208
- const inputs = Uint32Array.from(memory.getSlice(inputsOffset, inputsSize).map(word => word.toNumber()));
184
+ const state = Uint32Array.from(memory.getSlice(stateOffset, STATE_SIZE).map(word => word.toNumber()));
185
+ const inputs = Uint32Array.from(memory.getSlice(inputsOffset, INPUTS_SIZE).map(word => word.toNumber()));
209
186
  const output = sha256Compression(state, inputs);
210
187
 
211
188
  // Conversion required from Uint32Array to Uint32[] (can't map directly, need `...`)
212
189
  const res = [...output].map(word => new Uint32(word));
213
190
  memory.setSlice(outputOffset, res);
214
191
 
215
- memory.assert(memoryOperations);
192
+ memory.assert({ reads: STATE_SIZE + INPUTS_SIZE, writes: STATE_SIZE, addressing });
216
193
  context.machineState.incrementPc();
217
194
  }
218
195
  }
@@ -243,10 +220,9 @@ export class Pedersen extends Instruction {
243
220
 
244
221
  public async execute(context: AvmContext): Promise<void> {
245
222
  const memory = context.machineState.memory.track(this.type);
246
- const [genIndexOffset, dstOffset, messageOffset, messageSizeOffset] = Addressing.fromWire(this.indirect).resolve(
247
- [this.genIndexOffset, this.dstOffset, this.messageOffset, this.messageSizeOffset],
248
- memory,
249
- );
223
+ const operands = [this.genIndexOffset, this.dstOffset, this.messageOffset, this.messageSizeOffset];
224
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
225
+ const [genIndexOffset, dstOffset, messageOffset, messageSizeOffset] = addressing.resolve(operands, memory);
250
226
 
251
227
  // We hash a set of field elements
252
228
  const genIndex = Number(memory.get(genIndexOffset).toBigInt());
@@ -255,8 +231,7 @@ export class Pedersen extends Instruction {
255
231
  memory.checkTag(TypeTag.UINT32, messageSizeOffset);
256
232
  const hashData = memory.getSlice(messageOffset, messageSize);
257
233
 
258
- const memoryOperations = { reads: messageSize + 2, writes: 1, indirect: this.indirect };
259
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: messageSize }));
234
+ context.machineState.consumeGas(this.gasCost(messageSize));
260
235
 
261
236
  memory.checkTagsRange(TypeTag.FIELD, messageOffset, messageSize);
262
237
 
@@ -264,7 +239,7 @@ export class Pedersen extends Instruction {
264
239
  const hash = pedersenHash(hashData, genIndex);
265
240
  memory.set(dstOffset, new Field(hash));
266
241
 
267
- memory.assert(memoryOperations);
242
+ memory.assert({ reads: messageSize + 2, writes: 1, addressing });
268
243
  context.machineState.incrementPc();
269
244
  }
270
245
  }
@@ -1,8 +1,7 @@
1
1
  import { strict as assert } from 'assert';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
- import { getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js';
5
- import { type MemoryOperations } from '../avm_memory_types.js';
4
+ import { type Gas, getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js';
6
5
  import { type BufferCursor } from '../serialization/buffer_cursor.js';
7
6
  import { type Serializable } from '../serialization/bytecode_serialization.js';
8
7
  import { Opcode, type OperandType, deserialize, serializeAs } from '../serialization/instruction_serialization.js';
@@ -86,17 +85,11 @@ export abstract class Instruction {
86
85
 
87
86
  /**
88
87
  * Computes gas cost for the instruction based on its base cost and memory operations.
89
- * @param memoryOps Memory operations performed by the instruction.
90
88
  * @returns Gas cost.
91
89
  */
92
- protected gasCost(ops: Partial<MemoryOperations & { indirect: number; dynMultiplier: number }> = {}) {
90
+ protected gasCost(dynMultiplier: number = 0): Gas {
93
91
  const baseGasCost = getBaseGasCost(this.opcode);
94
- // TODO: We are using a simplified gas model to reduce complexity in the circuit.
95
- // Memory accounting will probably be removed.
96
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6861): reconsider.
97
- // const memoryGasCost = getMemoryGasCost(memoryOps);
98
- // const memoryGasCost = { l2Gas: 0, daGas: 0 };
99
- const dynGasCost = mulGas(getDynamicGasCost(this.opcode), ops.dynMultiplier ?? 0);
92
+ const dynGasCost = mulGas(getDynamicGasCost(this.opcode), dynMultiplier);
100
93
  return sumGas(baseGasCost, dynGasCost);
101
94
  }
102
95
 
@@ -62,60 +62,16 @@ export class Set extends Instruction {
62
62
  }
63
63
 
64
64
  public async execute(context: AvmContext): Promise<void> {
65
- const memoryOperations = { writes: 1, indirect: this.indirect };
66
65
  const memory = context.machineState.memory.track(this.type);
67
- context.machineState.consumeGas(this.gasCost(memoryOperations));
66
+ context.machineState.consumeGas(this.gasCost());
68
67
 
69
- const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], memory);
68
+ const operands = [this.dstOffset];
69
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
70
+ const [dstOffset] = addressing.resolve(operands, memory);
70
71
  const res = TaggedMemory.buildFromTagTruncating(this.value, this.inTag);
71
72
  memory.set(dstOffset, res);
72
73
 
73
- memory.assert(memoryOperations);
74
- context.machineState.incrementPc();
75
- }
76
- }
77
-
78
- export class CMov extends Instruction {
79
- static readonly type: string = 'CMOV';
80
- static readonly opcode: Opcode = Opcode.CMOV;
81
- // Informs (de)serialization. See Instruction.deserialize.
82
- static readonly wireFormat: OperandType[] = [
83
- OperandType.UINT8,
84
- OperandType.UINT8,
85
- OperandType.UINT32,
86
- OperandType.UINT32,
87
- OperandType.UINT32,
88
- OperandType.UINT32,
89
- ];
90
-
91
- constructor(
92
- private indirect: number,
93
- private aOffset: number,
94
- private bOffset: number,
95
- private condOffset: number,
96
- private dstOffset: number,
97
- ) {
98
- super();
99
- }
100
-
101
- public async execute(context: AvmContext): Promise<void> {
102
- const memoryOperations = { reads: 3, writes: 1, indirect: this.indirect };
103
- const memory = context.machineState.memory.track(this.type);
104
- context.machineState.consumeGas(this.gasCost(memoryOperations));
105
-
106
- const [aOffset, bOffset, condOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
107
- [this.aOffset, this.bOffset, this.condOffset, this.dstOffset],
108
- memory,
109
- );
110
-
111
- const a = memory.get(aOffset);
112
- const b = memory.get(bOffset);
113
- const cond = memory.get(condOffset);
114
-
115
- // TODO: reconsider toBigInt() here
116
- memory.set(dstOffset, cond.toBigInt() > 0 ? a : b);
117
-
118
- memory.assert(memoryOperations);
74
+ memory.assert({ writes: 1, addressing });
119
75
  context.machineState.incrementPc();
120
76
  }
121
77
  }
@@ -144,18 +100,19 @@ export class Cast extends Instruction {
144
100
  }
145
101
 
146
102
  public async execute(context: AvmContext): Promise<void> {
147
- const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
148
103
  const memory = context.machineState.memory.track(this.type);
149
- context.machineState.consumeGas(this.gasCost(memoryOperations));
104
+ context.machineState.consumeGas(this.gasCost());
150
105
 
151
- const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.srcOffset, this.dstOffset], memory);
106
+ const operands = [this.srcOffset, this.dstOffset];
107
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
108
+ const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
152
109
 
153
110
  const a = memory.get(srcOffset);
154
111
  const casted = TaggedMemory.buildFromTagTruncating(a.toBigInt(), this.dstTag);
155
112
 
156
113
  memory.set(dstOffset, casted);
157
114
 
158
- memory.assert(memoryOperations);
115
+ memory.assert({ reads: 1, writes: 1, addressing });
159
116
  context.machineState.incrementPc();
160
117
  }
161
118
  }
@@ -183,17 +140,18 @@ export class Mov extends Instruction {
183
140
  }
184
141
 
185
142
  public async execute(context: AvmContext): Promise<void> {
186
- const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
187
143
  const memory = context.machineState.memory.track(this.type);
188
- context.machineState.consumeGas(this.gasCost(memoryOperations));
144
+ context.machineState.consumeGas(this.gasCost());
189
145
 
190
- const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.srcOffset, this.dstOffset], memory);
146
+ const operands = [this.srcOffset, this.dstOffset];
147
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
148
+ const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
191
149
 
192
150
  const a = memory.get(srcOffset);
193
151
 
194
152
  memory.set(dstOffset, a);
195
153
 
196
- memory.assert(memoryOperations);
154
+ memory.assert({ reads: 1, writes: 1, addressing });
197
155
  context.machineState.incrementPc();
198
156
  }
199
157
  }
@@ -222,21 +180,19 @@ export class CalldataCopy extends Instruction {
222
180
  public async execute(context: AvmContext): Promise<void> {
223
181
  const memory = context.machineState.memory.track(this.type);
224
182
  // We don't need to check tags here because: (1) the calldata is NOT in memory, and (2) we are the ones writing to destination.
225
- const [cdStartOffset, copySizeOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
226
- [this.cdStartOffset, this.copySizeOffset, this.dstOffset],
227
- memory,
228
- );
183
+ const operands = [this.cdStartOffset, this.copySizeOffset, this.dstOffset];
184
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
185
+ const [cdStartOffset, copySizeOffset, dstOffset] = addressing.resolve(operands, memory);
229
186
 
230
187
  const cdStart = memory.get(cdStartOffset).toNumber();
231
188
  const copySize = memory.get(copySizeOffset).toNumber();
232
- const memoryOperations = { reads: 2, writes: copySize, indirect: this.indirect };
233
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: copySize }));
189
+ context.machineState.consumeGas(this.gasCost(copySize));
234
190
 
235
191
  const transformedData = context.environment.calldata.slice(cdStart, cdStart + copySize).map(f => new Field(f));
236
192
 
237
193
  memory.setSlice(dstOffset, transformedData);
238
194
 
239
- memory.assert(memoryOperations);
195
+ memory.assert({ reads: 2, writes: copySize, addressing });
240
196
  context.machineState.incrementPc();
241
197
  }
242
198
  }
@@ -33,17 +33,15 @@ export class DebugLog extends Instruction {
33
33
 
34
34
  public async execute(context: AvmContext): Promise<void> {
35
35
  const memory = context.machineState.memory.track(this.type);
36
- const [messageOffset, fieldsOffset, fieldsSizeOffset] = Addressing.fromWire(this.indirect).resolve(
37
- [this.messageOffset, this.fieldsOffset, this.fieldsSizeOffset],
38
- memory,
39
- );
36
+ const operands = [this.messageOffset, this.fieldsOffset, this.fieldsSizeOffset];
37
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
38
+ const [messageOffset, fieldsOffset, fieldsSizeOffset] = addressing.resolve(operands, memory);
40
39
 
41
40
  const fieldsSize = memory.get(fieldsSizeOffset).toNumber();
42
41
  memory.checkTagsRange(TypeTag.UINT8, messageOffset, this.messageSize);
43
42
  memory.checkTagsRange(TypeTag.FIELD, fieldsOffset, fieldsSize);
44
43
 
45
- const memoryOperations = { reads: 1 + fieldsSize + this.messageSize, writes: 0, indirect: this.indirect };
46
- context.machineState.consumeGas(this.gasCost(memoryOperations));
44
+ context.machineState.consumeGas(this.gasCost());
47
45
 
48
46
  const rawMessage = memory.getSlice(messageOffset, this.messageSize);
49
47
  const fields = memory.getSlice(fieldsOffset, fieldsSize);
@@ -57,7 +55,7 @@ export class DebugLog extends Instruction {
57
55
 
58
56
  DebugLog.logger.verbose(formattedStr);
59
57
 
60
- memory.assert(memoryOperations);
58
+ memory.assert({ reads: 1 + fieldsSize + this.messageSize, addressing });
61
59
  context.machineState.incrementPc();
62
60
  }
63
61
  }
@@ -35,15 +35,14 @@ export class MultiScalarMul extends Instruction {
35
35
  public async execute(context: AvmContext): Promise<void> {
36
36
  const memory = context.machineState.memory.track(this.type);
37
37
  // Resolve indirects
38
- const [pointsOffset, scalarsOffset, outputOffset] = Addressing.fromWire(this.indirect).resolve(
39
- [this.pointsOffset, this.scalarsOffset, this.outputOffset],
40
- memory,
41
- );
38
+ const operands = [this.pointsOffset, this.scalarsOffset, this.outputOffset, this.pointsLengthOffset];
39
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
40
+ const [pointsOffset, scalarsOffset, outputOffset, pointsLengthOffset] = addressing.resolve(operands, memory);
42
41
 
43
42
  // Length of the points vector should be U32
44
- memory.checkTag(TypeTag.UINT32, this.pointsLengthOffset);
43
+ memory.checkTag(TypeTag.UINT32, pointsLengthOffset);
45
44
  // Get the size of the unrolled (x, y , inf) points vector
46
- const pointsReadLength = memory.get(this.pointsLengthOffset).toNumber();
45
+ const pointsReadLength = memory.get(pointsLengthOffset).toNumber();
47
46
  if (pointsReadLength % 3 !== 0) {
48
47
  throw new InstructionExecutionError(`Points vector offset should be a multiple of 3, was ${pointsReadLength}`);
49
48
  }
@@ -62,13 +61,7 @@ export class MultiScalarMul extends Instruction {
62
61
 
63
62
  // The size of the scalars vector is twice the NUMBER of points because of the scalar limb decomposition
64
63
  const scalarReadLength = numPoints * 2;
65
- // Consume gas prior to performing work
66
- const memoryOperations = {
67
- reads: 1 + pointsReadLength + scalarReadLength /* points and scalars */,
68
- writes: 3 /* output triplet */,
69
- indirect: this.indirect,
70
- };
71
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: pointsReadLength }));
64
+ context.machineState.consumeGas(this.gasCost(pointsReadLength));
72
65
  // Get the unrolled scalar (lo & hi) representing the scalars
73
66
  const scalarsVector = memory.getSlice(scalarsOffset, scalarReadLength);
74
67
  memory.checkTagsRange(TypeTag.FIELD, scalarsOffset, scalarReadLength);
@@ -108,7 +101,11 @@ export class MultiScalarMul extends Instruction {
108
101
 
109
102
  memory.setSlice(outputOffset, output);
110
103
 
111
- memory.assert(memoryOperations);
104
+ memory.assert({
105
+ reads: 1 + pointsReadLength + scalarReadLength /* points and scalars */,
106
+ writes: 3 /* output triplet */,
107
+ addressing,
108
+ });
112
109
  context.machineState.incrementPc();
113
110
  }
114
111
  }
@@ -32,11 +32,12 @@ export class SStore extends BaseStorageInstruction {
32
32
  throw new StaticCallAlterationError();
33
33
  }
34
34
 
35
- const memoryOperations = { reads: 2, indirect: this.indirect };
36
35
  const memory = context.machineState.memory.track(this.type);
37
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations }));
36
+ context.machineState.consumeGas(this.gasCost());
38
37
 
39
- const [srcOffset, slotOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], memory);
38
+ const operands = [this.aOffset, this.bOffset];
39
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
40
+ const [srcOffset, slotOffset] = addressing.resolve(operands, memory);
40
41
  memory.checkTag(TypeTag.FIELD, slotOffset);
41
42
  memory.checkTag(TypeTag.FIELD, srcOffset);
42
43
 
@@ -44,7 +45,7 @@ export class SStore extends BaseStorageInstruction {
44
45
  const value = memory.get(srcOffset).toFr();
45
46
  context.persistableState.writeStorage(context.environment.storageAddress, slot, value);
46
47
 
47
- memory.assert(memoryOperations);
48
+ memory.assert({ reads: 2, addressing });
48
49
  context.machineState.incrementPc();
49
50
  }
50
51
  }
@@ -58,11 +59,12 @@ export class SLoad extends BaseStorageInstruction {
58
59
  }
59
60
 
60
61
  public async execute(context: AvmContext): Promise<void> {
61
- const memoryOperations = { writes: 1, reads: 1, indirect: this.indirect };
62
62
  const memory = context.machineState.memory.track(this.type);
63
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations }));
63
+ context.machineState.consumeGas(this.gasCost());
64
64
 
65
- const [slotOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], memory);
65
+ const operands = [this.aOffset, this.bOffset];
66
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
67
+ const [slotOffset, dstOffset] = addressing.resolve(operands, memory);
66
68
  memory.checkTag(TypeTag.FIELD, slotOffset);
67
69
 
68
70
  const slot = memory.get(slotOffset).toFr();
@@ -70,6 +72,6 @@ export class SLoad extends BaseStorageInstruction {
70
72
  memory.set(dstOffset, new Field(value));
71
73
 
72
74
  context.machineState.incrementPc();
73
- memory.assert(memoryOperations);
75
+ memory.assert({ writes: 1, reads: 1, addressing });
74
76
  }
75
77
  }
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  Add,
3
3
  And,
4
- CMov,
5
4
  Call,
6
5
  CalldataCopy,
7
6
  Cast,
@@ -114,7 +113,6 @@ const INSTRUCTION_SET = () =>
114
113
  [Opcode.SET_FF, Set.as(Set.wireFormatFF).deserialize],
115
114
  [Opcode.MOV_8, Mov.as(Mov.wireFormat8).deserialize],
116
115
  [Opcode.MOV_16, Mov.as(Mov.wireFormat16).deserialize],
117
- [CMov.opcode, Instruction.deserialize.bind(CMov)],
118
116
 
119
117
  // World State
120
118
  [SLoad.opcode, Instruction.deserialize.bind(SLoad)], // Public Storage
@@ -55,7 +55,6 @@ export enum Opcode {
55
55
  SET_FF,
56
56
  MOV_8,
57
57
  MOV_16,
58
- CMOV,
59
58
  // World state
60
59
  SLOAD,
61
60
  SSTORE,
@@ -94,7 +93,6 @@ export enum Opcode {
94
93
  // Note that cpp code introduced an additional enum value TAG to express the instruction tag. In TS,
95
94
  // this one is parsed as UINT8.
96
95
  export enum OperandType {
97
- UINT1,
98
96
  UINT8,
99
97
  UINT16,
100
98
  UINT32,
@@ -108,7 +106,6 @@ type OperandWriter = (value: any) => void;
108
106
 
109
107
  // Specifies how to read and write each operand type.
110
108
  const OPERAND_SPEC = new Map<OperandType, [number, () => OperandNativeType, OperandWriter]>([
111
- [OperandType.UINT1, [1, Buffer.prototype.readUint8, Buffer.prototype.writeUint8]],
112
109
  [OperandType.UINT8, [1, Buffer.prototype.readUint8, Buffer.prototype.writeUint8]],
113
110
  [OperandType.UINT16, [2, Buffer.prototype.readUint16BE, Buffer.prototype.writeUint16BE]],
114
111
  [OperandType.UINT32, [4, Buffer.prototype.readUint32BE, Buffer.prototype.writeUint32BE]],