Newer
Older
.build(); // genesis -> b0 -> b3[tx3] -> b4[tx4] -> b5[tx5]
let tx1 = b1.transactions[0].clone();
let tx1_hash = tx1.hash();
let tx2 = b2.transactions[0].clone();
let tx2_hash = tx2.hash();
let tx3 = b3.transactions[0].clone();
let tx4 = b4.transactions[0].clone();
let tx5 = b5.transactions[0].clone();
let path = RandomTempPath::create_dir();
let storage = Arc::new(db::Storage::new(path.as_path()).unwrap(), );
storage.insert_block(&genesis).expect("no db error");
let mut chain = Chain::new(storage, Arc::new(RwLock::new(MemoryPool::new())));
chain.insert_verified_transaction(tx3.into());
chain.insert_verified_transaction(tx4.into());
chain.insert_verified_transaction(tx5.into());
assert_eq!(chain.insert_best_block(&b0.clone().into()).expect("block accepted"), BlockInsertionResult::with_canonized_blocks(vec![b0.hash()]));
assert_eq!(chain.information().transactions.transactions_count, 3);
assert_eq!(chain.insert_best_block(&b1.clone().into()).expect("block accepted"), BlockInsertionResult::with_canonized_blocks(vec![b1.hash()]));
assert_eq!(chain.information().transactions.transactions_count, 3);
assert_eq!(chain.insert_best_block(&b2.clone().into()).expect("block accepted"), BlockInsertionResult::with_canonized_blocks(vec![b2.hash()]));
assert_eq!(chain.information().transactions.transactions_count, 3);
assert_eq!(chain.insert_best_block(&b3.clone().into()).expect("block accepted"), BlockInsertionResult::default());
assert_eq!(chain.information().transactions.transactions_count, 3);
assert_eq!(chain.insert_best_block(&b4.clone().into()).expect("block accepted"), BlockInsertionResult::default());
assert_eq!(chain.information().transactions.transactions_count, 3);
// order matters
let insert_result = chain.insert_best_block(&b5.clone().into()).expect("block accepted");
let transactions_to_reverify_hashes: Vec<_> = insert_result
.transactions_to_reverify
.into_iter()
.collect();
assert_eq!(transactions_to_reverify_hashes, vec![tx1_hash, tx2_hash]);
assert_eq!(insert_result.canonized_blocks_hashes, vec![b3.hash(), b4.hash(), b5.hash()]);
assert_eq!(chain.information().transactions.transactions_count, 0); // tx3, tx4, tx5 are added to the database
}
#[test]
fn double_spend_transaction_is_removed_from_memory_pool_when_output_is_spent_in_block_transaction() {
let genesis = test_data::genesis();
let tx0 = genesis.transactions[0].clone();
let b0 = test_data::block_builder().header().nonce(1).parent(genesis.hash()).build()
.transaction()
.lock_time(1)
.input().hash(tx0.hash()).index(0).build()
.build()
.build(); // genesis -> b0[tx1]
// tx1 && tx2 are spending same output
let tx2: Transaction = test_data::TransactionBuilder::with_output(20).add_input(&tx0, 0).into();
let tx3: Transaction = test_data::TransactionBuilder::with_output(20).add_input(&tx0, 1).into();
// insert tx2 to memory pool
let mut chain = Chain::new(Arc::new(db::TestStorage::with_genesis_block()), Arc::new(RwLock::new(MemoryPool::new())));
chain.insert_verified_transaction(tx2.clone().into());
chain.insert_verified_transaction(tx3.clone().into());
// insert verified block with tx1
// => tx2 is removed from memory pool, but tx3 remains
assert_eq!(chain.information().transactions.transactions_count, 1);
}
#[test]
fn update_memory_pool_transaction() {
use test_data::{ChainBuilder, TransactionBuilder};
let data_chain = &mut ChainBuilder::new();
TransactionBuilder::with_output(10).add_output(10).add_output(10).store(data_chain) // transaction0
.reset().set_input(&data_chain.at(0), 0).add_output(20).lock().store(data_chain) // transaction0 -> transaction1
.reset().set_input(&data_chain.at(0), 0).add_output(30).store(data_chain); // transaction0 -> transaction2
let mut chain = Chain::new(Arc::new(db::TestStorage::with_genesis_block()), Arc::new(RwLock::new(MemoryPool::new())));
chain.insert_verified_transaction(data_chain.at(1).into());
assert_eq!(chain.information().transactions.transactions_count, 1);
chain.insert_verified_transaction(data_chain.at(2).into());
assert_eq!(chain.information().transactions.transactions_count, 1); // tx was replaces
}