diff --git a/zebrad/src/components/inbound/tests.rs b/zebrad/src/components/inbound/tests.rs index 31bc02f7..91a84583 100644 --- a/zebrad/src/components/inbound/tests.rs +++ b/zebrad/src/components/inbound/tests.rs @@ -253,13 +253,16 @@ async fn setup( } fn add_some_stuff_to_mempool(mempool_service: &mut Mempool, network: Network) -> Vec { - // get the genesis block transactions from the Zcash blockchain. - let genesis_transactions = unmined_transactions_in_blocks(0, network); + // get the genesis block coinbase transaction from the Zcash blockchain. + let genesis_transactions: Vec<_> = unmined_transactions_in_blocks(..=0, network) + .take(1) + .collect(); + // Insert the genesis block coinbase transaction into the mempool storage. mempool_service .storage() - .insert(genesis_transactions.1[0].clone()) + .insert(genesis_transactions[0].clone()) .unwrap(); - genesis_transactions.1 + genesis_transactions } diff --git a/zebrad/src/components/mempool/storage/tests.rs b/zebrad/src/components/mempool/storage/tests.rs index cd297f78..ce1a7b30 100644 --- a/zebrad/src/components/mempool/storage/tests.rs +++ b/zebrad/src/components/mempool/storage/tests.rs @@ -1,3 +1,5 @@ +use std::ops::RangeBounds; + use super::*; use zebra_chain::{ @@ -15,11 +17,10 @@ fn mempool_storage_crud_mainnet() { // Create an empty storage instance let mut storage: Storage = Default::default(); - // Get transactions from the first 10 blocks of the Zcash blockchain - let (_, unmined_transactions) = unmined_transactions_in_blocks(10, network); - // Get one (1) unmined transaction - let unmined_tx = &unmined_transactions[0]; + let unmined_tx = unmined_transactions_in_blocks(.., network) + .next() + .expect("at least one unmined transaction"); // Insert unmined tx into the mempool. let _ = storage.insert(unmined_tx.clone()); @@ -49,77 +50,75 @@ fn mempool_storage_basic_for_network(network: Network) -> Result<()> { let mut storage: Storage = Default::default(); // Get transactions from the first 10 blocks of the Zcash blockchain - let (total_transactions, unmined_transactions) = unmined_transactions_in_blocks(10, network); + let unmined_transactions: Vec<_> = unmined_transactions_in_blocks(..=10, network).collect(); + let total_transactions = unmined_transactions.len(); // Insert them all to the storage for unmined_transaction in unmined_transactions.clone() { storage.insert(unmined_transaction)?; } + // Separate transactions into the ones expected to be in the mempool and those expected to be + // rejected. + let rejected_transaction_count = total_transactions - MEMPOOL_SIZE; + let expected_to_be_rejected = &unmined_transactions[..rejected_transaction_count]; + let expected_in_mempool = &unmined_transactions[rejected_transaction_count..]; + // Only MEMPOOL_SIZE should land in verified assert_eq!(storage.verified.len(), MEMPOOL_SIZE); // The rest of the transactions will be in rejected - assert_eq!(storage.rejected.len(), total_transactions - MEMPOOL_SIZE); + assert_eq!(storage.rejected.len(), rejected_transaction_count); // Make sure the last MEMPOOL_SIZE transactions we sent are in the verified - for tx in unmined_transactions.iter().rev().take(MEMPOOL_SIZE) { + for tx in expected_in_mempool { assert!(storage.contains(&tx.id)); } // Anything greater should not be in the verified - for tx in unmined_transactions - .iter() - .take(unmined_transactions.len() - MEMPOOL_SIZE) - { + for tx in expected_to_be_rejected { assert!(!storage.contains(&tx.id)); } // Query all the ids we have for rejected, get back `total - MEMPOOL_SIZE` let all_ids: HashSet = unmined_transactions.iter().map(|tx| tx.id).collect(); - let rejected_ids: HashSet = unmined_transactions - .iter() - .take(total_transactions - MEMPOOL_SIZE) - .map(|tx| tx.id) - .collect(); + // Convert response to a `HashSet` as we need a fixed order to compare. let rejected_response: HashSet = storage.rejected_transactions(all_ids).into_iter().collect(); + let rejected_ids = expected_to_be_rejected.iter().map(|tx| tx.id).collect(); + assert_eq!(rejected_response, rejected_ids); // Use `contains_rejected` to make sure the first id stored is now rejected - assert!(storage.contains_rejected(&unmined_transactions[0].id)); + assert!(storage.contains_rejected(&expected_to_be_rejected[0].id)); // Use `contains_rejected` to make sure the last id stored is not rejected - assert!(!storage.contains_rejected(&unmined_transactions[unmined_transactions.len() - 1].id)); + assert!(!storage.contains_rejected(&expected_in_mempool[0].id)); Ok(()) } pub fn unmined_transactions_in_blocks( - last_block_height: u32, + block_height_range: impl RangeBounds, network: Network, -) -> (usize, Vec) { - let mut transactions = vec![]; - let mut total = 0; - - let block_iter = match network { +) -> impl DoubleEndedIterator { + let blocks = match network { Network::Mainnet => zebra_test::vectors::MAINNET_BLOCKS.iter(), Network::Testnet => zebra_test::vectors::TESTNET_BLOCKS.iter(), }; - for (&height, block) in block_iter { - if height <= last_block_height { - let block = block + // Deserialize the blocks that are selected based on the specified `block_height_range`. + let selected_blocks = blocks + .filter(move |(&height, _)| block_height_range.contains(&height)) + .map(|(_, block)| { + block .zcash_deserialize_into::() - .expect("block is structurally valid"); + .expect("block test vector is structurally valid") + }); - for transaction in block.transactions.iter() { - transactions.push(UnminedTx::from(transaction)); - total += 1; - } - } - } - - (total, transactions) + // Extract the transactions from the blocks and warp each one as an unmined transaction. + selected_blocks + .flat_map(|block| block.transactions) + .map(UnminedTx::from) } diff --git a/zebrad/src/components/mempool/tests.rs b/zebrad/src/components/mempool/tests.rs index 9437cb49..2bbc1525 100644 --- a/zebrad/src/components/mempool/tests.rs +++ b/zebrad/src/components/mempool/tests.rs @@ -26,7 +26,12 @@ async fn mempool_service_basic() -> Result<(), Report> { .await; // get the genesis block transactions from the Zcash blockchain. - let genesis_transactions = unmined_transactions_in_blocks(0, network); + let mut unmined_transactions = unmined_transactions_in_blocks(..=10, network); + let genesis_transaction = unmined_transactions + .next() + .expect("Missing genesis transaction"); + let more_transactions = unmined_transactions; + // Start the mempool service let mut service = Mempool::new( network, @@ -37,7 +42,7 @@ async fn mempool_service_basic() -> Result<(), Report> { chain_tip_change, ); // Insert the genesis block coinbase transaction into the mempool storage. - service.storage.insert(genesis_transactions.1[0].clone())?; + service.storage.insert(genesis_transaction.clone())?; // Test `Request::TransactionIds` let response = service @@ -61,7 +66,7 @@ async fn mempool_service_basic() -> Result<(), Report> { .ready_and() .await .unwrap() - .oneshot(Request::TransactionsById( + .call(Request::TransactionsById( genesis_transactions_hash_set.clone(), )) .await @@ -73,12 +78,11 @@ async fn mempool_service_basic() -> Result<(), Report> { // Make sure the transaction from the blockchain test vector is the same as the // response of `Request::TransactionsById` - assert_eq!(genesis_transactions.1[0], transactions[0]); + assert_eq!(genesis_transaction, transactions[0]); // Insert more transactions into the mempool storage. // This will cause the genesis transaction to be moved into rejected. - let more_transactions = unmined_transactions_in_blocks(10, network); - for tx in more_transactions.1.iter().skip(1) { + for tx in more_transactions { service.storage.insert(tx.clone())?; }