From f33c8ea418a4f99c151ade18755017238a98d5b7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 30 Aug 2023 20:20:20 +0000 Subject: [PATCH] zcash_primitives: Parse the full opcode set This enhances the alternate `impl Debug for Script` to render unexpected scripts correctly. --- zcash_primitives/src/legacy.rs | 225 ++++++++++++++++++++++++++++++++- 1 file changed, 224 insertions(+), 1 deletion(-) diff --git a/zcash_primitives/src/legacy.rs b/zcash_primitives/src/legacy.rs index cdbbc2512..17ae8b0a0 100644 --- a/zcash_primitives/src/legacy.rs +++ b/zcash_primitives/src/legacy.rs @@ -11,37 +11,260 @@ use zcash_encoding::Vector; #[cfg(feature = "transparent-inputs")] pub mod keys; -/// Minimal subset of script opcodes. +/// Defined script opcodes. +/// +/// Most of the opcodes are unused by this crate, but we define them so that the alternate +/// `Debug` impl for [`Script`] renders correctly for unexpected scripts. #[derive(Debug)] enum OpCode { // push value + Op0 = 0x00, // False PushData1 = 0x4c, PushData2 = 0x4d, PushData4 = 0x4e, + Negative1 = 0x4f, + Reserved = 0x50, + Op1 = 0x51, // True + 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, + + // control + Nop = 0x61, + Ver = 0x62, + If = 0x63, + NotIf = 0x64, + VerIf = 0x65, + VerNotIf = 0x66, + Else = 0x67, + EndIf = 0x68, + Verify = 0x69, + Return = 0x6a, // stack ops + ToAltStack = 0x6b, + FromAltStack = 0x6c, + Drop2 = 0x6d, + Dup2 = 0x6e, + Dup3 = 0x6f, + Over2 = 0x70, + Rot2 = 0x71, + Swap2 = 0x72, + IfDup = 0x73, + Depth = 0x74, + Drop = 0x75, Dup = 0x76, + Nip = 0x77, + Over = 0x78, + Pick = 0x79, + Roll = 0x7a, + Rot = 0x7b, + Swap = 0x7c, + Tuck = 0x7d, + + // splice ops + Cat = 0x7e, // Disabled + Substr = 0x7f, // Disabled + Left = 0x80, // Disabled + Right = 0x81, // Disabled + Size = 0x82, // bit logic + Invert = 0x83, // Disabled + And = 0x84, // Disabled + Or = 0x85, // Disabled + Xor = 0x86, // Disabled Equal = 0x87, EqualVerify = 0x88, + Reserved1 = 0x89, + Reserved2 = 0x8a, + + // numeric + Add1 = 0x8b, + Sub1 = 0x8c, + Mul2 = 0x8d, // Disabled + Div2 = 0x8e, // Disabled + Negate = 0x8f, + Abs = 0x90, + Not = 0x91, + NotEqual0 = 0x92, + + Add = 0x93, + Sub = 0x94, + Mul = 0x95, // Disabled + Div = 0x96, // Disabled + Mod = 0x97, // Disabled + LShift = 0x98, // Disabled + RShift = 0x99, // Disabled + + BoolAnd = 0x9a, + BoolOr = 0x9b, + NumEqual = 0x9c, + NumEqualVerify = 0x9d, + NumNotEqual = 0x9e, + LessThan = 0x9f, + GreaterThan = 0xa0, + LessThanOrEqual = 0xa1, + GreaterThanOrEqual = 0xa2, + Min = 0xa3, + Max = 0xa4, + + Within = 0xa5, // crypto + Ripemd160 = 0xa6, + Sha1 = 0xa7, + Sha256 = 0xa8, Hash160 = 0xa9, + Hash256 = 0xaa, + CodeSeparator = 0xab, // Disabled CheckSig = 0xac, + CheckSigVerify = 0xad, + CheckMultisig = 0xae, + CheckMultisigVerify = 0xaf, + + // expansion + Nop1 = 0xb0, + CheckLockTimeVerify = 0xb1, + Nop3 = 0xb2, + Nop4 = 0xb3, + Nop5 = 0xb4, + Nop6 = 0xb5, + Nop7 = 0xb6, + Nop8 = 0xb7, + Nop9 = 0xb8, + Nop10 = 0xb9, + + InvalidOpCode = 0xff, } impl OpCode { fn parse(b: u8) -> Option { match b { + 0x00 => Some(OpCode::Op0), 0x4c => Some(OpCode::PushData1), 0x4d => Some(OpCode::PushData2), 0x4e => Some(OpCode::PushData4), + 0x4f => Some(OpCode::Negative1), + 0x50 => Some(OpCode::Reserved), + 0x51 => Some(OpCode::Op1), + 0x52 => Some(OpCode::Op2), + 0x53 => Some(OpCode::Op3), + 0x54 => Some(OpCode::Op4), + 0x55 => Some(OpCode::Op5), + 0x56 => Some(OpCode::Op6), + 0x57 => Some(OpCode::Op7), + 0x58 => Some(OpCode::Op8), + 0x59 => Some(OpCode::Op9), + 0x5a => Some(OpCode::Op10), + 0x5b => Some(OpCode::Op11), + 0x5c => Some(OpCode::Op12), + 0x5d => Some(OpCode::Op13), + 0x5e => Some(OpCode::Op14), + 0x5f => Some(OpCode::Op15), + 0x60 => Some(OpCode::Op16), + 0x61 => Some(OpCode::Nop), + 0x62 => Some(OpCode::Ver), + 0x63 => Some(OpCode::If), + 0x64 => Some(OpCode::NotIf), + 0x65 => Some(OpCode::VerIf), + 0x66 => Some(OpCode::VerNotIf), + 0x67 => Some(OpCode::Else), + 0x68 => Some(OpCode::EndIf), + 0x69 => Some(OpCode::Verify), + 0x6a => Some(OpCode::Return), + 0x6b => Some(OpCode::ToAltStack), + 0x6c => Some(OpCode::FromAltStack), + 0x6d => Some(OpCode::Drop2), + 0x6e => Some(OpCode::Dup2), + 0x6f => Some(OpCode::Dup3), + 0x70 => Some(OpCode::Over2), + 0x71 => Some(OpCode::Rot2), + 0x72 => Some(OpCode::Swap2), + 0x73 => Some(OpCode::IfDup), + 0x74 => Some(OpCode::Depth), + 0x75 => Some(OpCode::Drop), 0x76 => Some(OpCode::Dup), + 0x77 => Some(OpCode::Nip), + 0x78 => Some(OpCode::Over), + 0x79 => Some(OpCode::Pick), + 0x7a => Some(OpCode::Roll), + 0x7b => Some(OpCode::Rot), + 0x7c => Some(OpCode::Swap), + 0x7d => Some(OpCode::Tuck), + 0x7e => Some(OpCode::Cat), + 0x7f => Some(OpCode::Substr), + 0x80 => Some(OpCode::Left), + 0x81 => Some(OpCode::Right), + 0x82 => Some(OpCode::Size), + 0x83 => Some(OpCode::Invert), + 0x84 => Some(OpCode::And), + 0x85 => Some(OpCode::Or), + 0x86 => Some(OpCode::Xor), 0x87 => Some(OpCode::Equal), 0x88 => Some(OpCode::EqualVerify), + 0x89 => Some(OpCode::Reserved1), + 0x8a => Some(OpCode::Reserved2), + 0x8b => Some(OpCode::Add1), + 0x8c => Some(OpCode::Sub1), + 0x8d => Some(OpCode::Mul2), + 0x8e => Some(OpCode::Div2), + 0x8f => Some(OpCode::Negate), + 0x90 => Some(OpCode::Abs), + 0x91 => Some(OpCode::Not), + 0x92 => Some(OpCode::NotEqual0), + 0x93 => Some(OpCode::Add), + 0x94 => Some(OpCode::Sub), + 0x95 => Some(OpCode::Mul), + 0x96 => Some(OpCode::Div), + 0x97 => Some(OpCode::Mod), + 0x98 => Some(OpCode::LShift), + 0x99 => Some(OpCode::RShift), + 0x9a => Some(OpCode::BoolAnd), + 0x9b => Some(OpCode::BoolOr), + 0x9c => Some(OpCode::NumEqual), + 0x9d => Some(OpCode::NumEqualVerify), + 0x9e => Some(OpCode::NumNotEqual), + 0x9f => Some(OpCode::LessThan), + 0xa0 => Some(OpCode::GreaterThan), + 0xa1 => Some(OpCode::LessThanOrEqual), + 0xa2 => Some(OpCode::GreaterThanOrEqual), + 0xa3 => Some(OpCode::Min), + 0xa4 => Some(OpCode::Max), + 0xa5 => Some(OpCode::Within), + 0xa6 => Some(OpCode::Ripemd160), + 0xa7 => Some(OpCode::Sha1), + 0xa8 => Some(OpCode::Sha256), 0xa9 => Some(OpCode::Hash160), + 0xaa => Some(OpCode::Hash256), + 0xab => Some(OpCode::CodeSeparator), 0xac => Some(OpCode::CheckSig), + 0xad => Some(OpCode::CheckSigVerify), + 0xae => Some(OpCode::CheckMultisig), + 0xaf => Some(OpCode::CheckMultisigVerify), + 0xb0 => Some(OpCode::Nop1), + 0xb1 => Some(OpCode::CheckLockTimeVerify), + 0xb2 => Some(OpCode::Nop3), + 0xb3 => Some(OpCode::Nop4), + 0xb4 => Some(OpCode::Nop5), + 0xb5 => Some(OpCode::Nop6), + 0xb6 => Some(OpCode::Nop7), + 0xb7 => Some(OpCode::Nop8), + 0xb8 => Some(OpCode::Nop9), + 0xb9 => Some(OpCode::Nop10), + 0xff => Some(OpCode::InvalidOpCode), _ => None, } }