Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework pool tests to use real chain (was mock chain) #3342

Merged
merged 2 commits into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub const TESTING_INITIAL_GRAPH_WEIGHT: u32 = 1;
pub const TESTING_INITIAL_DIFFICULTY: u64 = 1;

/// Testing max_block_weight (artifically low, just enough to support a few txs).
pub const TESTING_MAX_BLOCK_WEIGHT: usize = 150;
pub const TESTING_MAX_BLOCK_WEIGHT: usize = 250;

/// If a peer's last updated difficulty is 2 hours ago and its difficulty's lower than ours,
/// we're sure this peer is a stuck node, and we will kick out such kind of stuck peers.
Expand Down
4 changes: 2 additions & 2 deletions pool/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,9 @@ pub trait PoolAdapter: Send + Sync {

/// Dummy adapter used as a placeholder for real implementations
#[allow(dead_code)]
pub struct NoopAdapter {}
pub struct NoopPoolAdapter {}

impl PoolAdapter for NoopAdapter {
impl PoolAdapter for NoopPoolAdapter {
fn tx_accepted(&self, _entry: &PoolEntry) {}
fn stem_tx_accepted(&self, _entry: &PoolEntry) -> Result<(), PoolError> {
Ok(())
Expand Down
182 changes: 77 additions & 105 deletions pool/tests/block_building.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,126 +16,98 @@ pub mod common;

use self::core::core::hash::Hashed;
use self::core::core::verifier_cache::LruVerifierCache;
use self::core::core::{Block, BlockHeader, Transaction};
use self::core::pow::Difficulty;
use self::core::{global, libtx};
use self::core::global;
use self::keychain::{ExtKeychain, Keychain};
use self::pool::PoolError;
use self::util::RwLock;
use crate::common::*;
use grin_core as core;
use grin_keychain as keychain;
use grin_pool as pool;
use grin_util as util;
use std::sync::Arc;

#[test]
fn test_transaction_pool_block_building() {
fn test_transaction_pool_block_building() -> Result<(), PoolError> {
util::init_test_logger();
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
let keychain: ExtKeychain = Keychain::from_random_seed(false).unwrap();

let db_root = ".grin_block_building".to_string();
clean_output_dir(db_root.clone());
let db_root = "target/.block_building";
clean_output_dir(db_root.into());

let genesis = genesis_block(&keychain);
let chain = Arc::new(init_chain(db_root, genesis));
let verifier_cache = Arc::new(RwLock::new(LruVerifierCache::new()));

// Initialize a new pool with our chain adapter.
let mut pool = init_transaction_pool(
Arc::new(ChainAdapter {
chain: chain.clone(),
}),
verifier_cache,
);

add_some_blocks(&chain, 3, &keychain);

let header_1 = chain.get_header_by_height(1).unwrap();

// Now create tx to spend an early coinbase (now matured).
// Provides us with some useful outputs to test with.
let initial_tx = test_transaction_spending_coinbase(&keychain, &header_1, vec![10, 20, 30, 40]);

// Mine that initial tx so we can spend it with multiple txs.
add_block(&chain, vec![initial_tx], &keychain);

let header = chain.head_header().unwrap();

let root_tx_1 = test_transaction(&keychain, vec![10, 20], vec![24]);
let root_tx_2 = test_transaction(&keychain, vec![30], vec![28]);
let root_tx_3 = test_transaction(&keychain, vec![40], vec![38]);

let child_tx_1 = test_transaction(&keychain, vec![24], vec![22]);
let child_tx_2 = test_transaction(&keychain, vec![38], vec![32]);

{
let mut chain = ChainAdapter::init(db_root.clone()).unwrap();

let verifier_cache = Arc::new(RwLock::new(LruVerifierCache::new()));

// Initialize the chain/txhashset with an initial block
// so we have a non-empty UTXO set.
let add_block =
|prev_header: BlockHeader, txs: Vec<Transaction>, chain: &mut ChainAdapter| {
let height = prev_header.height + 1;
let key_id = ExtKeychain::derive_key_id(1, height as u32, 0, 0, 0);
let fee = txs.iter().map(|x| x.fee()).sum();
let reward = libtx::reward::output(
&keychain,
&libtx::ProofBuilder::new(&keychain),
&key_id,
fee,
false,
)
.unwrap();
let mut block = Block::new(&prev_header, txs, Difficulty::min(), reward).unwrap();

// Set the prev_root to the prev hash for testing purposes (no MMR to obtain a root from).
block.header.prev_root = prev_header.hash();

chain.update_db_for_block(&block);
block
};

let block = add_block(BlockHeader::default(), vec![], &mut chain);
let header = block.header;

// Now create tx to spend that first coinbase (now matured).
// Provides us with some useful outputs to test with.
let initial_tx =
test_transaction_spending_coinbase(&keychain, &header, vec![10, 20, 30, 40]);

// Mine that initial tx so we can spend it with multiple txs
let block = add_block(header, vec![initial_tx], &mut chain);
let header = block.header;

// Initialize a new pool with our chain adapter.
let pool = RwLock::new(test_setup(Arc::new(chain.clone()), verifier_cache));

let root_tx_1 = test_transaction(&keychain, vec![10, 20], vec![24]);
let root_tx_2 = test_transaction(&keychain, vec![30], vec![28]);
let root_tx_3 = test_transaction(&keychain, vec![40], vec![38]);

let child_tx_1 = test_transaction(&keychain, vec![24], vec![22]);
let child_tx_2 = test_transaction(&keychain, vec![38], vec![32]);

{
let mut write_pool = pool.write();

// Add the three root txs to the pool.
write_pool
.add_to_pool(test_source(), root_tx_1.clone(), false, &header)
.unwrap();
write_pool
.add_to_pool(test_source(), root_tx_2.clone(), false, &header)
.unwrap();
write_pool
.add_to_pool(test_source(), root_tx_3.clone(), false, &header)
.unwrap();

// Now add the two child txs to the pool.
write_pool
.add_to_pool(test_source(), child_tx_1.clone(), false, &header)
.unwrap();
write_pool
.add_to_pool(test_source(), child_tx_2.clone(), false, &header)
.unwrap();

assert_eq!(write_pool.total_size(), 5);
}

let txs = pool.read().prepare_mineable_transactions().unwrap();

let block = add_block(header, txs, &mut chain);

// Check the block contains what we expect.
assert_eq!(block.inputs().len(), 4);
assert_eq!(block.outputs().len(), 4);
assert_eq!(block.kernels().len(), 6);

assert!(block.kernels().contains(&root_tx_1.kernels()[0]));
assert!(block.kernels().contains(&root_tx_2.kernels()[0]));
assert!(block.kernels().contains(&root_tx_3.kernels()[0]));
assert!(block.kernels().contains(&child_tx_1.kernels()[0]));
assert!(block.kernels().contains(&child_tx_1.kernels()[0]));

// Now reconcile the transaction pool with the new block
// and check the resulting contents of the pool are what we expect.
{
let mut write_pool = pool.write();
write_pool.reconcile_block(&block).unwrap();

assert_eq!(write_pool.total_size(), 0);
}
// Add the three root txs to the pool.
pool.add_to_pool(test_source(), root_tx_1.clone(), false, &header)?;
pool.add_to_pool(test_source(), root_tx_2.clone(), false, &header)?;
pool.add_to_pool(test_source(), root_tx_3.clone(), false, &header)?;

// Now add the two child txs to the pool.
pool.add_to_pool(test_source(), child_tx_1.clone(), false, &header)?;
pool.add_to_pool(test_source(), child_tx_2.clone(), false, &header)?;

assert_eq!(pool.total_size(), 5);
}

let txs = pool.prepare_mineable_transactions()?;

add_block(&chain, txs, &keychain);

// Get full block from head of the chain (block we just processed).
let block = chain.get_block(&chain.head().unwrap().hash()).unwrap();

// Check the block contains what we expect.
assert_eq!(block.inputs().len(), 4);
assert_eq!(block.outputs().len(), 4);
assert_eq!(block.kernels().len(), 6);

assert!(block.kernels().contains(&root_tx_1.kernels()[0]));
assert!(block.kernels().contains(&root_tx_2.kernels()[0]));
assert!(block.kernels().contains(&root_tx_3.kernels()[0]));
assert!(block.kernels().contains(&child_tx_1.kernels()[0]));
assert!(block.kernels().contains(&child_tx_1.kernels()[0]));

// Now reconcile the transaction pool with the new block
// and check the resulting contents of the pool are what we expect.
{
pool.reconcile_block(&block)?;
assert_eq!(pool.total_size(), 0);
}

// Cleanup db directory
clean_output_dir(db_root.clone());
clean_output_dir(db_root.into());

Ok(())
}
Loading