use blvm_consensus::*;
use blvm_consensus::serialization::varint::{encode_varint, decode_varint};
use blvm_consensus::serialization::{serialize_transaction, deserialize_transaction, serialize_block_header, deserialize_block_header};
#[test]
fn test_varint_maximum_value() {
let max_value = u64::MAX;
let encoded = encode_varint(max_value);
let (decoded, bytes_consumed) = decode_varint(&encoded).unwrap();
assert_eq!(decoded, max_value);
assert_eq!(bytes_consumed, 9); }
#[test]
fn test_varint_boundary_values() {
let test_cases = vec![
(0xfc, 1), (0xfd, 3), (0xffff, 3), (0x10000, 5), (0xffffffff, 5), (0x100000000, 9), ];
for (value, expected_bytes) in test_cases {
let encoded = encode_varint(value);
assert_eq!(encoded.len(), expected_bytes, "Wrong encoding length for value {}", value);
let (decoded, bytes_consumed) = decode_varint(&encoded).unwrap();
assert_eq!(decoded, value);
assert_eq!(bytes_consumed, expected_bytes);
}
}
#[test]
fn test_varint_invalid_encoding_rejected() {
assert!(decode_varint(&[0xfd, 252, 0]).is_err());
assert!(decode_varint(&[0xfe, 255, 255, 0, 0]).is_err());
assert!(decode_varint(&[0xff, 255, 255, 255, 255, 0, 0, 0, 0]).is_err());
}
#[test]
fn test_varint_truncated_data() {
assert!(decode_varint(&[]).is_err());
assert!(decode_varint(&[0xfd]).is_err());
assert!(decode_varint(&[0xfd, 0]).is_err());
assert!(decode_varint(&[0xfe]).is_err());
assert!(decode_varint(&[0xfe, 0, 0, 0]).is_err());
assert!(decode_varint(&[0xff]).is_err());
assert!(decode_varint(&[0xff, 0, 0, 0, 0, 0, 0, 0]).is_err());
}
#[test]
fn test_transaction_serialization_round_trip() {
let tx = Transaction {
version: 1,
inputs: vec![
TransactionInput {
prevout: OutPoint {
hash: [1; 32].into(),
index: 0,
},
script_sig: vec![0x51], sequence: 0xffffffff,
},
TransactionInput {
prevout: OutPoint {
hash: [2; 32],
index: 1,
},
script_sig: vec![0x51, 0x52], sequence: 0xfffffffe,
},
].into(),
outputs: vec![
TransactionOutput {
value: 5000000000,
script_pubkey: vec![0x51].into(), },
TransactionOutput {
value: 2500000000,
script_pubkey: vec![0x51, 0x52], },
].into(),
lock_time: 0,
};
let serialized = serialize_transaction(&tx);
let deserialized = deserialize_transaction(&serialized).unwrap();
assert_eq!(deserialized.version, tx.version);
assert_eq!(deserialized.inputs.len(), tx.inputs.len());
assert_eq!(deserialized.outputs.len(), tx.outputs.len());
assert_eq!(deserialized.lock_time, tx.lock_time);
}
#[test]
fn test_transaction_serialization_empty_scripts() {
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [0; 32].into(),
index: 0,
},
script_sig: vec![],
sequence: 0,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![].into(),
}].into(),
lock_time: 0,
};
let serialized = serialize_transaction(&tx);
let deserialized = deserialize_transaction(&serialized).unwrap();
assert_eq!(deserialized.inputs[0].script_sig, vec![]);
assert_eq!(deserialized.outputs[0].script_pubkey, vec![]);
}
#[test]
fn test_transaction_serialization_large_scripts() {
let large_script = vec![0x51; 10000];
let tx = Transaction {
version: 1,
inputs: vec![TransactionInput {
prevout: OutPoint {
hash: [0; 32].into(),
index: 0,
},
script_sig: large_script.clone(),
sequence: 0,
}].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: large_script.clone(),
}].into(),
lock_time: 0,
};
let serialized = serialize_transaction(&tx);
let deserialized = deserialize_transaction(&serialized).unwrap();
assert_eq!(deserialized.inputs[0].script_sig, large_script);
assert_eq!(deserialized.outputs[0].script_pubkey, large_script);
}
#[test]
fn test_transaction_deserialize_insufficient_bytes() {
assert!(deserialize_transaction(&[]).is_err());
assert!(deserialize_transaction(&[0, 0, 0, 0]).is_err());
assert!(deserialize_transaction(&[0, 0, 0, 0, 0xfd]).is_err());
}
#[test]
fn test_block_header_serialization_size() {
let header = BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 1231006505,
bits: 0x1d00ffff,
nonce: 0,
};
let serialized = serialize_block_header(&header);
assert_eq!(serialized.len(), 80, "Block header must be exactly 80 bytes");
}
#[test]
fn test_block_header_serialization_round_trip() {
let header = BlockHeader {
version: 1,
prev_block_hash: [1; 32],
merkle_root: [2; 32],
timestamp: 1231006505,
bits: 0x1d00ffff,
nonce: 12345,
};
let serialized = serialize_block_header(&header);
let deserialized = deserialize_block_header(&serialized).unwrap();
assert_eq!(deserialized.version, header.version);
assert_eq!(deserialized.prev_block_hash, header.prev_block_hash);
assert_eq!(deserialized.merkle_root, header.merkle_root);
assert_eq!(deserialized.timestamp, header.timestamp);
assert_eq!(deserialized.bits, header.bits);
assert_eq!(deserialized.nonce, header.nonce);
}
#[test]
fn test_block_header_deserialize_insufficient_bytes() {
assert!(deserialize_block_header(&[]).is_err());
assert!(deserialize_block_header(&[0; 40]).is_err());
assert!(deserialize_block_header(&[0; 79]).is_err());
}
#[test]
fn test_transaction_negative_version() {
let tx = Transaction {
version: 0xffffffff, inputs: vec![].into(),
outputs: vec![TransactionOutput {
value: 1000,
script_pubkey: vec![0x51].into(),
}].into(),
lock_time: 0,
};
let serialized = serialize_transaction(&tx);
let deserialized = deserialize_transaction(&serialized).unwrap();
assert_eq!(deserialized.version, tx.version);
}