Skip to content

Commit

Permalink
Test if the mempool storage is cleared (#2815)
Browse files Browse the repository at this point in the history
* Move mempool tests into `tests::vector` sub-module

Make it consistent with other test modules and prepare for adding
property tests.

* Reorder imports

Make it consistent with the general guidelines followed on other
modules.

* Export `ChainTipBlock` and `ChainTipSender`

Allow these types to be used in other crates for testing purposes.

* Derive `Arbitrary` for `ChainTipBlock`

Make it easy to generate random `ChainTipBlock`s for usage in property
tests.

* Refactor to move test methods into `tests` module

Reduce the repeated test configuration attributes and make it easier to
see what is test specific and what is part of the general
implementation.

* Add a `Mempool::dummy_call` test helper method

Performs a dummy call just so that `poll_ready` gets called.

* Use `dummy_call` in existing tests

Replace the custom dummy requests with the helper method.

* Test if the mempool is cleared on chain reset

A chain reset should force the mempool storage to be cleared so that
transaction verification can restart using the new chain tip.

* Test if mempool is cleared on syncer restart

If the block synchronizer falls behind and then starts catching up
again, the mempool should be disabled and therefore the storage should
be cleared.
  • Loading branch information
jvff authored Oct 1, 2021
1 parent 966f52a commit 50a5728
Show file tree
Hide file tree
Showing 8 changed files with 779 additions and 619 deletions.
3 changes: 2 additions & 1 deletion zebra-state/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
edition = "2018"

[features]
proptest-impl = ["proptest", "zebra-test"]
proptest-impl = ["proptest", "proptest-derive", "zebra-test"]

[dependencies]
zebra-chain = { path = "../zebra-chain" }
Expand Down Expand Up @@ -34,6 +34,7 @@ rlimit = "0.5.4"
multiset = "0.0.5"

proptest = { version = "0.10.1", optional = true }
proptest-derive = { version = "0.3", optional = true }
zebra-test = { path = "../zebra-test/", optional = true }

[dev-dependencies]
Expand Down
5 changes: 4 additions & 1 deletion zebra-state/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ pub use service::{
};

#[cfg(any(test, feature = "proptest-impl"))]
pub use service::init_test;
pub use service::{
chain_tip::{ChainTipBlock, ChainTipSender},
init_test,
};

pub(crate) use request::ContextuallyValidBlock;
4 changes: 4 additions & 0 deletions zebra-state/src/service/chain_tip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use std::sync::Arc;
use tokio::sync::watch;
use tracing::instrument;

#[cfg(any(test, feature = "proptest-impl"))]
use proptest_derive::Arbitrary;

use zebra_chain::{
block,
chain_tip::ChainTip,
Expand All @@ -33,6 +36,7 @@ type ChainTipData = Option<ChainTipBlock>;
/// Used to efficiently update [`ChainTipSender`], [`LatestChainTip`],
/// and [`ChainTipChange`].
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
pub struct ChainTipBlock {
/// The hash of the best chain tip block.
pub hash: block::Hash,
Expand Down
1 change: 1 addition & 0 deletions zebrad/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ proptest = "0.10"
proptest-derive = "0.3"

zebra-chain = { path = "../zebra-chain", features = ["proptest-impl"] }
zebra-state = { path = "../zebra-state", features = ["proptest-impl"] }
zebra-test = { path = "../zebra-test" }

[features]
Expand Down
40 changes: 0 additions & 40 deletions zebrad/src/components/mempool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ use self::downloads::{
Downloads as TxDownloads, Gossip, TRANSACTION_DOWNLOAD_TIMEOUT, TRANSACTION_VERIFY_TIMEOUT,
};

#[cfg(test)]
use super::sync::RecentSyncLengths;
use super::sync::SyncStatus;

type Outbound = Buffer<BoxService<zn::Request, zn::Response, zn::BoxError>, zn::Request>;
Expand Down Expand Up @@ -175,44 +173,6 @@ impl Mempool {
}
}

/// Get the storage field of the mempool for testing purposes.
#[cfg(test)]
pub fn storage(&mut self) -> &mut storage::Storage {
match &mut self.active_state {
ActiveState::Disabled => panic!("mempool must be enabled"),
ActiveState::Enabled { storage, .. } => storage,
}
}

/// Get the transaction downloader of the mempool for testing purposes.
#[cfg(test)]
pub fn tx_downloads(&self) -> &Pin<Box<InboundTxDownloads>> {
match &self.active_state {
ActiveState::Disabled => panic!("mempool must be enabled"),
ActiveState::Enabled { tx_downloads, .. } => tx_downloads,
}
}

/// Enable the mempool by pretending the synchronization is close to the tip.
#[cfg(test)]
pub async fn enable(&mut self, recent_syncs: &mut RecentSyncLengths) {
use tower::ServiceExt;
// Pretend we're close to tip
SyncStatus::sync_close_to_tip(recent_syncs);
// Make a dummy request to poll the mempool and make it enable itself
let _ = self.oneshot(Request::TransactionIds).await;
}

/// Disable the mempool by pretending the synchronization is far from the tip.
#[cfg(test)]
pub async fn disable(&mut self, recent_syncs: &mut RecentSyncLengths) {
use tower::ServiceExt;
// Pretend we're far from the tip
SyncStatus::sync_far_from_tip(recent_syncs);
// Make a dummy request to poll the mempool and make it disable itself
let _ = self.oneshot(Request::TransactionIds).await;
}

/// Check if transaction should be downloaded and/or verified.
///
/// If it is already in the mempool (or in its rejected list)
Expand Down
Loading

0 comments on commit 50a5728

Please sign in to comment.