@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
@@ -6,64 +6,64 @@ import { type Fr } from '@aztec/foundation/fields';
6
6
  // storageAddress: Fr;
7
7
  // endLifetime: Fr;
8
8
  //};
9
- //
10
- //export type TracedPublicStorageRead = {
11
- // callPointer: Fr;
12
- // storageAddress: Fr;
13
- // exists: boolean;
14
- // slot: Fr;
15
- // value: Fr;
16
- // counter: Fr;
17
- // endLifetime: Fr;
18
- //};
19
- //
20
- //export type TracedPublicStorageWrite = {
21
- // callPointer: Fr;
22
- // storageAddress: Fr;
23
- // slot: Fr;
24
- // value: Fr;
25
- // counter: Fr;
26
- // endLifetime: Fr;
27
- //};
28
- //
9
+
10
+ export type TracedPublicStorageRead = {
11
+ // callPointer: Fr;
12
+ storageAddress: Fr;
13
+ exists: boolean;
14
+ slot: Fr;
15
+ value: Fr;
16
+ counter: Fr;
17
+ // endLifetime: Fr;
18
+ };
19
+
20
+ export type TracedPublicStorageWrite = {
21
+ // callPointer: Fr;
22
+ storageAddress: Fr;
23
+ slot: Fr;
24
+ value: Fr;
25
+ counter: Fr;
26
+ // endLifetime: Fr;
27
+ };
28
+
29
29
  export type TracedNoteHashCheck = {
30
- callPointer: Fr;
30
+ // callPointer: Fr;
31
31
  storageAddress: Fr;
32
32
  leafIndex: Fr;
33
33
  noteHash: Fr;
34
34
  exists: boolean;
35
35
  counter: Fr;
36
- endLifetime: Fr;
36
+ // endLifetime: Fr;
37
+ };
38
+
39
+ export type TracedNoteHash = {
40
+ // callPointer: Fr;
41
+ storageAddress: Fr;
42
+ noteHash: Fr;
43
+ counter: Fr;
44
+ // endLifetime: Fr;
37
45
  };
38
- //
39
- //export type TracedNoteHash = {
40
- // callPointer: Fr;
41
- // storageAddress: Fr;
42
- // noteHash: Fr;
43
- // counter: Fr;
44
- // endLifetime: Fr;
45
- //};
46
46
 
47
47
  export type TracedNullifierCheck = {
48
- callPointer: Fr;
48
+ // callPointer: Fr;
49
49
  storageAddress: Fr;
50
50
  nullifier: Fr;
51
51
  exists: boolean;
52
52
  counter: Fr;
53
- endLifetime: Fr;
53
+ // endLifetime: Fr;
54
54
  // the fields below are relevant only to the public kernel
55
55
  // and are therefore omitted from VM inputs
56
56
  isPending: boolean;
57
57
  leafIndex: Fr;
58
58
  };
59
59
 
60
- //export type TracedNullifier = {
61
- // callPointer: Fr;
62
- // storageAddress: Fr;
63
- // nullifier: Fr;
64
- // counter: Fr;
65
- // endLifetime: Fr;
66
- //};
60
+ export type TracedNullifier = {
61
+ // callPointer: Fr;
62
+ storageAddress: Fr;
63
+ nullifier: Fr;
64
+ counter: Fr;
65
+ // endLifetime: Fr;
66
+ };
67
67
 
68
68
  export type TracedL1toL2MessageCheck = {
69
69
  //callPointer: Fr;
@@ -28,18 +28,23 @@ export class NoteHashExists extends Instruction {
28
28
  super();
29
29
  }
30
30
 
31
- async execute(context: AvmContext): Promise<void> {
31
+ public async execute(context: AvmContext): Promise<void> {
32
+ const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
33
+ const memory = context.machineState.memory.track(this.type);
34
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
35
+
32
36
  // Note that this instruction accepts any type in memory, and converts to Field.
33
- const noteHash = context.machineState.memory.get(this.noteHashOffset).toFr();
34
- const leafIndex = context.machineState.memory.get(this.leafIndexOffset).toFr();
37
+ const noteHash = memory.get(this.noteHashOffset).toFr();
38
+ const leafIndex = memory.get(this.leafIndexOffset).toFr();
35
39
 
36
40
  const exists = await context.persistableState.checkNoteHashExists(
37
41
  context.environment.storageAddress,
38
42
  noteHash,
39
43
  leafIndex,
40
44
  );
41
- context.machineState.memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
45
+ memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
42
46
 
47
+ memory.assert(memoryOperations);
43
48
  context.machineState.incrementPc();
44
49
  }
45
50
  }
@@ -54,14 +59,19 @@ export class EmitNoteHash extends Instruction {
54
59
  super();
55
60
  }
56
61
 
57
- async execute(context: AvmContext): Promise<void> {
62
+ public async execute(context: AvmContext): Promise<void> {
63
+ const memoryOperations = { reads: 1, indirect: this.indirect };
64
+ const memory = context.machineState.memory.track(this.type);
65
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
66
+
58
67
  if (context.environment.isStaticCall) {
59
68
  throw new StaticCallStorageAlterError();
60
69
  }
61
70
 
62
- const noteHash = context.machineState.memory.get(this.noteHashOffset).toFr();
63
- context.persistableState.writeNoteHash(noteHash);
71
+ const noteHash = memory.get(this.noteHashOffset).toFr();
72
+ context.persistableState.writeNoteHash(context.environment.storageAddress, noteHash);
64
73
 
74
+ memory.assert(memoryOperations);
65
75
  context.machineState.incrementPc();
66
76
  }
67
77
  }
@@ -76,12 +86,17 @@ export class NullifierExists extends Instruction {
76
86
  super();
77
87
  }
78
88
 
79
- async execute(context: AvmContext): Promise<void> {
80
- const nullifier = context.machineState.memory.get(this.nullifierOffset).toFr();
89
+ public async execute(context: AvmContext): Promise<void> {
90
+ const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
91
+ const memory = context.machineState.memory.track(this.type);
92
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
93
+
94
+ const nullifier = memory.get(this.nullifierOffset).toFr();
81
95
  const exists = await context.persistableState.checkNullifierExists(context.environment.storageAddress, nullifier);
82
96
 
83
- context.machineState.memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
97
+ memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
84
98
 
99
+ memory.assert(memoryOperations);
85
100
  context.machineState.incrementPc();
86
101
  }
87
102
  }
@@ -96,12 +111,16 @@ export class EmitNullifier extends Instruction {
96
111
  super();
97
112
  }
98
113
 
99
- async execute(context: AvmContext): Promise<void> {
114
+ public async execute(context: AvmContext): Promise<void> {
100
115
  if (context.environment.isStaticCall) {
101
116
  throw new StaticCallStorageAlterError();
102
117
  }
103
118
 
104
- const nullifier = context.machineState.memory.get(this.nullifierOffset).toFr();
119
+ const memoryOperations = { reads: 1, indirect: this.indirect };
120
+ const memory = context.machineState.memory.track(this.type);
121
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
122
+
123
+ const nullifier = memory.get(this.nullifierOffset).toFr();
105
124
  try {
106
125
  await context.persistableState.writeNullifier(context.environment.storageAddress, nullifier);
107
126
  } catch (e) {
@@ -115,6 +134,7 @@ export class EmitNullifier extends Instruction {
115
134
  }
116
135
  }
117
136
 
137
+ memory.assert(memoryOperations);
118
138
  context.machineState.incrementPc();
119
139
  }
120
140
  }
@@ -140,12 +160,17 @@ export class L1ToL2MessageExists extends Instruction {
140
160
  super();
141
161
  }
142
162
 
143
- async execute(context: AvmContext): Promise<void> {
144
- const msgHash = context.machineState.memory.get(this.msgHashOffset).toFr();
145
- const msgLeafIndex = context.machineState.memory.get(this.msgLeafIndexOffset).toFr();
163
+ public async execute(context: AvmContext): Promise<void> {
164
+ const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
165
+ const memory = context.machineState.memory.track(this.type);
166
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
167
+
168
+ const msgHash = memory.get(this.msgHashOffset).toFr();
169
+ const msgLeafIndex = memory.get(this.msgLeafIndexOffset).toFr();
146
170
  const exists = await context.persistableState.checkL1ToL2MessageExists(msgHash, msgLeafIndex);
147
- context.machineState.memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
171
+ memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
148
172
 
173
+ memory.assert(memoryOperations);
149
174
  context.machineState.incrementPc();
150
175
  }
151
176
  }
@@ -171,21 +196,26 @@ export class EmitUnencryptedLog extends Instruction {
171
196
  super();
172
197
  }
173
198
 
174
- async execute(context: AvmContext): Promise<void> {
199
+ public async execute(context: AvmContext): Promise<void> {
175
200
  if (context.environment.isStaticCall) {
176
201
  throw new StaticCallStorageAlterError();
177
202
  }
178
203
 
204
+ const memoryOperations = { reads: 1 + this.logSize, indirect: this.indirect };
205
+ const memory = context.machineState.memory.track(this.type);
206
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
207
+
179
208
  const [eventSelectorOffset, logOffset] = Addressing.fromWire(this.indirect).resolve(
180
209
  [this.eventSelectorOffset, this.logOffset],
181
- context.machineState.memory,
210
+ memory,
182
211
  );
183
212
 
184
213
  const contractAddress = context.environment.address;
185
- const event = context.machineState.memory.get(eventSelectorOffset).toFr();
186
- const log = context.machineState.memory.getSlice(logOffset, this.logSize).map(f => f.toFr());
214
+ const event = memory.get(eventSelectorOffset).toFr();
215
+ const log = memory.getSlice(logOffset, this.logSize).map(f => f.toFr());
187
216
  context.persistableState.writeLog(contractAddress, event, log);
188
217
 
218
+ memory.assert(memoryOperations);
189
219
  context.machineState.incrementPc();
190
220
  }
191
221
  }
@@ -200,15 +230,20 @@ export class SendL2ToL1Message extends Instruction {
200
230
  super();
201
231
  }
202
232
 
203
- async execute(context: AvmContext): Promise<void> {
233
+ public async execute(context: AvmContext): Promise<void> {
204
234
  if (context.environment.isStaticCall) {
205
235
  throw new StaticCallStorageAlterError();
206
236
  }
207
237
 
208
- const recipient = context.machineState.memory.get(this.recipientOffset).toFr();
209
- const content = context.machineState.memory.get(this.contentOffset).toFr();
238
+ const memoryOperations = { reads: 2, indirect: this.indirect };
239
+ const memory = context.machineState.memory.track(this.type);
240
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
241
+
242
+ const recipient = memory.get(this.recipientOffset).toFr();
243
+ const content = memory.get(this.contentOffset).toFr();
210
244
  context.persistableState.writeL1Message(recipient, content);
211
245
 
246
+ memory.assert(memoryOperations);
212
247
  context.machineState.incrementPc();
213
248
  }
214
249
  }
@@ -1,6 +1,6 @@
1
1
  import { strict as assert } from 'assert';
2
2
 
3
- import { type TaggedMemory } from '../avm_memory_types.js';
3
+ import { type TaggedMemoryInterface } from '../avm_memory_types.js';
4
4
 
5
5
  export enum AddressingMode {
6
6
  DIRECT,
@@ -12,7 +12,7 @@ export enum AddressingMode {
12
12
  export class Addressing {
13
13
  public constructor(
14
14
  /** The addressing mode for each operand. The length of this array is the number of operands of the instruction. */
15
- public readonly modePerOperand: AddressingMode[],
15
+ private readonly modePerOperand: AddressingMode[],
16
16
  ) {
17
17
  assert(modePerOperand.length <= 8, 'At most 8 operands are supported');
18
18
  }
@@ -39,13 +39,18 @@ export class Addressing {
39
39
  return wire;
40
40
  }
41
41
 
42
+ /** Returns how many operands use the given addressing mode. */
43
+ public count(mode: AddressingMode): number {
44
+ return this.modePerOperand.filter(m => m === mode).length;
45
+ }
46
+
42
47
  /**
43
48
  * Resolves the offsets using the addressing mode.
44
49
  * @param offsets The offsets to resolve.
45
50
  * @param mem The memory to use for resolution.
46
51
  * @returns The resolved offsets. The length of the returned array is the same as the length of the input array.
47
52
  */
48
- public resolve(offsets: number[], mem: TaggedMemory): number[] {
53
+ public resolve(offsets: number[], mem: TaggedMemoryInterface): number[] {
49
54
  assert(offsets.length <= this.modePerOperand.length);
50
55
  const resolved = new Array(offsets.length);
51
56
  for (const [i, offset] of offsets.entries()) {
@@ -1,33 +1,32 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { type GasCost, GasCostConstants, getGasCostMultiplierFromTypeTag, makeGasCost } from '../avm_gas_cost.js';
3
- import { type Field, type MemoryValue, TypeTag } from '../avm_memory_types.js';
2
+ import { getBaseGasCost, getGasCostForTypeTag, getMemoryGasCost, sumGas } from '../avm_gas.js';
3
+ import { type Field, type MemoryOperations, type MemoryValue, TypeTag } from '../avm_memory_types.js';
4
4
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
5
- import { Addressing, AddressingMode } from './addressing_mode.js';
6
5
  import { Instruction } from './instruction.js';
7
6
  import { ThreeOperandInstruction } from './instruction_impl.js';
8
7
 
9
8
  export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInstruction {
10
- async execute(context: AvmContext): Promise<void> {
11
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
9
+ public async execute(context: AvmContext): Promise<void> {
10
+ const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
11
+ const memory = context.machineState.memory.track(this.type);
12
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
12
13
 
13
- const a = context.machineState.memory.get(this.aOffset);
14
- const b = context.machineState.memory.get(this.bOffset);
14
+ memory.checkTags(this.inTag, this.aOffset, this.bOffset);
15
+
16
+ const a = memory.get(this.aOffset);
17
+ const b = memory.get(this.bOffset);
15
18
 
16
19
  const dest = this.compute(a, b);
17
- context.machineState.memory.set(this.dstOffset, dest);
20
+ memory.set(this.dstOffset, dest);
18
21
 
22
+ memory.assert(memoryOperations);
19
23
  context.machineState.incrementPc();
20
24
  }
21
25
 
22
- protected gasCost(): GasCost {
23
- const indirectCount = Addressing.fromWire(this.indirect).modePerOperand.filter(
24
- mode => mode === AddressingMode.INDIRECT,
25
- ).length;
26
-
27
- const l2Gas =
28
- indirectCount * GasCostConstants.ARITHMETIC_COST_PER_INDIRECT_ACCESS +
29
- getGasCostMultiplierFromTypeTag(this.inTag) * GasCostConstants.ARITHMETIC_COST_PER_BYTE;
30
- return makeGasCost({ l2Gas });
26
+ protected gasCost(memoryOps: Partial<MemoryOperations & { indirect: number }>) {
27
+ const baseGasCost = getGasCostForTypeTag(this.inTag, getBaseGasCost(this.opcode));
28
+ const memoryGasCost = getMemoryGasCost(memoryOps);
29
+ return sumGas(baseGasCost, memoryGasCost);
31
30
  }
32
31
 
33
32
  protected abstract compute(a: MemoryValue, b: MemoryValue): MemoryValue;
@@ -86,15 +85,26 @@ export class FieldDiv extends Instruction {
86
85
  super();
87
86
  }
88
87
 
89
- async execute(context: AvmContext): Promise<void> {
90
- context.machineState.memory.checkTags(TypeTag.FIELD, this.aOffset, this.bOffset);
88
+ public async execute(context: AvmContext): Promise<void> {
89
+ const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
90
+ const memory = context.machineState.memory.track(this.type);
91
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
92
+
93
+ memory.checkTags(TypeTag.FIELD, this.aOffset, this.bOffset);
91
94
 
92
- const a = context.machineState.memory.getAs<Field>(this.aOffset);
93
- const b = context.machineState.memory.getAs<Field>(this.bOffset);
95
+ const a = memory.getAs<Field>(this.aOffset);
96
+ const b = memory.getAs<Field>(this.bOffset);
94
97
 
95
98
  const dest = a.fdiv(b);
96
- context.machineState.memory.set(this.dstOffset, dest);
99
+ memory.set(this.dstOffset, dest);
97
100
 
101
+ memory.assert(memoryOperations);
98
102
  context.machineState.incrementPc();
99
103
  }
104
+
105
+ protected gasCost(memoryOps: Partial<MemoryOperations & { indirect: number }>) {
106
+ const baseGasCost = getGasCostForTypeTag(TypeTag.FIELD, getBaseGasCost(this.opcode));
107
+ const memoryGasCost = getMemoryGasCost(memoryOps);
108
+ return sumGas(baseGasCost, memoryGasCost);
109
+ }
100
110
  }
@@ -3,66 +3,69 @@ import { type IntegralValue } from '../avm_memory_types.js';
3
3
  import { Opcode } from '../serialization/instruction_serialization.js';
4
4
  import { ThreeOperandInstruction, TwoOperandInstruction } from './instruction_impl.js';
5
5
 
6
- export class And extends ThreeOperandInstruction {
7
- static readonly type: string = 'AND';
8
- static readonly opcode = Opcode.AND;
9
-
10
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
11
- super(indirect, inTag, aOffset, bOffset, dstOffset);
12
- }
6
+ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
7
+ public async execute(context: AvmContext): Promise<void> {
8
+ const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
9
+ const memory = context.machineState.memory.track(this.type);
10
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
13
11
 
14
- async execute(context: AvmContext): Promise<void> {
15
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
12
+ memory.checkTags(this.inTag, this.aOffset, this.bOffset);
16
13
 
17
- const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
18
- const b = context.machineState.memory.getAs<IntegralValue>(this.bOffset);
14
+ const a = memory.getAs<IntegralValue>(this.aOffset);
15
+ const b = memory.getAs<IntegralValue>(this.bOffset);
19
16
 
20
- const res = a.and(b);
21
- context.machineState.memory.set(this.dstOffset, res);
17
+ const res = this.compute(a, b);
18
+ memory.set(this.dstOffset, res);
22
19
 
20
+ memory.assert(memoryOperations);
23
21
  context.machineState.incrementPc();
24
22
  }
23
+
24
+ protected abstract compute(a: IntegralValue, b: IntegralValue): IntegralValue;
25
25
  }
26
26
 
27
- export class Or extends ThreeOperandInstruction {
28
- static readonly type: string = 'OR';
29
- static readonly opcode = Opcode.OR;
27
+ export class And extends ThreeOperandBitwiseInstruction {
28
+ static readonly type: string = 'AND';
29
+ static readonly opcode = Opcode.AND;
30
30
 
31
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
32
- super(indirect, inTag, aOffset, bOffset, dstOffset);
31
+ protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
32
+ return a.and(b);
33
33
  }
34
+ }
34
35
 
35
- async execute(context: AvmContext): Promise<void> {
36
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
37
-
38
- const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
39
- const b = context.machineState.memory.getAs<IntegralValue>(this.bOffset);
40
-
41
- const res = a.or(b);
42
- context.machineState.memory.set(this.dstOffset, res);
36
+ export class Or extends ThreeOperandBitwiseInstruction {
37
+ static readonly type: string = 'OR';
38
+ static readonly opcode = Opcode.OR;
43
39
 
44
- context.machineState.incrementPc();
40
+ protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
41
+ return a.or(b);
45
42
  }
46
43
  }
47
44
 
48
- export class Xor extends ThreeOperandInstruction {
45
+ export class Xor extends ThreeOperandBitwiseInstruction {
49
46
  static readonly type: string = 'XOR';
50
47
  static readonly opcode = Opcode.XOR;
51
48
 
52
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
53
- super(indirect, inTag, aOffset, bOffset, dstOffset);
49
+ protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
50
+ return a.xor(b);
54
51
  }
52
+ }
55
53
 
56
- async execute(context: AvmContext): Promise<void> {
57
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
54
+ export class Shl extends ThreeOperandBitwiseInstruction {
55
+ static readonly type: string = 'SHL';
56
+ static readonly opcode = Opcode.SHL;
58
57
 
59
- const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
60
- const b = context.machineState.memory.getAs<IntegralValue>(this.bOffset);
58
+ protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
59
+ return a.shl(b);
60
+ }
61
+ }
61
62
 
62
- const res = a.xor(b);
63
- context.machineState.memory.set(this.dstOffset, res);
63
+ export class Shr extends ThreeOperandBitwiseInstruction {
64
+ static readonly type: string = 'SHR';
65
+ static readonly opcode = Opcode.SHR;
64
66
 
65
- context.machineState.incrementPc();
67
+ protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
68
+ return a.shr(b);
66
69
  }
67
70
  }
68
71
 
@@ -74,56 +77,19 @@ export class Not extends TwoOperandInstruction {
74
77
  super(indirect, inTag, aOffset, dstOffset);
75
78
  }
76
79
 
77
- async execute(context: AvmContext): Promise<void> {
78
- context.machineState.memory.checkTags(this.inTag, this.aOffset);
79
-
80
- const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
81
-
82
- const res = a.not();
83
- context.machineState.memory.set(this.dstOffset, res);
84
-
85
- context.machineState.incrementPc();
86
- }
87
- }
88
-
89
- export class Shl extends ThreeOperandInstruction {
90
- static readonly type: string = 'SHL';
91
- static readonly opcode = Opcode.SHL;
92
-
93
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
94
- super(indirect, inTag, aOffset, bOffset, dstOffset);
95
- }
96
-
97
- async execute(context: AvmContext): Promise<void> {
98
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
80
+ public async execute(context: AvmContext): Promise<void> {
81
+ const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
82
+ const memory = context.machineState.memory.track(this.type);
83
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
99
84
 
100
- const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
101
- const b = context.machineState.memory.getAs<IntegralValue>(this.bOffset);
85
+ memory.checkTags(this.inTag, this.aOffset);
102
86
 
103
- const res = a.shl(b);
104
- context.machineState.memory.set(this.dstOffset, res);
87
+ const a = memory.getAs<IntegralValue>(this.aOffset);
105
88
 
106
- context.machineState.incrementPc();
107
- }
108
- }
109
-
110
- export class Shr extends ThreeOperandInstruction {
111
- static readonly type: string = 'SHR';
112
- static readonly opcode = Opcode.SHR;
113
-
114
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
115
- super(indirect, inTag, aOffset, bOffset, dstOffset);
116
- }
117
-
118
- async execute(context: AvmContext): Promise<void> {
119
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
120
-
121
- const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
122
- const b = context.machineState.memory.getAs<IntegralValue>(this.bOffset);
123
-
124
- const res = a.shr(b);
125
- context.machineState.memory.set(this.dstOffset, res);
89
+ const res = a.not();
90
+ memory.set(this.dstOffset, res);
126
91
 
92
+ memory.assert(memoryOperations);
127
93
  context.machineState.incrementPc();
128
94
  }
129
95
  }
@@ -1,67 +1,52 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { Uint8 } from '../avm_memory_types.js';
2
+ import { type MemoryValue, Uint8 } from '../avm_memory_types.js';
3
3
  import { Opcode } from '../serialization/instruction_serialization.js';
4
4
  import { ThreeOperandInstruction } from './instruction_impl.js';
5
5
 
6
- export class Eq extends ThreeOperandInstruction {
7
- static readonly type: string = 'EQ';
8
- static readonly opcode = Opcode.EQ;
9
-
10
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
11
- super(indirect, inTag, aOffset, bOffset, dstOffset);
12
- }
6
+ abstract class ComparatorInstruction extends ThreeOperandInstruction {
7
+ public async execute(context: AvmContext): Promise<void> {
8
+ const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
9
+ const memory = context.machineState.memory.track(this.type);
10
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
13
11
 
14
- async execute(context: AvmContext): Promise<void> {
15
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
12
+ memory.checkTags(this.inTag, this.aOffset, this.bOffset);
16
13
 
17
- const a = context.machineState.memory.get(this.aOffset);
18
- const b = context.machineState.memory.get(this.bOffset);
14
+ const a = memory.get(this.aOffset);
15
+ const b = memory.get(this.bOffset);
19
16
 
20
- const dest = new Uint8(a.equals(b) ? 1 : 0);
21
- context.machineState.memory.set(this.dstOffset, dest);
17
+ const dest = new Uint8(this.compare(a, b) ? 1 : 0);
18
+ memory.set(this.dstOffset, dest);
22
19
 
20
+ memory.assert(memoryOperations);
23
21
  context.machineState.incrementPc();
24
22
  }
23
+
24
+ protected abstract compare(a: MemoryValue, b: MemoryValue): boolean;
25
25
  }
26
26
 
27
- export class Lt extends ThreeOperandInstruction {
28
- static readonly type: string = 'LT';
29
- static readonly opcode = Opcode.LT;
27
+ export class Eq extends ComparatorInstruction {
28
+ static readonly type: string = 'EQ';
29
+ static readonly opcode = Opcode.EQ;
30
30
 
31
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
32
- super(indirect, inTag, aOffset, bOffset, dstOffset);
31
+ protected compare(a: MemoryValue, b: MemoryValue): boolean {
32
+ return a.equals(b);
33
33
  }
34
+ }
34
35
 
35
- async execute(context: AvmContext): Promise<void> {
36
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
37
-
38
- const a = context.machineState.memory.get(this.aOffset);
39
- const b = context.machineState.memory.get(this.bOffset);
40
-
41
- const dest = new Uint8(a.lt(b) ? 1 : 0);
42
- context.machineState.memory.set(this.dstOffset, dest);
36
+ export class Lt extends ComparatorInstruction {
37
+ static readonly type: string = 'LT';
38
+ static readonly opcode = Opcode.LT;
43
39
 
44
- context.machineState.incrementPc();
40
+ protected compare(a: MemoryValue, b: MemoryValue): boolean {
41
+ return a.lt(b);
45
42
  }
46
43
  }
47
44
 
48
- export class Lte extends ThreeOperandInstruction {
45
+ export class Lte extends ComparatorInstruction {
49
46
  static readonly type: string = 'LTE';
50
47
  static readonly opcode = Opcode.LTE;
51
48
 
52
- constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
53
- super(indirect, inTag, aOffset, bOffset, dstOffset);
54
- }
55
-
56
- async execute(context: AvmContext): Promise<void> {
57
- context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);
58
-
59
- const a = context.machineState.memory.get(this.aOffset);
60
- const b = context.machineState.memory.get(this.bOffset);
61
-
62
- const dest = new Uint8(a.lt(b) || a.equals(b) ? 1 : 0);
63
- context.machineState.memory.set(this.dstOffset, dest);
64
-
65
- context.machineState.incrementPc();
49
+ protected compare(a: MemoryValue, b: MemoryValue): boolean {
50
+ return a.lt(b) || a.equals(b);
66
51
  }
67
52
  }