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));
},
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
Opcode::OP_CHECKDATASIG | Opcode::OP_CHECKDATASIGVERIFY if flags.verify_checkdatasig => {
let pubkey = stack.pop()?;
let message = stack.pop()?;
let signature = stack.pop()?;
if message.len() != 32 {
return Err(Error::InvalidOperandSize);
}
let message = message[0..32].into();
check_signature_encoding(&signature, flags, version)?;
check_pubkey_encoding(&pubkey, flags)?;
let signature: Vec<u8> = signature.into();
let success = verify_signature(checker, signature.into(), pubkey.into(), message);
match opcode {
Opcode::OP_CHECKDATASIG => {
if success {
stack.push(vec![1].into());
} else {
stack.push(vec![0].into());
}
},
Opcode::OP_CHECKDATASIGVERIFY if !success => {
return Err(Error::CheckDataSigVerify);
},
_ => {},
}
},
Opcode::OP_CHECKDATASIG | Opcode::OP_CHECKDATASIGVERIFY => {
return Err(Error::DisabledOpcode(opcode));
},
if stack.len() + altstack.len() > 1000 {
return Err(Error::StackSize);
}
if !exec_stack.is_empty() {
return Err(Error::UnbalancedConditional);
}
use keys::{KeyPair, Private, Message, Network};
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())