UNPKG

libnexa-ts

Version:

A pure and powerful Nexa SDK library.

282 lines (247 loc) 6.15 kB
import BufferUtils from "../../utils/buffer.utils"; import ValidationUtils from "../../utils/validation.utils"; export enum Opcode { // push value OP_FALSE = 0, OP_0 = OP_FALSE, OP_PUSHDATA1 = 76, OP_PUSHDATA2 = 77, OP_PUSHDATA4 = 78, OP_1NEGATE = 79, OP_RESERVED = 80, OP_TRUE = 81, OP_1 = OP_TRUE, 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, // control OP_NOP = 97, OP_INVALID_CONTROL1 = 98, OP_IF = 99, OP_NOTIF = 100, OP_JUMP = 101, OP_INVALID_CONTROL2 = 102, OP_ELSE = 103, OP_ENDIF = 104, OP_VERIFY = 105, OP_RETURN = 106, // stack ops 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, // splice ops OP_CAT = 126, OP_SPLIT = 127, OP_NUM2BIN = 128, OP_BIN2NUM = 129, OP_SIZE = 130, // bit logic OP_INVERT = 131, OP_AND = 132, OP_OR = 133, OP_XOR = 134, OP_EQUAL = 135, OP_EQUALVERIFY = 136, OP_RESERVED1 = 137, OP_RESERVED2 = 138, // numeric 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, // crypto 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, // timelocks OP_NOP2 = 177, OP_CHECKLOCKTIMEVERIFY = OP_NOP2, OP_NOP3 = 178, OP_CHECKSEQUENCEVERIFY = OP_NOP3, // expansion OP_NOP1 = 176, OP_NOP4 = 179, OP_NOP5 = 180, OP_NOP6 = 181, OP_NOP7 = 182, OP_NOP8 = 183, OP_NOP9 = 184, OP_NOP10 = 185, // More crypto OP_CHECKDATASIG = 186, OP_CHECKDATASIGVERIFY = 187, // additional byte string operations OP_REVERSEBYTES = 188, // Transaction Introspection Opcodes OP_INPUTINDEX = 192, OP_ACTIVEBYTECODE = 193, OP_TXVERSION = 194, OP_TXINPUTCOUNT = 195, OP_TXOUTPUTCOUNT = 196, OP_TXLOCKTIME = 197, OP_UTXOVALUE = 198, OP_UTXOBYTECODE = 199, OP_OUTPOINTHASH = 200, OP_INPUTBYTECODE = 202, OP_INPUTSEQUENCENUMBER = 203, OP_OUTPUTVALUE = 204, OP_OUTPUTBYTECODE = 205, OP_INPUTTYPE = 206, OP_OUTPUTTYPE = 207, OP_INPUTVALUE = 208, // NEXA opcodes OP_PARSE = 230, OP_STORE = 231, OP_LOAD = 232, OP_PLACE = 233, OP_PUSH_TX_STATE = 234, OP_SETBMD = 235, OP_BIN2BIGNUM = 236, OP_EXEC = 237, OP_MERKLEROOT = 238, // The first op_code value after all defined opcodes FIRST_UNDEFINED_OP_VALUE, OP_INVALIDOPCODE = 255, } type OpcodeKey = keyof typeof Opcode; export default class ScriptOpcode { num: number; constructor(val: number | string) { if (typeof val === 'number') { this.num = val; } else if (typeof val === 'string') { this.num = Opcode[val as OpcodeKey]; } else { throw new TypeError('Unrecognized val type: "' + typeof(val) + '" for Opcode'); } } public static fromBuffer(buf: Uint8Array): ScriptOpcode { ValidationUtils.validateArgument(BufferUtils.isBuffer(buf), 'buf must be Buffer'); return new ScriptOpcode(Number('0x' + BufferUtils.bufferToHex(buf))); } public static fromNumber(num: number): ScriptOpcode { ValidationUtils.validateArgument(typeof num === 'number', 'num must be number'); return new ScriptOpcode(num); } public static fromString(str: string): ScriptOpcode { ValidationUtils.validateArgument(typeof str === 'string', 'str must be string'); let value = Opcode[str as OpcodeKey]; if (typeof value === 'undefined') { throw new TypeError('Invalid opcodestr'); } return new ScriptOpcode(value); } public static smallInt(n: number): ScriptOpcode { ValidationUtils.validateArgument(typeof n === 'number', 'n should be number'); ValidationUtils.validateArgument(n >= 0 && n <= 16, 'n must be between 0 and 16'); if (n === 0) { return new ScriptOpcode('OP_0'); } return new ScriptOpcode(Opcode.OP_1 + n - 1); } /** * @returns true if opcode is one of OP_0, OP_1, ..., OP_16 */ public static isSmallIntOp(opcode: ScriptOpcode | number): boolean { if (opcode instanceof ScriptOpcode) { opcode = opcode.toNumber(); } return opcode === Opcode.OP_0 || (opcode >= Opcode.OP_1 && opcode <= Opcode.OP_16); } public toHex(): string { return this.num.toString(16); } public toBuffer(): Uint8Array { return BufferUtils.hexToBuffer(this.toHex()); } public toNumber(): number { return this.num; } public toString(): string { let str = Opcode[this.num]; if (typeof str === 'undefined') { throw new Error('Opcode does not have a string representation'); } return str; } /** * Will return a string formatted for the console * * @returns Script opcode */ public inspect(): string { return '<Opcode: ' + this.toString() + ', hex: '+this.toHex()+', decimal: '+this.num+'>'; } /** * Comes from nexad's script DecodeOP_N function * @param opcode * @returns numeric value in range of 0 to 16 */ public static decodeOP_N(opcode: number): number { if (opcode === Opcode.OP_0) { return 0; } else if (opcode >= Opcode.OP_1 && opcode <= Opcode.OP_16) { return opcode - (Opcode.OP_1 - 1); } else { throw new Error('Invalid opcode: ' + JSON.stringify(opcode)); } } }