zebra_rpc/methods/types/
get_raw_mempool.rs

1//! Types used in `getrawmempool` RPC method.
2
3use std::collections::{HashMap, HashSet};
4
5use hex::ToHex as _;
6
7use zebra_chain::{amount::NonNegative, block::Height, transaction::VerifiedUnminedTx};
8use zebra_node_services::mempool::TransactionDependencies;
9
10use super::zec::Zec;
11
12/// Response to a `getrawmempool` RPC request.
13///
14/// See the notes for the [`Rpc::get_raw_mempool` method].
15#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
16#[serde(untagged)]
17pub enum GetRawMempool {
18    /// The transaction IDs, as hex strings (verbose=0)
19    TxIds(Vec<String>),
20    /// A map of transaction IDs to mempool transaction details objects
21    /// (verbose=1)
22    Verbose(HashMap<String, MempoolObject>),
23}
24
25/// A mempool transaction details object as returned by `getrawmempool` in
26/// verbose mode.
27#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
28pub struct MempoolObject {
29    /// Transaction size in bytes.
30    pub(crate) size: u64,
31    /// Transaction fee in zatoshi.
32    pub(crate) fee: Zec<NonNegative>,
33    /// Transaction fee with fee deltas used for mining priority.
34    #[serde(rename = "modifiedfee")]
35    pub(crate) modified_fee: Zec<NonNegative>,
36    /// Local time transaction entered pool in seconds since 1 Jan 1970 GMT
37    pub(crate) time: i64,
38    /// Block height when transaction entered pool.
39    pub(crate) height: Height,
40    /// Number of in-mempool descendant transactions (including this one).
41    pub(crate) descendantcount: u64,
42    /// Size of in-mempool descendants (including this one).
43    pub(crate) descendantsize: u64,
44    /// Modified fees (see "modifiedfee" above) of in-mempool descendants
45    /// (including this one).
46    pub(crate) descendantfees: u64,
47    /// Transaction IDs of unconfirmed transactions used as inputs for this
48    /// transaction.
49    pub(crate) depends: Vec<String>,
50}
51
52impl MempoolObject {
53    pub(crate) fn from_verified_unmined_tx(
54        unmined_tx: &VerifiedUnminedTx,
55        transactions: &[VerifiedUnminedTx],
56        transaction_dependencies: &TransactionDependencies,
57    ) -> Self {
58        // Map transactions by their txids to make lookups easier
59        let transactions_by_id = transactions
60            .iter()
61            .map(|unmined_tx| (unmined_tx.transaction.id.mined_id(), unmined_tx))
62            .collect::<HashMap<_, _>>();
63
64        // Get txids of this transaction's descendants (dependents)
65        let empty_set = HashSet::new();
66        let deps = transaction_dependencies
67            .dependents()
68            .get(&unmined_tx.transaction.id.mined_id())
69            .unwrap_or(&empty_set);
70        let deps_len = deps.len();
71
72        // For each dependent: get the tx, then its size and fee; then sum them
73        // up
74        let (deps_size, deps_fees) = deps
75            .iter()
76            .filter_map(|id| transactions_by_id.get(id))
77            .map(|unmined_tx| (unmined_tx.transaction.size, unmined_tx.miner_fee))
78            .reduce(|(size1, fee1), (size2, fee2)| {
79                (size1 + size2, (fee1 + fee2).unwrap_or_default())
80            })
81            .unwrap_or((0, Default::default()));
82
83        // Create the MempoolObject from the information we have gathered
84        let mempool_object = MempoolObject {
85            size: unmined_tx.transaction.size as u64,
86            fee: unmined_tx.miner_fee.into(),
87            // Change this if we ever support fee deltas (prioritisetransaction call)
88            modified_fee: unmined_tx.miner_fee.into(),
89            time: unmined_tx
90                .time
91                .map(|time| time.timestamp())
92                .unwrap_or_default(),
93            height: unmined_tx.height.unwrap_or(Height(0)),
94            // Note that the following three count this transaction itself
95            descendantcount: deps_len as u64 + 1,
96            descendantsize: (deps_size + unmined_tx.transaction.size) as u64,
97            descendantfees: (deps_fees + unmined_tx.miner_fee)
98                .unwrap_or_default()
99                .into(),
100            // Get dependencies as a txid vector
101            depends: transaction_dependencies
102                .dependencies()
103                .get(&unmined_tx.transaction.id.mined_id())
104                .cloned()
105                .unwrap_or_else(HashSet::new)
106                .iter()
107                .map(|id| id.encode_hex())
108                .collect(),
109        };
110        mempool_object
111    }
112}