@aztec/simulator 0.23.0 → 0.26.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 (177) hide show
  1. package/dest/acvm/deserialize.d.ts +5 -0
  2. package/dest/acvm/deserialize.d.ts.map +1 -1
  3. package/dest/acvm/deserialize.js +8 -1
  4. package/dest/acvm/oracle/oracle.d.ts +7 -6
  5. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/oracle.js +28 -15
  7. package/dest/acvm/oracle/typed_oracle.d.ts +9 -11
  8. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  9. package/dest/acvm/oracle/typed_oracle.js +11 -11
  10. package/dest/avm/avm_context.d.ts +4 -4
  11. package/dest/avm/avm_context.d.ts.map +1 -1
  12. package/dest/avm/avm_context.js +6 -6
  13. package/dest/avm/avm_execution_environment.d.ts +3 -2
  14. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  15. package/dest/avm/avm_execution_environment.js +6 -5
  16. package/dest/avm/avm_memory_types.d.ts +127 -37
  17. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  18. package/dest/avm/avm_memory_types.js +98 -106
  19. package/dest/avm/avm_simulator.d.ts +6 -4
  20. package/dest/avm/avm_simulator.d.ts.map +1 -1
  21. package/dest/avm/avm_simulator.js +17 -19
  22. package/dest/avm/errors.d.ts +3 -1
  23. package/dest/avm/errors.d.ts.map +1 -1
  24. package/dest/avm/errors.js +9 -3
  25. package/dest/avm/fixtures/index.d.ts +21 -5
  26. package/dest/avm/fixtures/index.d.ts.map +1 -1
  27. package/dest/avm/fixtures/index.js +28 -9
  28. package/dest/avm/journal/host_storage.d.ts +1 -1
  29. package/dest/avm/journal/host_storage.d.ts.map +1 -1
  30. package/dest/avm/journal/host_storage.js +1 -1
  31. package/dest/avm/journal/journal.d.ts +78 -50
  32. package/dest/avm/journal/journal.d.ts.map +1 -1
  33. package/dest/avm/journal/journal.js +125 -169
  34. package/dest/avm/journal/nullifiers.d.ts +85 -0
  35. package/dest/avm/journal/nullifiers.d.ts.map +1 -0
  36. package/dest/avm/journal/nullifiers.js +147 -0
  37. package/dest/avm/journal/public_storage.d.ts +88 -0
  38. package/dest/avm/journal/public_storage.d.ts.map +1 -0
  39. package/dest/avm/journal/public_storage.js +135 -0
  40. package/dest/avm/journal/trace.d.ts +43 -0
  41. package/dest/avm/journal/trace.d.ts.map +1 -0
  42. package/dest/avm/journal/trace.js +204 -0
  43. package/dest/avm/journal/trace_types.d.ts +26 -0
  44. package/dest/avm/journal/trace_types.d.ts.map +1 -0
  45. package/dest/avm/journal/trace_types.js +6 -0
  46. package/dest/avm/opcodes/accrued_substate.d.ts +37 -4
  47. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  48. package/dest/avm/opcodes/accrued_substate.js +109 -12
  49. package/dest/avm/opcodes/addressing_mode.d.ts +24 -0
  50. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -0
  51. package/dest/avm/opcodes/addressing_mode.js +62 -0
  52. package/dest/avm/opcodes/environment_getters.d.ts +14 -13
  53. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  54. package/dest/avm/opcodes/environment_getters.js +1 -1
  55. package/dest/avm/opcodes/external_calls.js +5 -5
  56. package/dest/avm/opcodes/hashing.d.ts +48 -0
  57. package/dest/avm/opcodes/hashing.d.ts.map +1 -0
  58. package/dest/avm/opcodes/hashing.js +127 -0
  59. package/dest/avm/opcodes/instruction.d.ts +4 -4
  60. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  61. package/dest/avm/opcodes/instruction.js +1 -1
  62. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  63. package/dest/avm/opcodes/memory.js +5 -3
  64. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  65. package/dest/avm/opcodes/storage.js +3 -3
  66. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  67. package/dest/avm/serialization/bytecode_serialization.js +28 -22
  68. package/dest/avm/serialization/instruction_serialization.d.ts +21 -16
  69. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  70. package/dest/avm/serialization/instruction_serialization.js +23 -18
  71. package/dest/avm/temporary_executor_migration.d.ts +25 -0
  72. package/dest/avm/temporary_executor_migration.d.ts.map +1 -0
  73. package/dest/avm/temporary_executor_migration.js +71 -0
  74. package/dest/client/client_execution_context.d.ts +13 -7
  75. package/dest/client/client_execution_context.d.ts.map +1 -1
  76. package/dest/client/client_execution_context.js +52 -27
  77. package/dest/client/db_oracle.d.ts +7 -0
  78. package/dest/client/db_oracle.d.ts.map +1 -1
  79. package/dest/client/db_oracle.js +1 -1
  80. package/dest/client/execution_note_cache.js +1 -1
  81. package/dest/client/execution_result.d.ts +4 -2
  82. package/dest/client/execution_result.d.ts.map +1 -1
  83. package/dest/client/execution_result.js +1 -1
  84. package/dest/client/private_execution.d.ts.map +1 -1
  85. package/dest/client/private_execution.js +4 -4
  86. package/dest/client/simulator.d.ts +11 -6
  87. package/dest/client/simulator.d.ts.map +1 -1
  88. package/dest/client/simulator.js +21 -12
  89. package/dest/client/unconstrained_execution.js +2 -2
  90. package/dest/client/view_data_oracle.d.ts +9 -2
  91. package/dest/client/view_data_oracle.d.ts.map +1 -1
  92. package/dest/client/view_data_oracle.js +13 -5
  93. package/dest/public/db.d.ts +17 -4
  94. package/dest/public/db.d.ts.map +1 -1
  95. package/dest/public/execution.d.ts +9 -4
  96. package/dest/public/execution.d.ts.map +1 -1
  97. package/dest/public/execution.js +18 -5
  98. package/dest/public/executor.d.ts +7 -0
  99. package/dest/public/executor.d.ts.map +1 -1
  100. package/dest/public/executor.js +40 -6
  101. package/dest/public/public_execution_context.d.ts +5 -4
  102. package/dest/public/public_execution_context.d.ts.map +1 -1
  103. package/dest/public/public_execution_context.js +24 -13
  104. package/dest/public/state_actions.d.ts +1 -1
  105. package/dest/public/state_actions.d.ts.map +1 -1
  106. package/dest/public/state_actions.js +6 -7
  107. package/dest/test/utils.js +4 -4
  108. package/dest/utils.d.ts +5 -20
  109. package/dest/utils.d.ts.map +1 -1
  110. package/dest/utils.js +4 -21
  111. package/package.json +9 -6
  112. package/src/acvm/acvm.ts +156 -0
  113. package/src/acvm/acvm_types.ts +11 -0
  114. package/src/acvm/deserialize.ts +44 -0
  115. package/src/acvm/index.ts +5 -0
  116. package/src/acvm/oracle/debug.ts +109 -0
  117. package/src/acvm/oracle/index.ts +17 -0
  118. package/src/acvm/oracle/oracle.ts +356 -0
  119. package/src/acvm/oracle/typed_oracle.ts +225 -0
  120. package/src/acvm/serialize.ts +75 -0
  121. package/src/avm/avm_context.ts +63 -0
  122. package/src/avm/avm_execution_environment.ts +98 -0
  123. package/src/avm/avm_machine_state.ts +93 -0
  124. package/src/avm/avm_memory_types.ts +324 -0
  125. package/src/avm/avm_message_call_result.ts +29 -0
  126. package/src/avm/avm_simulator.ts +87 -0
  127. package/src/avm/errors.ts +57 -0
  128. package/src/avm/fixtures/index.ts +115 -0
  129. package/src/avm/journal/host_storage.ts +14 -0
  130. package/src/avm/journal/index.ts +2 -0
  131. package/src/avm/journal/journal.ts +231 -0
  132. package/src/avm/journal/nullifiers.ts +170 -0
  133. package/src/avm/journal/public_storage.ts +149 -0
  134. package/src/avm/journal/trace.ts +223 -0
  135. package/src/avm/journal/trace_types.ts +79 -0
  136. package/src/avm/opcodes/.eslintrc.cjs +8 -0
  137. package/src/avm/opcodes/accrued_substate.ts +214 -0
  138. package/src/avm/opcodes/addressing_mode.ts +66 -0
  139. package/src/avm/opcodes/arithmetic.ts +79 -0
  140. package/src/avm/opcodes/bitwise.ts +129 -0
  141. package/src/avm/opcodes/comparators.ts +69 -0
  142. package/src/avm/opcodes/control_flow.ts +129 -0
  143. package/src/avm/opcodes/environment_getters.ts +201 -0
  144. package/src/avm/opcodes/external_calls.ts +122 -0
  145. package/src/avm/opcodes/hashing.ts +170 -0
  146. package/src/avm/opcodes/index.ts +10 -0
  147. package/src/avm/opcodes/instruction.ts +64 -0
  148. package/src/avm/opcodes/instruction_impl.ts +52 -0
  149. package/src/avm/opcodes/memory.ts +194 -0
  150. package/src/avm/opcodes/storage.ts +79 -0
  151. package/src/avm/serialization/buffer_cursor.ts +109 -0
  152. package/src/avm/serialization/bytecode_serialization.ts +179 -0
  153. package/src/avm/serialization/instruction_serialization.ts +170 -0
  154. package/src/avm/temporary_executor_migration.ts +109 -0
  155. package/src/client/client_execution_context.ts +502 -0
  156. package/src/client/db_oracle.ts +192 -0
  157. package/src/client/execution_note_cache.ts +90 -0
  158. package/src/client/execution_result.ts +89 -0
  159. package/src/client/index.ts +3 -0
  160. package/src/client/pick_notes.ts +125 -0
  161. package/src/client/private_execution.ts +79 -0
  162. package/src/client/simulator.ts +317 -0
  163. package/src/client/unconstrained_execution.ts +49 -0
  164. package/src/client/view_data_oracle.ts +253 -0
  165. package/src/common/errors.ts +61 -0
  166. package/src/common/index.ts +3 -0
  167. package/src/common/packed_args_cache.ts +55 -0
  168. package/src/common/side_effect_counter.ts +12 -0
  169. package/src/index.ts +3 -0
  170. package/src/public/db.ts +100 -0
  171. package/src/public/execution.ts +161 -0
  172. package/src/public/executor.ts +178 -0
  173. package/src/public/index.ts +9 -0
  174. package/src/public/public_execution_context.ts +241 -0
  175. package/src/public/state_actions.ts +100 -0
  176. package/src/test/utils.ts +38 -0
  177. package/src/utils.ts +18 -0
@@ -0,0 +1,170 @@
1
+ import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
2
+ import { keccak, pedersenHash, poseidonHash, sha256 } from '@aztec/foundation/crypto';
3
+
4
+ import { AvmContext } from '../avm_context.js';
5
+ import { Field } from '../avm_memory_types.js';
6
+ import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
+ import { Addressing } from './addressing_mode.js';
8
+ import { Instruction } from './instruction.js';
9
+
10
+ export class Poseidon2 extends Instruction {
11
+ static type: string = 'POSEIDON2';
12
+ static readonly opcode: Opcode = Opcode.POSEIDON;
13
+
14
+ // Informs (de)serialization. See Instruction.deserialize.
15
+ static readonly wireFormat: OperandType[] = [
16
+ OperandType.UINT8,
17
+ OperandType.UINT8,
18
+ OperandType.UINT32,
19
+ OperandType.UINT32,
20
+ OperandType.UINT32,
21
+ ];
22
+
23
+ constructor(
24
+ private indirect: number,
25
+ private dstOffset: number,
26
+ private hashOffset: number,
27
+ private hashSize: number,
28
+ ) {
29
+ super();
30
+ }
31
+
32
+ async execute(context: AvmContext): Promise<void> {
33
+ // We hash a set of field elements
34
+ const [hashOffset] = Addressing.fromWire(this.indirect).resolve([this.hashOffset], context.machineState.memory);
35
+
36
+ // Memory pointer will be indirect
37
+ const hashData = context.machineState.memory.getSlice(hashOffset, this.hashSize).map(word => word.toBuffer());
38
+
39
+ const hash = poseidonHash(hashData);
40
+ context.machineState.memory.set(this.dstOffset, new Field(hash));
41
+
42
+ context.machineState.incrementPc();
43
+ }
44
+ }
45
+
46
+ export class Keccak extends Instruction {
47
+ static type: string = 'KECCAK';
48
+ static readonly opcode: Opcode = Opcode.KECCAK;
49
+
50
+ // Informs (de)serialization. See Instruction.deserialize.
51
+ static readonly wireFormat: OperandType[] = [
52
+ OperandType.UINT8,
53
+ OperandType.UINT8,
54
+ OperandType.UINT32,
55
+ OperandType.UINT32,
56
+ OperandType.UINT32,
57
+ ];
58
+
59
+ constructor(
60
+ private indirect: number,
61
+ private dstOffset: number,
62
+ private hashOffset: number,
63
+ private hashSize: number,
64
+ ) {
65
+ super();
66
+ }
67
+
68
+ // Note hash output is 32 bytes, so takes up two fields
69
+ async execute(context: AvmContext): Promise<void> {
70
+ // We hash a set of field elements
71
+ const [hashOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
72
+ [this.hashOffset, this.dstOffset],
73
+ context.machineState.memory,
74
+ );
75
+
76
+ const hashData = context.machineState.memory.getSlice(hashOffset, this.hashSize).map(word => word.toBuffer());
77
+
78
+ const hash = keccak(Buffer.concat(hashData));
79
+
80
+ // Split output into two fields
81
+ const high = new Field(toBigIntBE(hash.subarray(0, 16)));
82
+ const low = new Field(toBigIntBE(hash.subarray(16, 32)));
83
+
84
+ context.machineState.memory.set(dstOffset, high);
85
+ context.machineState.memory.set(dstOffset + 1, low);
86
+
87
+ context.machineState.incrementPc();
88
+ }
89
+ }
90
+
91
+ export class Sha256 extends Instruction {
92
+ static type: string = 'SHA256';
93
+ static readonly opcode: Opcode = Opcode.SHA256;
94
+
95
+ // Informs (de)serialization. See Instruction.deserialize.
96
+ static readonly wireFormat: OperandType[] = [
97
+ OperandType.UINT8,
98
+ OperandType.UINT8,
99
+ OperandType.UINT32,
100
+ OperandType.UINT32,
101
+ OperandType.UINT32,
102
+ ];
103
+
104
+ constructor(
105
+ private indirect: number,
106
+ private dstOffset: number,
107
+ private hashOffset: number,
108
+ private hashSize: number,
109
+ ) {
110
+ super();
111
+ }
112
+
113
+ // Note hash output is 32 bytes, so takes up two fields
114
+ async execute(context: AvmContext): Promise<void> {
115
+ const [hashOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
116
+ [this.hashOffset, this.dstOffset],
117
+ context.machineState.memory,
118
+ );
119
+
120
+ // We hash a set of field elements
121
+ const hashData = context.machineState.memory.getSlice(hashOffset, this.hashSize).map(word => word.toBuffer());
122
+
123
+ const hash = sha256(Buffer.concat(hashData));
124
+
125
+ // Split output into two fields
126
+ const high = new Field(toBigIntBE(hash.subarray(0, 16)));
127
+ const low = new Field(toBigIntBE(hash.subarray(16, 32)));
128
+
129
+ context.machineState.memory.set(dstOffset, high);
130
+ context.machineState.memory.set(dstOffset + 1, low);
131
+
132
+ context.machineState.incrementPc();
133
+ }
134
+ }
135
+
136
+ export class Pedersen extends Instruction {
137
+ static type: string = 'PEDERSEN';
138
+ static readonly opcode: Opcode = Opcode.PEDERSEN;
139
+
140
+ // Informs (de)serialization. See Instruction.deserialize.
141
+ static readonly wireFormat: OperandType[] = [
142
+ OperandType.UINT8,
143
+ OperandType.UINT8,
144
+ OperandType.UINT32,
145
+ OperandType.UINT32,
146
+ OperandType.UINT32,
147
+ ];
148
+
149
+ constructor(
150
+ private indirect: number,
151
+ private dstOffset: number,
152
+ private hashOffset: number,
153
+ private hashSize: number,
154
+ ) {
155
+ super();
156
+ }
157
+
158
+ async execute(context: AvmContext): Promise<void> {
159
+ const [hashOffset] = Addressing.fromWire(this.indirect).resolve([this.hashOffset], context.machineState.memory);
160
+
161
+ // We hash a set of field elements
162
+ const hashData = context.machineState.memory.getSlice(hashOffset, this.hashSize).map(word => word.toBuffer());
163
+
164
+ // No domain sep for now
165
+ const hash = pedersenHash(hashData);
166
+ context.machineState.memory.set(this.dstOffset, new Field(hash));
167
+
168
+ context.machineState.incrementPc();
169
+ }
170
+ }
@@ -0,0 +1,10 @@
1
+ export * from './arithmetic.js';
2
+ export * from './bitwise.js';
3
+ export * from './control_flow.js';
4
+ export * from './instruction.js';
5
+ export * from './comparators.js';
6
+ export * from './memory.js';
7
+ export * from './storage.js';
8
+ export * from './external_calls.js';
9
+ export * from './environment_getters.js';
10
+ export * from './accrued_substate.js';
@@ -0,0 +1,64 @@
1
+ import { strict as assert } from 'assert';
2
+
3
+ import type { AvmContext } from '../avm_context.js';
4
+ import { BufferCursor } from '../serialization/buffer_cursor.js';
5
+ import { OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js';
6
+
7
+ type InstructionConstructor = {
8
+ new (...args: any[]): Instruction;
9
+ wireFormat?: OperandType[];
10
+ };
11
+
12
+ /**
13
+ * Parent class for all AVM instructions.
14
+ * It's most important aspects are execute and (de)serialize.
15
+ */
16
+ export abstract class Instruction {
17
+ /**
18
+ * Execute the instruction.
19
+ * Instruction sub-classes must implement this.
20
+ * As an AvmContext executes its contract code, it calls this function for
21
+ * each instruction until the machine state signals "halted".
22
+ * @param context - The AvmContext in which the instruction executes.
23
+ */
24
+ public abstract execute(context: AvmContext): Promise<void>;
25
+
26
+ /**
27
+ * Generate a string representation of the instruction including
28
+ * the instruction sub-class name all of its flags and operands.
29
+ * @returns Thee string representation.
30
+ */
31
+ public toString(): string {
32
+ let instructionStr = this.constructor.name + ': ';
33
+ // assumes that all properties are flags or operands
34
+ for (const prop of Object.getOwnPropertyNames(this) as (keyof Instruction)[]) {
35
+ instructionStr += `${prop}:${this[prop].toString()}, `;
36
+ }
37
+ return instructionStr;
38
+ }
39
+
40
+ /**
41
+ * Serialize the instruction to a Buffer according to its wire format specified in its subclass.
42
+ * If you want to use this, your subclass should specify a {@code static wireFormat: OperandType[]}.
43
+ * @param this - The instruction to serialize.
44
+ * @returns The serialized instruction.
45
+ */
46
+ public serialize(this: any): Buffer {
47
+ assert(!!this.constructor.wireFormat, 'wireFormat must be defined on the class');
48
+ return serialize(this.constructor.wireFormat, this);
49
+ }
50
+
51
+ /**
52
+ * Deserializes a subclass of Instruction from a Buffer.
53
+ * If you want to use this, your subclass should specify a {@code static wireFormat: OperandType[]}.
54
+ * @param this Class object to deserialize to.
55
+ * @param buf Buffer to read from.
56
+ * @returns Constructed instance of Class.
57
+ */
58
+ public static deserialize(this: InstructionConstructor, buf: BufferCursor | Buffer): Instruction {
59
+ assert(!!this.wireFormat, 'wireFormat must be defined on the instruction class');
60
+ const res = deserialize(buf, this.wireFormat);
61
+ const args = res.slice(1); // Remove opcode.
62
+ return new this(...args);
63
+ }
64
+ }
@@ -0,0 +1,52 @@
1
+ import { OperandType } from '../serialization/instruction_serialization.js';
2
+ import { Instruction } from './instruction.js';
3
+
4
+ /**
5
+ * Covers (de)serialization for an instruction with:
6
+ * indirect, inTag, and two UINT32s.
7
+ */
8
+ export abstract class TwoOperandInstruction extends Instruction {
9
+ // 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
+ ];
17
+
18
+ constructor(
19
+ protected indirect: number,
20
+ protected inTag: number,
21
+ protected aOffset: number,
22
+ protected dstOffset: number,
23
+ ) {
24
+ super();
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Covers (de)serialization for an instruction with:
30
+ * indirect, inTag, and three UINT32s.
31
+ */
32
+ export abstract class ThreeOperandInstruction extends Instruction {
33
+ // 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
+ ];
42
+
43
+ constructor(
44
+ protected indirect: number,
45
+ protected inTag: number,
46
+ protected aOffset: number,
47
+ protected bOffset: number,
48
+ protected dstOffset: number,
49
+ ) {
50
+ super();
51
+ }
52
+ }
@@ -0,0 +1,194 @@
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';
6
+ import { Addressing } from './addressing_mode.js';
7
+ import { Instruction } from './instruction.js';
8
+ import { TwoOperandInstruction } from './instruction_impl.js';
9
+
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
+ export class Set extends Instruction {
28
+ 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,
35
+ ];
36
+ private static readonly wireFormatAfterConst: OperandType[] = [OperandType.UINT32];
37
+
38
+ constructor(
39
+ private indirect: number,
40
+ private inTag: number,
41
+ private value: bigint | number,
42
+ private dstOffset: number,
43
+ ) {
44
+ super();
45
+ }
46
+
47
+ /** We need to use a custom serialize function because of the variable length of the value. */
48
+ public 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 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
+ async execute(context: AvmContext): Promise<void> {
72
+ // Per the YP, the tag cannot be a field.
73
+ if ([TypeTag.FIELD, TypeTag.UNINITIALIZED, TypeTag.INVALID].includes(this.inTag)) {
74
+ throw new InstructionExecutionError(`Invalid tag ${TypeTag[this.inTag]} for SET.`);
75
+ }
76
+
77
+ const res = TaggedMemory.integralFromTag(this.value, this.inTag);
78
+ context.machineState.memory.set(this.dstOffset, res);
79
+
80
+ context.machineState.incrementPc();
81
+ }
82
+ }
83
+
84
+ export class CMov extends Instruction {
85
+ static readonly type: string = 'CMOV';
86
+ static readonly opcode: Opcode = Opcode.CMOV;
87
+ // Informs (de)serialization. See Instruction.deserialize.
88
+ static readonly wireFormat: OperandType[] = [
89
+ OperandType.UINT8,
90
+ OperandType.UINT8,
91
+ OperandType.UINT32,
92
+ OperandType.UINT32,
93
+ OperandType.UINT32,
94
+ OperandType.UINT32,
95
+ ];
96
+
97
+ constructor(
98
+ private indirect: number,
99
+ private aOffset: number,
100
+ private bOffset: number,
101
+ private condOffset: number,
102
+ private dstOffset: number,
103
+ ) {
104
+ super();
105
+ }
106
+
107
+ async execute(context: AvmContext): Promise<void> {
108
+ const a = context.machineState.memory.get(this.aOffset);
109
+ const b = context.machineState.memory.get(this.bOffset);
110
+ const cond = context.machineState.memory.get(this.condOffset);
111
+
112
+ // TODO: reconsider toBigInt() here
113
+ context.machineState.memory.set(this.dstOffset, cond.toBigInt() > 0 ? a : b);
114
+
115
+ context.machineState.incrementPc();
116
+ }
117
+ }
118
+
119
+ export class Cast extends TwoOperandInstruction {
120
+ static readonly type: string = 'CAST';
121
+ static readonly opcode = Opcode.CAST;
122
+
123
+ constructor(indirect: number, dstTag: number, aOffset: number, dstOffset: number) {
124
+ super(indirect, dstTag, aOffset, dstOffset);
125
+ }
126
+
127
+ async execute(context: AvmContext): Promise<void> {
128
+ const a = context.machineState.memory.get(this.aOffset);
129
+
130
+ // TODO: consider not using toBigInt()
131
+ const casted =
132
+ this.inTag == TypeTag.FIELD ? new Field(a.toBigInt()) : TaggedMemory.integralFromTag(a.toBigInt(), this.inTag);
133
+
134
+ context.machineState.memory.set(this.dstOffset, casted);
135
+
136
+ context.machineState.incrementPc();
137
+ }
138
+ }
139
+
140
+ export class Mov extends Instruction {
141
+ static readonly type: string = 'MOV';
142
+ static readonly opcode: Opcode = Opcode.MOV;
143
+ // Informs (de)serialization. See Instruction.deserialize.
144
+ static readonly wireFormat: OperandType[] = [
145
+ OperandType.UINT8,
146
+ OperandType.UINT8,
147
+ OperandType.UINT32,
148
+ OperandType.UINT32,
149
+ ];
150
+
151
+ constructor(private indirect: number, private srcOffset: number, private dstOffset: number) {
152
+ super();
153
+ }
154
+
155
+ async execute(context: AvmContext): Promise<void> {
156
+ const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
157
+ [this.srcOffset, this.dstOffset],
158
+ context.machineState.memory,
159
+ );
160
+
161
+ const a = context.machineState.memory.get(srcOffset);
162
+
163
+ context.machineState.memory.set(dstOffset, a);
164
+
165
+ context.machineState.incrementPc();
166
+ }
167
+ }
168
+
169
+ export class CalldataCopy extends Instruction {
170
+ static readonly type: string = 'CALLDATACOPY';
171
+ static readonly opcode: Opcode = Opcode.CALLDATACOPY;
172
+ // Informs (de)serialization. See Instruction.deserialize.
173
+ static readonly wireFormat: OperandType[] = [
174
+ OperandType.UINT8,
175
+ OperandType.UINT8,
176
+ OperandType.UINT32,
177
+ OperandType.UINT32,
178
+ OperandType.UINT32,
179
+ ];
180
+
181
+ constructor(private indirect: number, private cdOffset: number, private copySize: number, private dstOffset: number) {
182
+ super();
183
+ }
184
+
185
+ async execute(context: AvmContext): Promise<void> {
186
+ const transformedData = context.environment.calldata
187
+ .slice(this.cdOffset, this.cdOffset + this.copySize)
188
+ .map(f => new Field(f));
189
+
190
+ context.machineState.memory.setSlice(this.dstOffset, transformedData);
191
+
192
+ context.machineState.incrementPc();
193
+ }
194
+ }
@@ -0,0 +1,79 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+
3
+ import type { AvmContext } from '../avm_context.js';
4
+ import { Field } from '../avm_memory_types.js';
5
+ import { InstructionExecutionError } from '../errors.js';
6
+ import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
7
+ import { Instruction } from './instruction.js';
8
+
9
+ abstract class BaseStorageInstruction extends Instruction {
10
+ // Informs (de)serialization. See Instruction.deserialize.
11
+ public static readonly wireFormat: OperandType[] = [
12
+ OperandType.UINT8,
13
+ OperandType.UINT8,
14
+ OperandType.UINT32,
15
+ OperandType.UINT32,
16
+ ];
17
+
18
+ constructor(protected indirect: number, protected aOffset: number, protected bOffset: number) {
19
+ super();
20
+ }
21
+ }
22
+
23
+ export class SStore extends BaseStorageInstruction {
24
+ static readonly type: string = 'SSTORE';
25
+ static readonly opcode = Opcode.SSTORE;
26
+
27
+ constructor(indirect: number, srcOffset: number, slotOffset: number) {
28
+ super(indirect, srcOffset, slotOffset);
29
+ }
30
+
31
+ async execute(context: AvmContext): Promise<void> {
32
+ if (context.environment.isStaticCall) {
33
+ throw new StaticCallStorageAlterError();
34
+ }
35
+
36
+ const slot = context.machineState.memory.get(this.aOffset);
37
+ const data = context.machineState.memory.get(this.bOffset);
38
+
39
+ context.persistableState.writeStorage(
40
+ context.environment.storageAddress,
41
+ new Fr(slot.toBigInt()),
42
+ new Fr(data.toBigInt()),
43
+ );
44
+
45
+ context.machineState.incrementPc();
46
+ }
47
+ }
48
+
49
+ export class SLoad extends BaseStorageInstruction {
50
+ static readonly type: string = 'SLOAD';
51
+ static readonly opcode = Opcode.SLOAD;
52
+
53
+ constructor(indirect: number, slotOffset: number, dstOffset: number) {
54
+ super(indirect, slotOffset, dstOffset);
55
+ }
56
+
57
+ async execute(context: AvmContext): Promise<void> {
58
+ const slot = context.machineState.memory.get(this.aOffset);
59
+
60
+ const data: Fr = await context.persistableState.readStorage(
61
+ context.environment.storageAddress,
62
+ new Fr(slot.toBigInt()),
63
+ );
64
+
65
+ context.machineState.memory.set(this.bOffset, new Field(data));
66
+
67
+ context.machineState.incrementPc();
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Error is thrown when a static call attempts to alter storage
73
+ */
74
+ export class StaticCallStorageAlterError extends InstructionExecutionError {
75
+ constructor() {
76
+ super('Static calls cannot alter storage');
77
+ this.name = 'StaticCallStorageAlterError';
78
+ }
79
+ }
@@ -0,0 +1,109 @@
1
+ import { strict as assert } from 'assert';
2
+
3
+ /*
4
+ * A Buffer-like class that automatically advances the position.
5
+ */
6
+ export class BufferCursor {
7
+ constructor(private _buffer: Buffer, private _position: number = 0) {}
8
+
9
+ public position(): number {
10
+ return this._position;
11
+ }
12
+
13
+ public eof(): boolean {
14
+ return this._position === this._buffer.length;
15
+ }
16
+
17
+ public bufferAtPosition(): Buffer {
18
+ return this._buffer.subarray(this._position);
19
+ }
20
+
21
+ public advance(n: number): void {
22
+ this._position += n;
23
+ assert(n < this._buffer.length);
24
+ }
25
+
26
+ public readUint8(): number {
27
+ const ret = this._buffer.readUint8(this._position);
28
+ this._position += 1;
29
+ return ret;
30
+ }
31
+
32
+ public readUint16LE(): number {
33
+ const ret = this._buffer.readUint16LE(this._position);
34
+ this._position += 2;
35
+ return ret;
36
+ }
37
+
38
+ public readUint16BE(): number {
39
+ const ret = this._buffer.readUint16BE(this._position);
40
+ this._position += 2;
41
+ return ret;
42
+ }
43
+
44
+ public readUint32LE(): number {
45
+ const ret = this._buffer.readUint32LE(this._position);
46
+ this._position += 4;
47
+ return ret;
48
+ }
49
+
50
+ public readUint32BE(): number {
51
+ const ret = this._buffer.readUint32BE(this._position);
52
+ this._position += 4;
53
+ return ret;
54
+ }
55
+
56
+ public readBigInt64LE(): bigint {
57
+ const ret = this._buffer.readBigInt64LE(this._position);
58
+ this._position += 8;
59
+ return ret;
60
+ }
61
+
62
+ public readBigInt64BE(): bigint {
63
+ const ret = this._buffer.readBigInt64BE(this._position);
64
+ this._position += 8;
65
+ return ret;
66
+ }
67
+
68
+ public writeUint8(v: number) {
69
+ const ret = this._buffer.writeUint8(v, this._position);
70
+ this._position += 1;
71
+ return ret;
72
+ }
73
+
74
+ public writeUint16LE(v: number) {
75
+ const ret = this._buffer.writeUint16LE(v, this._position);
76
+ this._position += 2;
77
+ return ret;
78
+ }
79
+
80
+ public writeUint16BE(v: number) {
81
+ const ret = this._buffer.writeUint16BE(v, this._position);
82
+ this._position += 2;
83
+ return ret;
84
+ }
85
+
86
+ public writeUint32LE(v: number) {
87
+ const ret = this._buffer.writeUint32LE(v, this._position);
88
+ this._position += 4;
89
+ return ret;
90
+ }
91
+
92
+ public writeUint32BE(v: number) {
93
+ const ret = this._buffer.writeUint32BE(v, this._position);
94
+ this._position += 4;
95
+ return ret;
96
+ }
97
+
98
+ public writeBigInt64LE(v: bigint) {
99
+ const ret = this._buffer.writeBigInt64LE(v, this._position);
100
+ this._position += 8;
101
+ return ret;
102
+ }
103
+
104
+ public writeBigInt64BE(v: bigint) {
105
+ const ret = this._buffer.writeBigInt64BE(v, this._position);
106
+ this._position += 8;
107
+ return ret;
108
+ }
109
+ }