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