@aztec/simulator 0.32.0 → 0.33.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 (227) hide show
  1. package/README.md +5 -3
  2. package/dest/acvm/acvm.d.ts +5 -5
  3. package/dest/acvm/acvm.d.ts.map +1 -1
  4. package/dest/acvm/acvm_types.d.ts +1 -1
  5. package/dest/acvm/acvm_types.d.ts.map +1 -1
  6. package/dest/acvm/deserialize.d.ts +1 -1
  7. package/dest/acvm/deserialize.d.ts.map +1 -1
  8. package/dest/acvm/oracle/index.d.ts +1 -2
  9. package/dest/acvm/oracle/index.d.ts.map +1 -1
  10. package/dest/acvm/oracle/index.js +1 -2
  11. package/dest/acvm/oracle/oracle.d.ts +2 -2
  12. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  13. package/dest/acvm/oracle/oracle.js +2 -3
  14. package/dest/acvm/oracle/typed_oracle.d.ts +6 -6
  15. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  16. package/dest/acvm/serialize.d.ts +4 -4
  17. package/dest/acvm/serialize.d.ts.map +1 -1
  18. package/dest/acvm/serialize.js +1 -1
  19. package/dest/avm/avm_context.d.ts +8 -18
  20. package/dest/avm/avm_context.d.ts.map +1 -1
  21. package/dest/avm/avm_context.js +10 -22
  22. package/dest/avm/avm_execution_environment.d.ts +4 -4
  23. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  24. package/dest/avm/avm_execution_environment.js +1 -1
  25. package/dest/avm/avm_gas.d.ts +71 -0
  26. package/dest/avm/avm_gas.d.ts.map +1 -0
  27. package/dest/avm/avm_gas.js +161 -0
  28. package/dest/avm/avm_machine_state.d.ts +5 -3
  29. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  30. package/dest/avm/avm_machine_state.js +8 -2
  31. package/dest/avm/avm_memory_types.d.ts +54 -2
  32. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  33. package/dest/avm/avm_memory_types.js +95 -2
  34. package/dest/avm/avm_message_call_result.d.ts +1 -1
  35. package/dest/avm/avm_message_call_result.d.ts.map +1 -1
  36. package/dest/avm/avm_simulator.d.ts.map +1 -1
  37. package/dest/avm/avm_simulator.js +10 -8
  38. package/dest/avm/errors.d.ts +1 -1
  39. package/dest/avm/errors.d.ts.map +1 -1
  40. package/dest/avm/fixtures/index.d.ts +1 -1
  41. package/dest/avm/fixtures/index.d.ts.map +1 -1
  42. package/dest/avm/fixtures/index.js +2 -2
  43. package/dest/avm/journal/host_storage.d.ts +1 -1
  44. package/dest/avm/journal/host_storage.d.ts.map +1 -1
  45. package/dest/avm/journal/journal.d.ts +2 -2
  46. package/dest/avm/journal/journal.d.ts.map +1 -1
  47. package/dest/avm/journal/trace.d.ts +1 -1
  48. package/dest/avm/journal/trace.d.ts.map +1 -1
  49. package/dest/avm/journal/trace_types.d.ts +1 -1
  50. package/dest/avm/journal/trace_types.d.ts.map +1 -1
  51. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  52. package/dest/avm/opcodes/accrued_substate.js +44 -16
  53. package/dest/avm/opcodes/addressing_mode.d.ts +5 -3
  54. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
  55. package/dest/avm/opcodes/addressing_mode.js +5 -1
  56. package/dest/avm/opcodes/arithmetic.d.ts +7 -3
  57. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  58. package/dest/avm/opcodes/arithmetic.js +27 -16
  59. package/dest/avm/opcodes/bitwise.d.ts +21 -20
  60. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  61. package/dest/avm/opcodes/bitwise.js +43 -65
  62. package/dest/avm/opcodes/comparators.d.ts +12 -9
  63. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  64. package/dest/avm/opcodes/comparators.js +22 -32
  65. package/dest/avm/opcodes/context_getters.d.ts +20 -0
  66. package/dest/avm/opcodes/context_getters.d.ts.map +1 -0
  67. package/dest/avm/opcodes/context_getters.js +26 -0
  68. package/dest/avm/opcodes/contract.d.ts +14 -0
  69. package/dest/avm/opcodes/contract.d.ts.map +1 -0
  70. package/dest/avm/opcodes/contract.js +49 -0
  71. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  72. package/dest/avm/opcodes/control_flow.js +12 -2
  73. package/dest/avm/opcodes/environment_getters.d.ts +31 -34
  74. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  75. package/dest/avm/opcodes/environment_getters.js +34 -43
  76. package/dest/avm/opcodes/external_calls.d.ts +13 -19
  77. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  78. package/dest/avm/opcodes/external_calls.js +50 -68
  79. package/dest/avm/opcodes/hashing.d.ts +3 -2
  80. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  81. package/dest/avm/opcodes/hashing.js +37 -18
  82. package/dest/avm/opcodes/index.d.ts +1 -0
  83. package/dest/avm/opcodes/index.d.ts.map +1 -1
  84. package/dest/avm/opcodes/index.js +2 -1
  85. package/dest/avm/opcodes/instruction.d.ts +12 -17
  86. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  87. package/dest/avm/opcodes/instruction.js +12 -22
  88. package/dest/avm/opcodes/instruction_impl.d.ts +14 -0
  89. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  90. package/dest/avm/opcodes/instruction_impl.js +37 -16
  91. package/dest/avm/opcodes/memory.d.ts +4 -3
  92. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  93. package/dest/avm/opcodes/memory.js +38 -19
  94. package/dest/avm/opcodes/storage.d.ts +5 -0
  95. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  96. package/dest/avm/opcodes/storage.js +21 -7
  97. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  98. package/dest/avm/serialization/bytecode_serialization.js +7 -5
  99. package/dest/avm/serialization/instruction_serialization.d.ts +12 -11
  100. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  101. package/dest/avm/serialization/instruction_serialization.js +13 -12
  102. package/dest/avm/temporary_executor_migration.d.ts +6 -4
  103. package/dest/avm/temporary_executor_migration.d.ts.map +1 -1
  104. package/dest/avm/temporary_executor_migration.js +14 -3
  105. package/dest/client/client_execution_context.d.ts +11 -11
  106. package/dest/client/client_execution_context.d.ts.map +1 -1
  107. package/dest/client/client_execution_context.js +1 -1
  108. package/dest/client/db_oracle.d.ts +9 -9
  109. package/dest/client/db_oracle.d.ts.map +1 -1
  110. package/dest/client/db_oracle.js +1 -1
  111. package/dest/client/execution_note_cache.d.ts +2 -2
  112. package/dest/client/execution_note_cache.d.ts.map +1 -1
  113. package/dest/client/execution_result.d.ts +5 -5
  114. package/dest/client/execution_result.d.ts.map +1 -1
  115. package/dest/client/execution_result.js +1 -1
  116. package/dest/client/pick_notes.d.ts +1 -1
  117. package/dest/client/pick_notes.d.ts.map +1 -1
  118. package/dest/client/pick_notes.js +1 -1
  119. package/dest/client/private_execution.d.ts +5 -5
  120. package/dest/client/private_execution.d.ts.map +1 -1
  121. package/dest/client/private_execution.js +6 -2
  122. package/dest/client/simulator.d.ts +6 -6
  123. package/dest/client/simulator.d.ts.map +1 -1
  124. package/dest/client/simulator.js +1 -1
  125. package/dest/client/unconstrained_execution.d.ts +5 -5
  126. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  127. package/dest/client/unconstrained_execution.js +1 -1
  128. package/dest/client/view_data_oracle.d.ts +6 -6
  129. package/dest/client/view_data_oracle.d.ts.map +1 -1
  130. package/dest/client/view_data_oracle.js +1 -1
  131. package/dest/common/errors.d.ts +1 -1
  132. package/dest/common/errors.d.ts.map +1 -1
  133. package/dest/common/errors.js +1 -1
  134. package/dest/public/db.d.ts +6 -6
  135. package/dest/public/db.d.ts.map +1 -1
  136. package/dest/public/execution.d.ts +2 -2
  137. package/dest/public/execution.d.ts.map +1 -1
  138. package/dest/public/executor.d.ts +13 -5
  139. package/dest/public/executor.d.ts.map +1 -1
  140. package/dest/public/executor.js +59 -20
  141. package/dest/public/index.d.ts +1 -1
  142. package/dest/public/index.d.ts.map +1 -1
  143. package/dest/public/public_execution_context.d.ts +7 -7
  144. package/dest/public/public_execution_context.d.ts.map +1 -1
  145. package/dest/public/public_execution_context.js +3 -3
  146. package/dest/public/state_actions.d.ts +2 -2
  147. package/dest/public/state_actions.d.ts.map +1 -1
  148. package/dest/simulator/acvm_native.d.ts +3 -3
  149. package/dest/simulator/acvm_native.d.ts.map +1 -1
  150. package/dest/simulator/acvm_wasm.d.ts +3 -3
  151. package/dest/simulator/acvm_wasm.d.ts.map +1 -1
  152. package/dest/simulator/acvm_wasm.js +2 -2
  153. package/dest/simulator/simulation_provider.d.ts +2 -2
  154. package/dest/simulator/simulation_provider.d.ts.map +1 -1
  155. package/dest/test/utils.d.ts +1 -1
  156. package/dest/test/utils.d.ts.map +1 -1
  157. package/dest/test/utils.js +1 -1
  158. package/dest/utils.d.ts +1 -1
  159. package/dest/utils.d.ts.map +1 -1
  160. package/package.json +15 -9
  161. package/src/acvm/acvm.ts +8 -8
  162. package/src/acvm/acvm_types.ts +1 -1
  163. package/src/acvm/deserialize.ts +1 -1
  164. package/src/acvm/oracle/index.ts +1 -2
  165. package/src/acvm/oracle/oracle.ts +3 -4
  166. package/src/acvm/oracle/typed_oracle.ts +18 -18
  167. package/src/acvm/serialize.ts +4 -4
  168. package/src/avm/avm_context.ts +15 -37
  169. package/src/avm/avm_execution_environment.ts +4 -4
  170. package/src/avm/{avm_gas_cost.ts → avm_gas.ts} +75 -21
  171. package/src/avm/avm_machine_state.ts +10 -3
  172. package/src/avm/avm_memory_types.ts +131 -3
  173. package/src/avm/avm_message_call_result.ts +1 -1
  174. package/src/avm/avm_simulator.ts +10 -8
  175. package/src/avm/errors.ts +1 -1
  176. package/src/avm/fixtures/index.ts +6 -1
  177. package/src/avm/journal/host_storage.ts +1 -1
  178. package/src/avm/journal/journal.ts +2 -2
  179. package/src/avm/journal/trace.ts +1 -1
  180. package/src/avm/journal/trace_types.ts +1 -1
  181. package/src/avm/opcodes/accrued_substate.ts +57 -22
  182. package/src/avm/opcodes/addressing_mode.ts +8 -3
  183. package/src/avm/opcodes/arithmetic.ts +32 -22
  184. package/src/avm/opcodes/bitwise.ts +50 -84
  185. package/src/avm/opcodes/comparators.ts +28 -43
  186. package/src/avm/opcodes/context_getters.ts +32 -0
  187. package/src/avm/opcodes/contract.ts +58 -0
  188. package/src/avm/opcodes/control_flow.ts +24 -6
  189. package/src/avm/opcodes/environment_getters.ts +36 -45
  190. package/src/avm/opcodes/external_calls.ts +65 -84
  191. package/src/avm/opcodes/hashing.ts +46 -23
  192. package/src/avm/opcodes/index.ts +1 -0
  193. package/src/avm/opcodes/instruction.ts +16 -28
  194. package/src/avm/opcodes/instruction_impl.ts +45 -15
  195. package/src/avm/opcodes/memory.ts +48 -28
  196. package/src/avm/opcodes/storage.ts +26 -12
  197. package/src/avm/serialization/bytecode_serialization.ts +6 -3
  198. package/src/avm/serialization/instruction_serialization.ts +1 -0
  199. package/src/avm/temporary_executor_migration.ts +20 -6
  200. package/src/client/client_execution_context.ts +15 -15
  201. package/src/client/db_oracle.ts +16 -10
  202. package/src/client/execution_note_cache.ts +2 -2
  203. package/src/client/execution_result.ts +9 -5
  204. package/src/client/pick_notes.ts +1 -1
  205. package/src/client/private_execution.ts +12 -6
  206. package/src/client/simulator.ts +8 -8
  207. package/src/client/unconstrained_execution.ts +5 -5
  208. package/src/client/view_data_oracle.ts +11 -11
  209. package/src/common/errors.ts +1 -1
  210. package/src/public/db.ts +6 -6
  211. package/src/public/execution.ts +10 -10
  212. package/src/public/executor.ts +78 -25
  213. package/src/public/index.ts +2 -2
  214. package/src/public/public_execution_context.ts +17 -7
  215. package/src/public/state_actions.ts +2 -2
  216. package/src/simulator/acvm_native.ts +3 -3
  217. package/src/simulator/acvm_wasm.ts +8 -4
  218. package/src/simulator/simulation_provider.ts +2 -2
  219. package/src/test/utils.ts +1 -1
  220. package/src/utils.ts +1 -1
  221. package/dest/acvm/oracle/debug.d.ts +0 -19
  222. package/dest/acvm/oracle/debug.d.ts.map +0 -1
  223. package/dest/acvm/oracle/debug.js +0 -95
  224. package/dest/avm/avm_gas_cost.d.ts +0 -322
  225. package/dest/avm/avm_gas_cost.d.ts.map +0 -1
  226. package/dest/avm/avm_gas_cost.js +0 -118
  227. package/src/acvm/oracle/debug.ts +0 -109
@@ -1,137 +1,128 @@
1
- import { Fr } from '@aztec/circuits.js';
1
+ import { type Fr } from '@aztec/circuits.js';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
4
  import type { AvmExecutionEnvironment } from '../avm_execution_environment.js';
5
- import { Field } from '../avm_memory_types.js';
6
- import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
- import { Instruction } from './instruction.js';
5
+ import { Field, type MemoryValue } from '../avm_memory_types.js';
6
+ import { Opcode } from '../serialization/instruction_serialization.js';
7
+ import { GetterInstruction } from './instruction_impl.js';
8
8
 
9
- abstract class GetterInstruction extends Instruction {
10
- // Informs (de)serialization. See Instruction.deserialize.
11
- static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT32];
12
-
13
- constructor(protected indirect: number, protected dstOffset: number) {
14
- super();
15
- }
16
-
17
- async execute(context: AvmContext): Promise<void> {
18
- const res = new Field(this.getIt(context.environment));
19
- context.machineState.memory.set(this.dstOffset, res);
20
- context.machineState.incrementPc();
9
+ abstract class EnvironmentGetterInstruction extends GetterInstruction {
10
+ protected getValue(context: AvmContext): MemoryValue {
11
+ return new Field(this.getEnvironmentValue(context.environment));
21
12
  }
22
13
 
23
- protected abstract getIt(env: AvmExecutionEnvironment): Fr | number | bigint;
14
+ protected abstract getEnvironmentValue(env: AvmExecutionEnvironment): Fr | number | bigint;
24
15
  }
25
16
 
26
- export class Address extends GetterInstruction {
17
+ export class Address extends EnvironmentGetterInstruction {
27
18
  static type: string = 'ADDRESS';
28
19
  static readonly opcode: Opcode = Opcode.ADDRESS;
29
20
 
30
- protected getIt(env: AvmExecutionEnvironment) {
21
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
31
22
  return env.address;
32
23
  }
33
24
  }
34
25
 
35
- export class StorageAddress extends GetterInstruction {
26
+ export class StorageAddress extends EnvironmentGetterInstruction {
36
27
  static type: string = 'STORAGEADDRESS';
37
28
  static readonly opcode: Opcode = Opcode.STORAGEADDRESS;
38
29
 
39
- protected getIt(env: AvmExecutionEnvironment) {
30
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
40
31
  return env.storageAddress;
41
32
  }
42
33
  }
43
34
 
44
- export class Sender extends GetterInstruction {
35
+ export class Sender extends EnvironmentGetterInstruction {
45
36
  static type: string = 'SENDER';
46
37
  static readonly opcode: Opcode = Opcode.SENDER;
47
38
 
48
- protected getIt(env: AvmExecutionEnvironment) {
39
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
49
40
  return env.sender;
50
41
  }
51
42
  }
52
43
 
53
- export class Origin extends GetterInstruction {
44
+ export class Origin extends EnvironmentGetterInstruction {
54
45
  static type: string = 'ORIGIN';
55
46
  static readonly opcode: Opcode = Opcode.ORIGIN;
56
47
 
57
- protected getIt(env: AvmExecutionEnvironment) {
48
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
58
49
  return env.origin;
59
50
  }
60
51
  }
61
52
 
62
- export class FeePerL1Gas extends GetterInstruction {
53
+ export class FeePerL1Gas extends EnvironmentGetterInstruction {
63
54
  static type: string = 'FEEPERL1GAS';
64
55
  static readonly opcode: Opcode = Opcode.FEEPERL1GAS;
65
56
 
66
- protected getIt(env: AvmExecutionEnvironment) {
57
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
67
58
  return env.feePerL1Gas;
68
59
  }
69
60
  }
70
61
 
71
- export class FeePerL2Gas extends GetterInstruction {
62
+ export class FeePerL2Gas extends EnvironmentGetterInstruction {
72
63
  static type: string = 'FEEPERL2GAS';
73
64
  static readonly opcode: Opcode = Opcode.FEEPERL2GAS;
74
65
 
75
- protected getIt(env: AvmExecutionEnvironment) {
66
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
76
67
  return env.feePerL2Gas;
77
68
  }
78
69
  }
79
70
 
80
- export class FeePerDAGas extends GetterInstruction {
71
+ export class FeePerDAGas extends EnvironmentGetterInstruction {
81
72
  static type: string = 'FEEPERDAGAS';
82
73
  static readonly opcode: Opcode = Opcode.FEEPERDAGAS;
83
74
 
84
- protected getIt(env: AvmExecutionEnvironment) {
75
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
85
76
  return env.feePerDaGas;
86
77
  }
87
78
  }
88
79
 
89
- export class Portal extends GetterInstruction {
80
+ export class Portal extends EnvironmentGetterInstruction {
90
81
  static type: string = 'PORTAL';
91
82
  static readonly opcode: Opcode = Opcode.PORTAL;
92
83
 
93
- protected getIt(env: AvmExecutionEnvironment) {
84
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
94
85
  return env.portal.toField();
95
86
  }
96
87
  }
97
88
 
98
- export class ChainId extends GetterInstruction {
89
+ export class ChainId extends EnvironmentGetterInstruction {
99
90
  static type: string = 'CHAINID';
100
91
  static readonly opcode: Opcode = Opcode.CHAINID;
101
92
 
102
- protected getIt(env: AvmExecutionEnvironment) {
93
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
103
94
  return env.globals.chainId;
104
95
  }
105
96
  }
106
97
 
107
- export class Version extends GetterInstruction {
98
+ export class Version extends EnvironmentGetterInstruction {
108
99
  static type: string = 'VERSION';
109
100
  static readonly opcode: Opcode = Opcode.VERSION;
110
101
 
111
- protected getIt(env: AvmExecutionEnvironment) {
102
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
112
103
  return env.globals.version;
113
104
  }
114
105
  }
115
106
 
116
- export class BlockNumber extends GetterInstruction {
107
+ export class BlockNumber extends EnvironmentGetterInstruction {
117
108
  static type: string = 'BLOCKNUMBER';
118
109
  static readonly opcode: Opcode = Opcode.BLOCKNUMBER;
119
110
 
120
- protected getIt(env: AvmExecutionEnvironment) {
111
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
121
112
  return env.globals.blockNumber;
122
113
  }
123
114
  }
124
115
 
125
- export class Timestamp extends GetterInstruction {
116
+ export class Timestamp extends EnvironmentGetterInstruction {
126
117
  static type: string = 'TIMESTAMP';
127
118
  static readonly opcode: Opcode = Opcode.TIMESTAMP;
128
119
 
129
- protected getIt(env: AvmExecutionEnvironment) {
120
+ protected getEnvironmentValue(env: AvmExecutionEnvironment) {
130
121
  return env.globals.timestamp;
131
122
  }
132
123
  }
133
124
 
134
- // export class Coinbase extends GetterInstruction {
125
+ // export class Coinbase extends EnvironmentGetterInstruction {
135
126
  // static type: string = 'COINBASE';
136
127
  // static numberOfOperands = 1;
137
128
 
@@ -149,7 +140,7 @@ export class Timestamp extends GetterInstruction {
149
140
  // }
150
141
 
151
142
  // // TODO: are these even needed within the block? (both block gas limit variables - why does the execution env care?)
152
- // export class BlockL1GasLimit extends GetterInstruction {
143
+ // export class BlockL1GasLimit extends EnvironmentGetterInstruction {
153
144
  // static type: string = 'BLOCKL1GASLIMIT';
154
145
  // static numberOfOperands = 1;
155
146
 
@@ -166,7 +157,7 @@ export class Timestamp extends GetterInstruction {
166
157
  // }
167
158
  // }
168
159
 
169
- // export class BlockL2GasLimit extends GetterInstruction {
160
+ // export class BlockL2GasLimit extends EnvironmentGetterInstruction {
170
161
  // static type: string = 'BLOCKL2GASLIMIT';
171
162
  // static numberOfOperands = 1;
172
163
 
@@ -183,7 +174,7 @@ export class Timestamp extends GetterInstruction {
183
174
  // }
184
175
  // }
185
176
 
186
- // export class BlockDAGasLimit extends GetterInstruction {
177
+ // export class BlockDAGasLimit extends EnvironmentGetterInstruction {
187
178
  // static type: string = 'BLOCKDAGASLIMIT';
188
179
  // static numberOfOperands = 1;
189
180
 
@@ -1,15 +1,15 @@
1
1
  import { FunctionSelector } from '@aztec/circuits.js';
2
+ import { padArrayEnd } from '@aztec/foundation/collection';
2
3
 
3
4
  import type { AvmContext } from '../avm_context.js';
5
+ import { gasLeftToGas, sumGas } from '../avm_gas.js';
4
6
  import { Field, Uint8 } from '../avm_memory_types.js';
5
7
  import { AvmSimulator } from '../avm_simulator.js';
6
8
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
9
  import { Addressing } from './addressing_mode.js';
8
10
  import { Instruction } from './instruction.js';
9
11
 
10
- export class Call extends Instruction {
11
- static type: string = 'CALL';
12
- static readonly opcode: Opcode = Opcode.CALL;
12
+ abstract class ExternalCall extends Instruction {
13
13
  // Informs (de)serialization. See Instruction.deserialize.
14
14
  static readonly wireFormat: OperandType[] = [
15
15
  OperandType.UINT8,
@@ -27,7 +27,7 @@ export class Call extends Instruction {
27
27
 
28
28
  constructor(
29
29
  private indirect: number,
30
- private _gasOffset: number /* Unused due to no formal gas implementation at this moment */,
30
+ private gasOffset: number /* Unused due to no formal gas implementation at this moment */,
31
31
  private addrOffset: number,
32
32
  private argsOffset: number,
33
33
  private argsSize: number,
@@ -42,110 +42,81 @@ export class Call extends Instruction {
42
42
  super();
43
43
  }
44
44
 
45
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3992): there is no concept of remaining / available gas at this moment
46
- async execute(context: AvmContext): Promise<void> {
47
- const [_gasOffset, addrOffset, argsOffset, retOffset, successOffset] = Addressing.fromWire(this.indirect).resolve(
48
- [this._gasOffset, this.addrOffset, this.argsOffset, this.retOffset, this.successOffset],
49
- context.machineState.memory,
45
+ public async execute(context: AvmContext) {
46
+ const memory = context.machineState.memory.track(this.type);
47
+ const [gasOffset, addrOffset, argsOffset, retOffset, successOffset] = Addressing.fromWire(this.indirect).resolve(
48
+ [this.gasOffset, this.addrOffset, this.argsOffset, this.retOffset, this.successOffset],
49
+ memory,
50
50
  );
51
51
 
52
- const callAddress = context.machineState.memory.getAs<Field>(addrOffset);
53
- const calldata = context.machineState.memory.getSlice(argsOffset, this.argsSize).map(f => f.toFr());
54
- const functionSelector = context.machineState.memory.getAs<Field>(this.temporaryFunctionSelectorOffset).toFr();
52
+ const callAddress = memory.getAs<Field>(addrOffset);
53
+ const calldata = memory.getSlice(argsOffset, this.argsSize).map(f => f.toFr());
54
+ const l1Gas = memory.get(gasOffset).toNumber();
55
+ const l2Gas = memory.getAs<Field>(gasOffset + 1).toNumber();
56
+ const daGas = memory.getAs<Field>(gasOffset + 2).toNumber();
57
+ const functionSelector = memory.getAs<Field>(this.temporaryFunctionSelectorOffset).toFr();
58
+
59
+ const allocatedGas = { l1Gas, l2Gas, daGas };
60
+ const memoryOperations = { reads: this.argsSize + 5, writes: 1 + this.retSize, indirect: this.indirect };
61
+ const totalGas = sumGas(this.gasCost(memoryOperations), allocatedGas);
62
+ context.machineState.consumeGas(totalGas);
55
63
 
56
64
  const nestedContext = context.createNestedContractCallContext(
57
65
  callAddress.toFr(),
58
66
  calldata,
67
+ allocatedGas,
68
+ this.type,
59
69
  FunctionSelector.fromField(functionSelector),
60
70
  );
61
71
 
62
72
  const nestedCallResults = await new AvmSimulator(nestedContext).execute();
63
73
  const success = !nestedCallResults.reverted;
64
74
 
65
- // We only take as much data as was specified in the return size -> TODO: should we be reverting here
75
+ // We only take as much data as was specified in the return size and pad with zeroes if the return data is smaller
76
+ // than the specified size in order to prevent that memory to be left with garbage
66
77
  const returnData = nestedCallResults.output.slice(0, this.retSize);
67
- const convertedReturnData = returnData.map(f => new Field(f));
78
+ const convertedReturnData = padArrayEnd(
79
+ returnData.map(f => new Field(f)),
80
+ new Field(0),
81
+ this.retSize,
82
+ );
68
83
 
69
84
  // Write our return data into memory
70
- context.machineState.memory.set(successOffset, new Uint8(success ? 1 : 0));
71
- context.machineState.memory.setSlice(retOffset, convertedReturnData);
85
+ memory.set(successOffset, new Uint8(success ? 1 : 0));
86
+ memory.setSlice(retOffset, convertedReturnData);
87
+
88
+ // Refund unused gas
89
+ context.machineState.refundGas(gasLeftToGas(nestedContext.machineState));
72
90
 
91
+ // TODO: Should we merge the changes from a nested call in the case of a STATIC call?
73
92
  if (success) {
74
93
  context.persistableState.acceptNestedCallState(nestedContext.persistableState);
75
94
  } else {
76
95
  context.persistableState.rejectNestedCallState(nestedContext.persistableState);
77
96
  }
78
97
 
98
+ memory.assert(memoryOperations);
79
99
  context.machineState.incrementPc();
80
100
  }
101
+
102
+ public abstract get type(): 'CALL' | 'STATICCALL';
81
103
  }
82
104
 
83
- export class StaticCall extends Instruction {
84
- static type: string = 'STATICCALL';
85
- static readonly opcode: Opcode = Opcode.STATICCALL;
86
- // Informs (de)serialization. See Instruction.deserialize.
87
- static readonly wireFormat: OperandType[] = [
88
- OperandType.UINT8,
89
- OperandType.UINT8,
90
- OperandType.UINT32,
91
- OperandType.UINT32,
92
- OperandType.UINT32,
93
- OperandType.UINT32,
94
- OperandType.UINT32,
95
- OperandType.UINT32,
96
- OperandType.UINT32,
97
- /* temporary function selector */
98
- OperandType.UINT32,
99
- ];
105
+ export class Call extends ExternalCall {
106
+ static type = 'CALL' as const;
107
+ static readonly opcode: Opcode = Opcode.CALL;
100
108
 
101
- constructor(
102
- private indirect: number,
103
- private _gasOffset: number /* Unused due to no formal gas implementation at this moment */,
104
- private addrOffset: number,
105
- private argsOffset: number,
106
- private argsSize: number,
107
- private retOffset: number,
108
- private retSize: number,
109
- private successOffset: number,
110
- private temporaryFunctionSelectorOffset: number,
111
- ) {
112
- super();
109
+ public get type() {
110
+ return Call.type;
113
111
  }
112
+ }
114
113
 
115
- async execute(context: AvmContext): Promise<void> {
116
- const [_gasOffset, addrOffset, argsOffset, retOffset, successOffset] = Addressing.fromWire(this.indirect).resolve(
117
- [this._gasOffset, this.addrOffset, this.argsOffset, this.retOffset, this.successOffset],
118
- context.machineState.memory,
119
- );
120
-
121
- const callAddress = context.machineState.memory.get(addrOffset);
122
- const calldata = context.machineState.memory.getSlice(argsOffset, this.argsSize).map(f => f.toFr());
123
- const functionSelector = context.machineState.memory.getAs<Field>(this.temporaryFunctionSelectorOffset).toFr();
124
-
125
- const nestedContext = context.createNestedContractStaticCallContext(
126
- callAddress.toFr(),
127
- calldata,
128
- FunctionSelector.fromField(functionSelector),
129
- );
130
-
131
- const nestedCallResults = await new AvmSimulator(nestedContext).execute();
132
- const success = !nestedCallResults.reverted;
133
-
134
- // We only take as much data as was specified in the return size -> TODO: should we be reverting here
135
- const returnData = nestedCallResults.output.slice(0, this.retSize);
136
- const convertedReturnData = returnData.map(f => new Field(f));
137
-
138
- // Write our return data into memory
139
- context.machineState.memory.set(successOffset, new Uint8(success ? 1 : 0));
140
- context.machineState.memory.setSlice(retOffset, convertedReturnData);
141
-
142
- if (success) {
143
- context.persistableState.acceptNestedCallState(nestedContext.persistableState);
144
- } else {
145
- context.persistableState.rejectNestedCallState(nestedContext.persistableState);
146
- }
114
+ export class StaticCall extends ExternalCall {
115
+ static type = 'STATICCALL' as const;
116
+ static readonly opcode: Opcode = Opcode.STATICCALL;
147
117
 
148
- context.machineState.incrementPc();
118
+ public get type() {
119
+ return StaticCall.type;
149
120
  }
150
121
  }
151
122
 
@@ -164,12 +135,17 @@ export class Return extends Instruction {
164
135
  super();
165
136
  }
166
137
 
167
- async execute(context: AvmContext): Promise<void> {
168
- const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], context.machineState.memory);
138
+ public async execute(context: AvmContext): Promise<void> {
139
+ const memoryOperations = { reads: this.copySize, indirect: this.indirect };
140
+ const memory = context.machineState.memory.track(this.type);
141
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
142
+
143
+ const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], memory);
169
144
 
170
- const output = context.machineState.memory.getSlice(returnOffset, this.copySize).map(word => word.toFr());
145
+ const output = memory.getSlice(returnOffset, this.copySize).map(word => word.toFr());
171
146
 
172
147
  context.machineState.return(output);
148
+ memory.assert(memoryOperations);
173
149
  }
174
150
  }
175
151
 
@@ -188,11 +164,16 @@ export class Revert extends Instruction {
188
164
  super();
189
165
  }
190
166
 
191
- async execute(context: AvmContext): Promise<void> {
192
- const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], context.machineState.memory);
167
+ public async execute(context: AvmContext): Promise<void> {
168
+ const memoryOperations = { reads: this.retSize, indirect: this.indirect };
169
+ const memory = context.machineState.memory.track(this.type);
170
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
171
+
172
+ const [returnOffset] = Addressing.fromWire(this.indirect).resolve([this.returnOffset], memory);
193
173
 
194
- const output = context.machineState.memory.getSlice(returnOffset, this.retSize).map(word => word.toFr());
174
+ const output = memory.getSlice(returnOffset, this.retSize).map(word => word.toFr());
195
175
 
196
176
  context.machineState.revert(output);
177
+ memory.assert(memoryOperations);
197
178
  }
198
179
  }
@@ -1,7 +1,7 @@
1
1
  import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
2
2
  import { keccak, pedersenHash, poseidonHash, sha256 } from '@aztec/foundation/crypto';
3
3
 
4
- import { AvmContext } from '../avm_context.js';
4
+ import { type AvmContext } from '../avm_context.js';
5
5
  import { Field } from '../avm_memory_types.js';
6
6
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
7
  import { Addressing } from './addressing_mode.js';
@@ -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,9 +1,10 @@
1
1
  import { strict as assert } from 'assert';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
- import { DynamicGasCost, GasCost, GasCosts } from '../avm_gas_cost.js';
5
- import { BufferCursor } from '../serialization/buffer_cursor.js';
6
- import { Opcode, OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
4
+ import { getBaseGasCost, getMemoryGasCost, sumGas } from '../avm_gas.js';
5
+ import { type MemoryOperations } from '../avm_memory_types.js';
6
+ import { type BufferCursor } from '../serialization/buffer_cursor.js';
7
+ import { Opcode, type OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
7
8
 
8
9
  type InstructionConstructor = {
9
10
  new (...args: any[]): Instruction;
@@ -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.