pub mod common;
use self::core::core::{transaction, Weighting};
use self::core::global;
use self::keychain::{ExtKeychain, Keychain};
use self::pool::TxSource;
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_the_transaction_pool() {
util::init_test_logger();
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
global::set_local_accept_fee_base(1);
let keychain: ExtKeychain = Keychain::from_random_seed(false).unwrap();
let db_root = "target/.transaction_pool";
clean_output_dir(db_root.into());
let genesis = genesis_block(&keychain);
let chain = Arc::new(init_chain(db_root, genesis));
let mut pool = init_transaction_pool(Arc::new(ChainAdapter {
chain: chain.clone(),
}));
add_some_blocks(&chain, 4 * 3, &keychain);
let header = chain.head_header().unwrap();
let header_1 = chain.get_header_by_height(1).unwrap();
let initial_tx = test_transaction_spending_coinbase(
&keychain,
&header_1,
vec![500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400],
);
{
pool.add_to_pool(test_source(), initial_tx, false, &header)
.unwrap();
assert_eq!(pool.total_size(), 1);
}
{
let tx = test_transaction_spending_coinbase(&keychain, &header, vec![501]);
assert!(pool.add_to_pool(test_source(), tx, false, &header).is_err());
}
let tx1 = test_transaction(&keychain, vec![500, 600], vec![469, 569]);
let tx2 = test_transaction(&keychain, vec![469, 700], vec![498]);
{
assert_eq!(pool.total_size(), 1);
pool.add_to_pool(test_source(), tx1.clone(), false, &header)
.unwrap();
assert_eq!(pool.total_size(), 2);
pool.add_to_pool(test_source(), tx2.clone(), false, &header)
.unwrap();
assert_eq!(pool.total_size(), 3);
}
{
assert!(pool
.add_to_pool(test_source(), tx1.clone(), false, &header)
.is_err());
}
{
let tx1a = test_transaction(&keychain, vec![500, 600], vec![469, 569]);
assert!(pool
.add_to_pool(test_source(), tx1a, false, &header)
.is_err());
}
{
let bad_tx = test_transaction(&keychain, vec![10_001], vec![9_900]);
assert!(pool
.add_to_pool(test_source(), bad_tx, false, &header)
.is_err());
}
{
let tx = test_transaction(&keychain, vec![900], vec![498]);
assert!(pool.add_to_pool(test_source(), tx, false, &header).is_err());
}
{
let tx3 = test_transaction(&keychain, vec![500], vec![467]);
assert!(pool
.add_to_pool(test_source(), tx3, false, &header)
.is_err());
assert_eq!(pool.total_size(), 3);
}
{
let tx = test_transaction(&keychain, vec![569], vec![538]);
pool.add_to_pool(test_source(), tx, true, &header).unwrap();
let tx2 = test_transaction(&keychain, vec![538], vec![507]);
pool.add_to_pool(test_source(), tx2, true, &header).unwrap();
assert_eq!(pool.total_size(), 3);
assert_eq!(pool.stempool.size(), 2);
}
{
let agg_tx = pool
.stempool
.all_transactions_aggregate(None)
.unwrap()
.unwrap();
assert_eq!(agg_tx.kernels().len(), 2);
pool.add_to_pool(test_source(), agg_tx, false, &header)
.unwrap();
assert_eq!(pool.total_size(), 4);
assert!(pool.stempool.is_empty());
}
{
let tx = test_transaction(&keychain, vec![507], vec![476]);
pool.add_to_pool(test_source(), tx.clone(), true, &header)
.unwrap();
assert_eq!(pool.total_size(), 4);
assert_eq!(pool.txpool.size(), 4);
assert_eq!(pool.stempool.size(), 1);
pool.add_to_pool(test_source(), tx.clone(), true, &header)
.unwrap();
assert_eq!(pool.total_size(), 5);
assert_eq!(pool.txpool.size(), 5);
assert!(pool.stempool.is_empty());
}
{
let tx4 = test_transaction(&keychain, vec![800], vec![769]);
let agg_tx = transaction::aggregate(&[tx1.clone(), tx2.clone(), tx4]).unwrap();
agg_tx.validate(Weighting::AsTransaction).unwrap();
pool.add_to_pool(test_source(), agg_tx, false, &header)
.unwrap();
assert_eq!(pool.total_size(), 6);
let entry = pool.txpool.entries.last().unwrap();
assert_eq!(entry.tx.kernels().len(), 1);
assert_eq!(entry.src, TxSource::Deaggregate);
}
{
let double_spend_tx = test_transaction_spending_coinbase(&keychain, &header, vec![1000]);
assert!(pool
.add_to_pool(test_source(), double_spend_tx.clone(), true, &header)
.is_err());
assert!(pool
.add_to_pool(test_source(), double_spend_tx.clone(), false, &header)
.is_err());
}
clean_output_dir(db_root.into());
}