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

add(mempool): Verify orphaned mempool transactions #8857

Open
wants to merge 53 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
fde3370
Adds a parameter to `zebra_consensus::router::init()` for accepting a…
arya2 Sep 4, 2024
85fdd88
Adds a `mempool` argument to the transaction::Verifier constructor (a…
arya2 Sep 4, 2024
174f4ea
Removes `Clone` impl on `transaction::Verifier` to add mempool onesho…
arya2 Sep 4, 2024
3c05b03
Adds TODOs
arya2 Sep 4, 2024
77aa2e3
updates transaction verifier's poll_ready() method to setup the mempo…
arya2 Sep 7, 2024
5c7f45b
Updates VerifiedSet struct used in mempool storage
arya2 Sep 7, 2024
ecc2ddd
Updates mempool service and its `Storage` to use the updated `Verifie…
arya2 Sep 7, 2024
e60197c
updates `created_outputs` when inserting or removing a transaction fr…
arya2 Sep 7, 2024
745e6a7
Adds a TODO, updates field docs
arya2 Sep 7, 2024
c9c0a11
Updates `spent_utxos()` to query the mempool for unspent outputs
arya2 Sep 7, 2024
cbb34e6
Adds `spent_mempool_outpoints` as a field on tx verifier mempool resp…
arya2 Sep 7, 2024
be6fd7b
Updates mempool `Downloads` to return the spent_mempool_outpoints fro…
arya2 Sep 7, 2024
90812b1
Updates `Storage.insert()` to accept a list of spent mempool transact…
arya2 Sep 7, 2024
d0b2d41
Adds transaction dependencies when inserting a tx in `VerifiedSet`
arya2 Sep 7, 2024
0a72b41
polls mempool svc from tx verifier when a mempool tx that creates tra…
arya2 Sep 7, 2024
2fc7829
Adds `pending_outputs` field on mempool Storage and responds to pendi…
arya2 Sep 7, 2024
ae87a27
replaces `UnminedTxId` type with `transaction::Hash` in mempool's ver…
arya2 Sep 16, 2024
61e6e21
prune pending outputs when rejecting and removing same effects.
arya2 Sep 16, 2024
bebe50e
Remove dependent transactions from verified set when removing a tx
arya2 Sep 16, 2024
29654b4
updates tests
arya2 Sep 16, 2024
aed637a
appeases clippy.
arya2 Sep 16, 2024
a838934
removes unused `len()` method
arya2 Sep 16, 2024
695a258
fixes doc links
arya2 Sep 16, 2024
bc981c0
Adds transaction dependencies to the `FullTransactions` response, let…
arya2 Sep 16, 2024
520660f
updates block template construction to avoid including transactions u…
arya2 Sep 17, 2024
b520d7b
updates tests
arya2 Sep 17, 2024
6c233f4
Replaces placeholder setup channel with one that sends the mempool sv…
arya2 Sep 17, 2024
56ae48f
Use a single query to check for unspent outputs in the mempool
arya2 Sep 17, 2024
05724ae
Updates `getblocktemplate` method to consider dependencies when sorti…
arya2 Sep 20, 2024
71a9c1b
fixes clippy lints, removes unnecessary Option in UnspentOutput respo…
arya2 Sep 23, 2024
310c320
renames type alias and method, adds a TODO to use iteration instead o…
arya2 Sep 23, 2024
40b6647
Adds mempool_removes_dependent_transactions() test
arya2 Sep 23, 2024
319ea7a
Updates Storage and VerifiedSet clear() methods to clear pending_outp…
arya2 Sep 24, 2024
475e286
removes outdated TODO
arya2 Sep 24, 2024
0ec768e
Adds a TODO for reporting queued transaction verification results fro…
arya2 Sep 24, 2024
2fb532f
Adds `mempool_responds_to_await_output` test
arya2 Sep 24, 2024
c4ec52d
updates mempool_responds_to_await_output test
arya2 Sep 24, 2024
8e118fc
Uses iteration instead of recursion in verified set's remove() method…
arya2 Sep 24, 2024
58fd7b3
Adds a mempool_request_with_mempool_output_is_accepted test for the t…
arya2 Sep 24, 2024
65fc0f8
Moves delay duration before polling the mempool to a constant, uses a…
arya2 Sep 24, 2024
5ff2da3
adds long_poll_input_mempool_tx_ids_are_sorted test
arya2 Sep 25, 2024
c72197c
Adds a `excludes_tx_with_unselected_dependencies` test
arya2 Sep 25, 2024
f93ca22
Updates a TODO
arya2 Sep 25, 2024
f44e640
moves `TransactionDependencies` struct to `zebra-node-services`
arya2 Sep 26, 2024
e195970
Updates `FullTransactions` response variant's `transaction_dependenci…
arya2 Sep 26, 2024
ddea848
updates zip317 transaction selection for block templates to include d…
arya2 Sep 27, 2024
dceaf87
Moves and refactors zip317 tx selection test to its own module, adds …
arya2 Sep 27, 2024
c2e5858
Removes `unmined_transactions_in_blocks()` test utility fn from memp…
arya2 Sep 27, 2024
fa9d89b
Fixes spelling mistake
arya2 Sep 27, 2024
dbcfafc
Adds `includes_tx_with_selected_dependencies` test
arya2 Sep 27, 2024
66b841e
fixes zip317 block construction issue
arya2 Sep 30, 2024
2342d75
Fixes vectors test
arya2 Sep 30, 2024
56f2ad4
Update zebra-node-services/src/mempool.rs
arya2 Oct 1, 2024
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
43 changes: 41 additions & 2 deletions zebra-chain/src/tests/vectors.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
//! Network methods for fetching blockchain vectors.
//!

use std::collections::BTreeMap;
use std::{collections::BTreeMap, ops::RangeBounds};

use crate::{block::Block, parameters::Network, serialization::ZcashDeserializeInto};
use crate::{
amount::Amount,
block::Block,
parameters::Network,
serialization::ZcashDeserializeInto,
transaction::{UnminedTx, VerifiedUnminedTx},
};

use zebra_test::vectors::{
BLOCK_MAINNET_1046400_BYTES, BLOCK_MAINNET_653599_BYTES, BLOCK_MAINNET_982681_BYTES,
Expand All @@ -30,6 +36,39 @@ impl Network {
}
}

/// Returns iterator over verified unmined transactions in the provided block height range.
pub fn unmined_transactions_in_blocks(
&self,
block_height_range: impl RangeBounds<u32>,
) -> impl DoubleEndedIterator<Item = VerifiedUnminedTx> {
let blocks = self.block_iter();

// 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::<Block>()
.expect("block test vector is structurally valid")
});

// Extract the transactions from the blocks and wrap each one as an unmined transaction.
// Use a fake zero miner fee and sigops, because we don't have the UTXOs to calculate
// the correct fee.
selected_blocks
.flat_map(|block| block.transactions)
.map(UnminedTx::from)
// Skip transactions that fail ZIP-317 mempool checks
.filter_map(|transaction| {
VerifiedUnminedTx::new(
transaction,
Amount::try_from(1_000_000).expect("invalid value"),
0,
)
.ok()
})
}

/// Returns blocks indexed by height in a [`BTreeMap`].
///
/// Returns Mainnet blocks if `self` is set to Mainnet, and Testnet blocks otherwise.
Expand Down
2 changes: 1 addition & 1 deletion zebra-consensus/src/block/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ async fn check_transcripts() -> Result<(), Report> {
let network = Network::Mainnet;
let state_service = zebra_state::init_test(&network);

let transaction = transaction::Verifier::new(&network, state_service.clone());
let transaction = transaction::Verifier::new_for_tests(&network, state_service.clone());
let transaction = Buffer::new(BoxService::new(transaction), 1);
let block_verifier = Buffer::new(
SemanticBlockVerifier::new(&network, state_service.clone(), transaction),
Expand Down
48 changes: 44 additions & 4 deletions zebra-consensus/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::{

use futures::{FutureExt, TryFutureExt};
use thiserror::Error;
use tokio::task::JoinHandle;
use tokio::{sync::oneshot, task::JoinHandle};
use tower::{buffer::Buffer, util::BoxService, Service, ServiceExt};
use tracing::{instrument, Instrument, Span};

Expand All @@ -30,6 +30,7 @@ use zebra_chain::{
parameters::Network,
};

use zebra_node_services::mempool;
use zebra_state as zs;

use crate::{
Expand Down Expand Up @@ -230,11 +231,12 @@ where
/// Block and transaction verification requests should be wrapped in a timeout,
/// so that out-of-order and invalid requests do not hang indefinitely.
/// See the [`router`](`crate::router`) module documentation for details.
#[instrument(skip(state_service))]
pub async fn init<S>(
#[instrument(skip(state_service, mempool))]
pub async fn init<S, Mempool>(
config: Config,
network: &Network,
mut state_service: S,
mempool: oneshot::Receiver<Mempool>,
) -> (
Buffer<BoxService<Request, block::Hash, RouterError>, Request>,
Buffer<
Expand All @@ -247,6 +249,11 @@ pub async fn init<S>(
where
S: Service<zs::Request, Response = zs::Response, Error = BoxError> + Send + Clone + 'static,
S::Future: Send + 'static,
Mempool: Service<mempool::Request, Response = mempool::Response, Error = BoxError>
+ Send
+ Clone
+ 'static,
Mempool::Future: Send + 'static,
{
// Give other tasks priority before spawning the checkpoint task.
tokio::task::yield_now().await;
Expand Down Expand Up @@ -333,7 +340,7 @@ where

// transaction verification

let transaction = transaction::Verifier::new(network, state_service.clone());
let transaction = transaction::Verifier::new(network, state_service.clone(), mempool);
let transaction = Buffer::new(BoxService::new(transaction), VERIFIER_BUFFER_BOUND);

// block verification
Expand Down Expand Up @@ -397,3 +404,36 @@ pub struct BackgroundTaskHandles {
/// Finishes when all the checkpoints are verified, or when the state tip is reached.
pub state_checkpoint_verify_handle: JoinHandle<()>,
}

/// Calls [`init`] with a closed mempool setup channel for conciseness in tests.
///
/// See [`init`] for more details.
#[cfg(any(test, feature = "proptest-impl"))]
pub async fn init_test<S>(
config: Config,
network: &Network,
state_service: S,
) -> (
Buffer<BoxService<Request, block::Hash, RouterError>, Request>,
Buffer<
BoxService<transaction::Request, transaction::Response, TransactionError>,
transaction::Request,
>,
BackgroundTaskHandles,
Height,
)
where
S: Service<zs::Request, Response = zs::Response, Error = BoxError> + Send + Clone + 'static,
S::Future: Send + 'static,
{
init(
config.clone(),
network,
state_service.clone(),
oneshot::channel::<
Buffer<BoxService<mempool::Request, mempool::Response, BoxError>, mempool::Request>,
>()
.1,
)
.await
}
4 changes: 2 additions & 2 deletions zebra-consensus/src/router/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ async fn verifiers_from_network(
_transaction_verifier,
_groth16_download_handle,
_max_checkpoint_height,
) = crate::router::init(Config::default(), &network, state_service.clone()).await;
) = crate::router::init_test(Config::default(), &network, state_service.clone()).await;

// We can drop the download task handle here, because:
// - if the download task fails, the tests will panic, and
Expand Down Expand Up @@ -169,7 +169,7 @@ async fn verify_checkpoint(config: Config) -> Result<(), Report> {
_transaction_verifier,
_groth16_download_handle,
_max_checkpoint_height,
) = super::init(config.clone(), &network, zs::init_test(&network)).await;
) = super::init_test(config.clone(), &network, zs::init_test(&network)).await;

// Add a timeout layer
let block_verifier_router =
Expand Down
Loading
Loading