Add serde regression tests

In order that we can safely change/maintain de/serialization code we
need to have regression tests with hard coded serializations for each
type that implements serde.

It is enough to test a single serde data format, use JSON for `opcodes`
and bincode for other types.

Do regression testing in a newly added `tests` module.
This commit is contained in:
Tobin Harding 2021-11-26 10:36:41 +11:00 committed by Tobin C. Harding
parent bbf89dd5a4
commit 962abcc963
38 changed files with 717 additions and 0 deletions

View File

@ -0,0 +1,12 @@
Serialization input/output
==========================
Files here contain hex strings and binary data representing types used for
regression testing.
- *_hex: consensus encoded types represented as hex strings
- *_ser: consensus encoded types represented as binary data
- *_bincode: types serialized with serde as bincode
We consensus deserialize, serde serialize, then check against the expected data
to verify no serde regressions have been introduced.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
<EFBFBD>ュ゙

Binary file not shown.

View File

@ -0,0 +1 @@
c1a9d6f66cd4b25004f526bfa873e56942f98e8e492bd79ed6532b966104817c2bda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0641e660d1e5392fb79d64838c2b84faf04b7f5f283c9d8bf83e39e177b64372a0cd22eeab7e093873e851e247714eff762d8a30be699ba4456cfe6491b282e193a071350ae099005a5950d74f73ba13077a57bc478007fb0e4d1099ce9cf3d4

Binary file not shown.

View File

@ -0,0 +1 @@
3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45

View File

@ -0,0 +1 @@
xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi

Binary file not shown.

View File

@ -0,0 +1 @@
xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

418
bitcoin/tests/serde.rs Normal file
View File

@ -0,0 +1,418 @@
//! Regression tests for _most_ types that implement `serde::Serialize`.
//!
//! For remaining types see: ./serde_opcodes.rs
//!
//! If you find a type defined in `rust-bitcoin` that implements `Serialize` and does _not_ have a
//! regression test please add it.
//!
//! Types/tests were found using, and are ordered by, the output of: `git grep -l Serialize`.
//!
// In tests below `deserialize` is consensus deserialize while `serialize` is serde serialize, that
// is why we have two different serialized data files for tests that use binary serialized input.
//
// To create a file with the expected serialized data do something like:
//
// use std::fs::File;
// use std::io::Write;
// let script = Script::from(vec![0u8, 1u8, 2u8]);
// let got = serialize(&script).unwrap();
// let mut file = File::create("/tmp/script_bincode").unwrap();
// file.write_all(&got).unwrap();
#![cfg(feature = "serde")]
use std::collections::BTreeMap;
use std::str::FromStr;
use bincode::serialize;
use bitcoin::blockdata::locktime::{absolute, relative};
use bitcoin::blockdata::witness::Witness;
use bitcoin::consensus::encode::deserialize;
use bitcoin::hashes::hex::FromHex;
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
use bitcoin::sighash::{EcdsaSighashType, SchnorrSighashType};
use bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource};
use bitcoin::util::psbt::raw::{self, Key, Pair, ProprietaryKey};
use bitcoin::util::psbt::{Input, Output, Psbt, PsbtSighashType};
use bitcoin::util::schnorr::UntweakedPublicKey;
use bitcoin::util::taproot::{ControlBlock, LeafVersion, TaprootBuilder, TaprootSpendInfo};
use bitcoin::{
Address, Block, EcdsaSig, Network, OutPoint, PrivateKey, PublicKey, SchnorrSig, Script,
Sequence, Target, Transaction, TxIn, TxOut, Txid, Work,
};
use secp256k1::Secp256k1;
/// Implicitly does regression test for `BlockHeader` also.
#[test]
fn serde_regression_block() {
let segwit = include_bytes!(
"data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw"
);
let block: Block = deserialize(segwit).unwrap();
let got = serialize(&block).unwrap();
// The cast is required because Rust 1.41.1 throws the following error without it:
// the trait `std::array::LengthAtMost32` is not implemented for `[u8; 5123]`
let want = include_bytes!("data/serde/block_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_absolute_lock_time_height() {
let t = absolute::LockTime::from_height(741521).expect("valid height");
let got = serialize(&t).unwrap();
let want = include_bytes!("data/serde/absolute_lock_time_blocks_bincode") as &[_];
assert_eq!(got, want);
}
#[test]
fn serde_regression_absolute_lock_time_time() {
let seconds: u32 = 1653195600; // May 22nd, 5am UTC.
let t = absolute::LockTime::from_time(seconds).expect("valid time");
let got = serialize(&t).unwrap();
let want = include_bytes!("data/serde/absolute_lock_time_seconds_bincode") as &[_];
assert_eq!(got, want);
}
#[test]
fn serde_regression_relative_lock_time_height() {
let t = relative::LockTime::from(relative::Height::from(0xCAFE_u16));
let got = serialize(&t).unwrap();
let want = include_bytes!("data/serde/relative_lock_time_blocks_bincode") as &[_];
assert_eq!(got, want);
}
#[test]
fn serde_regression_relative_lock_time_time() {
let t = relative::LockTime::from(relative::Time::from_512_second_intervals(0xFACE_u16));
let got = serialize(&t).unwrap();
let want = include_bytes!("data/serde/relative_lock_time_seconds_bincode") as &[_];
assert_eq!(got, want);
}
#[test]
fn serde_regression_script() {
let script = Script::from(vec![0u8, 1u8, 2u8]);
let got = serialize(&script).unwrap();
let want = include_bytes!("data/serde/script_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_txin() {
let ser = include_bytes!("data/serde/txin_ser");
let txin: TxIn = deserialize(ser).unwrap();
let got = serialize(&txin).unwrap();
let want = include_bytes!("data/serde/txin_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_txout() {
let txout =
TxOut { value: 0xDEADBEEFCAFEBABE, script_pubkey: Script::from(vec![0u8, 1u8, 2u8]) };
let got = serialize(&txout).unwrap();
let want = include_bytes!("data/serde/txout_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_transaction() {
let ser = include_bytes!("data/serde/transaction_ser");
let tx: Transaction = deserialize(ser).unwrap();
let got = serialize(&tx).unwrap();
let want = include_bytes!("data/serde/transaction_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_witness() {
let w0 = Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")
.unwrap();
let w1 = Vec::from_hex("000000").unwrap();
let vec = vec![w0, w1];
let witness = Witness::from_vec(vec);
let got = serialize(&witness).unwrap();
let want = include_bytes!("data/serde/witness_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_address() {
let s = include_str!("data/serde/public_key_hex");
let pk = PublicKey::from_str(s.trim()).unwrap();
let addr = Address::p2pkh(&pk, Network::Bitcoin);
let got = serialize(&addr).unwrap();
let want = include_bytes!("data/serde/address_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_extended_priv_key() {
let s = include_str!("data/serde/extended_priv_key");
let key = ExtendedPrivKey::from_str(s.trim()).unwrap();
let got = serialize(&key).unwrap();
let want = include_bytes!("data/serde/extended_priv_key_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_extended_pub_key() {
let s = include_str!("data/serde/extended_pub_key");
let key = ExtendedPubKey::from_str(s.trim()).unwrap();
let got = serialize(&key).unwrap();
let want = include_bytes!("data/serde/extended_pub_key_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_ecdsa_sig() {
let s = include_str!("data/serde/ecdsa_sig_hex");
let sig = EcdsaSig {
sig: secp256k1::ecdsa::Signature::from_str(s.trim()).unwrap(),
hash_ty: EcdsaSighashType::All,
};
let got = serialize(&sig).unwrap();
let want = include_bytes!("data/serde/ecdsa_sig_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_control_block() {
let s = include_str!("data/serde/control_block_hex");
let block = ControlBlock::from_slice(&Vec::<u8>::from_hex(s.trim()).unwrap()).unwrap();
let got = serialize(&block).unwrap();
let want = include_bytes!("data/serde/control_block_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_child_number() {
let num = ChildNumber::Normal { index: 0xDEADBEEF };
let got = serialize(&num).unwrap();
let want = include_bytes!("data/serde/child_number_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_private_key() {
let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
let got = serialize(&sk).unwrap();
let want = include_bytes!("data/serde/private_key_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_public_key() {
let s = include_str!("data/serde/public_key_hex");
let pk = PublicKey::from_str(s.trim()).unwrap();
let got = serialize(&pk).unwrap();
let want = include_bytes!("data/serde/public_key_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_psbt() {
let tx = Transaction {
version: 1,
lock_time: absolute::PackedLockTime::ZERO,
input: vec![TxIn {
previous_output: OutPoint {
txid: Txid::from_hex(
"e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
)
.unwrap(),
vout: 1,
},
script_sig: Script::from_str("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
sequence: Sequence::from_consensus(4294967295),
witness: Witness::from_vec(vec![Vec::from_hex(
"03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105",
)
.unwrap()]),
}],
output: vec![TxOut {
value: 190303501938,
script_pubkey: Script::from_str("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587")
.unwrap(),
}],
};
let unknown: BTreeMap<raw::Key, Vec<u8>> =
vec![(raw::Key { type_value: 1, key: vec![0, 1] }, vec![3, 4, 5])].into_iter().collect();
let key_source = ("deadbeef".parse().unwrap(), "m/0'/1".parse().unwrap());
let keypaths: BTreeMap<secp256k1::PublicKey, KeySource> = vec![(
"0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
key_source.clone(),
)]
.into_iter()
.collect();
let proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = vec![(
raw::ProprietaryKey {
prefix: "prefx".as_bytes().to_vec(),
subtype: 42,
key: "test_key".as_bytes().to_vec(),
},
vec![5, 6, 7],
)]
.into_iter()
.collect();
let psbt = Psbt {
version: 0,
xpub: {
let s = include_str!("data/serde/extended_pub_key");
let xpub = ExtendedPubKey::from_str(s.trim()).unwrap();
vec![(xpub, key_source)].into_iter().collect()
},
unsigned_tx: {
let mut unsigned = tx.clone();
unsigned.input[0].script_sig = Script::new();
unsigned.input[0].witness = Witness::default();
unsigned
},
proprietary: proprietary.clone(),
unknown: unknown.clone(),
inputs: vec![Input {
non_witness_utxo: Some(tx),
witness_utxo: Some(TxOut {
value: 190303501938,
script_pubkey: Script::from_str("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
}),
sighash_type: Some(PsbtSighashType::from(EcdsaSighashType::from_str("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY").unwrap())),
redeem_script: Some(vec![0x51].into()),
witness_script: None,
partial_sigs: vec![(
"0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
"304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(),
)].into_iter().collect(),
bip32_derivation: keypaths.clone().into_iter().collect(),
final_script_witness: Some(Witness::from_vec(vec![vec![1, 3], vec![5]])),
ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
hash256_preimages: vec![(sha256d::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
proprietary: proprietary.clone(),
unknown: unknown.clone(),
..Default::default()
}],
outputs: vec![Output {
bip32_derivation: keypaths.into_iter().collect(),
proprietary,
unknown,
..Default::default()
}],
};
let got = serialize(&psbt).unwrap();
let want = include_bytes!("data/serde/psbt_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_raw_pair() {
let pair = Pair {
key: Key { type_value: 1u8, key: vec![0u8, 1u8, 2u8, 3u8] },
value: vec![0u8, 1u8, 2u8, 3u8],
};
let got = serialize(&pair).unwrap();
let want = include_bytes!("data/serde/raw_pair_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_proprietary_key() {
let key = ProprietaryKey {
prefix: vec![0u8, 1u8, 2u8, 3u8],
subtype: 1u8,
key: vec![0u8, 1u8, 2u8, 3u8],
};
let got = serialize(&key).unwrap();
let want = include_bytes!("data/serde/proprietary_key_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_schnorr_sig() {
let s = include_str!("data/serde/schnorr_sig_hex");
let sig = SchnorrSig {
sig: secp256k1::schnorr::Signature::from_str(s.trim()).unwrap(),
hash_ty: SchnorrSighashType::All,
};
let got = serialize(&sig).unwrap();
let want = include_bytes!("data/serde/schnorr_sig_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_taproot_builder() {
let ver = LeafVersion::from_consensus(0).unwrap();
let script = Script::from(vec![0u8, 1u8, 2u8]);
let builder = TaprootBuilder::new().add_leaf_with_ver(1, script, ver).unwrap();
let got = serialize(&builder).unwrap();
let want = include_bytes!("data/serde/taproot_builder_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_taproot_spend_info() {
let secp = Secp256k1::verification_only();
let internal_key = UntweakedPublicKey::from_str(
"93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51",
)
.unwrap();
let script_weights = vec![
(10, Script::from_hex("51").unwrap()), // semantics of script don't matter for this test
(20, Script::from_hex("52").unwrap()),
(20, Script::from_hex("53").unwrap()),
(30, Script::from_hex("54").unwrap()),
(19, Script::from_hex("55").unwrap()),
];
let tree_info =
TaprootSpendInfo::with_huffman_tree(&secp, internal_key, script_weights).unwrap();
let got = serialize(&tree_info).unwrap();
let want = include_bytes!("data/serde/taproot_spend_info_bincode") as &[_];
assert_eq!(got, want)
}
// Used to get a 256 bit integer as a byte array.
fn le_bytes() -> [u8; 32] {
let x: u128 = 0xDEAD_BEEF_CAFE_BABE_DEAD_BEEF_CAFE_BABE;
let y: u128 = 0xCAFE_DEAD_BABE_BEEF_CAFE_DEAD_BABE_BEEF;
let mut bytes = [0_u8; 32];
bytes[..16].copy_from_slice(&x.to_le_bytes());
bytes[16..].copy_from_slice(&y.to_le_bytes());
bytes
}
#[test]
fn serde_regression_work() {
let work = Work::from_le_bytes(le_bytes());
let got = serialize(&work).unwrap();
let want = include_bytes!("data/serde/u256_bincode") as &[_];
assert_eq!(got, want)
}
#[test]
fn serde_regression_target() {
let target = Target::from_le_bytes(le_bytes());
let got = serialize(&target).unwrap();
let want = include_bytes!("data/serde/u256_bincode") as &[_];
assert_eq!(got, want)
}

View File

@ -0,0 +1,280 @@
//! serde regression tests for blockdata::opcodes module.
//!
#![cfg(feature = "serde")]
extern crate bitcoin;
extern crate serde_json;
macro_rules! test_opcodes {
($($op:ident),* $(,)+) => {
$(
let op = bitcoin::blockdata::opcodes::all::$op;
let want = concat!("\"", stringify!($op), "\"");
let got = ::serde_json::to_string(&op).unwrap();
assert_eq!(got, want);
)*
}
}
#[test]
fn serde_regression_opcodes() {
test_opcodes! {
OP_PUSHBYTES_0,
OP_PUSHBYTES_1,
OP_PUSHBYTES_2,
OP_PUSHBYTES_3,
OP_PUSHBYTES_4,
OP_PUSHBYTES_5,
OP_PUSHBYTES_6,
OP_PUSHBYTES_7,
OP_PUSHBYTES_8,
OP_PUSHBYTES_9,
OP_PUSHBYTES_10,
OP_PUSHBYTES_11,
OP_PUSHBYTES_12,
OP_PUSHBYTES_13,
OP_PUSHBYTES_14,
OP_PUSHBYTES_15,
OP_PUSHBYTES_16,
OP_PUSHBYTES_17,
OP_PUSHBYTES_18,
OP_PUSHBYTES_19,
OP_PUSHBYTES_20,
OP_PUSHBYTES_21,
OP_PUSHBYTES_22,
OP_PUSHBYTES_23,
OP_PUSHBYTES_24,
OP_PUSHBYTES_25,
OP_PUSHBYTES_26,
OP_PUSHBYTES_27,
OP_PUSHBYTES_28,
OP_PUSHBYTES_29,
OP_PUSHBYTES_30,
OP_PUSHBYTES_31,
OP_PUSHBYTES_32,
OP_PUSHBYTES_33,
OP_PUSHBYTES_34,
OP_PUSHBYTES_35,
OP_PUSHBYTES_36,
OP_PUSHBYTES_37,
OP_PUSHBYTES_38,
OP_PUSHBYTES_39,
OP_PUSHBYTES_40,
OP_PUSHBYTES_41,
OP_PUSHBYTES_42,
OP_PUSHBYTES_43,
OP_PUSHBYTES_44,
OP_PUSHBYTES_45,
OP_PUSHBYTES_46,
OP_PUSHBYTES_47,
OP_PUSHBYTES_48,
OP_PUSHBYTES_49,
OP_PUSHBYTES_50,
OP_PUSHBYTES_51,
OP_PUSHBYTES_52,
OP_PUSHBYTES_53,
OP_PUSHBYTES_54,
OP_PUSHBYTES_55,
OP_PUSHBYTES_56,
OP_PUSHBYTES_57,
OP_PUSHBYTES_58,
OP_PUSHBYTES_59,
OP_PUSHBYTES_60,
OP_PUSHBYTES_61,
OP_PUSHBYTES_62,
OP_PUSHBYTES_63,
OP_PUSHBYTES_64,
OP_PUSHBYTES_65,
OP_PUSHBYTES_66,
OP_PUSHBYTES_67,
OP_PUSHBYTES_68,
OP_PUSHBYTES_69,
OP_PUSHBYTES_70,
OP_PUSHBYTES_71,
OP_PUSHBYTES_72,
OP_PUSHBYTES_73,
OP_PUSHBYTES_74,
OP_PUSHBYTES_75,
OP_PUSHDATA1,
OP_PUSHDATA2,
OP_PUSHDATA4,
OP_PUSHNUM_NEG1,
OP_RESERVED,
OP_PUSHNUM_1,
OP_PUSHNUM_2,
OP_PUSHNUM_3,
OP_PUSHNUM_4,
OP_PUSHNUM_5,
OP_PUSHNUM_6,
OP_PUSHNUM_7,
OP_PUSHNUM_8,
OP_PUSHNUM_9,
OP_PUSHNUM_10,
OP_PUSHNUM_11,
OP_PUSHNUM_12,
OP_PUSHNUM_13,
OP_PUSHNUM_14,
OP_PUSHNUM_15,
OP_PUSHNUM_16,
OP_NOP,
OP_VER,
OP_IF,
OP_NOTIF,
OP_VERIF,
OP_VERNOTIF,
OP_ELSE,
OP_ENDIF,
OP_VERIFY,
OP_RETURN,
OP_TOALTSTACK,
OP_FROMALTSTACK,
OP_2DROP,
OP_2DUP,
OP_3DUP,
OP_2OVER,
OP_2ROT,
OP_2SWAP,
OP_IFDUP,
OP_DEPTH,
OP_DROP,
OP_DUP,
OP_NIP,
OP_OVER,
OP_PICK,
OP_ROLL,
OP_ROT,
OP_SWAP,
OP_TUCK,
OP_CAT,
OP_SUBSTR,
OP_LEFT,
OP_RIGHT,
OP_SIZE,
OP_INVERT,
OP_AND,
OP_OR,
OP_XOR,
OP_EQUAL,
OP_EQUALVERIFY,
OP_RESERVED1,
OP_RESERVED2,
OP_1ADD,
OP_1SUB,
OP_2MUL,
OP_2DIV,
OP_NEGATE,
OP_ABS,
OP_NOT,
OP_0NOTEQUAL,
OP_ADD,
OP_SUB,
OP_MUL,
OP_DIV,
OP_MOD,
OP_LSHIFT,
OP_RSHIFT,
OP_BOOLAND,
OP_BOOLOR,
OP_NUMEQUAL,
OP_NUMEQUALVERIFY,
OP_NUMNOTEQUAL,
OP_LESSTHAN ,
OP_GREATERTHAN ,
OP_LESSTHANOREQUAL ,
OP_GREATERTHANOREQUAL ,
OP_MIN,
OP_MAX,
OP_WITHIN,
OP_RIPEMD160,
OP_SHA1,
OP_SHA256,
OP_HASH160,
OP_HASH256,
OP_CODESEPARATOR,
OP_CHECKSIG,
OP_CHECKSIGVERIFY,
OP_CHECKMULTISIG,
OP_CHECKMULTISIGVERIFY,
OP_NOP1,
OP_CLTV,
OP_CSV,
OP_NOP4,
OP_NOP5,
OP_NOP6,
OP_NOP7,
OP_NOP8,
OP_NOP9,
OP_NOP10,
OP_CHECKSIGADD,
OP_RETURN_187,
OP_RETURN_188,
OP_RETURN_189,
OP_RETURN_190,
OP_RETURN_191,
OP_RETURN_192,
OP_RETURN_193,
OP_RETURN_194,
OP_RETURN_195,
OP_RETURN_196,
OP_RETURN_197,
OP_RETURN_198,
OP_RETURN_199,
OP_RETURN_200,
OP_RETURN_201,
OP_RETURN_202,
OP_RETURN_203,
OP_RETURN_204,
OP_RETURN_205,
OP_RETURN_206,
OP_RETURN_207,
OP_RETURN_208,
OP_RETURN_209,
OP_RETURN_210,
OP_RETURN_211,
OP_RETURN_212,
OP_RETURN_213,
OP_RETURN_214,
OP_RETURN_215,
OP_RETURN_216,
OP_RETURN_217,
OP_RETURN_218,
OP_RETURN_219,
OP_RETURN_220,
OP_RETURN_221,
OP_RETURN_222,
OP_RETURN_223,
OP_RETURN_224,
OP_RETURN_225,
OP_RETURN_226,
OP_RETURN_227,
OP_RETURN_228,
OP_RETURN_229,
OP_RETURN_230,
OP_RETURN_231,
OP_RETURN_232,
OP_RETURN_233,
OP_RETURN_234,
OP_RETURN_235,
OP_RETURN_236,
OP_RETURN_237,
OP_RETURN_238,
OP_RETURN_239,
OP_RETURN_240,
OP_RETURN_241,
OP_RETURN_242,
OP_RETURN_243,
OP_RETURN_244,
OP_RETURN_245,
OP_RETURN_246,
OP_RETURN_247,
OP_RETURN_248,
OP_RETURN_249,
OP_RETURN_250,
OP_RETURN_251,
OP_RETURN_252,
OP_RETURN_253,
OP_RETURN_254,
OP_INVALIDOPCODE,
}
}