zebra_rpc/methods/types/
get_raw_mempool.rs

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