@aztec/simulator 0.52.0 → 0.54.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 (92) hide show
  1. package/dest/acvm/acvm.d.ts +7 -0
  2. package/dest/acvm/acvm.d.ts.map +1 -1
  3. package/dest/acvm/acvm.js +17 -1
  4. package/dest/avm/avm_execution_environment.d.ts +2 -2
  5. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  6. package/dest/avm/avm_execution_environment.js +5 -6
  7. package/dest/avm/avm_gas.d.ts.map +1 -1
  8. package/dest/avm/avm_gas.js +73 -43
  9. package/dest/avm/avm_memory_types.d.ts +1 -1
  10. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  11. package/dest/avm/avm_memory_types.js +5 -3
  12. package/dest/avm/bytecode_utils.js +5 -5
  13. package/dest/avm/errors.js +2 -2
  14. package/dest/avm/fixtures/index.d.ts +2 -0
  15. package/dest/avm/fixtures/index.d.ts.map +1 -1
  16. package/dest/avm/fixtures/index.js +18 -2
  17. package/dest/avm/journal/journal.d.ts +1 -1
  18. package/dest/avm/journal/journal.d.ts.map +1 -1
  19. package/dest/avm/journal/journal.js +13 -8
  20. package/dest/avm/opcodes/arithmetic.d.ts +9 -16
  21. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  22. package/dest/avm/opcodes/arithmetic.js +12 -37
  23. package/dest/avm/opcodes/bitwise.d.ts +5 -5
  24. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  25. package/dest/avm/opcodes/bitwise.js +6 -6
  26. package/dest/avm/opcodes/comparators.d.ts +3 -3
  27. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  28. package/dest/avm/opcodes/comparators.js +4 -4
  29. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  30. package/dest/avm/opcodes/control_flow.js +6 -6
  31. package/dest/avm/opcodes/instruction.d.ts +18 -12
  32. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  33. package/dest/avm/opcodes/instruction.js +36 -19
  34. package/dest/avm/opcodes/instruction_impl.d.ts +4 -2
  35. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  36. package/dest/avm/opcodes/instruction_impl.js +15 -7
  37. package/dest/avm/opcodes/memory.d.ts +11 -12
  38. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  39. package/dest/avm/opcodes/memory.js +68 -68
  40. package/dest/avm/serialization/bytecode_serialization.d.ts +7 -8
  41. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  42. package/dest/avm/serialization/bytecode_serialization.js +83 -67
  43. package/dest/avm/serialization/instruction_serialization.d.ts +84 -68
  44. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  45. package/dest/avm/serialization/instruction_serialization.js +102 -71
  46. package/dest/avm/test_utils.d.ts +1 -1
  47. package/dest/avm/test_utils.d.ts.map +1 -1
  48. package/dest/avm/test_utils.js +11 -3
  49. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  50. package/dest/public/abstract_phase_manager.js +4 -4
  51. package/dest/public/db_interfaces.d.ts +6 -0
  52. package/dest/public/db_interfaces.d.ts.map +1 -1
  53. package/dest/public/execution.d.ts +3 -3
  54. package/dest/public/execution.d.ts.map +1 -1
  55. package/dest/public/execution.js +1 -1
  56. package/dest/public/hints_builder.d.ts +6 -4
  57. package/dest/public/hints_builder.d.ts.map +1 -1
  58. package/dest/public/hints_builder.js +20 -5
  59. package/dest/public/public_db_sources.d.ts +1 -0
  60. package/dest/public/public_db_sources.d.ts.map +1 -1
  61. package/dest/public/public_db_sources.js +11 -1
  62. package/dest/public/side_effect_trace.d.ts +2 -2
  63. package/dest/public/side_effect_trace.d.ts.map +1 -1
  64. package/dest/public/side_effect_trace.js +10 -12
  65. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  66. package/dest/public/tail_phase_manager.js +4 -3
  67. package/package.json +9 -9
  68. package/src/acvm/acvm.ts +22 -0
  69. package/src/avm/avm_execution_environment.ts +3 -4
  70. package/src/avm/avm_gas.ts +72 -42
  71. package/src/avm/avm_memory_types.ts +4 -2
  72. package/src/avm/bytecode_utils.ts +4 -4
  73. package/src/avm/errors.ts +1 -1
  74. package/src/avm/fixtures/index.ts +32 -2
  75. package/src/avm/journal/journal.ts +14 -8
  76. package/src/avm/opcodes/arithmetic.ts +12 -41
  77. package/src/avm/opcodes/bitwise.ts +5 -5
  78. package/src/avm/opcodes/comparators.ts +3 -3
  79. package/src/avm/opcodes/control_flow.ts +5 -5
  80. package/src/avm/opcodes/instruction.ts +41 -19
  81. package/src/avm/opcodes/instruction_impl.ts +14 -6
  82. package/src/avm/opcodes/memory.ts +76 -74
  83. package/src/avm/serialization/bytecode_serialization.ts +93 -77
  84. package/src/avm/serialization/instruction_serialization.ts +58 -25
  85. package/src/avm/test_utils.ts +9 -2
  86. package/src/public/abstract_phase_manager.ts +3 -2
  87. package/src/public/db_interfaces.ts +7 -0
  88. package/src/public/execution.ts +3 -2
  89. package/src/public/hints_builder.ts +48 -13
  90. package/src/public/public_db_sources.ts +11 -0
  91. package/src/public/side_effect_trace.ts +11 -12
  92. package/src/public/tail_phase_manager.ts +10 -7
@@ -1,39 +1,57 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { Field, TaggedMemory, TypeTag } from '../avm_memory_types.js';
3
- import { InstructionExecutionError } from '../errors.js';
4
- import { BufferCursor } from '../serialization/buffer_cursor.js';
5
- import { Opcode, OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
2
+ import { Field, TaggedMemory } from '../avm_memory_types.js';
3
+ import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
6
4
  import { Addressing } from './addressing_mode.js';
7
5
  import { Instruction } from './instruction.js';
8
6
  import { TwoOperandInstruction } from './instruction_impl.js';
9
7
 
10
- const TAG_TO_OPERAND_TYPE = new Map<TypeTag, OperandType>([
11
- [TypeTag.UINT8, OperandType.UINT8],
12
- [TypeTag.UINT16, OperandType.UINT16],
13
- [TypeTag.UINT32, OperandType.UINT32],
14
- [TypeTag.UINT64, OperandType.UINT64],
15
- [TypeTag.UINT128, OperandType.UINT128],
16
- ]);
17
-
18
- function getOperandTypeFromInTag(inTag: number | bigint): OperandType {
19
- inTag = inTag as number;
20
- const tagOperandType = TAG_TO_OPERAND_TYPE.get(inTag);
21
- if (tagOperandType === undefined) {
22
- throw new Error(`Invalid tag ${inTag} for SET.`);
23
- }
24
- return tagOperandType;
25
- }
26
-
27
8
  export class Set extends Instruction {
28
9
  static readonly type: string = 'SET';
29
- static readonly opcode: Opcode = Opcode.SET;
30
-
31
- private static readonly wireFormatBeforeConst: OperandType[] = [
32
- OperandType.UINT8,
33
- OperandType.UINT8,
34
- OperandType.UINT8,
10
+ // Required for gas.
11
+ static readonly opcode: Opcode = Opcode.SET_8;
12
+
13
+ public static readonly wireFormat8: OperandType[] = [
14
+ OperandType.UINT8, // opcode
15
+ OperandType.UINT8, // indirect
16
+ OperandType.UINT8, // tag
17
+ OperandType.UINT8, // const (value)
18
+ OperandType.UINT8, // dstOffset
19
+ ];
20
+ public static readonly wireFormat16: OperandType[] = [
21
+ OperandType.UINT8, // opcode
22
+ OperandType.UINT8, // indirect
23
+ OperandType.UINT8, // tag
24
+ OperandType.UINT16, // const (value)
25
+ OperandType.UINT16, // dstOffset
26
+ ];
27
+ public static readonly wireFormat32: OperandType[] = [
28
+ OperandType.UINT8, // opcode
29
+ OperandType.UINT8, // indirect
30
+ OperandType.UINT8, // tag
31
+ OperandType.UINT32, // const (value)
32
+ OperandType.UINT16, // dstOffset
33
+ ];
34
+ public static readonly wireFormat64: OperandType[] = [
35
+ OperandType.UINT8, // opcode
36
+ OperandType.UINT8, // indirect
37
+ OperandType.UINT8, // tag
38
+ OperandType.UINT64, // const (value)
39
+ OperandType.UINT16, // dstOffset
40
+ ];
41
+ public static readonly wireFormat128: OperandType[] = [
42
+ OperandType.UINT8, // opcode
43
+ OperandType.UINT8, // indirect
44
+ OperandType.UINT8, // tag
45
+ OperandType.UINT128, // const (value)
46
+ OperandType.UINT16, // dstOffset
47
+ ];
48
+ public static readonly wireFormatFF: OperandType[] = [
49
+ OperandType.UINT8, // opcode
50
+ OperandType.UINT8, // indirect
51
+ OperandType.UINT8, // tag
52
+ OperandType.FF, // const (value)
53
+ OperandType.UINT16, // dstOffset
35
54
  ];
36
- private static readonly wireFormatAfterConst: OperandType[] = [OperandType.UINT32];
37
55
 
38
56
  constructor(
39
57
  private indirect: number,
@@ -44,42 +62,13 @@ export class Set extends Instruction {
44
62
  super();
45
63
  }
46
64
 
47
- /** We need to use a custom serialize function because of the variable length of the value. */
48
- public override serialize(): Buffer {
49
- const format: OperandType[] = [
50
- ...Set.wireFormatBeforeConst,
51
- getOperandTypeFromInTag(this.inTag),
52
- ...Set.wireFormatAfterConst,
53
- ];
54
- return serialize(format, this);
55
- }
56
-
57
- /** We need to use a custom deserialize function because of the variable length of the value. */
58
- public static override deserialize(this: typeof Set, buf: BufferCursor | Buffer): Set {
59
- if (buf instanceof Buffer) {
60
- buf = new BufferCursor(buf);
61
- }
62
- const beforeConst = deserialize(buf, Set.wireFormatBeforeConst);
63
- const tag = beforeConst[beforeConst.length - 1];
64
- const val = deserialize(buf, [getOperandTypeFromInTag(tag)]);
65
- const afterConst = deserialize(buf, Set.wireFormatAfterConst);
66
- const res = [...beforeConst, ...val, ...afterConst];
67
- const args = res.slice(1) as ConstructorParameters<typeof Set>; // Remove opcode.
68
- return new this(...args);
69
- }
70
-
71
65
  public async execute(context: AvmContext): Promise<void> {
72
66
  const memoryOperations = { writes: 1, indirect: this.indirect };
73
67
  const memory = context.machineState.memory.track(this.type);
74
68
  context.machineState.consumeGas(this.gasCost(memoryOperations));
75
69
 
76
- // Per the YP, the tag cannot be a field.
77
- if ([TypeTag.FIELD, TypeTag.UNINITIALIZED, TypeTag.INVALID].includes(this.inTag)) {
78
- throw new InstructionExecutionError(`Invalid tag ${TypeTag[this.inTag]} for SET.`);
79
- }
80
70
  const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], memory);
81
-
82
- const res = TaggedMemory.integralFromTag(this.value, this.inTag);
71
+ const res = TaggedMemory.buildFromTagTruncating(this.value, this.inTag);
83
72
  memory.set(dstOffset, res);
84
73
 
85
74
  memory.assert(memoryOperations);
@@ -148,9 +137,7 @@ export class Cast extends TwoOperandInstruction {
148
137
  const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.dstOffset], memory);
149
138
 
150
139
  const a = memory.get(srcOffset);
151
-
152
- const casted =
153
- this.inTag == TypeTag.FIELD ? new Field(a.toBigInt()) : TaggedMemory.integralFromTag(a.toBigInt(), this.inTag);
140
+ const casted = TaggedMemory.buildFromTagTruncating(a.toBigInt(), this.inTag);
154
141
 
155
142
  memory.set(dstOffset, casted);
156
143
 
@@ -161,13 +148,20 @@ export class Cast extends TwoOperandInstruction {
161
148
 
162
149
  export class Mov extends Instruction {
163
150
  static readonly type: string = 'MOV';
164
- static readonly opcode: Opcode = Opcode.MOV;
165
- // Informs (de)serialization. See Instruction.deserialize.
166
- static readonly wireFormat: OperandType[] = [
151
+ // FIXME: This is needed for gas.
152
+ static readonly opcode: Opcode = Opcode.MOV_8;
153
+
154
+ static readonly wireFormat8: OperandType[] = [
167
155
  OperandType.UINT8,
168
156
  OperandType.UINT8,
169
- OperandType.UINT32,
170
- OperandType.UINT32,
157
+ OperandType.UINT8,
158
+ OperandType.UINT8,
159
+ ];
160
+ static readonly wireFormat16: OperandType[] = [
161
+ OperandType.UINT8,
162
+ OperandType.UINT8,
163
+ OperandType.UINT16,
164
+ OperandType.UINT16,
171
165
  ];
172
166
 
173
167
  constructor(private indirect: number, private srcOffset: number, private dstOffset: number) {
@@ -202,21 +196,29 @@ export class CalldataCopy extends Instruction {
202
196
  OperandType.UINT32,
203
197
  ];
204
198
 
205
- constructor(private indirect: number, private cdOffset: number, private copySize: number, private dstOffset: number) {
199
+ constructor(
200
+ private indirect: number,
201
+ private cdStartOffset: number,
202
+ private copySizeOffset: number,
203
+ private dstOffset: number,
204
+ ) {
206
205
  super();
207
206
  }
208
207
 
209
208
  public async execute(context: AvmContext): Promise<void> {
210
- const memoryOperations = { writes: this.copySize, indirect: this.indirect };
211
209
  const memory = context.machineState.memory.track(this.type);
212
- context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: this.copySize }));
213
-
214
210
  // 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.
215
- const [cdOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.cdOffset, this.dstOffset], memory);
211
+ const [cdStartOffset, copySizeOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
212
+ [this.cdStartOffset, this.copySizeOffset, this.dstOffset],
213
+ memory,
214
+ );
215
+
216
+ const cdStart = memory.get(cdStartOffset).toNumber();
217
+ const copySize = memory.get(copySizeOffset).toNumber();
218
+ const memoryOperations = { reads: 2, writes: copySize, indirect: this.indirect };
219
+ context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: copySize }));
216
220
 
217
- const transformedData = context.environment.calldata
218
- .slice(cdOffset, cdOffset + this.copySize)
219
- .map(f => new Field(f));
221
+ const transformedData = context.environment.calldata.slice(cdStart, cdStart + copySize).map(f => new Field(f));
220
222
 
221
223
  memory.setSlice(dstOffset, transformedData);
222
224
 
@@ -2,7 +2,7 @@ import { PedersenCommitment } from '../opcodes/commitment.js';
2
2
  import { DAGasLeft, L2GasLeft } from '../opcodes/context_getters.js';
3
3
  import { EcAdd } from '../opcodes/ec_add.js';
4
4
  import { Keccak, KeccakF1600, Pedersen, Poseidon2, Sha256 } from '../opcodes/hashing.js';
5
- import type { Instruction } from '../opcodes/index.js';
5
+ import { Instruction } from '../opcodes/index.js';
6
6
  import {
7
7
  Add,
8
8
  Address,
@@ -59,106 +59,122 @@ import { MultiScalarMul } from '../opcodes/multi_scalar_mul.js';
59
59
  import { BufferCursor } from './buffer_cursor.js';
60
60
  import { Opcode } from './instruction_serialization.js';
61
61
 
62
- interface DeserializableInstruction {
63
- deserialize(buf: BufferCursor | Buffer): Instruction;
64
- opcode: Opcode;
62
+ export type InstructionDeserializer = (buf: BufferCursor | Buffer) => Instruction;
63
+
64
+ export interface Serializable {
65
+ serialize(): Buffer;
66
+ }
67
+
68
+ export interface Deserializable {
69
+ deserialize: InstructionDeserializer;
65
70
  }
66
71
 
67
- export type InstructionSet = Map<Opcode, DeserializableInstruction>;
72
+ export type InstructionSet = Map<Opcode, InstructionDeserializer>;
68
73
  // TODO(4359): This is a function so that Call and StaticCall can be lazily resolved.
69
74
  // This is a temporary solution until we solve the dependency cycle.
70
75
  const INSTRUCTION_SET = () =>
71
- new Map<Opcode, DeserializableInstruction>([
72
- [Add.opcode, Add],
73
- [Sub.opcode, Sub],
74
- [Mul.opcode, Mul],
75
- [Div.opcode, Div],
76
- [FieldDiv.opcode, FieldDiv],
77
- [Eq.opcode, Eq],
78
- [Lt.opcode, Lt],
79
- [Lte.opcode, Lte],
80
- [And.opcode, And],
81
- [Or.opcode, Or],
82
- [Xor.opcode, Xor],
83
- [Not.opcode, Not],
84
- [Shl.opcode, Shl],
85
- [Shr.opcode, Shr],
86
- [Cast.opcode, Cast],
87
- [Address.opcode, Address],
88
- [StorageAddress.opcode, StorageAddress],
89
- [Sender.opcode, Sender],
90
- [FunctionSelector.opcode, FunctionSelector],
91
- [TransactionFee.opcode, TransactionFee],
76
+ new Map<Opcode, InstructionDeserializer>([
77
+ [Opcode.ADD_8, Add.as(Add.wireFormat8).deserialize],
78
+ [Opcode.ADD_16, Add.as(Add.wireFormat16).deserialize],
79
+ [Opcode.SUB_8, Sub.as(Sub.wireFormat8).deserialize],
80
+ [Opcode.SUB_16, Sub.as(Sub.wireFormat16).deserialize],
81
+ [Opcode.MUL_8, Mul.as(Mul.wireFormat8).deserialize],
82
+ [Opcode.MUL_16, Mul.as(Mul.wireFormat16).deserialize],
83
+ [Opcode.DIV_8, Div.as(Div.wireFormat8).deserialize],
84
+ [Opcode.DIV_16, Div.as(Div.wireFormat16).deserialize],
85
+ [Opcode.FDIV_8, FieldDiv.as(FieldDiv.wireFormat8).deserialize],
86
+ [Opcode.FDIV_16, FieldDiv.as(FieldDiv.wireFormat16).deserialize],
87
+ [Opcode.EQ_8, Eq.as(Eq.wireFormat8).deserialize],
88
+ [Opcode.EQ_16, Eq.as(Eq.wireFormat16).deserialize],
89
+ [Opcode.LT_8, Lt.as(Lt.wireFormat8).deserialize],
90
+ [Opcode.LT_16, Lt.as(Lt.wireFormat16).deserialize],
91
+ [Opcode.LTE_8, Lte.as(Lte.wireFormat8).deserialize],
92
+ [Opcode.LTE_16, Lte.as(Lte.wireFormat16).deserialize],
93
+ [Opcode.AND_8, And.as(And.wireFormat8).deserialize],
94
+ [Opcode.AND_16, And.as(And.wireFormat16).deserialize],
95
+ [Opcode.OR_8, Or.as(Or.wireFormat8).deserialize],
96
+ [Opcode.OR_16, Or.as(Or.wireFormat16).deserialize],
97
+ [Opcode.XOR_8, Xor.as(Xor.wireFormat8).deserialize],
98
+ [Opcode.XOR_16, Xor.as(Xor.wireFormat16).deserialize],
99
+ [Not.opcode, Instruction.deserialize.bind(Not)],
100
+ [Opcode.SHL_8, Shl.as(Shl.wireFormat8).deserialize],
101
+ [Opcode.SHL_16, Shl.as(Shl.wireFormat16).deserialize],
102
+ [Opcode.SHR_8, Shr.as(Shr.wireFormat8).deserialize],
103
+ [Opcode.SHR_16, Shr.as(Shr.wireFormat16).deserialize],
104
+ [Cast.opcode, Instruction.deserialize.bind(Cast)],
105
+ [Address.opcode, Instruction.deserialize.bind(Address)],
106
+ [StorageAddress.opcode, Instruction.deserialize.bind(StorageAddress)],
107
+ [Sender.opcode, Instruction.deserialize.bind(Sender)],
108
+ [FunctionSelector.opcode, Instruction.deserialize.bind(FunctionSelector)],
109
+ [TransactionFee.opcode, Instruction.deserialize.bind(TransactionFee)],
92
110
  // Execution Environment - Globals
93
- [ChainId.opcode, ChainId],
94
- [Version.opcode, Version],
95
- [BlockNumber.opcode, BlockNumber],
96
- [Timestamp.opcode, Timestamp],
97
- //[Coinbase.opcode, Coinbase],
98
- [FeePerL2Gas.opcode, FeePerL2Gas],
99
- [FeePerDAGas.opcode, FeePerDAGas],
100
- //[Blockl2gaslimit.opcode, Blockl2gaslimit],
101
- //[Blockdagaslimit.opcode, Blockdagaslimit],
111
+ [ChainId.opcode, Instruction.deserialize.bind(ChainId)],
112
+ [Version.opcode, Instruction.deserialize.bind(Version)],
113
+ [BlockNumber.opcode, Instruction.deserialize.bind(BlockNumber)],
114
+ [Timestamp.opcode, Instruction.deserialize.bind(Timestamp)],
115
+ [FeePerL2Gas.opcode, Instruction.deserialize.bind(FeePerL2Gas)],
116
+ [FeePerDAGas.opcode, Instruction.deserialize.bind(FeePerDAGas)],
102
117
  // Execution Environment - Calldata
103
- [CalldataCopy.opcode, CalldataCopy],
118
+ [CalldataCopy.opcode, Instruction.deserialize.bind(CalldataCopy)],
104
119
 
105
120
  // Machine State
106
121
  // Machine State - Gas
107
- [L2GasLeft.opcode, L2GasLeft],
108
- [DAGasLeft.opcode, DAGasLeft],
122
+ [L2GasLeft.opcode, Instruction.deserialize.bind(L2GasLeft)],
123
+ [DAGasLeft.opcode, Instruction.deserialize.bind(DAGasLeft)],
109
124
  // Machine State - Internal Control Flow
110
- [Jump.opcode, Jump],
111
- [JumpI.opcode, JumpI],
112
- [InternalCall.opcode, InternalCall],
113
- [InternalReturn.opcode, InternalReturn],
114
- [Set.opcode, Set],
115
- [Mov.opcode, Mov],
116
- [CMov.opcode, CMov],
125
+ [Jump.opcode, Instruction.deserialize.bind(Jump)],
126
+ [JumpI.opcode, Instruction.deserialize.bind(JumpI)],
127
+ [InternalCall.opcode, Instruction.deserialize.bind(InternalCall)],
128
+ [InternalReturn.opcode, Instruction.deserialize.bind(InternalReturn)],
129
+ [Opcode.SET_8, Set.as(Set.wireFormat8).deserialize],
130
+ [Opcode.SET_16, Set.as(Set.wireFormat16).deserialize],
131
+ [Opcode.SET_32, Set.as(Set.wireFormat32).deserialize],
132
+ [Opcode.SET_64, Set.as(Set.wireFormat64).deserialize],
133
+ [Opcode.SET_128, Set.as(Set.wireFormat128).deserialize],
134
+ [Opcode.SET_FF, Set.as(Set.wireFormatFF).deserialize],
135
+ [Opcode.MOV_8, Mov.as(Mov.wireFormat8).deserialize],
136
+ [Opcode.MOV_16, Mov.as(Mov.wireFormat16).deserialize],
137
+ [CMov.opcode, Instruction.deserialize.bind(CMov)],
117
138
 
118
139
  // World State
119
- [SLoad.opcode, SLoad], // Public Storage
120
- [SStore.opcode, SStore], // Public Storage
121
- [NoteHashExists.opcode, NoteHashExists], // Notes & Nullifiers
122
- [EmitNoteHash.opcode, EmitNoteHash], // Notes & Nullifiers
123
- [NullifierExists.opcode, NullifierExists], // Notes & Nullifiers
124
- [EmitNullifier.opcode, EmitNullifier], // Notes & Nullifiers
125
- [L1ToL2MessageExists.opcode, L1ToL2MessageExists], // Messages
126
- //[HeaderMember.opcode, HeaderMember], // Header
140
+ [SLoad.opcode, Instruction.deserialize.bind(SLoad)], // Public Storage
141
+ [SStore.opcode, Instruction.deserialize.bind(SStore)], // Public Storage
142
+ [NoteHashExists.opcode, Instruction.deserialize.bind(NoteHashExists)], // Notes & Nullifiers
143
+ [EmitNoteHash.opcode, Instruction.deserialize.bind(EmitNoteHash)], // Notes & Nullifiers
144
+ [NullifierExists.opcode, Instruction.deserialize.bind(NullifierExists)], // Notes & Nullifiers
145
+ [EmitNullifier.opcode, Instruction.deserialize.bind(EmitNullifier)], // Notes & Nullifiers
146
+ [L1ToL2MessageExists.opcode, Instruction.deserialize.bind(L1ToL2MessageExists)], // Messages
127
147
 
128
148
  // Accrued Substate
129
- [EmitUnencryptedLog.opcode, EmitUnencryptedLog],
130
- [SendL2ToL1Message.opcode, SendL2ToL1Message],
131
- [GetContractInstance.opcode, GetContractInstance],
149
+ [EmitUnencryptedLog.opcode, Instruction.deserialize.bind(EmitUnencryptedLog)],
150
+ [SendL2ToL1Message.opcode, Instruction.deserialize.bind(SendL2ToL1Message)],
151
+ [GetContractInstance.opcode, Instruction.deserialize.bind(GetContractInstance)],
132
152
 
133
153
  // Control Flow - Contract Calls
134
- [Call.opcode, Call],
135
- [StaticCall.opcode, StaticCall],
136
- //[DelegateCall.opcode, DelegateCall],
137
- [Return.opcode, Return],
138
- [Revert.opcode, Revert],
154
+ [Call.opcode, Instruction.deserialize.bind(Call)],
155
+ [StaticCall.opcode, Instruction.deserialize.bind(StaticCall)],
156
+ //[DelegateCall.opcode, Instruction.deserialize.bind(DelegateCall)],
157
+ [Return.opcode, Instruction.deserialize.bind(Return)],
158
+ [Revert.opcode, Instruction.deserialize.bind(Revert)],
139
159
 
140
160
  // Misc
141
- [DebugLog.opcode, DebugLog],
161
+ [DebugLog.opcode, Instruction.deserialize.bind(DebugLog)],
142
162
 
143
163
  // Gadgets
144
- [EcAdd.opcode, EcAdd],
145
- [Keccak.opcode, Keccak],
146
- [Poseidon2.opcode, Poseidon2],
147
- [Sha256.opcode, Sha256],
148
- [Pedersen.opcode, Pedersen],
149
- [MultiScalarMul.opcode, MultiScalarMul],
150
- [PedersenCommitment.opcode, PedersenCommitment],
164
+ [EcAdd.opcode, Instruction.deserialize.bind(EcAdd)],
165
+ [Keccak.opcode, Instruction.deserialize.bind(Keccak)],
166
+ [Poseidon2.opcode, Instruction.deserialize.bind(Poseidon2)],
167
+ [Sha256.opcode, Instruction.deserialize.bind(Sha256)],
168
+ [Pedersen.opcode, Instruction.deserialize.bind(Pedersen)],
169
+ [MultiScalarMul.opcode, Instruction.deserialize.bind(MultiScalarMul)],
170
+ [PedersenCommitment.opcode, Instruction.deserialize.bind(PedersenCommitment)],
151
171
  // Conversions
152
- [ToRadixLE.opcode, ToRadixLE],
172
+ [ToRadixLE.opcode, Instruction.deserialize.bind(ToRadixLE)],
153
173
  // Future Gadgets -- pending changes in noir
154
174
  // SHA256COMPRESSION,
155
- [KeccakF1600.opcode, KeccakF1600],
175
+ [KeccakF1600.opcode, Instruction.deserialize.bind(KeccakF1600)],
156
176
  ]);
157
177
 
158
- interface Serializable {
159
- serialize(): Buffer;
160
- }
161
-
162
178
  /**
163
179
  * Serializes an array of instructions to bytecode.
164
180
  */
@@ -186,8 +202,8 @@ export function decodeFromBytecode(
186
202
  throw new Error(`Opcode ${Opcode[opcode]} (0x${opcode.toString(16)}) not implemented`);
187
203
  }
188
204
 
189
- const instructionDeserializer: DeserializableInstruction = instructionDeserializerOrUndef;
190
- const i: Instruction = instructionDeserializer.deserialize(cursor);
205
+ const instructionDeserializer: InstructionDeserializer = instructionDeserializerOrUndef;
206
+ const i: Instruction = instructionDeserializer(cursor);
191
207
  instructions.push(i);
192
208
  }
193
209
 
@@ -8,20 +8,33 @@ import { BufferCursor } from './buffer_cursor.js';
8
8
  */
9
9
  export enum Opcode {
10
10
  // Compute
11
- ADD,
12
- SUB,
13
- MUL,
14
- DIV,
15
- FDIV,
16
- EQ,
17
- LT,
18
- LTE,
19
- AND,
20
- OR,
21
- XOR,
11
+ ADD_8,
12
+ ADD_16,
13
+ SUB_8,
14
+ SUB_16,
15
+ MUL_8,
16
+ MUL_16,
17
+ DIV_8,
18
+ DIV_16,
19
+ FDIV_8,
20
+ FDIV_16,
21
+ EQ_8,
22
+ EQ_16,
23
+ LT_8,
24
+ LT_16,
25
+ LTE_8,
26
+ LTE_16,
27
+ AND_8,
28
+ AND_16,
29
+ OR_8,
30
+ OR_16,
31
+ XOR_8,
32
+ XOR_16,
22
33
  NOT,
23
- SHL,
24
- SHR,
34
+ SHL_8,
35
+ SHL_16,
36
+ SHR_8,
37
+ SHR_16,
25
38
  CAST,
26
39
  // Execution environment
27
40
  ADDRESS,
@@ -33,23 +46,26 @@ export enum Opcode {
33
46
  VERSION,
34
47
  BLOCKNUMBER,
35
48
  TIMESTAMP,
36
- COINBASE,
37
49
  FEEPERL2GAS,
38
50
  FEEPERDAGAS,
39
- BLOCKL2GASLIMIT,
40
- BLOCKDAGASLIMIT,
41
51
  CALLDATACOPY,
42
52
  // Gas
43
53
  L2GASLEFT,
44
54
  DAGASLEFT,
45
55
  // Control flow
46
- JUMP,
47
- JUMPI,
56
+ JUMP_16,
57
+ JUMPI_16,
48
58
  INTERNALCALL,
49
59
  INTERNALRETURN,
50
60
  // Memory
51
- SET,
52
- MOV,
61
+ SET_8,
62
+ SET_16,
63
+ SET_32,
64
+ SET_64,
65
+ SET_128,
66
+ SET_FF,
67
+ MOV_8,
68
+ MOV_16,
53
69
  CMOV,
54
70
  // World state
55
71
  SLOAD,
@@ -59,7 +75,6 @@ export enum Opcode {
59
75
  NULLIFIEREXISTS,
60
76
  EMITNULLIFIER,
61
77
  L1TOL2MSGEXISTS,
62
- HEADERMEMBER,
63
78
  GETCONTRACTINSTANCE,
64
79
  EMITUNENCRYPTEDLOG,
65
80
  SENDL2TOL1MSG,
@@ -96,6 +111,7 @@ export enum OperandType {
96
111
  UINT32,
97
112
  UINT64,
98
113
  UINT128,
114
+ FF,
99
115
  }
100
116
 
101
117
  type OperandNativeType = number | bigint;
@@ -108,8 +124,27 @@ const OPERAND_SPEC = new Map<OperandType, [number, () => OperandNativeType, Oper
108
124
  [OperandType.UINT32, [4, Buffer.prototype.readUint32BE, Buffer.prototype.writeUint32BE]],
109
125
  [OperandType.UINT64, [8, Buffer.prototype.readBigInt64BE, Buffer.prototype.writeBigInt64BE]],
110
126
  [OperandType.UINT128, [16, readBigInt128BE, writeBigInt128BE]],
127
+ [OperandType.FF, [32, readBigInt254BE, writeBigInt254BE]],
111
128
  ]);
112
129
 
130
+ function readBigInt254BE(this: Buffer): bigint {
131
+ const totalBytes = 32;
132
+ let ret: bigint = 0n;
133
+ for (let i = 0; i < totalBytes; ++i) {
134
+ ret <<= 8n;
135
+ ret |= BigInt(this.readUint8(i));
136
+ }
137
+ return ret;
138
+ }
139
+
140
+ function writeBigInt254BE(this: Buffer, value: bigint): void {
141
+ const totalBytes = 32;
142
+ for (let offset = totalBytes - 1; offset >= 0; --offset) {
143
+ this.writeUint8(Number(value & 0xffn), offset);
144
+ value >>= 8n;
145
+ }
146
+ }
147
+
113
148
  function readBigInt128BE(this: Buffer): bigint {
114
149
  const totalBytes = 16;
115
150
  let ret: bigint = 0n;
@@ -160,12 +195,10 @@ export function deserialize(cursor: BufferCursor | Buffer, operands: OperandType
160
195
  * @param cls The class to be serialized.
161
196
  * @returns
162
197
  */
163
- export function serialize(operands: OperandType[], cls: any): Buffer {
198
+ export function serializeAs(operands: OperandType[], opcode: Opcode, cls: any): Buffer {
164
199
  const chunks: Buffer[] = [];
165
200
 
166
- // TODO: infer opcode not in this loop
167
- assert(cls.constructor.opcode !== undefined && cls.constructor.opcode !== null);
168
- const rawClassValues: any[] = [cls.constructor.opcode, ...Object.values(cls)];
201
+ const rawClassValues: any[] = [opcode, ...Object.values(cls)];
169
202
  assert(
170
203
  rawClassValues.length === operands.length,
171
204
  `Got ${rawClassValues.length} values but only ${operands.length} serialization operands are specified!`,
@@ -28,8 +28,15 @@ export function mockStorageReadWithMap(hs: HostStorage, mockedStorage: Map<bigin
28
28
  );
29
29
  }
30
30
 
31
- export function mockNoteHashExists(hs: HostStorage, leafIndex: Fr, _value?: Fr) {
32
- (hs.commitmentsDb as jest.Mocked<CommitmentsDB>).getCommitmentIndex.mockResolvedValue(leafIndex.toBigInt());
31
+ export function mockNoteHashExists(hs: HostStorage, _leafIndex: Fr, value?: Fr) {
32
+ (hs.commitmentsDb as jest.Mocked<CommitmentsDB>).getCommitmentValue.mockImplementation((index: bigint) => {
33
+ if (index == _leafIndex.toBigInt()) {
34
+ return Promise.resolve(value);
35
+ } else {
36
+ // This is ok for now since the traceing functions handle it
37
+ return Promise.resolve(undefined);
38
+ }
39
+ });
33
40
  }
34
41
 
35
42
  export function mockNullifierExists(hs: HostStorage, leafIndex: Fr, _value?: Fr) {
@@ -47,6 +47,7 @@ import {
47
47
  PublicKernelData,
48
48
  ReadRequest,
49
49
  RevertCode,
50
+ TreeLeafReadRequest,
50
51
  makeEmptyProof,
51
52
  makeEmptyRecursiveProof,
52
53
  } from '@aztec/circuits.js';
@@ -412,7 +413,7 @@ export abstract class AbstractPhaseManager {
412
413
  returnsHash: computeVarArgsHash(result.returnValues),
413
414
  noteHashReadRequests: padArrayEnd(
414
415
  result.noteHashReadRequests,
415
- ReadRequest.empty(),
416
+ TreeLeafReadRequest.empty(),
416
417
  MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
417
418
  ),
418
419
  nullifierReadRequests: padArrayEnd(
@@ -427,7 +428,7 @@ export abstract class AbstractPhaseManager {
427
428
  ),
428
429
  l1ToL2MsgReadRequests: padArrayEnd(
429
430
  result.l1ToL2MsgReadRequests,
430
- ReadRequest.empty(),
431
+ TreeLeafReadRequest.empty(),
431
432
  MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL,
432
433
  ),
433
434
  contractStorageReads: padArrayEnd(
@@ -100,6 +100,13 @@ export interface CommitmentsDB {
100
100
  */
101
101
  getCommitmentIndex(commitment: Fr): Promise<bigint | undefined>;
102
102
 
103
+ /**
104
+ * Gets commitment in the note hash tree given a leaf index.
105
+ * @param leafIndex - the leaf to look up.
106
+ * @returns - The commitment at that index. Undefined if leaf index is not found.
107
+ */
108
+ getCommitmentValue(leafIndex: bigint): Promise<Fr | undefined>;
109
+
103
110
  /**
104
111
  * Gets the index of a nullifier in the nullifier tree.
105
112
  * @param nullifier - The nullifier.
@@ -17,6 +17,7 @@ import {
17
17
  PublicCallStackItemCompressed,
18
18
  type ReadRequest,
19
19
  RevertCode,
20
+ type TreeLeafReadRequest,
20
21
  } from '@aztec/circuits.js';
21
22
  import { computeVarArgsHash } from '@aztec/circuits.js/hash';
22
23
 
@@ -62,13 +63,13 @@ export interface PublicExecutionResult {
62
63
  /** The new nullifiers to be inserted into the nullifier tree. */
63
64
  nullifiers: Nullifier[];
64
65
  /** The note hash read requests emitted in this call. */
65
- noteHashReadRequests: ReadRequest[];
66
+ noteHashReadRequests: TreeLeafReadRequest[];
66
67
  /** The nullifier read requests emitted in this call. */
67
68
  nullifierReadRequests: ReadRequest[];
68
69
  /** The nullifier non existent read requests emitted in this call. */
69
70
  nullifierNonExistentReadRequests: ReadRequest[];
70
71
  /** L1 to L2 message read requests emitted in this call. */
71
- l1ToL2MsgReadRequests: ReadRequest[];
72
+ l1ToL2MsgReadRequests: TreeLeafReadRequest[];
72
73
  /**
73
74
  * The hashed logs with side effect counter.
74
75
  * Note: required as we don't track the counter anywhere else.