@fluffylabs/anan-as 1.2.0-41e43f6 → 1.2.0-5196d29

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 (77) hide show
  1. package/dist/bin/index.js +3 -2
  2. package/dist/bin/src/fuzz.js +1 -1
  3. package/dist/bin/src/test-json.js +2 -6
  4. package/dist/bin/src/trace-replay.js +8 -4
  5. package/dist/build/compiler-inline.js +1 -1
  6. package/dist/build/compiler.d.ts +2 -13
  7. package/dist/build/compiler.js +1 -25
  8. package/dist/build/compiler.wasm +0 -0
  9. package/dist/build/debug-inline.js +1 -1
  10. package/dist/build/debug-raw-inline.js +1 -1
  11. package/dist/build/debug-raw.d.ts +27 -25
  12. package/dist/build/debug-raw.js +58 -57
  13. package/dist/build/debug-raw.wasm +0 -0
  14. package/dist/build/debug.d.ts +27 -25
  15. package/dist/build/debug.js +59 -58
  16. package/dist/build/debug.wasm +0 -0
  17. package/dist/build/js/assembly/api-debugger.d.ts +3 -3
  18. package/dist/build/js/assembly/api-debugger.js +6 -6
  19. package/dist/build/js/assembly/api-internal.d.ts +1 -1
  20. package/dist/build/js/assembly/api-internal.js +2 -3
  21. package/dist/build/js/assembly/api-types.d.ts +0 -1
  22. package/dist/build/js/assembly/api-types.js +0 -1
  23. package/dist/build/js/assembly/api-utils.d.ts +12 -5
  24. package/dist/build/js/assembly/api-utils.js +28 -13
  25. package/dist/build/js/assembly/arguments.d.ts +4 -4
  26. package/dist/build/js/assembly/arguments.js +10 -10
  27. package/dist/build/js/assembly/gas.d.ts +1 -1
  28. package/dist/build/js/assembly/gas.js +3 -2
  29. package/dist/build/js/assembly/instructions/bit.js +22 -22
  30. package/dist/build/js/assembly/instructions/branch.js +56 -56
  31. package/dist/build/js/assembly/instructions/jump.js +10 -10
  32. package/dist/build/js/assembly/instructions/load.js +41 -41
  33. package/dist/build/js/assembly/instructions/logic.js +20 -20
  34. package/dist/build/js/assembly/instructions/math.js +105 -105
  35. package/dist/build/js/assembly/instructions/misc.js +10 -10
  36. package/dist/build/js/assembly/instructions/mov.js +16 -16
  37. package/dist/build/js/assembly/instructions/outcome.d.ts +7 -7
  38. package/dist/build/js/assembly/instructions/outcome.js +63 -36
  39. package/dist/build/js/assembly/instructions/rot.js +18 -18
  40. package/dist/build/js/assembly/instructions/set.js +18 -18
  41. package/dist/build/js/assembly/instructions/shift.js +59 -59
  42. package/dist/build/js/assembly/instructions/store.js +29 -29
  43. package/dist/build/js/assembly/instructions/utils.d.ts +6 -4
  44. package/dist/build/js/assembly/instructions/utils.js +32 -16
  45. package/dist/build/js/assembly/instructions.d.ts +2 -3
  46. package/dist/build/js/assembly/instructions.js +4 -4
  47. package/dist/build/js/assembly/interpreter.d.ts +0 -1
  48. package/dist/build/js/assembly/interpreter.js +15 -22
  49. package/dist/build/js/assembly/math.d.ts +6 -8
  50. package/dist/build/js/assembly/math.js +21 -13
  51. package/dist/build/js/assembly/memory.js +9 -7
  52. package/dist/build/js/assembly/portable.js +1 -0
  53. package/dist/build/js/assembly/program-build.js +4 -4
  54. package/dist/build/js/assembly/program.d.ts +15 -8
  55. package/dist/build/js/assembly/program.js +90 -40
  56. package/dist/build/js/assembly/spi.d.ts +1 -1
  57. package/dist/build/js/assembly/spi.js +2 -2
  58. package/dist/build/js/portable-bundle.js +666 -579
  59. package/dist/build/release-inline.js +1 -1
  60. package/dist/build/release-mini-inline.js +1 -1
  61. package/dist/build/release-mini.d.ts +27 -25
  62. package/dist/build/release-mini.js +59 -58
  63. package/dist/build/release-mini.wasm +0 -0
  64. package/dist/build/release-stub-inline.js +1 -1
  65. package/dist/build/release-stub.d.ts +27 -25
  66. package/dist/build/release-stub.js +59 -58
  67. package/dist/build/release-stub.wasm +0 -0
  68. package/dist/build/release.d.ts +27 -25
  69. package/dist/build/release.js +59 -58
  70. package/dist/build/release.wasm +0 -0
  71. package/dist/build/test-inline.js +1 -1
  72. package/dist/build/test.wasm +0 -0
  73. package/dist/test/test-gas-cost.js +2 -3
  74. package/dist/test/test-w3f-common.js +1 -2
  75. package/package.json +7 -7
  76. package/dist/build/js/assembly/gas-costs.d.ts +0 -6
  77. package/dist/build/js/assembly/gas-costs.js +0 -39
@@ -1,7 +1,7 @@
1
1
  import { Arguments, higNibble, lowNibble, REQUIRED_BYTES } from "./arguments";
2
2
  import { encodeVarU32 } from "./codec";
3
3
  import { INSTRUCTIONS, MISSING_INSTRUCTION } from "./instructions";
4
- import { minI32 } from "./math";
4
+ import { IntMath } from "./math";
5
5
  /** Turn given bytecode into a valid program. Add JumpTable and Mask. */
6
6
  export function wrapAsProgram(bytecode) {
7
7
  const jumpTableLength = 0;
@@ -57,9 +57,9 @@ function skipBytes(kind, data) {
57
57
  case Arguments.TwoReg:
58
58
  return 1;
59
59
  case Arguments.TwoRegOneImm:
60
- return 1 + minI32(4, data.length);
60
+ return 1 + IntMath.minI32(4, data.length);
61
61
  case Arguments.TwoRegOneOff:
62
- return 1 + minI32(4, data.length);
62
+ return 1 + IntMath.minI32(4, data.length);
63
63
  case Arguments.TwoRegTwoImm: {
64
64
  const low = lowNibble(data[1]);
65
65
  const split = low + 1;
@@ -100,5 +100,5 @@ function immBytes(dataLength, required) {
100
100
  if (dataLength < required) {
101
101
  return 0;
102
102
  }
103
- return minI32(4, dataLength - required);
103
+ return IntMath.minI32(4, dataLength - required);
104
104
  }
@@ -1,6 +1,7 @@
1
1
  import { Args, Arguments } from "./arguments";
2
2
  import { Registers } from "./registers";
3
3
  export type ProgramCounter = u32;
4
+ export type Code = StaticArray<u8>;
4
5
  export declare class CodeAndMetadata {
5
6
  readonly code: Uint8Array;
6
7
  readonly metadata: Uint8Array;
@@ -10,10 +11,10 @@ export declare class CodeAndMetadata {
10
11
  export declare function extractCodeAndMetadata(data: Uint8Array): CodeAndMetadata;
11
12
  /** Convert `u8` to `Uint8Array` */
12
13
  export declare function liftBytes(data: u8[]): Uint8Array;
13
- /** Convert `Uint8Array` to `u8` */
14
- export declare function lowerBytes(data: Uint8Array): u8[];
14
+ /** Convert `Uint8Array` to `Code` (StaticArray<u8>) */
15
+ export declare function lowerBytes(data: Uint8Array): Code;
15
16
  /** https://graypaper.fluffylabs.dev/#/cc517d7/234f01234f01?v=0.6.5 */
16
- export declare function deblob(program: Uint8Array): Program;
17
+ export declare function deblob(program: Uint8Array, useBlockGas: boolean): Program;
17
18
  /**
18
19
  * https://graypaper.fluffylabs.dev/#/cc517d7/236e01236e01?v=0.6.5
19
20
  */
@@ -39,6 +40,11 @@ export declare class Mask {
39
40
  skipBytesToNextInstruction(i: u32): u32;
40
41
  toString(): string;
41
42
  }
43
+ export declare class GasCosts {
44
+ readonly codeAndGas: StaticArray<u32>;
45
+ constructor(code: Code, mask: Mask, blocks: BasicBlocks, useBlockGasCost: boolean);
46
+ toString(): string;
47
+ }
42
48
  export declare enum BasicBlock {
43
49
  NONE = 0,
44
50
  START = 2,
@@ -49,7 +55,7 @@ export declare enum BasicBlock {
49
55
  */
50
56
  export declare class BasicBlocks {
51
57
  readonly isStartOrEnd: StaticArray<BasicBlock>;
52
- constructor(code: u8[], mask: Mask);
58
+ constructor(code: Code, mask: Mask);
53
59
  isStart(newPc: u32): boolean;
54
60
  toString(): string;
55
61
  }
@@ -59,14 +65,15 @@ export declare class JumpTable {
59
65
  toString(): string;
60
66
  }
61
67
  export declare class Program {
62
- readonly code: u8[];
68
+ readonly code: Code;
63
69
  readonly mask: Mask;
64
70
  readonly jumpTable: JumpTable;
65
71
  readonly basicBlocks: BasicBlocks;
66
- constructor(code: u8[], mask: Mask, jumpTable: JumpTable, basicBlocks: BasicBlocks);
72
+ readonly gasCosts: GasCosts;
73
+ constructor(code: Code, mask: Mask, jumpTable: JumpTable, basicBlocks: BasicBlocks, gasCosts: GasCosts);
67
74
  toString(): string;
68
75
  }
69
- export declare function decodeArguments(args: Args, kind: Arguments, code: u8[], offset: i32, lim: u32): Args;
76
+ export declare function decodeArguments(args: Args, kind: Arguments, code: Code, offset: i32, lim: u32): Args;
70
77
  declare class ResolvedArguments {
71
78
  a: i64;
72
79
  b: i64;
@@ -74,5 +81,5 @@ declare class ResolvedArguments {
74
81
  d: i64;
75
82
  decoded: Args;
76
83
  }
77
- export declare function resolveArguments(argsRes: Args, kind: Arguments, code: u8[], offset: u32, lim: u32, registers: Registers): ResolvedArguments | null;
84
+ export declare function resolveArguments(argsRes: Args, kind: Arguments, code: Code, offset: u32, lim: u32, registers: Registers): ResolvedArguments | null;
78
85
  export {};
@@ -1,7 +1,7 @@
1
1
  import { Args, Arguments, DECODERS, REQUIRED_BYTES } from "./arguments";
2
2
  import { Decoder } from "./codec";
3
3
  import { INSTRUCTIONS, MISSING_INSTRUCTION } from "./instructions";
4
- import { reg, u32SignExtend } from "./instructions/utils";
4
+ import { Inst } from "./instructions/utils";
5
5
  import { portable } from "./portable";
6
6
  const MAX_SKIP = 24;
7
7
  export class CodeAndMetadata {
@@ -24,16 +24,16 @@ export function liftBytes(data) {
24
24
  p.set(data, 0);
25
25
  return p;
26
26
  }
27
- /** Convert `Uint8Array` to `u8` */
27
+ /** Convert `Uint8Array` to `Code` (StaticArray<u8>) */
28
28
  export function lowerBytes(data) {
29
- const r = new Array(data.length);
29
+ const r = new StaticArray(data.length);
30
30
  for (let i = 0; i < data.length; i++) {
31
31
  r[i] = data[i];
32
32
  }
33
33
  return r;
34
34
  }
35
35
  /** https://graypaper.fluffylabs.dev/#/cc517d7/234f01234f01?v=0.6.5 */
36
- export function deblob(program) {
36
+ export function deblob(program, useBlockGas) {
37
37
  const decoder = new Decoder(program);
38
38
  // number of items in the jump table
39
39
  const jumpTableLength = decoder.varU32();
@@ -50,7 +50,8 @@ export function deblob(program) {
50
50
  const mask = new Mask(rawMask, codeLength);
51
51
  const jumpTable = new JumpTable(jumpTableItemLength, rawJumpTable);
52
52
  const basicBlocks = new BasicBlocks(rawCode, mask);
53
- return new Program(rawCode, mask, jumpTable, basicBlocks);
53
+ const gasCosts = new GasCosts(rawCode, mask, basicBlocks, useBlockGas);
54
+ return new Program(rawCode, mask, jumpTable, basicBlocks, gasCosts);
54
55
  }
55
56
  /**
56
57
  * https://graypaper.fluffylabs.dev/#/cc517d7/236e01236e01?v=0.6.5
@@ -100,6 +101,54 @@ export class Mask {
100
101
  return `${v}]`;
101
102
  }
102
103
  }
104
+ export class GasCosts {
105
+ constructor(code, mask, blocks, useBlockGasCost) {
106
+ const len = code.length;
107
+ const costs = new StaticArray(len);
108
+ for (let n = 0; n < len; n += 1) {
109
+ const isInstructionInMask = mask.isInstruction(n);
110
+ if (!isInstructionInMask) {
111
+ costs[n] = code[n];
112
+ continue;
113
+ }
114
+ const skipArgs = mask.skipBytesToNextInstruction(n);
115
+ const iData = code[n] >= INSTRUCTIONS.length ? MISSING_INSTRUCTION : INSTRUCTIONS[code[n]];
116
+ costs[n] = code[n] | (iData.gas << 8);
117
+ n += skipArgs;
118
+ }
119
+ // sum up costs per block
120
+ if (useBlockGasCost) {
121
+ let previousStart = 0;
122
+ let previousSum = 0;
123
+ for (let n = 0; n < len; n += 1) {
124
+ const currentGas = costs[n] >> 8;
125
+ costs[n] = code[n]; // reset to just opcode (gas=0)
126
+ if (blocks.isStart(n)) {
127
+ costs[previousStart] = code[previousStart] | (previousSum << 8);
128
+ previousSum = currentGas;
129
+ previousStart = n;
130
+ }
131
+ else {
132
+ previousSum += currentGas;
133
+ }
134
+ n += mask.skipBytesToNextInstruction(n);
135
+ }
136
+ // final assignment
137
+ costs[previousStart] = code[previousStart] | (previousSum << 8);
138
+ }
139
+ this.codeAndGas = costs;
140
+ }
141
+ toString() {
142
+ let v = "GasCosts[";
143
+ for (let i = 0; i < this.codeAndGas.length; i += 1) {
144
+ const gas = this.codeAndGas[i] >> 8;
145
+ if (gas !== 0) {
146
+ v += `${i} -> ${gas}, `;
147
+ }
148
+ }
149
+ return `${v}]`;
150
+ }
151
+ }
103
152
  export var BasicBlock;
104
153
  (function (BasicBlock) {
105
154
  BasicBlock[BasicBlock["NONE"] = 0] = "NONE";
@@ -185,32 +234,33 @@ export class JumpTable {
185
234
  }
186
235
  }
187
236
  export class Program {
188
- constructor(code, mask, jumpTable, basicBlocks) {
237
+ constructor(code, mask, jumpTable, basicBlocks, gasCosts) {
189
238
  this.code = code;
190
239
  this.mask = mask;
191
240
  this.jumpTable = jumpTable;
192
241
  this.basicBlocks = basicBlocks;
242
+ this.gasCosts = gasCosts;
193
243
  }
194
244
  toString() {
195
- return `Program { code: ${this.code}, mask: ${this.mask}, jumpTable: ${this.jumpTable}, basicBlocks: ${this.basicBlocks} }`;
245
+ return `Program { code: ${this.code}, mask: ${this.mask}, jumpTable: ${this.jumpTable}, basicBlocks: ${this.basicBlocks}, gasCosts: ${this.gasCosts} }`;
196
246
  }
197
247
  }
198
248
  // Pre-allocated buffer for the rare case when code is shorter than needed.
199
249
  // Max REQUIRED_BYTES is 9 (OneRegOneExtImm). We allocate 16 for safety.
200
- const EXTENDED_BUF = new Array(16);
250
+ const EXTENDED_BUF = new StaticArray(16);
201
251
  export function decodeArguments(args, kind, code, offset, lim) {
202
252
  if (code.length < offset + REQUIRED_BYTES[kind]) {
203
253
  // in case we have less data than needed we extend the data with zeros.
204
- const reqBytes = REQUIRED_BYTES[kind];
254
+ const reqBytes = unchecked(REQUIRED_BYTES[kind]);
205
255
  for (let i = 0; i < reqBytes; i++) {
206
256
  EXTENDED_BUF[i] = 0;
207
257
  }
208
258
  for (let i = offset; i < code.length; i++) {
209
- EXTENDED_BUF[i - offset] = code[i];
259
+ EXTENDED_BUF[i - offset] = unchecked(code[i]);
210
260
  }
211
- return DECODERS[kind](args, EXTENDED_BUF, 0, lim);
261
+ return unchecked(DECODERS[kind])(args, EXTENDED_BUF, 0, lim);
212
262
  }
213
- return DECODERS[kind](args, code, offset, offset + lim);
263
+ return unchecked(DECODERS[kind])(args, code, offset, offset + lim);
214
264
  }
215
265
  class ResolvedArguments {
216
266
  constructor() {
@@ -232,57 +282,57 @@ export function resolveArguments(argsRes, kind, code, offset, lim, registers) {
232
282
  case Arguments.Zero:
233
283
  return resolved;
234
284
  case Arguments.OneImm:
235
- resolved.a = u32SignExtend(args.a);
285
+ resolved.a = Inst.u32SignExtend(args.a);
236
286
  return resolved;
237
287
  case Arguments.TwoImm:
238
- resolved.a = u32SignExtend(args.a);
239
- resolved.b = u32SignExtend(args.b);
288
+ resolved.a = Inst.u32SignExtend(args.a);
289
+ resolved.b = Inst.u32SignExtend(args.b);
240
290
  return resolved;
241
291
  case Arguments.OneOff:
242
- resolved.a = u32SignExtend(args.a);
292
+ resolved.a = Inst.u32SignExtend(args.a);
243
293
  return resolved;
244
294
  case Arguments.OneRegOneImm:
245
- resolved.a = registers[reg(u64(args.a))];
246
- resolved.b = u32SignExtend(args.b);
295
+ resolved.a = registers[Inst.reg(u64(args.a))];
296
+ resolved.b = Inst.u32SignExtend(args.b);
247
297
  return resolved;
248
298
  case Arguments.OneRegOneExtImm:
249
- resolved.a = registers[reg(u64(args.a))];
299
+ resolved.a = registers[Inst.reg(u64(args.a))];
250
300
  resolved.b = portable.u64_add(u64(args.a) << u64(32), u64(args.b));
251
301
  return resolved;
252
302
  case Arguments.OneRegTwoImm:
253
- resolved.a = registers[reg(u64(args.a))];
254
- resolved.b = u32SignExtend(args.b);
255
- resolved.c = u32SignExtend(args.c);
303
+ resolved.a = registers[Inst.reg(u64(args.a))];
304
+ resolved.b = Inst.u32SignExtend(args.b);
305
+ resolved.c = Inst.u32SignExtend(args.c);
256
306
  return resolved;
257
307
  case Arguments.OneRegOneImmOneOff:
258
- resolved.a = registers[reg(u64(args.a))];
259
- resolved.b = u32SignExtend(args.b);
260
- resolved.c = u32SignExtend(args.c);
308
+ resolved.a = registers[Inst.reg(u64(args.a))];
309
+ resolved.b = Inst.u32SignExtend(args.b);
310
+ resolved.c = Inst.u32SignExtend(args.c);
261
311
  return resolved;
262
312
  case Arguments.TwoReg:
263
- resolved.a = registers[reg(u64(args.a))];
264
- resolved.b = registers[reg(u64(args.b))];
313
+ resolved.a = registers[Inst.reg(u64(args.a))];
314
+ resolved.b = registers[Inst.reg(u64(args.b))];
265
315
  return resolved;
266
316
  case Arguments.TwoRegOneImm:
267
- resolved.a = registers[reg(u64(args.a))];
268
- resolved.b = registers[reg(u64(args.b))];
269
- resolved.c = u32SignExtend(args.c);
317
+ resolved.a = registers[Inst.reg(u64(args.a))];
318
+ resolved.b = registers[Inst.reg(u64(args.b))];
319
+ resolved.c = Inst.u32SignExtend(args.c);
270
320
  return resolved;
271
321
  case Arguments.TwoRegOneOff:
272
- resolved.a = registers[reg(u64(args.a))];
273
- resolved.b = registers[reg(u64(args.b))];
274
- resolved.c = u32SignExtend(args.c);
322
+ resolved.a = registers[Inst.reg(u64(args.a))];
323
+ resolved.b = registers[Inst.reg(u64(args.b))];
324
+ resolved.c = Inst.u32SignExtend(args.c);
275
325
  return resolved;
276
326
  case Arguments.TwoRegTwoImm:
277
- resolved.a = registers[reg(u64(args.a))];
278
- resolved.b = registers[reg(u64(args.b))];
279
- resolved.c = u32SignExtend(args.c);
280
- resolved.d = u32SignExtend(args.d);
327
+ resolved.a = registers[Inst.reg(u64(args.a))];
328
+ resolved.b = registers[Inst.reg(u64(args.b))];
329
+ resolved.c = Inst.u32SignExtend(args.c);
330
+ resolved.d = Inst.u32SignExtend(args.d);
281
331
  return resolved;
282
332
  case Arguments.ThreeReg:
283
- resolved.a = registers[reg(u64(args.a))];
284
- resolved.b = registers[reg(u64(args.b))];
285
- resolved.c = registers[reg(u64(args.c))];
333
+ resolved.a = registers[Inst.reg(u64(args.a))];
334
+ resolved.b = registers[Inst.reg(u64(args.b))];
335
+ resolved.c = registers[Inst.reg(u64(args.c))];
286
336
  return resolved;
287
337
  default:
288
338
  throw new Error(`Unhandled arguments kind: ${kind}`);
@@ -8,7 +8,7 @@ export declare const ARGS_SEGMENT_START: u32;
8
8
  /** https://graypaper.fluffylabs.dev/#/ab2cdbd/2d33022d3502?v=0.7.2 */
9
9
  export declare const STACK_SEGMENT_END: u32;
10
10
  /** https://graypaper.fluffylabs.dev/#/ab2cdbd/2da3002da300?v=0.7.2 */
11
- export declare function decodeSpi(data: Uint8Array, args: Uint8Array, preallocateMemoryPages?: u32): StandardProgram;
11
+ export declare function decodeSpi(data: Uint8Array, args: Uint8Array, preallocateMemoryPages?: u32, useBlockGas?: boolean): StandardProgram;
12
12
  /**
13
13
  * SPI Program with memory and registers.
14
14
  *
@@ -10,7 +10,7 @@ export const ARGS_SEGMENT_START = 2 ** 32 - SEGMENT_SIZE - MAX_ARGS_LEN;
10
10
  /** https://graypaper.fluffylabs.dev/#/ab2cdbd/2d33022d3502?v=0.7.2 */
11
11
  export const STACK_SEGMENT_END = ARGS_SEGMENT_START - SEGMENT_SIZE;
12
12
  /** https://graypaper.fluffylabs.dev/#/ab2cdbd/2da3002da300?v=0.7.2 */
13
- export function decodeSpi(data, args, preallocateMemoryPages = 0) {
13
+ export function decodeSpi(data, args, preallocateMemoryPages = 0, useBlockGas = false) {
14
14
  const argsLength = args.length;
15
15
  if (argsLength > MAX_ARGS_LEN) {
16
16
  throw new Error(`Arguments length is too big. Got: ${argsLength}, max: ${MAX_ARGS_LEN}`);
@@ -25,7 +25,7 @@ export function decodeSpi(data, args, preallocateMemoryPages = 0) {
25
25
  const codeLength = decoder.u32();
26
26
  const code = decoder.bytes(codeLength);
27
27
  decoder.finish();
28
- const program = deblob(code);
28
+ const program = deblob(code, useBlockGas);
29
29
  // building memory
30
30
  const builder = new MemoryBuilder(preallocateMemoryPages);
31
31
  const heapStart = 2 * SEGMENT_SIZE + alignToSegmentSize(roLength);