use blvm_node::storage::*;
use blvm_protocol::*;
use tempfile::TempDir;
mod common;
use common::*;
#[test]
fn test_block_store_atomicity() {
let temp_dir = TempDir::new().unwrap();
let storage = Storage::new(temp_dir.path()).unwrap();
let blockstore = storage.blocks();
let block = TestBlockBuilder::new()
.add_coinbase_transaction(p2pkh_script(random_hash20()))
.build();
let result = blockstore.store_block(&block);
assert!(result.is_ok());
let block_hash = blockstore.get_block_hash(&block);
let retrieved = blockstore.get_block(&block_hash).unwrap();
assert_eq!(retrieved.unwrap().header.version, block.header.version);
}
#[test]
fn test_utxo_store_consistency() {
let temp_dir = TempDir::new().unwrap();
let storage = Storage::new(temp_dir.path()).unwrap();
let utxostore = storage.utxos();
let outpoint = OutPoint {
hash: random_hash(),
index: 0,
};
let utxo = UTXO {
value: 1000000,
script_pubkey: p2pkh_script(random_hash20()).into(),
height: 0,
is_coinbase: false,
};
utxostore.add_utxo(&outpoint, &utxo).unwrap();
let retrieved = utxostore.get_utxo(&outpoint).unwrap();
assert!(retrieved.is_some());
let retrieved_utxo = retrieved.unwrap();
assert_eq!(retrieved_utxo.value, utxo.value);
assert_eq!(retrieved_utxo.height, utxo.height);
utxostore.remove_utxo(&outpoint).unwrap();
let result = utxostore.get_utxo(&outpoint).unwrap();
assert!(result.is_none());
}
#[test]
fn test_chain_state_consistency() {
let temp_dir = TempDir::new().unwrap();
let storage = Storage::new(temp_dir.path()).unwrap();
let chainstate = storage.chain();
let genesis_header = BlockHeader {
version: 1,
prev_block_hash: [0u8; 32],
merkle_root: [0u8; 32],
timestamp: 1231006505,
bits: 0x1d00ffff,
nonce: 2083236893,
};
chainstate.initialize(&genesis_header).unwrap();
let height = chainstate.get_height().unwrap();
assert_eq!(height, Some(0));
let tip_header = chainstate.get_tip_header().unwrap();
assert_eq!(tip_header.unwrap().version, genesis_header.version);
}
#[test]
fn test_storage_concurrent_reads() {
let temp_dir = TempDir::new().unwrap();
let storage = Storage::new(temp_dir.path()).unwrap();
let blockstore = storage.blocks();
let block = TestBlockBuilder::new()
.add_coinbase_transaction(p2pkh_script(random_hash20()))
.build();
blockstore.store_block(&block).unwrap();
let block_hash = blockstore.get_block_hash(&block);
use std::sync::Arc;
use std::thread;
let storage_arc = Arc::new(storage);
let mut handles = vec![];
for _ in 0..10 {
let storage_clone = Arc::clone(&storage_arc);
let hash = block_hash;
handles.push(thread::spawn(move || {
let blockstore = storage_clone.blocks();
blockstore.get_block(&hash).unwrap()
}));
}
for handle in handles {
let retrieved = handle.join().unwrap();
assert_eq!(retrieved.unwrap().header.version, block.header.version);
}
}
#[test]
fn test_storage_index_consistency() {
let temp_dir = TempDir::new().unwrap();
let storage = Storage::new(temp_dir.path()).unwrap();
let blockstore = storage.blocks();
let txindex = storage.transactions();
let tx = TestTransactionBuilder::new()
.add_input(OutPoint {
hash: random_hash(),
index: 0,
})
.add_output(1000, p2pkh_script(random_hash20()))
.build();
let block = TestBlockBuilder::new()
.add_coinbase_transaction(p2pkh_script(random_hash20()))
.add_transaction(tx.clone())
.build();
blockstore.store_block(&block).unwrap();
let block_hash = blockstore.get_block_hash(&block);
let retrieved_block = blockstore.get_block(&block_hash).unwrap();
assert!(retrieved_block.is_some());
}