cuprated/rpc/service/
txpool.rs

1//! Functions to send [`TxpoolReadRequest`]s.
2
3use std::{collections::HashSet, convert::Infallible, num::NonZero};
4
5use anyhow::{anyhow, Error};
6use monero_serai::transaction::Transaction;
7use tower::{Service, ServiceExt};
8
9use cuprate_helper::cast::usize_to_u64;
10use cuprate_rpc_types::misc::{SpentKeyImageInfo, TxInfo};
11use cuprate_txpool::{
12    service::{
13        interface::{TxpoolReadRequest, TxpoolReadResponse},
14        TxpoolReadHandle,
15    },
16    TxEntry,
17};
18use cuprate_types::{
19    rpc::{PoolInfo, PoolInfoFull, PoolInfoIncremental, PoolTxInfo, TxpoolStats},
20    TxInPool, TxRelayChecks,
21};
22
23// FIXME: use `anyhow::Error` over `tower::BoxError` in txpool.
24
25/// [`TxpoolReadRequest::Backlog`]
26pub async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result<Vec<TxEntry>, Error> {
27    let TxpoolReadResponse::Backlog(tx_entries) = txpool_read
28        .ready()
29        .await
30        .map_err(|e| anyhow!(e))?
31        .call(TxpoolReadRequest::Backlog)
32        .await
33        .map_err(|e| anyhow!(e))?
34    else {
35        unreachable!();
36    };
37
38    Ok(tx_entries)
39}
40
41/// [`TxpoolReadRequest::Size`]
42pub async fn size(
43    txpool_read: &mut TxpoolReadHandle,
44    include_sensitive_txs: bool,
45) -> Result<u64, Error> {
46    let TxpoolReadResponse::Size(size) = txpool_read
47        .ready()
48        .await
49        .map_err(|e| anyhow!(e))?
50        .call(TxpoolReadRequest::Size {
51            include_sensitive_txs,
52        })
53        .await
54        .map_err(|e| anyhow!(e))?
55    else {
56        unreachable!();
57    };
58
59    Ok(usize_to_u64(size))
60}
61
62/// [`TxpoolReadRequest::PoolInfo`]
63pub async fn pool_info(
64    txpool_read: &mut TxpoolReadHandle,
65    include_sensitive_txs: bool,
66    max_tx_count: usize,
67    start_time: Option<NonZero<usize>>,
68) -> Result<PoolInfo, Error> {
69    let TxpoolReadResponse::PoolInfo(pool_info) = txpool_read
70        .ready()
71        .await
72        .map_err(|e| anyhow!(e))?
73        .call(TxpoolReadRequest::PoolInfo {
74            include_sensitive_txs,
75            max_tx_count,
76            start_time,
77        })
78        .await
79        .map_err(|e| anyhow!(e))?
80    else {
81        unreachable!();
82    };
83
84    Ok(pool_info)
85}
86
87/// [`TxpoolReadRequest::TxsByHash`]
88pub async fn txs_by_hash(
89    txpool_read: &mut TxpoolReadHandle,
90    tx_hashes: Vec<[u8; 32]>,
91    include_sensitive_txs: bool,
92) -> Result<Vec<TxInPool>, Error> {
93    let TxpoolReadResponse::TxsByHash(txs_in_pool) = txpool_read
94        .ready()
95        .await
96        .map_err(|e| anyhow!(e))?
97        .call(TxpoolReadRequest::TxsByHash {
98            tx_hashes,
99            include_sensitive_txs,
100        })
101        .await
102        .map_err(|e| anyhow!(e))?
103    else {
104        unreachable!();
105    };
106
107    Ok(txs_in_pool)
108}
109
110/// [`TxpoolReadRequest::KeyImagesSpent`]
111pub async fn key_images_spent(
112    txpool_read: &mut TxpoolReadHandle,
113    key_images: HashSet<[u8; 32]>,
114    include_sensitive_txs: bool,
115) -> Result<bool, Error> {
116    let TxpoolReadResponse::KeyImagesSpent(status) = txpool_read
117        .ready()
118        .await
119        .map_err(|e| anyhow!(e))?
120        .call(TxpoolReadRequest::KeyImagesSpent {
121            key_images,
122            include_sensitive_txs,
123        })
124        .await
125        .map_err(|e| anyhow!(e))?
126    else {
127        unreachable!();
128    };
129
130    Ok(status)
131}
132
133/// [`TxpoolReadRequest::KeyImagesSpentVec`]
134pub async fn key_images_spent_vec(
135    txpool_read: &mut TxpoolReadHandle,
136    key_images: Vec<[u8; 32]>,
137    include_sensitive_txs: bool,
138) -> Result<Vec<bool>, Error> {
139    let TxpoolReadResponse::KeyImagesSpentVec(status) = txpool_read
140        .ready()
141        .await
142        .map_err(|e| anyhow!(e))?
143        .call(TxpoolReadRequest::KeyImagesSpentVec {
144            key_images,
145            include_sensitive_txs,
146        })
147        .await
148        .map_err(|e| anyhow!(e))?
149    else {
150        unreachable!();
151    };
152
153    Ok(status)
154}
155
156/// [`TxpoolReadRequest::Pool`]
157pub async fn pool(
158    txpool_read: &mut TxpoolReadHandle,
159    include_sensitive_txs: bool,
160) -> Result<(Vec<TxInfo>, Vec<SpentKeyImageInfo>), Error> {
161    let TxpoolReadResponse::Pool {
162        txs,
163        spent_key_images,
164    } = txpool_read
165        .ready()
166        .await
167        .map_err(|e| anyhow!(e))?
168        .call(TxpoolReadRequest::Pool {
169            include_sensitive_txs,
170        })
171        .await
172        .map_err(|e| anyhow!(e))?
173    else {
174        unreachable!();
175    };
176
177    let txs = txs.into_iter().map(Into::into).collect();
178    let spent_key_images = spent_key_images.into_iter().map(Into::into).collect();
179
180    Ok((txs, spent_key_images))
181}
182
183/// [`TxpoolReadRequest::PoolStats`]
184pub async fn pool_stats(
185    txpool_read: &mut TxpoolReadHandle,
186    include_sensitive_txs: bool,
187) -> Result<TxpoolStats, Error> {
188    let TxpoolReadResponse::PoolStats(txpool_stats) = txpool_read
189        .ready()
190        .await
191        .map_err(|e| anyhow!(e))?
192        .call(TxpoolReadRequest::PoolStats {
193            include_sensitive_txs,
194        })
195        .await
196        .map_err(|e| anyhow!(e))?
197    else {
198        unreachable!();
199    };
200
201    Ok(txpool_stats)
202}
203
204/// [`TxpoolReadRequest::AllHashes`]
205pub async fn all_hashes(
206    txpool_read: &mut TxpoolReadHandle,
207    include_sensitive_txs: bool,
208) -> Result<Vec<[u8; 32]>, Error> {
209    let TxpoolReadResponse::AllHashes(hashes) = txpool_read
210        .ready()
211        .await
212        .map_err(|e| anyhow!(e))?
213        .call(TxpoolReadRequest::AllHashes {
214            include_sensitive_txs,
215        })
216        .await
217        .map_err(|e| anyhow!(e))?
218    else {
219        unreachable!();
220    };
221
222    Ok(hashes)
223}
224
225/// TODO: impl txpool manager.
226pub async fn flush(txpool_manager: &mut Infallible, tx_hashes: Vec<[u8; 32]>) -> Result<(), Error> {
227    todo!();
228    Ok(())
229}
230
231/// TODO: impl txpool manager.
232pub async fn relay(txpool_manager: &mut Infallible, tx_hashes: Vec<[u8; 32]>) -> Result<(), Error> {
233    todo!();
234    Ok(())
235}
236
237/// TODO: impl txpool manager.
238pub async fn check_maybe_relay_local(
239    txpool_manager: &mut Infallible,
240    tx: Transaction,
241    relay: bool,
242) -> Result<TxRelayChecks, Error> {
243    Ok(todo!())
244}