use blvm_consensus::mempool::*;
use blvm_consensus::mining::*;
use blvm_consensus::opcodes::*;
use blvm_consensus::segwit::*;
use blvm_consensus::*;
#[test]
fn test_consensus_proof_new() {
let _consensus = ConsensusProof::new();
assert!(true); }
#[test]
fn test_consensus_proof_default() {
let _consensus = ConsensusProof;
assert!(true);
}
#[test]
fn test_validate_transaction() {
let consensus = ConsensusProof::new();
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![OP_1],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let result = consensus.validate_transaction(&tx).unwrap();
assert!(matches!(result, ValidationResult::Valid));
let invalid_tx = Transaction {
version: 1,
inputs: vec![].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let result = consensus.validate_transaction(&invalid_tx).unwrap();
assert!(matches!(result, ValidationResult::Invalid(_)));
}
#[test]
fn test_validate_tx_inputs() {
let consensus = ConsensusProof::new();
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![OP_1],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let mut utxo_set = UtxoSet::default();
let outpoint = OutPoint {
hash: [1; 32],
index: 0,
};
let utxo = UTXO {
value: 2000,
script_pubkey: vec![OP_1].into(),
height: 100,
is_coinbase: false,
};
utxo_set.insert(outpoint, std::sync::Arc::new(utxo));
let (result, total_value) = consensus.validate_tx_inputs(&tx, &utxo_set, 100).unwrap();
assert!(matches!(result, ValidationResult::Valid));
assert!(total_value >= 0); }
#[test]
fn test_validate_block() {
let consensus = ConsensusProof::new();
let coinbase_tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [0; 32].into(),
index: 0xffffffff,
},
script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 5000000000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let merkle_root = calculate_merkle_root(&[coinbase_tx.clone()]).unwrap();
let block = Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root,
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
},
transactions: vec![coinbase_tx].into_boxed_slice(),
};
let utxo_set = UtxoSet::default();
let witnesses: Vec<Vec<blvm_consensus::segwit::Witness>> = block
.transactions
.iter()
.map(|tx| tx.inputs.iter().map(|_| Vec::new()).collect())
.collect();
let time_context = None;
let network = blvm_consensus::types::Network::Mainnet;
let (result, new_utxo_set) = consensus
.validate_block_with_time_context(&block, &witnesses, utxo_set, 0, time_context, network)
.unwrap();
match result {
ValidationResult::Valid => {
assert!(!new_utxo_set.is_empty());
}
ValidationResult::Invalid(reason) => {
eprintln!("Block validation failed (expected in some cases): {reason}");
}
}
}
#[test]
fn test_verify_script() {
let consensus = ConsensusProof::new();
let script_sig = vec![OP_1]; let script_pubkey = vec![OP_1];
let result = consensus
.verify_script(&script_sig, &script_pubkey, None, 0)
.unwrap();
let _ = result;
let witness = Some(vec![OP_2]); let result = consensus
.verify_script(&script_sig, &script_pubkey, witness.as_ref(), 0)
.unwrap();
let _ = result;
}
#[test]
fn test_check_proof_of_work() {
let consensus = ConsensusProof::new();
let header = BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
};
let result = consensus.check_proof_of_work(&header).unwrap();
let _ = result;
let invalid_header = BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x1d00ffff, nonce: 0,
};
let result = consensus.check_proof_of_work(&invalid_header);
assert!(result.is_ok());
let is_valid = result.unwrap();
assert!(!is_valid);
}
#[test]
fn test_get_block_subsidy() {
let consensus = ConsensusProof::new();
use blvm_consensus::orange_paper_constants::{C, H};
let initial_subsidy = (50 * C) as i64;
let subsidy = consensus.get_block_subsidy(0);
assert_eq!(subsidy, initial_subsidy);
let subsidy = consensus.get_block_subsidy(H);
assert_eq!(subsidy, initial_subsidy / 2);
let subsidy = consensus.get_block_subsidy(H * 2);
assert_eq!(subsidy, initial_subsidy / 4);
let subsidy = consensus.get_block_subsidy(H * 64);
assert_eq!(subsidy, 0);
}
#[test]
fn test_total_supply() {
let consensus = ConsensusProof::new();
let supply = consensus.total_supply(0);
assert!(supply >= 0);
let supply = consensus.total_supply(1);
assert!(supply >= 0);
use blvm_consensus::orange_paper_constants::H;
let supply = consensus.total_supply(H);
assert!(supply > 0);
assert!(supply <= MAX_MONEY);
}
#[test]
fn test_get_next_work_required() {
let consensus = ConsensusProof::new();
let current_header = BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x1d00ffff,
nonce: 0,
};
let prev_headers = vec![];
let result = consensus.get_next_work_required(¤t_header, &prev_headers);
match result {
Ok(_) => assert!(true),
Err(_) => assert!(true),
}
let mut prev_headers = Vec::new();
for i in 0..2016 {
prev_headers.push(BlockHeader {
version: 1,
prev_block_hash: [i as u8; 32],
merkle_root: [0; 32],
timestamp: 1231006505 + (i * 600),
bits: 0x1d00ffff,
nonce: 0,
});
}
let result = consensus
.get_next_work_required(¤t_header, &prev_headers)
.unwrap();
assert!(result > 0); }
#[test]
fn test_accept_to_memory_pool() {
let consensus = ConsensusProof::new();
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![OP_1],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let utxo_set = UtxoSet::default();
let mempool = Mempool::new();
let time_context = None;
let result = consensus.accept_to_memory_pool(&tx, &utxo_set, &mempool, 100, time_context);
match result {
Ok(mempool_result) => {
assert!(matches!(
mempool_result,
MempoolResult::Accepted | MempoolResult::Rejected(_)
));
}
Err(_) => {
}
}
}
#[test]
fn test_is_standard_tx() {
let consensus = ConsensusProof::new();
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![OP_1],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let result = consensus.is_standard_tx(&tx).unwrap();
let _ = result;
}
#[test]
fn test_replacement_checks() {
let consensus = ConsensusProof::new();
let tx1 = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![OP_1],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let tx2 = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![OP_1],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 2000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let mut utxo_set = UtxoSet::default();
let outpoint = OutPoint {
hash: [1; 32],
index: 0,
};
let utxo = UTXO {
value: 10000, script_pubkey: vec![OP_1].into(),
height: 100,
is_coinbase: false,
};
utxo_set.insert(outpoint, std::sync::Arc::new(utxo));
let mempool = Mempool::new();
let result = consensus
.replacement_checks(&tx2, &tx1, &utxo_set, &mempool)
.unwrap();
let _ = result;
}
#[test]
fn test_create_new_block() {
let consensus = ConsensusProof::new();
let utxo_set = UtxoSet::default();
let mempool_txs = vec![];
let prev_header = BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
};
let prev_headers = vec![prev_header.clone(), prev_header.clone()];
let block = consensus
.create_new_block(
&utxo_set,
&mempool_txs,
0,
&prev_header,
&prev_headers,
&vec![OP_1],
&vec![OP_1],
)
.unwrap();
assert_eq!(block.transactions.len(), 1); assert!(block.transactions[0].inputs[0].prevout.index == 0xffffffff); }
#[test]
fn test_mine_block() {
let consensus = ConsensusProof::new();
let block = Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
},
transactions: vec![Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [0; 32].into(),
index: 0xffffffff,
},
script_sig: vec![OP_1],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 5000000000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
}]
.into_boxed_slice(),
};
let (_mined_block, result) = consensus.mine_block(block, 1000).unwrap();
assert!(matches!(
result,
MiningResult::Success | MiningResult::Failure
));
}
#[test]
fn test_create_block_template() {
let consensus = ConsensusProof::new();
let utxo_set = UtxoSet::default();
let mempool_txs = vec![];
let prev_header = BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
};
let prev_headers = vec![prev_header.clone()];
let template = consensus.create_block_template(
&utxo_set,
&mempool_txs,
0,
&prev_header,
&prev_headers,
&vec![OP_1],
&vec![OP_1],
);
match template {
Ok(template) => {
assert_eq!(template.coinbase_tx.outputs[0].value, 5000000000);
assert_eq!(template.transactions.len(), 1); }
Err(_) => {
}
}
}
#[test]
fn test_reorganize_chain() {
let consensus = ConsensusProof::new();
let coinbase_tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [0; 32].into(),
index: 0xffffffff,
},
script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 5000000000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let merkle_root = calculate_merkle_root(&[coinbase_tx.clone()]).unwrap();
let new_chain = vec![Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root,
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
},
transactions: vec![coinbase_tx.clone()].into_boxed_slice(),
}];
let current_chain = vec![Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root,
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
},
transactions: vec![coinbase_tx].into_boxed_slice(),
}];
let utxo_set = UtxoSet::default();
let result = consensus.reorganize_chain(
&new_chain,
¤t_chain,
utxo_set,
1,
blvm_consensus::types::Network::Regtest,
);
match result {
Ok(_reorg_result) => {
}
Err(_) => {
}
}
}
#[test]
fn test_should_reorganize() {
let consensus = ConsensusProof::new();
let coinbase_tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [0; 32].into(),
index: 0xffffffff,
},
script_sig: vec![0x01, 0x00], sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 5000000000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let merkle_root = calculate_merkle_root(&[coinbase_tx.clone()]).unwrap();
let new_chain = vec![Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root,
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
},
transactions: vec![coinbase_tx.clone()].into_boxed_slice(),
}];
let current_chain = vec![Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root,
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
},
transactions: vec![coinbase_tx].into_boxed_slice(),
}];
let result = consensus
.should_reorganize(&new_chain, ¤t_chain)
.unwrap();
let _ = result;
}
#[test]
fn test_calculate_transaction_weight() {
let consensus = ConsensusProof::new();
let tx = Transaction {
version: 2,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
}]
.into(),
lock_time: 0,
};
let witness = Some(Witness::new());
let weight = consensus
.calculate_transaction_weight(&tx, witness.as_ref())
.unwrap();
assert!(weight > 0);
}
#[test]
fn test_validate_segwit_block() {
let consensus = ConsensusProof::new();
let block = Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x0300ffff,
nonce: 0,
},
transactions: vec![Transaction {
version: 2,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [0; 32].into(),
index: 0xffffffff,
},
script_sig: vec![],
sequence: 0xffffffff,
}]
.into(),
outputs: vec![TransactionOutput {
value: 5000000000,
script_pubkey: vec![
0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
.into(),
}]
.into(),
lock_time: 0,
}]
.into_boxed_slice(),
};
let witnesses = vec![Witness::new()];
let result = consensus
.validate_segwit_block(&block, &witnesses, 4000000)
.unwrap();
let _ = result;
}
#[test]
fn test_validate_taproot_transaction() {
let consensus = ConsensusProof::new();
let tx = Transaction {
version: 1,
inputs: vec![].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![
0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
.into(),
}]
.into(),
lock_time: 0,
};
let result = consensus.validate_taproot_transaction(&tx, None).unwrap();
let _ = result;
}
#[test]
fn test_is_taproot_output() {
let consensus = ConsensusProof::new();
let taproot_output = TransactionOutput {
value: 1000,
script_pubkey: vec![
0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
.into(),
};
let result = consensus.is_taproot_output(&taproot_output);
let _ = result;
let non_taproot_output = TransactionOutput {
value: 1000,
script_pubkey: vec![OP_1].into(),
};
let result = consensus.is_taproot_output(&non_taproot_output);
let _ = result;
}