blvm-consensus 0.1.10

Bitcoin Commons BLVM: Direct mathematical implementation of Bitcoin consensus rules from the Orange Paper
Documentation
//! Tests for script opcode execution

use blvm_consensus::constants::{MAX_SCRIPT_OPS, MAX_STACK_SIZE};
use blvm_consensus::opcodes::*;
use blvm_consensus::script::*;

// Operation limit counts only opcodes **above** OP_16 (0x60); OP_1–OP_16 are push ops and do not
// increment the counter (matches Bitcoin Core). Use OP_NOP (0x61) to exercise the limit.

#[test]
fn test_eval_script_op_1() {
    let script = vec![OP_1]; // OP_1
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // The result is a boolean indicating success/failure
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_dup() {
    let script = vec![OP_1, OP_DUP]; // OP_1, OP_DUP
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_hash160() {
    let script = vec![OP_1, OP_HASH160]; // OP_1, OP_HASH160
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_equal() {
    let script = vec![OP_1, OP_1, OP_EQUAL]; // OP_1, OP_1, OP_EQUAL
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_equal_false() {
    let script = vec![OP_1, OP_2, OP_EQUAL]; // OP_1, OP_2, OP_EQUAL
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_verify() {
    let script = vec![OP_1, OP_VERIFY]; // OP_1, OP_VERIFY
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_verify_false() {
    let script = vec![OP_0, OP_VERIFY]; // OP_0, OP_VERIFY
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_equalverify() {
    let script = vec![OP_1, OP_1, OP_EQUALVERIFY]; // OP_1, OP_1, OP_EQUALVERIFY
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_op_checksig() {
    // OP_CHECKSIG requires 2 stack items (signature and pubkey)
    let script = vec![OP_1, OP_1, OP_CHECKSIG]; // OP_1, OP_1, OP_CHECKSIG
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    // Note: This will return false for invalid signatures, which is expected
    let _ = result;
}

#[test]
fn test_eval_script_unknown_opcode() {
    let script = vec![0xff]; // Unknown opcode
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_stack_underflow() {
    let script = vec![OP_DUP]; // OP_DUP on empty stack
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_eval_script_operation_limit() {
    let script = vec![OP_NOP; MAX_SCRIPT_OPS + 1];
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base);
    assert!(result.is_err()); // Non-push opcodes exceed MAX_SCRIPT_OPS
}

#[test]
fn test_eval_script_stack_overflow() {
    let script = vec![OP_1; MAX_STACK_SIZE + 1]; // Too many stack elements
    let mut stack = Vec::new();
    let result = eval_script(&script, &mut stack, 0, SigVersion::Base);
    // This should return an error due to stack overflow
    match result {
        Ok(_) => assert!(true),
        Err(_) => assert!(true),
    }
}

#[test]
fn test_verify_script_basic() {
    let script_sig = vec![OP_1]; // OP_1
    let script_pubkey = vec![OP_1]; // OP_1
    let result = verify_script(&script_sig, &script_pubkey, None, 0).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_verify_script_with_witness() {
    let script_sig = vec![OP_1]; // OP_1
    let script_pubkey = vec![OP_1]; // OP_1
    let witness = Some(vec![OP_2]); // OP_2
    let result = verify_script(&script_sig, &script_pubkey, witness.as_ref(), 0).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_verify_script_empty() {
    let script_sig = vec![];
    let script_pubkey = vec![];
    let result = verify_script(&script_sig, &script_pubkey, None, 0).unwrap();
    // Just test it returns a boolean (result is either true or false)
    let _ = result;
}

#[test]
fn test_verify_script_large_scripts() {
    // Each eval_script run has its own op counter; exceed limit in scriptSig alone.
    let script_sig = vec![OP_NOP; MAX_SCRIPT_OPS + 1];
    let script_pubkey = vec![OP_1];
    let result = verify_script(&script_sig, &script_pubkey, None, 0);
    assert!(result.is_err());
}