@aztec/simulator 0.53.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.
- package/dest/avm/avm_execution_environment.d.ts +2 -2
- package/dest/avm/avm_execution_environment.d.ts.map +1 -1
- package/dest/avm/avm_execution_environment.js +5 -6
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +73 -35
- package/dest/avm/avm_memory_types.d.ts +1 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +5 -3
- package/dest/avm/bytecode_utils.js +5 -5
- package/dest/avm/opcodes/arithmetic.d.ts +9 -16
- package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
- package/dest/avm/opcodes/arithmetic.js +12 -37
- package/dest/avm/opcodes/bitwise.d.ts +5 -5
- package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
- package/dest/avm/opcodes/bitwise.js +6 -6
- package/dest/avm/opcodes/comparators.d.ts +3 -3
- package/dest/avm/opcodes/comparators.d.ts.map +1 -1
- package/dest/avm/opcodes/comparators.js +4 -4
- package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
- package/dest/avm/opcodes/control_flow.js +6 -6
- package/dest/avm/opcodes/instruction.d.ts +18 -12
- package/dest/avm/opcodes/instruction.d.ts.map +1 -1
- package/dest/avm/opcodes/instruction.js +36 -19
- package/dest/avm/opcodes/instruction_impl.d.ts +4 -2
- package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
- package/dest/avm/opcodes/instruction_impl.js +15 -7
- package/dest/avm/opcodes/memory.d.ts +8 -9
- package/dest/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/avm/opcodes/memory.js +59 -59
- package/dest/avm/serialization/bytecode_serialization.d.ts +7 -8
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +83 -63
- package/dest/avm/serialization/instruction_serialization.d.ts +84 -64
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +102 -67
- package/dest/public/hints_builder.d.ts +3 -4
- package/dest/public/hints_builder.d.ts.map +1 -1
- package/dest/public/hints_builder.js +2 -5
- package/dest/public/tail_phase_manager.d.ts.map +1 -1
- package/dest/public/tail_phase_manager.js +2 -3
- package/package.json +9 -9
- package/src/avm/avm_execution_environment.ts +3 -4
- package/src/avm/avm_gas.ts +72 -34
- package/src/avm/avm_memory_types.ts +4 -2
- package/src/avm/bytecode_utils.ts +4 -4
- package/src/avm/opcodes/arithmetic.ts +12 -41
- package/src/avm/opcodes/bitwise.ts +5 -5
- package/src/avm/opcodes/comparators.ts +3 -3
- package/src/avm/opcodes/control_flow.ts +5 -5
- package/src/avm/opcodes/instruction.ts +41 -19
- package/src/avm/opcodes/instruction_impl.ts +14 -6
- package/src/avm/opcodes/memory.ts +60 -66
- package/src/avm/serialization/bytecode_serialization.ts +93 -73
- package/src/avm/serialization/instruction_serialization.ts +58 -21
- package/src/public/hints_builder.ts +0 -11
- package/src/public/tail_phase_manager.ts +0 -7
package/src/avm/avm_gas.ts
CHANGED
|
@@ -57,20 +57,33 @@ export const GasDimensions = ['l2Gas', 'daGas'] as const;
|
|
|
57
57
|
|
|
58
58
|
/** Base gas costs for each instruction. Additional gas cost may be added on top due to memory or storage accesses, etc. */
|
|
59
59
|
const BaseGasCosts: Record<Opcode, Gas> = {
|
|
60
|
-
[Opcode.
|
|
61
|
-
[Opcode.
|
|
62
|
-
[Opcode.
|
|
63
|
-
[Opcode.
|
|
64
|
-
[Opcode.
|
|
65
|
-
[Opcode.
|
|
66
|
-
[Opcode.
|
|
67
|
-
[Opcode.
|
|
68
|
-
[Opcode.
|
|
69
|
-
[Opcode.
|
|
70
|
-
[Opcode.
|
|
60
|
+
[Opcode.ADD_8]: makeCost(c.AVM_ADD_BASE_L2_GAS, 0),
|
|
61
|
+
[Opcode.ADD_16]: makeCost(c.AVM_ADD_BASE_L2_GAS, 0),
|
|
62
|
+
[Opcode.SUB_8]: makeCost(c.AVM_SUB_BASE_L2_GAS, 0),
|
|
63
|
+
[Opcode.SUB_16]: makeCost(c.AVM_SUB_BASE_L2_GAS, 0),
|
|
64
|
+
[Opcode.MUL_8]: makeCost(c.AVM_MUL_BASE_L2_GAS, 0),
|
|
65
|
+
[Opcode.MUL_16]: makeCost(c.AVM_MUL_BASE_L2_GAS, 0),
|
|
66
|
+
[Opcode.DIV_8]: makeCost(c.AVM_DIV_BASE_L2_GAS, 0),
|
|
67
|
+
[Opcode.DIV_16]: makeCost(c.AVM_DIV_BASE_L2_GAS, 0),
|
|
68
|
+
[Opcode.FDIV_8]: makeCost(c.AVM_FDIV_BASE_L2_GAS, 0),
|
|
69
|
+
[Opcode.FDIV_16]: makeCost(c.AVM_FDIV_BASE_L2_GAS, 0),
|
|
70
|
+
[Opcode.EQ_8]: makeCost(c.AVM_EQ_BASE_L2_GAS, 0),
|
|
71
|
+
[Opcode.EQ_16]: makeCost(c.AVM_EQ_BASE_L2_GAS, 0),
|
|
72
|
+
[Opcode.LT_8]: makeCost(c.AVM_LT_BASE_L2_GAS, 0),
|
|
73
|
+
[Opcode.LT_16]: makeCost(c.AVM_LT_BASE_L2_GAS, 0),
|
|
74
|
+
[Opcode.LTE_8]: makeCost(c.AVM_LTE_BASE_L2_GAS, 0),
|
|
75
|
+
[Opcode.LTE_16]: makeCost(c.AVM_LTE_BASE_L2_GAS, 0),
|
|
76
|
+
[Opcode.AND_8]: makeCost(c.AVM_AND_BASE_L2_GAS, 0),
|
|
77
|
+
[Opcode.AND_16]: makeCost(c.AVM_AND_BASE_L2_GAS, 0),
|
|
78
|
+
[Opcode.OR_8]: makeCost(c.AVM_OR_BASE_L2_GAS, 0),
|
|
79
|
+
[Opcode.OR_16]: makeCost(c.AVM_OR_BASE_L2_GAS, 0),
|
|
80
|
+
[Opcode.XOR_8]: makeCost(c.AVM_XOR_BASE_L2_GAS, 0),
|
|
81
|
+
[Opcode.XOR_16]: makeCost(c.AVM_XOR_BASE_L2_GAS, 0),
|
|
71
82
|
[Opcode.NOT]: makeCost(c.AVM_NOT_BASE_L2_GAS, 0),
|
|
72
|
-
[Opcode.
|
|
73
|
-
[Opcode.
|
|
83
|
+
[Opcode.SHL_8]: makeCost(c.AVM_SHL_BASE_L2_GAS, 0),
|
|
84
|
+
[Opcode.SHL_16]: makeCost(c.AVM_SHL_BASE_L2_GAS, 0),
|
|
85
|
+
[Opcode.SHR_8]: makeCost(c.AVM_SHR_BASE_L2_GAS, 0),
|
|
86
|
+
[Opcode.SHR_16]: makeCost(c.AVM_SHR_BASE_L2_GAS, 0),
|
|
74
87
|
[Opcode.CAST]: makeCost(c.AVM_CAST_BASE_L2_GAS, 0),
|
|
75
88
|
[Opcode.ADDRESS]: makeCost(c.AVM_ADDRESS_BASE_L2_GAS, 0),
|
|
76
89
|
[Opcode.STORAGEADDRESS]: makeCost(c.AVM_STORAGEADDRESS_BASE_L2_GAS, 0),
|
|
@@ -86,12 +99,18 @@ const BaseGasCosts: Record<Opcode, Gas> = {
|
|
|
86
99
|
[Opcode.CALLDATACOPY]: makeCost(c.AVM_CALLDATACOPY_BASE_L2_GAS, 0),
|
|
87
100
|
[Opcode.L2GASLEFT]: makeCost(c.AVM_L2GASLEFT_BASE_L2_GAS, 0),
|
|
88
101
|
[Opcode.DAGASLEFT]: makeCost(c.AVM_DAGASLEFT_BASE_L2_GAS, 0),
|
|
89
|
-
[Opcode.
|
|
90
|
-
[Opcode.
|
|
102
|
+
[Opcode.JUMP_16]: makeCost(c.AVM_JUMP_BASE_L2_GAS, 0),
|
|
103
|
+
[Opcode.JUMPI_16]: makeCost(c.AVM_JUMPI_BASE_L2_GAS, 0),
|
|
91
104
|
[Opcode.INTERNALCALL]: makeCost(c.AVM_INTERNALCALL_BASE_L2_GAS, 0),
|
|
92
105
|
[Opcode.INTERNALRETURN]: makeCost(c.AVM_INTERNALRETURN_BASE_L2_GAS, 0),
|
|
93
|
-
[Opcode.
|
|
94
|
-
[Opcode.
|
|
106
|
+
[Opcode.SET_8]: makeCost(c.AVM_SET_BASE_L2_GAS, 0),
|
|
107
|
+
[Opcode.SET_16]: makeCost(c.AVM_SET_BASE_L2_GAS, 0),
|
|
108
|
+
[Opcode.SET_32]: makeCost(c.AVM_SET_BASE_L2_GAS, 0),
|
|
109
|
+
[Opcode.SET_64]: makeCost(c.AVM_SET_BASE_L2_GAS, 0),
|
|
110
|
+
[Opcode.SET_128]: makeCost(c.AVM_SET_BASE_L2_GAS, 0),
|
|
111
|
+
[Opcode.SET_FF]: makeCost(c.AVM_SET_BASE_L2_GAS, 0),
|
|
112
|
+
[Opcode.MOV_8]: makeCost(c.AVM_MOV_BASE_L2_GAS, 0),
|
|
113
|
+
[Opcode.MOV_16]: makeCost(c.AVM_MOV_BASE_L2_GAS, 0),
|
|
95
114
|
[Opcode.CMOV]: makeCost(c.AVM_CMOV_BASE_L2_GAS, 0),
|
|
96
115
|
[Opcode.SLOAD]: makeCost(c.AVM_SLOAD_BASE_L2_GAS, 0),
|
|
97
116
|
[Opcode.SSTORE]: makeCost(c.AVM_SSTORE_BASE_L2_GAS, 0),
|
|
@@ -122,20 +141,33 @@ const BaseGasCosts: Record<Opcode, Gas> = {
|
|
|
122
141
|
};
|
|
123
142
|
|
|
124
143
|
const DynamicGasCosts: Record<Opcode, Gas> = {
|
|
125
|
-
[Opcode.
|
|
126
|
-
[Opcode.
|
|
127
|
-
[Opcode.
|
|
128
|
-
[Opcode.
|
|
129
|
-
[Opcode.
|
|
130
|
-
[Opcode.
|
|
131
|
-
[Opcode.
|
|
132
|
-
[Opcode.
|
|
133
|
-
[Opcode.
|
|
134
|
-
[Opcode.
|
|
135
|
-
[Opcode.
|
|
144
|
+
[Opcode.ADD_8]: makeCost(c.AVM_ADD_DYN_L2_GAS, 0),
|
|
145
|
+
[Opcode.ADD_16]: makeCost(c.AVM_ADD_DYN_L2_GAS, 0),
|
|
146
|
+
[Opcode.SUB_8]: makeCost(c.AVM_SUB_DYN_L2_GAS, 0),
|
|
147
|
+
[Opcode.SUB_16]: makeCost(c.AVM_SUB_DYN_L2_GAS, 0),
|
|
148
|
+
[Opcode.MUL_8]: makeCost(c.AVM_MUL_DYN_L2_GAS, 0),
|
|
149
|
+
[Opcode.MUL_16]: makeCost(c.AVM_MUL_DYN_L2_GAS, 0),
|
|
150
|
+
[Opcode.DIV_8]: makeCost(c.AVM_DIV_DYN_L2_GAS, 0),
|
|
151
|
+
[Opcode.DIV_16]: makeCost(c.AVM_DIV_DYN_L2_GAS, 0),
|
|
152
|
+
[Opcode.FDIV_8]: makeCost(c.AVM_FDIV_DYN_L2_GAS, 0),
|
|
153
|
+
[Opcode.FDIV_16]: makeCost(c.AVM_FDIV_DYN_L2_GAS, 0),
|
|
154
|
+
[Opcode.EQ_8]: makeCost(c.AVM_EQ_DYN_L2_GAS, 0),
|
|
155
|
+
[Opcode.EQ_16]: makeCost(c.AVM_EQ_DYN_L2_GAS, 0),
|
|
156
|
+
[Opcode.LT_8]: makeCost(c.AVM_LT_DYN_L2_GAS, 0),
|
|
157
|
+
[Opcode.LT_16]: makeCost(c.AVM_LT_DYN_L2_GAS, 0),
|
|
158
|
+
[Opcode.LTE_8]: makeCost(c.AVM_LTE_DYN_L2_GAS, 0),
|
|
159
|
+
[Opcode.LTE_16]: makeCost(c.AVM_LTE_DYN_L2_GAS, 0),
|
|
160
|
+
[Opcode.AND_8]: makeCost(c.AVM_AND_DYN_L2_GAS, 0),
|
|
161
|
+
[Opcode.AND_16]: makeCost(c.AVM_AND_DYN_L2_GAS, 0),
|
|
162
|
+
[Opcode.OR_8]: makeCost(c.AVM_OR_DYN_L2_GAS, 0),
|
|
163
|
+
[Opcode.OR_16]: makeCost(c.AVM_OR_DYN_L2_GAS, 0),
|
|
164
|
+
[Opcode.XOR_8]: makeCost(c.AVM_XOR_DYN_L2_GAS, 0),
|
|
165
|
+
[Opcode.XOR_16]: makeCost(c.AVM_XOR_DYN_L2_GAS, 0),
|
|
136
166
|
[Opcode.NOT]: makeCost(c.AVM_NOT_DYN_L2_GAS, 0),
|
|
137
|
-
[Opcode.
|
|
138
|
-
[Opcode.
|
|
167
|
+
[Opcode.SHL_8]: makeCost(c.AVM_SHL_DYN_L2_GAS, 0),
|
|
168
|
+
[Opcode.SHL_16]: makeCost(c.AVM_SHL_DYN_L2_GAS, 0),
|
|
169
|
+
[Opcode.SHR_8]: makeCost(c.AVM_SHR_DYN_L2_GAS, 0),
|
|
170
|
+
[Opcode.SHR_16]: makeCost(c.AVM_SHR_DYN_L2_GAS, 0),
|
|
139
171
|
[Opcode.CAST]: makeCost(c.AVM_CAST_DYN_L2_GAS, 0),
|
|
140
172
|
[Opcode.ADDRESS]: makeCost(c.AVM_ADDRESS_DYN_L2_GAS, 0),
|
|
141
173
|
[Opcode.STORAGEADDRESS]: makeCost(c.AVM_STORAGEADDRESS_DYN_L2_GAS, 0),
|
|
@@ -151,12 +183,18 @@ const DynamicGasCosts: Record<Opcode, Gas> = {
|
|
|
151
183
|
[Opcode.CALLDATACOPY]: makeCost(c.AVM_CALLDATACOPY_DYN_L2_GAS, 0),
|
|
152
184
|
[Opcode.L2GASLEFT]: makeCost(c.AVM_L2GASLEFT_DYN_L2_GAS, 0),
|
|
153
185
|
[Opcode.DAGASLEFT]: makeCost(c.AVM_DAGASLEFT_DYN_L2_GAS, 0),
|
|
154
|
-
[Opcode.
|
|
155
|
-
[Opcode.
|
|
186
|
+
[Opcode.JUMP_16]: makeCost(c.AVM_JUMP_DYN_L2_GAS, 0),
|
|
187
|
+
[Opcode.JUMPI_16]: makeCost(c.AVM_JUMPI_DYN_L2_GAS, 0),
|
|
156
188
|
[Opcode.INTERNALCALL]: makeCost(c.AVM_INTERNALCALL_DYN_L2_GAS, 0),
|
|
157
189
|
[Opcode.INTERNALRETURN]: makeCost(c.AVM_INTERNALRETURN_DYN_L2_GAS, 0),
|
|
158
|
-
[Opcode.
|
|
159
|
-
[Opcode.
|
|
190
|
+
[Opcode.SET_8]: makeCost(c.AVM_SET_DYN_L2_GAS, 0),
|
|
191
|
+
[Opcode.SET_16]: makeCost(c.AVM_SET_DYN_L2_GAS, 0),
|
|
192
|
+
[Opcode.SET_32]: makeCost(c.AVM_SET_DYN_L2_GAS, 0),
|
|
193
|
+
[Opcode.SET_64]: makeCost(c.AVM_SET_DYN_L2_GAS, 0),
|
|
194
|
+
[Opcode.SET_128]: makeCost(c.AVM_SET_DYN_L2_GAS, 0),
|
|
195
|
+
[Opcode.SET_FF]: makeCost(c.AVM_SET_DYN_L2_GAS, 0),
|
|
196
|
+
[Opcode.MOV_8]: makeCost(c.AVM_MOV_DYN_L2_GAS, 0),
|
|
197
|
+
[Opcode.MOV_16]: makeCost(c.AVM_MOV_DYN_L2_GAS, 0),
|
|
160
198
|
[Opcode.CMOV]: makeCost(c.AVM_CMOV_DYN_L2_GAS, 0),
|
|
161
199
|
[Opcode.SLOAD]: makeCost(c.AVM_SLOAD_DYN_L2_GAS, 0),
|
|
162
200
|
[Opcode.SSTORE]: makeCost(c.AVM_SSTORE_DYN_L2_GAS, 0),
|
|
@@ -350,7 +350,7 @@ export class TaggedMemory implements TaggedMemoryInterface {
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
// Truncates the value to fit the type.
|
|
353
|
-
public static
|
|
353
|
+
public static buildFromTagTruncating(v: bigint | number, tag: TypeTag): MemoryValue {
|
|
354
354
|
v = BigInt(v);
|
|
355
355
|
switch (tag) {
|
|
356
356
|
case TypeTag.UINT8:
|
|
@@ -363,8 +363,10 @@ export class TaggedMemory implements TaggedMemoryInterface {
|
|
|
363
363
|
return new Uint64(v & ((1n << 64n) - 1n));
|
|
364
364
|
case TypeTag.UINT128:
|
|
365
365
|
return new Uint128(v & ((1n << 128n) - 1n));
|
|
366
|
+
case TypeTag.FIELD:
|
|
367
|
+
return new Field(v);
|
|
366
368
|
default:
|
|
367
|
-
throw new Error(`${TypeTag[tag]} is not a valid
|
|
369
|
+
throw new Error(`${TypeTag[tag]} is not a valid tag.`);
|
|
368
370
|
}
|
|
369
371
|
}
|
|
370
372
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { promisify } from 'util';
|
|
2
2
|
import { gunzip } from 'zlib';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { Opcode } from './serialization/instruction_serialization.js';
|
|
5
5
|
|
|
6
6
|
const AVM_MAGIC_SUFFIX = Buffer.from([
|
|
7
|
-
|
|
7
|
+
Opcode.MOV_16, // opcode
|
|
8
8
|
0x00, // indirect
|
|
9
|
-
...Buffer.from('
|
|
10
|
-
...Buffer.from('
|
|
9
|
+
...Buffer.from('18ca', 'hex'), // srcOffset
|
|
10
|
+
...Buffer.from('18ca', 'hex'), // dstOffset
|
|
11
11
|
]);
|
|
12
12
|
|
|
13
13
|
export function markBytecodeAsAvm(bytecode: Buffer): Buffer {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { AvmContext } from '../avm_context.js';
|
|
2
|
-
import { type Field, type MemoryValue
|
|
3
|
-
import { Opcode
|
|
2
|
+
import { type Field, type MemoryValue } from '../avm_memory_types.js';
|
|
3
|
+
import { Opcode } from '../serialization/instruction_serialization.js';
|
|
4
4
|
import { Addressing } from './addressing_mode.js';
|
|
5
|
-
import { Instruction } from './instruction.js';
|
|
6
5
|
import { ThreeOperandInstruction } from './instruction_impl.js';
|
|
7
6
|
|
|
8
7
|
export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInstruction {
|
|
@@ -32,7 +31,7 @@ export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInst
|
|
|
32
31
|
|
|
33
32
|
export class Add extends ThreeOperandArithmeticInstruction {
|
|
34
33
|
static readonly type: string = 'ADD';
|
|
35
|
-
static readonly opcode = Opcode.
|
|
34
|
+
static readonly opcode = Opcode.ADD_8; // FIXME: needed for gas.
|
|
36
35
|
|
|
37
36
|
protected compute(a: MemoryValue, b: MemoryValue): MemoryValue {
|
|
38
37
|
return a.add(b);
|
|
@@ -41,7 +40,7 @@ export class Add extends ThreeOperandArithmeticInstruction {
|
|
|
41
40
|
|
|
42
41
|
export class Sub extends ThreeOperandArithmeticInstruction {
|
|
43
42
|
static readonly type: string = 'SUB';
|
|
44
|
-
static readonly opcode = Opcode.
|
|
43
|
+
static readonly opcode = Opcode.SUB_8; // FIXME: needed for gas.
|
|
45
44
|
|
|
46
45
|
protected compute(a: MemoryValue, b: MemoryValue): MemoryValue {
|
|
47
46
|
return a.sub(b);
|
|
@@ -50,7 +49,7 @@ export class Sub extends ThreeOperandArithmeticInstruction {
|
|
|
50
49
|
|
|
51
50
|
export class Mul extends ThreeOperandArithmeticInstruction {
|
|
52
51
|
static type: string = 'MUL';
|
|
53
|
-
static readonly opcode = Opcode.
|
|
52
|
+
static readonly opcode = Opcode.MUL_8; // FIXME: needed for gas.
|
|
54
53
|
|
|
55
54
|
protected compute(a: MemoryValue, b: MemoryValue): MemoryValue {
|
|
56
55
|
return a.mul(b);
|
|
@@ -59,48 +58,20 @@ export class Mul extends ThreeOperandArithmeticInstruction {
|
|
|
59
58
|
|
|
60
59
|
export class Div extends ThreeOperandArithmeticInstruction {
|
|
61
60
|
static type: string = 'DIV';
|
|
62
|
-
static readonly opcode = Opcode.
|
|
61
|
+
static readonly opcode = Opcode.DIV_8; // FIXME: needed for gas.
|
|
63
62
|
|
|
64
63
|
protected compute(a: MemoryValue, b: MemoryValue): MemoryValue {
|
|
65
64
|
return a.div(b);
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
// TODO: This class now temporarily has a tag, until all tags are removed.
|
|
69
|
+
export class FieldDiv extends ThreeOperandArithmeticInstruction {
|
|
70
70
|
static type: string = 'FDIV';
|
|
71
|
-
static readonly opcode = Opcode.
|
|
72
|
-
|
|
73
|
-
// Informs (de)serialization. See Instruction.deserialize.
|
|
74
|
-
static readonly wireFormat: OperandType[] = [
|
|
75
|
-
OperandType.UINT8,
|
|
76
|
-
OperandType.UINT8,
|
|
77
|
-
OperandType.UINT32,
|
|
78
|
-
OperandType.UINT32,
|
|
79
|
-
OperandType.UINT32,
|
|
80
|
-
];
|
|
81
|
-
|
|
82
|
-
constructor(private indirect: number, private aOffset: number, private bOffset: number, private dstOffset: number) {
|
|
83
|
-
super();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public async execute(context: AvmContext): Promise<void> {
|
|
87
|
-
const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
|
|
88
|
-
const memory = context.machineState.memory.track(this.type);
|
|
89
|
-
context.machineState.consumeGas(this.gasCost(memoryOperations));
|
|
90
|
-
|
|
91
|
-
const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
|
|
92
|
-
[this.aOffset, this.bOffset, this.dstOffset],
|
|
93
|
-
memory,
|
|
94
|
-
);
|
|
95
|
-
memory.checkTags(TypeTag.FIELD, aOffset, bOffset);
|
|
96
|
-
|
|
97
|
-
const a = memory.getAs<Field>(aOffset);
|
|
98
|
-
const b = memory.getAs<Field>(bOffset);
|
|
71
|
+
static readonly opcode = Opcode.FDIV_8; // FIXME: needed for gas.
|
|
99
72
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
memory.assert(memoryOperations);
|
|
104
|
-
context.machineState.incrementPc();
|
|
73
|
+
protected compute(a: Field, b: Field): Field {
|
|
74
|
+
// return (a as Field).fdiv(b as Field);
|
|
75
|
+
return a.fdiv(b);
|
|
105
76
|
}
|
|
106
77
|
}
|
|
@@ -34,7 +34,7 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
|
|
|
34
34
|
|
|
35
35
|
export class And extends ThreeOperandBitwiseInstruction {
|
|
36
36
|
static readonly type: string = 'AND';
|
|
37
|
-
static readonly opcode = Opcode.
|
|
37
|
+
static readonly opcode = Opcode.AND_8; // FIXME: needed for gas.
|
|
38
38
|
|
|
39
39
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
40
40
|
return a.and(b);
|
|
@@ -43,7 +43,7 @@ export class And extends ThreeOperandBitwiseInstruction {
|
|
|
43
43
|
|
|
44
44
|
export class Or extends ThreeOperandBitwiseInstruction {
|
|
45
45
|
static readonly type: string = 'OR';
|
|
46
|
-
static readonly opcode = Opcode.
|
|
46
|
+
static readonly opcode = Opcode.OR_8; // FIXME: needed for gas.
|
|
47
47
|
|
|
48
48
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
49
49
|
return a.or(b);
|
|
@@ -52,7 +52,7 @@ export class Or extends ThreeOperandBitwiseInstruction {
|
|
|
52
52
|
|
|
53
53
|
export class Xor extends ThreeOperandBitwiseInstruction {
|
|
54
54
|
static readonly type: string = 'XOR';
|
|
55
|
-
static readonly opcode = Opcode.
|
|
55
|
+
static readonly opcode = Opcode.XOR_8; // FIXME: needed for gas.
|
|
56
56
|
|
|
57
57
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
58
58
|
return a.xor(b);
|
|
@@ -61,7 +61,7 @@ export class Xor extends ThreeOperandBitwiseInstruction {
|
|
|
61
61
|
|
|
62
62
|
export class Shl extends ThreeOperandBitwiseInstruction {
|
|
63
63
|
static readonly type: string = 'SHL';
|
|
64
|
-
static readonly opcode = Opcode.
|
|
64
|
+
static readonly opcode = Opcode.SHL_8; // FIXME: needed for gas.
|
|
65
65
|
|
|
66
66
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
67
67
|
return a.shl(b);
|
|
@@ -74,7 +74,7 @@ export class Shl extends ThreeOperandBitwiseInstruction {
|
|
|
74
74
|
|
|
75
75
|
export class Shr extends ThreeOperandBitwiseInstruction {
|
|
76
76
|
static readonly type: string = 'SHR';
|
|
77
|
-
static readonly opcode = Opcode.
|
|
77
|
+
static readonly opcode = Opcode.SHR_8; // FIXME: needed for gas.
|
|
78
78
|
|
|
79
79
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
80
80
|
return a.shr(b);
|
|
@@ -31,7 +31,7 @@ abstract class ComparatorInstruction extends ThreeOperandInstruction {
|
|
|
31
31
|
|
|
32
32
|
export class Eq extends ComparatorInstruction {
|
|
33
33
|
static readonly type: string = 'EQ';
|
|
34
|
-
static readonly opcode = Opcode.
|
|
34
|
+
static readonly opcode = Opcode.EQ_8; // FIXME: needed for gas.
|
|
35
35
|
|
|
36
36
|
protected compare(a: MemoryValue, b: MemoryValue): boolean {
|
|
37
37
|
return a.equals(b);
|
|
@@ -40,7 +40,7 @@ export class Eq extends ComparatorInstruction {
|
|
|
40
40
|
|
|
41
41
|
export class Lt extends ComparatorInstruction {
|
|
42
42
|
static readonly type: string = 'LT';
|
|
43
|
-
static readonly opcode = Opcode.
|
|
43
|
+
static readonly opcode = Opcode.LT_8; // FIXME: needed for gas.
|
|
44
44
|
|
|
45
45
|
protected compare(a: MemoryValue, b: MemoryValue): boolean {
|
|
46
46
|
return a.lt(b);
|
|
@@ -49,7 +49,7 @@ export class Lt extends ComparatorInstruction {
|
|
|
49
49
|
|
|
50
50
|
export class Lte extends ComparatorInstruction {
|
|
51
51
|
static readonly type: string = 'LTE';
|
|
52
|
-
static readonly opcode = Opcode.
|
|
52
|
+
static readonly opcode = Opcode.LTE_8; // FIXME: needed for gas.
|
|
53
53
|
|
|
54
54
|
protected compare(a: MemoryValue, b: MemoryValue): boolean {
|
|
55
55
|
return a.lt(b) || a.equals(b);
|
|
@@ -7,9 +7,9 @@ import { Instruction } from './instruction.js';
|
|
|
7
7
|
|
|
8
8
|
export class Jump extends Instruction {
|
|
9
9
|
static type: string = 'JUMP';
|
|
10
|
-
static readonly opcode: Opcode = Opcode.
|
|
10
|
+
static readonly opcode: Opcode = Opcode.JUMP_16;
|
|
11
11
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
12
|
-
static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.
|
|
12
|
+
static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT16];
|
|
13
13
|
|
|
14
14
|
constructor(private jumpOffset: number) {
|
|
15
15
|
super();
|
|
@@ -26,14 +26,14 @@ export class Jump extends Instruction {
|
|
|
26
26
|
|
|
27
27
|
export class JumpI extends Instruction {
|
|
28
28
|
static type: string = 'JUMPI';
|
|
29
|
-
static readonly opcode: Opcode = Opcode.
|
|
29
|
+
static readonly opcode: Opcode = Opcode.JUMPI_16;
|
|
30
30
|
|
|
31
31
|
// Instruction wire format with opcode.
|
|
32
32
|
static readonly wireFormat: OperandType[] = [
|
|
33
33
|
OperandType.UINT8,
|
|
34
34
|
OperandType.UINT8,
|
|
35
|
-
OperandType.
|
|
36
|
-
OperandType.
|
|
35
|
+
OperandType.UINT16,
|
|
36
|
+
OperandType.UINT16,
|
|
37
37
|
];
|
|
38
38
|
|
|
39
39
|
constructor(private indirect: number, private loc: number, private condOffset: number) {
|
|
@@ -4,11 +4,11 @@ import type { AvmContext } from '../avm_context.js';
|
|
|
4
4
|
import { getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js';
|
|
5
5
|
import { type MemoryOperations } from '../avm_memory_types.js';
|
|
6
6
|
import { type BufferCursor } from '../serialization/buffer_cursor.js';
|
|
7
|
-
import {
|
|
7
|
+
import { type Serializable } from '../serialization/bytecode_serialization.js';
|
|
8
|
+
import { Opcode, type OperandType, deserialize, serializeAs } from '../serialization/instruction_serialization.js';
|
|
8
9
|
|
|
9
10
|
type InstructionConstructor = {
|
|
10
11
|
new (...args: any[]): Instruction;
|
|
11
|
-
wireFormat?: OperandType[];
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -37,29 +37,51 @@ export abstract class Instruction {
|
|
|
37
37
|
return instructionStr;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// Default deserialization which uses Class.opcode and Class.wireFormat.
|
|
41
|
+
public static deserialize(
|
|
42
|
+
this: InstructionConstructor & { wireFormat: OperandType[]; as: any },
|
|
43
|
+
buf: BufferCursor | Buffer,
|
|
44
|
+
): Instruction {
|
|
45
|
+
return this.as(this.wireFormat).deserialize(buf);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Default serialization which uses Class.opcode and Class.wireFormat.
|
|
49
|
+
public serialize(): Buffer {
|
|
50
|
+
const klass = this.constructor as any;
|
|
51
|
+
assert(klass.opcode !== undefined && klass.opcode !== null);
|
|
52
|
+
assert(klass.wireFormat !== undefined && klass.wireFormat !== null);
|
|
53
|
+
return this.as(klass.opcode, klass.wireFormat).serialize();
|
|
54
|
+
}
|
|
55
|
+
|
|
40
56
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @param
|
|
44
|
-
* @returns The
|
|
57
|
+
* Returns a new instruction instance that can be serialized with the given opcode and wire format.
|
|
58
|
+
* @param opcode The opcode of the instruction.
|
|
59
|
+
* @param wireFormat The wire format of the instruction.
|
|
60
|
+
* @returns The new instruction instance.
|
|
45
61
|
*/
|
|
46
|
-
public
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
public as(opcode: Opcode, wireFormat: OperandType[]): Instruction & Serializable {
|
|
63
|
+
return Object.defineProperty(this, 'serialize', {
|
|
64
|
+
value: (): Buffer => {
|
|
65
|
+
return serializeAs(wireFormat, opcode, this);
|
|
66
|
+
},
|
|
67
|
+
enumerable: false,
|
|
68
|
+
});
|
|
49
69
|
}
|
|
50
70
|
|
|
51
71
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* @param
|
|
55
|
-
* @
|
|
56
|
-
* @returns Constructed instance of Class.
|
|
72
|
+
* Returns a new instruction class that can be deserialized with the given opcode and wire format.
|
|
73
|
+
* @param opcode The opcode of the instruction.
|
|
74
|
+
* @param wireFormat The wire format of the instruction.
|
|
75
|
+
* @returns The new instruction class.
|
|
57
76
|
*/
|
|
58
|
-
public static
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
public static as(this: InstructionConstructor, wireFormat: OperandType[]) {
|
|
78
|
+
return Object.assign(this, {
|
|
79
|
+
deserialize: (buf: BufferCursor | Buffer): Instruction => {
|
|
80
|
+
const res = deserialize(buf, wireFormat);
|
|
81
|
+
const args = res.slice(1); // Remove opcode.
|
|
82
|
+
return new this(...args);
|
|
83
|
+
},
|
|
84
|
+
});
|
|
63
85
|
}
|
|
64
86
|
|
|
65
87
|
/**
|
|
@@ -14,13 +14,21 @@ export const TwoOperandWireFormat = [
|
|
|
14
14
|
];
|
|
15
15
|
|
|
16
16
|
/** Wire format that informs deserialization for instructions with three operands. */
|
|
17
|
-
export const
|
|
17
|
+
export const ThreeOperandWireFormat8 = [
|
|
18
|
+
OperandType.UINT8,
|
|
19
|
+
OperandType.UINT8,
|
|
20
|
+
OperandType.UINT8,
|
|
18
21
|
OperandType.UINT8,
|
|
19
22
|
OperandType.UINT8,
|
|
20
23
|
OperandType.UINT8,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
OperandType.
|
|
24
|
+
];
|
|
25
|
+
export const ThreeOperandWireFormat16 = [
|
|
26
|
+
OperandType.UINT8,
|
|
27
|
+
OperandType.UINT8,
|
|
28
|
+
OperandType.UINT8,
|
|
29
|
+
OperandType.UINT16,
|
|
30
|
+
OperandType.UINT16,
|
|
31
|
+
OperandType.UINT16,
|
|
24
32
|
];
|
|
25
33
|
|
|
26
34
|
/**
|
|
@@ -46,8 +54,8 @@ export abstract class TwoOperandInstruction extends Instruction {
|
|
|
46
54
|
* indirect, inTag, and three UINT32s.
|
|
47
55
|
*/
|
|
48
56
|
export abstract class ThreeOperandInstruction extends Instruction {
|
|
49
|
-
|
|
50
|
-
static readonly
|
|
57
|
+
static readonly wireFormat8: OperandType[] = ThreeOperandWireFormat8;
|
|
58
|
+
static readonly wireFormat16: OperandType[] = ThreeOperandWireFormat16;
|
|
51
59
|
|
|
52
60
|
constructor(
|
|
53
61
|
protected indirect: number,
|
|
@@ -1,39 +1,57 @@
|
|
|
1
1
|
import type { AvmContext } from '../avm_context.js';
|
|
2
|
-
import { Field, TaggedMemory
|
|
3
|
-
import {
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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.
|
|
170
|
-
OperandType.
|
|
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) {
|