@aztec/simulator 0.32.1 → 0.34.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 (160) hide show
  1. package/README.md +5 -3
  2. package/dest/acvm/acvm.js +2 -2
  3. package/dest/acvm/oracle/index.d.ts +0 -1
  4. package/dest/acvm/oracle/index.d.ts.map +1 -1
  5. package/dest/acvm/oracle/index.js +1 -2
  6. package/dest/acvm/oracle/oracle.d.ts +1 -1
  7. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  8. package/dest/acvm/oracle/oracle.js +4 -5
  9. package/dest/avm/avm_context.d.ts +4 -14
  10. package/dest/avm/avm_context.d.ts.map +1 -1
  11. package/dest/avm/avm_context.js +10 -22
  12. package/dest/avm/avm_execution_environment.d.ts +4 -3
  13. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  14. package/dest/avm/avm_execution_environment.js +8 -7
  15. package/dest/avm/avm_gas.d.ts +71 -0
  16. package/dest/avm/avm_gas.d.ts.map +1 -0
  17. package/dest/avm/avm_gas.js +161 -0
  18. package/dest/avm/avm_machine_state.d.ts +4 -2
  19. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  20. package/dest/avm/avm_machine_state.js +8 -2
  21. package/dest/avm/avm_memory_types.d.ts +53 -1
  22. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  23. package/dest/avm/avm_memory_types.js +99 -6
  24. package/dest/avm/avm_simulator.d.ts.map +1 -1
  25. package/dest/avm/avm_simulator.js +15 -13
  26. package/dest/avm/fixtures/index.d.ts.map +1 -1
  27. package/dest/avm/fixtures/index.js +3 -3
  28. package/dest/avm/journal/journal.d.ts +14 -13
  29. package/dest/avm/journal/journal.d.ts.map +1 -1
  30. package/dest/avm/journal/journal.js +5 -5
  31. package/dest/avm/journal/trace.d.ts +8 -19
  32. package/dest/avm/journal/trace.d.ts.map +1 -1
  33. package/dest/avm/journal/trace.js +48 -116
  34. package/dest/avm/journal/trace_types.d.ts +23 -4
  35. package/dest/avm/journal/trace_types.d.ts.map +1 -1
  36. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  37. package/dest/avm/opcodes/accrued_substate.js +45 -17
  38. package/dest/avm/opcodes/addressing_mode.d.ts +5 -3
  39. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
  40. package/dest/avm/opcodes/addressing_mode.js +5 -1
  41. package/dest/avm/opcodes/arithmetic.d.ts +7 -3
  42. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  43. package/dest/avm/opcodes/arithmetic.js +27 -16
  44. package/dest/avm/opcodes/bitwise.d.ts +21 -20
  45. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  46. package/dest/avm/opcodes/bitwise.js +43 -65
  47. package/dest/avm/opcodes/comparators.d.ts +12 -9
  48. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  49. package/dest/avm/opcodes/comparators.js +22 -32
  50. package/dest/avm/opcodes/context_getters.d.ts +20 -0
  51. package/dest/avm/opcodes/context_getters.d.ts.map +1 -0
  52. package/dest/avm/opcodes/context_getters.js +26 -0
  53. package/dest/avm/opcodes/contract.d.ts +14 -0
  54. package/dest/avm/opcodes/contract.d.ts.map +1 -0
  55. package/dest/avm/opcodes/contract.js +49 -0
  56. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  57. package/dest/avm/opcodes/control_flow.js +12 -2
  58. package/dest/avm/opcodes/environment_getters.d.ts +30 -33
  59. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  60. package/dest/avm/opcodes/environment_getters.js +34 -43
  61. package/dest/avm/opcodes/external_calls.d.ts +13 -19
  62. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  63. package/dest/avm/opcodes/external_calls.js +69 -72
  64. package/dest/avm/opcodes/hashing.d.ts +2 -1
  65. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  66. package/dest/avm/opcodes/hashing.js +37 -18
  67. package/dest/avm/opcodes/index.d.ts +1 -0
  68. package/dest/avm/opcodes/index.d.ts.map +1 -1
  69. package/dest/avm/opcodes/index.js +2 -1
  70. package/dest/avm/opcodes/instruction.d.ts +10 -15
  71. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  72. package/dest/avm/opcodes/instruction.js +12 -22
  73. package/dest/avm/opcodes/instruction_impl.d.ts +14 -0
  74. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  75. package/dest/avm/opcodes/instruction_impl.js +37 -16
  76. package/dest/avm/opcodes/memory.d.ts +4 -3
  77. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  78. package/dest/avm/opcodes/memory.js +38 -19
  79. package/dest/avm/opcodes/storage.d.ts +5 -0
  80. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  81. package/dest/avm/opcodes/storage.js +21 -7
  82. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  83. package/dest/avm/serialization/bytecode_serialization.js +7 -5
  84. package/dest/avm/serialization/instruction_serialization.d.ts +12 -11
  85. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  86. package/dest/avm/serialization/instruction_serialization.js +13 -12
  87. package/dest/client/client_execution_context.d.ts +2 -2
  88. package/dest/client/client_execution_context.d.ts.map +1 -1
  89. package/dest/client/client_execution_context.js +6 -6
  90. package/dest/client/private_execution.d.ts +1 -1
  91. package/dest/client/private_execution.d.ts.map +1 -1
  92. package/dest/client/private_execution.js +8 -4
  93. package/dest/client/unconstrained_execution.d.ts +1 -1
  94. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  95. package/dest/client/unconstrained_execution.js +2 -2
  96. package/dest/client/view_data_oracle.d.ts +2 -2
  97. package/dest/client/view_data_oracle.d.ts.map +1 -1
  98. package/dest/client/view_data_oracle.js +2 -2
  99. package/dest/public/executor.d.ts +2 -8
  100. package/dest/public/executor.d.ts.map +1 -1
  101. package/dest/public/executor.js +101 -69
  102. package/dest/public/index.d.ts +1 -1
  103. package/dest/public/index.d.ts.map +1 -1
  104. package/dest/public/public_execution_context.d.ts +6 -6
  105. package/dest/public/public_execution_context.d.ts.map +1 -1
  106. package/dest/public/public_execution_context.js +8 -12
  107. package/dest/public/transitional_adaptors.d.ts +32 -0
  108. package/dest/public/transitional_adaptors.d.ts.map +1 -0
  109. package/dest/public/transitional_adaptors.js +161 -0
  110. package/package.json +15 -9
  111. package/src/acvm/acvm.ts +1 -1
  112. package/src/acvm/oracle/index.ts +0 -1
  113. package/src/acvm/oracle/oracle.ts +3 -4
  114. package/src/avm/avm_context.ts +11 -33
  115. package/src/avm/avm_execution_environment.ts +9 -17
  116. package/src/avm/{avm_gas_cost.ts → avm_gas.ts} +75 -21
  117. package/src/avm/avm_machine_state.ts +9 -2
  118. package/src/avm/avm_memory_types.ts +134 -6
  119. package/src/avm/avm_simulator.ts +14 -12
  120. package/src/avm/fixtures/index.ts +2 -1
  121. package/src/avm/journal/journal.ts +24 -17
  122. package/src/avm/journal/trace.ts +59 -121
  123. package/src/avm/journal/trace_types.ts +39 -39
  124. package/src/avm/opcodes/accrued_substate.ts +58 -23
  125. package/src/avm/opcodes/addressing_mode.ts +8 -3
  126. package/src/avm/opcodes/arithmetic.ts +32 -22
  127. package/src/avm/opcodes/bitwise.ts +49 -83
  128. package/src/avm/opcodes/comparators.ts +28 -43
  129. package/src/avm/opcodes/context_getters.ts +32 -0
  130. package/src/avm/opcodes/contract.ts +58 -0
  131. package/src/avm/opcodes/control_flow.ts +23 -5
  132. package/src/avm/opcodes/environment_getters.ts +35 -44
  133. package/src/avm/opcodes/external_calls.ts +90 -89
  134. package/src/avm/opcodes/hashing.ts +45 -22
  135. package/src/avm/opcodes/index.ts +1 -0
  136. package/src/avm/opcodes/instruction.ts +14 -26
  137. package/src/avm/opcodes/instruction_impl.ts +45 -15
  138. package/src/avm/opcodes/memory.ts +48 -28
  139. package/src/avm/opcodes/storage.ts +26 -12
  140. package/src/avm/serialization/bytecode_serialization.ts +6 -3
  141. package/src/avm/serialization/instruction_serialization.ts +1 -0
  142. package/src/client/client_execution_context.ts +5 -5
  143. package/src/client/private_execution.ts +10 -4
  144. package/src/client/unconstrained_execution.ts +1 -1
  145. package/src/client/view_data_oracle.ts +1 -1
  146. package/src/public/executor.ts +123 -75
  147. package/src/public/index.ts +2 -2
  148. package/src/public/public_execution_context.ts +14 -19
  149. package/src/public/transitional_adaptors.ts +240 -0
  150. package/dest/acvm/oracle/debug.d.ts +0 -19
  151. package/dest/acvm/oracle/debug.d.ts.map +0 -1
  152. package/dest/acvm/oracle/debug.js +0 -95
  153. package/dest/avm/avm_gas_cost.d.ts +0 -322
  154. package/dest/avm/avm_gas_cost.d.ts.map +0 -1
  155. package/dest/avm/avm_gas_cost.js +0 -118
  156. package/dest/avm/temporary_executor_migration.d.ts +0 -25
  157. package/dest/avm/temporary_executor_migration.d.ts.map +0 -1
  158. package/dest/avm/temporary_executor_migration.js +0 -83
  159. package/src/acvm/oracle/debug.ts +0 -109
  160. package/src/avm/temporary_executor_migration.ts +0 -122
@@ -29,19 +29,24 @@ export class Poseidon2 extends Instruction {
29
29
  super();
30
30
  }
31
31
 
32
- async execute(context: AvmContext): Promise<void> {
32
+ public async execute(context: AvmContext): Promise<void> {
33
+ const memoryOperations = { reads: this.messageSize, writes: 1, indirect: this.indirect };
34
+ const memory = context.machineState.memory.track(this.type);
35
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
36
+
33
37
  // We hash a set of field elements
34
38
  const [dstOffset, messageOffset] = Addressing.fromWire(this.indirect).resolve(
35
39
  [this.dstOffset, this.messageOffset],
36
- context.machineState.memory,
40
+ memory,
37
41
  );
38
42
 
39
43
  // Memory pointer will be indirect
40
- const hashData = context.machineState.memory.getSlice(messageOffset, this.messageSize).map(word => word.toBuffer());
44
+ const hashData = memory.getSlice(messageOffset, this.messageSize).map(word => word.toBuffer());
41
45
 
42
46
  const hash = poseidonHash(hashData);
43
- context.machineState.memory.set(dstOffset, new Field(hash));
47
+ memory.set(dstOffset, new Field(hash));
44
48
 
49
+ memory.assert(memoryOperations);
45
50
  context.machineState.incrementPc();
46
51
  }
47
52
  }
@@ -69,14 +74,18 @@ export class Keccak extends Instruction {
69
74
  }
70
75
 
71
76
  // Note hash output is 32 bytes, so takes up two fields
72
- async execute(context: AvmContext): Promise<void> {
77
+ public async execute(context: AvmContext): Promise<void> {
78
+ const memoryOperations = { reads: this.messageSize, writes: 2, indirect: this.indirect };
79
+ const memory = context.machineState.memory.track(this.type);
80
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
81
+
73
82
  // We hash a set of field elements
74
83
  const [dstOffset, messageOffset] = Addressing.fromWire(this.indirect).resolve(
75
84
  [this.dstOffset, this.messageOffset],
76
- context.machineState.memory,
85
+ memory,
77
86
  );
78
87
 
79
- const hashData = context.machineState.memory.getSlice(messageOffset, this.messageSize).map(word => word.toBuffer());
88
+ const hashData = memory.getSlice(messageOffset, this.messageSize).map(word => word.toBuffer());
80
89
 
81
90
  const hash = keccak(Buffer.concat(hashData));
82
91
 
@@ -84,9 +93,10 @@ export class Keccak extends Instruction {
84
93
  const high = new Field(toBigIntBE(hash.subarray(0, 16)));
85
94
  const low = new Field(toBigIntBE(hash.subarray(16, 32)));
86
95
 
87
- context.machineState.memory.set(dstOffset, high);
88
- context.machineState.memory.set(dstOffset + 1, low);
96
+ memory.set(dstOffset, high);
97
+ memory.set(dstOffset + 1, low);
89
98
 
99
+ memory.assert(memoryOperations);
90
100
  context.machineState.incrementPc();
91
101
  }
92
102
  }
@@ -114,14 +124,18 @@ export class Sha256 extends Instruction {
114
124
  }
115
125
 
116
126
  // Note hash output is 32 bytes, so takes up two fields
117
- async execute(context: AvmContext): Promise<void> {
127
+ public async execute(context: AvmContext): Promise<void> {
128
+ const memoryOperations = { reads: this.messageSize, writes: 2, indirect: this.indirect };
129
+ const memory = context.machineState.memory.track(this.type);
130
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
131
+
118
132
  const [dstOffset, messageOffset] = Addressing.fromWire(this.indirect).resolve(
119
133
  [this.dstOffset, this.messageOffset],
120
- context.machineState.memory,
134
+ memory,
121
135
  );
122
136
 
123
137
  // We hash a set of field elements
124
- const hashData = context.machineState.memory.getSlice(messageOffset, this.messageSize).map(word => word.toBuffer());
138
+ const hashData = memory.getSlice(messageOffset, this.messageSize).map(word => word.toBuffer());
125
139
 
126
140
  const hash = sha256(Buffer.concat(hashData));
127
141
 
@@ -129,9 +143,10 @@ export class Sha256 extends Instruction {
129
143
  const high = new Field(toBigIntBE(hash.subarray(0, 16)));
130
144
  const low = new Field(toBigIntBE(hash.subarray(16, 32)));
131
145
 
132
- context.machineState.memory.set(dstOffset, high);
133
- context.machineState.memory.set(dstOffset + 1, low);
146
+ memory.set(dstOffset, high);
147
+ memory.set(dstOffset + 1, low);
134
148
 
149
+ memory.assert(memoryOperations);
135
150
  context.machineState.incrementPc();
136
151
  }
137
152
  }
@@ -147,10 +162,12 @@ export class Pedersen extends Instruction {
147
162
  OperandType.UINT32,
148
163
  OperandType.UINT32,
149
164
  OperandType.UINT32,
165
+ OperandType.UINT32,
150
166
  ];
151
167
 
152
168
  constructor(
153
169
  private indirect: number,
170
+ private genIndexOffset: number,
154
171
  private dstOffset: number,
155
172
  private messageOffset: number,
156
173
  private messageSizeOffset: number,
@@ -158,20 +175,26 @@ export class Pedersen extends Instruction {
158
175
  super();
159
176
  }
160
177
 
161
- async execute(context: AvmContext): Promise<void> {
162
- const [dstOffset, messageOffset, messageSizeOffset] = Addressing.fromWire(this.indirect).resolve(
163
- [this.dstOffset, this.messageOffset, this.messageSizeOffset],
164
- context.machineState.memory,
178
+ public async execute(context: AvmContext): Promise<void> {
179
+ const memory = context.machineState.memory.track(this.type);
180
+ const [genIndexOffset, dstOffset, messageOffset, messageSizeOffset] = Addressing.fromWire(this.indirect).resolve(
181
+ [this.genIndexOffset, this.dstOffset, this.messageOffset, this.messageSizeOffset],
182
+ memory,
165
183
  );
166
184
 
167
185
  // We hash a set of field elements
168
- const messageSize = Number(context.machineState.memory.get(messageSizeOffset).toBigInt());
169
- const hashData = context.machineState.memory.getSlice(messageOffset, messageSize);
186
+ const genIndex = Number(memory.get(genIndexOffset).toBigInt());
187
+ const messageSize = Number(memory.get(messageSizeOffset).toBigInt());
188
+ const hashData = memory.getSlice(messageOffset, messageSize);
189
+
190
+ const memoryOperations = { reads: messageSize + 2, writes: 1, indirect: this.indirect };
191
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
170
192
 
171
193
  // No domain sep for now
172
- const hash = pedersenHash(hashData);
173
- context.machineState.memory.set(dstOffset, new Field(hash));
194
+ const hash = pedersenHash(hashData, genIndex);
195
+ memory.set(dstOffset, new Field(hash));
174
196
 
197
+ memory.assert(memoryOperations);
175
198
  context.machineState.incrementPc();
176
199
  }
177
200
  }
@@ -1,6 +1,7 @@
1
1
  export * from './arithmetic.js';
2
2
  export * from './bitwise.js';
3
3
  export * from './control_flow.js';
4
+ export * from './contract.js';
4
5
  export * from './instruction.js';
5
6
  export * from './comparators.js';
6
7
  export * from './memory.js';
@@ -1,7 +1,8 @@
1
1
  import { strict as assert } from 'assert';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
- import { DynamicGasCost, type GasCost, GasCosts } from '../avm_gas_cost.js';
4
+ import { getBaseGasCost, getMemoryGasCost, sumGas } from '../avm_gas.js';
5
+ import { type MemoryOperations } from '../avm_memory_types.js';
5
6
  import { type BufferCursor } from '../serialization/buffer_cursor.js';
6
7
  import { Opcode, type OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
7
8
 
@@ -20,31 +21,7 @@ export abstract class Instruction {
20
21
  * This is the main entry point for the instruction.
21
22
  * @param context - The AvmContext in which the instruction executes.
22
23
  */
23
- public run(context: AvmContext): Promise<void> {
24
- context.machineState.consumeGas(this.gasCost());
25
- return this.execute(context);
26
- }
27
-
28
- /**
29
- * Loads default gas cost for the instruction from the GasCosts table.
30
- * Instruction sub-classes can override this if their gas cost is not fixed.
31
- */
32
- protected gasCost(): GasCost {
33
- const gasCost = GasCosts[this.opcode];
34
- if (gasCost === DynamicGasCost) {
35
- throw new Error(`Instruction ${this.type} must define its own gas cost`);
36
- }
37
- return gasCost;
38
- }
39
-
40
- /**
41
- * Execute the instruction.
42
- * Instruction sub-classes must implement this.
43
- * As an AvmContext executes its contract code, it calls this function for
44
- * each instruction until the machine state signals "halted".
45
- * @param context - The AvmContext in which the instruction executes.
46
- */
47
- protected abstract execute(context: AvmContext): Promise<void>;
24
+ public abstract execute(context: AvmContext): Promise<void>;
48
25
 
49
26
  /**
50
27
  * Generate a string representation of the instruction including
@@ -85,6 +62,17 @@ export abstract class Instruction {
85
62
  return new this(...args);
86
63
  }
87
64
 
65
+ /**
66
+ * Computes gas cost for the instruction based on its base cost and memory operations.
67
+ * @param memoryOps Memory operations performed by the instruction.
68
+ * @returns Gas cost.
69
+ */
70
+ protected gasCost(memoryOps: Partial<MemoryOperations & { indirect: number }> = {}) {
71
+ const baseGasCost = getBaseGasCost(this.opcode);
72
+ const memoryGasCost = getMemoryGasCost(memoryOps);
73
+ return sumGas(baseGasCost, memoryGasCost);
74
+ }
75
+
88
76
  /**
89
77
  * Returns the stringified type of the instruction.
90
78
  * Instruction sub-classes should have a static `type` property.
@@ -1,19 +1,34 @@
1
+ import { type AvmContext } from '../avm_context.js';
2
+ import { type MemoryValue } from '../avm_memory_types.js';
1
3
  import { OperandType } from '../serialization/instruction_serialization.js';
2
4
  import { Instruction } from './instruction.js';
3
5
 
6
+ /** Wire format that informs deserialization for instructions with two operands. */
7
+ export const TwoOperandWireFormat = [
8
+ OperandType.UINT8,
9
+ OperandType.UINT8,
10
+ OperandType.UINT8,
11
+ OperandType.UINT32,
12
+ OperandType.UINT32,
13
+ ];
14
+
15
+ /** Wire format that informs deserialization for instructions with three operands. */
16
+ export const ThreeOperandWireFormat = [
17
+ OperandType.UINT8,
18
+ OperandType.UINT8,
19
+ OperandType.UINT8,
20
+ OperandType.UINT32,
21
+ OperandType.UINT32,
22
+ OperandType.UINT32,
23
+ ];
24
+
4
25
  /**
5
26
  * Covers (de)serialization for an instruction with:
6
27
  * indirect, inTag, and two UINT32s.
7
28
  */
8
29
  export abstract class TwoOperandInstruction extends Instruction {
9
30
  // Informs (de)serialization. See Instruction.deserialize.
10
- static readonly wireFormat: OperandType[] = [
11
- OperandType.UINT8,
12
- OperandType.UINT8,
13
- OperandType.UINT8,
14
- OperandType.UINT32,
15
- OperandType.UINT32,
16
- ];
31
+ static readonly wireFormat: OperandType[] = TwoOperandWireFormat;
17
32
 
18
33
  constructor(
19
34
  protected indirect: number,
@@ -31,14 +46,7 @@ export abstract class TwoOperandInstruction extends Instruction {
31
46
  */
32
47
  export abstract class ThreeOperandInstruction extends Instruction {
33
48
  // Informs (de)serialization. See Instruction.deserialize.
34
- static readonly wireFormat: OperandType[] = [
35
- OperandType.UINT8,
36
- OperandType.UINT8,
37
- OperandType.UINT8,
38
- OperandType.UINT32,
39
- OperandType.UINT32,
40
- OperandType.UINT32,
41
- ];
49
+ static readonly wireFormat: OperandType[] = ThreeOperandWireFormat;
42
50
 
43
51
  constructor(
44
52
  protected indirect: number,
@@ -50,3 +58,25 @@ export abstract class ThreeOperandInstruction extends Instruction {
50
58
  super();
51
59
  }
52
60
  }
61
+
62
+ export abstract class GetterInstruction extends Instruction {
63
+ // Informs (de)serialization. See Instruction.deserialize.
64
+ static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT32];
65
+
66
+ constructor(protected indirect: number, protected dstOffset: number) {
67
+ super();
68
+ }
69
+
70
+ public async execute(context: AvmContext): Promise<void> {
71
+ const memoryOperations = { writes: 1, indirect: this.indirect };
72
+ const memory = context.machineState.memory.track(this.type);
73
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
74
+
75
+ memory.set(this.dstOffset, this.getValue(context));
76
+
77
+ memory.assert(memoryOperations);
78
+ context.machineState.incrementPc();
79
+ }
80
+
81
+ protected abstract getValue(env: AvmContext): MemoryValue;
82
+ }
@@ -1,6 +1,6 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { type GasCost, GasCostConstants, getGasCostMultiplierFromTypeTag, makeGasCost } from '../avm_gas_cost.js';
3
- import { Field, TaggedMemory, TypeTag } from '../avm_memory_types.js';
2
+ import { getBaseGasCost, getMemoryGasCost, mulGas, sumGas } from '../avm_gas.js';
3
+ import { Field, type MemoryOperations, TaggedMemory, TypeTag } from '../avm_memory_types.js';
4
4
  import { InstructionExecutionError } from '../errors.js';
5
5
  import { BufferCursor } from '../serialization/buffer_cursor.js';
6
6
  import { Opcode, OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
@@ -69,21 +69,22 @@ export class Set extends Instruction {
69
69
  return new this(...args);
70
70
  }
71
71
 
72
- async execute(context: AvmContext): Promise<void> {
72
+ public async execute(context: AvmContext): Promise<void> {
73
+ const memoryOperations = { writes: 1, indirect: this.indirect };
74
+ const memory = context.machineState.memory.track(this.type);
75
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
76
+
73
77
  // Per the YP, the tag cannot be a field.
74
78
  if ([TypeTag.FIELD, TypeTag.UNINITIALIZED, TypeTag.INVALID].includes(this.inTag)) {
75
79
  throw new InstructionExecutionError(`Invalid tag ${TypeTag[this.inTag]} for SET.`);
76
80
  }
77
81
 
78
82
  const res = TaggedMemory.integralFromTag(this.value, this.inTag);
79
- context.machineState.memory.set(this.dstOffset, res);
83
+ memory.set(this.dstOffset, res);
80
84
 
85
+ memory.assert(memoryOperations);
81
86
  context.machineState.incrementPc();
82
87
  }
83
-
84
- protected gasCost(): GasCost {
85
- return makeGasCost({ l2Gas: GasCostConstants.SET_COST_PER_BYTE * getGasCostMultiplierFromTypeTag(this.inTag) });
86
- }
87
88
  }
88
89
 
89
90
  export class CMov extends Instruction {
@@ -109,14 +110,19 @@ export class CMov extends Instruction {
109
110
  super();
110
111
  }
111
112
 
112
- async execute(context: AvmContext): Promise<void> {
113
- const a = context.machineState.memory.get(this.aOffset);
114
- const b = context.machineState.memory.get(this.bOffset);
115
- const cond = context.machineState.memory.get(this.condOffset);
113
+ public async execute(context: AvmContext): Promise<void> {
114
+ const memoryOperations = { reads: 3, writes: 1, indirect: this.indirect };
115
+ const memory = context.machineState.memory.track(this.type);
116
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
117
+
118
+ const a = memory.get(this.aOffset);
119
+ const b = memory.get(this.bOffset);
120
+ const cond = memory.get(this.condOffset);
116
121
 
117
122
  // TODO: reconsider toBigInt() here
118
- context.machineState.memory.set(this.dstOffset, cond.toBigInt() > 0 ? a : b);
123
+ memory.set(this.dstOffset, cond.toBigInt() > 0 ? a : b);
119
124
 
125
+ memory.assert(memoryOperations);
120
126
  context.machineState.incrementPc();
121
127
  }
122
128
  }
@@ -129,15 +135,20 @@ export class Cast extends TwoOperandInstruction {
129
135
  super(indirect, dstTag, aOffset, dstOffset);
130
136
  }
131
137
 
132
- async execute(context: AvmContext): Promise<void> {
133
- const a = context.machineState.memory.get(this.aOffset);
138
+ public async execute(context: AvmContext): Promise<void> {
139
+ const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
140
+ const memory = context.machineState.memory.track(this.type);
141
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
142
+
143
+ const a = memory.get(this.aOffset);
134
144
 
135
145
  // TODO: consider not using toBigInt()
136
146
  const casted =
137
147
  this.inTag == TypeTag.FIELD ? new Field(a.toBigInt()) : TaggedMemory.integralFromTag(a.toBigInt(), this.inTag);
138
148
 
139
- context.machineState.memory.set(this.dstOffset, casted);
149
+ memory.set(this.dstOffset, casted);
140
150
 
151
+ memory.assert(memoryOperations);
141
152
  context.machineState.incrementPc();
142
153
  }
143
154
  }
@@ -157,16 +168,18 @@ export class Mov extends Instruction {
157
168
  super();
158
169
  }
159
170
 
160
- async execute(context: AvmContext): Promise<void> {
161
- const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
162
- [this.srcOffset, this.dstOffset],
163
- context.machineState.memory,
164
- );
171
+ public async execute(context: AvmContext): Promise<void> {
172
+ const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
173
+ const memory = context.machineState.memory.track(this.type);
174
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
175
+
176
+ const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.srcOffset, this.dstOffset], memory);
165
177
 
166
- const a = context.machineState.memory.get(srcOffset);
178
+ const a = memory.get(srcOffset);
167
179
 
168
- context.machineState.memory.set(dstOffset, a);
180
+ memory.set(dstOffset, a);
169
181
 
182
+ memory.assert(memoryOperations);
170
183
  context.machineState.incrementPc();
171
184
  }
172
185
  }
@@ -187,19 +200,26 @@ export class CalldataCopy extends Instruction {
187
200
  super();
188
201
  }
189
202
 
190
- async execute(context: AvmContext): Promise<void> {
191
- const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], context.machineState.memory);
203
+ public async execute(context: AvmContext): Promise<void> {
204
+ const memoryOperations = { writes: this.copySize, indirect: this.indirect };
205
+ const memory = context.machineState.memory.track(this.type);
206
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
207
+
208
+ const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], memory);
192
209
 
193
210
  const transformedData = context.environment.calldata
194
211
  .slice(this.cdOffset, this.cdOffset + this.copySize)
195
212
  .map(f => new Field(f));
196
213
 
197
- context.machineState.memory.setSlice(dstOffset, transformedData);
214
+ memory.setSlice(dstOffset, transformedData);
198
215
 
216
+ memory.assert(memoryOperations);
199
217
  context.machineState.incrementPc();
200
218
  }
201
219
 
202
- protected gasCost(): GasCost {
203
- return makeGasCost({ l2Gas: GasCostConstants.CALLDATACOPY_COST_PER_BYTE * this.copySize });
220
+ protected gasCost(memoryOps: Partial<MemoryOperations & { indirect: number }> = {}) {
221
+ const baseGasCost = mulGas(getBaseGasCost(this.opcode), this.copySize);
222
+ const memoryGasCost = getMemoryGasCost(memoryOps);
223
+ return sumGas(baseGasCost, memoryGasCost);
204
224
  }
205
225
  }
@@ -1,7 +1,8 @@
1
1
  import { Fr } from '@aztec/foundation/fields';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
- import { Field } from '../avm_memory_types.js';
4
+ import { type Gas, getBaseGasCost, getMemoryGasCost, mulGas, sumGas } from '../avm_gas.js';
5
+ import { Field, type MemoryOperations } from '../avm_memory_types.js';
5
6
  import { InstructionExecutionError } from '../errors.js';
6
7
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
8
  import { Addressing } from './addressing_mode.js';
@@ -25,6 +26,12 @@ abstract class BaseStorageInstruction extends Instruction {
25
26
  ) {
26
27
  super();
27
28
  }
29
+
30
+ protected gasCost(memoryOps: Partial<MemoryOperations & { indirect: number }>): Gas {
31
+ const baseGasCost = mulGas(getBaseGasCost(this.opcode), this.size);
32
+ const memoryGasCost = getMemoryGasCost(memoryOps);
33
+ return sumGas(baseGasCost, memoryGasCost);
34
+ }
28
35
  }
29
36
 
30
37
  export class SStore extends BaseStorageInstruction {
@@ -35,24 +42,26 @@ export class SStore extends BaseStorageInstruction {
35
42
  super(indirect, srcOffset, srcSize, slotOffset);
36
43
  }
37
44
 
38
- async execute(context: AvmContext): Promise<void> {
45
+ public async execute(context: AvmContext): Promise<void> {
39
46
  if (context.environment.isStaticCall) {
40
47
  throw new StaticCallStorageAlterError();
41
48
  }
42
49
 
43
- const [srcOffset, slotOffset] = Addressing.fromWire(this.indirect).resolve(
44
- [this.aOffset, this.bOffset],
45
- context.machineState.memory,
46
- );
50
+ const memoryOperations = { reads: this.size + 1, indirect: this.indirect };
51
+ const memory = context.machineState.memory.track(this.type);
52
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
47
53
 
48
- const slot = context.machineState.memory.get(slotOffset).toFr();
49
- const data = context.machineState.memory.getSlice(srcOffset, this.size).map(field => field.toFr());
54
+ const [srcOffset, slotOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], memory);
55
+
56
+ const slot = memory.get(slotOffset).toFr();
57
+ const data = memory.getSlice(srcOffset, this.size).map(field => field.toFr());
50
58
 
51
59
  for (const [index, value] of Object.entries(data)) {
52
60
  const adjustedSlot = slot.add(new Fr(BigInt(index)));
53
61
  context.persistableState.writeStorage(context.environment.storageAddress, adjustedSlot, value);
54
62
  }
55
63
 
64
+ memory.assert(memoryOperations);
56
65
  context.machineState.incrementPc();
57
66
  }
58
67
  }
@@ -65,13 +74,17 @@ export class SLoad extends BaseStorageInstruction {
65
74
  super(indirect, slotOffset, size, dstOffset);
66
75
  }
67
76
 
68
- async execute(context: AvmContext): Promise<void> {
77
+ public async execute(context: AvmContext): Promise<void> {
78
+ const memoryOperations = { writes: this.size, reads: 1, indirect: this.indirect };
79
+ const memory = context.machineState.memory.track(this.type);
80
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
81
+
69
82
  const [aOffset, size, bOffset] = Addressing.fromWire(this.indirect).resolve(
70
83
  [this.aOffset, this.size, this.bOffset],
71
- context.machineState.memory,
84
+ memory,
72
85
  );
73
86
 
74
- const slot = context.machineState.memory.get(aOffset);
87
+ const slot = memory.get(aOffset);
75
88
 
76
89
  // Write each read value from storage into memory
77
90
  for (let i = 0; i < size; i++) {
@@ -80,10 +93,11 @@ export class SLoad extends BaseStorageInstruction {
80
93
  new Fr(slot.toBigInt() + BigInt(i)),
81
94
  );
82
95
 
83
- context.machineState.memory.set(bOffset + i, new Field(data));
96
+ memory.set(bOffset + i, new Field(data));
84
97
  }
85
98
 
86
99
  context.machineState.incrementPc();
100
+ memory.assert(memoryOperations);
87
101
  }
88
102
  }
89
103
 
@@ -1,3 +1,4 @@
1
+ import { DAGasLeft, L1GasLeft, L2GasLeft } from '../opcodes/context_getters.js';
1
2
  import { Keccak, Pedersen, Poseidon2, Sha256 } from '../opcodes/hashing.js';
2
3
  import {
3
4
  Add,
@@ -18,6 +19,7 @@ import {
18
19
  FeePerL1Gas,
19
20
  FeePerL2Gas,
20
21
  FieldDiv,
22
+ GetContractInstance,
21
23
  InternalCall,
22
24
  InternalReturn,
23
25
  Jump,
@@ -101,9 +103,9 @@ const INSTRUCTION_SET = () =>
101
103
 
102
104
  // Machine State
103
105
  // Machine State - Gas
104
- //[L1gasleft.opcode, L1gasleft],
105
- //[L2gasleft.opcode, L2gasleft],
106
- //[Dagasleft.opcode, Dagasleft],
106
+ [L1GasLeft.opcode, L1GasLeft],
107
+ [L2GasLeft.opcode, L2GasLeft],
108
+ [DAGasLeft.opcode, DAGasLeft],
107
109
  // Machine State - Internal Control Flow
108
110
  [Jump.opcode, Jump],
109
111
  [JumpI.opcode, JumpI],
@@ -126,6 +128,7 @@ const INSTRUCTION_SET = () =>
126
128
  // Accrued Substate
127
129
  [EmitUnencryptedLog.opcode, EmitUnencryptedLog],
128
130
  [SendL2ToL1Message.opcode, SendL2ToL1Message],
131
+ [GetContractInstance.opcode, GetContractInstance],
129
132
 
130
133
  // Control Flow - Contract Calls
131
134
  [Call.opcode, Call],
@@ -64,6 +64,7 @@ export enum Opcode {
64
64
  EMITNULLIFIER,
65
65
  L1TOL2MSGEXISTS,
66
66
  HEADERMEMBER,
67
+ GETCONTRACTINSTANCE,
67
68
  EMITUNENCRYPTEDLOG,
68
69
  SENDL2TOL1MSG,
69
70
  // External calls
@@ -235,7 +235,7 @@ export class ClientExecutionContext extends ViewDataOracle {
235
235
  offset,
236
236
  });
237
237
 
238
- this.log(
238
+ this.log.debug(
239
239
  `Returning ${notes.length} notes for ${this.callContext.storageContractAddress} at ${storageSlot}: ${notes
240
240
  .map(n => `${n.nonce.toString()}:[${n.note.items.map(i => i.toString()).join(',')}]`)
241
241
  .join(', ')}`,
@@ -316,7 +316,7 @@ export class ClientExecutionContext extends ViewDataOracle {
316
316
  public emitUnencryptedLog(log: UnencryptedL2Log) {
317
317
  this.unencryptedLogs.push(log);
318
318
  const text = log.toHumanReadable();
319
- this.log(`Emitted unencrypted log: "${text.length > 100 ? text.slice(0, 100) + '...' : text}"`);
319
+ this.log.verbose(`Emitted unencrypted log: "${text.length > 100 ? text.slice(0, 100) + '...' : text}"`);
320
320
  }
321
321
 
322
322
  #checkValidStaticCall(childExecutionResult: ExecutionResult) {
@@ -349,7 +349,7 @@ export class ClientExecutionContext extends ViewDataOracle {
349
349
  isStaticCall: boolean,
350
350
  isDelegateCall: boolean,
351
351
  ) {
352
- this.log(
352
+ this.log.debug(
353
353
  `Calling private function ${this.contractAddress}:${functionSelector} from ${this.callContext.storageContractAddress}`,
354
354
  );
355
355
 
@@ -441,7 +441,7 @@ export class ClientExecutionContext extends ViewDataOracle {
441
441
  // side-effect counter, that will leak info about how many other private
442
442
  // side-effects occurred in the TX. Ultimately the private kernel should
443
443
  // just output everything in the proper order without any counters.
444
- this.log(
444
+ this.log.verbose(
445
445
  `Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
446
446
  );
447
447
 
@@ -497,7 +497,7 @@ export class ClientExecutionContext extends ViewDataOracle {
497
497
  throw new Error(`No witness for slot ${storageSlot.toString()}`);
498
498
  }
499
499
  const value = witness.leafPreimage.value;
500
- this.log(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
500
+ this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
501
501
  values.push(value);
502
502
  }
503
503
  return values;
@@ -1,5 +1,5 @@
1
1
  import { type FunctionData, PrivateCallStackItem, PrivateCircuitPublicInputs } from '@aztec/circuits.js';
2
- import { type FunctionArtifactWithDebugMetadata, decodeReturnValues } from '@aztec/foundation/abi';
2
+ import { type AbiType, type FunctionArtifactWithDebugMetadata, decodeReturnValues } from '@aztec/foundation/abi';
3
3
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
4
4
  import { Fr } from '@aztec/foundation/fields';
5
5
  import { createDebugLogger } from '@aztec/foundation/log';
@@ -22,7 +22,7 @@ export async function executePrivateFunction(
22
22
  log = createDebugLogger('aztec:simulator:secret_execution'),
23
23
  ): Promise<ExecutionResult> {
24
24
  const functionSelector = functionData.selector;
25
- log(`Executing external function ${contractAddress}:${functionSelector}(${artifact.name})`);
25
+ log.verbose(`Executing external function ${contractAddress}:${functionSelector}(${artifact.name})`);
26
26
  const acir = artifact.bytecode;
27
27
  const initialWitness = context.getInitialWitness(artifact);
28
28
  const acvmCallback = new Oracle(context);
@@ -52,7 +52,13 @@ export async function executePrivateFunction(
52
52
  publicInputs.unencryptedLogPreimagesLength = new Fr(unencryptedLogs.getSerializedLength());
53
53
 
54
54
  const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs);
55
- const returnValues = decodeReturnValues(artifact, publicInputs.returnValues);
55
+
56
+ // Mocking the return type to be an array of 4 fields
57
+ // TODO: @LHerskind must be updated as we are progressing with the macros to get the information
58
+ const returnTypes: AbiType[] = [{ kind: 'array', length: 4, type: { kind: 'field' } }];
59
+ const mockArtifact = { ...artifact, returnTypes };
60
+ const returnValues = decodeReturnValues(mockArtifact, publicInputs.returnValues);
61
+
56
62
  const noteHashReadRequestPartialWitnesses = context.getNoteHashReadRequestPartialWitnesses(
57
63
  publicInputs.noteHashReadRequests,
58
64
  );
@@ -60,7 +66,7 @@ export async function executePrivateFunction(
60
66
  const nestedExecutions = context.getNestedExecutions();
61
67
  const enqueuedPublicFunctionCalls = context.getEnqueuedPublicFunctionCalls();
62
68
 
63
- log(`Returning from call to ${contractAddress.toString()}:${functionSelector}`);
69
+ log.debug(`Returning from call to ${contractAddress.toString()}:${functionSelector}`);
64
70
 
65
71
  return {
66
72
  acir,
@@ -23,7 +23,7 @@ export async function executeUnconstrainedFunction(
23
23
  log = createDebugLogger('aztec:simulator:unconstrained_execution'),
24
24
  ): Promise<DecodedReturn> {
25
25
  const functionSelector = functionData.selector;
26
- log(`Executing unconstrained function ${contractAddress}:${functionSelector}`);
26
+ log.verbose(`Executing unconstrained function ${contractAddress}:${functionSelector}(${artifact.name})`);
27
27
 
28
28
  const acir = artifact.bytecode;
29
29
  const initialWitness = toACVMWitness(0, args);