use blvm_consensus::types::{OutPoint, UtxoSet};
use blvm_consensus::{Block, BlockHeader, Transaction, TransactionInput, TransactionOutput};
use blvm_protocol::validation::{ProtocolValidationContext, ProtocolValidationRules};
use blvm_protocol::{BitcoinProtocolEngine, ProtocolVersion};
fn create_simple_transaction() -> Transaction {
Transaction {
version: 1,
inputs: blvm_consensus::tx_inputs![TransactionInput {
prevout: OutPoint {
hash: [0u8; 32],
index: 0xffffffff,
},
script_sig: vec![blvm_consensus::opcodes::OP_1],
sequence: 0xffffffff,
}],
outputs: blvm_consensus::tx_outputs![TransactionOutput {
value: 1000,
script_pubkey: vec![blvm_consensus::opcodes::OP_1],
}],
lock_time: 0,
}
}
#[test]
fn test_validation_rules_for_protocol() {
let mainnet_rules = ProtocolValidationRules::for_protocol(ProtocolVersion::BitcoinV1);
let testnet_rules = ProtocolValidationRules::for_protocol(ProtocolVersion::Testnet3);
let regtest_rules = ProtocolValidationRules::for_protocol(ProtocolVersion::Regtest);
assert_eq!(mainnet_rules.max_block_size, 4_000_000);
assert_eq!(testnet_rules.max_block_size, 4_000_000);
assert_eq!(regtest_rules.max_block_size, 4_000_000);
}
#[test]
fn test_validation_rules_mainnet() {
let rules = ProtocolValidationRules::mainnet();
assert_eq!(rules.max_block_size, 4_000_000);
assert_eq!(rules.max_tx_size, 1_000_000);
assert_eq!(rules.max_script_size, 10_000);
assert!(rules.segwit_enabled);
assert!(rules.taproot_enabled);
assert!(rules.rbf_enabled);
assert_eq!(rules.min_fee_rate, 1);
assert_eq!(rules.max_fee_rate, 1_000_000);
}
#[test]
fn test_validation_rules_testnet() {
let rules = ProtocolValidationRules::testnet();
assert_eq!(rules.max_block_size, 4_000_000);
assert_eq!(rules.max_tx_size, 1_000_000);
assert!(rules.segwit_enabled);
assert!(rules.taproot_enabled);
}
#[test]
fn test_validation_rules_regtest() {
let rules = ProtocolValidationRules::regtest();
assert_eq!(rules.max_block_size, 4_000_000);
assert_eq!(rules.max_tx_size, 1_000_000);
assert_eq!(rules.min_fee_rate, 0); }
#[test]
fn test_validation_context_creation() {
let context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 100000).unwrap();
assert_eq!(context.block_height, 100000);
assert_eq!(context.validation_rules.max_block_size, 4_000_000);
}
#[test]
fn test_validation_context_feature_check() {
let context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 1000000).unwrap();
assert!(context.is_feature_enabled("segwit"));
assert!(context.is_feature_enabled("taproot"));
assert!(context.is_feature_enabled("rbf"));
assert!(!context.is_feature_enabled("nonexistent"));
}
#[test]
fn test_validation_context_max_sizes() {
let context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 100000).unwrap();
assert_eq!(context.get_max_size("block"), 4_000_000);
assert_eq!(context.get_max_size("transaction"), 1_000_000);
assert_eq!(context.get_max_size("script"), 10_000);
assert_eq!(context.get_max_size("nonexistent"), 0);
}
#[test]
fn test_block_size_validation() {
let _engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
let _context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 0).unwrap();
let block = Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0u8; 32],
merkle_root: [0u8; 32],
timestamp: 1231006505,
bits: 0x1d00ffff,
nonce: 0,
},
transactions: vec![create_simple_transaction()].into_boxed_slice(),
};
assert!(!block.transactions.is_empty());
assert!(block.transactions.len() < 10000); }
#[test]
fn test_transaction_size_validation() {
let _engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
let _context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 0).unwrap();
let tx = create_simple_transaction();
assert!(!tx.inputs.is_empty());
assert!(!tx.outputs.is_empty());
}
#[test]
fn test_script_size_validation() {
let context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 0).unwrap();
let tx = create_simple_transaction();
for input in &tx.inputs {
assert!(input.script_sig.len() <= context.validation_rules.max_script_size as usize);
}
for output in &tx.outputs {
assert!(output.script_pubkey.len() <= context.validation_rules.max_script_size as usize);
}
}
#[test]
fn test_validate_block_with_protocol() {
let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
let context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 0).unwrap();
let utxos = UtxoSet::default();
let block = Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0u8; 32],
merkle_root: [0u8; 32],
timestamp: 1231006505,
bits: 0x1d00ffff,
nonce: 0,
},
transactions: vec![create_simple_transaction()].into_boxed_slice(),
};
let result = engine.validate_block_with_protocol(&block, &utxos, 0, &context);
let _ = result;
}
#[test]
fn test_validate_transaction_with_protocol() {
let engine = BitcoinProtocolEngine::new(ProtocolVersion::BitcoinV1).unwrap();
let context = ProtocolValidationContext::new(ProtocolVersion::BitcoinV1, 0).unwrap();
let tx = create_simple_transaction();
let result = engine.validate_transaction_with_protocol(&tx, &context);
let _ = result;
}
#[test]
fn test_fee_rate_limits() {
let mainnet_rules = ProtocolValidationRules::mainnet();
let regtest_rules = ProtocolValidationRules::regtest();
assert_eq!(mainnet_rules.min_fee_rate, 1);
assert_eq!(regtest_rules.min_fee_rate, 0);
assert_eq!(mainnet_rules.max_fee_rate, 1_000_000);
assert_eq!(regtest_rules.max_fee_rate, 1_000_000);
}
#[test]
fn test_feature_flags_mainnet() {
let rules = ProtocolValidationRules::mainnet();
assert!(rules.segwit_enabled);
assert!(rules.taproot_enabled);
assert!(rules.rbf_enabled);
}
#[test]
fn test_feature_flags_all_networks() {
let mainnet = ProtocolValidationRules::mainnet();
let testnet = ProtocolValidationRules::testnet();
let regtest = ProtocolValidationRules::regtest();
assert_eq!(mainnet.segwit_enabled, testnet.segwit_enabled);
assert_eq!(testnet.segwit_enabled, regtest.segwit_enabled);
assert_eq!(mainnet.taproot_enabled, testnet.taproot_enabled);
assert_eq!(testnet.taproot_enabled, regtest.taproot_enabled);
}