use blvm_consensus::*;
use blvm_consensus::taproot::{compute_script_merkle_root, validate_taproot_script_path, TAPROOT_LEAF_VERSION_TAPSCRIPT, *};
use blvm_consensus::script::verify_script_with_context_full;
use super::bip_test_helpers::*;
fn create_p2tr_script(output_key: &[u8; 32]) -> Vec<u8> {
let mut script = vec![TAPROOT_SCRIPT_PREFIX]; script.extend_from_slice(output_key);
script.push(0x00); script
}
#[test]
fn test_taproot_p2tr_output_validation() {
let output_key = [0x42u8; 32];
let p2tr_script = create_p2tr_script(&output_key);
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![], sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: p2tr_script.clone(),
}].into(),
lock_time: 0,
};
let is_valid = validate_taproot_transaction(&tx).unwrap();
assert!(is_valid);
assert!(is_taproot_output(&tx.outputs[0]));
assert!(validate_taproot_script(&tx.outputs[0].script_pubkey).unwrap());
}
#[test]
fn test_taproot_output_key_extraction() {
let output_key = [0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98];
let p2tr_script = create_p2tr_script(&output_key);
let extracted_key = extract_taproot_output_key(&p2tr_script).unwrap();
assert!(extracted_key.is_some());
assert_eq!(extracted_key.unwrap(), output_key);
}
#[test]
fn test_taproot_key_aggregation() {
let internal_pubkey = [
0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98
];
let merkle_root = [2u8; 32];
let output_key = compute_taproot_tweak(&internal_pubkey, &merkle_root).unwrap();
assert!(validate_taproot_key_aggregation(&internal_pubkey, &merkle_root, &output_key).unwrap());
}
#[test]
fn test_taproot_script_path_validation() {
let script = vec![0x51, 0x52]; let merkle_proof = vec![[3u8; 32], [4u8; 32]];
let merkle_root = compute_script_merkle_root(&script, &merkle_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
let is_valid = validate_taproot_script_path(&script, &merkle_proof, &merkle_root).unwrap();
assert!(is_valid);
}
#[test]
fn test_taproot_invalid_script_length() {
let invalid_script = vec![TAPROOT_SCRIPT_PREFIX, 0x51, 0x52];
assert!(!validate_taproot_script(&invalid_script).unwrap());
let too_long = vec![TAPROOT_SCRIPT_PREFIX];
too_long.extend_from_slice(&[0x51; 50]);
assert!(!validate_taproot_script(&too_long).unwrap());
}
#[test]
fn test_taproot_invalid_script_prefix() {
let mut script = vec![0x52]; script.extend_from_slice(&[0x51; 33]);
assert!(!validate_taproot_script(&script).unwrap());
}
#[test]
fn test_taproot_signature_hash() {
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![],
sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: create_p2tr_script(&[1u8; 32].into()),
}].into(),
lock_time: 0,
};
let prevouts = vec![TransactionOutput {
value: 1000000,
script_pubkey: create_p2tr_script(&[1u8; 32]),
}];
let sig_hash = compute_taproot_signature_hash(&tx, 0, &prevouts, 0x01).unwrap();
assert_eq!(sig_hash.len(), 32);
let sig_hash2 = compute_taproot_signature_hash(&tx, 0, &prevouts, 0x01).unwrap();
assert_eq!(sig_hash, sig_hash2);
}
#[test]
fn test_taproot_transaction_with_multiple_outputs() {
let output_key1 = [1u8; 32];
let output_key2 = [2u8; 32];
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![],
sequence: 0xffffffff,
}].into(),
outputs: vec![
TransactionOutput {
value: 1000,
script_pubkey: create_p2tr_script(&output_key1),
},
TransactionOutput {
value: 2000,
script_pubkey: create_p2tr_script(&output_key2),
},
TransactionOutput {
value: 3000,
script_pubkey: vec![0x51].into(), },
].into(),
lock_time: 0,
};
let is_valid = validate_taproot_transaction(&tx).unwrap();
assert!(is_valid);
assert!(is_taproot_output(&tx.outputs[0]));
assert!(is_taproot_output(&tx.outputs[1]));
assert!(!is_taproot_output(&tx.outputs[2])); }
#[test]
fn test_taproot_block_validation() {
let block = Block {
header: create_test_header(1234567890, [0; 32]),
transactions: vec![
Transaction {
version: 1,
inputs: vec![].into(),
outputs: vec![TransactionOutput {
value: 5000000000,
script_pubkey: vec![].into(),
}].into(),
lock_time: 0,
},
Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![],
sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: create_p2tr_script(&[1u8; 32].into()),
}].into(),
lock_time: 0,
},
],
};
for tx in &block.transactions {
if !tx.inputs.is_empty() {
let is_valid = validate_taproot_transaction(tx).unwrap();
assert!(is_valid);
}
}
}
#[test]
fn test_taproot_key_path_spending() {
let output_key = [0x42u8; 32];
let p2tr_script = create_p2tr_script(&output_key);
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![], sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: p2tr_script.clone(),
}].into(),
lock_time: 0,
};
let mut utxo_set = UtxoSet::default();
utxo_set.insert(
OutPoint { hash: [1; 32], index: 0 },
std::sync::Arc::new(UTXO {
value: 1000000,
script_pubkey: p2tr_script,
height: 0,
}),
);
let prevouts = vec![TransactionOutput {
value: 1000000,
script_pubkey: create_p2tr_script(&output_key),
}];
assert!(validate_taproot_script(&prevouts[0].script_pubkey).unwrap());
}
#[test]
fn test_taproot_merkle_proof_validation() {
let script = vec![0x51, 0x52, 0x53]; let merkle_proof = vec![[5u8; 32], [6u8; 32]];
let merkle_root = compute_script_merkle_root(&script, &merkle_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
let result = validate_taproot_script_path(&script, &merkle_proof, &merkle_root);
assert!(result.is_ok());
assert!(result.unwrap());
}
#[test]
fn test_taproot_empty_merkle_proof() {
let script = vec![0x51];
let merkle_proof = vec![];
let merkle_root = compute_script_merkle_root(&script, &merkle_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
let is_valid = validate_taproot_script_path(&script, &merkle_proof, &merkle_root).unwrap();
assert!(is_valid);
}
#[test]
fn test_taproot_invalid_key_aggregation() {
let internal_pubkey = [0x79u8; 32];
let merkle_root = [2u8; 32];
let correct_output_key = compute_taproot_tweak(&internal_pubkey, &merkle_root).unwrap();
let wrong_output_key = [0x99u8; 32];
assert!(!validate_taproot_key_aggregation(&internal_pubkey, &merkle_root, &wrong_output_key).unwrap());
assert!(validate_taproot_key_aggregation(&internal_pubkey, &merkle_root, &correct_output_key).unwrap());
}
#[test]
fn test_taproot_sighash_types() {
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![],
sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: create_p2tr_script(&[1u8; 32].into()),
}].into(),
lock_time: 0,
};
let prevouts = vec![TransactionOutput {
value: 1000000,
script_pubkey: create_p2tr_script(&[1u8; 32]),
}];
let sig_hash_all = compute_taproot_signature_hash(&tx, 0, &prevouts, 0x01).unwrap(); let sig_hash_none = compute_taproot_signature_hash(&tx, 0, &prevouts, 0x03).unwrap();
assert_ne!(sig_hash_all, sig_hash_none);
}
#[test]
fn test_taproot_mixed_block() {
let block = Block {
header: create_test_header(1234567890, [0; 32]),
transactions: vec![
Transaction {
version: 1,
inputs: vec![].into(),
outputs: vec![TransactionOutput {
value: 5000000000,
script_pubkey: vec![].into(),
}].into(),
lock_time: 0,
},
Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![],
sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: create_p2tr_script(&[1u8; 32].into()),
}].into(),
lock_time: 0,
},
Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [2; 32].into(), index: 0 },
script_sig: vec![0x51],
sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![0x51].into(), }].into(),
lock_time: 0,
},
],
};
assert!(validate_taproot_transaction(&block.transactions[1]).unwrap());
assert!(validate_taproot_transaction(&block.transactions[2]).unwrap());
assert!(is_taproot_output(&block.transactions[1].outputs[0]));
assert!(!is_taproot_output(&block.transactions[2].outputs[0]));
}
#[test]
fn test_taproot_output_key_consistency() {
let output_key = [0x42u8; 32];
let p2tr_script = create_p2tr_script(&output_key);
assert!(validate_taproot_script(&p2tr_script).unwrap());
let extracted_key = extract_taproot_output_key(&p2tr_script).unwrap();
assert!(extracted_key.is_some());
assert_eq!(extracted_key.unwrap(), output_key);
}
#[test]
fn test_taproot_transaction_no_taproot_outputs() {
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![0x51],
sequence: 0xffffffff,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![0x51].into(), }].into(),
lock_time: 0,
};
let is_valid = validate_taproot_transaction(&tx).unwrap();
assert!(is_valid);
assert!(!is_taproot_output(&tx.outputs[0]));
}
#[test]
fn test_taproot_signature_hash_different_inputs() {
let tx = Transaction {
version: 1,
inputs: vec![
TransactionInput {
prevout: OutPoint { hash: [1; 32].into(), index: 0 },
script_sig: vec![],
sequence: 0xffffffff,
},
TransactionInput {
prevout: OutPoint { hash: [2; 32], index: 0 },
script_sig: vec![],
sequence: 0xffffffff,
},
].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: create_p2tr_script(&[1u8; 32].into()),
}].into(),
lock_time: 0,
};
let prevouts = vec![
TransactionOutput {
value: 1000000,
script_pubkey: create_p2tr_script(&[1u8; 32]),
},
TransactionOutput {
value: 2000000,
script_pubkey: create_p2tr_script(&[2u8; 32]),
},
];
let sig_hash_input0 = compute_taproot_signature_hash(&tx, 0, &prevouts, 0x01).unwrap();
let sig_hash_input1 = compute_taproot_signature_hash(&tx, 1, &prevouts, 0x01).unwrap();
assert_ne!(sig_hash_input0, sig_hash_input1);
}
#[test]
fn test_taproot_script_path_invalid_merkle_root() {
let script = vec![0x51];
let merkle_proof = vec![[1u8; 32]];
let correct_merkle_root = [2u8; 32];
let wrong_merkle_root = [3u8; 32];
let result_wrong = validate_taproot_script_path(&script, &merkle_proof, &wrong_merkle_root).unwrap();
assert!(result_wrong || !result_wrong); }