#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
#[allow(non_camel_case_types)]
pub enum Op {
Op0 = 0x00,
OpPushData1 = 0x4c,
OpPushData2 = 0x4d,
OpPushData4 = 0x4e,
Op1Negate = 0x4f,
OpReserved = 0x50,
Op1 = 0x51,
Op2 = 0x52,
Op3 = 0x53,
Op4 = 0x54,
Op5 = 0x55,
Op6 = 0x56,
Op7 = 0x57,
Op8 = 0x58,
Op9 = 0x59,
Op10 = 0x5a,
Op11 = 0x5b,
Op12 = 0x5c,
Op13 = 0x5d,
Op14 = 0x5e,
Op15 = 0x5f,
Op16 = 0x60,
OpNop = 0x61,
OpVer = 0x62,
OpIf = 0x63,
OpNotIf = 0x64,
OpVerIf = 0x65,
OpVerNotIf = 0x66,
OpElse = 0x67,
OpEndIf = 0x68,
OpVerify = 0x69,
OpReturn = 0x6a,
OpToAltStack = 0x6b,
OpFromAltStack = 0x6c,
Op2Drop = 0x6d,
Op2Dup = 0x6e,
Op3Dup = 0x6f,
Op2Over = 0x70,
Op2Rot = 0x71,
Op2Swap = 0x72,
OpIfDup = 0x73,
OpDepth = 0x74,
OpDrop = 0x75,
OpDup = 0x76,
OpNip = 0x77,
OpOver = 0x78,
OpPick = 0x79,
OpRoll = 0x7a,
OpRot = 0x7b,
OpSwap = 0x7c,
OpTuck = 0x7d,
OpCat = 0x7e,
OpSplit = 0x7f,
OpNum2Bin = 0x80,
OpBin2Num = 0x81,
OpSize = 0x82,
OpInvert = 0x83,
OpAnd = 0x84,
OpOr = 0x85,
OpXor = 0x86,
OpEqual = 0x87,
OpEqualVerify = 0x88,
OpReserved1 = 0x89,
OpReserved2 = 0x8a,
Op1Add = 0x8b,
Op1Sub = 0x8c,
Op2Mul = 0x8d,
Op2Div = 0x8e,
OpNegate = 0x8f,
OpAbs = 0x90,
OpNot = 0x91,
Op0NotEqual = 0x92,
OpAdd = 0x93,
OpSub = 0x94,
OpMul = 0x95,
OpDiv = 0x96,
OpMod = 0x97,
OpLShift = 0x98,
OpRShift = 0x99,
OpBoolAnd = 0x9a,
OpBoolOr = 0x9b,
OpNumEqual = 0x9c,
OpNumEqualVerify = 0x9d,
OpNumNotEqual = 0x9e,
OpLessThan = 0x9f,
OpGreaterThan = 0xa0,
OpLessThanOrEqual = 0xa1,
OpGreaterThanOrEqual = 0xa2,
OpMin = 0xa3,
OpMax = 0xa4,
OpWithin = 0xa5,
OpRipemd160 = 0xa6,
OpSha1 = 0xa7,
OpSha256 = 0xa8,
OpHash160 = 0xa9,
OpHash256 = 0xaa,
OpCodeSeparator = 0xab,
OpCheckSig = 0xac,
OpCheckSigVerify = 0xad,
OpCheckMultiSig = 0xae,
OpCheckMultiSigVerify = 0xaf,
OpNop1 = 0xb0,
OpNop2 = 0xb1,
OpNop3 = 0xb2,
OpSubstr = 0xb3,
OpLeft = 0xb4,
OpRight = 0xb5,
OpLShiftNum = 0xb6,
OpRShiftNum = 0xb7,
OpNop9 = 0xb8,
OpNop10 = 0xb9,
OpNop11 = 0xba,
OpNop12 = 0xbb,
OpNop13 = 0xbc,
OpNop14 = 0xbd,
OpNop15 = 0xbe,
OpNop16 = 0xbf,
OpNop17 = 0xc0,
OpNop18 = 0xc1,
OpNop19 = 0xc2,
OpNop20 = 0xc3,
OpNop21 = 0xc4,
OpNop22 = 0xc5,
OpNop23 = 0xc6,
OpNop24 = 0xc7,
OpNop25 = 0xc8,
OpNop26 = 0xc9,
OpNop27 = 0xca,
OpNop28 = 0xcb,
OpNop29 = 0xcc,
OpNop30 = 0xcd,
OpNop31 = 0xce,
OpNop32 = 0xcf,
OpNop33 = 0xd0,
OpNop34 = 0xd1,
OpNop35 = 0xd2,
OpNop36 = 0xd3,
OpNop37 = 0xd4,
OpNop38 = 0xd5,
OpNop39 = 0xd6,
OpNop40 = 0xd7,
OpNop41 = 0xd8,
OpNop42 = 0xd9,
OpNop43 = 0xda,
OpNop44 = 0xdb,
OpNop45 = 0xdc,
OpNop46 = 0xdd,
OpNop47 = 0xde,
OpNop48 = 0xdf,
OpNop49 = 0xe0,
OpNop50 = 0xe1,
OpNop51 = 0xe2,
OpNop52 = 0xe3,
OpNop53 = 0xe4,
OpNop54 = 0xe5,
OpNop55 = 0xe6,
OpNop56 = 0xe7,
OpNop57 = 0xe8,
OpNop58 = 0xe9,
OpNop59 = 0xea,
OpNop60 = 0xeb,
OpNop61 = 0xec,
OpNop62 = 0xed,
OpNop63 = 0xee,
OpNop64 = 0xef,
OpNop65 = 0xf0,
OpNop66 = 0xf1,
OpNop67 = 0xf2,
OpNop68 = 0xf3,
OpNop69 = 0xf4,
OpNop70 = 0xf5,
OpNop71 = 0xf6,
OpNop72 = 0xf7,
OpNop73 = 0xf8,
OpSmallData = 0xf9,
OpSmallInteger = 0xfa,
OpPubKeys = 0xfb,
OpNop77 = 0xfc,
OpPubKeyHash = 0xfd,
OpPubKey = 0xfe,
OpInvalidOpcode = 0xff,
}
impl Op {
pub fn to_name(&self) -> &'static str {
match self {
Op::Op0 => "OP_0",
Op::OpPushData1 => "OP_PUSHDATA1",
Op::OpPushData2 => "OP_PUSHDATA2",
Op::OpPushData4 => "OP_PUSHDATA4",
Op::Op1Negate => "OP_1NEGATE",
Op::OpReserved => "OP_RESERVED",
Op::Op1 => "OP_1",
Op::Op2 => "OP_2",
Op::Op3 => "OP_3",
Op::Op4 => "OP_4",
Op::Op5 => "OP_5",
Op::Op6 => "OP_6",
Op::Op7 => "OP_7",
Op::Op8 => "OP_8",
Op::Op9 => "OP_9",
Op::Op10 => "OP_10",
Op::Op11 => "OP_11",
Op::Op12 => "OP_12",
Op::Op13 => "OP_13",
Op::Op14 => "OP_14",
Op::Op15 => "OP_15",
Op::Op16 => "OP_16",
Op::OpNop => "OP_NOP",
Op::OpVer => "OP_VER",
Op::OpIf => "OP_IF",
Op::OpNotIf => "OP_NOTIF",
Op::OpVerIf => "OP_VERIF",
Op::OpVerNotIf => "OP_VERNOTIF",
Op::OpElse => "OP_ELSE",
Op::OpEndIf => "OP_ENDIF",
Op::OpVerify => "OP_VERIFY",
Op::OpReturn => "OP_RETURN",
Op::OpToAltStack => "OP_TOALTSTACK",
Op::OpFromAltStack => "OP_FROMALTSTACK",
Op::Op2Drop => "OP_2DROP",
Op::Op2Dup => "OP_2DUP",
Op::Op3Dup => "OP_3DUP",
Op::Op2Over => "OP_2OVER",
Op::Op2Rot => "OP_2ROT",
Op::Op2Swap => "OP_2SWAP",
Op::OpIfDup => "OP_IFDUP",
Op::OpDepth => "OP_DEPTH",
Op::OpDrop => "OP_DROP",
Op::OpDup => "OP_DUP",
Op::OpNip => "OP_NIP",
Op::OpOver => "OP_OVER",
Op::OpPick => "OP_PICK",
Op::OpRoll => "OP_ROLL",
Op::OpRot => "OP_ROT",
Op::OpSwap => "OP_SWAP",
Op::OpTuck => "OP_TUCK",
Op::OpCat => "OP_CAT",
Op::OpSplit => "OP_SPLIT",
Op::OpNum2Bin => "OP_NUM2BIN",
Op::OpBin2Num => "OP_BIN2NUM",
Op::OpSize => "OP_SIZE",
Op::OpInvert => "OP_INVERT",
Op::OpAnd => "OP_AND",
Op::OpOr => "OP_OR",
Op::OpXor => "OP_XOR",
Op::OpEqual => "OP_EQUAL",
Op::OpEqualVerify => "OP_EQUALVERIFY",
Op::OpReserved1 => "OP_RESERVED1",
Op::OpReserved2 => "OP_RESERVED2",
Op::Op1Add => "OP_1ADD",
Op::Op1Sub => "OP_1SUB",
Op::Op2Mul => "OP_2MUL",
Op::Op2Div => "OP_2DIV",
Op::OpNegate => "OP_NEGATE",
Op::OpAbs => "OP_ABS",
Op::OpNot => "OP_NOT",
Op::Op0NotEqual => "OP_0NOTEQUAL",
Op::OpAdd => "OP_ADD",
Op::OpSub => "OP_SUB",
Op::OpMul => "OP_MUL",
Op::OpDiv => "OP_DIV",
Op::OpMod => "OP_MOD",
Op::OpLShift => "OP_LSHIFT",
Op::OpRShift => "OP_RSHIFT",
Op::OpBoolAnd => "OP_BOOLAND",
Op::OpBoolOr => "OP_BOOLOR",
Op::OpNumEqual => "OP_NUMEQUAL",
Op::OpNumEqualVerify => "OP_NUMEQUALVERIFY",
Op::OpNumNotEqual => "OP_NUMNOTEQUAL",
Op::OpLessThan => "OP_LESSTHAN",
Op::OpGreaterThan => "OP_GREATERTHAN",
Op::OpLessThanOrEqual => "OP_LESSTHANOREQUAL",
Op::OpGreaterThanOrEqual => "OP_GREATERTHANOREQUAL",
Op::OpMin => "OP_MIN",
Op::OpMax => "OP_MAX",
Op::OpWithin => "OP_WITHIN",
Op::OpRipemd160 => "OP_RIPEMD160",
Op::OpSha1 => "OP_SHA1",
Op::OpSha256 => "OP_SHA256",
Op::OpHash160 => "OP_HASH160",
Op::OpHash256 => "OP_HASH256",
Op::OpCodeSeparator => "OP_CODESEPARATOR",
Op::OpCheckSig => "OP_CHECKSIG",
Op::OpCheckSigVerify => "OP_CHECKSIGVERIFY",
Op::OpCheckMultiSig => "OP_CHECKMULTISIG",
Op::OpCheckMultiSigVerify => "OP_CHECKMULTISIGVERIFY",
Op::OpNop1 => "OP_NOP1",
Op::OpNop2 => "OP_NOP2",
Op::OpNop3 => "OP_NOP3",
Op::OpSubstr => "OP_SUBSTR",
Op::OpLeft => "OP_LEFT",
Op::OpRight => "OP_RIGHT",
Op::OpLShiftNum => "OP_LSHIFTNUM",
Op::OpRShiftNum => "OP_RSHIFTNUM",
Op::OpNop9 => "OP_NOP9",
Op::OpNop10 => "OP_NOP10",
Op::OpNop11 => "OP_NOP11",
Op::OpNop12 => "OP_NOP12",
Op::OpNop13 => "OP_NOP13",
Op::OpNop14 => "OP_NOP14",
Op::OpNop15 => "OP_NOP15",
Op::OpNop16 => "OP_NOP16",
Op::OpNop17 => "OP_NOP17",
Op::OpNop18 => "OP_NOP18",
Op::OpNop19 => "OP_NOP19",
Op::OpNop20 => "OP_NOP20",
Op::OpNop21 => "OP_NOP21",
Op::OpNop22 => "OP_NOP22",
Op::OpNop23 => "OP_NOP23",
Op::OpNop24 => "OP_NOP24",
Op::OpNop25 => "OP_NOP25",
Op::OpNop26 => "OP_NOP26",
Op::OpNop27 => "OP_NOP27",
Op::OpNop28 => "OP_NOP28",
Op::OpNop29 => "OP_NOP29",
Op::OpNop30 => "OP_NOP30",
Op::OpNop31 => "OP_NOP31",
Op::OpNop32 => "OP_NOP32",
Op::OpNop33 => "OP_NOP33",
Op::OpNop34 => "OP_NOP34",
Op::OpNop35 => "OP_NOP35",
Op::OpNop36 => "OP_NOP36",
Op::OpNop37 => "OP_NOP37",
Op::OpNop38 => "OP_NOP38",
Op::OpNop39 => "OP_NOP39",
Op::OpNop40 => "OP_NOP40",
Op::OpNop41 => "OP_NOP41",
Op::OpNop42 => "OP_NOP42",
Op::OpNop43 => "OP_NOP43",
Op::OpNop44 => "OP_NOP44",
Op::OpNop45 => "OP_NOP45",
Op::OpNop46 => "OP_NOP46",
Op::OpNop47 => "OP_NOP47",
Op::OpNop48 => "OP_NOP48",
Op::OpNop49 => "OP_NOP49",
Op::OpNop50 => "OP_NOP50",
Op::OpNop51 => "OP_NOP51",
Op::OpNop52 => "OP_NOP52",
Op::OpNop53 => "OP_NOP53",
Op::OpNop54 => "OP_NOP54",
Op::OpNop55 => "OP_NOP55",
Op::OpNop56 => "OP_NOP56",
Op::OpNop57 => "OP_NOP57",
Op::OpNop58 => "OP_NOP58",
Op::OpNop59 => "OP_NOP59",
Op::OpNop60 => "OP_NOP60",
Op::OpNop61 => "OP_NOP61",
Op::OpNop62 => "OP_NOP62",
Op::OpNop63 => "OP_NOP63",
Op::OpNop64 => "OP_NOP64",
Op::OpNop65 => "OP_NOP65",
Op::OpNop66 => "OP_NOP66",
Op::OpNop67 => "OP_NOP67",
Op::OpNop68 => "OP_NOP68",
Op::OpNop69 => "OP_NOP69",
Op::OpNop70 => "OP_NOP70",
Op::OpNop71 => "OP_NOP71",
Op::OpNop72 => "OP_NOP72",
Op::OpNop73 => "OP_NOP73",
Op::OpSmallData => "OP_SMALLDATA",
Op::OpSmallInteger => "OP_SMALLINTEGER",
Op::OpPubKeys => "OP_PUBKEYS",
Op::OpNop77 => "OP_NOP77",
Op::OpPubKeyHash => "OP_PUBKEYHASH",
Op::OpPubKey => "OP_PUBKEY",
Op::OpInvalidOpcode => "OP_INVALIDOPCODE",
}
}
pub fn to_byte(&self) -> u8 {
*self as u8
}
pub fn from_name(name: &str) -> Option<Op> {
match name {
"OP_0" | "OP_FALSE" => Some(Op::Op0),
"OP_PUSHDATA1" => Some(Op::OpPushData1),
"OP_PUSHDATA2" => Some(Op::OpPushData2),
"OP_PUSHDATA4" => Some(Op::OpPushData4),
"OP_1NEGATE" => Some(Op::Op1Negate),
"OP_RESERVED" => Some(Op::OpReserved),
"OP_1" | "OP_TRUE" => Some(Op::Op1),
"OP_2" => Some(Op::Op2),
"OP_3" => Some(Op::Op3),
"OP_4" => Some(Op::Op4),
"OP_5" => Some(Op::Op5),
"OP_6" => Some(Op::Op6),
"OP_7" => Some(Op::Op7),
"OP_8" => Some(Op::Op8),
"OP_9" => Some(Op::Op9),
"OP_10" => Some(Op::Op10),
"OP_11" => Some(Op::Op11),
"OP_12" => Some(Op::Op12),
"OP_13" => Some(Op::Op13),
"OP_14" => Some(Op::Op14),
"OP_15" => Some(Op::Op15),
"OP_16" => Some(Op::Op16),
"OP_NOP" => Some(Op::OpNop),
"OP_VER" => Some(Op::OpVer),
"OP_IF" => Some(Op::OpIf),
"OP_NOTIF" => Some(Op::OpNotIf),
"OP_VERIF" => Some(Op::OpVerIf),
"OP_VERNOTIF" => Some(Op::OpVerNotIf),
"OP_ELSE" => Some(Op::OpElse),
"OP_ENDIF" => Some(Op::OpEndIf),
"OP_VERIFY" => Some(Op::OpVerify),
"OP_RETURN" => Some(Op::OpReturn),
"OP_TOALTSTACK" => Some(Op::OpToAltStack),
"OP_FROMALTSTACK" => Some(Op::OpFromAltStack),
"OP_2DROP" => Some(Op::Op2Drop),
"OP_2DUP" => Some(Op::Op2Dup),
"OP_3DUP" => Some(Op::Op3Dup),
"OP_2OVER" => Some(Op::Op2Over),
"OP_2ROT" => Some(Op::Op2Rot),
"OP_2SWAP" => Some(Op::Op2Swap),
"OP_IFDUP" => Some(Op::OpIfDup),
"OP_DEPTH" => Some(Op::OpDepth),
"OP_DROP" => Some(Op::OpDrop),
"OP_DUP" => Some(Op::OpDup),
"OP_NIP" => Some(Op::OpNip),
"OP_OVER" => Some(Op::OpOver),
"OP_PICK" => Some(Op::OpPick),
"OP_ROLL" => Some(Op::OpRoll),
"OP_ROT" => Some(Op::OpRot),
"OP_SWAP" => Some(Op::OpSwap),
"OP_TUCK" => Some(Op::OpTuck),
"OP_CAT" => Some(Op::OpCat),
"OP_SPLIT" => Some(Op::OpSplit),
"OP_NUM2BIN" => Some(Op::OpNum2Bin),
"OP_BIN2NUM" => Some(Op::OpBin2Num),
"OP_SIZE" => Some(Op::OpSize),
"OP_INVERT" => Some(Op::OpInvert),
"OP_AND" => Some(Op::OpAnd),
"OP_OR" => Some(Op::OpOr),
"OP_XOR" => Some(Op::OpXor),
"OP_EQUAL" => Some(Op::OpEqual),
"OP_EQUALVERIFY" => Some(Op::OpEqualVerify),
"OP_RESERVED1" => Some(Op::OpReserved1),
"OP_RESERVED2" => Some(Op::OpReserved2),
"OP_1ADD" => Some(Op::Op1Add),
"OP_1SUB" => Some(Op::Op1Sub),
"OP_2MUL" => Some(Op::Op2Mul),
"OP_2DIV" => Some(Op::Op2Div),
"OP_NEGATE" => Some(Op::OpNegate),
"OP_ABS" => Some(Op::OpAbs),
"OP_NOT" => Some(Op::OpNot),
"OP_0NOTEQUAL" => Some(Op::Op0NotEqual),
"OP_ADD" => Some(Op::OpAdd),
"OP_SUB" => Some(Op::OpSub),
"OP_MUL" => Some(Op::OpMul),
"OP_DIV" => Some(Op::OpDiv),
"OP_MOD" => Some(Op::OpMod),
"OP_LSHIFT" => Some(Op::OpLShift),
"OP_RSHIFT" => Some(Op::OpRShift),
"OP_BOOLAND" => Some(Op::OpBoolAnd),
"OP_BOOLOR" => Some(Op::OpBoolOr),
"OP_NUMEQUAL" => Some(Op::OpNumEqual),
"OP_NUMEQUALVERIFY" => Some(Op::OpNumEqualVerify),
"OP_NUMNOTEQUAL" => Some(Op::OpNumNotEqual),
"OP_LESSTHAN" => Some(Op::OpLessThan),
"OP_GREATERTHAN" => Some(Op::OpGreaterThan),
"OP_LESSTHANOREQUAL" => Some(Op::OpLessThanOrEqual),
"OP_GREATERTHANOREQUAL" => Some(Op::OpGreaterThanOrEqual),
"OP_MIN" => Some(Op::OpMin),
"OP_MAX" => Some(Op::OpMax),
"OP_WITHIN" => Some(Op::OpWithin),
"OP_RIPEMD160" => Some(Op::OpRipemd160),
"OP_SHA1" => Some(Op::OpSha1),
"OP_SHA256" => Some(Op::OpSha256),
"OP_HASH160" => Some(Op::OpHash160),
"OP_HASH256" => Some(Op::OpHash256),
"OP_CODESEPARATOR" => Some(Op::OpCodeSeparator),
"OP_CHECKSIG" => Some(Op::OpCheckSig),
"OP_CHECKSIGVERIFY" => Some(Op::OpCheckSigVerify),
"OP_CHECKMULTISIG" => Some(Op::OpCheckMultiSig),
"OP_CHECKMULTISIGVERIFY" => Some(Op::OpCheckMultiSigVerify),
"OP_NOP1" => Some(Op::OpNop1),
"OP_NOP2" => Some(Op::OpNop2),
"OP_NOP3" => Some(Op::OpNop3),
"OP_NOP4" | "OP_SUBSTR" => Some(Op::OpSubstr),
"OP_NOP5" | "OP_LEFT" => Some(Op::OpLeft),
"OP_NOP6" | "OP_RIGHT" => Some(Op::OpRight),
"OP_NOP7" | "OP_LSHIFTNUM" => Some(Op::OpLShiftNum),
"OP_NOP8" | "OP_RSHIFTNUM" => Some(Op::OpRShiftNum),
"OP_INVALIDOPCODE" => Some(Op::OpInvalidOpcode),
_ => {
if let Some(suffix) = name.strip_prefix("OP_NOP") {
if let Ok(n) = suffix.parse::<u8>() {
return Some(Op::from(0xb8 + n.saturating_sub(9)));
}
}
None
}
}
}
}
impl From<u8> for Op {
fn from(byte: u8) -> Self {
match byte {
0x00 => Op::Op0,
0x4c => Op::OpPushData1,
0x4d => Op::OpPushData2,
0x4e => Op::OpPushData4,
0x4f => Op::Op1Negate,
0x50 => Op::OpReserved,
0x51 => Op::Op1,
0x52 => Op::Op2,
0x53 => Op::Op3,
0x54 => Op::Op4,
0x55 => Op::Op5,
0x56 => Op::Op6,
0x57 => Op::Op7,
0x58 => Op::Op8,
0x59 => Op::Op9,
0x5a => Op::Op10,
0x5b => Op::Op11,
0x5c => Op::Op12,
0x5d => Op::Op13,
0x5e => Op::Op14,
0x5f => Op::Op15,
0x60 => Op::Op16,
0x61 => Op::OpNop,
0x62 => Op::OpVer,
0x63 => Op::OpIf,
0x64 => Op::OpNotIf,
0x65 => Op::OpVerIf,
0x66 => Op::OpVerNotIf,
0x67 => Op::OpElse,
0x68 => Op::OpEndIf,
0x69 => Op::OpVerify,
0x6a => Op::OpReturn,
0x6b => Op::OpToAltStack,
0x6c => Op::OpFromAltStack,
0x6d => Op::Op2Drop,
0x6e => Op::Op2Dup,
0x6f => Op::Op3Dup,
0x70 => Op::Op2Over,
0x71 => Op::Op2Rot,
0x72 => Op::Op2Swap,
0x73 => Op::OpIfDup,
0x74 => Op::OpDepth,
0x75 => Op::OpDrop,
0x76 => Op::OpDup,
0x77 => Op::OpNip,
0x78 => Op::OpOver,
0x79 => Op::OpPick,
0x7a => Op::OpRoll,
0x7b => Op::OpRot,
0x7c => Op::OpSwap,
0x7d => Op::OpTuck,
0x7e => Op::OpCat,
0x7f => Op::OpSplit,
0x80 => Op::OpNum2Bin,
0x81 => Op::OpBin2Num,
0x82 => Op::OpSize,
0x83 => Op::OpInvert,
0x84 => Op::OpAnd,
0x85 => Op::OpOr,
0x86 => Op::OpXor,
0x87 => Op::OpEqual,
0x88 => Op::OpEqualVerify,
0x89 => Op::OpReserved1,
0x8a => Op::OpReserved2,
0x8b => Op::Op1Add,
0x8c => Op::Op1Sub,
0x8d => Op::Op2Mul,
0x8e => Op::Op2Div,
0x8f => Op::OpNegate,
0x90 => Op::OpAbs,
0x91 => Op::OpNot,
0x92 => Op::Op0NotEqual,
0x93 => Op::OpAdd,
0x94 => Op::OpSub,
0x95 => Op::OpMul,
0x96 => Op::OpDiv,
0x97 => Op::OpMod,
0x98 => Op::OpLShift,
0x99 => Op::OpRShift,
0x9a => Op::OpBoolAnd,
0x9b => Op::OpBoolOr,
0x9c => Op::OpNumEqual,
0x9d => Op::OpNumEqualVerify,
0x9e => Op::OpNumNotEqual,
0x9f => Op::OpLessThan,
0xa0 => Op::OpGreaterThan,
0xa1 => Op::OpLessThanOrEqual,
0xa2 => Op::OpGreaterThanOrEqual,
0xa3 => Op::OpMin,
0xa4 => Op::OpMax,
0xa5 => Op::OpWithin,
0xa6 => Op::OpRipemd160,
0xa7 => Op::OpSha1,
0xa8 => Op::OpSha256,
0xa9 => Op::OpHash160,
0xaa => Op::OpHash256,
0xab => Op::OpCodeSeparator,
0xac => Op::OpCheckSig,
0xad => Op::OpCheckSigVerify,
0xae => Op::OpCheckMultiSig,
0xaf => Op::OpCheckMultiSigVerify,
0xb0 => Op::OpNop1,
0xb1 => Op::OpNop2,
0xb2 => Op::OpNop3,
0xb3 => Op::OpSubstr,
0xb4 => Op::OpLeft,
0xb5 => Op::OpRight,
0xb6 => Op::OpLShiftNum,
0xb7 => Op::OpRShiftNum,
0xb8 => Op::OpNop9,
0xb9 => Op::OpNop10,
0xba => Op::OpNop11,
0xbb => Op::OpNop12,
0xbc => Op::OpNop13,
0xbd => Op::OpNop14,
0xbe => Op::OpNop15,
0xbf => Op::OpNop16,
0xc0 => Op::OpNop17,
0xc1 => Op::OpNop18,
0xc2 => Op::OpNop19,
0xc3 => Op::OpNop20,
0xc4 => Op::OpNop21,
0xc5 => Op::OpNop22,
0xc6 => Op::OpNop23,
0xc7 => Op::OpNop24,
0xc8 => Op::OpNop25,
0xc9 => Op::OpNop26,
0xca => Op::OpNop27,
0xcb => Op::OpNop28,
0xcc => Op::OpNop29,
0xcd => Op::OpNop30,
0xce => Op::OpNop31,
0xcf => Op::OpNop32,
0xd0 => Op::OpNop33,
0xd1 => Op::OpNop34,
0xd2 => Op::OpNop35,
0xd3 => Op::OpNop36,
0xd4 => Op::OpNop37,
0xd5 => Op::OpNop38,
0xd6 => Op::OpNop39,
0xd7 => Op::OpNop40,
0xd8 => Op::OpNop41,
0xd9 => Op::OpNop42,
0xda => Op::OpNop43,
0xdb => Op::OpNop44,
0xdc => Op::OpNop45,
0xdd => Op::OpNop46,
0xde => Op::OpNop47,
0xdf => Op::OpNop48,
0xe0 => Op::OpNop49,
0xe1 => Op::OpNop50,
0xe2 => Op::OpNop51,
0xe3 => Op::OpNop52,
0xe4 => Op::OpNop53,
0xe5 => Op::OpNop54,
0xe6 => Op::OpNop55,
0xe7 => Op::OpNop56,
0xe8 => Op::OpNop57,
0xe9 => Op::OpNop58,
0xea => Op::OpNop59,
0xeb => Op::OpNop60,
0xec => Op::OpNop61,
0xed => Op::OpNop62,
0xee => Op::OpNop63,
0xef => Op::OpNop64,
0xf0 => Op::OpNop65,
0xf1 => Op::OpNop66,
0xf2 => Op::OpNop67,
0xf3 => Op::OpNop68,
0xf4 => Op::OpNop69,
0xf5 => Op::OpNop70,
0xf6 => Op::OpNop71,
0xf7 => Op::OpNop72,
0xf8 => Op::OpNop73,
0xf9 => Op::OpSmallData,
0xfa => Op::OpSmallInteger,
0xfb => Op::OpPubKeys,
0xfc => Op::OpNop77,
0xfd => Op::OpPubKeyHash,
0xfe => Op::OpPubKey,
0xff => Op::OpInvalidOpcode,
_ => Op::OpInvalidOpcode,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_u8_roundtrip_known_opcodes() {
let known: Vec<(u8, Op)> = vec![
(0x00, Op::Op0),
(0x4c, Op::OpPushData1),
(0x4d, Op::OpPushData2),
(0x4e, Op::OpPushData4),
(0x4f, Op::Op1Negate),
(0x50, Op::OpReserved),
(0x51, Op::Op1),
(0x60, Op::Op16),
(0x61, Op::OpNop),
(0x63, Op::OpIf),
(0x68, Op::OpEndIf),
(0x6a, Op::OpReturn),
(0x76, Op::OpDup),
(0x7e, Op::OpCat),
(0x7f, Op::OpSplit),
(0x80, Op::OpNum2Bin),
(0x81, Op::OpBin2Num),
(0x87, Op::OpEqual),
(0x88, Op::OpEqualVerify),
(0x93, Op::OpAdd),
(0x95, Op::OpMul),
(0x96, Op::OpDiv),
(0x97, Op::OpMod),
(0x98, Op::OpLShift),
(0x99, Op::OpRShift),
(0xa9, Op::OpHash160),
(0xac, Op::OpCheckSig),
(0xae, Op::OpCheckMultiSig),
(0xb0, Op::OpNop1),
(0xb3, Op::OpSubstr),
(0xb4, Op::OpLeft),
(0xb5, Op::OpRight),
(0xb6, Op::OpLShiftNum),
(0xb7, Op::OpRShiftNum),
(0xff, Op::OpInvalidOpcode),
];
for (byte, expected) in known {
let op = Op::from(byte);
assert_eq!(op, expected, "From<u8> for byte {:#04x} failed", byte);
assert_eq!(op.to_byte(), byte, "to_byte for {:#04x} failed", byte);
}
}
#[test]
fn test_unknown_bytes_map_to_invalid() {
for byte in 0x01..=0x4bu8 {
assert_eq!(
Op::from(byte),
Op::OpInvalidOpcode,
"Direct-push byte {:#04x} should map to OpInvalidOpcode",
byte
);
}
}
#[test]
fn test_to_name_common_opcodes() {
assert_eq!(Op::Op0.to_name(), "OP_0");
assert_eq!(Op::OpDup.to_name(), "OP_DUP");
assert_eq!(Op::OpCheckSig.to_name(), "OP_CHECKSIG");
assert_eq!(Op::OpReturn.to_name(), "OP_RETURN");
assert_eq!(Op::OpHash160.to_name(), "OP_HASH160");
assert_eq!(Op::OpEqualVerify.to_name(), "OP_EQUALVERIFY");
assert_eq!(Op::Op1.to_name(), "OP_1");
assert_eq!(Op::Op16.to_name(), "OP_16");
assert_eq!(Op::OpCat.to_name(), "OP_CAT");
assert_eq!(Op::OpMul.to_name(), "OP_MUL");
assert_eq!(Op::OpSubstr.to_name(), "OP_SUBSTR");
assert_eq!(Op::OpInvalidOpcode.to_name(), "OP_INVALIDOPCODE");
}
#[test]
fn test_from_name_roundtrip() {
let names = [
"OP_0",
"OP_DUP",
"OP_CHECKSIG",
"OP_RETURN",
"OP_HASH160",
"OP_EQUALVERIFY",
"OP_1",
"OP_16",
"OP_CAT",
"OP_MUL",
"OP_SUBSTR",
"OP_INVALIDOPCODE",
"OP_FALSE",
"OP_TRUE",
];
for name in &names {
let op = Op::from_name(name).unwrap_or_else(|| panic!("from_name failed for {}", name));
let canonical = op.to_name();
let op2 = Op::from_name(canonical)
.unwrap_or_else(|| panic!("from_name failed for canonical {}", canonical));
assert_eq!(op, op2);
}
}
#[test]
fn test_all_nop_variants_exist() {
for byte in 0xb8..=0xf8u8 {
let op = Op::from(byte);
assert_ne!(
op,
Op::OpInvalidOpcode,
"Byte {:#04x} should not be OpInvalidOpcode",
byte
);
}
}
#[test]
fn test_opcode_count() {
let mut count = 0u32;
for byte in 0x00..=0xffu16 {
let op = Op::from(byte as u8);
if op != Op::OpInvalidOpcode || byte == 0xff {
count += 1;
}
}
assert!(
count >= 130,
"Expected at least 130 named opcodes, got {}",
count
);
}
}