@aztec/simulator 0.42.0 → 0.44.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 (191) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +5 -2
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +25 -8
  4. package/dest/acvm/oracle/typed_oracle.d.ts +7 -4
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +14 -5
  7. package/dest/avm/avm_execution_environment.d.ts +2 -0
  8. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  9. package/dest/avm/avm_execution_environment.js +9 -4
  10. package/dest/avm/avm_gas.d.ts.map +1 -1
  11. package/dest/avm/avm_gas.js +3 -1
  12. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  13. package/dest/avm/avm_memory_types.js +2 -4
  14. package/dest/avm/avm_simulator.d.ts.map +1 -1
  15. package/dest/avm/avm_simulator.js +2 -3
  16. package/dest/avm/fixtures/index.d.ts +10 -3
  17. package/dest/avm/fixtures/index.d.ts.map +1 -1
  18. package/dest/avm/fixtures/index.js +9 -11
  19. package/dest/avm/journal/journal.d.ts +57 -66
  20. package/dest/avm/journal/journal.d.ts.map +1 -1
  21. package/dest/avm/journal/journal.js +97 -131
  22. package/dest/avm/journal/nullifiers.d.ts +21 -8
  23. package/dest/avm/journal/nullifiers.d.ts.map +1 -1
  24. package/dest/avm/journal/nullifiers.js +26 -8
  25. package/dest/avm/journal/public_storage.d.ts +4 -0
  26. package/dest/avm/journal/public_storage.d.ts.map +1 -1
  27. package/dest/avm/journal/public_storage.js +10 -1
  28. package/dest/avm/opcodes/accrued_substate.d.ts +2 -2
  29. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  30. package/dest/avm/opcodes/accrued_substate.js +39 -24
  31. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  32. package/dest/avm/opcodes/arithmetic.js +12 -9
  33. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  34. package/dest/avm/opcodes/bitwise.js +11 -8
  35. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  36. package/dest/avm/opcodes/comparators.js +7 -5
  37. package/dest/avm/opcodes/contract.d.ts.map +1 -1
  38. package/dest/avm/opcodes/contract.js +20 -24
  39. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  40. package/dest/avm/opcodes/control_flow.js +4 -2
  41. package/dest/avm/opcodes/ec_add.d.ts +19 -0
  42. package/dest/avm/opcodes/ec_add.d.ts.map +1 -0
  43. package/dest/avm/opcodes/ec_add.js +78 -0
  44. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  45. package/dest/avm/opcodes/external_calls.js +19 -29
  46. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  47. package/dest/avm/opcodes/hashing.js +10 -2
  48. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  49. package/dest/avm/opcodes/instruction_impl.js +4 -2
  50. package/dest/avm/opcodes/memory.d.ts +1 -1
  51. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  52. package/dest/avm/opcodes/memory.js +14 -12
  53. package/dest/avm/opcodes/multi_scalar_mul.d.ts +16 -0
  54. package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -0
  55. package/dest/avm/opcodes/multi_scalar_mul.js +95 -0
  56. package/dest/avm/opcodes/storage.d.ts +1 -1
  57. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  58. package/dest/avm/opcodes/storage.js +11 -8
  59. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  60. package/dest/avm/serialization/bytecode_serialization.js +5 -1
  61. package/dest/avm/serialization/instruction_serialization.d.ts +3 -1
  62. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  63. package/dest/avm/serialization/instruction_serialization.js +4 -2
  64. package/dest/avm/test_utils.d.ts +14 -0
  65. package/dest/avm/test_utils.d.ts.map +1 -0
  66. package/dest/avm/test_utils.js +36 -0
  67. package/dest/client/client_execution_context.d.ts +17 -5
  68. package/dest/client/client_execution_context.d.ts.map +1 -1
  69. package/dest/client/client_execution_context.js +32 -18
  70. package/dest/client/execution_note_cache.d.ts.map +1 -1
  71. package/dest/client/execution_note_cache.js +1 -1
  72. package/dest/client/execution_result.d.ts +2 -1
  73. package/dest/client/execution_result.d.ts.map +1 -1
  74. package/dest/client/execution_result.js +1 -1
  75. package/dest/client/index.d.ts +2 -0
  76. package/dest/client/index.d.ts.map +1 -1
  77. package/dest/client/index.js +3 -1
  78. package/dest/client/simulator.d.ts +4 -3
  79. package/dest/client/simulator.d.ts.map +1 -1
  80. package/dest/client/simulator.js +17 -9
  81. package/dest/client/view_data_oracle.d.ts +2 -0
  82. package/dest/client/view_data_oracle.d.ts.map +1 -1
  83. package/dest/client/view_data_oracle.js +7 -1
  84. package/dest/mocks/fixtures.d.ts.map +1 -1
  85. package/dest/mocks/fixtures.js +3 -2
  86. package/dest/public/abstract_phase_manager.d.ts +11 -11
  87. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  88. package/dest/public/abstract_phase_manager.js +84 -59
  89. package/dest/public/app_logic_phase_manager.d.ts +3 -3
  90. package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
  91. package/dest/public/app_logic_phase_manager.js +4 -3
  92. package/dest/public/db_interfaces.d.ts +1 -0
  93. package/dest/public/db_interfaces.d.ts.map +1 -1
  94. package/dest/public/execution.d.ts +28 -40
  95. package/dest/public/execution.d.ts.map +1 -1
  96. package/dest/public/execution.js +1 -51
  97. package/dest/public/executor.d.ts +9 -4
  98. package/dest/public/executor.d.ts.map +1 -1
  99. package/dest/public/executor.js +38 -27
  100. package/dest/public/hints_builder.d.ts +1 -1
  101. package/dest/public/index.d.ts +6 -6
  102. package/dest/public/index.d.ts.map +1 -1
  103. package/dest/public/index.js +7 -7
  104. package/dest/public/phase_manager_factory.d.ts +3 -3
  105. package/dest/public/phase_manager_factory.d.ts.map +1 -1
  106. package/dest/public/phase_manager_factory.js +5 -5
  107. package/dest/public/public_db_sources.d.ts +3 -1
  108. package/dest/public/public_db_sources.d.ts.map +1 -1
  109. package/dest/public/public_db_sources.js +54 -8
  110. package/dest/public/public_processor.d.ts +5 -2
  111. package/dest/public/public_processor.d.ts.map +1 -1
  112. package/dest/public/public_processor.js +143 -125
  113. package/dest/public/setup_phase_manager.d.ts +3 -3
  114. package/dest/public/setup_phase_manager.d.ts.map +1 -1
  115. package/dest/public/setup_phase_manager.js +3 -3
  116. package/dest/public/side_effect_trace.d.ts +86 -0
  117. package/dest/public/side_effect_trace.d.ts.map +1 -0
  118. package/dest/public/side_effect_trace.js +222 -0
  119. package/dest/public/side_effect_trace_interface.d.ts +36 -0
  120. package/dest/public/side_effect_trace_interface.d.ts.map +1 -0
  121. package/dest/public/side_effect_trace_interface.js +2 -0
  122. package/dest/public/tail_phase_manager.d.ts +3 -3
  123. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  124. package/dest/public/tail_phase_manager.js +3 -3
  125. package/dest/public/teardown_phase_manager.d.ts +3 -3
  126. package/dest/public/teardown_phase_manager.d.ts.map +1 -1
  127. package/dest/public/teardown_phase_manager.js +4 -3
  128. package/dest/public/transitional_adaptors.d.ts +2 -6
  129. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  130. package/dest/public/transitional_adaptors.js +1 -43
  131. package/package.json +18 -9
  132. package/src/acvm/oracle/oracle.ts +46 -9
  133. package/src/acvm/oracle/typed_oracle.ts +37 -7
  134. package/src/avm/avm_execution_environment.ts +10 -3
  135. package/src/avm/avm_gas.ts +2 -0
  136. package/src/avm/avm_memory_types.ts +1 -3
  137. package/src/avm/avm_simulator.ts +2 -3
  138. package/src/avm/fixtures/index.ts +19 -14
  139. package/src/avm/journal/journal.ts +127 -231
  140. package/src/avm/journal/nullifiers.ts +30 -13
  141. package/src/avm/journal/public_storage.ts +10 -0
  142. package/src/avm/opcodes/accrued_substate.ts +60 -23
  143. package/src/avm/opcodes/arithmetic.ts +17 -8
  144. package/src/avm/opcodes/bitwise.ts +13 -8
  145. package/src/avm/opcodes/comparators.ts +9 -4
  146. package/src/avm/opcodes/contract.ts +22 -26
  147. package/src/avm/opcodes/control_flow.ts +3 -1
  148. package/src/avm/opcodes/ec_add.ts +92 -0
  149. package/src/avm/opcodes/external_calls.ts +20 -36
  150. package/src/avm/opcodes/hashing.ts +11 -1
  151. package/src/avm/opcodes/instruction_impl.ts +4 -1
  152. package/src/avm/opcodes/memory.ts +18 -11
  153. package/src/avm/opcodes/multi_scalar_mul.ts +114 -0
  154. package/src/avm/opcodes/storage.ts +10 -10
  155. package/src/avm/serialization/bytecode_serialization.ts +4 -0
  156. package/src/avm/serialization/instruction_serialization.ts +2 -0
  157. package/src/avm/test_utils.ts +53 -0
  158. package/src/client/client_execution_context.ts +55 -21
  159. package/src/client/execution_note_cache.ts +0 -1
  160. package/src/client/execution_result.ts +2 -1
  161. package/src/client/index.ts +2 -0
  162. package/src/client/simulator.ts +26 -10
  163. package/src/client/view_data_oracle.ts +8 -0
  164. package/src/mocks/fixtures.ts +2 -1
  165. package/src/public/abstract_phase_manager.ts +99 -70
  166. package/src/public/app_logic_phase_manager.ts +3 -2
  167. package/src/public/db_interfaces.ts +2 -0
  168. package/src/public/execution.ts +35 -94
  169. package/src/public/executor.ts +56 -40
  170. package/src/public/index.ts +6 -12
  171. package/src/public/phase_manager_factory.ts +6 -6
  172. package/src/public/public_db_sources.ts +62 -7
  173. package/src/public/public_processor.ts +15 -9
  174. package/src/public/setup_phase_manager.ts +2 -2
  175. package/src/public/side_effect_trace.ts +323 -0
  176. package/src/public/side_effect_trace_interface.ts +41 -0
  177. package/src/public/tail_phase_manager.ts +2 -2
  178. package/src/public/teardown_phase_manager.ts +3 -2
  179. package/src/public/transitional_adaptors.ts +2 -60
  180. package/dest/avm/journal/trace.d.ts +0 -33
  181. package/dest/avm/journal/trace.d.ts.map +0 -1
  182. package/dest/avm/journal/trace.js +0 -151
  183. package/dest/avm/journal/trace_types.d.ts +0 -51
  184. package/dest/avm/journal/trace_types.d.ts.map +0 -1
  185. package/dest/avm/journal/trace_types.js +0 -6
  186. package/dest/public/utils.d.ts +0 -8
  187. package/dest/public/utils.d.ts.map +0 -1
  188. package/dest/public/utils.js +0 -38
  189. package/src/avm/journal/trace.ts +0 -184
  190. package/src/avm/journal/trace_types.ts +0 -88
  191. package/src/public/utils.ts +0 -39
@@ -114,12 +114,17 @@ export class CMov extends Instruction {
114
114
  const memory = context.machineState.memory.track(this.type);
115
115
  context.machineState.consumeGas(this.gasCost(memoryOperations));
116
116
 
117
- const a = memory.get(this.aOffset);
118
- const b = memory.get(this.bOffset);
119
- 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);
120
125
 
121
126
  // TODO: reconsider toBigInt() here
122
- memory.set(this.dstOffset, cond.toBigInt() > 0 ? a : b);
127
+ memory.set(dstOffset, cond.toBigInt() > 0 ? a : b);
123
128
 
124
129
  memory.assert(memoryOperations);
125
130
  context.machineState.incrementPc();
@@ -130,8 +135,8 @@ export class Cast extends TwoOperandInstruction {
130
135
  static readonly type: string = 'CAST';
131
136
  static readonly opcode = Opcode.CAST;
132
137
 
133
- constructor(indirect: number, dstTag: number, aOffset: number, dstOffset: number) {
134
- super(indirect, dstTag, aOffset, dstOffset);
138
+ constructor(indirect: number, dstTag: number, srcOffset: number, dstOffset: number) {
139
+ super(indirect, dstTag, srcOffset, dstOffset);
135
140
  }
136
141
 
137
142
  public async execute(context: AvmContext): Promise<void> {
@@ -139,13 +144,14 @@ export class Cast extends TwoOperandInstruction {
139
144
  const memory = context.machineState.memory.track(this.type);
140
145
  context.machineState.consumeGas(this.gasCost(memoryOperations));
141
146
 
142
- 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);
143
150
 
144
- // TODO: consider not using toBigInt()
145
151
  const casted =
146
152
  this.inTag == TypeTag.FIELD ? new Field(a.toBigInt()) : TaggedMemory.integralFromTag(a.toBigInt(), this.inTag);
147
153
 
148
- memory.set(this.dstOffset, casted);
154
+ memory.set(dstOffset, casted);
149
155
 
150
156
  memory.assert(memoryOperations);
151
157
  context.machineState.incrementPc();
@@ -204,10 +210,11 @@ export class CalldataCopy extends Instruction {
204
210
  const memory = context.machineState.memory.track(this.type);
205
211
  context.machineState.consumeGas(this.gasCost(memoryOperations));
206
212
 
207
- 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);
208
215
 
209
216
  const transformedData = context.environment.calldata
210
- .slice(this.cdOffset, this.cdOffset + this.copySize)
217
+ .slice(cdOffset, cdOffset + this.copySize)
211
218
  .map(f => new Field(f));
212
219
 
213
220
  memory.setSlice(dstOffset, transformedData);
@@ -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,7 +1,7 @@
1
1
  import { Fr } from '@aztec/foundation/fields';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
- import { Field } from '../avm_memory_types.js';
4
+ import { Field, TypeTag } from '../avm_memory_types.js';
5
5
  import { StaticCallAlterationError } from '../errors.js';
6
6
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
7
  import { Addressing } from './addressing_mode.js';
@@ -31,8 +31,8 @@ export class SStore extends BaseStorageInstruction {
31
31
  static readonly type: string = 'SSTORE';
32
32
  static readonly opcode = Opcode.SSTORE;
33
33
 
34
- constructor(indirect: number, srcOffset: number, /*temporary*/ srcSize: number, slotOffset: number) {
35
- super(indirect, srcOffset, srcSize, slotOffset);
34
+ constructor(indirect: number, srcOffset: number, /*temporary*/ size: number, slotOffset: number) {
35
+ super(indirect, srcOffset, size, slotOffset);
36
36
  }
37
37
 
38
38
  public async execute(context: AvmContext): Promise<void> {
@@ -45,6 +45,8 @@ export class SStore extends BaseStorageInstruction {
45
45
  context.machineState.consumeGas(this.gasCost(memoryOperations));
46
46
 
47
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);
48
50
 
49
51
  const slot = memory.get(slotOffset).toFr();
50
52
  const data = memory.getSlice(srcOffset, this.size).map(field => field.toFr());
@@ -72,21 +74,19 @@ export class SLoad extends BaseStorageInstruction {
72
74
  const memory = context.machineState.memory.track(this.type);
73
75
  context.machineState.consumeGas(this.gasCost(memoryOperations));
74
76
 
75
- const [aOffset, size, bOffset] = Addressing.fromWire(this.indirect).resolve(
76
- [this.aOffset, this.size, this.bOffset],
77
- memory,
78
- );
77
+ const [slotOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], memory);
78
+ memory.checkTag(TypeTag.FIELD, slotOffset);
79
79
 
80
- const slot = memory.get(aOffset);
80
+ const slot = memory.get(slotOffset);
81
81
 
82
82
  // Write each read value from storage into memory
83
- for (let i = 0; i < size; i++) {
83
+ for (let i = 0; i < this.size; i++) {
84
84
  const data: Fr = await context.persistableState.readStorage(
85
85
  context.environment.storageAddress,
86
86
  new Fr(slot.toBigInt() + BigInt(i)),
87
87
  );
88
88
 
89
- memory.set(bOffset + i, new Field(data));
89
+ memory.set(dstOffset + i, new Field(data));
90
90
  }
91
91
 
92
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
 
@@ -137,10 +139,12 @@ const INSTRUCTION_SET = () =>
137
139
  [DebugLog.opcode, DebugLog],
138
140
 
139
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
  }
@@ -0,0 +1,53 @@
1
+ import { Fr } from '@aztec/circuits.js';
2
+ import { type ContractInstanceWithAddress } from '@aztec/types/contracts';
3
+
4
+ import { type jest } from '@jest/globals';
5
+ import { mock } from 'jest-mock-extended';
6
+
7
+ import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../public/db_interfaces.js';
8
+ import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js';
9
+ import { type HostStorage } from './journal/host_storage.js';
10
+
11
+ export function mockGetBytecode(hs: HostStorage, bytecode: Buffer) {
12
+ (hs as jest.Mocked<HostStorage>).contractsDb.getBytecode.mockResolvedValue(bytecode);
13
+ }
14
+
15
+ export function mockTraceFork(trace: PublicSideEffectTraceInterface, nestedTrace?: PublicSideEffectTraceInterface) {
16
+ (trace as jest.Mocked<PublicSideEffectTraceInterface>).fork.mockReturnValue(
17
+ nestedTrace ?? mock<PublicSideEffectTraceInterface>(),
18
+ );
19
+ }
20
+
21
+ export function mockStorageRead(hs: HostStorage, value: Fr) {
22
+ (hs.publicStateDb as jest.Mocked<PublicStateDB>).storageRead.mockResolvedValue(value);
23
+ }
24
+
25
+ export function mockStorageReadWithMap(hs: HostStorage, mockedStorage: Map<bigint, Fr>) {
26
+ (hs.publicStateDb as jest.Mocked<PublicStateDB>).storageRead.mockImplementation((_address, slot) =>
27
+ Promise.resolve(mockedStorage.get(slot.toBigInt()) ?? Fr.ZERO),
28
+ );
29
+ }
30
+
31
+ export function mockNoteHashExists(hs: HostStorage, leafIndex: Fr, _value?: Fr) {
32
+ (hs.commitmentsDb as jest.Mocked<CommitmentsDB>).getCommitmentIndex.mockResolvedValue(leafIndex.toBigInt());
33
+ }
34
+
35
+ export function mockNullifierExists(hs: HostStorage, leafIndex: Fr, _value?: Fr) {
36
+ (hs.commitmentsDb as jest.Mocked<CommitmentsDB>).getNullifierIndex.mockResolvedValue(leafIndex.toBigInt());
37
+ }
38
+
39
+ export function mockL1ToL2MessageExists(hs: HostStorage, leafIndex: Fr, value: Fr, valueAtOtherIndices?: Fr) {
40
+ (hs.commitmentsDb as jest.Mocked<CommitmentsDB>).getL1ToL2LeafValue.mockImplementation((index: bigint) => {
41
+ if (index == leafIndex.toBigInt()) {
42
+ return Promise.resolve(value);
43
+ } else {
44
+ // any indices other than mockAtLeafIndex will return a different value
45
+ // (or undefined if no value is specified for other indices)
46
+ return Promise.resolve(valueAtOtherIndices!);
47
+ }
48
+ });
49
+ }
50
+
51
+ export function mockGetContractInstance(hs: HostStorage, contractInstance: ContractInstanceWithAddress) {
52
+ (hs.contractsDb as jest.Mocked<PublicContractsDB>).getContractInstance.mockResolvedValue(contractInstance);
53
+ }
@@ -3,10 +3,12 @@ import {
3
3
  type AztecNode,
4
4
  EncryptedL2Log,
5
5
  EncryptedL2NoteLog,
6
+ Event,
7
+ L1EventPayload,
6
8
  L1NotePayload,
7
9
  Note,
8
10
  type NoteStatus,
9
- TaggedNote,
11
+ TaggedLog,
10
12
  type UnencryptedL2Log,
11
13
  } from '@aztec/circuit-types';
12
14
  import {
@@ -19,8 +21,14 @@ import {
19
21
  type TxContext,
20
22
  } from '@aztec/circuits.js';
21
23
  import { Aes128 } from '@aztec/circuits.js/barretenberg';
22
- import { computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash';
23
- import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi';
24
+ import { computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash';
25
+ import {
26
+ EventSelector,
27
+ type FunctionAbi,
28
+ type FunctionArtifact,
29
+ type NoteSelector,
30
+ countArgumentsSize,
31
+ } from '@aztec/foundation/abi';
24
32
  import { AztecAddress } from '@aztec/foundation/aztec-address';
25
33
  import { pedersenHash } from '@aztec/foundation/crypto';
26
34
  import { Fr, GrumpkinScalar, type Point } from '@aztec/foundation/fields';
@@ -286,7 +294,7 @@ export class ClientExecutionContext extends ViewDataOracle {
286
294
  */
287
295
  public override notifyCreatedNote(
288
296
  storageSlot: Fr,
289
- noteTypeId: Fr,
297
+ noteTypeId: NoteSelector,
290
298
  noteItems: Fr[],
291
299
  innerNoteHash: Fr,
292
300
  counter: number,
@@ -330,13 +338,15 @@ export class ClientExecutionContext extends ViewDataOracle {
330
338
 
331
339
  /**
332
340
  * Emit encrypted data
333
- * @param encryptedNote - The encrypted data.
341
+ * @param contractAddress - The contract emitting the encrypted event.
342
+ * @param randomness - A value used to mask the contract address we are siloing with.
343
+ * @param encryptedEvent - The encrypted event data.
334
344
  * @param counter - The effects counter.
335
345
  */
336
- public override emitEncryptedLog(
346
+ public override emitEncryptedEventLog(
337
347
  contractAddress: AztecAddress,
338
348
  randomness: Fr,
339
- encryptedData: Buffer,
349
+ encryptedEvent: Buffer,
340
350
  counter: number,
341
351
  ) {
342
352
  // In some cases, we actually want to reveal the contract address we are siloing with:
@@ -345,7 +355,7 @@ export class ClientExecutionContext extends ViewDataOracle {
345
355
  const maskedContractAddress = randomness.isZero()
346
356
  ? contractAddress.toField()
347
357
  : pedersenHash([contractAddress, randomness], 0);
348
- const encryptedLog = new CountedLog(new EncryptedL2Log(encryptedData, maskedContractAddress), counter);
358
+ const encryptedLog = new CountedLog(new EncryptedL2Log(encryptedEvent, maskedContractAddress), counter);
349
359
  this.encryptedLogs.push(encryptedLog);
350
360
  }
351
361
 
@@ -360,6 +370,34 @@ export class ClientExecutionContext extends ViewDataOracle {
360
370
  this.noteEncryptedLogs.push(encryptedLog);
361
371
  }
362
372
 
373
+ /**
374
+ * Encrypt an event
375
+ * @param contractAddress - The contract emitting the encrypted event.
376
+ * @param randomness - A value used to mask the contract address we are siloing with.
377
+ * @param eventTypeId - The type ID of the event (function selector).
378
+ * @param ovKeys - The outgoing viewing keys to use to encrypt.
379
+ * @param ivpkM - The master incoming viewing public key.
380
+ * @param preimage - The event preimage.
381
+ */
382
+ public override computeEncryptedEventLog(
383
+ contractAddress: AztecAddress,
384
+ randomness: Fr,
385
+ eventTypeId: Fr,
386
+ ovKeys: KeyValidationRequest,
387
+ ivpkM: Point,
388
+ preimage: Fr[],
389
+ ) {
390
+ const event = new Event(preimage);
391
+ const l1EventPayload = new L1EventPayload(event, contractAddress, randomness, EventSelector.fromField(eventTypeId));
392
+ const taggedEvent = new TaggedLog(l1EventPayload);
393
+
394
+ const ephSk = GrumpkinScalar.random();
395
+
396
+ const recipient = AztecAddress.random();
397
+
398
+ return taggedEvent.encrypt(ephSk, recipient, ivpkM, ovKeys);
399
+ }
400
+
363
401
  /**
364
402
  * Encrypt a note
365
403
  * @param contractAddress - The contract address of the note.
@@ -369,20 +407,23 @@ export class ClientExecutionContext extends ViewDataOracle {
369
407
  * @param ivpkM - The master incoming viewing public key.
370
408
  * @param preimage - The note preimage.
371
409
  */
372
- public override computeEncryptedLog(
410
+ public override computeEncryptedNoteLog(
373
411
  contractAddress: AztecAddress,
374
412
  storageSlot: Fr,
375
- noteTypeId: Fr,
413
+ noteTypeId: NoteSelector,
376
414
  ovKeys: KeyValidationRequest,
377
415
  ivpkM: Point,
378
416
  preimage: Fr[],
379
417
  ) {
380
418
  const note = new Note(preimage);
381
419
  const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
382
- const taggedNote = new TaggedNote(l1NotePayload);
420
+ const taggedNote = new TaggedLog(l1NotePayload);
383
421
 
384
422
  const ephSk = GrumpkinScalar.random();
385
423
 
424
+ // @todo This should be populated properly.
425
+ // Note that this encryption function SHOULD not be used, but is currently used
426
+ // as oracle for encrypted event logs.
386
427
  const recipient = AztecAddress.random();
387
428
 
388
429
  return taggedNote.encrypt(ephSk, recipient, ivpkM, ovKeys);
@@ -641,20 +682,13 @@ export class ClientExecutionContext extends ViewDataOracle {
641
682
  * @param numberOfElements - Number of elements to read from the starting storage slot.
642
683
  */
643
684
  public override async storageRead(startStorageSlot: Fr, numberOfElements: number): Promise<Fr[]> {
644
- // TODO(#4320): This is a hack to work around not having directly access to the public data tree but
645
- // still having access to the witnesses
646
- const bn = await this.db.getBlockNumber();
647
-
648
685
  const values = [];
649
686
  for (let i = 0n; i < numberOfElements; i++) {
650
687
  const storageSlot = new Fr(startStorageSlot.value + i);
651
- const leafSlot = computePublicDataTreeLeafSlot(this.callContext.storageContractAddress, storageSlot);
652
- const witness = await this.db.getPublicDataTreeWitness(bn, leafSlot);
653
- if (!witness) {
654
- throw new Error(`No witness for slot ${storageSlot.toString()}`);
655
- }
656
- const value = witness.leafPreimage.value;
688
+
689
+ const value = await this.aztecNode.getPublicStorageAt(this.callContext.storageContractAddress, storageSlot);
657
690
  this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
691
+
658
692
  values.push(value);
659
693
  }
660
694
  return values;
@@ -63,7 +63,6 @@ export class ExecutionNoteCache {
63
63
  nullifiedNoteHashCounter = note.counter;
64
64
  this.newNotes.set(contractAddress.toBigInt(), notes);
65
65
  }
66
-
67
66
  return nullifiedNoteHashCounter;
68
67
  }
69
68
 
@@ -8,6 +8,7 @@ import {
8
8
  type UnencryptedL2Log,
9
9
  } from '@aztec/circuit-types';
10
10
  import { type IsEmpty, type PrivateCallStackItem, PublicCallRequest, sortByCounter } from '@aztec/circuits.js';
11
+ import { type NoteSelector } from '@aztec/foundation/abi';
11
12
  import { type Fr } from '@aztec/foundation/fields';
12
13
 
13
14
  import { type ACVMField } from '../acvm/index.js';
@@ -21,7 +22,7 @@ export interface NoteAndSlot {
21
22
  /** The storage slot of the note. */
22
23
  storageSlot: Fr;
23
24
  /** The note type identifier. */
24
- noteTypeId: Fr;
25
+ noteTypeId: NoteSelector;
25
26
  }
26
27
 
27
28
  export class CountedLog<TLog extends UnencryptedL2Log | EncryptedL2NoteLog | EncryptedL2Log> implements IsEmpty {
@@ -1,3 +1,5 @@
1
1
  export * from './simulator.js';
2
2
  export * from './db_oracle.js';
3
3
  export * from './execution_result.js';
4
+ export * from './pick_notes.js';
5
+ export * from './execution_note_cache.js';
@@ -5,6 +5,7 @@ import {
5
5
  type FunctionArtifact,
6
6
  FunctionSelector,
7
7
  FunctionType,
8
+ type NoteSelector,
8
9
  encodeArguments,
9
10
  } from '@aztec/foundation/abi';
10
11
  import { AztecAddress } from '@aztec/foundation/aztec-address';
@@ -132,29 +133,31 @@ export class AcirSimulator {
132
133
  * @param nonce - The nonce of the note hash.
133
134
  * @param storageSlot - The storage slot.
134
135
  * @param noteTypeId - The note type identifier.
136
+ * @param computeNullifier - A flag indicating whether to compute the nullifier or just return 0.
135
137
  * @param note - The note.
136
138
  * @returns The nullifier.
137
139
  */
138
- public async computeNoteHashAndNullifier(
140
+ public async computeNoteHashAndOptionallyANullifier(
139
141
  contractAddress: AztecAddress,
140
142
  nonce: Fr,
141
143
  storageSlot: Fr,
142
- noteTypeId: Fr,
144
+ noteTypeId: NoteSelector,
145
+ computeNullifier: boolean,
143
146
  note: Note,
144
147
  ) {
145
148
  const artifact: FunctionArtifact | undefined = await this.db.getFunctionArtifactByName(
146
149
  contractAddress,
147
- 'compute_note_hash_and_nullifier',
150
+ 'compute_note_hash_and_optionally_a_nullifier',
148
151
  );
149
152
  if (!artifact) {
150
153
  throw new Error(
151
- `Mandatory implementation of "compute_note_hash_and_nullifier" missing in noir contract ${contractAddress.toString()}.`,
154
+ `Mandatory implementation of "compute_note_hash_and_optionally_a_nullifier" missing in noir contract ${contractAddress.toString()}.`,
152
155
  );
153
156
  }
154
157
 
155
- if (artifact.parameters.length != 5) {
158
+ if (artifact.parameters.length != 6) {
156
159
  throw new Error(
157
- `Expected 5 parameters in mandatory implementation of "compute_note_hash_and_nullifier", but found ${
160
+ `Expected 6 parameters in mandatory implementation of "compute_note_hash_and_optionally_a_nullifier", but found ${
158
161
  artifact.parameters.length
159
162
  } in noir contract ${contractAddress.toString()}.`,
160
163
  );
@@ -163,7 +166,7 @@ export class AcirSimulator {
163
166
  const maxNoteFields = (artifact.parameters[artifact.parameters.length - 1].type as ArrayType).length;
164
167
  if (maxNoteFields < note.items.length) {
165
168
  throw new Error(
166
- `The note being processed has ${note.items.length} fields, while "compute_note_hash_and_nullifier" can only handle a maximum of ${maxNoteFields} fields. Please reduce the number of fields in your note.`,
169
+ `The note being processed has ${note.items.length} fields, while "compute_note_hash_and_optionally_a_nullifier" can only handle a maximum of ${maxNoteFields} fields. Please reduce the number of fields in your note.`,
167
170
  );
168
171
  }
169
172
 
@@ -175,7 +178,14 @@ export class AcirSimulator {
175
178
  selector: FunctionSelector.empty(),
176
179
  type: FunctionType.UNCONSTRAINED,
177
180
  isStatic: artifact.isStatic,
178
- args: encodeArguments(artifact, [contractAddress, nonce, storageSlot, noteTypeId, extendedNoteItems]),
181
+ args: encodeArguments(artifact, [
182
+ contractAddress,
183
+ nonce,
184
+ storageSlot,
185
+ noteTypeId,
186
+ computeNullifier,
187
+ extendedNoteItems,
188
+ ]),
179
189
  returnTypes: artifact.returnTypes,
180
190
  };
181
191
 
@@ -201,12 +211,18 @@ export class AcirSimulator {
201
211
  * @param note - The note.
202
212
  * @returns The note hash.
203
213
  */
204
- public async computeInnerNoteHash(contractAddress: AztecAddress, storageSlot: Fr, noteTypeId: Fr, note: Note) {
205
- const { innerNoteHash } = await this.computeNoteHashAndNullifier(
214
+ public async computeInnerNoteHash(
215
+ contractAddress: AztecAddress,
216
+ storageSlot: Fr,
217
+ noteTypeId: NoteSelector,
218
+ note: Note,
219
+ ) {
220
+ const { innerNoteHash } = await this.computeNoteHashAndOptionallyANullifier(
206
221
  contractAddress,
207
222
  Fr.ZERO,
208
223
  storageSlot,
209
224
  noteTypeId,
225
+ false,
210
226
  note,
211
227
  );
212
228
  return innerNoteHash;
@@ -42,6 +42,14 @@ export class ViewDataOracle extends TypedOracle {
42
42
  return Promise.resolve(this.contractAddress);
43
43
  }
44
44
 
45
+ public override getChainId(): Promise<Fr> {
46
+ return Promise.resolve(this.aztecNode.getChainId().then(id => new Fr(id)));
47
+ }
48
+
49
+ public override getVersion(): Promise<Fr> {
50
+ return Promise.resolve(this.aztecNode.getVersion().then(v => new Fr(v)));
51
+ }
52
+
45
53
  /**
46
54
  * Retrieve keys associated with a specific master public key and app address.
47
55
  * @param pkMHash - The master public key hash.
@@ -143,7 +143,8 @@ export class PublicExecutionResultBuilder {
143
143
  endGasLeft: Gas.test(),
144
144
  transactionFee: Fr.ZERO,
145
145
  calldata: [],
146
- avmHints: AvmExecutionHints.empty(),
146
+ avmCircuitHints: AvmExecutionHints.empty(),
147
+ functionName: 'unknown',
147
148
  ...overrides,
148
149
  };
149
150
  }