check mempool::is_spent in ChainMemoryPoolTransactionOutputProvider::is_spent

This commit is contained in:
Svyatoslav Nikolsky 2016-12-12 00:56:32 +03:00
parent 1065541453
commit fdf704f6ae
2 changed files with 34 additions and 7 deletions

View File

@ -195,6 +195,12 @@ impl Chain {
&self.memory_pool
}
/// Get mutable memory pool
#[cfg(test)]
pub fn memory_pool_mut(&mut self) -> &mut MemoryPool {
&mut self.memory_pool
}
/// Get number of blocks in given state
pub fn length_of_blocks_state(&self, state: BlockState) -> u32 {
match state {

View File

@ -198,16 +198,19 @@ impl ChainMemoryPoolTransactionOutputProvider {
impl PreviousTransactionOutputProvider for ChainMemoryPoolTransactionOutputProvider {
fn previous_transaction_output(&self, prevout: &OutPoint) -> Option<TransactionOutput> {
self.chain.read().memory_pool().previous_transaction_output(prevout)
let chain = self.chain.read();
chain.memory_pool().previous_transaction_output(prevout)
.or_else(|| chain.storage().as_previous_transaction_output_provider().previous_transaction_output(prevout))
}
}
impl TransactionOutputObserver for ChainMemoryPoolTransactionOutputProvider {
fn is_spent(&self, prevout: &OutPoint) -> Option<bool> {
self.chain.read()
.storage()
.transaction_meta(&prevout.hash)
.and_then(|tm| tm.is_spent(prevout.index as usize))
let chain = self.chain.read();
if chain.memory_pool().is_spent(prevout) {
return Some(true);
}
chain.storage().transaction_meta(&prevout.hash).and_then(|tm| tm.is_spent(prevout.index as usize))
}
}
@ -227,12 +230,15 @@ impl TransactionOutputObserver for EmptyTransactionOutputProvider {
pub mod tests {
use std::sync::Arc;
use std::collections::HashMap;
use parking_lot::RwLock;
use chain::Transaction;
use synchronization_chain::{Chain, ChainRef};
use synchronization_client::CoreVerificationSink;
use synchronization_executor::tests::DummyTaskExecutor;
use primitives::hash::H256;
use super::{Verifier, BlockVerificationSink, TransactionVerificationSink};
use db::IndexedBlock;
use super::{Verifier, BlockVerificationSink, TransactionVerificationSink, ChainMemoryPoolTransactionOutputProvider};
use db::{self, IndexedBlock};
use test_data;
#[derive(Default)]
pub struct DummyVerifier {
@ -274,4 +280,19 @@ pub mod tests {
}
}
}
#[test]
fn when_transaction_spends_output_twice() {
use db::TransactionOutputObserver;
let tx1: Transaction = test_data::TransactionBuilder::with_default_input(0).into();
let tx2: Transaction = test_data::TransactionBuilder::with_default_input(1).into();
let out1 = tx1.inputs[0].previous_output.clone();
let out2 = tx2.inputs[0].previous_output.clone();
let mut chain = Chain::new(Arc::new(db::TestStorage::with_genesis_block()));
chain.memory_pool_mut().insert_verified(tx1);
let chain = ChainRef::new(RwLock::new(chain));
let provider = ChainMemoryPoolTransactionOutputProvider::with_chain(chain);
assert!(provider.is_spent(&out1).unwrap_or_default());
assert!(!provider.is_spent(&out2).unwrap_or_default());
}
}