From 2a2d82e5836ad758eb2bffbc922035dca6ac75ba Mon Sep 17 00:00:00 2001 From: PeterParker <149929152+decentraldev1@users.noreply.github.com> Date: Fri, 27 Dec 2024 17:55:48 +0800 Subject: [PATCH] Optimize OPS type from Record to Enum (#2189) * feat: use enum enhance OPS types * feat: update OPS reference * wip: update OPS avoid duplicate value * wip: build src * wip: set REVERSE_OPS as alias of OPS * wip: remove REVERSE_OPS and add check if the chunk is a valid opcode string in OPS * test: add OPS test * test: add decodes OP_FALSE as empty buffer * test: add decodes a series of numbers from '82 to 96' correctly * test: optimize unit test --- src/cjs/ops.cjs | 253 ++++++++++++++++++++-------------------- src/cjs/ops.d.ts | 129 ++++++++++++++++++-- src/cjs/script.cjs | 18 +-- src/esm/ops.js | 252 ++++++++++++++++++++------------------- src/esm/script.js | 20 ++-- test/ops.spec.ts | 47 ++++++++ test/script.spec.ts | 21 ++++ ts_src/ops.ts | 278 ++++++++++++++++++++++---------------------- ts_src/script.ts | 21 ++-- 9 files changed, 612 insertions(+), 427 deletions(-) create mode 100644 test/ops.spec.ts diff --git a/src/cjs/ops.cjs b/src/cjs/ops.cjs index 7853ad0f0..7e9f27bb8 100644 --- a/src/cjs/ops.cjs +++ b/src/cjs/ops.cjs @@ -1,131 +1,126 @@ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); -exports.REVERSE_OPS = exports.OPS = void 0; -const OPS = { - OP_FALSE: 0, - OP_0: 0, - OP_PUSHDATA1: 76, - OP_PUSHDATA2: 77, - OP_PUSHDATA4: 78, - OP_1NEGATE: 79, - OP_RESERVED: 80, - OP_TRUE: 81, - OP_1: 81, - OP_2: 82, - OP_3: 83, - OP_4: 84, - OP_5: 85, - OP_6: 86, - OP_7: 87, - OP_8: 88, - OP_9: 89, - OP_10: 90, - OP_11: 91, - OP_12: 92, - OP_13: 93, - OP_14: 94, - OP_15: 95, - OP_16: 96, - OP_NOP: 97, - OP_VER: 98, - OP_IF: 99, - OP_NOTIF: 100, - OP_VERIF: 101, - OP_VERNOTIF: 102, - OP_ELSE: 103, - OP_ENDIF: 104, - OP_VERIFY: 105, - OP_RETURN: 106, - OP_TOALTSTACK: 107, - OP_FROMALTSTACK: 108, - OP_2DROP: 109, - OP_2DUP: 110, - OP_3DUP: 111, - OP_2OVER: 112, - OP_2ROT: 113, - OP_2SWAP: 114, - OP_IFDUP: 115, - OP_DEPTH: 116, - OP_DROP: 117, - OP_DUP: 118, - OP_NIP: 119, - OP_OVER: 120, - OP_PICK: 121, - OP_ROLL: 122, - OP_ROT: 123, - OP_SWAP: 124, - OP_TUCK: 125, - OP_CAT: 126, - OP_SUBSTR: 127, - OP_LEFT: 128, - OP_RIGHT: 129, - OP_SIZE: 130, - OP_INVERT: 131, - OP_AND: 132, - OP_OR: 133, - OP_XOR: 134, - OP_EQUAL: 135, - OP_EQUALVERIFY: 136, - OP_RESERVED1: 137, - OP_RESERVED2: 138, - OP_1ADD: 139, - OP_1SUB: 140, - OP_2MUL: 141, - OP_2DIV: 142, - OP_NEGATE: 143, - OP_ABS: 144, - OP_NOT: 145, - OP_0NOTEQUAL: 146, - OP_ADD: 147, - OP_SUB: 148, - OP_MUL: 149, - OP_DIV: 150, - OP_MOD: 151, - OP_LSHIFT: 152, - OP_RSHIFT: 153, - OP_BOOLAND: 154, - OP_BOOLOR: 155, - OP_NUMEQUAL: 156, - OP_NUMEQUALVERIFY: 157, - OP_NUMNOTEQUAL: 158, - OP_LESSTHAN: 159, - OP_GREATERTHAN: 160, - OP_LESSTHANOREQUAL: 161, - OP_GREATERTHANOREQUAL: 162, - OP_MIN: 163, - OP_MAX: 164, - OP_WITHIN: 165, - OP_RIPEMD160: 166, - OP_SHA1: 167, - OP_SHA256: 168, - OP_HASH160: 169, - OP_HASH256: 170, - OP_CODESEPARATOR: 171, - OP_CHECKSIG: 172, - OP_CHECKSIGVERIFY: 173, - OP_CHECKMULTISIG: 174, - OP_CHECKMULTISIGVERIFY: 175, - OP_NOP1: 176, - OP_NOP2: 177, - OP_CHECKLOCKTIMEVERIFY: 177, - OP_NOP3: 178, - OP_CHECKSEQUENCEVERIFY: 178, - OP_NOP4: 179, - OP_NOP5: 180, - OP_NOP6: 181, - OP_NOP7: 182, - OP_NOP8: 183, - OP_NOP9: 184, - OP_NOP10: 185, - OP_CHECKSIGADD: 186, - OP_PUBKEYHASH: 253, - OP_PUBKEY: 254, - OP_INVALIDOPCODE: 255, -}; -exports.OPS = OPS; -const REVERSE_OPS = {}; -exports.REVERSE_OPS = REVERSE_OPS; -for (const op of Object.keys(OPS)) { - const code = OPS[op]; - REVERSE_OPS[code] = op; -} +exports.OPS = void 0; +// Define OPS enum +var OPS; +(function (OPS) { + OPS[(OPS['OP_FALSE'] = 0)] = 'OP_FALSE'; + OPS[(OPS['OP_0'] = 0)] = 'OP_0'; + OPS[(OPS['OP_PUSHDATA1'] = 76)] = 'OP_PUSHDATA1'; + OPS[(OPS['OP_PUSHDATA2'] = 77)] = 'OP_PUSHDATA2'; + OPS[(OPS['OP_PUSHDATA4'] = 78)] = 'OP_PUSHDATA4'; + OPS[(OPS['OP_1NEGATE'] = 79)] = 'OP_1NEGATE'; + OPS[(OPS['OP_RESERVED'] = 80)] = 'OP_RESERVED'; + OPS[(OPS['OP_TRUE'] = 81)] = 'OP_TRUE'; + OPS[(OPS['OP_1'] = 81)] = 'OP_1'; + OPS[(OPS['OP_2'] = 82)] = 'OP_2'; + OPS[(OPS['OP_3'] = 83)] = 'OP_3'; + OPS[(OPS['OP_4'] = 84)] = 'OP_4'; + OPS[(OPS['OP_5'] = 85)] = 'OP_5'; + OPS[(OPS['OP_6'] = 86)] = 'OP_6'; + OPS[(OPS['OP_7'] = 87)] = 'OP_7'; + OPS[(OPS['OP_8'] = 88)] = 'OP_8'; + OPS[(OPS['OP_9'] = 89)] = 'OP_9'; + OPS[(OPS['OP_10'] = 90)] = 'OP_10'; + OPS[(OPS['OP_11'] = 91)] = 'OP_11'; + OPS[(OPS['OP_12'] = 92)] = 'OP_12'; + OPS[(OPS['OP_13'] = 93)] = 'OP_13'; + OPS[(OPS['OP_14'] = 94)] = 'OP_14'; + OPS[(OPS['OP_15'] = 95)] = 'OP_15'; + OPS[(OPS['OP_16'] = 96)] = 'OP_16'; + OPS[(OPS['OP_NOP'] = 97)] = 'OP_NOP'; + OPS[(OPS['OP_VER'] = 98)] = 'OP_VER'; + OPS[(OPS['OP_IF'] = 99)] = 'OP_IF'; + OPS[(OPS['OP_NOTIF'] = 100)] = 'OP_NOTIF'; + OPS[(OPS['OP_VERIF'] = 101)] = 'OP_VERIF'; + OPS[(OPS['OP_VERNOTIF'] = 102)] = 'OP_VERNOTIF'; + OPS[(OPS['OP_ELSE'] = 103)] = 'OP_ELSE'; + OPS[(OPS['OP_ENDIF'] = 104)] = 'OP_ENDIF'; + OPS[(OPS['OP_VERIFY'] = 105)] = 'OP_VERIFY'; + OPS[(OPS['OP_RETURN'] = 106)] = 'OP_RETURN'; + OPS[(OPS['OP_TOALTSTACK'] = 107)] = 'OP_TOALTSTACK'; + OPS[(OPS['OP_FROMALTSTACK'] = 108)] = 'OP_FROMALTSTACK'; + OPS[(OPS['OP_2DROP'] = 109)] = 'OP_2DROP'; + OPS[(OPS['OP_2DUP'] = 110)] = 'OP_2DUP'; + OPS[(OPS['OP_3DUP'] = 111)] = 'OP_3DUP'; + OPS[(OPS['OP_2OVER'] = 112)] = 'OP_2OVER'; + OPS[(OPS['OP_2ROT'] = 113)] = 'OP_2ROT'; + OPS[(OPS['OP_2SWAP'] = 114)] = 'OP_2SWAP'; + OPS[(OPS['OP_IFDUP'] = 115)] = 'OP_IFDUP'; + OPS[(OPS['OP_DEPTH'] = 116)] = 'OP_DEPTH'; + OPS[(OPS['OP_DROP'] = 117)] = 'OP_DROP'; + OPS[(OPS['OP_DUP'] = 118)] = 'OP_DUP'; + OPS[(OPS['OP_NIP'] = 119)] = 'OP_NIP'; + OPS[(OPS['OP_OVER'] = 120)] = 'OP_OVER'; + OPS[(OPS['OP_PICK'] = 121)] = 'OP_PICK'; + OPS[(OPS['OP_ROLL'] = 122)] = 'OP_ROLL'; + OPS[(OPS['OP_ROT'] = 123)] = 'OP_ROT'; + OPS[(OPS['OP_SWAP'] = 124)] = 'OP_SWAP'; + OPS[(OPS['OP_TUCK'] = 125)] = 'OP_TUCK'; + OPS[(OPS['OP_CAT'] = 126)] = 'OP_CAT'; + OPS[(OPS['OP_SUBSTR'] = 127)] = 'OP_SUBSTR'; + OPS[(OPS['OP_LEFT'] = 128)] = 'OP_LEFT'; + OPS[(OPS['OP_RIGHT'] = 129)] = 'OP_RIGHT'; + OPS[(OPS['OP_SIZE'] = 130)] = 'OP_SIZE'; + OPS[(OPS['OP_INVERT'] = 131)] = 'OP_INVERT'; + OPS[(OPS['OP_AND'] = 132)] = 'OP_AND'; + OPS[(OPS['OP_OR'] = 133)] = 'OP_OR'; + OPS[(OPS['OP_XOR'] = 134)] = 'OP_XOR'; + OPS[(OPS['OP_EQUAL'] = 135)] = 'OP_EQUAL'; + OPS[(OPS['OP_EQUALVERIFY'] = 136)] = 'OP_EQUALVERIFY'; + OPS[(OPS['OP_RESERVED1'] = 137)] = 'OP_RESERVED1'; + OPS[(OPS['OP_RESERVED2'] = 138)] = 'OP_RESERVED2'; + OPS[(OPS['OP_1ADD'] = 139)] = 'OP_1ADD'; + OPS[(OPS['OP_1SUB'] = 140)] = 'OP_1SUB'; + OPS[(OPS['OP_2MUL'] = 141)] = 'OP_2MUL'; + OPS[(OPS['OP_2DIV'] = 142)] = 'OP_2DIV'; + OPS[(OPS['OP_NEGATE'] = 143)] = 'OP_NEGATE'; + OPS[(OPS['OP_ABS'] = 144)] = 'OP_ABS'; + OPS[(OPS['OP_NOT'] = 145)] = 'OP_NOT'; + OPS[(OPS['OP_0NOTEQUAL'] = 146)] = 'OP_0NOTEQUAL'; + OPS[(OPS['OP_ADD'] = 147)] = 'OP_ADD'; + OPS[(OPS['OP_SUB'] = 148)] = 'OP_SUB'; + OPS[(OPS['OP_MUL'] = 149)] = 'OP_MUL'; + OPS[(OPS['OP_DIV'] = 150)] = 'OP_DIV'; + OPS[(OPS['OP_MOD'] = 151)] = 'OP_MOD'; + OPS[(OPS['OP_LSHIFT'] = 152)] = 'OP_LSHIFT'; + OPS[(OPS['OP_RSHIFT'] = 153)] = 'OP_RSHIFT'; + OPS[(OPS['OP_BOOLAND'] = 154)] = 'OP_BOOLAND'; + OPS[(OPS['OP_BOOLOR'] = 155)] = 'OP_BOOLOR'; + OPS[(OPS['OP_NUMEQUAL'] = 156)] = 'OP_NUMEQUAL'; + OPS[(OPS['OP_NUMEQUALVERIFY'] = 157)] = 'OP_NUMEQUALVERIFY'; + OPS[(OPS['OP_NUMNOTEQUAL'] = 158)] = 'OP_NUMNOTEQUAL'; + OPS[(OPS['OP_LESSTHAN'] = 159)] = 'OP_LESSTHAN'; + OPS[(OPS['OP_GREATERTHAN'] = 160)] = 'OP_GREATERTHAN'; + OPS[(OPS['OP_LESSTHANOREQUAL'] = 161)] = 'OP_LESSTHANOREQUAL'; + OPS[(OPS['OP_GREATERTHANOREQUAL'] = 162)] = 'OP_GREATERTHANOREQUAL'; + OPS[(OPS['OP_MIN'] = 163)] = 'OP_MIN'; + OPS[(OPS['OP_MAX'] = 164)] = 'OP_MAX'; + OPS[(OPS['OP_WITHIN'] = 165)] = 'OP_WITHIN'; + OPS[(OPS['OP_RIPEMD160'] = 166)] = 'OP_RIPEMD160'; + OPS[(OPS['OP_SHA1'] = 167)] = 'OP_SHA1'; + OPS[(OPS['OP_SHA256'] = 168)] = 'OP_SHA256'; + OPS[(OPS['OP_HASH160'] = 169)] = 'OP_HASH160'; + OPS[(OPS['OP_HASH256'] = 170)] = 'OP_HASH256'; + OPS[(OPS['OP_CODESEPARATOR'] = 171)] = 'OP_CODESEPARATOR'; + OPS[(OPS['OP_CHECKSIG'] = 172)] = 'OP_CHECKSIG'; + OPS[(OPS['OP_CHECKSIGVERIFY'] = 173)] = 'OP_CHECKSIGVERIFY'; + OPS[(OPS['OP_CHECKMULTISIG'] = 174)] = 'OP_CHECKMULTISIG'; + OPS[(OPS['OP_CHECKMULTISIGVERIFY'] = 175)] = 'OP_CHECKMULTISIGVERIFY'; + OPS[(OPS['OP_NOP1'] = 176)] = 'OP_NOP1'; + OPS[(OPS['OP_CHECKLOCKTIMEVERIFY'] = 177)] = 'OP_CHECKLOCKTIMEVERIFY'; + OPS[(OPS['OP_NOP2'] = 177)] = 'OP_NOP2'; + OPS[(OPS['OP_CHECKSEQUENCEVERIFY'] = 178)] = 'OP_CHECKSEQUENCEVERIFY'; + OPS[(OPS['OP_NOP3'] = 178)] = 'OP_NOP3'; + OPS[(OPS['OP_NOP4'] = 179)] = 'OP_NOP4'; + OPS[(OPS['OP_NOP5'] = 180)] = 'OP_NOP5'; + OPS[(OPS['OP_NOP6'] = 181)] = 'OP_NOP6'; + OPS[(OPS['OP_NOP7'] = 182)] = 'OP_NOP7'; + OPS[(OPS['OP_NOP8'] = 183)] = 'OP_NOP8'; + OPS[(OPS['OP_NOP9'] = 184)] = 'OP_NOP9'; + OPS[(OPS['OP_NOP10'] = 185)] = 'OP_NOP10'; + OPS[(OPS['OP_CHECKSIGADD'] = 186)] = 'OP_CHECKSIGADD'; + OPS[(OPS['OP_PUBKEYHASH'] = 253)] = 'OP_PUBKEYHASH'; + OPS[(OPS['OP_PUBKEY'] = 254)] = 'OP_PUBKEY'; + OPS[(OPS['OP_INVALIDOPCODE'] = 255)] = 'OP_INVALIDOPCODE'; +})(OPS || (exports.OPS = OPS = {})); diff --git a/src/cjs/ops.d.ts b/src/cjs/ops.d.ts index cda7a84a6..e3dd4b27e 100644 --- a/src/cjs/ops.d.ts +++ b/src/cjs/ops.d.ts @@ -1,7 +1,122 @@ -declare const OPS: { - [key: string]: number; -}; -declare const REVERSE_OPS: { - [key: number]: string; -}; -export { OPS, REVERSE_OPS }; +declare enum OPS { + OP_FALSE = 0, + OP_0 = 0,// Avoid duplicate value + OP_PUSHDATA1 = 76, + OP_PUSHDATA2 = 77, + OP_PUSHDATA4 = 78, + OP_1NEGATE = 79, + OP_RESERVED = 80, + OP_TRUE = 81, + OP_1 = 81,// Avoid duplicate value + OP_2 = 82, + OP_3 = 83, + OP_4 = 84, + OP_5 = 85, + OP_6 = 86, + OP_7 = 87, + OP_8 = 88, + OP_9 = 89, + OP_10 = 90, + OP_11 = 91, + OP_12 = 92, + OP_13 = 93, + OP_14 = 94, + OP_15 = 95, + OP_16 = 96, + OP_NOP = 97, + OP_VER = 98, + OP_IF = 99, + OP_NOTIF = 100, + OP_VERIF = 101, + OP_VERNOTIF = 102, + OP_ELSE = 103, + OP_ENDIF = 104, + OP_VERIFY = 105, + OP_RETURN = 106, + OP_TOALTSTACK = 107, + OP_FROMALTSTACK = 108, + OP_2DROP = 109, + OP_2DUP = 110, + OP_3DUP = 111, + OP_2OVER = 112, + OP_2ROT = 113, + OP_2SWAP = 114, + OP_IFDUP = 115, + OP_DEPTH = 116, + OP_DROP = 117, + OP_DUP = 118, + OP_NIP = 119, + OP_OVER = 120, + OP_PICK = 121, + OP_ROLL = 122, + OP_ROT = 123, + OP_SWAP = 124, + OP_TUCK = 125, + OP_CAT = 126, + OP_SUBSTR = 127, + OP_LEFT = 128, + OP_RIGHT = 129, + OP_SIZE = 130, + OP_INVERT = 131, + OP_AND = 132, + OP_OR = 133, + OP_XOR = 134, + OP_EQUAL = 135, + OP_EQUALVERIFY = 136, + OP_RESERVED1 = 137, + OP_RESERVED2 = 138, + OP_1ADD = 139, + OP_1SUB = 140, + OP_2MUL = 141, + OP_2DIV = 142, + OP_NEGATE = 143, + OP_ABS = 144, + OP_NOT = 145, + OP_0NOTEQUAL = 146, + OP_ADD = 147, + OP_SUB = 148, + OP_MUL = 149, + OP_DIV = 150, + OP_MOD = 151, + OP_LSHIFT = 152, + OP_RSHIFT = 153, + OP_BOOLAND = 154, + OP_BOOLOR = 155, + OP_NUMEQUAL = 156, + OP_NUMEQUALVERIFY = 157, + OP_NUMNOTEQUAL = 158, + OP_LESSTHAN = 159, + OP_GREATERTHAN = 160, + OP_LESSTHANOREQUAL = 161, + OP_GREATERTHANOREQUAL = 162, + OP_MIN = 163, + OP_MAX = 164, + OP_WITHIN = 165, + OP_RIPEMD160 = 166, + OP_SHA1 = 167, + OP_SHA256 = 168, + OP_HASH160 = 169, + OP_HASH256 = 170, + OP_CODESEPARATOR = 171, + OP_CHECKSIG = 172, + OP_CHECKSIGVERIFY = 173, + OP_CHECKMULTISIG = 174, + OP_CHECKMULTISIGVERIFY = 175, + OP_NOP1 = 176, + OP_CHECKLOCKTIMEVERIFY = 177,// Alias: OP_NOP2 + OP_NOP2 = 177, + OP_CHECKSEQUENCEVERIFY = 178,// Alias: OP_NOP3 + OP_NOP3 = 178, + OP_NOP4 = 179, + OP_NOP5 = 180, + OP_NOP6 = 181, + OP_NOP7 = 182, + OP_NOP8 = 183, + OP_NOP9 = 184, + OP_NOP10 = 185, + OP_CHECKSIGADD = 186, + OP_PUBKEYHASH = 253, + OP_PUBKEY = 254, + OP_INVALIDOPCODE = 255 +} +export { OPS }; diff --git a/src/cjs/script.cjs b/src/cjs/script.cjs index 476480677..d3653658e 100644 --- a/src/cjs/script.cjs +++ b/src/cjs/script.cjs @@ -260,7 +260,7 @@ function toASM(chunks) { chunk = op; } // opcode! - return ops_js_1.REVERSE_OPS[chunk]; + return ops_js_1.OPS[chunk]; }) .join(' '); } @@ -271,13 +271,17 @@ function toASM(chunks) { */ function fromASM(asm) { v.parse(v.string(), asm); + // Compile the ASM string into a Uint8Array return compile( - asm.split(' ').map(chunkStr => { - // opcode? - if (ops_js_1.OPS[chunkStr] !== undefined) return ops_js_1.OPS[chunkStr]; - v.parse(types.HexSchema, chunkStr); - // data! - return tools.fromHex(chunkStr); + asm.split(' ').map(chunk => { + // Check if the chunk is an opcode + if (isNaN(Number(chunk)) && chunk in ops_js_1.OPS) { + return ops_js_1.OPS[chunk]; + } + // Validate if the chunk is a hexadecimal string + v.parse(types.HexSchema, chunk); + // Convert the chunk to Uint8Array data + return tools.fromHex(chunk); }), ); } diff --git a/src/esm/ops.js b/src/esm/ops.js index 9e24a7c94..147c10961 100644 --- a/src/esm/ops.js +++ b/src/esm/ops.js @@ -1,127 +1,125 @@ -const OPS = { - OP_FALSE: 0, - OP_0: 0, - OP_PUSHDATA1: 76, - OP_PUSHDATA2: 77, - OP_PUSHDATA4: 78, - OP_1NEGATE: 79, - OP_RESERVED: 80, - OP_TRUE: 81, - OP_1: 81, - OP_2: 82, - OP_3: 83, - OP_4: 84, - OP_5: 85, - OP_6: 86, - OP_7: 87, - OP_8: 88, - OP_9: 89, - OP_10: 90, - OP_11: 91, - OP_12: 92, - OP_13: 93, - OP_14: 94, - OP_15: 95, - OP_16: 96, - OP_NOP: 97, - OP_VER: 98, - OP_IF: 99, - OP_NOTIF: 100, - OP_VERIF: 101, - OP_VERNOTIF: 102, - OP_ELSE: 103, - OP_ENDIF: 104, - OP_VERIFY: 105, - OP_RETURN: 106, - OP_TOALTSTACK: 107, - OP_FROMALTSTACK: 108, - OP_2DROP: 109, - OP_2DUP: 110, - OP_3DUP: 111, - OP_2OVER: 112, - OP_2ROT: 113, - OP_2SWAP: 114, - OP_IFDUP: 115, - OP_DEPTH: 116, - OP_DROP: 117, - OP_DUP: 118, - OP_NIP: 119, - OP_OVER: 120, - OP_PICK: 121, - OP_ROLL: 122, - OP_ROT: 123, - OP_SWAP: 124, - OP_TUCK: 125, - OP_CAT: 126, - OP_SUBSTR: 127, - OP_LEFT: 128, - OP_RIGHT: 129, - OP_SIZE: 130, - OP_INVERT: 131, - OP_AND: 132, - OP_OR: 133, - OP_XOR: 134, - OP_EQUAL: 135, - OP_EQUALVERIFY: 136, - OP_RESERVED1: 137, - OP_RESERVED2: 138, - OP_1ADD: 139, - OP_1SUB: 140, - OP_2MUL: 141, - OP_2DIV: 142, - OP_NEGATE: 143, - OP_ABS: 144, - OP_NOT: 145, - OP_0NOTEQUAL: 146, - OP_ADD: 147, - OP_SUB: 148, - OP_MUL: 149, - OP_DIV: 150, - OP_MOD: 151, - OP_LSHIFT: 152, - OP_RSHIFT: 153, - OP_BOOLAND: 154, - OP_BOOLOR: 155, - OP_NUMEQUAL: 156, - OP_NUMEQUALVERIFY: 157, - OP_NUMNOTEQUAL: 158, - OP_LESSTHAN: 159, - OP_GREATERTHAN: 160, - OP_LESSTHANOREQUAL: 161, - OP_GREATERTHANOREQUAL: 162, - OP_MIN: 163, - OP_MAX: 164, - OP_WITHIN: 165, - OP_RIPEMD160: 166, - OP_SHA1: 167, - OP_SHA256: 168, - OP_HASH160: 169, - OP_HASH256: 170, - OP_CODESEPARATOR: 171, - OP_CHECKSIG: 172, - OP_CHECKSIGVERIFY: 173, - OP_CHECKMULTISIG: 174, - OP_CHECKMULTISIGVERIFY: 175, - OP_NOP1: 176, - OP_NOP2: 177, - OP_CHECKLOCKTIMEVERIFY: 177, - OP_NOP3: 178, - OP_CHECKSEQUENCEVERIFY: 178, - OP_NOP4: 179, - OP_NOP5: 180, - OP_NOP6: 181, - OP_NOP7: 182, - OP_NOP8: 183, - OP_NOP9: 184, - OP_NOP10: 185, - OP_CHECKSIGADD: 186, - OP_PUBKEYHASH: 253, - OP_PUBKEY: 254, - OP_INVALIDOPCODE: 255, -}; -const REVERSE_OPS = {}; -for (const op of Object.keys(OPS)) { - const code = OPS[op]; - REVERSE_OPS[code] = op; -} -export { OPS, REVERSE_OPS }; +// Define OPS enum +var OPS; +(function (OPS) { + OPS[(OPS['OP_FALSE'] = 0)] = 'OP_FALSE'; + OPS[(OPS['OP_0'] = 0)] = 'OP_0'; + OPS[(OPS['OP_PUSHDATA1'] = 76)] = 'OP_PUSHDATA1'; + OPS[(OPS['OP_PUSHDATA2'] = 77)] = 'OP_PUSHDATA2'; + OPS[(OPS['OP_PUSHDATA4'] = 78)] = 'OP_PUSHDATA4'; + OPS[(OPS['OP_1NEGATE'] = 79)] = 'OP_1NEGATE'; + OPS[(OPS['OP_RESERVED'] = 80)] = 'OP_RESERVED'; + OPS[(OPS['OP_TRUE'] = 81)] = 'OP_TRUE'; + OPS[(OPS['OP_1'] = 81)] = 'OP_1'; + OPS[(OPS['OP_2'] = 82)] = 'OP_2'; + OPS[(OPS['OP_3'] = 83)] = 'OP_3'; + OPS[(OPS['OP_4'] = 84)] = 'OP_4'; + OPS[(OPS['OP_5'] = 85)] = 'OP_5'; + OPS[(OPS['OP_6'] = 86)] = 'OP_6'; + OPS[(OPS['OP_7'] = 87)] = 'OP_7'; + OPS[(OPS['OP_8'] = 88)] = 'OP_8'; + OPS[(OPS['OP_9'] = 89)] = 'OP_9'; + OPS[(OPS['OP_10'] = 90)] = 'OP_10'; + OPS[(OPS['OP_11'] = 91)] = 'OP_11'; + OPS[(OPS['OP_12'] = 92)] = 'OP_12'; + OPS[(OPS['OP_13'] = 93)] = 'OP_13'; + OPS[(OPS['OP_14'] = 94)] = 'OP_14'; + OPS[(OPS['OP_15'] = 95)] = 'OP_15'; + OPS[(OPS['OP_16'] = 96)] = 'OP_16'; + OPS[(OPS['OP_NOP'] = 97)] = 'OP_NOP'; + OPS[(OPS['OP_VER'] = 98)] = 'OP_VER'; + OPS[(OPS['OP_IF'] = 99)] = 'OP_IF'; + OPS[(OPS['OP_NOTIF'] = 100)] = 'OP_NOTIF'; + OPS[(OPS['OP_VERIF'] = 101)] = 'OP_VERIF'; + OPS[(OPS['OP_VERNOTIF'] = 102)] = 'OP_VERNOTIF'; + OPS[(OPS['OP_ELSE'] = 103)] = 'OP_ELSE'; + OPS[(OPS['OP_ENDIF'] = 104)] = 'OP_ENDIF'; + OPS[(OPS['OP_VERIFY'] = 105)] = 'OP_VERIFY'; + OPS[(OPS['OP_RETURN'] = 106)] = 'OP_RETURN'; + OPS[(OPS['OP_TOALTSTACK'] = 107)] = 'OP_TOALTSTACK'; + OPS[(OPS['OP_FROMALTSTACK'] = 108)] = 'OP_FROMALTSTACK'; + OPS[(OPS['OP_2DROP'] = 109)] = 'OP_2DROP'; + OPS[(OPS['OP_2DUP'] = 110)] = 'OP_2DUP'; + OPS[(OPS['OP_3DUP'] = 111)] = 'OP_3DUP'; + OPS[(OPS['OP_2OVER'] = 112)] = 'OP_2OVER'; + OPS[(OPS['OP_2ROT'] = 113)] = 'OP_2ROT'; + OPS[(OPS['OP_2SWAP'] = 114)] = 'OP_2SWAP'; + OPS[(OPS['OP_IFDUP'] = 115)] = 'OP_IFDUP'; + OPS[(OPS['OP_DEPTH'] = 116)] = 'OP_DEPTH'; + OPS[(OPS['OP_DROP'] = 117)] = 'OP_DROP'; + OPS[(OPS['OP_DUP'] = 118)] = 'OP_DUP'; + OPS[(OPS['OP_NIP'] = 119)] = 'OP_NIP'; + OPS[(OPS['OP_OVER'] = 120)] = 'OP_OVER'; + OPS[(OPS['OP_PICK'] = 121)] = 'OP_PICK'; + OPS[(OPS['OP_ROLL'] = 122)] = 'OP_ROLL'; + OPS[(OPS['OP_ROT'] = 123)] = 'OP_ROT'; + OPS[(OPS['OP_SWAP'] = 124)] = 'OP_SWAP'; + OPS[(OPS['OP_TUCK'] = 125)] = 'OP_TUCK'; + OPS[(OPS['OP_CAT'] = 126)] = 'OP_CAT'; + OPS[(OPS['OP_SUBSTR'] = 127)] = 'OP_SUBSTR'; + OPS[(OPS['OP_LEFT'] = 128)] = 'OP_LEFT'; + OPS[(OPS['OP_RIGHT'] = 129)] = 'OP_RIGHT'; + OPS[(OPS['OP_SIZE'] = 130)] = 'OP_SIZE'; + OPS[(OPS['OP_INVERT'] = 131)] = 'OP_INVERT'; + OPS[(OPS['OP_AND'] = 132)] = 'OP_AND'; + OPS[(OPS['OP_OR'] = 133)] = 'OP_OR'; + OPS[(OPS['OP_XOR'] = 134)] = 'OP_XOR'; + OPS[(OPS['OP_EQUAL'] = 135)] = 'OP_EQUAL'; + OPS[(OPS['OP_EQUALVERIFY'] = 136)] = 'OP_EQUALVERIFY'; + OPS[(OPS['OP_RESERVED1'] = 137)] = 'OP_RESERVED1'; + OPS[(OPS['OP_RESERVED2'] = 138)] = 'OP_RESERVED2'; + OPS[(OPS['OP_1ADD'] = 139)] = 'OP_1ADD'; + OPS[(OPS['OP_1SUB'] = 140)] = 'OP_1SUB'; + OPS[(OPS['OP_2MUL'] = 141)] = 'OP_2MUL'; + OPS[(OPS['OP_2DIV'] = 142)] = 'OP_2DIV'; + OPS[(OPS['OP_NEGATE'] = 143)] = 'OP_NEGATE'; + OPS[(OPS['OP_ABS'] = 144)] = 'OP_ABS'; + OPS[(OPS['OP_NOT'] = 145)] = 'OP_NOT'; + OPS[(OPS['OP_0NOTEQUAL'] = 146)] = 'OP_0NOTEQUAL'; + OPS[(OPS['OP_ADD'] = 147)] = 'OP_ADD'; + OPS[(OPS['OP_SUB'] = 148)] = 'OP_SUB'; + OPS[(OPS['OP_MUL'] = 149)] = 'OP_MUL'; + OPS[(OPS['OP_DIV'] = 150)] = 'OP_DIV'; + OPS[(OPS['OP_MOD'] = 151)] = 'OP_MOD'; + OPS[(OPS['OP_LSHIFT'] = 152)] = 'OP_LSHIFT'; + OPS[(OPS['OP_RSHIFT'] = 153)] = 'OP_RSHIFT'; + OPS[(OPS['OP_BOOLAND'] = 154)] = 'OP_BOOLAND'; + OPS[(OPS['OP_BOOLOR'] = 155)] = 'OP_BOOLOR'; + OPS[(OPS['OP_NUMEQUAL'] = 156)] = 'OP_NUMEQUAL'; + OPS[(OPS['OP_NUMEQUALVERIFY'] = 157)] = 'OP_NUMEQUALVERIFY'; + OPS[(OPS['OP_NUMNOTEQUAL'] = 158)] = 'OP_NUMNOTEQUAL'; + OPS[(OPS['OP_LESSTHAN'] = 159)] = 'OP_LESSTHAN'; + OPS[(OPS['OP_GREATERTHAN'] = 160)] = 'OP_GREATERTHAN'; + OPS[(OPS['OP_LESSTHANOREQUAL'] = 161)] = 'OP_LESSTHANOREQUAL'; + OPS[(OPS['OP_GREATERTHANOREQUAL'] = 162)] = 'OP_GREATERTHANOREQUAL'; + OPS[(OPS['OP_MIN'] = 163)] = 'OP_MIN'; + OPS[(OPS['OP_MAX'] = 164)] = 'OP_MAX'; + OPS[(OPS['OP_WITHIN'] = 165)] = 'OP_WITHIN'; + OPS[(OPS['OP_RIPEMD160'] = 166)] = 'OP_RIPEMD160'; + OPS[(OPS['OP_SHA1'] = 167)] = 'OP_SHA1'; + OPS[(OPS['OP_SHA256'] = 168)] = 'OP_SHA256'; + OPS[(OPS['OP_HASH160'] = 169)] = 'OP_HASH160'; + OPS[(OPS['OP_HASH256'] = 170)] = 'OP_HASH256'; + OPS[(OPS['OP_CODESEPARATOR'] = 171)] = 'OP_CODESEPARATOR'; + OPS[(OPS['OP_CHECKSIG'] = 172)] = 'OP_CHECKSIG'; + OPS[(OPS['OP_CHECKSIGVERIFY'] = 173)] = 'OP_CHECKSIGVERIFY'; + OPS[(OPS['OP_CHECKMULTISIG'] = 174)] = 'OP_CHECKMULTISIG'; + OPS[(OPS['OP_CHECKMULTISIGVERIFY'] = 175)] = 'OP_CHECKMULTISIGVERIFY'; + OPS[(OPS['OP_NOP1'] = 176)] = 'OP_NOP1'; + OPS[(OPS['OP_CHECKLOCKTIMEVERIFY'] = 177)] = 'OP_CHECKLOCKTIMEVERIFY'; + OPS[(OPS['OP_NOP2'] = 177)] = 'OP_NOP2'; + OPS[(OPS['OP_CHECKSEQUENCEVERIFY'] = 178)] = 'OP_CHECKSEQUENCEVERIFY'; + OPS[(OPS['OP_NOP3'] = 178)] = 'OP_NOP3'; + OPS[(OPS['OP_NOP4'] = 179)] = 'OP_NOP4'; + OPS[(OPS['OP_NOP5'] = 180)] = 'OP_NOP5'; + OPS[(OPS['OP_NOP6'] = 181)] = 'OP_NOP6'; + OPS[(OPS['OP_NOP7'] = 182)] = 'OP_NOP7'; + OPS[(OPS['OP_NOP8'] = 183)] = 'OP_NOP8'; + OPS[(OPS['OP_NOP9'] = 184)] = 'OP_NOP9'; + OPS[(OPS['OP_NOP10'] = 185)] = 'OP_NOP10'; + OPS[(OPS['OP_CHECKSIGADD'] = 186)] = 'OP_CHECKSIGADD'; + OPS[(OPS['OP_PUBKEYHASH'] = 253)] = 'OP_PUBKEYHASH'; + OPS[(OPS['OP_PUBKEY'] = 254)] = 'OP_PUBKEY'; + OPS[(OPS['OP_INVALIDOPCODE'] = 255)] = 'OP_INVALIDOPCODE'; +})(OPS || (OPS = {})); +// Export modules +export { OPS }; diff --git a/src/esm/script.js b/src/esm/script.js index 6c9a8e2a5..4f566e182 100644 --- a/src/esm/script.js +++ b/src/esm/script.js @@ -6,7 +6,7 @@ * @packageDocumentation */ import * as bip66 from './bip66.js'; -import { OPS, REVERSE_OPS } from './ops.js'; +import { OPS } from './ops.js'; import * as pushdata from './push_data.js'; import * as scriptNumber from './script_number.js'; import * as scriptSignature from './script_signature.js'; @@ -198,7 +198,7 @@ export function toASM(chunks) { chunk = op; } // opcode! - return REVERSE_OPS[chunk]; + return OPS[chunk]; }) .join(' '); } @@ -209,13 +209,17 @@ export function toASM(chunks) { */ export function fromASM(asm) { v.parse(v.string(), asm); + // Compile the ASM string into a Uint8Array return compile( - asm.split(' ').map(chunkStr => { - // opcode? - if (OPS[chunkStr] !== undefined) return OPS[chunkStr]; - v.parse(types.HexSchema, chunkStr); - // data! - return tools.fromHex(chunkStr); + asm.split(' ').map(chunk => { + // Check if the chunk is an opcode + if (isNaN(Number(chunk)) && chunk in OPS) { + return OPS[chunk]; + } + // Validate if the chunk is a hexadecimal string + v.parse(types.HexSchema, chunk); + // Convert the chunk to Uint8Array data + return tools.fromHex(chunk); }), ); } diff --git a/test/ops.spec.ts b/test/ops.spec.ts new file mode 100644 index 000000000..7a3c8af5f --- /dev/null +++ b/test/ops.spec.ts @@ -0,0 +1,47 @@ +import { describe, it } from 'mocha'; +import assert from 'assert'; +import { opcodes as OPS } from 'bitcoinjs-lib'; + +describe('OPS Enum Tests', () => { + it('should map OPS keys to correct numbers and reverse lookup', () => { + Object.keys(OPS) + .filter(key => isNaN(Number(key))) // Only test enum keys, not reverse-mapped numbers + .forEach(key => { + const value = OPS[key as keyof typeof OPS]; + + // Assert the forward mapping + assert.strictEqual( + OPS[key], + value, + `Failed for key: ${key}, value: ${value}`, + ); + }); + }); + + it('should reverse map numbers to correct keys', () => { + const valueToKeysMap = new Map(); + + Object.keys(OPS) + .filter(key => isNaN(Number(key))) + .forEach(key => { + const value = OPS[key as keyof typeof OPS]; + if (!valueToKeysMap.has(value)) { + valueToKeysMap.set(value, []); + } + valueToKeysMap.get(value)!.push(key); + }); + + Object.values(OPS) + .filter(value => typeof value === 'number') + .forEach(value => { + const keys = valueToKeysMap.get(value) || []; + keys.forEach(key => { + assert.strictEqual( + OPS[key], + value, + `Failed for value: ${value}, key: ${key}`, + ); + }); + }); + }); +}); diff --git a/test/script.spec.ts b/test/script.spec.ts index eba1a15c5..3736cdbdf 100644 --- a/test/script.spec.ts +++ b/test/script.spec.ts @@ -41,6 +41,27 @@ describe('script', () => { }); }); + describe('fromASM', () => { + const OPS = bscript.OPS; + it('decodes OP_FALSE as empty buffer', () => { + const string = 'OP_RETURN OP_FALSE'; + assert.deepStrictEqual( + bscript.fromASM(string), + Uint8Array.from([OPS.OP_RETURN, OPS.OP_FALSE]), + ); + }); + + it("decodes a series of numbers from '82 to 96' correctly", () => { + const asm = Array.from({ length: 15 }, (_, i) => i + 82).join(' '); + const expected = Array.from({ length: 15 }, (_, i) => [ + 1, + parseInt(String(i + 82), 16), + ]).flat(); + const result = bscript.fromASM(asm); + assert.deepStrictEqual(result, Uint8Array.from(expected)); + }); + }); + describe('toASM', () => { const OP_RETURN = bscript.OPS.OP_RETURN; it('encodes empty buffer as OP_0', () => { diff --git a/ts_src/ops.ts b/ts_src/ops.ts index dd8b1e6da..99de223cb 100644 --- a/ts_src/ops.ts +++ b/ts_src/ops.ts @@ -1,143 +1,139 @@ -const OPS: { [key: string]: number } = { - OP_FALSE: 0, - OP_0: 0, - OP_PUSHDATA1: 76, - OP_PUSHDATA2: 77, - OP_PUSHDATA4: 78, - OP_1NEGATE: 79, - OP_RESERVED: 80, - OP_TRUE: 81, - OP_1: 81, - OP_2: 82, - OP_3: 83, - OP_4: 84, - OP_5: 85, - OP_6: 86, - OP_7: 87, - OP_8: 88, - OP_9: 89, - OP_10: 90, - OP_11: 91, - OP_12: 92, - OP_13: 93, - OP_14: 94, - OP_15: 95, - OP_16: 96, - - OP_NOP: 97, - OP_VER: 98, - OP_IF: 99, - OP_NOTIF: 100, - OP_VERIF: 101, - OP_VERNOTIF: 102, - OP_ELSE: 103, - OP_ENDIF: 104, - OP_VERIFY: 105, - OP_RETURN: 106, - - OP_TOALTSTACK: 107, - OP_FROMALTSTACK: 108, - OP_2DROP: 109, - OP_2DUP: 110, - OP_3DUP: 111, - OP_2OVER: 112, - OP_2ROT: 113, - OP_2SWAP: 114, - OP_IFDUP: 115, - OP_DEPTH: 116, - OP_DROP: 117, - OP_DUP: 118, - OP_NIP: 119, - OP_OVER: 120, - OP_PICK: 121, - OP_ROLL: 122, - OP_ROT: 123, - OP_SWAP: 124, - OP_TUCK: 125, - - OP_CAT: 126, - OP_SUBSTR: 127, - OP_LEFT: 128, - OP_RIGHT: 129, - OP_SIZE: 130, - - OP_INVERT: 131, - OP_AND: 132, - OP_OR: 133, - OP_XOR: 134, - OP_EQUAL: 135, - OP_EQUALVERIFY: 136, - OP_RESERVED1: 137, - OP_RESERVED2: 138, - - OP_1ADD: 139, - OP_1SUB: 140, - OP_2MUL: 141, - OP_2DIV: 142, - OP_NEGATE: 143, - OP_ABS: 144, - OP_NOT: 145, - OP_0NOTEQUAL: 146, - OP_ADD: 147, - OP_SUB: 148, - OP_MUL: 149, - OP_DIV: 150, - OP_MOD: 151, - OP_LSHIFT: 152, - OP_RSHIFT: 153, - - OP_BOOLAND: 154, - OP_BOOLOR: 155, - OP_NUMEQUAL: 156, - OP_NUMEQUALVERIFY: 157, - OP_NUMNOTEQUAL: 158, - OP_LESSTHAN: 159, - OP_GREATERTHAN: 160, - OP_LESSTHANOREQUAL: 161, - OP_GREATERTHANOREQUAL: 162, - OP_MIN: 163, - OP_MAX: 164, - - OP_WITHIN: 165, - - OP_RIPEMD160: 166, - OP_SHA1: 167, - OP_SHA256: 168, - OP_HASH160: 169, - OP_HASH256: 170, - OP_CODESEPARATOR: 171, - OP_CHECKSIG: 172, - OP_CHECKSIGVERIFY: 173, - OP_CHECKMULTISIG: 174, - OP_CHECKMULTISIGVERIFY: 175, - - OP_NOP1: 176, - - OP_NOP2: 177, - OP_CHECKLOCKTIMEVERIFY: 177, - - OP_NOP3: 178, - OP_CHECKSEQUENCEVERIFY: 178, - - OP_NOP4: 179, - OP_NOP5: 180, - OP_NOP6: 181, - OP_NOP7: 182, - OP_NOP8: 183, - OP_NOP9: 184, - OP_NOP10: 185, - - OP_CHECKSIGADD: 186, - - OP_PUBKEYHASH: 253, - OP_PUBKEY: 254, - OP_INVALIDOPCODE: 255, -}; - -const REVERSE_OPS: { [key: number]: string } = {}; -for (const op of Object.keys(OPS)) { - const code = OPS[op]; - REVERSE_OPS[code] = op; +// Define OPS enum +enum OPS { + OP_FALSE = 0, + OP_0 = OPS.OP_FALSE, // Avoid duplicate value + OP_PUSHDATA1 = 76, + OP_PUSHDATA2 = 77, + OP_PUSHDATA4 = 78, + OP_1NEGATE = 79, + OP_RESERVED = 80, + OP_TRUE = 81, + OP_1 = OPS.OP_TRUE, // Avoid duplicate value + OP_2 = 82, + OP_3 = 83, + OP_4 = 84, + OP_5 = 85, + OP_6 = 86, + OP_7 = 87, + OP_8 = 88, + OP_9 = 89, + OP_10 = 90, + OP_11 = 91, + OP_12 = 92, + OP_13 = 93, + OP_14 = 94, + OP_15 = 95, + OP_16 = 96, + + OP_NOP = 97, + OP_VER = 98, + OP_IF = 99, + OP_NOTIF = 100, + OP_VERIF = 101, + OP_VERNOTIF = 102, + OP_ELSE = 103, + OP_ENDIF = 104, + OP_VERIFY = 105, + OP_RETURN = 106, + + OP_TOALTSTACK = 107, + OP_FROMALTSTACK = 108, + OP_2DROP = 109, + OP_2DUP = 110, + OP_3DUP = 111, + OP_2OVER = 112, + OP_2ROT = 113, + OP_2SWAP = 114, + OP_IFDUP = 115, + OP_DEPTH = 116, + OP_DROP = 117, + OP_DUP = 118, + OP_NIP = 119, + OP_OVER = 120, + OP_PICK = 121, + OP_ROLL = 122, + OP_ROT = 123, + OP_SWAP = 124, + OP_TUCK = 125, + + OP_CAT = 126, + OP_SUBSTR = 127, + OP_LEFT = 128, + OP_RIGHT = 129, + OP_SIZE = 130, + + OP_INVERT = 131, + OP_AND = 132, + OP_OR = 133, + OP_XOR = 134, + OP_EQUAL = 135, + OP_EQUALVERIFY = 136, + OP_RESERVED1 = 137, + OP_RESERVED2 = 138, + + OP_1ADD = 139, + OP_1SUB = 140, + OP_2MUL = 141, + OP_2DIV = 142, + OP_NEGATE = 143, + OP_ABS = 144, + OP_NOT = 145, + OP_0NOTEQUAL = 146, + OP_ADD = 147, + OP_SUB = 148, + OP_MUL = 149, + OP_DIV = 150, + OP_MOD = 151, + OP_LSHIFT = 152, + OP_RSHIFT = 153, + + OP_BOOLAND = 154, + OP_BOOLOR = 155, + OP_NUMEQUAL = 156, + OP_NUMEQUALVERIFY = 157, + OP_NUMNOTEQUAL = 158, + OP_LESSTHAN = 159, + OP_GREATERTHAN = 160, + OP_LESSTHANOREQUAL = 161, + OP_GREATERTHANOREQUAL = 162, + OP_MIN = 163, + OP_MAX = 164, + + OP_WITHIN = 165, + + OP_RIPEMD160 = 166, + OP_SHA1 = 167, + OP_SHA256 = 168, + OP_HASH160 = 169, + OP_HASH256 = 170, + OP_CODESEPARATOR = 171, + OP_CHECKSIG = 172, + OP_CHECKSIGVERIFY = 173, + OP_CHECKMULTISIG = 174, + OP_CHECKMULTISIGVERIFY = 175, + + OP_NOP1 = 176, + + OP_CHECKLOCKTIMEVERIFY = 177, // Alias: OP_NOP2 + OP_NOP2 = OPS.OP_CHECKLOCKTIMEVERIFY, + + OP_CHECKSEQUENCEVERIFY = 178, // Alias: OP_NOP3 + OP_NOP3 = OPS.OP_CHECKSEQUENCEVERIFY, + + OP_NOP4 = 179, + OP_NOP5 = 180, + OP_NOP6 = 181, + OP_NOP7 = 182, + OP_NOP8 = 183, + OP_NOP9 = 184, + OP_NOP10 = 185, + + OP_CHECKSIGADD = 186, + + OP_PUBKEYHASH = 253, + OP_PUBKEY = 254, + OP_INVALIDOPCODE = 255, } -export { OPS, REVERSE_OPS }; +// Export modules +export { OPS }; diff --git a/ts_src/script.ts b/ts_src/script.ts index 0510f323e..6e6f8580c 100644 --- a/ts_src/script.ts +++ b/ts_src/script.ts @@ -7,7 +7,7 @@ */ import * as bip66 from './bip66.js'; -import { OPS, REVERSE_OPS } from './ops.js'; +import { OPS } from './ops.js'; import { Stack } from './payments/index.js'; import * as pushdata from './push_data.js'; import * as scriptNumber from './script_number.js'; @@ -238,7 +238,7 @@ export function toASM(chunks: Uint8Array | Array): string { } // opcode! - return REVERSE_OPS[chunk]; + return OPS[chunk]; }) .join(' '); } @@ -251,14 +251,19 @@ export function toASM(chunks: Uint8Array | Array): string { export function fromASM(asm: string): Uint8Array { v.parse(v.string(), asm); + // Compile the ASM string into a Uint8Array return compile( - asm.split(' ').map(chunkStr => { - // opcode? - if (OPS[chunkStr] !== undefined) return OPS[chunkStr]; - v.parse(types.HexSchema, chunkStr); + asm.split(' ').map((chunk: string): number | Uint8Array => { + // Check if the chunk is an opcode + if (isNaN(Number(chunk)) && chunk in OPS) { + return OPS[chunk as keyof typeof OPS]; + } + + // Validate if the chunk is a hexadecimal string + v.parse(types.HexSchema, chunk); - // data! - return tools.fromHex(chunkStr); + // Convert the chunk to Uint8Array data + return tools.fromHex(chunk); }), ); }