zebra_node_services/
mempool.rs

1//! The Zebra mempool.
2//!
3//! A service that manages known unmined Zcash transactions.
4
5use std::collections::HashSet;
6
7use tokio::sync::oneshot;
8use zebra_chain::{
9    transaction::{self, UnminedTx, UnminedTxId, VerifiedUnminedTx},
10    transparent,
11};
12
13use crate::BoxError;
14
15mod gossip;
16mod mempool_change;
17mod transaction_dependencies;
18
19pub use self::{
20    gossip::Gossip,
21    mempool_change::{MempoolChange, MempoolChangeKind, MempoolTxSubscriber},
22    transaction_dependencies::TransactionDependencies,
23};
24
25/// A mempool service request.
26///
27/// Requests can query the current set of mempool transactions,
28/// queue transactions to be downloaded and verified, or
29/// run the mempool to check for newly verified transactions.
30///
31/// Requests can't modify the mempool directly,
32/// because all mempool transactions must be verified.
33#[derive(Debug, Eq, PartialEq)]
34pub enum Request {
35    /// Query all [`UnminedTxId`]s in the mempool.
36    TransactionIds,
37
38    /// Query matching [`UnminedTx`] in the mempool,
39    /// using a unique set of [`UnminedTxId`]s.
40    TransactionsById(HashSet<UnminedTxId>),
41
42    /// Query matching [`UnminedTx`] in the mempool,
43    /// using a unique set of [`transaction::Hash`]es. Pre-V5 transactions are matched
44    /// directly; V5 transaction are matched just by the Hash, disregarding
45    /// the [`AuthDigest`](zebra_chain::transaction::AuthDigest).
46    TransactionsByMinedId(HashSet<transaction::Hash>),
47
48    /// Request a [`transparent::Output`] identified by the given [`OutPoint`](transparent::OutPoint),
49    /// waiting until it becomes available if it is unknown.
50    ///
51    /// This request is purely informational, and there are no guarantees about
52    /// whether the UTXO remains unspent or is on the best chain, or any chain.
53    /// Its purpose is to allow orphaned mempool transaction verification.
54    ///
55    /// # Correctness
56    ///
57    /// Output requests should be wrapped in a timeout, so that
58    /// out-of-order and invalid requests do not hang indefinitely.
59    ///
60    /// Outdated requests are pruned on a regular basis.
61    AwaitOutput(transparent::OutPoint),
62
63    /// Request a [`VerifiedUnminedTx`] and its dependencies by its mined id.
64    TransactionWithDepsByMinedId(transaction::Hash),
65
66    /// Get all the [`VerifiedUnminedTx`] in the mempool.
67    ///
68    /// Equivalent to `TransactionsById(TransactionIds)`,
69    /// but each transaction also includes the `miner_fee` and `legacy_sigop_count` fields.
70    //
71    // TODO: make the Transactions response return VerifiedUnminedTx,
72    //       and remove the FullTransactions variant
73    FullTransactions,
74
75    /// Query matching cached rejected transaction IDs in the mempool,
76    /// using a unique set of [`UnminedTxId`]s.
77    RejectedTransactionIds(HashSet<UnminedTxId>),
78
79    /// Queue a list of gossiped transactions or transaction IDs, or
80    /// crawled transaction IDs.
81    ///
82    /// The transaction downloader checks for duplicates across IDs and transactions.
83    Queue(Vec<Gossip>),
84
85    /// Check for newly verified transactions.
86    ///
87    /// The transaction downloader does not push transactions into the mempool.
88    /// So a task should send this request regularly (every 5-10 seconds).
89    ///
90    /// These checks also happen for other request variants,
91    /// but we can't rely on peers to send queries regularly,
92    /// and crawler queue requests depend on peer responses.
93    /// Also, crawler requests aren't frequent enough for transaction propagation.
94    ///
95    /// # Correctness
96    ///
97    /// This request is required to avoid hangs in the mempool.
98    ///
99    /// The queue checker task can't call `poll_ready` directly on the mempool
100    /// service, because the service is wrapped in a `Buffer`. Calling
101    /// `Buffer::poll_ready` reserves a buffer slot, which can cause hangs
102    /// when too many slots are reserved but unused:
103    /// <https://docs.rs/tower/0.4.10/tower/buffer/struct.Buffer.html#a-note-on-choosing-a-bound>
104    CheckForVerifiedTransactions,
105}
106
107/// A response to a mempool service request.
108///
109/// Responses can read the current set of mempool transactions,
110/// check the queued status of transactions to be downloaded and verified, or
111/// confirm that the mempool has been checked for newly verified transactions.
112#[derive(Debug)]
113pub enum Response {
114    /// Returns all [`UnminedTxId`]s from the mempool.
115    TransactionIds(HashSet<UnminedTxId>),
116
117    /// Returns matching [`UnminedTx`] from the mempool.
118    ///
119    /// Since the [`Request::TransactionsById`] request is unique,
120    /// the response transactions are also unique. The same applies to
121    /// [`Request::TransactionsByMinedId`] requests, since the mempool does not allow
122    /// different transactions with different mined IDs.
123    Transactions(Vec<UnminedTx>),
124
125    /// Response to [`Request::AwaitOutput`] with the transparent output
126    UnspentOutput(transparent::Output),
127
128    /// Response to [`Request::TransactionWithDepsByMinedId`].
129    TransactionWithDeps {
130        /// The queried transaction
131        transaction: VerifiedUnminedTx,
132        /// A list of dependencies of the queried transaction.
133        dependencies: HashSet<transaction::Hash>,
134    },
135
136    /// Returns all [`VerifiedUnminedTx`] in the mempool.
137    //
138    // TODO: make the Transactions response return VerifiedUnminedTx,
139    //       and remove the FullTransactions variant
140    FullTransactions {
141        /// All [`VerifiedUnminedTx`]s in the mempool
142        transactions: Vec<VerifiedUnminedTx>,
143
144        /// All transaction dependencies in the mempool
145        transaction_dependencies: TransactionDependencies,
146
147        /// Last seen chain tip hash by mempool service
148        last_seen_tip_hash: zebra_chain::block::Hash,
149    },
150
151    /// Returns matching cached rejected [`UnminedTxId`]s from the mempool,
152    RejectedTransactionIds(HashSet<UnminedTxId>),
153
154    /// Returns a list of initial queue checks results and a oneshot receiver
155    /// for awaiting download and/or verification results.
156    ///
157    /// Each result matches the request at the corresponding vector index.
158    Queued(Vec<Result<oneshot::Receiver<Result<(), BoxError>>, BoxError>>),
159
160    /// Confirms that the mempool has checked for recently verified transactions.
161    CheckedForVerifiedTransactions,
162}