@tact-lang/opcode
Advanced tools
Comparing version 0.0.10 to 0.0.11
@@ -8,2 +8,7 @@ # Changelog | ||
## [0.0.11] - 2023-03-27 | ||
## Fixed | ||
- Fixed implicit jump handling | ||
## [0.0.10] - 2023-03-27 | ||
@@ -10,0 +15,0 @@ |
@@ -5,3 +5,3 @@ import { Cell, Slice } from 'ton-core'; | ||
export type Op = OpCode; | ||
type OpResolver = ((slice: Slice) => Op) | Op; | ||
type OpResolver = ((slice: Slice, cell: Cell) => Op) | Op; | ||
export declare class Codepage { | ||
@@ -8,0 +8,0 @@ private readonly _trie; |
@@ -1,4 +0,4 @@ | ||
import { Slice } from "ton-core"; | ||
import { Cell, Slice } from "ton-core"; | ||
import { OpCode } from "./opcodes.gen"; | ||
export declare function loadOpcode(sc: Slice): { | ||
export declare function loadOpcode(slice: Slice, cell: Cell): { | ||
readonly ok: false; | ||
@@ -5,0 +5,0 @@ readonly read: string; |
@@ -6,7 +6,7 @@ "use strict"; | ||
const codepage = opcodes_1.CP0Auto; | ||
function loadOpcode(sc) { | ||
function loadOpcode(slice, cell) { | ||
let opCode = ''; | ||
while (sc.remainingBits > 0) { | ||
while (slice.remainingBits > 0) { | ||
// Load next bit | ||
let opCodePart = sc.loadBit(); | ||
let opCodePart = slice.loadBit(); | ||
opCode += opCodePart ? '1' : '0'; | ||
@@ -30,3 +30,3 @@ // Find opcode in codepage | ||
if (typeof op === 'function') { | ||
resolvedOpcode = op(sc); | ||
resolvedOpcode = op(slice, cell); | ||
} | ||
@@ -33,0 +33,0 @@ else { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.CP0Auto = void 0; | ||
const ton_core_1 = require("ton-core"); | ||
const Codepage_1 = require("./Codepage"); | ||
@@ -275,3 +274,3 @@ const CP0Auto = new Codepage_1.Codepage(); | ||
CP0Auto.insertHex('8a', 8, (slice) => ({ code: 'PUSHREFCONT', args: [slice.loadRef()] })); | ||
CP0Auto.insertHex('8b', 8, (slice) => { | ||
CP0Auto.insertHex('8b', 8, (slice, cell) => { | ||
let x = slice.loadUint(4); | ||
@@ -282,6 +281,6 @@ let bits = 8 * x + 4; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHSLICE', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}); | ||
CP0Auto.insertHex('8c', 8, (slice) => { | ||
CP0Auto.insertHex('8c', 8, (slice, cell) => { | ||
let refs = slice.loadUint(2) + 1; | ||
@@ -291,6 +290,6 @@ let bits = (8 * slice.loadUint(5) + 1); | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHSLICE', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}); | ||
CP0Auto.insertHex('8d', 8, (slice) => { | ||
CP0Auto.insertHex('8d', 8, (slice, cell) => { | ||
let refs = slice.loadUint(3); | ||
@@ -300,7 +299,7 @@ let bits = 8 * slice.loadUint(7) + 6; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHSLICE', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}); | ||
// 9281536 (DUMMY) | ||
CP0Auto.insertHex('8E', 7, (slice) => { | ||
CP0Auto.insertHex('8E', 7, (slice, cell) => { | ||
let args = slice.loadUint(9); | ||
@@ -311,6 +310,6 @@ let refs = (args >> 7) & 3; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHCONT', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}); | ||
CP0Auto.insertHex('9', 4, (slice) => { | ||
CP0Auto.insertHex('9', 4, (slice, cell) => { | ||
let bits = slice.loadUint(4) * 8; | ||
@@ -320,3 +319,3 @@ let refs = 0; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHCONT', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
@@ -545,3 +544,3 @@ }); | ||
// 13583104 (DUMMY) | ||
CP0Auto.insertHex('cf8', 9, (slice) => { | ||
CP0Auto.insertHex('cf8', 9, (slice, cell) => { | ||
let refs = slice.loadUint(2); | ||
@@ -551,3 +550,3 @@ let bits = slice.loadUint(3) * 8 + 1; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: `STSLICECONST`, args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
@@ -1181,9 +1180,7 @@ }); | ||
// | ||
function loadSubslice(slice, bits, refs) { | ||
let b = (0, ton_core_1.beginCell)() | ||
.storeBits(slice.loadBits(bits)); | ||
function skipSubslice(slice, bits, refs) { | ||
slice.skip(bits); | ||
for (let i = 0; i < (refs || 0); i++) { | ||
b.storeRef(slice.loadRef()); | ||
slice.loadRef(); | ||
} | ||
return b.asCell(); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.opcodeToString = void 0; | ||
const subcell_1 = require("../utils/subcell"); | ||
const opcodes_gen_1 = require("./opcodes.gen"); | ||
@@ -79,3 +80,10 @@ function opcodeToString(op) { | ||
|| op.code === 'STSLICECONST') { | ||
return `${op.args[0]} ${op.code}`; | ||
let c = (0, subcell_1.subcell)({ | ||
cell: op.args[0], | ||
offsetBits: op.args[1], | ||
offsetRefs: op.args[2], | ||
bits: op.args[3], | ||
refs: op.args[4] | ||
}); | ||
return `${c} ${op.code}`; | ||
} | ||
@@ -82,0 +90,0 @@ // Debug |
@@ -120,3 +120,3 @@ "use strict"; | ||
decompileCell({ | ||
src: args.src, | ||
src: opcode.args[0], | ||
offset: { bits: opcode.args[1], refs: opcode.args[2] }, | ||
@@ -123,0 +123,0 @@ limit: { bits: opcode.args[3], refs: opcode.args[4] }, |
@@ -31,18 +31,15 @@ "use strict"; | ||
// Prepare offset | ||
let bitsLimit = args.limit ? (args.limit.bits + bitsDelta) : source.bits.length; | ||
let refsLimit = args.limit ? (args.limit.refs + refsDelta) : source.refs.length; | ||
let slice = (0, subcell_1.subcell)({ | ||
let bitsLimit = args.limit ? (args.limit.bits) : source.bits.length - bitsDelta; | ||
let refsLimit = args.limit ? (args.limit.refs) : source.refs.length - refsDelta; | ||
let slice = (0, subcell_1.subslice)({ | ||
cell: source, | ||
offsetBits: bitsDelta, | ||
offsetRefs: refsDelta, | ||
bits: bitsLimit, | ||
refs: refsLimit | ||
}).beginParse(); | ||
if (args.offset) { | ||
slice.skip(args.offset.bits); | ||
for (let i = 0; i < args.offset.refs; i++) | ||
slice.loadRef(); | ||
} | ||
}); | ||
while (slice.remainingBits > 0) { | ||
// Load opcode | ||
const opcodeOffset = slice.offsetBits; | ||
const opcode = (0, loadOpcode_1.loadOpcode)(slice); | ||
const opcode = (0, loadOpcode_1.loadOpcode)(slice, source); | ||
const opcodeLength = slice.offsetBits - opcodeOffset; | ||
@@ -81,5 +78,5 @@ // Failed case | ||
if (slice.remainingBits === 0 && slice.remainingRefs > 0) { | ||
let n = slice.loadRef(); | ||
hash = n.hash().toString('hex'); | ||
slice = n.beginParse(); | ||
source = slice.loadRef(); | ||
hash = source.hash().toString('hex'); | ||
slice = source.beginParse(); | ||
} | ||
@@ -86,0 +83,0 @@ } |
@@ -1,6 +0,15 @@ | ||
import { Cell } from "ton-core"; | ||
import { Cell, Slice } from "ton-core"; | ||
export declare function subcell(args: { | ||
cell: Cell; | ||
offsetBits: number; | ||
offsetRefs: number; | ||
bits: number; | ||
refs: number; | ||
}): Cell; | ||
export declare function subslice(args: { | ||
cell: Cell; | ||
offsetBits: number; | ||
offsetRefs: number; | ||
bits: number; | ||
refs: number; | ||
}): Slice; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.subcell = void 0; | ||
exports.subslice = exports.subcell = void 0; | ||
const ton_core_1 = require("ton-core"); | ||
@@ -8,2 +8,7 @@ function subcell(args) { | ||
let b = (0, ton_core_1.beginCell)(); | ||
// Skip bits and refs | ||
s.skip(args.offsetBits); | ||
for (let i = 0; i < args.offsetRefs; i++) { | ||
s.loadRef(); | ||
} | ||
// Copy bits and refs | ||
@@ -17,1 +22,18 @@ b.storeBits(s.loadBits(args.bits)); | ||
exports.subcell = subcell; | ||
function subslice(args) { | ||
let s = args.cell.beginParse(); | ||
let b = (0, ton_core_1.beginCell)(); | ||
// Copu bits and refs | ||
b.storeBits(s.loadBits(args.bits + args.offsetBits)); | ||
for (let i = 0; i < args.refs + args.offsetRefs; i++) { | ||
b.storeRef(s.loadRef()); | ||
} | ||
let s2 = b.endCell().beginParse(); | ||
// Skip bits and refs | ||
s2.skip(args.offsetBits); | ||
for (let i = 0; i < args.offsetRefs; i++) { | ||
s2.loadRef(); | ||
} | ||
return s2; | ||
} | ||
exports.subslice = subslice; |
{ | ||
"name": "@tact-lang/opcode", | ||
"version": "0.0.10", | ||
"version": "0.0.11", | ||
"main": "dist/index.js", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/tact-lang/ton-opcode.git", |
@@ -8,3 +8,3 @@ import { Cell, Slice } from 'ton-core'; | ||
type OpResolver = ((slice: Slice) => Op) | Op | ||
type OpResolver = ((slice: Slice, cell: Cell) => Op) | Op | ||
@@ -11,0 +11,0 @@ export class Codepage { |
@@ -7,8 +7,8 @@ import { Cell, Slice } from "ton-core"; | ||
export function loadOpcode(sc: Slice) { | ||
export function loadOpcode(slice: Slice, cell: Cell) { | ||
let opCode = ''; | ||
while (sc.remainingBits > 0) { | ||
while (slice.remainingBits > 0) { | ||
// Load next bit | ||
let opCodePart = sc.loadBit(); | ||
let opCodePart = slice.loadBit(); | ||
opCode += opCodePart ? '1' : '0' | ||
@@ -35,3 +35,3 @@ | ||
if (typeof op === 'function') { | ||
resolvedOpcode = op(sc); | ||
resolvedOpcode = op(slice, cell); | ||
} else { | ||
@@ -38,0 +38,0 @@ resolvedOpcode = op; |
@@ -1,2 +0,2 @@ | ||
import { beginCell, Slice } from 'ton-core'; | ||
import { beginCell, Cell, Slice } from 'ton-core'; | ||
import { Codepage } from './Codepage'; | ||
@@ -273,3 +273,3 @@ | ||
CP0Auto.insertHex('8a', 8, (slice) => ({ code: 'PUSHREFCONT', args: [slice.loadRef()] })); | ||
CP0Auto.insertHex('8b', 8, (slice) => { | ||
CP0Auto.insertHex('8b', 8, (slice, cell) => { | ||
let x = slice.loadUint(4); | ||
@@ -280,6 +280,6 @@ let bits = 8 * x + 4; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHSLICE', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}); | ||
CP0Auto.insertHex('8c', 8, (slice) => { | ||
CP0Auto.insertHex('8c', 8, (slice, cell) => { | ||
let refs = slice.loadUint(2) + 1; | ||
@@ -289,6 +289,6 @@ let bits = (8 * slice.loadUint(5) + 1); | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHSLICE', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}); | ||
CP0Auto.insertHex('8d', 8, (slice) => { | ||
CP0Auto.insertHex('8d', 8, (slice, cell) => { | ||
let refs = slice.loadUint(3); | ||
@@ -298,7 +298,7 @@ let bits = 8 * slice.loadUint(7) + 6; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHSLICE', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}); | ||
// 9281536 (DUMMY) | ||
CP0Auto.insertHex('8E', 7, (slice) => { | ||
CP0Auto.insertHex('8E', 7, (slice, cell) => { | ||
let args = slice.loadUint(9); | ||
@@ -309,6 +309,6 @@ let refs = (args >> 7) & 3; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHCONT', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
}) | ||
CP0Auto.insertHex('9', 4, (slice) => { | ||
CP0Auto.insertHex('9', 4, (slice, cell) => { | ||
let bits = slice.loadUint(4) * 8; | ||
@@ -318,3 +318,3 @@ let refs = 0; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: 'PUSHCONT', args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
@@ -543,3 +543,3 @@ }) | ||
// 13583104 (DUMMY) | ||
CP0Auto.insertHex('cf8', 9, (slice) => { | ||
CP0Auto.insertHex('cf8', 9, (slice, cell) => { | ||
let refs = slice.loadUint(2); | ||
@@ -549,3 +549,3 @@ let bits = slice.loadUint(3) * 8 + 1; | ||
let refsOffset = slice.offsetRefs; | ||
let cell = loadSubslice(slice, bits, refs); | ||
skipSubslice(slice, bits, refs); | ||
return { code: `STSLICECONST`, args: [cell, bitsOffset, refsOffset, bits, refs] }; | ||
@@ -1192,9 +1192,7 @@ }); | ||
function loadSubslice(slice: Slice, bits: number, refs?: number) { | ||
let b = beginCell() | ||
.storeBits(slice.loadBits(bits)); | ||
function skipSubslice(slice: Slice, bits: number, refs?: number) { | ||
slice.skip(bits); | ||
for (let i = 0; i < (refs || 0); i++) { | ||
b.storeRef(slice.loadRef()); | ||
slice.loadRef(); | ||
} | ||
return b.asCell(); | ||
} |
@@ -0,1 +1,2 @@ | ||
import { subcell } from "../utils/subcell"; | ||
import { isOpCodeWithArgs, OpCode } from "./opcodes.gen"; | ||
@@ -81,3 +82,10 @@ | ||
|| op.code === 'STSLICECONST') { | ||
return `${op.args[0]} ${op.code}`; | ||
let c = subcell({ | ||
cell: op.args[0], | ||
offsetBits: op.args[1], | ||
offsetRefs: op.args[2], | ||
bits: op.args[3], | ||
refs: op.args[4] | ||
}); | ||
return `${c} ${op.code}`; | ||
} | ||
@@ -84,0 +92,0 @@ |
@@ -61,2 +61,8 @@ import { decompileAll } from "./decompileAll"; | ||
}); | ||
it('should decompile wallet', () => { | ||
const wallet = fs.readFileSync(__dirname + '/__testdata__/wallet_Wallet.code.boc'); | ||
let res = decompileAll({ src: wallet }); | ||
expect(res).toMatchSnapshot(); | ||
}); | ||
}); |
@@ -137,3 +137,3 @@ import { Cell, Dictionary, DictionaryValue } from "ton-core"; | ||
decompileCell({ | ||
src: args.src, | ||
src: opcode.args[0], | ||
offset: { bits: opcode.args[1], refs: opcode.args[2] }, | ||
@@ -140,0 +140,0 @@ limit: { bits: opcode.args[3], refs: opcode.args[4] }, |
@@ -5,3 +5,3 @@ import { beginCell, Cell, Slice } from "ton-core"; | ||
import { Maybe } from "../utils/maybe"; | ||
import { subcell } from "../utils/subcell"; | ||
import { subcell, subslice } from "../utils/subcell"; | ||
@@ -48,14 +48,11 @@ export type DecompiledOpCode = OpCode | { code: 'unknown', data: Cell }; | ||
// Prepare offset | ||
let bitsLimit = args.limit ? (args.limit.bits + bitsDelta) : source.bits.length; | ||
let refsLimit = args.limit ? (args.limit.refs + refsDelta) : source.refs.length; | ||
let slice = subcell({ | ||
let bitsLimit = args.limit ? (args.limit.bits) : source.bits.length - bitsDelta; | ||
let refsLimit = args.limit ? (args.limit.refs) : source.refs.length - refsDelta; | ||
let slice = subslice({ | ||
cell: source, | ||
offsetBits: bitsDelta, | ||
offsetRefs: refsDelta, | ||
bits: bitsLimit, | ||
refs: refsLimit | ||
}).beginParse(); | ||
if (args.offset) { | ||
slice.skip(args.offset.bits); | ||
for (let i = 0; i < args.offset.refs; i++) | ||
slice.loadRef(); | ||
} | ||
}); | ||
@@ -66,3 +63,3 @@ while (slice.remainingBits > 0) { | ||
const opcodeOffset = slice.offsetBits; | ||
const opcode = loadOpcode(slice); | ||
const opcode = loadOpcode(slice, source); | ||
const opcodeLength = slice.offsetBits - opcodeOffset; | ||
@@ -103,5 +100,5 @@ | ||
if (slice.remainingBits === 0 && slice.remainingRefs > 0) { | ||
let n = slice.loadRef(); | ||
hash = n.hash().toString('hex'); | ||
slice = n.beginParse(); | ||
source = slice.loadRef(); | ||
hash = source.hash().toString('hex'); | ||
slice = source.beginParse(); | ||
} | ||
@@ -108,0 +105,0 @@ } |
@@ -1,7 +0,13 @@ | ||
import { beginCell, Cell } from "ton-core"; | ||
import { beginCell, Cell, Slice } from "ton-core"; | ||
export function subcell(args: { cell: Cell, bits: number, refs: number }): Cell { | ||
export function subcell(args: { cell: Cell, offsetBits: number, offsetRefs: number, bits: number, refs: number }): Cell { | ||
let s = args.cell.beginParse(); | ||
let b = beginCell(); | ||
// Skip bits and refs | ||
s.skip(args.offsetBits); | ||
for (let i = 0; i < args.offsetRefs; i++) { | ||
s.loadRef(); | ||
} | ||
// Copy bits and refs | ||
@@ -14,2 +20,23 @@ b.storeBits(s.loadBits(args.bits)); | ||
return b.endCell(); | ||
} | ||
export function subslice(args: { cell: Cell, offsetBits: number, offsetRefs: number, bits: number, refs: number }): Slice { | ||
let s = args.cell.beginParse(); | ||
let b = beginCell(); | ||
// Copu bits and refs | ||
b.storeBits(s.loadBits(args.bits + args.offsetBits)); | ||
for (let i = 0; i < args.refs + args.offsetRefs; i++) { | ||
b.storeRef(s.loadRef()); | ||
} | ||
let s2 = b.endCell().beginParse(); | ||
// Skip bits and refs | ||
s2.skip(args.offsetBits); | ||
for (let i = 0; i < args.offsetRefs; i++) { | ||
s2.loadRef(); | ||
} | ||
return s2; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6102129
69
6116
3