Mempool support for transaction expiration (#2774)
* mempool - support transaction expiration * use `LatestChainTip` instead of state call * clippy * remove spawn task * remove non needed async from function * remove return value * add a `expiry_height_mut()` method to `Transaction` for testing purposes * fix `remove_expired_transactions()` * add a `mempool_transaction_expiration()` test * tidy cleanup to `expiry_height()` * improve docs * fix the build * try fix macos build * extend tests * add doc to function * clippy * fix build * start tests at block two
This commit is contained in:
parent
c6878d9b63
commit
37595c4b32
|
|
@ -294,8 +294,7 @@ impl Transaction {
|
||||||
/// Get this transaction's expiry height, if any.
|
/// Get this transaction's expiry height, if any.
|
||||||
pub fn expiry_height(&self) -> Option<block::Height> {
|
pub fn expiry_height(&self) -> Option<block::Height> {
|
||||||
match self {
|
match self {
|
||||||
Transaction::V1 { .. } => None,
|
Transaction::V1 { .. } | Transaction::V2 { .. } => None,
|
||||||
Transaction::V2 { .. } => None,
|
|
||||||
Transaction::V3 { expiry_height, .. }
|
Transaction::V3 { expiry_height, .. }
|
||||||
| Transaction::V4 { expiry_height, .. }
|
| Transaction::V4 { expiry_height, .. }
|
||||||
| Transaction::V5 { expiry_height, .. } => match expiry_height {
|
| Transaction::V5 { expiry_height, .. } => match expiry_height {
|
||||||
|
|
@ -308,6 +307,32 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Modify the expiry height of this transaction.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// - if called on a v1 or v2 transaction
|
||||||
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
|
pub fn expiry_height_mut(&mut self) -> &mut block::Height {
|
||||||
|
match self {
|
||||||
|
Transaction::V1 { .. } | Transaction::V2 { .. } => {
|
||||||
|
panic!("v1 and v2 transactions are not supported")
|
||||||
|
}
|
||||||
|
Transaction::V3 {
|
||||||
|
ref mut expiry_height,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| Transaction::V4 {
|
||||||
|
ref mut expiry_height,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| Transaction::V5 {
|
||||||
|
ref mut expiry_height,
|
||||||
|
..
|
||||||
|
} => expiry_height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get this transaction's network upgrade field, if any.
|
/// Get this transaction's network upgrade field, if any.
|
||||||
/// This field is serialized as `nConsensusBranchId` ([7.1]).
|
/// This field is serialized as `nConsensusBranchId` ([7.1]).
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ impl StartCmd {
|
||||||
));
|
));
|
||||||
|
|
||||||
let (peer_set, address_book) =
|
let (peer_set, address_book) =
|
||||||
zebra_network::init(config.network.clone(), inbound, latest_chain_tip).await;
|
zebra_network::init(config.network.clone(), inbound, latest_chain_tip.clone()).await;
|
||||||
|
|
||||||
info!("initializing syncer");
|
info!("initializing syncer");
|
||||||
let (syncer, sync_status) =
|
let (syncer, sync_status) =
|
||||||
|
|
@ -96,6 +96,7 @@ impl StartCmd {
|
||||||
state,
|
state,
|
||||||
tx_verifier,
|
tx_verifier,
|
||||||
sync_status.clone(),
|
sync_status.clone(),
|
||||||
|
latest_chain_tip,
|
||||||
chain_tip_change.clone(),
|
chain_tip_change.clone(),
|
||||||
));
|
));
|
||||||
let mempool = ServiceBuilder::new().buffer(20).service(mempool_service);
|
let mempool = ServiceBuilder::new().buffer(20).service(mempool_service);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ use zebra_test::mock_service::{MockService, PanicAssertion};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mempool_requests_for_transactions() {
|
async fn mempool_requests_for_transactions() {
|
||||||
let (inbound_service, added_transactions, _, mut peer_set) = setup(true).await;
|
let (inbound_service, added_transactions, _, mut peer_set, _) = setup(true).await;
|
||||||
|
|
||||||
let added_transaction_ids: Vec<UnminedTxId> = added_transactions
|
let added_transaction_ids: Vec<UnminedTxId> = added_transactions
|
||||||
.clone()
|
.clone()
|
||||||
|
|
@ -74,7 +74,7 @@ async fn mempool_push_transaction() -> Result<(), crate::BoxError> {
|
||||||
// use the first transaction that is not coinbase
|
// use the first transaction that is not coinbase
|
||||||
let tx = block.transactions[1].clone();
|
let tx = block.transactions[1].clone();
|
||||||
|
|
||||||
let (inbound_service, _, mut tx_verifier, mut peer_set) = setup(false).await;
|
let (inbound_service, _, mut tx_verifier, mut peer_set, _) = setup(false).await;
|
||||||
|
|
||||||
// Test `Request::PushTransaction`
|
// Test `Request::PushTransaction`
|
||||||
let request = inbound_service
|
let request = inbound_service
|
||||||
|
|
@ -123,7 +123,7 @@ async fn mempool_advertise_transaction_ids() -> Result<(), crate::BoxError> {
|
||||||
let test_transaction_id = test_transaction.unmined_id();
|
let test_transaction_id = test_transaction.unmined_id();
|
||||||
let txs = HashSet::from_iter([test_transaction_id]);
|
let txs = HashSet::from_iter([test_transaction_id]);
|
||||||
|
|
||||||
let (inbound_service, _, mut tx_verifier, mut peer_set) = setup(false).await;
|
let (inbound_service, _, mut tx_verifier, mut peer_set, _) = setup(false).await;
|
||||||
|
|
||||||
// Test `Request::AdvertiseTransactionIds`
|
// Test `Request::AdvertiseTransactionIds`
|
||||||
let request = inbound_service
|
let request = inbound_service
|
||||||
|
|
@ -173,6 +173,178 @@ async fn mempool_advertise_transaction_ids() -> Result<(), crate::BoxError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn mempool_transaction_expiration() -> Result<(), crate::BoxError> {
|
||||||
|
// Get a block that has at least one non coinbase transaction
|
||||||
|
let block: Block = zebra_test::vectors::BLOCK_MAINNET_982681_BYTES.zcash_deserialize_into()?;
|
||||||
|
|
||||||
|
// Use the first transaction that is not coinbase to test expiration
|
||||||
|
let tx1 = &*(block.transactions[1]).clone();
|
||||||
|
let mut tx1_id = tx1.unmined_id();
|
||||||
|
|
||||||
|
// Change the expiration height of the transaction to block 3
|
||||||
|
let mut tx1 = tx1.clone();
|
||||||
|
*tx1.expiry_height_mut() = zebra_chain::block::Height(3);
|
||||||
|
|
||||||
|
// Use the second transaction that is not coinbase to trigger `remove_expired_transactions()`
|
||||||
|
let tx2 = block.transactions[2].clone();
|
||||||
|
let mut tx2_id = tx2.unmined_id();
|
||||||
|
|
||||||
|
// Get services
|
||||||
|
let (inbound_service, _, mut tx_verifier, _peer_set, state_service) = setup(false).await;
|
||||||
|
|
||||||
|
// Push test transaction
|
||||||
|
let request = inbound_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(Request::PushTransaction(tx1.clone().into()));
|
||||||
|
// Simulate a successful transaction verification
|
||||||
|
let verification = tx_verifier.expect_request_that(|_| true).map(|responder| {
|
||||||
|
tx1_id = responder.request().tx_id();
|
||||||
|
responder.respond(tx1_id);
|
||||||
|
});
|
||||||
|
let (response, _) = futures::join!(request, verification);
|
||||||
|
match response {
|
||||||
|
Ok(Response::Nil) => (),
|
||||||
|
_ => unreachable!("`PushTransaction` requests should always respond `Ok(Nil)`"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use `Request::MempoolTransactionIds` to check the transaction was inserted to mempool
|
||||||
|
let request = inbound_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(Request::MempoolTransactionIds)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match request {
|
||||||
|
Ok(Response::TransactionIds(response)) => {
|
||||||
|
assert_eq!(response, vec![tx1_id])
|
||||||
|
}
|
||||||
|
_ => unreachable!(
|
||||||
|
"`MempoolTransactionIds` requests should always respond `Ok(Vec<UnminedTxId>)`"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a new block to the state (make the chain tip advance)
|
||||||
|
let block_one: Arc<Block> = zebra_test::vectors::BLOCK_MAINNET_2_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap();
|
||||||
|
state_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(zebra_state::Request::CommitFinalizedBlock(
|
||||||
|
block_one.clone().into(),
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Make sure tx1 is still in the mempool as it is not expired yet.
|
||||||
|
let request = inbound_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(Request::MempoolTransactionIds)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match request {
|
||||||
|
Ok(Response::TransactionIds(response)) => {
|
||||||
|
assert_eq!(response, vec![tx1_id])
|
||||||
|
}
|
||||||
|
_ => unreachable!(
|
||||||
|
"`MempoolTransactionIds` requests should always respond `Ok(Vec<UnminedTxId>)`"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// As our test transaction will expire at a block height greater or equal to 3 we need to push block 3.
|
||||||
|
let block_two: Arc<Block> = zebra_test::vectors::BLOCK_MAINNET_3_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap();
|
||||||
|
state_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(zebra_state::Request::CommitFinalizedBlock(
|
||||||
|
block_two.clone().into(),
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Push a second transaction to trigger `remove_expired_transactions()`
|
||||||
|
let request = inbound_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(Request::PushTransaction(tx2.clone().into()));
|
||||||
|
// Simulate a successful transaction verification
|
||||||
|
let verification = tx_verifier.expect_request_that(|_| true).map(|responder| {
|
||||||
|
tx2_id = responder.request().tx_id();
|
||||||
|
responder.respond(tx2_id);
|
||||||
|
});
|
||||||
|
let (response, _) = futures::join!(request, verification);
|
||||||
|
match response {
|
||||||
|
Ok(Response::Nil) => (),
|
||||||
|
_ => unreachable!("`PushTransaction` requests should always respond `Ok(Nil)`"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use `Request::MempoolTransactionIds` to check the transaction was inserted to mempool
|
||||||
|
let request = inbound_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(Request::MempoolTransactionIds)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// Only tx2 will be in the mempool while tx1 was expired
|
||||||
|
match request {
|
||||||
|
Ok(Response::TransactionIds(response)) => {
|
||||||
|
assert_eq!(response, vec![tx2_id])
|
||||||
|
}
|
||||||
|
_ => unreachable!(
|
||||||
|
"`MempoolTransactionIds` requests should always respond `Ok(Vec<UnminedTxId>)`"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add all the rest of the continous blocks we have to test tx2 will never expire.
|
||||||
|
let more_blocks: Vec<Arc<Block>> = vec![
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_4_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap(),
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_5_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap(),
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_6_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap(),
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_7_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap(),
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_8_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap(),
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_9_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap(),
|
||||||
|
zebra_test::vectors::BLOCK_MAINNET_10_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap(),
|
||||||
|
];
|
||||||
|
for block in more_blocks {
|
||||||
|
state_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(zebra_state::Request::CommitFinalizedBlock(
|
||||||
|
block.clone().into(),
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let request = inbound_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(Request::MempoolTransactionIds)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// tx2 is still in the mempool as the blockchain progress because the zero expiration height
|
||||||
|
match request {
|
||||||
|
Ok(Response::TransactionIds(response)) => {
|
||||||
|
assert_eq!(response, vec![tx2_id])
|
||||||
|
}
|
||||||
|
_ => unreachable!(
|
||||||
|
"`MempoolTransactionIds` requests should always respond `Ok(Vec<UnminedTxId>)`"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn setup(
|
async fn setup(
|
||||||
add_transactions: bool,
|
add_transactions: bool,
|
||||||
) -> (
|
) -> (
|
||||||
|
|
@ -180,6 +352,14 @@ async fn setup(
|
||||||
Option<Vec<UnminedTx>>,
|
Option<Vec<UnminedTx>>,
|
||||||
MockService<transaction::Request, transaction::Response, PanicAssertion, TransactionError>,
|
MockService<transaction::Request, transaction::Response, PanicAssertion, TransactionError>,
|
||||||
MockService<Request, Response, PanicAssertion>,
|
MockService<Request, Response, PanicAssertion>,
|
||||||
|
Buffer<
|
||||||
|
BoxService<
|
||||||
|
zebra_state::Request,
|
||||||
|
zebra_state::Response,
|
||||||
|
Box<dyn std::error::Error + Send + Sync>,
|
||||||
|
>,
|
||||||
|
zebra_state::Request,
|
||||||
|
>,
|
||||||
) {
|
) {
|
||||||
let network = Network::Mainnet;
|
let network = Network::Mainnet;
|
||||||
let consensus_config = ConsensusConfig::default();
|
let consensus_config = ConsensusConfig::default();
|
||||||
|
|
@ -187,7 +367,7 @@ async fn setup(
|
||||||
let address_book = AddressBook::new(SocketAddr::from_str("0.0.0.0:0").unwrap(), Span::none());
|
let address_book = AddressBook::new(SocketAddr::from_str("0.0.0.0:0").unwrap(), Span::none());
|
||||||
let address_book = Arc::new(std::sync::Mutex::new(address_book));
|
let address_book = Arc::new(std::sync::Mutex::new(address_book));
|
||||||
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
||||||
let (state, _latest_chain_tip, chain_tip_change) =
|
let (state, latest_chain_tip, chain_tip_change) =
|
||||||
zebra_state::init(state_config.clone(), network);
|
zebra_state::init(state_config.clone(), network);
|
||||||
|
|
||||||
let mut state_service = ServiceBuilder::new().buffer(1).service(state);
|
let mut state_service = ServiceBuilder::new().buffer(1).service(state);
|
||||||
|
|
@ -218,12 +398,27 @@ async fn setup(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Also push block 1.
|
||||||
|
// Block one is a network upgrade and the mempool will be cleared at it,
|
||||||
|
// let all our tests start after this event.
|
||||||
|
let block_one: Arc<Block> = zebra_test::vectors::BLOCK_MAINNET_1_BYTES
|
||||||
|
.zcash_deserialize_into()
|
||||||
|
.unwrap();
|
||||||
|
state_service
|
||||||
|
.clone()
|
||||||
|
.oneshot(zebra_state::Request::CommitFinalizedBlock(
|
||||||
|
block_one.clone().into(),
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut mempool_service = Mempool::new(
|
let mut mempool_service = Mempool::new(
|
||||||
network,
|
network,
|
||||||
buffered_peer_set.clone(),
|
buffered_peer_set.clone(),
|
||||||
state_service.clone(),
|
state_service.clone(),
|
||||||
buffered_tx_verifier.clone(),
|
buffered_tx_verifier.clone(),
|
||||||
sync_status,
|
sync_status,
|
||||||
|
latest_chain_tip,
|
||||||
chain_tip_change,
|
chain_tip_change,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -258,6 +453,7 @@ async fn setup(
|
||||||
added_transactions,
|
added_transactions,
|
||||||
mock_tx_verifier,
|
mock_tx_verifier,
|
||||||
peer_set,
|
peer_set,
|
||||||
|
state_service,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ use futures::{future::FutureExt, stream::Stream};
|
||||||
use tower::{buffer::Buffer, timeout::Timeout, util::BoxService, Service};
|
use tower::{buffer::Buffer, timeout::Timeout, util::BoxService, Service};
|
||||||
|
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
|
chain_tip::ChainTip,
|
||||||
parameters::Network,
|
parameters::Network,
|
||||||
transaction::{UnminedTx, UnminedTxId},
|
transaction::{UnminedTx, UnminedTxId},
|
||||||
};
|
};
|
||||||
|
|
@ -100,6 +101,8 @@ pub struct Mempool {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
sync_status: SyncStatus,
|
sync_status: SyncStatus,
|
||||||
|
|
||||||
|
/// Allow efficient access to the best tip of the blockchain.
|
||||||
|
latest_chain_tip: zs::LatestChainTip,
|
||||||
/// Allows the detection of chain tip resets.
|
/// Allows the detection of chain tip resets.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
chain_tip_change: ChainTipChange,
|
chain_tip_change: ChainTipChange,
|
||||||
|
|
@ -125,11 +128,13 @@ impl Mempool {
|
||||||
state: State,
|
state: State,
|
||||||
tx_verifier: TxVerifier,
|
tx_verifier: TxVerifier,
|
||||||
sync_status: SyncStatus,
|
sync_status: SyncStatus,
|
||||||
|
latest_chain_tip: zs::LatestChainTip,
|
||||||
chain_tip_change: ChainTipChange,
|
chain_tip_change: ChainTipChange,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Mempool {
|
Mempool {
|
||||||
active_state: ActiveState::Disabled,
|
active_state: ActiveState::Disabled,
|
||||||
sync_status,
|
sync_status,
|
||||||
|
latest_chain_tip,
|
||||||
chain_tip_change,
|
chain_tip_change,
|
||||||
outbound,
|
outbound,
|
||||||
state,
|
state,
|
||||||
|
|
@ -246,7 +251,7 @@ impl Service<Request> for Mempool {
|
||||||
storage.clear();
|
storage.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up completed download tasks and add to mempool if successful
|
// Clean up completed download tasks and add to mempool if successful.
|
||||||
while let Poll::Ready(Some(r)) = tx_downloads.as_mut().poll_next(cx) {
|
while let Poll::Ready(Some(r)) = tx_downloads.as_mut().poll_next(cx) {
|
||||||
if let Ok(tx) = r {
|
if let Ok(tx) = r {
|
||||||
// Storage handles conflicting transactions or a full mempool internally,
|
// Storage handles conflicting transactions or a full mempool internally,
|
||||||
|
|
@ -254,6 +259,11 @@ impl Service<Request> for Mempool {
|
||||||
let _ = storage.insert(tx);
|
let _ = storage.insert(tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove expired transactions from the mempool.
|
||||||
|
if let Some(tip_height) = self.latest_chain_tip.best_tip_height() {
|
||||||
|
remove_expired_transactions(storage, tip_height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ActiveState::Disabled => {
|
ActiveState::Disabled => {
|
||||||
// When the mempool is disabled we still return that the service is ready.
|
// When the mempool is disabled we still return that the service is ready.
|
||||||
|
|
@ -261,6 +271,7 @@ impl Service<Request> for Mempool {
|
||||||
// which may not be the desired behaviour.
|
// which may not be the desired behaviour.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,3 +333,22 @@ impl Service<Request> for Mempool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove transactions from the mempool if they have not been mined after a specified height.
|
||||||
|
///
|
||||||
|
/// https://zips.z.cash/zip-0203#specification
|
||||||
|
fn remove_expired_transactions(
|
||||||
|
storage: &mut storage::Storage,
|
||||||
|
tip_height: zebra_chain::block::Height,
|
||||||
|
) {
|
||||||
|
let ids = storage.tx_ids().iter().copied().collect();
|
||||||
|
let transactions = storage.transactions(ids);
|
||||||
|
|
||||||
|
for t in transactions {
|
||||||
|
if let Some(expiry_height) = t.transaction.expiry_height() {
|
||||||
|
if tip_height >= expiry_height {
|
||||||
|
storage.remove(&t.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ async fn mempool_service_basic() -> Result<(), Report> {
|
||||||
let state_config = StateConfig::ephemeral();
|
let state_config = StateConfig::ephemeral();
|
||||||
let peer_set = MockService::build().for_unit_tests();
|
let peer_set = MockService::build().for_unit_tests();
|
||||||
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
||||||
let (state, _latest_chain_tip, chain_tip_change) =
|
let (state, latest_chain_tip, chain_tip_change) =
|
||||||
zebra_state::init(state_config.clone(), network);
|
zebra_state::init(state_config.clone(), network);
|
||||||
|
|
||||||
let state_service = ServiceBuilder::new().buffer(1).service(state);
|
let state_service = ServiceBuilder::new().buffer(1).service(state);
|
||||||
|
|
@ -39,6 +39,7 @@ async fn mempool_service_basic() -> Result<(), Report> {
|
||||||
state_service.clone(),
|
state_service.clone(),
|
||||||
tx_verifier,
|
tx_verifier,
|
||||||
sync_status,
|
sync_status,
|
||||||
|
latest_chain_tip,
|
||||||
chain_tip_change,
|
chain_tip_change,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -136,7 +137,7 @@ async fn mempool_queue() -> Result<(), Report> {
|
||||||
let state_config = StateConfig::ephemeral();
|
let state_config = StateConfig::ephemeral();
|
||||||
let peer_set = MockService::build().for_unit_tests();
|
let peer_set = MockService::build().for_unit_tests();
|
||||||
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
||||||
let (state, _latest_chain_tip, chain_tip_change) =
|
let (state, latest_chain_tip, chain_tip_change) =
|
||||||
zebra_state::init(state_config.clone(), network);
|
zebra_state::init(state_config.clone(), network);
|
||||||
|
|
||||||
let state_service = ServiceBuilder::new().buffer(1).service(state);
|
let state_service = ServiceBuilder::new().buffer(1).service(state);
|
||||||
|
|
@ -165,6 +166,7 @@ async fn mempool_queue() -> Result<(), Report> {
|
||||||
state_service.clone(),
|
state_service.clone(),
|
||||||
tx_verifier,
|
tx_verifier,
|
||||||
sync_status,
|
sync_status,
|
||||||
|
latest_chain_tip,
|
||||||
chain_tip_change,
|
chain_tip_change,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -238,7 +240,7 @@ async fn mempool_service_disabled() -> Result<(), Report> {
|
||||||
let peer_set = MockService::build().for_unit_tests();
|
let peer_set = MockService::build().for_unit_tests();
|
||||||
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
let (sync_status, mut recent_syncs) = SyncStatus::new();
|
||||||
|
|
||||||
let (state, _latest_chain_tip, chain_tip_change) = zebra_state::init(state_config, network);
|
let (state, latest_chain_tip, chain_tip_change) = zebra_state::init(state_config, network);
|
||||||
let state_service = ServiceBuilder::new().buffer(1).service(state);
|
let state_service = ServiceBuilder::new().buffer(1).service(state);
|
||||||
let (_chain_verifier, tx_verifier) =
|
let (_chain_verifier, tx_verifier) =
|
||||||
zebra_consensus::chain::init(consensus_config.clone(), network, state_service.clone())
|
zebra_consensus::chain::init(consensus_config.clone(), network, state_service.clone())
|
||||||
|
|
@ -258,6 +260,7 @@ async fn mempool_service_disabled() -> Result<(), Report> {
|
||||||
state_service.clone(),
|
state_service.clone(),
|
||||||
tx_verifier,
|
tx_verifier,
|
||||||
sync_status,
|
sync_status,
|
||||||
|
latest_chain_tip,
|
||||||
chain_tip_change,
|
chain_tip_change,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue