@aztec/simulator 0.62.0 → 0.63.1

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 (216) hide show
  1. package/dest/acvm/acvm.d.ts +2 -16
  2. package/dest/acvm/acvm.d.ts.map +1 -1
  3. package/dest/acvm/acvm.js +2 -70
  4. package/dest/acvm/oracle/oracle.d.ts +4 -4
  5. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/oracle.js +10 -11
  7. package/dest/acvm/oracle/typed_oracle.d.ts +5 -5
  8. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  9. package/dest/acvm/oracle/typed_oracle.js +8 -8
  10. package/dest/avm/avm_gas.d.ts.map +1 -1
  11. package/dest/avm/avm_gas.js +2 -1
  12. package/dest/avm/avm_machine_state.d.ts +27 -8
  13. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  14. package/dest/avm/avm_machine_state.js +6 -10
  15. package/dest/avm/avm_memory_types.d.ts +8 -0
  16. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  17. package/dest/avm/avm_memory_types.js +5 -1
  18. package/dest/avm/avm_simulator.d.ts +2 -19
  19. package/dest/avm/avm_simulator.d.ts.map +1 -1
  20. package/dest/avm/avm_simulator.js +12 -14
  21. package/dest/avm/avm_tree.d.ts +249 -0
  22. package/dest/avm/avm_tree.d.ts.map +1 -0
  23. package/dest/avm/avm_tree.js +637 -0
  24. package/dest/avm/errors.d.ts +4 -17
  25. package/dest/avm/errors.d.ts.map +1 -1
  26. package/dest/avm/errors.js +21 -50
  27. package/dest/avm/fixtures/index.d.ts +7 -2
  28. package/dest/avm/fixtures/index.d.ts.map +1 -1
  29. package/dest/avm/fixtures/index.js +12 -12
  30. package/dest/avm/index.d.ts +1 -0
  31. package/dest/avm/index.d.ts.map +1 -1
  32. package/dest/avm/index.js +2 -1
  33. package/dest/avm/journal/journal.d.ts +43 -24
  34. package/dest/avm/journal/journal.d.ts.map +1 -1
  35. package/dest/avm/journal/journal.js +172 -39
  36. package/dest/avm/journal/nullifiers.d.ts +5 -4
  37. package/dest/avm/journal/nullifiers.d.ts.map +1 -1
  38. package/dest/avm/journal/nullifiers.js +2 -3
  39. package/dest/avm/journal/public_storage.d.ts +6 -5
  40. package/dest/avm/journal/public_storage.d.ts.map +1 -1
  41. package/dest/avm/journal/public_storage.js +1 -1
  42. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  43. package/dest/avm/opcodes/accrued_substate.js +4 -10
  44. package/dest/avm/opcodes/arithmetic.d.ts +4 -1
  45. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  46. package/dest/avm/opcodes/arithmetic.js +18 -4
  47. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  48. package/dest/avm/opcodes/bitwise.js +1 -3
  49. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  50. package/dest/avm/opcodes/comparators.js +1 -2
  51. package/dest/avm/opcodes/contract.d.ts.map +1 -1
  52. package/dest/avm/opcodes/contract.js +2 -3
  53. package/dest/avm/opcodes/control_flow.d.ts +4 -0
  54. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  55. package/dest/avm/opcodes/control_flow.js +21 -6
  56. package/dest/avm/opcodes/conversion.d.ts.map +1 -1
  57. package/dest/avm/opcodes/conversion.js +1 -2
  58. package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
  59. package/dest/avm/opcodes/ec_add.js +5 -11
  60. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  61. package/dest/avm/opcodes/environment_getters.js +1 -2
  62. package/dest/avm/opcodes/external_calls.d.ts +4 -2
  63. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  64. package/dest/avm/opcodes/external_calls.js +38 -22
  65. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  66. package/dest/avm/opcodes/hashing.js +1 -4
  67. package/dest/avm/opcodes/instruction.d.ts +4 -0
  68. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  69. package/dest/avm/opcodes/instruction.js +7 -1
  70. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  71. package/dest/avm/opcodes/memory.js +1 -7
  72. package/dest/avm/opcodes/misc.js +3 -3
  73. package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
  74. package/dest/avm/opcodes/multi_scalar_mul.js +6 -5
  75. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  76. package/dest/avm/opcodes/storage.js +2 -4
  77. package/dest/avm/serialization/bytecode_serialization.d.ts +1 -6
  78. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  79. package/dest/avm/serialization/bytecode_serialization.js +24 -20
  80. package/dest/client/client_execution_context.d.ts +7 -11
  81. package/dest/client/client_execution_context.d.ts.map +1 -1
  82. package/dest/client/client_execution_context.js +18 -20
  83. package/dest/client/db_oracle.d.ts +17 -10
  84. package/dest/client/db_oracle.d.ts.map +1 -1
  85. package/dest/client/db_oracle.js +1 -1
  86. package/dest/client/private_execution.d.ts.map +1 -1
  87. package/dest/client/private_execution.js +5 -4
  88. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  89. package/dest/client/unconstrained_execution.js +3 -2
  90. package/dest/client/view_data_oracle.d.ts +6 -12
  91. package/dest/client/view_data_oracle.d.ts.map +1 -1
  92. package/dest/client/view_data_oracle.js +10 -12
  93. package/dest/common/errors.d.ts +15 -2
  94. package/dest/common/errors.d.ts.map +1 -1
  95. package/dest/common/errors.js +85 -4
  96. package/dest/mocks/fixtures.d.ts +9 -28
  97. package/dest/mocks/fixtures.d.ts.map +1 -1
  98. package/dest/mocks/fixtures.js +12 -57
  99. package/dest/public/dual_side_effect_trace.d.ts +34 -26
  100. package/dest/public/dual_side_effect_trace.d.ts.map +1 -1
  101. package/dest/public/dual_side_effect_trace.js +48 -36
  102. package/dest/public/enqueued_call_side_effect_trace.d.ts +96 -33
  103. package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
  104. package/dest/public/enqueued_call_side_effect_trace.js +212 -138
  105. package/dest/public/execution.d.ts +50 -17
  106. package/dest/public/execution.d.ts.map +1 -1
  107. package/dest/public/execution.js +1 -29
  108. package/dest/public/executor.d.ts +28 -11
  109. package/dest/public/executor.d.ts.map +1 -1
  110. package/dest/public/executor.js +33 -33
  111. package/dest/public/index.d.ts +4 -5
  112. package/dest/public/index.d.ts.map +1 -1
  113. package/dest/public/index.js +4 -5
  114. package/dest/public/public_db_sources.d.ts +1 -0
  115. package/dest/public/public_db_sources.d.ts.map +1 -1
  116. package/dest/public/public_db_sources.js +12 -5
  117. package/dest/public/public_processor.d.ts +7 -11
  118. package/dest/public/public_processor.d.ts.map +1 -1
  119. package/dest/public/public_processor.js +60 -42
  120. package/dest/public/public_processor_metrics.d.ts +3 -3
  121. package/dest/public/public_processor_metrics.d.ts.map +1 -1
  122. package/dest/public/public_processor_metrics.js +1 -1
  123. package/dest/public/public_tx_context.d.ts +130 -0
  124. package/dest/public/public_tx_context.d.ts.map +1 -0
  125. package/dest/public/public_tx_context.js +293 -0
  126. package/dest/public/public_tx_simulator.d.ts +36 -0
  127. package/dest/public/public_tx_simulator.d.ts.map +1 -0
  128. package/dest/public/public_tx_simulator.js +148 -0
  129. package/dest/public/side_effect_trace.d.ts +30 -15
  130. package/dest/public/side_effect_trace.d.ts.map +1 -1
  131. package/dest/public/side_effect_trace.js +70 -16
  132. package/dest/public/side_effect_trace_interface.d.ts +43 -12
  133. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  134. package/dest/public/transitional_adapters.d.ts +9 -0
  135. package/dest/public/transitional_adapters.d.ts.map +1 -0
  136. package/dest/public/transitional_adapters.js +127 -0
  137. package/dest/public/utils.d.ts +5 -0
  138. package/dest/public/utils.d.ts.map +1 -0
  139. package/dest/public/utils.js +30 -0
  140. package/package.json +12 -9
  141. package/src/acvm/acvm.ts +3 -94
  142. package/src/acvm/oracle/oracle.ts +9 -14
  143. package/src/acvm/oracle/typed_oracle.ts +8 -8
  144. package/src/avm/avm_gas.ts +1 -0
  145. package/src/avm/avm_machine_state.ts +28 -12
  146. package/src/avm/avm_memory_types.ts +5 -0
  147. package/src/avm/avm_simulator.ts +13 -16
  148. package/src/avm/avm_tree.ts +785 -0
  149. package/src/avm/errors.ts +25 -48
  150. package/src/avm/fixtures/index.ts +16 -12
  151. package/src/avm/index.ts +1 -0
  152. package/src/avm/journal/journal.ts +291 -52
  153. package/src/avm/journal/nullifiers.ts +7 -7
  154. package/src/avm/journal/public_storage.ts +5 -5
  155. package/src/avm/opcodes/accrued_substate.ts +3 -9
  156. package/src/avm/opcodes/arithmetic.ts +26 -4
  157. package/src/avm/opcodes/bitwise.ts +0 -2
  158. package/src/avm/opcodes/comparators.ts +0 -1
  159. package/src/avm/opcodes/contract.ts +1 -2
  160. package/src/avm/opcodes/control_flow.ts +24 -5
  161. package/src/avm/opcodes/conversion.ts +0 -1
  162. package/src/avm/opcodes/ec_add.ts +6 -9
  163. package/src/avm/opcodes/environment_getters.ts +0 -1
  164. package/src/avm/opcodes/external_calls.ts +39 -21
  165. package/src/avm/opcodes/hashing.ts +0 -3
  166. package/src/avm/opcodes/instruction.ts +7 -0
  167. package/src/avm/opcodes/memory.ts +0 -6
  168. package/src/avm/opcodes/misc.ts +2 -2
  169. package/src/avm/opcodes/multi_scalar_mul.ts +5 -4
  170. package/src/avm/opcodes/storage.ts +1 -3
  171. package/src/avm/serialization/bytecode_serialization.ts +31 -22
  172. package/src/client/client_execution_context.ts +22 -23
  173. package/src/client/db_oracle.ts +22 -11
  174. package/src/client/private_execution.ts +5 -4
  175. package/src/client/unconstrained_execution.ts +2 -1
  176. package/src/client/view_data_oracle.ts +14 -13
  177. package/src/common/errors.ts +119 -3
  178. package/src/mocks/fixtures.ts +15 -106
  179. package/src/public/dual_side_effect_trace.ts +138 -50
  180. package/src/public/enqueued_call_side_effect_trace.ts +352 -212
  181. package/src/public/execution.ts +58 -42
  182. package/src/public/executor.ts +52 -67
  183. package/src/public/index.ts +7 -5
  184. package/src/public/public_db_sources.ts +12 -4
  185. package/src/public/public_processor.ts +111 -73
  186. package/src/public/public_processor_metrics.ts +3 -3
  187. package/src/public/public_tx_context.ts +411 -0
  188. package/src/public/public_tx_simulator.ts +232 -0
  189. package/src/public/side_effect_trace.ts +154 -28
  190. package/src/public/side_effect_trace_interface.ts +92 -14
  191. package/src/public/transitional_adapters.ts +347 -0
  192. package/src/public/utils.ts +32 -0
  193. package/dest/public/enqueued_call_simulator.d.ts +0 -43
  194. package/dest/public/enqueued_call_simulator.d.ts.map +0 -1
  195. package/dest/public/enqueued_call_simulator.js +0 -156
  196. package/dest/public/enqueued_calls_processor.d.ts +0 -43
  197. package/dest/public/enqueued_calls_processor.d.ts.map +0 -1
  198. package/dest/public/enqueued_calls_processor.js +0 -209
  199. package/dest/public/hints_builder.d.ts +0 -29
  200. package/dest/public/hints_builder.d.ts.map +0 -1
  201. package/dest/public/hints_builder.js +0 -75
  202. package/dest/public/public_kernel.d.ts +0 -30
  203. package/dest/public/public_kernel.d.ts.map +0 -1
  204. package/dest/public/public_kernel.js +0 -67
  205. package/dest/public/public_kernel_circuit_simulator.d.ts +0 -25
  206. package/dest/public/public_kernel_circuit_simulator.d.ts.map +0 -1
  207. package/dest/public/public_kernel_circuit_simulator.js +0 -2
  208. package/dest/public/public_kernel_tail_simulator.d.ts +0 -15
  209. package/dest/public/public_kernel_tail_simulator.d.ts.map +0 -1
  210. package/dest/public/public_kernel_tail_simulator.js +0 -39
  211. package/src/public/enqueued_call_simulator.ts +0 -360
  212. package/src/public/enqueued_calls_processor.ts +0 -372
  213. package/src/public/hints_builder.ts +0 -168
  214. package/src/public/public_kernel.ts +0 -100
  215. package/src/public/public_kernel_circuit_simulator.ts +0 -32
  216. package/src/public/public_kernel_tail_simulator.ts +0 -97
@@ -1,5 +1,12 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { type Field, type MemoryValue } from '../avm_memory_types.js';
2
+ import {
3
+ type Field,
4
+ type MemoryValue,
5
+ TaggedMemory,
6
+ type TaggedMemoryInterface,
7
+ TypeTag,
8
+ } from '../avm_memory_types.js';
9
+ import { ArithmeticError } from '../errors.js';
3
10
  import { Opcode } from '../serialization/instruction_serialization.js';
4
11
  import { Addressing } from './addressing_mode.js';
5
12
  import { ThreeOperandInstruction } from './instruction_impl.js';
@@ -12,7 +19,7 @@ export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInst
12
19
  const operands = [this.aOffset, this.bOffset, this.dstOffset];
13
20
  const addressing = Addressing.fromWire(this.indirect, operands.length);
14
21
  const [aOffset, bOffset, dstOffset] = addressing.resolve(operands, memory);
15
- memory.checkTagsAreSame(aOffset, bOffset);
22
+ this.checkTags(memory, aOffset, bOffset);
16
23
 
17
24
  const a = memory.get(aOffset);
18
25
  const b = memory.get(bOffset);
@@ -21,10 +28,12 @@ export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInst
21
28
  memory.set(dstOffset, dest);
22
29
 
23
30
  memory.assert({ reads: 2, writes: 1, addressing });
24
- context.machineState.incrementPc();
25
31
  }
26
32
 
27
33
  protected abstract compute(a: MemoryValue, b: MemoryValue): MemoryValue;
34
+ protected checkTags(memory: TaggedMemoryInterface, aOffset: number, bOffset: number) {
35
+ memory.checkTagsAreSame(aOffset, bOffset);
36
+ }
28
37
  }
29
38
 
30
39
  export class Add extends ThreeOperandArithmeticInstruction {
@@ -59,11 +68,19 @@ export class Div extends ThreeOperandArithmeticInstruction {
59
68
  static readonly opcode = Opcode.DIV_8; // FIXME: needed for gas.
60
69
 
61
70
  protected compute(a: MemoryValue, b: MemoryValue): MemoryValue {
71
+ if (b.toBigInt() === 0n) {
72
+ throw new ArithmeticError('Division by zero');
73
+ }
74
+
62
75
  return a.div(b);
63
76
  }
77
+
78
+ protected override checkTags(memory: TaggedMemoryInterface, aOffset: number, bOffset: number) {
79
+ memory.checkTagsAreSame(aOffset, bOffset);
80
+ TaggedMemory.checkIsIntegralTag(memory.getTag(aOffset)); // Follows that bOffset tag is also of integral type
81
+ }
64
82
  }
65
83
 
66
- // TODO: This class now temporarily has a tag, until all tags are removed.
67
84
  export class FieldDiv extends ThreeOperandArithmeticInstruction {
68
85
  static type: string = 'FDIV';
69
86
  static readonly opcode = Opcode.FDIV_8; // FIXME: needed for gas.
@@ -72,4 +89,9 @@ export class FieldDiv extends ThreeOperandArithmeticInstruction {
72
89
  // return (a as Field).fdiv(b as Field);
73
90
  return a.fdiv(b);
74
91
  }
92
+
93
+ protected override checkTags(memory: TaggedMemoryInterface, aOffset: number, bOffset: number) {
94
+ memory.checkTagsAreSame(aOffset, bOffset);
95
+ memory.checkTag(TypeTag.FIELD, aOffset); // Follows that bOffset has also tag of type Field
96
+ }
75
97
  }
@@ -22,7 +22,6 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
22
22
  memory.set(dstOffset, res);
23
23
 
24
24
  memory.assert({ reads: 2, writes: 1, addressing });
25
- context.machineState.incrementPc();
26
25
  }
27
26
 
28
27
  protected abstract compute(a: IntegralValue, b: IntegralValue): IntegralValue;
@@ -110,6 +109,5 @@ export class Not extends Instruction {
110
109
  memory.set(dstOffset, res);
111
110
 
112
111
  memory.assert({ reads: 1, writes: 1, addressing });
113
- context.machineState.incrementPc();
114
112
  }
115
113
  }
@@ -21,7 +21,6 @@ abstract class ComparatorInstruction extends ThreeOperandInstruction {
21
21
  memory.set(dstOffset, dest);
22
22
 
23
23
  memory.assert({ reads: 2, writes: 1, addressing });
24
- context.machineState.incrementPc();
25
24
  }
26
25
 
27
26
  protected abstract compare(a: MemoryValue, b: MemoryValue): boolean;
@@ -47,7 +47,7 @@ export class GetContractInstance extends Instruction {
47
47
  const [addressOffset, dstOffset, existsOffset] = addressing.resolve(operands, memory);
48
48
  memory.checkTag(TypeTag.FIELD, addressOffset);
49
49
 
50
- const address = memory.get(addressOffset).toFr();
50
+ const address = memory.get(addressOffset).toAztecAddress();
51
51
  const instance = await context.persistableState.getContractInstance(address);
52
52
  const exists = instance !== undefined;
53
53
 
@@ -70,6 +70,5 @@ export class GetContractInstance extends Instruction {
70
70
  memory.set(dstOffset, memberValue);
71
71
 
72
72
  memory.assert({ reads: 1, writes: 2, addressing });
73
- context.machineState.incrementPc();
74
73
  }
75
74
  }
@@ -22,6 +22,10 @@ export class Jump extends Instruction {
22
22
 
23
23
  context.machineState.memory.assert({});
24
24
  }
25
+
26
+ public override handlesPC(): boolean {
27
+ return true;
28
+ }
25
29
  }
26
30
 
27
31
  export class JumpI extends Instruction {
@@ -50,13 +54,17 @@ export class JumpI extends Instruction {
50
54
  const condition = memory.getAs<IntegralValue>(condOffset);
51
55
 
52
56
  if (condition.toBigInt() == 0n) {
53
- context.machineState.incrementPc();
57
+ context.machineState.pc = context.machineState.nextPc;
54
58
  } else {
55
59
  context.machineState.pc = this.loc;
56
60
  }
57
61
 
58
62
  memory.assert({ reads: 1, addressing });
59
63
  }
64
+
65
+ public override handlesPC(): boolean {
66
+ return true;
67
+ }
60
68
  }
61
69
 
62
70
  export class InternalCall extends Instruction {
@@ -72,11 +80,18 @@ export class InternalCall extends Instruction {
72
80
  public async execute(context: AvmContext): Promise<void> {
73
81
  context.machineState.consumeGas(this.gasCost());
74
82
 
75
- context.machineState.internalCallStack.push(context.machineState.pc + 1);
83
+ context.machineState.internalCallStack.push({
84
+ callPc: context.machineState.pc,
85
+ returnPc: context.machineState.nextPc,
86
+ });
76
87
  context.machineState.pc = this.loc;
77
88
 
78
89
  context.machineState.memory.assert({});
79
90
  }
91
+
92
+ public override handlesPC(): boolean {
93
+ return true;
94
+ }
80
95
  }
81
96
 
82
97
  export class InternalReturn extends Instruction {
@@ -92,12 +107,16 @@ export class InternalReturn extends Instruction {
92
107
  public async execute(context: AvmContext): Promise<void> {
93
108
  context.machineState.consumeGas(this.gasCost());
94
109
 
95
- const jumpOffset = context.machineState.internalCallStack.pop();
96
- if (jumpOffset === undefined) {
110
+ const stackEntry = context.machineState.internalCallStack.pop();
111
+ if (stackEntry === undefined) {
97
112
  throw new InstructionExecutionError('Internal call stack empty!');
98
113
  }
99
- context.machineState.pc = jumpOffset;
114
+ context.machineState.pc = stackEntry.returnPc;
100
115
 
101
116
  context.machineState.memory.assert({});
102
117
  }
118
+
119
+ public override handlesPC(): boolean {
120
+ return true;
121
+ }
103
122
  }
@@ -64,6 +64,5 @@ export class ToRadixBE extends Instruction {
64
64
  memory.setSlice(dstOffset, res);
65
65
 
66
66
  memory.assert({ reads: 2, writes: this.numLimbs, addressing });
67
- context.machineState.incrementPc();
68
67
  }
69
68
  }
@@ -2,7 +2,7 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg';
2
2
  import { Point } from '@aztec/foundation/fields';
3
3
 
4
4
  import { type AvmContext } from '../avm_context.js';
5
- import { Field } from '../avm_memory_types.js';
5
+ import { Field, TypeTag, Uint1 } from '../avm_memory_types.js';
6
6
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
7
  import { Addressing } from './addressing_mode.js';
8
8
  import { Instruction } from './instruction.js';
@@ -54,6 +54,9 @@ export class EcAdd extends Instruction {
54
54
  const [p1XOffset, p1YOffset, p1IsInfiniteOffset, p2XOffset, p2YOffset, p2IsInfiniteOffset, dstOffset] =
55
55
  addressing.resolve(operands, memory);
56
56
 
57
+ memory.checkTags(TypeTag.FIELD, p1XOffset, p1YOffset, p2XOffset, p2YOffset);
58
+ memory.checkTags(TypeTag.UINT1, p1IsInfiniteOffset, p2IsInfiniteOffset);
59
+
57
60
  const p1X = memory.get(p1XOffset);
58
61
  const p1Y = memory.get(p1YOffset);
59
62
  const p1IsInfinite = memory.get(p1IsInfiniteOffset).toNumber() === 1;
@@ -80,18 +83,12 @@ export class EcAdd extends Instruction {
80
83
  } else {
81
84
  dest = grumpkin.add(p1, p2);
82
85
  }
83
- // Temporary,
84
- if (p1IsInfinite) {
85
- dest = p2;
86
- } else if (p2IsInfinite) {
87
- dest = p1;
88
- }
86
+
89
87
  memory.set(dstOffset, new Field(dest.x));
90
88
  memory.set(dstOffset + 1, new Field(dest.y));
91
89
  // Check representation of infinity for grumpkin
92
- memory.set(dstOffset + 2, new Field(dest.equals(Point.ZERO) ? 1 : 0));
90
+ memory.set(dstOffset + 2, new Uint1(dest.equals(Point.ZERO) ? 1 : 0));
93
91
 
94
92
  memory.assert({ reads: 6, writes: 3, addressing });
95
- context.machineState.incrementPc();
96
93
  }
97
94
  }
@@ -83,6 +83,5 @@ export class GetEnvVar extends Instruction {
83
83
  memory.set(dstOffset, getValue(this.varEnum as EnvironmentVariable, context));
84
84
 
85
85
  memory.assert({ writes: 1, addressing });
86
- context.machineState.incrementPc();
87
86
  }
88
87
  }
@@ -5,7 +5,6 @@ import { type AvmContractCallResult } from '../avm_contract_call_result.js';
5
5
  import { gasLeftToGas } from '../avm_gas.js';
6
6
  import { type Field, TypeTag, Uint1 } from '../avm_memory_types.js';
7
7
  import { AvmSimulator } from '../avm_simulator.js';
8
- import { RethrownError } from '../errors.js';
9
8
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
10
9
  import { Addressing } from './addressing_mode.js';
11
10
  import { Instruction } from './instruction.js';
@@ -65,7 +64,7 @@ abstract class ExternalCall extends Instruction {
65
64
  context.machineState.consumeGas(allocatedGas);
66
65
 
67
66
  const nestedContext = context.createNestedContractCallContext(
68
- callAddress.toFr(),
67
+ callAddress.toAztecAddress(),
69
68
  calldata,
70
69
  allocatedGas,
71
70
  callType,
@@ -76,28 +75,35 @@ abstract class ExternalCall extends Instruction {
76
75
  const nestedCallResults: AvmContractCallResult = await simulator.execute();
77
76
  const success = !nestedCallResults.reverted;
78
77
 
79
- // TRANSITIONAL: We rethrow here so that the MESSAGE gets propagated.
80
- // This means that for now, the caller cannot recover from errors.
81
- if (!success) {
82
- if (!nestedCallResults.revertReason) {
83
- throw new Error('A reverted nested call should be assigned a revert reason in the AVM execution loop');
84
- }
85
- // The nested call's revertReason will be used to track the stack of error causes down to the root.
86
- throw new RethrownError(nestedCallResults.revertReason.message, nestedCallResults.revertReason);
87
- }
88
-
89
78
  // Save return/revert data for later.
90
79
  const fullReturnData = nestedCallResults.output;
91
80
  context.machineState.nestedReturndata = fullReturnData;
92
81
 
82
+ // If the nested call reverted, we try to save the reason and the revert data.
83
+ // This will be used by the caller to try to reconstruct the call stack.
84
+ // This is only a heuristic and may not always work. It is intended to work
85
+ // for the case where a nested call reverts and the caller always rethrows
86
+ // (in Noir code).
87
+ if (!success) {
88
+ context.machineState.collectedRevertInfo = {
89
+ revertDataRepresentative: fullReturnData,
90
+ recursiveRevertReason: nestedCallResults.revertReason!,
91
+ };
92
+ }
93
+
93
94
  // Write our success flag into memory.
94
95
  memory.set(successOffset, new Uint1(success ? 1 : 0));
95
96
 
96
97
  // Refund unused gas
97
98
  context.machineState.refundGas(gasLeftToGas(nestedContext.machineState));
98
99
 
99
- // Accept the nested call's state and trace the nested call
100
- await context.persistableState.processNestedCall(
100
+ // Merge nested call's state and trace based on whether it succeeded.
101
+ if (success) {
102
+ context.persistableState.merge(nestedContext.persistableState);
103
+ } else {
104
+ context.persistableState.reject(nestedContext.persistableState);
105
+ }
106
+ await context.persistableState.traceNestedCall(
101
107
  /*nestedState=*/ nestedContext.persistableState,
102
108
  /*nestedEnvironment=*/ nestedContext.environment,
103
109
  /*startGasLeft=*/ Gas.from(allocatedGas),
@@ -107,7 +113,6 @@ abstract class ExternalCall extends Instruction {
107
113
  );
108
114
 
109
115
  memory.assert({ reads: calldataSize + 4, writes: 1, addressing });
110
- context.machineState.incrementPc();
111
116
  }
112
117
 
113
118
  public abstract override get type(): 'CALL' | 'STATICCALL';
@@ -142,22 +147,29 @@ export class Return extends Instruction {
142
147
  OperandType.UINT16,
143
148
  ];
144
149
 
145
- constructor(private indirect: number, private returnOffset: number, private copySize: number) {
150
+ constructor(private indirect: number, private returnOffset: number, private returnSizeOffset: number) {
146
151
  super();
147
152
  }
148
153
 
149
154
  public async execute(context: AvmContext): Promise<void> {
150
155
  const memory = context.machineState.memory.track(this.type);
151
- context.machineState.consumeGas(this.gasCost(this.copySize));
152
156
 
153
- const operands = [this.returnOffset];
157
+ const operands = [this.returnOffset, this.returnSizeOffset];
154
158
  const addressing = Addressing.fromWire(this.indirect, operands.length);
155
- const [returnOffset] = addressing.resolve(operands, memory);
159
+ const [returnOffset, returnSizeOffset] = addressing.resolve(operands, memory);
160
+
161
+ memory.checkTag(TypeTag.UINT32, returnSizeOffset);
162
+ const returnSize = memory.get(returnSizeOffset).toNumber();
163
+ context.machineState.consumeGas(this.gasCost(returnSize));
156
164
 
157
- const output = memory.getSlice(returnOffset, this.copySize).map(word => word.toFr());
165
+ const output = memory.getSlice(returnOffset, returnSize).map(word => word.toFr());
158
166
 
159
167
  context.machineState.return(output);
160
- memory.assert({ reads: this.copySize, addressing });
168
+ memory.assert({ reads: returnSize + 1, addressing });
169
+ }
170
+
171
+ public override handlesPC(): boolean {
172
+ return true;
161
173
  }
162
174
  }
163
175
 
@@ -197,6 +209,12 @@ export class Revert extends Instruction {
197
209
  context.machineState.revert(output);
198
210
  memory.assert({ reads: retSize + 1, addressing });
199
211
  }
212
+
213
+ // We don't want to increase the PC after reverting because it breaks messages.
214
+ // Maybe we can remove this once messages don't depend on PCs.
215
+ public override handlesPC(): boolean {
216
+ return true;
217
+ }
200
218
  }
201
219
 
202
220
  /** Returns the smaller of two bigints. */
@@ -40,7 +40,6 @@ export class Poseidon2 extends Instruction {
40
40
  );
41
41
 
42
42
  memory.assert({ reads: Poseidon2.stateSize, writes: Poseidon2.stateSize, addressing });
43
- context.machineState.incrementPc();
44
43
  }
45
44
  }
46
45
 
@@ -78,7 +77,6 @@ export class KeccakF1600 extends Instruction {
78
77
  memory.setSlice(dstOffset, res);
79
78
 
80
79
  memory.assert({ reads: inputSize, writes: inputSize, addressing });
81
- context.machineState.incrementPc();
82
80
  }
83
81
  }
84
82
 
@@ -127,6 +125,5 @@ export class Sha256Compression extends Instruction {
127
125
  memory.setSlice(outputOffset, res);
128
126
 
129
127
  memory.assert({ reads: STATE_SIZE + INPUTS_SIZE, writes: STATE_SIZE, addressing });
130
- context.machineState.incrementPc();
131
128
  }
132
129
  }
@@ -22,6 +22,13 @@ export abstract class Instruction {
22
22
  */
23
23
  public abstract execute(context: AvmContext): Promise<void>;
24
24
 
25
+ /**
26
+ * Whether the instruction will modify the PC itself.
27
+ */
28
+ public handlesPC(): boolean {
29
+ return false;
30
+ }
31
+
25
32
  /**
26
33
  * Generate a string representation of the instruction including
27
34
  * the instruction sub-class name all of its flags and operands.
@@ -72,7 +72,6 @@ export class Set extends Instruction {
72
72
  memory.set(dstOffset, res);
73
73
 
74
74
  memory.assert({ writes: 1, addressing });
75
- context.machineState.incrementPc();
76
75
  }
77
76
  }
78
77
 
@@ -113,7 +112,6 @@ export class Cast extends Instruction {
113
112
  memory.set(dstOffset, casted);
114
113
 
115
114
  memory.assert({ reads: 1, writes: 1, addressing });
116
- context.machineState.incrementPc();
117
115
  }
118
116
  }
119
117
 
@@ -152,7 +150,6 @@ export class Mov extends Instruction {
152
150
  memory.set(dstOffset, a);
153
151
 
154
152
  memory.assert({ reads: 1, writes: 1, addressing });
155
- context.machineState.incrementPc();
156
153
  }
157
154
  }
158
155
 
@@ -193,7 +190,6 @@ export class CalldataCopy extends Instruction {
193
190
  memory.setSlice(dstOffset, transformedData);
194
191
 
195
192
  memory.assert({ reads: 2, writes: copySize, addressing });
196
- context.machineState.incrementPc();
197
193
  }
198
194
  }
199
195
 
@@ -217,7 +213,6 @@ export class ReturndataSize extends Instruction {
217
213
  memory.set(dstOffset, new Uint32(context.machineState.nestedReturndata.length));
218
214
 
219
215
  memory.assert({ writes: 1, addressing });
220
- context.machineState.incrementPc();
221
216
  }
222
217
  }
223
218
 
@@ -260,6 +255,5 @@ export class ReturndataCopy extends Instruction {
260
255
  memory.setSlice(dstOffset, transformedData);
261
256
 
262
257
  memory.assert({ reads: 2, writes: copySize, addressing });
263
- context.machineState.incrementPc();
264
258
  }
265
259
  }
@@ -37,11 +37,12 @@ export class DebugLog extends Instruction {
37
37
  const addressing = Addressing.fromWire(this.indirect, operands.length);
38
38
  const [messageOffset, fieldsOffset, fieldsSizeOffset] = addressing.resolve(operands, memory);
39
39
 
40
+ memory.checkTag(TypeTag.UINT32, fieldsSizeOffset);
40
41
  const fieldsSize = memory.get(fieldsSizeOffset).toNumber();
41
42
  memory.checkTagsRange(TypeTag.UINT8, messageOffset, this.messageSize);
42
43
  memory.checkTagsRange(TypeTag.FIELD, fieldsOffset, fieldsSize);
43
44
 
44
- context.machineState.consumeGas(this.gasCost());
45
+ context.machineState.consumeGas(this.gasCost(this.messageSize + fieldsSize));
45
46
 
46
47
  const rawMessage = memory.getSlice(messageOffset, this.messageSize);
47
48
  const fields = memory.getSlice(fieldsOffset, fieldsSize);
@@ -56,6 +57,5 @@ export class DebugLog extends Instruction {
56
57
  DebugLog.logger.verbose(formattedStr);
57
58
 
58
59
  memory.assert({ reads: 1 + fieldsSize + this.messageSize, addressing });
59
- context.machineState.incrementPc();
60
60
  }
61
61
  }
@@ -2,7 +2,7 @@ import { Fq, Point } from '@aztec/circuits.js';
2
2
  import { Grumpkin } from '@aztec/circuits.js/barretenberg';
3
3
 
4
4
  import { type AvmContext } from '../avm_context.js';
5
- import { Field, TypeTag } from '../avm_memory_types.js';
5
+ import { Field, TypeTag, Uint1 } from '../avm_memory_types.js';
6
6
  import { InstructionExecutionError } from '../errors.js';
7
7
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
8
8
  import { Addressing } from './addressing_mode.js';
@@ -105,15 +105,16 @@ export class MultiScalarMul extends Instruction {
105
105
  return grumpkin.add(acc, grumpkin.mul(curr[0], curr[1]));
106
106
  }
107
107
  }, grumpkin.mul(firstBaseScalarPair[0], firstBaseScalarPair[1]));
108
- const output = outputPoint.toFields().map(f => new Field(f));
109
108
 
110
- memory.setSlice(outputOffset, output);
109
+ memory.set(outputOffset, new Field(outputPoint.x));
110
+ memory.set(outputOffset + 1, new Field(outputPoint.y));
111
+ // Check representation of infinity for grumpkin
112
+ memory.set(outputOffset + 2, new Uint1(outputPoint.equals(Point.ZERO) ? 1 : 0));
111
113
 
112
114
  memory.assert({
113
115
  reads: 1 + pointsReadLength + scalarReadLength /* points and scalars */,
114
116
  writes: 3 /* output triplet */,
115
117
  addressing,
116
118
  });
117
- context.machineState.incrementPc();
118
119
  }
119
120
  }
@@ -43,10 +43,9 @@ export class SStore extends BaseStorageInstruction {
43
43
 
44
44
  const slot = memory.get(slotOffset).toFr();
45
45
  const value = memory.get(srcOffset).toFr();
46
- context.persistableState.writeStorage(context.environment.address, slot, value);
46
+ await context.persistableState.writeStorage(context.environment.address, slot, value);
47
47
 
48
48
  memory.assert({ reads: 2, addressing });
49
- context.machineState.incrementPc();
50
49
  }
51
50
  }
52
51
 
@@ -71,7 +70,6 @@ export class SLoad extends BaseStorageInstruction {
71
70
  const value = await context.persistableState.readStorage(context.environment.address, slot);
72
71
  memory.set(dstOffset, new Field(value));
73
72
 
74
- context.machineState.incrementPc();
75
73
  memory.assert({ writes: 1, reads: 1, addressing });
76
74
  }
77
75
  }
@@ -143,12 +143,11 @@ const INSTRUCTION_SET = () =>
143
143
  [EcAdd.opcode, Instruction.deserialize.bind(EcAdd)],
144
144
  [Poseidon2.opcode, Instruction.deserialize.bind(Poseidon2)],
145
145
  [Sha256Compression.opcode, Instruction.deserialize.bind(Sha256Compression)],
146
+ [KeccakF1600.opcode, Instruction.deserialize.bind(KeccakF1600)],
146
147
  [MultiScalarMul.opcode, Instruction.deserialize.bind(MultiScalarMul)],
148
+
147
149
  // Conversions
148
150
  [ToRadixBE.opcode, Instruction.deserialize.bind(ToRadixBE)],
149
- // Future Gadgets -- pending changes in noir
150
- // SHA256COMPRESSION,
151
- [KeccakF1600.opcode, Instruction.deserialize.bind(KeccakF1600)],
152
151
  ]);
153
152
 
154
153
  /**
@@ -158,30 +157,40 @@ export function encodeToBytecode(instructions: Serializable[]): Buffer {
158
157
  return Buffer.concat(instructions.map(i => i.serialize()));
159
158
  }
160
159
 
161
- /**
162
- * Convert a buffer of bytecode into an array of instructions.
163
- * @param bytecode Buffer of bytecode.
164
- * @param instructionSet Optional {@code InstructionSet} to be used for deserialization.
165
- * @returns Bytecode decoded into an ordered array of Instructions
166
- */
160
+ // For testing only
167
161
  export function decodeFromBytecode(
168
162
  bytecode: Buffer,
169
163
  instructionSet: InstructionSet = INSTRUCTION_SET(),
170
164
  ): Instruction[] {
171
165
  const instructions: Instruction[] = [];
172
- const cursor = new BufferCursor(bytecode);
173
-
174
- while (!cursor.eof()) {
175
- const opcode: Opcode = cursor.bufferAtPosition().readUint8(); // peek.
176
- const instructionDeserializerOrUndef = instructionSet.get(opcode);
177
- if (instructionDeserializerOrUndef === undefined) {
178
- throw new Error(`Opcode ${Opcode[opcode]} (0x${opcode.toString(16)}) not implemented`);
179
- }
180
-
181
- const instructionDeserializer: InstructionDeserializer = instructionDeserializerOrUndef;
182
- const i: Instruction = instructionDeserializer(cursor);
183
- instructions.push(i);
166
+ let pc = 0;
167
+ while (pc < bytecode.length) {
168
+ const [instruction, bytesConsumed] = decodeInstructionFromBytecode(bytecode, pc, instructionSet);
169
+ instructions.push(instruction);
170
+ pc += bytesConsumed;
184
171
  }
185
-
186
172
  return instructions;
187
173
  }
174
+
175
+ // Returns the instruction and the number of bytes consumed.
176
+ export function decodeInstructionFromBytecode(
177
+ bytecode: Buffer,
178
+ pc: number,
179
+ instructionSet: InstructionSet = INSTRUCTION_SET(),
180
+ ): [Instruction, number] {
181
+ if (pc >= bytecode.length) {
182
+ throw new Error(`pc ${pc} is out of bounds for bytecode of length ${bytecode.length}`);
183
+ }
184
+ const cursor = new BufferCursor(bytecode, pc);
185
+ const startingPosition = cursor.position();
186
+ const opcode: Opcode = cursor.bufferAtPosition().readUint8(); // peek.
187
+
188
+ const instructionDeserializerOrUndef = instructionSet.get(opcode);
189
+ if (instructionDeserializerOrUndef === undefined) {
190
+ throw new Error(`Opcode ${Opcode[opcode]} (0x${opcode.toString(16)}) not implemented`);
191
+ }
192
+
193
+ const instructionDeserializer: InstructionDeserializer = instructionDeserializerOrUndef;
194
+ const instruction = instructionDeserializer(cursor);
195
+ return [instruction, cursor.position() - startingPosition];
196
+ }