@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
@@ -3,6 +3,7 @@ import { Fr } from '@aztec/foundation/fields';
3
3
  import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
4
4
  import { SerializableContractInstance } from '@aztec/types/contracts';
5
5
 
6
+ import { getPublicFunctionDebugName } from '../../common/debug_fn_name.js';
6
7
  import { type WorldStateDB } from '../../public/public_db_sources.js';
7
8
  import { type TracedContractInstance } from '../../public/side_effect_trace.js';
8
9
  import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js';
@@ -187,12 +188,13 @@ export class AvmPersistableStateManager {
187
188
 
188
189
  /**
189
190
  * Write an L2 to L1 message.
191
+ * @param contractAddress - L2 contract address that created this message
190
192
  * @param recipient - L1 contract address to send the message to.
191
193
  * @param content - Message content.
192
194
  */
193
- public writeL2ToL1Message(recipient: Fr, content: Fr) {
194
- this.log.debug(`L1Messages(${recipient}) += ${content}.`);
195
- this.trace.traceNewL2ToL1Message(recipient, content);
195
+ public writeL2ToL1Message(contractAddress: Fr, recipient: Fr, content: Fr) {
196
+ this.log.debug(`L2ToL1Messages(${contractAddress}) += (recipient: ${recipient}, content: ${content}).`);
197
+ this.trace.traceNewL2ToL1Message(contractAddress, recipient, content);
196
198
  }
197
199
 
198
200
  /**
@@ -256,9 +258,12 @@ export class AvmPersistableStateManager {
256
258
  if (!avmCallResults.reverted) {
257
259
  this.acceptNestedCallState(nestedState);
258
260
  }
259
- const functionName =
260
- (await this.worldStateDB.getDebugFunctionName(nestedEnvironment.address, nestedEnvironment.functionSelector)) ??
261
- `${nestedEnvironment.address}:${nestedEnvironment.functionSelector}`;
261
+ const functionName = await getPublicFunctionDebugName(
262
+ this.worldStateDB,
263
+ nestedEnvironment.address,
264
+ nestedEnvironment.functionSelector,
265
+ nestedEnvironment.calldata,
266
+ );
262
267
 
263
268
  this.log.verbose(`[AVM] Calling nested function ${functionName}`);
264
269
 
@@ -28,13 +28,11 @@ export class NoteHashExists extends Instruction {
28
28
  }
29
29
 
30
30
  public async execute(context: AvmContext): Promise<void> {
31
- const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
32
31
  const memory = context.machineState.memory.track(this.type);
33
- context.machineState.consumeGas(this.gasCost(memoryOperations));
34
- const [noteHashOffset, leafIndexOffset, existsOffset] = Addressing.fromWire(this.indirect).resolve(
35
- [this.noteHashOffset, this.leafIndexOffset, this.existsOffset],
36
- memory,
37
- );
32
+ context.machineState.consumeGas(this.gasCost());
33
+ const operands = [this.noteHashOffset, this.leafIndexOffset, this.existsOffset];
34
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
35
+ const [noteHashOffset, leafIndexOffset, existsOffset] = addressing.resolve(operands, memory);
38
36
  memory.checkTags(TypeTag.FIELD, noteHashOffset, leafIndexOffset);
39
37
 
40
38
  // Note that this instruction accepts any type in memory, and converts to Field.
@@ -48,7 +46,7 @@ export class NoteHashExists extends Instruction {
48
46
  );
49
47
  memory.set(existsOffset, exists ? new Uint8(1) : new Uint8(0));
50
48
 
51
- memory.assert(memoryOperations);
49
+ memory.assert({ reads: 2, writes: 1, addressing });
52
50
  context.machineState.incrementPc();
53
51
  }
54
52
  }
@@ -64,11 +62,12 @@ export class EmitNoteHash extends Instruction {
64
62
  }
65
63
 
66
64
  public async execute(context: AvmContext): Promise<void> {
67
- const memoryOperations = { reads: 1, indirect: this.indirect };
68
65
  const memory = context.machineState.memory.track(this.type);
69
- context.machineState.consumeGas(this.gasCost(memoryOperations));
66
+ context.machineState.consumeGas(this.gasCost());
70
67
 
71
- const [noteHashOffset] = Addressing.fromWire(this.indirect).resolve([this.noteHashOffset], memory);
68
+ const operands = [this.noteHashOffset];
69
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
70
+ const [noteHashOffset] = addressing.resolve(operands, memory);
72
71
  memory.checkTag(TypeTag.FIELD, noteHashOffset);
73
72
 
74
73
  if (context.environment.isStaticCall) {
@@ -78,7 +77,7 @@ export class EmitNoteHash extends Instruction {
78
77
  const noteHash = memory.get(noteHashOffset).toFr();
79
78
  context.persistableState.writeNoteHash(context.environment.storageAddress, noteHash);
80
79
 
81
- memory.assert(memoryOperations);
80
+ memory.assert({ reads: 1, addressing });
82
81
  context.machineState.incrementPc();
83
82
  }
84
83
  }
@@ -105,14 +104,12 @@ export class NullifierExists extends Instruction {
105
104
  }
106
105
 
107
106
  public async execute(context: AvmContext): Promise<void> {
108
- const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
109
107
  const memory = context.machineState.memory.track(this.type);
110
- context.machineState.consumeGas(this.gasCost(memoryOperations));
108
+ context.machineState.consumeGas(this.gasCost());
111
109
 
112
- const [nullifierOffset, addressOffset, existsOffset] = Addressing.fromWire(this.indirect).resolve(
113
- [this.nullifierOffset, this.addressOffset, this.existsOffset],
114
- memory,
115
- );
110
+ const operands = [this.nullifierOffset, this.addressOffset, this.existsOffset];
111
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
112
+ const [nullifierOffset, addressOffset, existsOffset] = addressing.resolve(operands, memory);
116
113
  memory.checkTags(TypeTag.FIELD, nullifierOffset, addressOffset);
117
114
 
118
115
  const nullifier = memory.get(nullifierOffset).toFr();
@@ -121,7 +118,7 @@ export class NullifierExists extends Instruction {
121
118
 
122
119
  memory.set(existsOffset, exists ? new Uint8(1) : new Uint8(0));
123
120
 
124
- memory.assert(memoryOperations);
121
+ memory.assert({ reads: 2, writes: 1, addressing });
125
122
  context.machineState.incrementPc();
126
123
  }
127
124
  }
@@ -141,11 +138,12 @@ export class EmitNullifier extends Instruction {
141
138
  throw new StaticCallAlterationError();
142
139
  }
143
140
 
144
- const memoryOperations = { reads: 1, indirect: this.indirect };
145
141
  const memory = context.machineState.memory.track(this.type);
146
- context.machineState.consumeGas(this.gasCost(memoryOperations));
142
+ context.machineState.consumeGas(this.gasCost());
147
143
 
148
- const [nullifierOffset] = Addressing.fromWire(this.indirect).resolve([this.nullifierOffset], memory);
144
+ const operands = [this.nullifierOffset];
145
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
146
+ const [nullifierOffset] = addressing.resolve(operands, memory);
149
147
  memory.checkTag(TypeTag.FIELD, nullifierOffset);
150
148
 
151
149
  const nullifier = memory.get(nullifierOffset).toFr();
@@ -162,7 +160,7 @@ export class EmitNullifier extends Instruction {
162
160
  }
163
161
  }
164
162
 
165
- memory.assert(memoryOperations);
163
+ memory.assert({ reads: 1, addressing });
166
164
  context.machineState.incrementPc();
167
165
  }
168
166
  }
@@ -189,14 +187,12 @@ export class L1ToL2MessageExists extends Instruction {
189
187
  }
190
188
 
191
189
  public async execute(context: AvmContext): Promise<void> {
192
- const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
193
190
  const memory = context.machineState.memory.track(this.type);
194
- context.machineState.consumeGas(this.gasCost(memoryOperations));
191
+ context.machineState.consumeGas(this.gasCost());
195
192
 
196
- const [msgHashOffset, msgLeafIndexOffset, existsOffset] = Addressing.fromWire(this.indirect).resolve(
197
- [this.msgHashOffset, this.msgLeafIndexOffset, this.existsOffset],
198
- memory,
199
- );
193
+ const operands = [this.msgHashOffset, this.msgLeafIndexOffset, this.existsOffset];
194
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
195
+ const [msgHashOffset, msgLeafIndexOffset, existsOffset] = addressing.resolve(operands, memory);
200
196
  memory.checkTags(TypeTag.FIELD, msgHashOffset, msgLeafIndexOffset);
201
197
 
202
198
  const msgHash = memory.get(msgHashOffset).toFr();
@@ -208,7 +204,7 @@ export class L1ToL2MessageExists extends Instruction {
208
204
  );
209
205
  memory.set(existsOffset, exists ? new Uint8(1) : new Uint8(0));
210
206
 
211
- memory.assert(memoryOperations);
207
+ memory.assert({ reads: 2, writes: 1, addressing });
212
208
  context.machineState.incrementPc();
213
209
  }
214
210
  }
@@ -230,22 +226,20 @@ export class EmitUnencryptedLog extends Instruction {
230
226
 
231
227
  const memory = context.machineState.memory.track(this.type);
232
228
 
233
- const [logOffset, logSizeOffset] = Addressing.fromWire(this.indirect).resolve(
234
- [this.logOffset, this.logSizeOffset],
235
- memory,
236
- );
229
+ const operands = [this.logOffset, this.logSizeOffset];
230
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
231
+ const [logOffset, logSizeOffset] = addressing.resolve(operands, memory);
237
232
  memory.checkTag(TypeTag.UINT32, logSizeOffset);
238
233
  const logSize = memory.get(logSizeOffset).toNumber();
239
234
  memory.checkTagsRange(TypeTag.FIELD, logOffset, logSize);
240
235
 
241
236
  const contractAddress = context.environment.address;
242
237
 
243
- const memoryOperations = { reads: 1 + logSize, indirect: this.indirect };
244
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: logSize }));
238
+ context.machineState.consumeGas(this.gasCost(logSize));
245
239
  const log = memory.getSlice(logOffset, logSize).map(f => f.toFr());
246
240
  context.persistableState.writeUnencryptedLog(contractAddress, log);
247
241
 
248
- memory.assert(memoryOperations);
242
+ memory.assert({ reads: 1 + logSize, addressing });
249
243
  context.machineState.incrementPc();
250
244
  }
251
245
  }
@@ -265,20 +259,18 @@ export class SendL2ToL1Message extends Instruction {
265
259
  throw new StaticCallAlterationError();
266
260
  }
267
261
 
268
- const memoryOperations = { reads: 2, indirect: this.indirect };
269
262
  const memory = context.machineState.memory.track(this.type);
270
- context.machineState.consumeGas(this.gasCost(memoryOperations));
263
+ context.machineState.consumeGas(this.gasCost());
271
264
 
272
- const [recipientOffset, contentOffset] = Addressing.fromWire(this.indirect).resolve(
273
- [this.recipientOffset, this.contentOffset],
274
- memory,
275
- );
265
+ const operands = [this.recipientOffset, this.contentOffset];
266
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
267
+ const [recipientOffset, contentOffset] = addressing.resolve(operands, memory);
276
268
 
277
269
  const recipient = memory.get(recipientOffset).toFr();
278
270
  const content = memory.get(contentOffset).toFr();
279
- context.persistableState.writeL2ToL1Message(recipient, content);
271
+ context.persistableState.writeL2ToL1Message(context.environment.address, recipient, content);
280
272
 
281
- memory.assert(memoryOperations);
273
+ memory.assert({ reads: 2, addressing });
282
274
  context.machineState.incrementPc();
283
275
  }
284
276
  }
@@ -3,9 +3,10 @@ import { strict as assert } from 'assert';
3
3
  import { type TaggedMemoryInterface } from '../avm_memory_types.js';
4
4
 
5
5
  export enum AddressingMode {
6
- DIRECT,
7
- INDIRECT,
8
- INDIRECT_PLUS_CONSTANT, // Not implemented yet.
6
+ DIRECT = 0,
7
+ INDIRECT = 1,
8
+ RELATIVE = 2,
9
+ INDIRECT_RELATIVE = 3,
9
10
  }
10
11
 
11
12
  /** A class to represent the addressing mode of an instruction. */
@@ -13,16 +14,17 @@ export class Addressing {
13
14
  public constructor(
14
15
  /** The addressing mode for each operand. The length of this array is the number of operands of the instruction. */
15
16
  private readonly modePerOperand: AddressingMode[],
16
- ) {
17
- assert(modePerOperand.length <= 8, 'At most 8 operands are supported');
18
- }
17
+ ) {}
19
18
 
20
- public static fromWire(wireModes: number): Addressing {
19
+ // TODO(facundo): 8 for backwards compatibility.
20
+ public static fromWire(wireModes: number, numOperands: number = 8): Addressing {
21
21
  // The modes are stored in the wire format as a byte, with each bit representing the mode for an operand.
22
22
  // The least significant bit represents the zeroth operand, and the most significant bit represents the last operand.
23
- const modes = new Array<AddressingMode>(8);
24
- for (let i = 0; i < 8; i++) {
25
- modes[i] = (wireModes & (1 << i)) === 0 ? AddressingMode.DIRECT : AddressingMode.INDIRECT;
23
+ const modes = new Array<AddressingMode>(numOperands);
24
+ for (let i = 0; i < numOperands; i++) {
25
+ modes[i] =
26
+ (((wireModes >> i) & 1) * AddressingMode.INDIRECT) |
27
+ (((wireModes >> (i + numOperands)) & 1) * AddressingMode.RELATIVE);
26
28
  }
27
29
  return new Addressing(modes);
28
30
  }
@@ -31,17 +33,20 @@ export class Addressing {
31
33
  // The modes are stored in the wire format as a byte, with each bit representing the mode for an operand.
32
34
  // The least significant bit represents the zeroth operand, and the least significant bit represents the last operand.
33
35
  let wire: number = 0;
34
- for (let i = 0; i < 8; i++) {
35
- if (this.modePerOperand[i] === AddressingMode.INDIRECT) {
36
+ for (let i = 0; i < this.modePerOperand.length; i++) {
37
+ if (this.modePerOperand[i] & AddressingMode.INDIRECT) {
36
38
  wire |= 1 << i;
37
39
  }
40
+ if (this.modePerOperand[i] & AddressingMode.RELATIVE) {
41
+ wire |= 1 << (this.modePerOperand.length + i);
42
+ }
38
43
  }
39
44
  return wire;
40
45
  }
41
46
 
42
47
  /** Returns how many operands use the given addressing mode. */
43
48
  public count(mode: AddressingMode): number {
44
- return this.modePerOperand.filter(m => m === mode).length;
49
+ return this.modePerOperand.filter(m => (m & mode) !== 0).length;
45
50
  }
46
51
 
47
52
  /**
@@ -54,17 +59,15 @@ export class Addressing {
54
59
  assert(offsets.length <= this.modePerOperand.length);
55
60
  const resolved = new Array(offsets.length);
56
61
  for (const [i, offset] of offsets.entries()) {
57
- switch (this.modePerOperand[i]) {
58
- case AddressingMode.INDIRECT:
59
- // NOTE(reviewer): less than equal is a deviation from the spec - i dont see why this shouldnt be possible!
60
- mem.checkIsValidMemoryOffsetTag(offset);
61
- resolved[i] = Number(mem.get(offset).toBigInt());
62
- break;
63
- case AddressingMode.DIRECT:
64
- resolved[i] = offset;
65
- break;
66
- default:
67
- throw new Error(`Unimplemented addressing mode: ${AddressingMode[this.modePerOperand[i]]}`);
62
+ const mode = this.modePerOperand[i];
63
+ resolved[i] = offset;
64
+ if (mode & AddressingMode.RELATIVE) {
65
+ mem.checkIsValidMemoryOffsetTag(0);
66
+ resolved[i] += Number(mem.get(0).toBigInt());
67
+ }
68
+ if (mode & AddressingMode.INDIRECT) {
69
+ mem.checkIsValidMemoryOffsetTag(resolved[i]);
70
+ resolved[i] = Number(mem.get(resolved[i]).toBigInt());
68
71
  }
69
72
  }
70
73
  return resolved;
@@ -6,14 +6,12 @@ import { ThreeOperandInstruction } from './instruction_impl.js';
6
6
 
7
7
  export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInstruction {
8
8
  public async execute(context: AvmContext): Promise<void> {
9
- const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
10
9
  const memory = context.machineState.memory.track(this.type);
11
- context.machineState.consumeGas(this.gasCost(memoryOperations));
10
+ context.machineState.consumeGas(this.gasCost());
12
11
 
13
- const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
14
- [this.aOffset, this.bOffset, this.dstOffset],
15
- memory,
16
- );
12
+ const operands = [this.aOffset, this.bOffset, this.dstOffset];
13
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
14
+ const [aOffset, bOffset, dstOffset] = addressing.resolve(operands, memory);
17
15
  memory.checkTags(this.inTag, aOffset, bOffset);
18
16
 
19
17
  const a = memory.get(aOffset);
@@ -22,7 +20,7 @@ export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInst
22
20
  const dest = this.compute(a, b);
23
21
  memory.set(dstOffset, dest);
24
22
 
25
- memory.assert(memoryOperations);
23
+ memory.assert({ reads: 2, writes: 1, addressing });
26
24
  context.machineState.incrementPc();
27
25
  }
28
26
 
@@ -7,14 +7,12 @@ import { ThreeOperandInstruction } from './instruction_impl.js';
7
7
 
8
8
  abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
9
9
  public async execute(context: AvmContext): Promise<void> {
10
- const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
11
10
  const memory = context.machineState.memory.track(this.type);
12
- context.machineState.consumeGas(this.gasCost(memoryOperations));
11
+ context.machineState.consumeGas(this.gasCost());
13
12
 
14
- const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
15
- [this.aOffset, this.bOffset, this.dstOffset],
16
- memory,
17
- );
13
+ const operands = [this.aOffset, this.bOffset, this.dstOffset];
14
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
15
+ const [aOffset, bOffset, dstOffset] = addressing.resolve(operands, memory);
18
16
  this.checkTags(memory, this.inTag, aOffset, bOffset);
19
17
 
20
18
  const a = memory.getAs<IntegralValue>(aOffset);
@@ -23,7 +21,7 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
23
21
  const res = this.compute(a, b);
24
22
  memory.set(dstOffset, res);
25
23
 
26
- memory.assert(memoryOperations);
24
+ memory.assert({ reads: 2, writes: 1, addressing });
27
25
  context.machineState.incrementPc();
28
26
  }
29
27
 
@@ -98,18 +96,19 @@ export class Not extends Instruction {
98
96
  }
99
97
 
100
98
  public async execute(context: AvmContext): Promise<void> {
101
- const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
102
99
  const memory = context.machineState.memory.track(this.type);
103
- context.machineState.consumeGas(this.gasCost(memoryOperations));
100
+ context.machineState.consumeGas(this.gasCost());
104
101
 
105
- const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.srcOffset, this.dstOffset], memory);
102
+ const operands = [this.srcOffset, this.dstOffset];
103
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
104
+ const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
106
105
  TaggedMemory.checkIsIntegralTag(memory.getTag(srcOffset));
107
106
  const value = memory.getAs<IntegralValue>(srcOffset);
108
107
 
109
108
  const res = value.not();
110
109
  memory.set(dstOffset, res);
111
110
 
112
- memory.assert(memoryOperations);
111
+ memory.assert({ reads: 1, writes: 1, addressing });
113
112
  context.machineState.incrementPc();
114
113
  }
115
114
  }
@@ -32,10 +32,10 @@ export class PedersenCommitment extends Instruction {
32
32
 
33
33
  public async execute(context: AvmContext): Promise<void> {
34
34
  const memory = context.machineState.memory.track(this.type);
35
- const [inputOffset, outputOffset, inputSizeOffset, genIndexOffset] = Addressing.fromWire(this.indirect).resolve(
36
- [this.inputOffset, this.outputOffset, this.inputSizeOffset, this.genIndexOffset],
37
- memory,
38
- );
35
+
36
+ const operands = [this.inputOffset, this.outputOffset, this.inputSizeOffset, this.genIndexOffset];
37
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
38
+ const [inputOffset, outputOffset, inputSizeOffset, genIndexOffset] = addressing.resolve(operands, memory);
39
39
 
40
40
  const inputSize = memory.get(inputSizeOffset).toNumber();
41
41
  memory.checkTag(TypeTag.UINT32, inputSizeOffset);
@@ -46,8 +46,7 @@ export class PedersenCommitment extends Instruction {
46
46
  const generatorIndex = memory.get(genIndexOffset).toNumber();
47
47
  memory.checkTag(TypeTag.UINT32, genIndexOffset);
48
48
 
49
- const memoryOperations = { reads: inputSize + 2, writes: 3, indirect: this.indirect };
50
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: inputSize }));
49
+ context.machineState.consumeGas(this.gasCost(inputSize));
51
50
 
52
51
  const inputBuffer: Buffer[] = inputs.map(input => input.toBuffer());
53
52
  // TODO: Add the generate index to the pedersenCommit function
@@ -60,7 +59,7 @@ export class PedersenCommitment extends Instruction {
60
59
  memory.set(outputOffset + 1, commitment[1]); // Field typed
61
60
  memory.set(outputOffset + 2, new Uint8(isInfinity ? 1 : 0)); // U8 typed
62
61
 
63
- memory.assert(memoryOperations);
62
+ memory.assert({ reads: inputSize + 2, writes: 3, addressing });
64
63
  context.machineState.incrementPc();
65
64
  }
66
65
  }
@@ -6,14 +6,12 @@ import { ThreeOperandInstruction } from './instruction_impl.js';
6
6
 
7
7
  abstract class ComparatorInstruction extends ThreeOperandInstruction {
8
8
  public async execute(context: AvmContext): Promise<void> {
9
- const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
10
9
  const memory = context.machineState.memory.track(this.type);
11
- context.machineState.consumeGas(this.gasCost(memoryOperations));
10
+ context.machineState.consumeGas(this.gasCost());
12
11
 
13
- const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
14
- [this.aOffset, this.bOffset, this.dstOffset],
15
- memory,
16
- );
12
+ const operands = [this.aOffset, this.bOffset, this.dstOffset];
13
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
14
+ const [aOffset, bOffset, dstOffset] = addressing.resolve(operands, memory);
17
15
  memory.checkTags(this.inTag, aOffset, bOffset);
18
16
 
19
17
  const a = memory.get(aOffset);
@@ -22,7 +20,7 @@ abstract class ComparatorInstruction extends ThreeOperandInstruction {
22
20
  const dest = new Uint1(this.compare(a, b) ? 1 : 0);
23
21
  memory.set(dstOffset, dest);
24
22
 
25
- memory.assert(memoryOperations);
23
+ memory.assert({ reads: 2, writes: 1, addressing });
26
24
  context.machineState.incrementPc();
27
25
  }
28
26
 
@@ -22,14 +22,12 @@ export class GetContractInstance extends Instruction {
22
22
  }
23
23
 
24
24
  async execute(context: AvmContext): Promise<void> {
25
- const memoryOperations = { reads: 1, writes: 6, indirect: this.indirect };
26
25
  const memory = context.machineState.memory.track(this.type);
27
- context.machineState.consumeGas(this.gasCost(memoryOperations));
26
+ context.machineState.consumeGas(this.gasCost());
28
27
 
29
- const [addressOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
30
- [this.addressOffset, this.dstOffset],
31
- memory,
32
- );
28
+ const operands = [this.addressOffset, this.dstOffset];
29
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
30
+ const [addressOffset, dstOffset] = addressing.resolve(operands, memory);
33
31
  memory.checkTag(TypeTag.FIELD, addressOffset);
34
32
 
35
33
  const address = memory.get(addressOffset).toFr();
@@ -46,7 +44,7 @@ export class GetContractInstance extends Instruction {
46
44
 
47
45
  memory.setSlice(dstOffset, data);
48
46
 
49
- memory.assert(memoryOperations);
47
+ memory.assert({ reads: 1, writes: 6, addressing });
50
48
  context.machineState.incrementPc();
51
49
  }
52
50
  }
@@ -41,21 +41,21 @@ export class JumpI extends Instruction {
41
41
  }
42
42
 
43
43
  public async execute(context: AvmContext): Promise<void> {
44
- const memoryOperations = { reads: 1, indirect: this.indirect };
45
44
  const memory = context.machineState.memory.track(this.type);
46
- context.machineState.consumeGas(this.gasCost(memoryOperations));
45
+ context.machineState.consumeGas(this.gasCost());
47
46
 
48
- const [condOffset] = Addressing.fromWire(this.indirect).resolve([this.condOffset], memory);
47
+ const operands = [this.condOffset];
48
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
49
+ const [condOffset] = addressing.resolve(operands, memory);
49
50
  const condition = memory.getAs<IntegralValue>(condOffset);
50
51
 
51
- // TODO: reconsider this casting
52
52
  if (condition.toBigInt() == 0n) {
53
53
  context.machineState.incrementPc();
54
54
  } else {
55
55
  context.machineState.pc = this.loc;
56
56
  }
57
57
 
58
- memory.assert(memoryOperations);
58
+ memory.assert({ reads: 1, addressing });
59
59
  }
60
60
  }
61
61
 
@@ -17,7 +17,7 @@ export class ToRadixLE extends Instruction {
17
17
  OperandType.UINT32, // dst memory address
18
18
  OperandType.UINT32, // radix memory address
19
19
  OperandType.UINT32, // number of limbs (Immediate)
20
- OperandType.UINT1, // output is in "bits" mode (Immediate - Uint1 still takes up a whole byte)
20
+ OperandType.UINT8, // output is in "bits" mode (Immediate - Uint1 still takes up a whole byte)
21
21
  ];
22
22
 
23
23
  constructor(
@@ -33,12 +33,10 @@ export class ToRadixLE 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 [srcOffset, dstOffset, radixOffset] = Addressing.fromWire(this.indirect).resolve(
37
- [this.srcOffset, this.dstOffset, this.radixOffset],
38
- memory,
39
- );
40
- const memoryOperations = { reads: 2, writes: this.numLimbs, indirect: this.indirect };
41
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: this.numLimbs }));
36
+ const operands = [this.srcOffset, this.dstOffset, this.radixOffset];
37
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
38
+ const [srcOffset, dstOffset, radixOffset] = addressing.resolve(operands, memory);
39
+ context.machineState.consumeGas(this.gasCost(this.numLimbs));
42
40
 
43
41
  // The radix gadget only takes in a Field
44
42
  memory.checkTag(TypeTag.FIELD, srcOffset);
@@ -62,7 +60,7 @@ export class ToRadixLE extends Instruction {
62
60
  const res = limbArray.map(byte => new outputType(byte));
63
61
  memory.setSlice(dstOffset, res);
64
62
 
65
- memory.assert(memoryOperations);
63
+ memory.assert({ reads: 2, writes: this.numLimbs, addressing });
66
64
  context.machineState.incrementPc();
67
65
  }
68
66
  }
@@ -14,7 +14,7 @@ export class EcAdd extends Instruction {
14
14
  // Informs (de)serialization. See Instruction.deserialize.
15
15
  static readonly wireFormat: OperandType[] = [
16
16
  OperandType.UINT8, // reserved
17
- OperandType.UINT8, // indirect
17
+ OperandType.UINT16, // indirect
18
18
  OperandType.UINT32, // p1X
19
19
  OperandType.UINT32, // p1Y
20
20
  OperandType.UINT32, // p1IsInfinite
@@ -38,23 +38,21 @@ export class EcAdd extends Instruction {
38
38
  }
39
39
 
40
40
  public async execute(context: AvmContext): Promise<void> {
41
- const memoryOperations = { reads: 6, writes: 3, indirect: this.indirect };
42
41
  const memory = context.machineState.memory.track(this.type);
43
- context.machineState.consumeGas(this.gasCost(memoryOperations));
42
+ context.machineState.consumeGas(this.gasCost());
44
43
 
44
+ const operands = [
45
+ this.p1XOffset,
46
+ this.p1YOffset,
47
+ this.p1IsInfiniteOffset,
48
+ this.p2XOffset,
49
+ this.p2YOffset,
50
+ this.p2IsInfiniteOffset,
51
+ this.dstOffset,
52
+ ];
53
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
45
54
  const [p1XOffset, p1YOffset, p1IsInfiniteOffset, p2XOffset, p2YOffset, p2IsInfiniteOffset, dstOffset] =
46
- Addressing.fromWire(this.indirect).resolve(
47
- [
48
- this.p1XOffset,
49
- this.p1YOffset,
50
- this.p1IsInfiniteOffset,
51
- this.p2XOffset,
52
- this.p2YOffset,
53
- this.p2IsInfiniteOffset,
54
- this.dstOffset,
55
- ],
56
- memory,
57
- );
55
+ addressing.resolve(operands, memory);
58
56
 
59
57
  const p1X = memory.get(p1XOffset);
60
58
  const p1Y = memory.get(p1YOffset);
@@ -86,7 +84,7 @@ export class EcAdd extends Instruction {
86
84
  // Check representation of infinity for grumpkin
87
85
  memory.set(dstOffset + 2, new Field(dest.equals(Point.ZERO) ? 1 : 0));
88
86
 
89
- memory.assert(memoryOperations);
87
+ memory.assert({ reads: 6, writes: 3, addressing });
90
88
  context.machineState.incrementPc();
91
89
  }
92
90
  }
@@ -71,15 +71,16 @@ export class GetEnvVar extends Instruction {
71
71
  }
72
72
 
73
73
  public async execute(context: AvmContext): Promise<void> {
74
- const memoryOperations = { writes: 1, indirect: this.indirect };
75
74
  const memory = context.machineState.memory.track(this.type);
76
- context.machineState.consumeGas(this.gasCost(memoryOperations));
75
+ context.machineState.consumeGas(this.gasCost());
77
76
 
78
- const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], memory);
77
+ const operands = [this.dstOffset];
78
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
79
+ const [dstOffset] = addressing.resolve(operands, memory);
79
80
 
80
81
  memory.set(dstOffset, getValue(this.varEnum, context));
81
82
 
82
- memory.assert(memoryOperations);
83
+ memory.assert({ writes: 1, addressing });
83
84
  context.machineState.incrementPc();
84
85
  }
85
86
  }