@aztec/simulator 0.32.1 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +5 -3
  2. package/dest/acvm/oracle/index.d.ts +0 -1
  3. package/dest/acvm/oracle/index.d.ts.map +1 -1
  4. package/dest/acvm/oracle/index.js +1 -2
  5. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/oracle.js +2 -3
  7. package/dest/avm/avm_context.d.ts +4 -14
  8. package/dest/avm/avm_context.d.ts.map +1 -1
  9. package/dest/avm/avm_context.js +10 -22
  10. package/dest/avm/avm_gas.d.ts +71 -0
  11. package/dest/avm/avm_gas.d.ts.map +1 -0
  12. package/dest/avm/avm_gas.js +161 -0
  13. package/dest/avm/avm_machine_state.d.ts +4 -2
  14. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  15. package/dest/avm/avm_machine_state.js +8 -2
  16. package/dest/avm/avm_memory_types.d.ts +53 -1
  17. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  18. package/dest/avm/avm_memory_types.js +95 -2
  19. package/dest/avm/avm_simulator.d.ts.map +1 -1
  20. package/dest/avm/avm_simulator.js +10 -8
  21. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  22. package/dest/avm/opcodes/accrued_substate.js +44 -16
  23. package/dest/avm/opcodes/addressing_mode.d.ts +5 -3
  24. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
  25. package/dest/avm/opcodes/addressing_mode.js +5 -1
  26. package/dest/avm/opcodes/arithmetic.d.ts +7 -3
  27. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  28. package/dest/avm/opcodes/arithmetic.js +27 -16
  29. package/dest/avm/opcodes/bitwise.d.ts +21 -20
  30. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  31. package/dest/avm/opcodes/bitwise.js +43 -65
  32. package/dest/avm/opcodes/comparators.d.ts +12 -9
  33. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  34. package/dest/avm/opcodes/comparators.js +22 -32
  35. package/dest/avm/opcodes/context_getters.d.ts +20 -0
  36. package/dest/avm/opcodes/context_getters.d.ts.map +1 -0
  37. package/dest/avm/opcodes/context_getters.js +26 -0
  38. package/dest/avm/opcodes/contract.d.ts +14 -0
  39. package/dest/avm/opcodes/contract.d.ts.map +1 -0
  40. package/dest/avm/opcodes/contract.js +49 -0
  41. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  42. package/dest/avm/opcodes/control_flow.js +12 -2
  43. package/dest/avm/opcodes/environment_getters.d.ts +30 -33
  44. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  45. package/dest/avm/opcodes/environment_getters.js +34 -43
  46. package/dest/avm/opcodes/external_calls.d.ts +13 -19
  47. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  48. package/dest/avm/opcodes/external_calls.js +50 -68
  49. package/dest/avm/opcodes/hashing.d.ts +2 -1
  50. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  51. package/dest/avm/opcodes/hashing.js +37 -18
  52. package/dest/avm/opcodes/index.d.ts +1 -0
  53. package/dest/avm/opcodes/index.d.ts.map +1 -1
  54. package/dest/avm/opcodes/index.js +2 -1
  55. package/dest/avm/opcodes/instruction.d.ts +10 -15
  56. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  57. package/dest/avm/opcodes/instruction.js +12 -22
  58. package/dest/avm/opcodes/instruction_impl.d.ts +14 -0
  59. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  60. package/dest/avm/opcodes/instruction_impl.js +37 -16
  61. package/dest/avm/opcodes/memory.d.ts +4 -3
  62. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  63. package/dest/avm/opcodes/memory.js +38 -19
  64. package/dest/avm/opcodes/storage.d.ts +5 -0
  65. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  66. package/dest/avm/opcodes/storage.js +21 -7
  67. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  68. package/dest/avm/serialization/bytecode_serialization.js +7 -5
  69. package/dest/avm/serialization/instruction_serialization.d.ts +12 -11
  70. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  71. package/dest/avm/serialization/instruction_serialization.js +13 -12
  72. package/dest/avm/temporary_executor_migration.d.ts +2 -0
  73. package/dest/avm/temporary_executor_migration.d.ts.map +1 -1
  74. package/dest/avm/temporary_executor_migration.js +14 -3
  75. package/dest/client/private_execution.d.ts.map +1 -1
  76. package/dest/client/private_execution.js +6 -2
  77. package/dest/public/executor.d.ts +10 -2
  78. package/dest/public/executor.d.ts.map +1 -1
  79. package/dest/public/executor.js +59 -20
  80. package/dest/public/index.d.ts +1 -1
  81. package/dest/public/index.d.ts.map +1 -1
  82. package/package.json +15 -9
  83. package/src/acvm/oracle/index.ts +0 -1
  84. package/src/acvm/oracle/oracle.ts +1 -2
  85. package/src/avm/avm_context.ts +11 -33
  86. package/src/avm/{avm_gas_cost.ts → avm_gas.ts} +75 -21
  87. package/src/avm/avm_machine_state.ts +9 -2
  88. package/src/avm/avm_memory_types.ts +130 -2
  89. package/src/avm/avm_simulator.ts +9 -7
  90. package/src/avm/opcodes/accrued_substate.ts +57 -22
  91. package/src/avm/opcodes/addressing_mode.ts +8 -3
  92. package/src/avm/opcodes/arithmetic.ts +32 -22
  93. package/src/avm/opcodes/bitwise.ts +49 -83
  94. package/src/avm/opcodes/comparators.ts +28 -43
  95. package/src/avm/opcodes/context_getters.ts +32 -0
  96. package/src/avm/opcodes/contract.ts +58 -0
  97. package/src/avm/opcodes/control_flow.ts +23 -5
  98. package/src/avm/opcodes/environment_getters.ts +35 -44
  99. package/src/avm/opcodes/external_calls.ts +65 -84
  100. package/src/avm/opcodes/hashing.ts +45 -22
  101. package/src/avm/opcodes/index.ts +1 -0
  102. package/src/avm/opcodes/instruction.ts +14 -26
  103. package/src/avm/opcodes/instruction_impl.ts +45 -15
  104. package/src/avm/opcodes/memory.ts +48 -28
  105. package/src/avm/opcodes/storage.ts +26 -12
  106. package/src/avm/serialization/bytecode_serialization.ts +6 -3
  107. package/src/avm/serialization/instruction_serialization.ts +1 -0
  108. package/src/avm/temporary_executor_migration.ts +16 -2
  109. package/src/client/private_execution.ts +8 -2
  110. package/src/public/executor.ts +75 -22
  111. package/src/public/index.ts +2 -2
  112. package/dest/acvm/oracle/debug.d.ts +0 -19
  113. package/dest/acvm/oracle/debug.d.ts.map +0 -1
  114. package/dest/acvm/oracle/debug.js +0 -95
  115. package/dest/avm/avm_gas_cost.d.ts +0 -322
  116. package/dest/avm/avm_gas_cost.d.ts.map +0 -1
  117. package/dest/avm/avm_gas_cost.js +0 -118
  118. package/src/acvm/oracle/debug.ts +0 -109
@@ -1,19 +1,34 @@
1
+ import { type AvmContext } from '../avm_context.js';
2
+ import { type MemoryValue } from '../avm_memory_types.js';
1
3
  import { OperandType } from '../serialization/instruction_serialization.js';
2
4
  import { Instruction } from './instruction.js';
3
5
 
6
+ /** Wire format that informs deserialization for instructions with two operands. */
7
+ export const TwoOperandWireFormat = [
8
+ OperandType.UINT8,
9
+ OperandType.UINT8,
10
+ OperandType.UINT8,
11
+ OperandType.UINT32,
12
+ OperandType.UINT32,
13
+ ];
14
+
15
+ /** Wire format that informs deserialization for instructions with three operands. */
16
+ export const ThreeOperandWireFormat = [
17
+ OperandType.UINT8,
18
+ OperandType.UINT8,
19
+ OperandType.UINT8,
20
+ OperandType.UINT32,
21
+ OperandType.UINT32,
22
+ OperandType.UINT32,
23
+ ];
24
+
4
25
  /**
5
26
  * Covers (de)serialization for an instruction with:
6
27
  * indirect, inTag, and two UINT32s.
7
28
  */
8
29
  export abstract class TwoOperandInstruction extends Instruction {
9
30
  // Informs (de)serialization. See Instruction.deserialize.
10
- static readonly wireFormat: OperandType[] = [
11
- OperandType.UINT8,
12
- OperandType.UINT8,
13
- OperandType.UINT8,
14
- OperandType.UINT32,
15
- OperandType.UINT32,
16
- ];
31
+ static readonly wireFormat: OperandType[] = TwoOperandWireFormat;
17
32
 
18
33
  constructor(
19
34
  protected indirect: number,
@@ -31,14 +46,7 @@ export abstract class TwoOperandInstruction extends Instruction {
31
46
  */
32
47
  export abstract class ThreeOperandInstruction extends Instruction {
33
48
  // Informs (de)serialization. See Instruction.deserialize.
34
- static readonly wireFormat: OperandType[] = [
35
- OperandType.UINT8,
36
- OperandType.UINT8,
37
- OperandType.UINT8,
38
- OperandType.UINT32,
39
- OperandType.UINT32,
40
- OperandType.UINT32,
41
- ];
49
+ static readonly wireFormat: OperandType[] = ThreeOperandWireFormat;
42
50
 
43
51
  constructor(
44
52
  protected indirect: number,
@@ -50,3 +58,25 @@ export abstract class ThreeOperandInstruction extends Instruction {
50
58
  super();
51
59
  }
52
60
  }
61
+
62
+ export abstract class GetterInstruction extends Instruction {
63
+ // Informs (de)serialization. See Instruction.deserialize.
64
+ static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT32];
65
+
66
+ constructor(protected indirect: number, protected dstOffset: number) {
67
+ super();
68
+ }
69
+
70
+ public async execute(context: AvmContext): Promise<void> {
71
+ const memoryOperations = { writes: 1, indirect: this.indirect };
72
+ const memory = context.machineState.memory.track(this.type);
73
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
74
+
75
+ memory.set(this.dstOffset, this.getValue(context));
76
+
77
+ memory.assert(memoryOperations);
78
+ context.machineState.incrementPc();
79
+ }
80
+
81
+ protected abstract getValue(env: AvmContext): MemoryValue;
82
+ }
@@ -1,6 +1,6 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { type GasCost, GasCostConstants, getGasCostMultiplierFromTypeTag, makeGasCost } from '../avm_gas_cost.js';
3
- import { Field, TaggedMemory, TypeTag } from '../avm_memory_types.js';
2
+ import { getBaseGasCost, getMemoryGasCost, mulGas, sumGas } from '../avm_gas.js';
3
+ import { Field, type MemoryOperations, TaggedMemory, TypeTag } from '../avm_memory_types.js';
4
4
  import { InstructionExecutionError } from '../errors.js';
5
5
  import { BufferCursor } from '../serialization/buffer_cursor.js';
6
6
  import { Opcode, OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
@@ -69,21 +69,22 @@ export class Set extends Instruction {
69
69
  return new this(...args);
70
70
  }
71
71
 
72
- async execute(context: AvmContext): Promise<void> {
72
+ public async execute(context: AvmContext): Promise<void> {
73
+ const memoryOperations = { writes: 1, indirect: this.indirect };
74
+ const memory = context.machineState.memory.track(this.type);
75
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
76
+
73
77
  // Per the YP, the tag cannot be a field.
74
78
  if ([TypeTag.FIELD, TypeTag.UNINITIALIZED, TypeTag.INVALID].includes(this.inTag)) {
75
79
  throw new InstructionExecutionError(`Invalid tag ${TypeTag[this.inTag]} for SET.`);
76
80
  }
77
81
 
78
82
  const res = TaggedMemory.integralFromTag(this.value, this.inTag);
79
- context.machineState.memory.set(this.dstOffset, res);
83
+ memory.set(this.dstOffset, res);
80
84
 
85
+ memory.assert(memoryOperations);
81
86
  context.machineState.incrementPc();
82
87
  }
83
-
84
- protected gasCost(): GasCost {
85
- return makeGasCost({ l2Gas: GasCostConstants.SET_COST_PER_BYTE * getGasCostMultiplierFromTypeTag(this.inTag) });
86
- }
87
88
  }
88
89
 
89
90
  export class CMov extends Instruction {
@@ -109,14 +110,19 @@ export class CMov extends Instruction {
109
110
  super();
110
111
  }
111
112
 
112
- async execute(context: AvmContext): Promise<void> {
113
- const a = context.machineState.memory.get(this.aOffset);
114
- const b = context.machineState.memory.get(this.bOffset);
115
- const cond = context.machineState.memory.get(this.condOffset);
113
+ public async execute(context: AvmContext): Promise<void> {
114
+ const memoryOperations = { reads: 3, writes: 1, indirect: this.indirect };
115
+ const memory = context.machineState.memory.track(this.type);
116
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
117
+
118
+ const a = memory.get(this.aOffset);
119
+ const b = memory.get(this.bOffset);
120
+ const cond = memory.get(this.condOffset);
116
121
 
117
122
  // TODO: reconsider toBigInt() here
118
- context.machineState.memory.set(this.dstOffset, cond.toBigInt() > 0 ? a : b);
123
+ memory.set(this.dstOffset, cond.toBigInt() > 0 ? a : b);
119
124
 
125
+ memory.assert(memoryOperations);
120
126
  context.machineState.incrementPc();
121
127
  }
122
128
  }
@@ -129,15 +135,20 @@ export class Cast extends TwoOperandInstruction {
129
135
  super(indirect, dstTag, aOffset, dstOffset);
130
136
  }
131
137
 
132
- async execute(context: AvmContext): Promise<void> {
133
- const a = context.machineState.memory.get(this.aOffset);
138
+ public async execute(context: AvmContext): Promise<void> {
139
+ const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
140
+ const memory = context.machineState.memory.track(this.type);
141
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
142
+
143
+ const a = memory.get(this.aOffset);
134
144
 
135
145
  // TODO: consider not using toBigInt()
136
146
  const casted =
137
147
  this.inTag == TypeTag.FIELD ? new Field(a.toBigInt()) : TaggedMemory.integralFromTag(a.toBigInt(), this.inTag);
138
148
 
139
- context.machineState.memory.set(this.dstOffset, casted);
149
+ memory.set(this.dstOffset, casted);
140
150
 
151
+ memory.assert(memoryOperations);
141
152
  context.machineState.incrementPc();
142
153
  }
143
154
  }
@@ -157,16 +168,18 @@ export class Mov extends Instruction {
157
168
  super();
158
169
  }
159
170
 
160
- async execute(context: AvmContext): Promise<void> {
161
- const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
162
- [this.srcOffset, this.dstOffset],
163
- context.machineState.memory,
164
- );
171
+ public async execute(context: AvmContext): Promise<void> {
172
+ const memoryOperations = { reads: 1, writes: 1, indirect: this.indirect };
173
+ const memory = context.machineState.memory.track(this.type);
174
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
175
+
176
+ const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.srcOffset, this.dstOffset], memory);
165
177
 
166
- const a = context.machineState.memory.get(srcOffset);
178
+ const a = memory.get(srcOffset);
167
179
 
168
- context.machineState.memory.set(dstOffset, a);
180
+ memory.set(dstOffset, a);
169
181
 
182
+ memory.assert(memoryOperations);
170
183
  context.machineState.incrementPc();
171
184
  }
172
185
  }
@@ -187,19 +200,26 @@ export class CalldataCopy extends Instruction {
187
200
  super();
188
201
  }
189
202
 
190
- async execute(context: AvmContext): Promise<void> {
191
- const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], context.machineState.memory);
203
+ public async execute(context: AvmContext): Promise<void> {
204
+ const memoryOperations = { writes: this.copySize, indirect: this.indirect };
205
+ const memory = context.machineState.memory.track(this.type);
206
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
207
+
208
+ const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], memory);
192
209
 
193
210
  const transformedData = context.environment.calldata
194
211
  .slice(this.cdOffset, this.cdOffset + this.copySize)
195
212
  .map(f => new Field(f));
196
213
 
197
- context.machineState.memory.setSlice(dstOffset, transformedData);
214
+ memory.setSlice(dstOffset, transformedData);
198
215
 
216
+ memory.assert(memoryOperations);
199
217
  context.machineState.incrementPc();
200
218
  }
201
219
 
202
- protected gasCost(): GasCost {
203
- return makeGasCost({ l2Gas: GasCostConstants.CALLDATACOPY_COST_PER_BYTE * this.copySize });
220
+ protected gasCost(memoryOps: Partial<MemoryOperations & { indirect: number }> = {}) {
221
+ const baseGasCost = mulGas(getBaseGasCost(this.opcode), this.copySize);
222
+ const memoryGasCost = getMemoryGasCost(memoryOps);
223
+ return sumGas(baseGasCost, memoryGasCost);
204
224
  }
205
225
  }
@@ -1,7 +1,8 @@
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 { type Gas, getBaseGasCost, getMemoryGasCost, mulGas, sumGas } from '../avm_gas.js';
5
+ import { Field, type MemoryOperations } from '../avm_memory_types.js';
5
6
  import { InstructionExecutionError } from '../errors.js';
6
7
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
8
  import { Addressing } from './addressing_mode.js';
@@ -25,6 +26,12 @@ abstract class BaseStorageInstruction extends Instruction {
25
26
  ) {
26
27
  super();
27
28
  }
29
+
30
+ protected 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
+ }
28
35
  }
29
36
 
30
37
  export class SStore extends BaseStorageInstruction {
@@ -35,24 +42,26 @@ export class SStore extends BaseStorageInstruction {
35
42
  super(indirect, srcOffset, srcSize, slotOffset);
36
43
  }
37
44
 
38
- async execute(context: AvmContext): Promise<void> {
45
+ public async execute(context: AvmContext): Promise<void> {
39
46
  if (context.environment.isStaticCall) {
40
47
  throw new StaticCallStorageAlterError();
41
48
  }
42
49
 
43
- const [srcOffset, slotOffset] = Addressing.fromWire(this.indirect).resolve(
44
- [this.aOffset, this.bOffset],
45
- context.machineState.memory,
46
- );
50
+ const memoryOperations = { reads: this.size + 1, indirect: this.indirect };
51
+ const memory = context.machineState.memory.track(this.type);
52
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
47
53
 
48
- const slot = context.machineState.memory.get(slotOffset).toFr();
49
- const data = context.machineState.memory.getSlice(srcOffset, this.size).map(field => field.toFr());
54
+ const [srcOffset, slotOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], memory);
55
+
56
+ const slot = memory.get(slotOffset).toFr();
57
+ const data = memory.getSlice(srcOffset, this.size).map(field => field.toFr());
50
58
 
51
59
  for (const [index, value] of Object.entries(data)) {
52
60
  const adjustedSlot = slot.add(new Fr(BigInt(index)));
53
61
  context.persistableState.writeStorage(context.environment.storageAddress, adjustedSlot, value);
54
62
  }
55
63
 
64
+ memory.assert(memoryOperations);
56
65
  context.machineState.incrementPc();
57
66
  }
58
67
  }
@@ -65,13 +74,17 @@ export class SLoad extends BaseStorageInstruction {
65
74
  super(indirect, slotOffset, size, dstOffset);
66
75
  }
67
76
 
68
- async execute(context: AvmContext): Promise<void> {
77
+ public async execute(context: AvmContext): Promise<void> {
78
+ const memoryOperations = { writes: this.size, reads: 1, indirect: this.indirect };
79
+ const memory = context.machineState.memory.track(this.type);
80
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
81
+
69
82
  const [aOffset, size, bOffset] = Addressing.fromWire(this.indirect).resolve(
70
83
  [this.aOffset, this.size, this.bOffset],
71
- context.machineState.memory,
84
+ memory,
72
85
  );
73
86
 
74
- const slot = context.machineState.memory.get(aOffset);
87
+ const slot = memory.get(aOffset);
75
88
 
76
89
  // Write each read value from storage into memory
77
90
  for (let i = 0; i < size; i++) {
@@ -80,10 +93,11 @@ export class SLoad extends BaseStorageInstruction {
80
93
  new Fr(slot.toBigInt() + BigInt(i)),
81
94
  );
82
95
 
83
- context.machineState.memory.set(bOffset + i, new Field(data));
96
+ memory.set(bOffset + i, new Field(data));
84
97
  }
85
98
 
86
99
  context.machineState.incrementPc();
100
+ memory.assert(memoryOperations);
87
101
  }
88
102
  }
89
103
 
@@ -1,3 +1,4 @@
1
+ import { DAGasLeft, L1GasLeft, L2GasLeft } from '../opcodes/context_getters.js';
1
2
  import { Keccak, Pedersen, Poseidon2, Sha256 } from '../opcodes/hashing.js';
2
3
  import {
3
4
  Add,
@@ -18,6 +19,7 @@ import {
18
19
  FeePerL1Gas,
19
20
  FeePerL2Gas,
20
21
  FieldDiv,
22
+ GetContractInstance,
21
23
  InternalCall,
22
24
  InternalReturn,
23
25
  Jump,
@@ -101,9 +103,9 @@ const INSTRUCTION_SET = () =>
101
103
 
102
104
  // Machine State
103
105
  // Machine State - Gas
104
- //[L1gasleft.opcode, L1gasleft],
105
- //[L2gasleft.opcode, L2gasleft],
106
- //[Dagasleft.opcode, Dagasleft],
106
+ [L1GasLeft.opcode, L1GasLeft],
107
+ [L2GasLeft.opcode, L2GasLeft],
108
+ [DAGasLeft.opcode, DAGasLeft],
107
109
  // Machine State - Internal Control Flow
108
110
  [Jump.opcode, Jump],
109
111
  [JumpI.opcode, JumpI],
@@ -126,6 +128,7 @@ const INSTRUCTION_SET = () =>
126
128
  // Accrued Substate
127
129
  [EmitUnencryptedLog.opcode, EmitUnencryptedLog],
128
130
  [SendL2ToL1Message.opcode, SendL2ToL1Message],
131
+ [GetContractInstance.opcode, GetContractInstance],
129
132
 
130
133
  // Control Flow - Contract Calls
131
134
  [Call.opcode, Call],
@@ -64,6 +64,7 @@ export enum Opcode {
64
64
  EMITNULLIFIER,
65
65
  L1TOL2MSGEXISTS,
66
66
  HEADERMEMBER,
67
+ GETCONTRACTINSTANCE,
67
68
  EMITUNENCRYPTEDLOG,
68
69
  SENDL2TOL1MSG,
69
70
  // External calls
@@ -7,7 +7,7 @@ import {
7
7
  L2ToL1Message,
8
8
  type ReadRequest,
9
9
  SideEffect,
10
- type SideEffectLinkedToNoteHash,
10
+ SideEffectLinkedToNoteHash,
11
11
  } from '@aztec/circuits.js';
12
12
  import { Fr } from '@aztec/foundation/fields';
13
13
 
@@ -16,6 +16,7 @@ import { type PublicExecution, type PublicExecutionResult } from '../public/exec
16
16
  import { AvmExecutionEnvironment } from './avm_execution_environment.js';
17
17
  import { type AvmContractCallResults } from './avm_message_call_result.js';
18
18
  import { type JournalData } from './journal/journal.js';
19
+ import { Mov } from './opcodes/memory.js';
19
20
 
20
21
  /** Temporary Method
21
22
  *
@@ -95,7 +96,9 @@ export function temporaryConvertAvmResults(
95
96
  const nestedExecutions: PublicExecutionResult[] = [];
96
97
  const nullifierReadRequests: ReadRequest[] = [];
97
98
  const nullifierNonExistentReadRequests: ReadRequest[] = [];
98
- const newNullifiers: SideEffectLinkedToNoteHash[] = [];
99
+ const newNullifiers: SideEffectLinkedToNoteHash[] = newWorldState.newNullifiers.map(
100
+ (nullifier, i) => new SideEffectLinkedToNoteHash(nullifier.toField(), Fr.zero(), new Fr(i + 1)),
101
+ );
99
102
  const unencryptedLogs = UnencryptedFunctionL2Logs.empty();
100
103
  const newL2ToL1Messages = newWorldState.newL1Messages.map(() => L2ToL1Message.empty());
101
104
  // TODO keep track of side effect counters
@@ -120,3 +123,14 @@ export function temporaryConvertAvmResults(
120
123
  revertReason: result.revertReason ? createSimulationError(result.revertReason) : undefined,
121
124
  };
122
125
  }
126
+
127
+ export function isAvmBytecode(bytecode: Buffer): boolean {
128
+ const magicBuf = Buffer.from([
129
+ Mov.opcode, // opcode
130
+ 0x00, // indirect
131
+ ...Buffer.from('000018ca', 'hex'), // srcOffset
132
+ ...Buffer.from('000018ca', 'hex'), // dstOffset
133
+ ]);
134
+ const magicSize = magicBuf.length;
135
+ return bytecode.subarray(-magicSize).equals(magicBuf);
136
+ }
@@ -1,5 +1,5 @@
1
1
  import { type FunctionData, PrivateCallStackItem, PrivateCircuitPublicInputs } from '@aztec/circuits.js';
2
- import { type FunctionArtifactWithDebugMetadata, decodeReturnValues } from '@aztec/foundation/abi';
2
+ import { type AbiType, type FunctionArtifactWithDebugMetadata, decodeReturnValues } from '@aztec/foundation/abi';
3
3
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
4
4
  import { Fr } from '@aztec/foundation/fields';
5
5
  import { createDebugLogger } from '@aztec/foundation/log';
@@ -52,7 +52,13 @@ export async function executePrivateFunction(
52
52
  publicInputs.unencryptedLogPreimagesLength = new Fr(unencryptedLogs.getSerializedLength());
53
53
 
54
54
  const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs);
55
- const returnValues = decodeReturnValues(artifact, publicInputs.returnValues);
55
+
56
+ // Mocking the return type to be an array of 4 fields
57
+ // TODO: @LHerskind must be updated as we are progressing with the macros to get the information
58
+ const returnTypes: AbiType[] = [{ kind: 'array', length: 4, type: { kind: 'field' } }];
59
+ const mockArtifact = { ...artifact, returnTypes };
60
+ const returnValues = decodeReturnValues(mockArtifact, publicInputs.returnValues);
61
+
56
62
  const noteHashReadRequestPartialWitnesses = context.getNoteHashReadRequestPartialWitnesses(
57
63
  publicInputs.noteHashReadRequests,
58
64
  );
@@ -13,6 +13,7 @@ import { AvmSimulator } from '../avm/avm_simulator.js';
13
13
  import { HostStorage } from '../avm/journal/host_storage.js';
14
14
  import { AvmPersistableStateManager } from '../avm/journal/index.js';
15
15
  import {
16
+ isAvmBytecode,
16
17
  temporaryConvertAvmResults,
17
18
  temporaryCreateAvmExecutionEnvironment,
18
19
  } from '../avm/temporary_executor_migration.js';
@@ -166,6 +167,7 @@ export class PublicExecutor {
166
167
  private readonly header: Header,
167
168
  ) {}
168
169
 
170
+ private readonly log = createDebugLogger('aztec:simulator:public_executor');
169
171
  /**
170
172
  * Executes a public execution request.
171
173
  * @param execution - The execution to run.
@@ -176,6 +178,30 @@ export class PublicExecutor {
176
178
  execution: PublicExecution,
177
179
  globalVariables: GlobalVariables,
178
180
  sideEffectCounter: number = 0,
181
+ ): Promise<PublicExecutionResult> {
182
+ const selector = execution.functionData.selector;
183
+ const bytecode = await this.contractsDb.getBytecode(execution.contractAddress, selector);
184
+ if (!bytecode) {
185
+ throw new Error(`Bytecode not found for ${execution.contractAddress}:${selector}`);
186
+ }
187
+
188
+ if (isAvmBytecode(bytecode)) {
189
+ return await this.simulateAvm(execution, globalVariables, sideEffectCounter);
190
+ } else {
191
+ return await this.simulateAcvm(execution, globalVariables, sideEffectCounter);
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Executes a public execution request with the ACVM.
197
+ * @param execution - The execution to run.
198
+ * @param globalVariables - The global variables to use.
199
+ * @returns The result of the run plus all nested runs.
200
+ */
201
+ private async simulateAcvm(
202
+ execution: PublicExecution,
203
+ globalVariables: GlobalVariables,
204
+ sideEffectCounter: number = 0,
179
205
  ): Promise<PublicExecutionResult> {
180
206
  const selector = execution.functionData.selector;
181
207
  const acir = await this.contractsDb.getBytecode(execution.contractAddress, selector);
@@ -214,12 +240,12 @@ export class PublicExecutor {
214
240
  }
215
241
 
216
242
  /**
217
- * Executes a public execution request in the avm.
243
+ * Executes a public execution request in the AVM.
218
244
  * @param execution - The execution to run.
219
245
  * @param globalVariables - The global variables to use.
220
246
  * @returns The result of the run plus all nested runs.
221
247
  */
222
- public async simulateAvm(
248
+ private async simulateAvm(
223
249
  execution: PublicExecution,
224
250
  globalVariables: GlobalVariables,
225
251
  _sideEffectCounter = 0,
@@ -230,13 +256,14 @@ export class PublicExecutor {
230
256
  const worldStateJournal = new AvmPersistableStateManager(hostStorage);
231
257
  const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
232
258
  // TODO(@spalladino) Load initial gas from the public execution request
233
- const machineState = new AvmMachineState(100_000, 100_000, 100_000);
259
+ const machineState = new AvmMachineState(1e10, 1e10, 1e10);
234
260
 
235
261
  const context = new AvmContext(worldStateJournal, executionEnv, machineState);
236
262
  const simulator = new AvmSimulator(context);
237
263
 
238
264
  const result = await simulator.execute();
239
265
  const newWorldState = context.persistableState.flush();
266
+
240
267
  // TODO(@spalladino) Read gas left from machineState and return it
241
268
  return temporaryConvertAvmResults(execution, newWorldState, result);
242
269
  }
@@ -260,6 +287,7 @@ export class PublicExecutor {
260
287
  const artifactsPath = path.resolve('target');
261
288
 
262
289
  // Create the directory if it does not exist
290
+ await fs.rm(artifactsPath, { recursive: true, force: true });
263
291
  await fs.mkdir(artifactsPath, { recursive: true });
264
292
 
265
293
  const calldataPath = path.join(artifactsPath, 'calldata.bin');
@@ -269,34 +297,54 @@ export class PublicExecutor {
269
297
  const { args, functionData, contractAddress } = avmExecution;
270
298
  const bytecode = await this.contractsDb.getBytecode(contractAddress, functionData.selector);
271
299
  // Write call data and bytecode to files.
272
- await Promise.all([
273
- fs.writeFile(
274
- calldataPath,
275
- args.map(c => c.toBuffer()),
276
- ),
277
- fs.writeFile(bytecodePath, bytecode!),
278
- ]);
279
-
280
- const bbBinary = spawn(path.join(bbPath, 'build', 'bin', 'bb'), [
281
- 'avm_prove',
282
- '-b',
283
- bytecodePath,
284
- '-d',
300
+ await fs.writeFile(
285
301
  calldataPath,
286
- '-o',
287
- proofPath,
288
- ]);
302
+ args.map(c => c.toBuffer()),
303
+ );
304
+ await fs.writeFile(bytecodePath, bytecode!);
305
+
306
+ const bbExec = path.join(bbPath, 'build', 'bin', 'bb');
307
+ const bbArgs = ['avm_prove', '-b', bytecodePath, '-d', calldataPath, '-o', proofPath];
308
+ this.log(`calling '${bbExec} ${bbArgs.join(' ')}'`);
309
+ const bbBinary = spawn(bbExec, bbArgs);
310
+
289
311
  // The binary writes the proof and the verification key to the write path.
290
312
  return new Promise((resolve, reject) => {
313
+ let stdout: string = '';
314
+ let stderr: string = '';
315
+
291
316
  bbBinary.on('close', () => {
292
- resolve(Promise.all([fs.readFile(proofPath), fs.readFile(path.join(artifactsPath, 'vk'))]));
317
+ this.log(`Proof generation complete. Reading proof and vk from ${proofPath}.`);
318
+ return resolve(Promise.all([fs.readFile(proofPath), fs.readFile(path.join(artifactsPath, 'vk'))]));
319
+ });
320
+
321
+ // Catch stdout.
322
+ bbBinary.stdout.on('data', (data: Buffer) => {
323
+ stdout += data.toString();
293
324
  });
325
+ bbBinary.stdout.on('end', () => {
326
+ if (stdout.length > 0) {
327
+ this.log(`stdout: ${stdout}`);
328
+ }
329
+ });
330
+
331
+ // Catch stderr.
332
+ bbBinary.stderr.on('data', (data: Buffer) => {
333
+ stderr += data.toString();
334
+ });
335
+ bbBinary.stderr.on('end', () => {
336
+ if (stderr.length > 0) {
337
+ this.log(`stderr: ${stderr}`);
338
+ }
339
+ });
340
+
294
341
  // Catch and propagate errors from spawning
295
342
  bbBinary.on('error', err => {
296
343
  reject(err);
297
344
  });
298
345
  });
299
346
  }
347
+
300
348
  /**
301
349
  * Verifies an AVM proof. This function is currently only used for testing purposes, as verification
302
350
  * is not fully complete in the AVM yet.
@@ -313,9 +361,14 @@ export class PublicExecutor {
313
361
  const proofPath = path.join(artifactsPath, 'proof');
314
362
 
315
363
  // Write the verification key and the proof to files.
316
- await Promise.all([fs.writeFile(vkPath, vk), fs.writeFile(proofPath, proof)]);
364
+ await fs.writeFile(vkPath, vk);
365
+ await fs.writeFile(proofPath, proof);
366
+
367
+ const bbExec = path.join(bbPath, 'build', 'bin', 'bb');
368
+ const bbArgs = ['avm_verify', '-p', proofPath];
369
+ this.log(`calling '${bbPath} ${bbArgs.join(' ')}'`);
370
+ const bbBinary = spawn(bbExec, bbArgs);
317
371
 
318
- const bbBinary = spawn(path.join(bbPath, 'build', 'bin', 'bb'), ['avm_verify', '-p', proofPath]);
319
372
  // The binary prints to stdout 1 if the proof is valid and 0 if it is not.
320
373
  return new Promise((resolve, reject) => {
321
374
  let result = Buffer.alloc(0);
@@ -1,7 +1,7 @@
1
1
  export * from './db.js';
2
2
  export {
3
- PublicExecution,
4
- PublicExecutionResult,
3
+ type PublicExecution,
4
+ type PublicExecutionResult,
5
5
  isPublicExecutionResult,
6
6
  collectPublicDataReads,
7
7
  collectPublicDataUpdateRequests,
@@ -1,19 +0,0 @@
1
- import { type ForeignCallInput } from '@noir-lang/acvm_js';
2
- import { type ACVMField } from '../acvm_types.js';
3
- /**
4
- * Convert an array of ACVMFields to a string.
5
- *
6
- * @param msg - array of ACVMFields where each represents a single ascii character
7
- * @returns string representation of the message
8
- */
9
- export declare function acvmFieldMessageToString(msg: ACVMField[]): string;
10
- /**
11
- * Convert an array of ACVMFields from ACVM to a formatted string.
12
- *
13
- * @param parameters - either one parameter representing a simple field or array, or two parameters when
14
- * It's a message without args or three parameters when it's a message with arguments.
15
- *
16
- * @returns formatted string
17
- */
18
- export declare function oracleDebugCallToFormattedStr(parameters: ForeignCallInput[]): string;
19
- //# sourceMappingURL=debug.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/acvm/oracle/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,MAAM,CAajE;AAyBD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAcpF"}