Newer
Older
},
Opcode::OP_CODESEPARATOR => {
begincode = pc;
},
Opcode::OP_CHECKSIG | Opcode::OP_CHECKSIGVERIFY => {
let pubkey = stack.pop()?;
let signature = stack.pop()?;
let sighash = parse_hash_type(version, &signature);
let mut subscript = script.subscript(begincode);
match version {
SignatureVersion::ForkId if sighash.fork_id => (),
SignatureVersion::WitnessV0 => (),
SignatureVersion::Base | SignatureVersion::ForkId => {
let signature_script = Builder::default().push_data(&*signature).into_script();
subscript = subscript.find_and_delete(&*signature_script);
},
check_signature_encoding(&signature, flags, version)?;
check_pubkey_encoding(&pubkey, flags)?;
let success = check_signature(checker, signature.into(), pubkey.into(), &subscript, version);
if success {
stack.push(vec![1].into());
} else {
stack.push(vec![0].into());
}
},
Opcode::OP_CHECKSIGVERIFY if !success => {
return Err(Error::CheckSigVerify);
},
_ => {},
}
Opcode::OP_CHECKMULTISIG | Opcode::OP_CHECKMULTISIGVERIFY => {
let keys_count = Num::from_slice(&stack.pop()?, flags.verify_minimaldata, 4)?;
if keys_count < 0.into() || keys_count > script::MAX_PUBKEYS_PER_MULTISIG.into() {
return Err(Error::PubkeyCount);
}
let keys_count: usize = keys_count.into();
let keys = (0..keys_count).into_iter().map(|_| stack.pop()).collect::<Result<Vec<_>, _>>()?;
let sigs_count = Num::from_slice(&stack.pop()?, flags.verify_minimaldata, 4)?;
if sigs_count < 0.into() || sigs_count > keys_count.into() {
return Err(Error::SigCount);
}
let sigs_count: usize = sigs_count.into();
let sigs = (0..sigs_count).into_iter().map(|_| stack.pop()).collect::<Result<Vec<_>, _>>()?;
let mut subscript = script.subscript(begincode);
for signature in &sigs {
let sighash = parse_hash_type(version, &signature);
match version {
SignatureVersion::ForkId if sighash.fork_id => (),
SignatureVersion::WitnessV0 => (),
SignatureVersion::Base | SignatureVersion::ForkId => {
let signature_script = Builder::default().push_data(&*signature).into_script();
subscript = subscript.find_and_delete(&*signature_script);
},
}
}
let mut success = true;
let mut k = 0;
let mut s = 0;
while s < sigs.len() && success {
// TODO: remove redundant copying
let key = keys[k].clone();
let sig = sigs[s].clone();
check_signature_encoding(&sig, flags, version)?;
check_pubkey_encoding(&key, flags)?;
let ok = check_signature(checker, sig.into(), key.into(), &subscript, version);
if ok {
s += 1;
}
k += 1;
success = sigs.len() - s <= keys.len() - k;
}
if !stack.pop()?.is_empty() && flags.verify_nulldummy {
return Err(Error::SignatureNullDummy);
}
match opcode {
Opcode::OP_CHECKMULTISIG => {
if success {
stack.push(vec![1].into());
} else {
stack.push(vec![0].into());
}
},
Opcode::OP_CHECKMULTISIGVERIFY if !success => {
return Err(Error::CheckSigVerify);
},
_ => {},
}
},
Opcode::OP_RESERVED |
Opcode::OP_VER |
Opcode::OP_RESERVED1 |
Opcode::OP_RESERVED2 => {
if executing {
return Err(Error::DisabledOpcode(opcode));
}
},
Opcode::OP_VERNOTIF => {
return Err(Error::DisabledOpcode(opcode));
},
if stack.len() + altstack.len() > 1000 {
return Err(Error::StackSize);
}
if !exec_stack.is_empty() {
return Err(Error::UnbalancedConditional);
}
Opcode, Script, ScriptWitness, VerificationFlags, Builder, Error, Num, TransactionInputSigner,
use super::{eval_script, verify_script, is_public_key};
#[test]
fn tests_is_public_key() {
assert!(!is_public_key(&[]));
assert!(!is_public_key(&[1]));
assert!(is_public_key(&Bytes::from("0495dfb90f202c7d016ef42c65bc010cd26bb8237b06253cc4d12175097bef767ed6b1fcb3caf1ed57c98d92e6cb70278721b952e29a335134857acd4c199b9d2f")));
assert!(is_public_key(&[2; 33]));
assert!(is_public_key(&[3; 33]));
assert!(!is_public_key(&[4; 33]));
}
// https://github.com/bitcoin/bitcoin/blob/d612837814020ae832499d18e6ee5eb919a87907/src/test/script_tests.cpp#L900
#[test]
fn test_push_data() {
let expected: Stack<Bytes> = vec![vec![0x5a].into()].into();
let flags = VerificationFlags::default()
.verify_p2sh(true);
let checker = NoopSignatureChecker;
let version = SignatureVersion::Base;
let direct: Script = vec![Opcode::OP_PUSHBYTES_1 as u8, 0x5a].into();
let pushdata1: Script = vec![Opcode::OP_PUSHDATA1 as u8, 0x1, 0x5a].into();
let pushdata2: Script = vec![Opcode::OP_PUSHDATA2 as u8, 0x1, 0, 0x5a].into();
let pushdata4: Script = vec![Opcode::OP_PUSHDATA4 as u8, 0x1, 0, 0, 0, 0x5a].into();
let mut direct_stack = Stack::new();
let mut pushdata1_stack = Stack::new();
let mut pushdata2_stack = Stack::new();
let mut pushdata4_stack = Stack::new();
assert!(eval_script(&mut direct_stack, &direct, &flags, &checker, version).unwrap());
assert!(eval_script(&mut pushdata1_stack, &pushdata1, &flags, &checker, version).unwrap());
assert!(eval_script(&mut pushdata2_stack, &pushdata2, &flags, &checker, version).unwrap());
assert!(eval_script(&mut pushdata4_stack, &pushdata4, &flags, &checker, version).unwrap());
assert_eq!(direct_stack, expected);
assert_eq!(pushdata1_stack, expected);
assert_eq!(pushdata2_stack, expected);
assert_eq!(pushdata4_stack, expected);
fn basic_test_with_flags(script: &Script, flags: &VerificationFlags, expected: Result<bool, Error>, expected_stack: Stack<Bytes>) {
let checker = NoopSignatureChecker;
let version = SignatureVersion::Base;
assert_eq!(eval_script(&mut stack, script, &flags, &checker, version), expected);
if expected.is_ok() {
fn basic_test(script: &Script, expected: Result<bool, Error>, expected_stack: Stack<Bytes>) {
let flags = VerificationFlags::default()
.verify_p2sh(true);
basic_test_with_flags(script, &flags, expected, expected_stack)
}
#[test]
fn test_equal() {
let script = Builder::default()
.push_data(&[0x4])
.push_data(&[0x4])
.push_opcode(Opcode::OP_EQUAL)
.into_script();
let result = Ok(true);
basic_test(&script, result, stack);
}
#[test]
fn test_equal_false() {
let script = Builder::default()
.push_data(&[0x4])
.push_data(&[0x3])
.push_opcode(Opcode::OP_EQUAL)
.into_script();
let result = Ok(false);
basic_test(&script, result, stack);
}
#[test]
fn test_equal_invalid_stack() {
let script = Builder::default()
.push_data(&[0x4])
.push_opcode(Opcode::OP_EQUAL)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_equal_verify() {
let script = Builder::default()
.push_data(&[0x4])
.push_data(&[0x4])
.push_opcode(Opcode::OP_EQUALVERIFY)
.into_script();
let result = Ok(false);
basic_test(&script, result, stack);
}
#[test]
fn test_equal_verify_failed() {
let script = Builder::default()
.push_data(&[0x4])
.push_data(&[0x3])
.push_opcode(Opcode::OP_EQUALVERIFY)
.into_script();
let result = Err(Error::EqualVerify);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_equal_verify_invalid_stack() {
let script = Builder::default()
.push_data(&[0x4])
.push_opcode(Opcode::OP_EQUALVERIFY)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_size() {
let script = Builder::default()
.push_data(&[0x12, 0x34])
.push_opcode(Opcode::OP_SIZE)
.into_script();
let result = Ok(true);
let stack = vec![vec![0x12, 0x34].into(), vec![0x2].into()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_size_false() {
let script = Builder::default()
.push_data(&[])
.push_opcode(Opcode::OP_SIZE)
.into_script();
let result = Ok(false);
let stack = vec![vec![].into(), vec![].into()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_size_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_SIZE)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
#[test]
fn test_hash256() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_HASH256)
.into_script();
let result = Ok(true);
let stack = vec!["9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50".into()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_hash256_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_HASH256)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_ripemd160() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_RIPEMD160)
.into_script();
let result = Ok(true);
let stack = vec!["108f07b8382412612c048d07d13f814118445acd".into()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_ripemd160_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_RIPEMD160)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_sha1() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_SHA1)
.into_script();
let result = Ok(true);
let stack = vec!["aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d".into()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_sha1_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_SHA1)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_sha256() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_SHA256)
.into_script();
let result = Ok(true);
let stack = vec!["2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824".into()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_sha256_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_SHA256)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
#[test]
fn test_1add() {
let script = Builder::default()
.push_num(5.into())
.push_opcode(Opcode::OP_1ADD)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(6).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_1add_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_1ADD)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_1sub() {
let script = Builder::default()
.push_num(5.into())
.push_opcode(Opcode::OP_1SUB)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(4).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_1sub_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_1SUB)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_negate() {
let script = Builder::default()
.push_num(5.into())
.push_opcode(Opcode::OP_NEGATE)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(-5).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_negate_negative() {
let script = Builder::default()
.push_num((-5).into())
.push_opcode(Opcode::OP_NEGATE)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(5).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_negate_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_NEGATE)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_abs() {
let script = Builder::default()
.push_num(5.into())
.push_opcode(Opcode::OP_ABS)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(5).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_abs_negative() {
let script = Builder::default()
.push_num((-5).into())
.push_opcode(Opcode::OP_ABS)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(5).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_abs_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_ABS)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_not() {
let script = Builder::default()
.push_num(4.into())
.push_opcode(Opcode::OP_NOT)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_not_zero() {
let script = Builder::default()
.push_num(0.into())
.push_opcode(Opcode::OP_NOT)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_not_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_NOT)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_0notequal() {
let script = Builder::default()
.push_num(4.into())
.push_opcode(Opcode::OP_0NOTEQUAL)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_0notequal_zero() {
let script = Builder::default()
.push_num(0.into())
.push_opcode(Opcode::OP_0NOTEQUAL)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_0notequal_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_0NOTEQUAL)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_add() {
let script = Builder::default()
.push_num(2.into())
.push_num(3.into())
.push_opcode(Opcode::OP_ADD)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(5).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_add_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_ADD)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_sub() {
let script = Builder::default()
.push_num(3.into())
.push_num(2.into())
.push_opcode(Opcode::OP_SUB)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_sub_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_SUB)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_booland() {
let script = Builder::default()
.push_num(3.into())
.push_num(2.into())
.push_opcode(Opcode::OP_BOOLAND)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_booland_first() {
let script = Builder::default()
.push_num(2.into())
.push_num(0.into())
.push_opcode(Opcode::OP_BOOLAND)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_booland_second() {
let script = Builder::default()
.push_num(0.into())
.push_num(3.into())
.push_opcode(Opcode::OP_BOOLAND)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_booland_none() {
let script = Builder::default()
.push_num(0.into())
.push_num(0.into())
.push_opcode(Opcode::OP_BOOLAND)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_booland_invalid_stack() {
let script = Builder::default()
.push_num(0.into())
.push_opcode(Opcode::OP_BOOLAND)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_boolor() {
let script = Builder::default()
.push_num(3.into())
.push_num(2.into())
.push_opcode(Opcode::OP_BOOLOR)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_boolor_first() {
let script = Builder::default()
.push_num(2.into())
.push_num(0.into())
.push_opcode(Opcode::OP_BOOLOR)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_boolor_second() {
let script = Builder::default()
.push_num(0.into())
.push_num(3.into())
.push_opcode(Opcode::OP_BOOLOR)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_boolor_none() {
let script = Builder::default()
.push_num(0.into())
.push_num(0.into())
.push_opcode(Opcode::OP_BOOLOR)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_boolor_invalid_stack() {
let script = Builder::default()
.push_num(0.into())
.push_opcode(Opcode::OP_BOOLOR)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_numequal() {
let script = Builder::default()
.push_num(2.into())
.push_num(2.into())
.push_opcode(Opcode::OP_NUMEQUAL)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_numequal_not() {
let script = Builder::default()
.push_num(2.into())
.push_num(3.into())
.push_opcode(Opcode::OP_NUMEQUAL)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_numequal_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_NUMEQUAL)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_numequalverify() {
let script = Builder::default()
.push_num(2.into())
.push_num(2.into())
.push_opcode(Opcode::OP_NUMEQUALVERIFY)
.into_script();
let result = Ok(false);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_numequalverify_failed() {
let script = Builder::default()
.push_num(2.into())
.push_num(3.into())
.push_opcode(Opcode::OP_NUMEQUALVERIFY)
.into_script();
let result = Err(Error::NumEqualVerify);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_numequalverify_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_NUMEQUALVERIFY)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
#[test]
fn test_numnotequal() {
let script = Builder::default()
.push_num(2.into())
.push_num(3.into())
.push_opcode(Opcode::OP_NUMNOTEQUAL)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_numnotequal_not() {
let script = Builder::default()
.push_num(2.into())
.push_num(2.into())
.push_opcode(Opcode::OP_NUMNOTEQUAL)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_numnotequal_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_NUMNOTEQUAL)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_lessthan() {
let script = Builder::default()
.push_num(2.into())
.push_num(3.into())
.push_opcode(Opcode::OP_LESSTHAN)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_lessthan_not() {
let script = Builder::default()
.push_num(2.into())
.push_num(2.into())
.push_opcode(Opcode::OP_LESSTHAN)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_lessthan_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_LESSTHAN)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_greaterthan() {
let script = Builder::default()
.push_num(3.into())
.push_num(2.into())
.push_opcode(Opcode::OP_GREATERTHAN)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_greaterthan_not() {
let script = Builder::default()
.push_num(2.into())
.push_num(2.into())
.push_opcode(Opcode::OP_GREATERTHAN)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_greaterthan_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_GREATERTHAN)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_lessthanorequal() {
let script = Builder::default()
.push_num(2.into())
.push_num(3.into())
.push_opcode(Opcode::OP_LESSTHANOREQUAL)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_lessthanorequal_equal() {
let script = Builder::default()
.push_num(2.into())
.push_num(2.into())
.push_opcode(Opcode::OP_LESSTHANOREQUAL)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_lessthanorequal_not() {
let script = Builder::default()
.push_num(2.into())
.push_num(1.into())
.push_opcode(Opcode::OP_LESSTHANOREQUAL)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_lessthanorequal_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_LESSTHANOREQUAL)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_greaterthanorequal() {
let script = Builder::default()
.push_num(3.into())
.push_num(2.into())
.push_opcode(Opcode::OP_GREATERTHANOREQUAL)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_greaterthanorequal_equal() {
let script = Builder::default()
.push_num(2.into())
.push_num(2.into())
.push_opcode(Opcode::OP_GREATERTHANOREQUAL)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(1).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_greaterthanorequal_not() {
let script = Builder::default()
.push_num(1.into())
.push_num(2.into())
.push_opcode(Opcode::OP_GREATERTHANOREQUAL)
.into_script();
let result = Ok(false);
let stack = vec![Num::from(0).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_greaterthanorequal_invalid_stack() {
let script = Builder::default()
.push_num(2.into())
.push_opcode(Opcode::OP_GREATERTHANOREQUAL)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());
}
#[test]
fn test_min() {
let script = Builder::default()
.push_num(2.into())
.push_num(3.into())
.push_opcode(Opcode::OP_MIN)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(2).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_min_second() {
let script = Builder::default()
.push_num(4.into())
.push_num(3.into())
.push_opcode(Opcode::OP_MIN)
.into_script();
let result = Ok(true);
let stack = vec![Num::from(3).to_bytes()].into();
basic_test(&script, result, stack);
}
#[test]
fn test_min_invalid_stack() {
let script = Builder::default()
.push_num(4.into())
.push_opcode(Opcode::OP_MIN)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, Stack::default());