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 /// Request summary statistics from the mempool for `getmempoolinfo`.
107 QueueStats,
108}
109
110/// A response to a mempool service request.
111///
112/// Responses can read the current set of mempool transactions,
113/// check the queued status of transactions to be downloaded and verified, or
114/// confirm that the mempool has been checked for newly verified transactions.
115#[derive(Debug)]
116pub enum Response {
117 /// Returns all [`UnminedTxId`]s from the mempool.
118 TransactionIds(HashSet<UnminedTxId>),
119
120 /// Returns matching [`UnminedTx`] from the mempool.
121 ///
122 /// Since the [`Request::TransactionsById`] request is unique,
123 /// the response transactions are also unique. The same applies to
124 /// [`Request::TransactionsByMinedId`] requests, since the mempool does not allow
125 /// different transactions with different mined IDs.
126 Transactions(Vec<UnminedTx>),
127
128 /// Response to [`Request::AwaitOutput`] with the transparent output
129 UnspentOutput(transparent::Output),
130
131 /// Response to [`Request::TransactionWithDepsByMinedId`].
132 TransactionWithDeps {
133 /// The queried transaction
134 transaction: VerifiedUnminedTx,
135 /// A list of dependencies of the queried transaction.
136 dependencies: HashSet<transaction::Hash>,
137 },
138
139 /// Returns all [`VerifiedUnminedTx`] in the mempool.
140 //
141 // TODO: make the Transactions response return VerifiedUnminedTx,
142 // and remove the FullTransactions variant
143 FullTransactions {
144 /// All [`VerifiedUnminedTx`]s in the mempool
145 transactions: Vec<VerifiedUnminedTx>,
146
147 /// All transaction dependencies in the mempool
148 transaction_dependencies: TransactionDependencies,
149
150 /// Last seen chain tip hash by mempool service
151 last_seen_tip_hash: zebra_chain::block::Hash,
152 },
153
154 /// Returns matching cached rejected [`UnminedTxId`]s from the mempool,
155 RejectedTransactionIds(HashSet<UnminedTxId>),
156
157 /// Returns a list of initial queue checks results and a oneshot receiver
158 /// for awaiting download and/or verification results.
159 ///
160 /// Each result matches the request at the corresponding vector index.
161 Queued(Vec<Result<oneshot::Receiver<Result<(), BoxError>>, BoxError>>),
162
163 /// Confirms that the mempool has checked for recently verified transactions.
164 CheckedForVerifiedTransactions,
165
166 /// Summary statistics for the mempool: count, total size, memory usage, and regtest info.
167 QueueStats {
168 /// Number of transactions currently in the mempool
169 size: usize,
170 /// Total size in bytes of all transactions
171 bytes: usize,
172 /// Estimated memory usage in bytes
173 usage: usize,
174 /// Whether all transactions have been fully notified (regtest only)
175 fully_notified: Option<bool>,
176 },
177}