@tychosdk/disasm 0.1.5 → 0.1.7

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.
@@ -1,48 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.disasmToFift = disasmToFift;
4
- const core_1 = require("@ton/core");
5
4
  const structured_1 = require("./structured");
6
5
  async function disasmToFift(code, params = {}) {
7
6
  const { root, items } = await (0, structured_1.disasmStructured)(code);
8
- const codeCells = new CodeCells(code);
7
+ const codeCells = new structured_1.CodeCells(code);
9
8
  const ctx = new Context(items, codeCells, {
10
9
  tabWidth: params.tabWidth != null ? params.tabWidth : 2,
11
10
  });
12
11
  new State(ctx, 0).disasm(ctx.getCode(root));
13
12
  return ctx.output;
14
13
  }
15
- class CodeCells {
16
- constructor(code) {
17
- this.hashToCell = new Map();
18
- const stack = [];
19
- if (code instanceof core_1.Cell) {
20
- stack.push(code);
21
- }
22
- else {
23
- stack.push(core_1.Cell.fromBase64(code));
24
- }
25
- while (stack.length > 0) {
26
- const cell = stack[stack.length - 1];
27
- const reprHash = cell.hash(3).toString("hex");
28
- if (this.hashToCell.has(reprHash)) {
29
- stack.pop();
30
- }
31
- else {
32
- this.hashToCell.set(reprHash, cell);
33
- for (const child of cell.refs) {
34
- stack.push(child);
35
- }
36
- }
37
- }
38
- }
39
- getCell(hash) {
40
- const res = this.hashToCell.get(hash);
41
- if (res == null)
42
- throw new Error("Unknown cell");
43
- return res;
44
- }
45
- }
46
14
  class State {
47
15
  constructor(ctx, depth) {
48
16
  this.ctx = ctx;
@@ -50,22 +18,64 @@ class State {
50
18
  }
51
19
  disasm(block) {
52
20
  while (true) {
21
+ let opcodeBits = 0;
22
+ let opcodeRefs = 0;
53
23
  for (const opcode of block.opcodes) {
54
24
  this.showOp(opcode);
25
+ opcodeBits += opcode.bits;
26
+ opcodeRefs += opcode.refs || 0;
55
27
  }
56
28
  if (block.tail == null) {
29
+ this.dict = undefined;
30
+ this.flushCont();
57
31
  break;
58
32
  }
59
33
  else if (block.tail.type === "incomplete") {
60
- this.writeln("Cannot disassemble");
34
+ this.dict = undefined;
35
+ this.flushCont();
36
+ this.showIncompleteTail(block, opcodeBits, opcodeRefs);
61
37
  break;
62
38
  }
63
39
  else {
64
40
  block = this.ctx.getCode(block.tail.id);
65
41
  }
66
42
  }
67
- this.dict = undefined;
68
- this.flushCont();
43
+ }
44
+ showIncompleteTail(block, opcodeBits, opcodeRefs) {
45
+ const cell = this.ctx.getCell(block.cellHash);
46
+ const bits = cell
47
+ .asSlice()
48
+ .skip(block.offsetBits + opcodeBits)
49
+ .loadBits(block.bits - opcodeBits);
50
+ this.writeln(`Cannot disassemble: x{${bits.toString()}}`);
51
+ const stack = [];
52
+ if (opcodeRefs < block.refs) {
53
+ stack.push({
54
+ depth: 1,
55
+ refs: cell.refs.slice(block.offsetRefs + opcodeRefs, block.offsetRefs + block.refs),
56
+ index: block.offsetRefs + opcodeRefs,
57
+ });
58
+ }
59
+ const prevDepth = this.depth;
60
+ this.depth = 0;
61
+ outer: while (stack.length > 0) {
62
+ const item = stack[stack.length - 1];
63
+ while (item.index < item.refs.length) {
64
+ const child = item.refs[item.index++];
65
+ const indent = " ".repeat(item.depth);
66
+ this.writeln(`${indent}x{${child.bits.toString()}}`);
67
+ if (child.refs.length > 0) {
68
+ stack.push({
69
+ depth: item.depth + 1,
70
+ refs: child.refs,
71
+ index: 0,
72
+ });
73
+ continue outer;
74
+ }
75
+ }
76
+ stack.pop();
77
+ }
78
+ this.depth = prevDepth;
69
79
  }
70
80
  showOp(opcode) {
71
81
  // Track consequent dict ops.
@@ -384,20 +394,20 @@ class Context {
384
394
  break;
385
395
  }
386
396
  case "library": {
387
- cellHash = item.hash;
397
+ cellHash = item.cellHash;
388
398
  break;
389
399
  }
390
- case "dataBlock": {
400
+ case "data": {
391
401
  if (item.data.type !== "cell")
392
402
  throw new Error("Unexpected slice");
393
- cellHash = core_1.Cell.fromBase64(item.data.boc).hash(3).toString("hex");
403
+ cellHash = item.data.cellHash;
394
404
  break;
395
405
  }
396
406
  case "jumpTable": {
397
407
  throw new Error("Unexpected jump table");
398
408
  }
399
409
  }
400
- return `(${cellHash})`;
410
+ return `(${cellHash.toUpperCase()})`;
401
411
  }
402
412
  case "slice": {
403
413
  const item = this.items[arg.id];
@@ -412,12 +422,13 @@ class Context {
412
422
  refCount = item.refs;
413
423
  break;
414
424
  }
415
- case "dataBlock": {
425
+ case "data": {
416
426
  if (item.data.type !== "slice")
417
427
  throw new Error("Unexpected cell");
418
- const slice = core_1.Cell.fromBase64(item.data.boc).asSlice();
419
- bits = slice.loadBits(item.data.bits);
420
- refCount = item.data.refs;
428
+ const { data } = item;
429
+ const cell = this.getCell(data.cellHash);
430
+ bits = cell.asSlice().skip(data.offsetBits).loadBits(data.bits);
431
+ refCount = data.refs;
421
432
  break;
422
433
  }
423
434
  case "jumpTable": {
@@ -432,7 +443,7 @@ class Context {
432
443
  return `(${bits.toString()},${refCount})`;
433
444
  }
434
445
  else {
435
- return bits.toString();
446
+ return `x{${bits.toString()}}`;
436
447
  }
437
448
  }
438
449
  }
@@ -1,4 +1,4 @@
1
- import { Cell } from "@ton/core";
1
+ import { Cell, Slice } from "@ton/core";
2
2
  /**
3
3
  * All code parts are referenced by a numberic ID.
4
4
  */
@@ -18,7 +18,7 @@ export type Item = ({
18
18
  type: "code";
19
19
  } & CodeBlock) | ({
20
20
  id: number;
21
- type: "dataBlock";
21
+ type: "data";
22
22
  } & DataBlock) | ({
23
23
  id: number;
24
24
  type: "library";
@@ -99,19 +99,25 @@ export type Data = ({
99
99
  } & DataCell);
100
100
  export type DataType = Data["type"];
101
101
  export type DataSlice = {
102
+ cellHash: string;
102
103
  offsetBits: number;
103
104
  offsetRefs: number;
104
105
  bits: number;
105
106
  refs: number;
106
- boc: string;
107
107
  };
108
108
  export type DataCell = {
109
- boc: string;
109
+ cellHash: string;
110
110
  };
111
111
  export type Library = {
112
- hash: string;
112
+ cellHash: string;
113
113
  };
114
114
  export declare function disasmStructured(code: Cell | string): Promise<Code>;
115
+ export declare class CodeCells {
116
+ private hashToCell;
117
+ constructor(code: Cell | string);
118
+ getCell(hash: DataCell | DataSlice | Library | JumpTable | CodeBlock | string): Cell;
119
+ getSlice(slice: DataSlice | CodeBlock): Slice;
120
+ }
115
121
  export declare function expectJumpTable(item: Item): asserts item is {
116
122
  id: ItemId;
117
123
  type: "jumpTable";
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodeCells = void 0;
3
4
  exports.disasmStructured = disasmStructured;
4
5
  exports.expectJumpTable = expectJumpTable;
5
6
  exports.expectCont = expectCont;
@@ -15,6 +16,7 @@ exports.expectSliceArg = expectSliceArg;
15
16
  exports.expectContArg = expectContArg;
16
17
  const core_1 = require("@ton/core");
17
18
  const env_1 = require("../env");
19
+ const slice_1 = require("../util/slice");
18
20
  async function disasmStructured(code) {
19
21
  await (0, env_1.wasmLoaded)();
20
22
  let boc;
@@ -28,6 +30,51 @@ async function disasmStructured(code) {
28
30
  const parsed = JSON.parse(res);
29
31
  return parsed;
30
32
  }
33
+ class CodeCells {
34
+ constructor(code) {
35
+ this.hashToCell = new Map();
36
+ if (typeof code === "string") {
37
+ code = core_1.Cell.fromBase64(code);
38
+ }
39
+ const stack = [];
40
+ const addCell = (cell) => {
41
+ const reprHash = cell.hash(3).toString("hex");
42
+ if (this.hashToCell.has(reprHash)) {
43
+ return false;
44
+ }
45
+ this.hashToCell.set(reprHash, cell);
46
+ if (cell.refs.length > 0) {
47
+ stack.push({ refs: cell.refs, index: 0 });
48
+ }
49
+ return true;
50
+ };
51
+ addCell(code);
52
+ outer: while (stack.length > 0) {
53
+ const item = stack[stack.length - 1];
54
+ while (item.index < item.refs.length) {
55
+ const child = item.refs[item.index++];
56
+ if (addCell(child)) {
57
+ continue outer;
58
+ }
59
+ }
60
+ stack.pop();
61
+ }
62
+ }
63
+ getCell(hash) {
64
+ if (typeof hash === "object") {
65
+ hash = hash.cellHash;
66
+ }
67
+ const res = this.hashToCell.get(hash);
68
+ if (res == null)
69
+ throw new Error("Unknown cell");
70
+ return res;
71
+ }
72
+ getSlice(slice) {
73
+ const cell = this.getCell(slice);
74
+ return (0, slice_1.makeSlice)(cell, slice.offsetBits, slice.offsetRefs, slice.bits, slice.refs);
75
+ }
76
+ }
77
+ exports.CodeCells = CodeCells;
31
78
  // === Expect Item ===
32
79
  function expectJumpTable(item) {
33
80
  if (item.type !== "jumpTable")
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { disasmStructured, expectCellArg, expectCont, expectContArg, expectData, expectDataCell, expectDataSlice, expectIntArg, expectJumpTable, expectLibrary, expectRegArg, expectSliceArg, expectStackArg, Code, CodeBlock, CodeBlockTail, CodeBlockTailType, Data, DataBlock, DataCell, DataSlice, DataType, Item, ItemId, ItemType, JumpTable, Library, Opcode, OpcodeArg, OpcodeArgType, } from "./disasm/structured";
1
+ export { disasmStructured, expectCellArg, expectCont, expectContArg, expectData, expectDataCell, expectDataSlice, expectIntArg, expectJumpTable, expectLibrary, expectRegArg, expectSliceArg, expectStackArg, Code, CodeBlock, CodeBlockTail, CodeBlockTailType, CodeCells, Data, DataBlock, DataCell, DataSlice, DataType, Item, ItemId, ItemType, JumpTable, Library, Opcode, OpcodeArg, OpcodeArgType, } from "./disasm/structured";
2
2
  export { disasmToFift } from "./disasm/fift";
3
3
  export { makeSlice } from "./util/slice";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeSlice = exports.disasmToFift = exports.expectStackArg = exports.expectSliceArg = exports.expectRegArg = exports.expectLibrary = exports.expectJumpTable = exports.expectIntArg = exports.expectDataSlice = exports.expectDataCell = exports.expectData = exports.expectContArg = exports.expectCont = exports.expectCellArg = exports.disasmStructured = void 0;
3
+ exports.makeSlice = exports.disasmToFift = exports.CodeCells = exports.expectStackArg = exports.expectSliceArg = exports.expectRegArg = exports.expectLibrary = exports.expectJumpTable = exports.expectIntArg = exports.expectDataSlice = exports.expectDataCell = exports.expectData = exports.expectContArg = exports.expectCont = exports.expectCellArg = exports.disasmStructured = void 0;
4
4
  var structured_1 = require("./disasm/structured");
5
5
  Object.defineProperty(exports, "disasmStructured", { enumerable: true, get: function () { return structured_1.disasmStructured; } });
6
6
  Object.defineProperty(exports, "expectCellArg", { enumerable: true, get: function () { return structured_1.expectCellArg; } });
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "expectLibrary", { enumerable: true, get: functio
15
15
  Object.defineProperty(exports, "expectRegArg", { enumerable: true, get: function () { return structured_1.expectRegArg; } });
16
16
  Object.defineProperty(exports, "expectSliceArg", { enumerable: true, get: function () { return structured_1.expectSliceArg; } });
17
17
  Object.defineProperty(exports, "expectStackArg", { enumerable: true, get: function () { return structured_1.expectStackArg; } });
18
+ Object.defineProperty(exports, "CodeCells", { enumerable: true, get: function () { return structured_1.CodeCells; } });
18
19
  var fift_1 = require("./disasm/fift");
19
20
  Object.defineProperty(exports, "disasmToFift", { enumerable: true, get: function () { return fift_1.disasmToFift; } });
20
21
  var slice_1 = require("./util/slice");
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tychosdk/disasm",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Tycho TVM disasm",
5
5
  "main": "dist/index.js",
6
6
  "browser": {