@aztec/simulator 0.41.0 → 0.43.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 (243) hide show
  1. package/dest/acvm/acvm.d.ts +2 -2
  2. package/dest/acvm/acvm.d.ts.map +1 -1
  3. package/dest/acvm/acvm.js +3 -3
  4. package/dest/acvm/oracle/oracle.d.ts +7 -4
  5. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/oracle.js +32 -12
  7. package/dest/acvm/oracle/typed_oracle.d.ts +6 -3
  8. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  9. package/dest/acvm/oracle/typed_oracle.js +15 -6
  10. package/dest/acvm/serialize.js +2 -2
  11. package/dest/avm/avm_gas.d.ts +1 -5
  12. package/dest/avm/avm_gas.d.ts.map +1 -1
  13. package/dest/avm/avm_gas.js +69 -73
  14. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  15. package/dest/avm/avm_memory_types.js +2 -4
  16. package/dest/avm/avm_simulator.d.ts +5 -0
  17. package/dest/avm/avm_simulator.d.ts.map +1 -1
  18. package/dest/avm/avm_simulator.js +8 -1
  19. package/dest/avm/fixtures/index.d.ts +6 -0
  20. package/dest/avm/fixtures/index.d.ts.map +1 -1
  21. package/dest/avm/fixtures/index.js +18 -1
  22. package/dest/avm/index.d.ts +2 -0
  23. package/dest/avm/index.d.ts.map +1 -0
  24. package/dest/avm/index.js +2 -0
  25. package/dest/avm/journal/host_storage.d.ts +1 -1
  26. package/dest/avm/journal/host_storage.d.ts.map +1 -1
  27. package/dest/avm/journal/journal.d.ts +5 -3
  28. package/dest/avm/journal/journal.d.ts.map +1 -1
  29. package/dest/avm/journal/journal.js +23 -14
  30. package/dest/avm/journal/trace.d.ts +3 -1
  31. package/dest/avm/journal/trace.d.ts.map +1 -1
  32. package/dest/avm/journal/trace.js +8 -1
  33. package/dest/avm/journal/trace_types.d.ts +5 -0
  34. package/dest/avm/journal/trace_types.d.ts.map +1 -1
  35. package/dest/avm/journal/trace_types.js +1 -5
  36. package/dest/avm/opcodes/accrued_substate.d.ts +2 -2
  37. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  38. package/dest/avm/opcodes/accrued_substate.js +36 -21
  39. package/dest/avm/opcodes/arithmetic.d.ts +1 -7
  40. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  41. package/dest/avm/opcodes/arithmetic.js +12 -20
  42. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  43. package/dest/avm/opcodes/bitwise.js +11 -8
  44. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  45. package/dest/avm/opcodes/comparators.js +7 -5
  46. package/dest/avm/opcodes/contract.d.ts.map +1 -1
  47. package/dest/avm/opcodes/contract.js +20 -24
  48. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  49. package/dest/avm/opcodes/control_flow.js +4 -2
  50. package/dest/avm/opcodes/conversion.js +2 -2
  51. package/dest/avm/opcodes/ec_add.d.ts +19 -0
  52. package/dest/avm/opcodes/ec_add.d.ts.map +1 -0
  53. package/dest/avm/opcodes/ec_add.js +78 -0
  54. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  55. package/dest/avm/opcodes/external_calls.js +11 -5
  56. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  57. package/dest/avm/opcodes/hashing.js +10 -2
  58. package/dest/avm/opcodes/instruction.d.ts +1 -1
  59. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  60. package/dest/avm/opcodes/instruction.js +6 -4
  61. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  62. package/dest/avm/opcodes/instruction_impl.js +4 -2
  63. package/dest/avm/opcodes/memory.d.ts +1 -5
  64. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  65. package/dest/avm/opcodes/memory.js +14 -18
  66. package/dest/avm/opcodes/multi_scalar_mul.d.ts +16 -0
  67. package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -0
  68. package/dest/avm/opcodes/multi_scalar_mul.js +95 -0
  69. package/dest/avm/opcodes/storage.d.ts +1 -6
  70. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  71. package/dest/avm/opcodes/storage.js +11 -14
  72. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  73. package/dest/avm/serialization/bytecode_serialization.js +6 -2
  74. package/dest/avm/serialization/instruction_serialization.d.ts +3 -1
  75. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  76. package/dest/avm/serialization/instruction_serialization.js +4 -2
  77. package/dest/client/client_execution_context.d.ts +24 -20
  78. package/dest/client/client_execution_context.d.ts.map +1 -1
  79. package/dest/client/client_execution_context.js +52 -55
  80. package/dest/client/db_oracle.d.ts +7 -1
  81. package/dest/client/db_oracle.d.ts.map +1 -1
  82. package/dest/client/execution_note_cache.d.ts +0 -17
  83. package/dest/client/execution_note_cache.d.ts.map +1 -1
  84. package/dest/client/execution_note_cache.js +1 -24
  85. package/dest/client/execution_result.d.ts +8 -4
  86. package/dest/client/execution_result.d.ts.map +1 -1
  87. package/dest/client/execution_result.js +16 -6
  88. package/dest/client/private_execution.d.ts +2 -3
  89. package/dest/client/private_execution.d.ts.map +1 -1
  90. package/dest/client/private_execution.js +20 -9
  91. package/dest/client/simulator.d.ts +2 -17
  92. package/dest/client/simulator.d.ts.map +1 -1
  93. package/dest/client/simulator.js +24 -33
  94. package/dest/client/unconstrained_execution.d.ts +2 -3
  95. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  96. package/dest/client/unconstrained_execution.js +5 -7
  97. package/dest/client/view_data_oracle.d.ts +2 -0
  98. package/dest/client/view_data_oracle.d.ts.map +1 -1
  99. package/dest/client/view_data_oracle.js +7 -1
  100. package/dest/index.d.ts +3 -1
  101. package/dest/index.d.ts.map +1 -1
  102. package/dest/index.js +4 -2
  103. package/dest/mocks/fixtures.d.ts +14 -10
  104. package/dest/mocks/fixtures.d.ts.map +1 -1
  105. package/dest/mocks/fixtures.js +22 -16
  106. package/dest/{simulator → providers}/acvm_native.d.ts.map +1 -1
  107. package/dest/{simulator → providers}/acvm_native.js +13 -14
  108. package/dest/providers/acvm_wasm.d.ts.map +1 -0
  109. package/dest/providers/acvm_wasm.js +15 -0
  110. package/dest/providers/index.d.ts.map +1 -0
  111. package/dest/{simulator → providers}/index.js +1 -1
  112. package/dest/{simulator → providers}/simulation_provider.d.ts.map +1 -1
  113. package/dest/{simulator → providers}/simulation_provider.js +1 -1
  114. package/dest/public/abstract_phase_manager.d.ts +53 -53
  115. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  116. package/dest/public/abstract_phase_manager.js +146 -153
  117. package/dest/public/app_logic_phase_manager.d.ts +8 -9
  118. package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
  119. package/dest/public/app_logic_phase_manager.js +15 -15
  120. package/dest/public/{db.d.ts → db_interfaces.d.ts} +4 -3
  121. package/dest/public/db_interfaces.d.ts.map +1 -0
  122. package/dest/public/db_interfaces.js +2 -0
  123. package/dest/public/execution.d.ts +16 -23
  124. package/dest/public/execution.d.ts.map +1 -1
  125. package/dest/public/execution.js +1 -51
  126. package/dest/public/executor.d.ts +4 -31
  127. package/dest/public/executor.d.ts.map +1 -1
  128. package/dest/public/executor.js +40 -283
  129. package/dest/public/fee_payment.d.ts +11 -0
  130. package/dest/public/fee_payment.d.ts.map +1 -0
  131. package/dest/public/fee_payment.js +24 -0
  132. package/dest/public/hints_builder.d.ts +2 -1
  133. package/dest/public/hints_builder.d.ts.map +1 -1
  134. package/dest/public/hints_builder.js +6 -2
  135. package/dest/public/index.d.ts +8 -6
  136. package/dest/public/index.d.ts.map +1 -1
  137. package/dest/public/index.js +9 -7
  138. package/dest/public/phase_manager_factory.d.ts +4 -4
  139. package/dest/public/phase_manager_factory.d.ts.map +1 -1
  140. package/dest/public/phase_manager_factory.js +5 -5
  141. package/dest/public/{public_executor.d.ts → public_db_sources.d.ts} +6 -3
  142. package/dest/public/public_db_sources.d.ts.map +1 -0
  143. package/dest/public/public_db_sources.js +244 -0
  144. package/dest/public/public_kernel.js +14 -14
  145. package/dest/public/public_processor.d.ts +6 -4
  146. package/dest/public/public_processor.d.ts.map +1 -1
  147. package/dest/public/public_processor.js +48 -30
  148. package/dest/public/setup_phase_manager.d.ts +8 -10
  149. package/dest/public/setup_phase_manager.d.ts.map +1 -1
  150. package/dest/public/setup_phase_manager.js +12 -21
  151. package/dest/public/tail_phase_manager.d.ts +7 -13
  152. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  153. package/dest/public/tail_phase_manager.js +17 -37
  154. package/dest/public/teardown_phase_manager.d.ts +8 -10
  155. package/dest/public/teardown_phase_manager.d.ts.map +1 -1
  156. package/dest/public/teardown_phase_manager.js +16 -22
  157. package/dest/public/transitional_adaptors.d.ts +2 -2
  158. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  159. package/dest/public/transitional_adaptors.js +14 -6
  160. package/package.json +12 -9
  161. package/src/acvm/acvm.ts +0 -3
  162. package/src/acvm/oracle/oracle.ts +68 -16
  163. package/src/acvm/oracle/typed_oracle.ts +31 -6
  164. package/src/acvm/serialize.ts +1 -1
  165. package/src/avm/avm_gas.ts +68 -73
  166. package/src/avm/avm_memory_types.ts +1 -3
  167. package/src/avm/avm_simulator.ts +9 -0
  168. package/src/avm/fixtures/index.ts +24 -0
  169. package/src/avm/index.ts +1 -0
  170. package/src/avm/journal/host_storage.ts +1 -1
  171. package/src/avm/journal/journal.ts +32 -22
  172. package/src/avm/journal/trace.ts +9 -0
  173. package/src/avm/journal/trace_types.ts +4 -0
  174. package/src/avm/opcodes/accrued_substate.ts +53 -20
  175. package/src/avm/opcodes/arithmetic.ts +18 -22
  176. package/src/avm/opcodes/bitwise.ts +13 -8
  177. package/src/avm/opcodes/comparators.ts +9 -4
  178. package/src/avm/opcodes/contract.ts +22 -26
  179. package/src/avm/opcodes/control_flow.ts +3 -1
  180. package/src/avm/opcodes/conversion.ts +1 -1
  181. package/src/avm/opcodes/ec_add.ts +92 -0
  182. package/src/avm/opcodes/external_calls.ts +11 -3
  183. package/src/avm/opcodes/hashing.ts +11 -1
  184. package/src/avm/opcodes/instruction.ts +5 -3
  185. package/src/avm/opcodes/instruction_impl.ts +4 -1
  186. package/src/avm/opcodes/memory.ts +19 -19
  187. package/src/avm/opcodes/multi_scalar_mul.ts +114 -0
  188. package/src/avm/opcodes/storage.ts +10 -17
  189. package/src/avm/serialization/bytecode_serialization.ts +5 -1
  190. package/src/avm/serialization/instruction_serialization.ts +2 -0
  191. package/src/client/client_execution_context.ts +76 -60
  192. package/src/client/db_oracle.ts +8 -1
  193. package/src/client/execution_note_cache.ts +0 -28
  194. package/src/client/execution_result.ts +21 -7
  195. package/src/client/private_execution.ts +36 -21
  196. package/src/client/simulator.ts +25 -35
  197. package/src/client/unconstrained_execution.ts +9 -12
  198. package/src/client/view_data_oracle.ts +8 -0
  199. package/src/index.ts +3 -1
  200. package/src/mocks/fixtures.ts +30 -32
  201. package/src/{simulator → providers}/acvm_native.ts +21 -19
  202. package/src/{simulator → providers}/acvm_wasm.ts +2 -16
  203. package/src/public/abstract_phase_manager.ts +209 -258
  204. package/src/public/app_logic_phase_manager.ts +24 -40
  205. package/src/public/{db.ts → db_interfaces.ts} +4 -2
  206. package/src/public/execution.ts +15 -77
  207. package/src/public/executor.ts +61 -399
  208. package/src/public/fee_payment.ts +26 -0
  209. package/src/public/hints_builder.ts +6 -0
  210. package/src/public/index.ts +8 -12
  211. package/src/public/phase_manager_factory.ts +7 -7
  212. package/src/public/{public_executor.ts → public_db_sources.ts} +65 -9
  213. package/src/public/public_kernel.ts +24 -24
  214. package/src/public/public_processor.ts +81 -40
  215. package/src/public/setup_phase_manager.ts +21 -46
  216. package/src/public/tail_phase_manager.ts +19 -67
  217. package/src/public/teardown_phase_manager.ts +23 -42
  218. package/src/public/transitional_adaptors.ts +41 -5
  219. package/dest/public/db.d.ts.map +0 -1
  220. package/dest/public/db.js +0 -2
  221. package/dest/public/public_execution_context.d.ts +0 -121
  222. package/dest/public/public_execution_context.d.ts.map +0 -1
  223. package/dest/public/public_execution_context.js +0 -214
  224. package/dest/public/public_executor.d.ts.map +0 -1
  225. package/dest/public/public_executor.js +0 -197
  226. package/dest/public/state_actions.d.ts +0 -39
  227. package/dest/public/state_actions.d.ts.map +0 -1
  228. package/dest/public/state_actions.js +0 -80
  229. package/dest/public/utils.d.ts +0 -8
  230. package/dest/public/utils.d.ts.map +0 -1
  231. package/dest/public/utils.js +0 -31
  232. package/dest/simulator/acvm_wasm.d.ts.map +0 -1
  233. package/dest/simulator/acvm_wasm.js +0 -22
  234. package/dest/simulator/index.d.ts.map +0 -1
  235. package/src/public/public_execution_context.ts +0 -289
  236. package/src/public/state_actions.ts +0 -102
  237. package/src/public/utils.ts +0 -33
  238. /package/dest/{simulator → providers}/acvm_native.d.ts +0 -0
  239. /package/dest/{simulator → providers}/acvm_wasm.d.ts +0 -0
  240. /package/dest/{simulator → providers}/index.d.ts +0 -0
  241. /package/dest/{simulator → providers}/simulation_provider.d.ts +0 -0
  242. /package/src/{simulator → providers}/index.ts +0 -0
  243. /package/src/{simulator → providers}/simulation_provider.ts +0 -0
@@ -1,6 +1,5 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { getBaseGasCost, getMemoryGasCost, sumGas } from '../avm_gas.js';
3
- import { Field, type MemoryOperations, TaggedMemory, TypeTag } from '../avm_memory_types.js';
2
+ import { Field, TaggedMemory, TypeTag } from '../avm_memory_types.js';
4
3
  import { InstructionExecutionError } from '../errors.js';
5
4
  import { BufferCursor } from '../serialization/buffer_cursor.js';
6
5
  import { Opcode, OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
@@ -115,12 +114,17 @@ export class CMov extends Instruction {
115
114
  const memory = context.machineState.memory.track(this.type);
116
115
  context.machineState.consumeGas(this.gasCost(memoryOperations));
117
116
 
118
- const a = memory.get(this.aOffset);
119
- const b = memory.get(this.bOffset);
120
- const cond = memory.get(this.condOffset);
117
+ const [aOffset, bOffset, condOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
118
+ [this.aOffset, this.bOffset, this.condOffset, this.dstOffset],
119
+ memory,
120
+ );
121
+
122
+ const a = memory.get(aOffset);
123
+ const b = memory.get(bOffset);
124
+ const cond = memory.get(condOffset);
121
125
 
122
126
  // TODO: reconsider toBigInt() here
123
- memory.set(this.dstOffset, cond.toBigInt() > 0 ? a : b);
127
+ memory.set(dstOffset, cond.toBigInt() > 0 ? a : b);
124
128
 
125
129
  memory.assert(memoryOperations);
126
130
  context.machineState.incrementPc();
@@ -131,8 +135,8 @@ export class Cast extends TwoOperandInstruction {
131
135
  static readonly type: string = 'CAST';
132
136
  static readonly opcode = Opcode.CAST;
133
137
 
134
- constructor(indirect: number, dstTag: number, aOffset: number, dstOffset: number) {
135
- super(indirect, dstTag, aOffset, dstOffset);
138
+ constructor(indirect: number, dstTag: number, srcOffset: number, dstOffset: number) {
139
+ super(indirect, dstTag, srcOffset, dstOffset);
136
140
  }
137
141
 
138
142
  public async execute(context: AvmContext): Promise<void> {
@@ -140,13 +144,14 @@ export class Cast extends TwoOperandInstruction {
140
144
  const memory = context.machineState.memory.track(this.type);
141
145
  context.machineState.consumeGas(this.gasCost(memoryOperations));
142
146
 
143
- const a = memory.get(this.aOffset);
147
+ const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.dstOffset], memory);
148
+
149
+ const a = memory.get(srcOffset);
144
150
 
145
- // TODO: consider not using toBigInt()
146
151
  const casted =
147
152
  this.inTag == TypeTag.FIELD ? new Field(a.toBigInt()) : TaggedMemory.integralFromTag(a.toBigInt(), this.inTag);
148
153
 
149
- memory.set(this.dstOffset, casted);
154
+ memory.set(dstOffset, casted);
150
155
 
151
156
  memory.assert(memoryOperations);
152
157
  context.machineState.incrementPc();
@@ -205,10 +210,11 @@ export class CalldataCopy extends Instruction {
205
210
  const memory = context.machineState.memory.track(this.type);
206
211
  context.machineState.consumeGas(this.gasCost(memoryOperations));
207
212
 
208
- const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], memory);
213
+ // We don't need to check tags here because: (1) the calldata is NOT in memory, and (2) we are the ones writing to destination.
214
+ const [cdOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.cdOffset, this.dstOffset], memory);
209
215
 
210
216
  const transformedData = context.environment.calldata
211
- .slice(this.cdOffset, this.cdOffset + this.copySize)
217
+ .slice(cdOffset, cdOffset + this.copySize)
212
218
  .map(f => new Field(f));
213
219
 
214
220
  memory.setSlice(dstOffset, transformedData);
@@ -216,10 +222,4 @@ export class CalldataCopy extends Instruction {
216
222
  memory.assert(memoryOperations);
217
223
  context.machineState.incrementPc();
218
224
  }
219
-
220
- protected override gasCost(memoryOps: Partial<MemoryOperations & { indirect: number }> = {}) {
221
- const baseGasCost = getBaseGasCost(this.opcode);
222
- const memoryGasCost = getMemoryGasCost(memoryOps);
223
- return sumGas(baseGasCost, memoryGasCost);
224
- }
225
225
  }
@@ -0,0 +1,114 @@
1
+ import { Fq, Point } from '@aztec/circuits.js';
2
+ import { Grumpkin } from '@aztec/circuits.js/barretenberg';
3
+
4
+ import { strict as assert } from 'assert';
5
+
6
+ import { type AvmContext } from '../avm_context.js';
7
+ import { Field, TypeTag } from '../avm_memory_types.js';
8
+ import { InstructionExecutionError } from '../errors.js';
9
+ import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
10
+ import { Addressing } from './addressing_mode.js';
11
+ import { Instruction } from './instruction.js';
12
+
13
+ export class MultiScalarMul extends Instruction {
14
+ static type: string = 'MultiScalarMul';
15
+ static readonly opcode: Opcode = Opcode.MSM;
16
+
17
+ // Informs (de)serialization. See Instruction.deserialize.
18
+ static readonly wireFormat: OperandType[] = [
19
+ OperandType.UINT8 /* opcode */,
20
+ OperandType.UINT8 /* indirect */,
21
+ OperandType.UINT32 /* points vector offset */,
22
+ OperandType.UINT32 /* scalars vector offset */,
23
+ OperandType.UINT32 /* output offset (fixed triplet) */,
24
+ OperandType.UINT32 /* points length offset */,
25
+ ];
26
+
27
+ constructor(
28
+ private indirect: number,
29
+ private pointsOffset: number,
30
+ private scalarsOffset: number,
31
+ private outputOffset: number,
32
+ private pointsLengthOffset: number,
33
+ ) {
34
+ super();
35
+ }
36
+
37
+ public async execute(context: AvmContext): Promise<void> {
38
+ const memory = context.machineState.memory.track(this.type);
39
+ // Resolve indirects
40
+ const [pointsOffset, scalarsOffset, outputOffset] = Addressing.fromWire(this.indirect).resolve(
41
+ [this.pointsOffset, this.scalarsOffset, this.outputOffset],
42
+ memory,
43
+ );
44
+
45
+ // Length of the points vector should be U32
46
+ memory.checkTag(TypeTag.UINT32, this.pointsLengthOffset);
47
+ // Get the size of the unrolled (x, y , inf) points vector
48
+ const pointsReadLength = memory.get(this.pointsLengthOffset).toNumber();
49
+ assert(pointsReadLength % 3 === 0, 'Points vector offset should be a multiple of 3');
50
+ // Divide by 3 since each point is represented as a triplet to get the number of points
51
+ const numPoints = pointsReadLength / 3;
52
+ // The tag for each triplet will be (Field, Field, Uint8)
53
+ for (let i = 0; i < numPoints; i++) {
54
+ const offset = pointsOffset + i * 3;
55
+ // Check (Field, Field)
56
+ memory.checkTagsRange(TypeTag.FIELD, offset, 2);
57
+ // Check Uint8 (inf flag)
58
+ memory.checkTag(TypeTag.UINT8, offset + 2);
59
+ }
60
+ // Get the unrolled (x, y, inf) representing the points
61
+ const pointsVector = memory.getSlice(pointsOffset, pointsReadLength);
62
+
63
+ // The size of the scalars vector is twice the NUMBER of points because of the scalar limb decomposition
64
+ const scalarReadLength = numPoints * 2;
65
+ // Consume gas prior to performing work
66
+ const memoryOperations = {
67
+ reads: 1 + pointsReadLength + scalarReadLength /* points and scalars */,
68
+ writes: 3 /* output triplet */,
69
+ indirect: this.indirect,
70
+ };
71
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
72
+ // Get the unrolled scalar (lo & hi) representing the scalars
73
+ const scalarsVector = memory.getSlice(scalarsOffset, scalarReadLength);
74
+ memory.checkTagsRange(TypeTag.FIELD, scalarsOffset, scalarReadLength);
75
+
76
+ // Now we need to reconstruct the points and scalars into something we can operate on.
77
+ const grumpkinPoints: Point[] = [];
78
+ for (let i = 0; i < numPoints; i++) {
79
+ const p: Point = new Point(pointsVector[3 * i].toFr(), pointsVector[3 * i + 1].toFr());
80
+ // Include this later when we have a standard for representing infinity
81
+ // const isInf = pointsVector[i + 2].toBoolean();
82
+
83
+ if (!p.isOnGrumpkin()) {
84
+ throw new InstructionExecutionError(`Point ${p.toString()} is not on the curve.`);
85
+ }
86
+ grumpkinPoints.push(p);
87
+ }
88
+ // The scalars are read from memory as Fr elements, which are limbs of Fq elements
89
+ // So we need to reconstruct them before performing the scalar multiplications
90
+ const scalarFqVector: Fq[] = [];
91
+ for (let i = 0; i < numPoints; i++) {
92
+ const scalarLo = scalarsVector[2 * i].toFr();
93
+ const scalarHi = scalarsVector[2 * i + 1].toFr();
94
+ const fqScalar = Fq.fromHighLow(scalarHi, scalarLo);
95
+ scalarFqVector.push(fqScalar);
96
+ }
97
+ // TODO: Is there an efficient MSM implementation in ts that we can replace this by?
98
+ const grumpkin = new Grumpkin();
99
+ // Zip the points and scalars into pairs
100
+ const [firstBaseScalarPair, ...rest]: Array<[Point, Fq]> = grumpkinPoints.map((p, idx) => [p, scalarFqVector[idx]]);
101
+ // Fold the points and scalars into a single point
102
+ // We have to ensure get the first point, since the identity element (point at infinity) isn't quite working in ts
103
+ const outputPoint = rest.reduce(
104
+ (acc, curr) => grumpkin.add(acc, grumpkin.mul(curr[0], curr[1])),
105
+ grumpkin.mul(firstBaseScalarPair[0], firstBaseScalarPair[1]),
106
+ );
107
+ const output = outputPoint.toFieldsWithInf().map(f => new Field(f));
108
+
109
+ memory.setSlice(outputOffset, output);
110
+
111
+ memory.assert(memoryOperations);
112
+ context.machineState.incrementPc();
113
+ }
114
+ }
@@ -1,8 +1,7 @@
1
1
  import { Fr } from '@aztec/foundation/fields';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
- import { type Gas, getBaseGasCost, getMemoryGasCost, mulGas, sumGas } from '../avm_gas.js';
5
- import { Field, type MemoryOperations } from '../avm_memory_types.js';
4
+ import { Field, TypeTag } from '../avm_memory_types.js';
6
5
  import { StaticCallAlterationError } from '../errors.js';
7
6
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
8
7
  import { Addressing } from './addressing_mode.js';
@@ -26,20 +25,14 @@ abstract class BaseStorageInstruction extends Instruction {
26
25
  ) {
27
26
  super();
28
27
  }
29
-
30
- protected override 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
- }
35
28
  }
36
29
 
37
30
  export class SStore extends BaseStorageInstruction {
38
31
  static readonly type: string = 'SSTORE';
39
32
  static readonly opcode = Opcode.SSTORE;
40
33
 
41
- constructor(indirect: number, srcOffset: number, /*temporary*/ srcSize: number, slotOffset: number) {
42
- super(indirect, srcOffset, srcSize, slotOffset);
34
+ constructor(indirect: number, srcOffset: number, /*temporary*/ size: number, slotOffset: number) {
35
+ super(indirect, srcOffset, size, slotOffset);
43
36
  }
44
37
 
45
38
  public async execute(context: AvmContext): Promise<void> {
@@ -52,6 +45,8 @@ export class SStore extends BaseStorageInstruction {
52
45
  context.machineState.consumeGas(this.gasCost(memoryOperations));
53
46
 
54
47
  const [srcOffset, slotOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], memory);
48
+ memory.checkTag(TypeTag.FIELD, slotOffset);
49
+ memory.checkTagsRange(TypeTag.FIELD, srcOffset, this.size);
55
50
 
56
51
  const slot = memory.get(slotOffset).toFr();
57
52
  const data = memory.getSlice(srcOffset, this.size).map(field => field.toFr());
@@ -79,21 +74,19 @@ export class SLoad extends BaseStorageInstruction {
79
74
  const memory = context.machineState.memory.track(this.type);
80
75
  context.machineState.consumeGas(this.gasCost(memoryOperations));
81
76
 
82
- const [aOffset, size, bOffset] = Addressing.fromWire(this.indirect).resolve(
83
- [this.aOffset, this.size, this.bOffset],
84
- memory,
85
- );
77
+ const [slotOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], memory);
78
+ memory.checkTag(TypeTag.FIELD, slotOffset);
86
79
 
87
- const slot = memory.get(aOffset);
80
+ const slot = memory.get(slotOffset);
88
81
 
89
82
  // Write each read value from storage into memory
90
- for (let i = 0; i < size; i++) {
83
+ for (let i = 0; i < this.size; i++) {
91
84
  const data: Fr = await context.persistableState.readStorage(
92
85
  context.environment.storageAddress,
93
86
  new Fr(slot.toBigInt() + BigInt(i)),
94
87
  );
95
88
 
96
- memory.set(bOffset + i, new Field(data));
89
+ memory.set(dstOffset + i, new Field(data));
97
90
  }
98
91
 
99
92
  context.machineState.incrementPc();
@@ -1,4 +1,5 @@
1
1
  import { DAGasLeft, L2GasLeft } from '../opcodes/context_getters.js';
2
+ import { EcAdd } from '../opcodes/ec_add.js';
2
3
  import { Keccak, Pedersen, Poseidon2, Sha256 } from '../opcodes/hashing.js';
3
4
  import type { Instruction } from '../opcodes/index.js';
4
5
  import {
@@ -52,6 +53,7 @@ import {
52
53
  Version,
53
54
  Xor,
54
55
  } from '../opcodes/index.js';
56
+ import { MultiScalarMul } from '../opcodes/multi_scalar_mul.js';
55
57
  import { BufferCursor } from './buffer_cursor.js';
56
58
  import { Opcode } from './instruction_serialization.js';
57
59
 
@@ -136,11 +138,13 @@ const INSTRUCTION_SET = () =>
136
138
  // Misc
137
139
  [DebugLog.opcode, DebugLog],
138
140
 
139
- // //// Gadgets
141
+ // Gadgets
142
+ [EcAdd.opcode, EcAdd],
140
143
  [Keccak.opcode, Keccak],
141
144
  [Poseidon2.opcode, Poseidon2],
142
145
  [Sha256.opcode, Sha256],
143
146
  [Pedersen.opcode, Pedersen],
147
+ [MultiScalarMul.opcode, MultiScalarMul],
144
148
  // Conversions
145
149
  [ToRadixLE.opcode, ToRadixLE],
146
150
  ]);
@@ -76,6 +76,8 @@ export enum Opcode {
76
76
  POSEIDON2,
77
77
  SHA256, // temp - may be removed, but alot of contracts rely on it
78
78
  PEDERSEN, // temp - may be removed, but alot of contracts rely on it
79
+ ECADD,
80
+ MSM,
79
81
  // Conversion
80
82
  TORADIXLE,
81
83
  }
@@ -2,25 +2,29 @@ import {
2
2
  type AuthWitness,
3
3
  type AztecNode,
4
4
  EncryptedL2Log,
5
+ EncryptedL2NoteLog,
6
+ Event,
7
+ L1EventPayload,
5
8
  L1NotePayload,
6
9
  Note,
7
10
  type NoteStatus,
8
- TaggedNote,
11
+ TaggedLog,
9
12
  type UnencryptedL2Log,
10
13
  } from '@aztec/circuit-types';
11
14
  import {
12
15
  CallContext,
13
- FunctionData,
14
16
  FunctionSelector,
15
17
  type Header,
18
+ type KeyValidationRequest,
16
19
  PrivateContextInputs,
17
20
  PublicCallRequest,
18
21
  type TxContext,
19
22
  } from '@aztec/circuits.js';
20
23
  import { Aes128 } from '@aztec/circuits.js/barretenberg';
21
- import { computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash';
24
+ import { computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash';
22
25
  import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi';
23
26
  import { AztecAddress } from '@aztec/foundation/aztec-address';
27
+ import { pedersenHash } from '@aztec/foundation/crypto';
24
28
  import { Fr, GrumpkinScalar, type Point } from '@aztec/foundation/fields';
25
29
  import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log';
26
30
 
@@ -28,7 +32,7 @@ import { type NoteData, toACVMWitness } from '../acvm/index.js';
28
32
  import { type PackedValuesCache } from '../common/packed_values_cache.js';
29
33
  import { type DBOracle } from './db_oracle.js';
30
34
  import { type ExecutionNoteCache } from './execution_note_cache.js';
31
- import { CountedLog, type ExecutionResult, type NoteAndSlot } from './execution_result.js';
35
+ import { CountedLog, CountedNoteLog, type ExecutionResult, type NoteAndSlot } from './execution_result.js';
32
36
  import { pickNotes } from './pick_notes.js';
33
37
  import { executePrivateFunction } from './private_execution.js';
34
38
  import { ViewDataOracle } from './view_data_oracle.js';
@@ -56,7 +60,7 @@ export class ClientExecutionContext extends ViewDataOracle {
56
60
  */
57
61
  private noteHashLeafIndexMap: Map<bigint, bigint> = new Map();
58
62
  private nullifiedNoteHashCounters: Map<number, number> = new Map();
59
- private noteEncryptedLogs: CountedLog<EncryptedL2Log>[] = [];
63
+ private noteEncryptedLogs: CountedNoteLog[] = [];
60
64
  private encryptedLogs: CountedLog<EncryptedL2Log>[] = [];
61
65
  private unencryptedLogs: CountedLog<UnencryptedL2Log>[] = [];
62
66
  private nestedExecutions: ExecutionResult[] = [];
@@ -136,33 +140,6 @@ export class ClientExecutionContext extends ViewDataOracle {
136
140
  return this.noteEncryptedLogs;
137
141
  }
138
142
 
139
- /**
140
- * Sometimes notes can be chopped after a nested execution is complete.
141
- * This means finished nested executions still hold transient logs. This method removes them.
142
- * TODO(Miranda): is there a cleaner solution?
143
- */
144
- public chopNoteEncryptedLogs() {
145
- // Do not return logs that have been chopped in the cache
146
- const allNoteLogs = this.noteCache.getLogs();
147
- this.noteEncryptedLogs = this.noteEncryptedLogs.filter(l => allNoteLogs.includes(l));
148
- const chop = (thing: any) =>
149
- thing.nestedExecutions.forEach((result: ExecutionResult) => {
150
- if (!result.noteEncryptedLogs[0]?.isEmpty()) {
151
- // The execution has note logs
152
- result.noteEncryptedLogs = result.noteEncryptedLogs.filter(l => allNoteLogs.includes(l));
153
- }
154
- chop(result);
155
- });
156
- chop(this);
157
- }
158
-
159
- /**
160
- * Return the note encrypted logs emitted during this execution and nested executions.
161
- */
162
- public getAllNoteEncryptedLogs() {
163
- return this.noteCache.getLogs();
164
- }
165
-
166
143
  /**
167
144
  * Return the encrypted logs emitted during this execution.
168
145
  */
@@ -355,24 +332,64 @@ export class ClientExecutionContext extends ViewDataOracle {
355
332
 
356
333
  /**
357
334
  * Emit encrypted data
358
- * @param encryptedNote - The encrypted data.
335
+ * @param contractAddress - The contract emitting the encrypted event.
336
+ * @param randomness - A value used to mask the contract address we are siloing with.
337
+ * @param encryptedEvent - The encrypted event data.
359
338
  * @param counter - The effects counter.
360
339
  */
361
- public override emitEncryptedLog(encryptedData: Buffer, counter: number) {
362
- const encryptedLog = new CountedLog(new EncryptedL2Log(encryptedData), counter);
340
+ public override emitEncryptedEventLog(
341
+ contractAddress: AztecAddress,
342
+ randomness: Fr,
343
+ encryptedEvent: Buffer,
344
+ counter: number,
345
+ ) {
346
+ // In some cases, we actually want to reveal the contract address we are siloing with:
347
+ // e.g. 'handshaking' contract w/ known address
348
+ // An app providing randomness = 0 signals to not mask the address.
349
+ const maskedContractAddress = randomness.isZero()
350
+ ? contractAddress.toField()
351
+ : pedersenHash([contractAddress, randomness], 0);
352
+ const encryptedLog = new CountedLog(new EncryptedL2Log(encryptedEvent, maskedContractAddress), counter);
363
353
  this.encryptedLogs.push(encryptedLog);
364
354
  }
365
355
 
366
356
  /**
367
357
  * Emit encrypted note data
368
- * @param noteHash - The note hash.
358
+ * @param noteHashCounter - The note hash counter.
369
359
  * @param encryptedNote - The encrypted note data.
370
- * @param counter - The effects counter.
360
+ * @param counter - The log counter.
371
361
  */
372
- public override emitEncryptedNoteLog(noteHash: Fr, encryptedNote: Buffer, counter: number) {
373
- const encryptedLog = new CountedLog(new EncryptedL2Log(encryptedNote), counter);
362
+ public override emitEncryptedNoteLog(noteHashCounter: number, encryptedNote: Buffer, counter: number) {
363
+ const encryptedLog = new CountedNoteLog(new EncryptedL2NoteLog(encryptedNote), counter, noteHashCounter);
374
364
  this.noteEncryptedLogs.push(encryptedLog);
375
- this.noteCache.addNewLog(encryptedLog, noteHash);
365
+ }
366
+
367
+ /**
368
+ * Encrypt an event
369
+ * @param contractAddress - The contract emitting the encrypted event.
370
+ * @param randomness - A value used to mask the contract address we are siloing with.
371
+ * @param eventTypeId - The type ID of the event (function selector).
372
+ * @param ovKeys - The outgoing viewing keys to use to encrypt.
373
+ * @param ivpkM - The master incoming viewing public key.
374
+ * @param preimage - The event preimage.
375
+ */
376
+ public override computeEncryptedEventLog(
377
+ contractAddress: AztecAddress,
378
+ randomness: Fr,
379
+ eventTypeId: Fr,
380
+ ovKeys: KeyValidationRequest,
381
+ ivpkM: Point,
382
+ preimage: Fr[],
383
+ ) {
384
+ const event = new Event(preimage);
385
+ const l1EventPayload = new L1EventPayload(event, contractAddress, randomness, eventTypeId);
386
+ const taggedEvent = new TaggedLog(l1EventPayload);
387
+
388
+ const ephSk = GrumpkinScalar.random();
389
+
390
+ const recipient = AztecAddress.random();
391
+
392
+ return taggedEvent.encrypt(ephSk, recipient, ivpkM, ovKeys);
376
393
  }
377
394
 
378
395
  /**
@@ -380,27 +397,30 @@ export class ClientExecutionContext extends ViewDataOracle {
380
397
  * @param contractAddress - The contract address of the note.
381
398
  * @param storageSlot - The storage slot the note is at.
382
399
  * @param noteTypeId - The type ID of the note.
383
- * @param ivpk - The master incoming viewing public key.
400
+ * @param ovKeys - The outgoing viewing keys to use to encrypt.
401
+ * @param ivpkM - The master incoming viewing public key.
384
402
  * @param preimage - The note preimage.
385
403
  */
386
- public override computeEncryptedLog(
404
+ public override computeEncryptedNoteLog(
387
405
  contractAddress: AztecAddress,
388
406
  storageSlot: Fr,
389
407
  noteTypeId: Fr,
390
- ivpk: Point,
408
+ ovKeys: KeyValidationRequest,
409
+ ivpkM: Point,
391
410
  preimage: Fr[],
392
411
  ) {
393
412
  const note = new Note(preimage);
394
413
  const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
395
- const taggedNote = new TaggedNote(l1NotePayload);
414
+ const taggedNote = new TaggedLog(l1NotePayload);
396
415
 
397
416
  const ephSk = GrumpkinScalar.random();
398
417
 
399
- // @todo Issue(#6410) Right now we are completely ignoring the outgoing log. Just drawing random data.
400
- const ovsk = GrumpkinScalar.random();
418
+ // @todo This should be populated properly.
419
+ // Note that this encryption function SHOULD not be used, but is currently used
420
+ // as oracle for encrypted event logs.
401
421
  const recipient = AztecAddress.random();
402
422
 
403
- return taggedNote.encrypt(ephSk, recipient, ivpk, ovsk);
423
+ return taggedNote.encrypt(ephSk, recipient, ivpkM, ovKeys);
404
424
  }
405
425
 
406
426
  /**
@@ -468,7 +488,6 @@ export class ClientExecutionContext extends ViewDataOracle {
468
488
  isStaticCall = isStaticCall || this.callContext.isStaticCall;
469
489
 
470
490
  const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
471
- const targetFunctionData = FunctionData.fromAbi(targetArtifact);
472
491
 
473
492
  const derivedTxContext = this.txContext.clone();
474
493
 
@@ -498,7 +517,7 @@ export class ClientExecutionContext extends ViewDataOracle {
498
517
  context,
499
518
  targetArtifact,
500
519
  targetContractAddress,
501
- targetFunctionData,
520
+ functionSelector,
502
521
  );
503
522
 
504
523
  if (isStaticCall) {
@@ -552,7 +571,7 @@ export class ClientExecutionContext extends ViewDataOracle {
552
571
  args,
553
572
  callContext: derivedCallContext,
554
573
  parentCallContext: this.callContext,
555
- functionData: FunctionData.fromAbi(targetArtifact),
574
+ functionSelector,
556
575
  contractAddress: targetContractAddress,
557
576
  });
558
577
  }
@@ -657,20 +676,13 @@ export class ClientExecutionContext extends ViewDataOracle {
657
676
  * @param numberOfElements - Number of elements to read from the starting storage slot.
658
677
  */
659
678
  public override async storageRead(startStorageSlot: Fr, numberOfElements: number): Promise<Fr[]> {
660
- // TODO(#4320): This is a hack to work around not having directly access to the public data tree but
661
- // still having access to the witnesses
662
- const bn = await this.db.getBlockNumber();
663
-
664
679
  const values = [];
665
680
  for (let i = 0n; i < numberOfElements; i++) {
666
681
  const storageSlot = new Fr(startStorageSlot.value + i);
667
- const leafSlot = computePublicDataTreeLeafSlot(this.callContext.storageContractAddress, storageSlot);
668
- const witness = await this.db.getPublicDataTreeWitness(bn, leafSlot);
669
- if (!witness) {
670
- throw new Error(`No witness for slot ${storageSlot.toString()}`);
671
- }
672
- const value = witness.leafPreimage.value;
682
+
683
+ const value = await this.aztecNode.getPublicStorageAt(this.callContext.storageContractAddress, storageSlot);
673
684
  this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
685
+
674
686
  values.push(value);
675
687
  }
676
688
  return values;
@@ -684,4 +696,8 @@ export class ClientExecutionContext extends ViewDataOracle {
684
696
  public override debugLog(message: string, fields: Fr[]) {
685
697
  this.log.verbose(`debug_log ${applyStringFormatting(message, fields)}`);
686
698
  }
699
+
700
+ public getDebugFunctionName() {
701
+ return this.db.getDebugFunctionName(this.contractAddress, this.callContext.functionSelector);
702
+ }
687
703
  }
@@ -12,7 +12,7 @@ import { type Fr } from '@aztec/foundation/fields';
12
12
  import { type ContractInstance } from '@aztec/types/contracts';
13
13
 
14
14
  import { type NoteData } from '../acvm/index.js';
15
- import { type CommitmentsDB } from '../public/db.js';
15
+ import { type CommitmentsDB } from '../public/db_interfaces.js';
16
16
 
17
17
  /**
18
18
  * Error thrown when a contract is not found in the database.
@@ -95,6 +95,13 @@ export interface DBOracle extends CommitmentsDB {
95
95
  */
96
96
  getFunctionArtifact(contractAddress: AztecAddress, selector: FunctionSelector): Promise<FunctionArtifact>;
97
97
 
98
+ /**
99
+ * Generates a stable function name for debug purposes.
100
+ * @param contractAddress - The contract address.
101
+ * @param selector - The corresponding function selector.
102
+ */
103
+ getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string>;
104
+
98
105
  /**
99
106
  * Retrieves the artifact of a specified function within a given contract.
100
107
  * The function is identified by its name, which is unique within a contract.
@@ -1,10 +1,8 @@
1
- import { type EncryptedL2Log } from '@aztec/circuit-types';
2
1
  import { siloNullifier } from '@aztec/circuits.js/hash';
3
2
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
4
3
  import { Fr } from '@aztec/foundation/fields';
5
4
 
6
5
  import { type NoteData } from '../acvm/index.js';
7
- import { type CountedLog } from './execution_result.js';
8
6
 
9
7
  export interface PendingNote {
10
8
  note: NoteData;
@@ -29,13 +27,6 @@ export class ExecutionNoteCache {
29
27
  */
30
28
  private nullifiers: Map<bigint, Set<bigint>> = new Map();
31
29
 
32
- /**
33
- * The list of encrypted logs linked to note hashes created in this transaction.
34
- * This mapping maps from inner note hash to log(s) emitted for that note hash.
35
- * Note that their value (bigint representation) is used because Frs cannot be looked up in Sets.
36
- */
37
- private logs: Map<bigint, CountedLog<EncryptedL2Log>[]> = new Map();
38
-
39
30
  /**
40
31
  * Add a new note to cache.
41
32
  * @param note - New note created during execution.
@@ -46,16 +37,6 @@ export class ExecutionNoteCache {
46
37
  this.newNotes.set(note.contractAddress.toBigInt(), notes);
47
38
  }
48
39
 
49
- /**
50
- * Add a new note to cache.
51
- * @param note - New note created during execution.
52
- */
53
- public addNewLog(log: CountedLog<EncryptedL2Log>, innerNoteHash: Fr) {
54
- const logs = this.logs.get(innerNoteHash.toBigInt()) ?? [];
55
- logs.push(log);
56
- this.logs.set(innerNoteHash.toBigInt(), logs);
57
- }
58
-
59
40
  /**
60
41
  * Add a nullifier to cache. It could be for a db note or a new note created during execution.
61
42
  * @param contractAddress - Contract address of the note.
@@ -81,8 +62,6 @@ export class ExecutionNoteCache {
81
62
  const note = notes.splice(noteIndexToRemove, 1)[0];
82
63
  nullifiedNoteHashCounter = note.counter;
83
64
  this.newNotes.set(contractAddress.toBigInt(), notes);
84
- // If a log linked to the note hash does not exist, this method just does nothing
85
- this.logs.delete(innerNoteHash.toBigInt());
86
65
  }
87
66
 
88
67
  return nullifiedNoteHashCounter;
@@ -117,11 +96,4 @@ export class ExecutionNoteCache {
117
96
  public getNullifiers(contractAddress: AztecAddress): Set<bigint> {
118
97
  return this.nullifiers.get(contractAddress.toBigInt()) ?? new Set();
119
98
  }
120
-
121
- /**
122
- * Return all note logs emitted from a contract.
123
- */
124
- public getLogs(): CountedLog<EncryptedL2Log>[] {
125
- return Array.from(this.logs.values()).flat();
126
- }
127
99
  }