cuprated/rpc/service/
blockchain_manager.rs

1//! Functions to send [`BlockchainManagerRequest`]s.
2
3use anyhow::Error;
4use monero_serai::block::Block;
5use tower::{Service, ServiceExt};
6
7use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
8use cuprate_p2p_core::{types::ConnectionId, NetworkZone};
9use cuprate_pruning::PruningSeed;
10use cuprate_rpc_types::misc::Span;
11use cuprate_types::BlockTemplate;
12
13use crate::rpc::rpc_handler::{
14    BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse,
15};
16
17/// [`BlockchainManagerRequest::PopBlocks`]
18pub async fn pop_blocks(
19    blockchain_manager: &mut BlockchainManagerHandle,
20    amount: u64,
21) -> Result<u64, Error> {
22    let BlockchainManagerResponse::PopBlocks { new_height } = blockchain_manager
23        .ready()
24        .await?
25        .call(BlockchainManagerRequest::PopBlocks {
26            amount: u64_to_usize(amount),
27        })
28        .await?
29    else {
30        unreachable!();
31    };
32
33    Ok(usize_to_u64(new_height))
34}
35
36/// [`BlockchainManagerRequest::Prune`]
37pub async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> Result<PruningSeed, Error> {
38    let BlockchainManagerResponse::Prune(seed) = blockchain_manager
39        .ready()
40        .await?
41        .call(BlockchainManagerRequest::Prune)
42        .await?
43    else {
44        unreachable!();
45    };
46
47    Ok(seed)
48}
49
50/// [`BlockchainManagerRequest::Pruned`]
51pub async fn pruned(blockchain_manager: &mut BlockchainManagerHandle) -> Result<bool, Error> {
52    let BlockchainManagerResponse::Pruned(pruned) = blockchain_manager
53        .ready()
54        .await?
55        .call(BlockchainManagerRequest::Pruned)
56        .await?
57    else {
58        unreachable!();
59    };
60
61    Ok(pruned)
62}
63
64/// [`BlockchainManagerRequest::RelayBlock`]
65pub async fn relay_block(
66    blockchain_manager: &mut BlockchainManagerHandle,
67    block: Box<Block>,
68) -> Result<(), Error> {
69    let BlockchainManagerResponse::Ok = blockchain_manager
70        .ready()
71        .await?
72        .call(BlockchainManagerRequest::RelayBlock(block))
73        .await?
74    else {
75        unreachable!();
76    };
77
78    Ok(())
79}
80
81/// [`BlockchainManagerRequest::Syncing`]
82pub async fn syncing(blockchain_manager: &mut BlockchainManagerHandle) -> Result<bool, Error> {
83    let BlockchainManagerResponse::Syncing(syncing) = blockchain_manager
84        .ready()
85        .await?
86        .call(BlockchainManagerRequest::Syncing)
87        .await?
88    else {
89        unreachable!();
90    };
91
92    Ok(syncing)
93}
94
95/// [`BlockchainManagerRequest::Synced`]
96pub async fn synced(blockchain_manager: &mut BlockchainManagerHandle) -> Result<bool, Error> {
97    let BlockchainManagerResponse::Synced(syncing) = blockchain_manager
98        .ready()
99        .await?
100        .call(BlockchainManagerRequest::Synced)
101        .await?
102    else {
103        unreachable!();
104    };
105
106    Ok(syncing)
107}
108
109/// [`BlockchainManagerRequest::Target`]
110pub async fn target(
111    blockchain_manager: &mut BlockchainManagerHandle,
112) -> Result<std::time::Duration, Error> {
113    let BlockchainManagerResponse::Target(target) = blockchain_manager
114        .ready()
115        .await?
116        .call(BlockchainManagerRequest::Target)
117        .await?
118    else {
119        unreachable!();
120    };
121
122    Ok(target)
123}
124
125/// [`BlockchainManagerRequest::TargetHeight`]
126pub async fn target_height(blockchain_manager: &mut BlockchainManagerHandle) -> Result<u64, Error> {
127    let BlockchainManagerResponse::TargetHeight { height } = blockchain_manager
128        .ready()
129        .await?
130        .call(BlockchainManagerRequest::TargetHeight)
131        .await?
132    else {
133        unreachable!();
134    };
135
136    Ok(usize_to_u64(height))
137}
138
139/// [`BlockchainManagerRequest::GenerateBlocks`]
140pub async fn generate_blocks(
141    blockchain_manager: &mut BlockchainManagerHandle,
142    amount_of_blocks: u64,
143    prev_block: Option<[u8; 32]>,
144    starting_nonce: u32,
145    wallet_address: String,
146) -> Result<(Vec<[u8; 32]>, u64), Error> {
147    let BlockchainManagerResponse::GenerateBlocks { blocks, height } = blockchain_manager
148        .ready()
149        .await?
150        .call(BlockchainManagerRequest::GenerateBlocks {
151            amount_of_blocks,
152            prev_block,
153            starting_nonce,
154            wallet_address,
155        })
156        .await?
157    else {
158        unreachable!();
159    };
160
161    Ok((blocks, usize_to_u64(height)))
162}
163
164// [`BlockchainManagerRequest::Spans`]
165pub async fn spans<Z: NetworkZone>(
166    blockchain_manager: &mut BlockchainManagerHandle,
167) -> Result<Vec<Span>, Error> {
168    // let BlockchainManagerResponse::Spans(vec) = blockchain_manager
169    //     .ready()
170    //     .await?
171    //     .call(BlockchainManagerRequest::Spans)
172    //     .await?
173    // else {
174    //     unreachable!();
175    // };
176
177    let vec: Vec<cuprate_p2p_core::types::Span<Z::Addr>> =
178        todo!("waiting on blockchain downloader/syncer: <https://github.com/Cuprate/cuprate/pull/320#discussion_r1811089758>");
179
180    // FIXME: impl this map somewhere instead of inline.
181    let vec = vec
182        .into_iter()
183        .map(|span| Span {
184            connection_id: String::from(ConnectionId::DEFAULT_STR),
185            nblocks: span.nblocks,
186            rate: span.rate,
187            remote_address: span.remote_address.to_string(),
188            size: span.size,
189            speed: span.speed,
190            start_block_height: span.start_block_height,
191        })
192        .collect();
193
194    Ok(vec)
195}
196
197/// [`BlockchainManagerRequest::NextNeededPruningSeed`]
198pub async fn next_needed_pruning_seed(
199    blockchain_manager: &mut BlockchainManagerHandle,
200) -> Result<PruningSeed, Error> {
201    let BlockchainManagerResponse::NextNeededPruningSeed(seed) = blockchain_manager
202        .ready()
203        .await?
204        .call(BlockchainManagerRequest::NextNeededPruningSeed)
205        .await?
206    else {
207        unreachable!();
208    };
209
210    Ok(seed)
211}
212
213/// [`BlockchainManagerRequest::CreateBlockTemplate`]
214pub async fn create_block_template(
215    blockchain_manager: &mut BlockchainManagerHandle,
216    prev_block: [u8; 32],
217    account_public_address: String,
218    extra_nonce: Vec<u8>,
219) -> Result<Box<BlockTemplate>, Error> {
220    let BlockchainManagerResponse::CreateBlockTemplate(block_template) = blockchain_manager
221        .ready()
222        .await?
223        .call(BlockchainManagerRequest::CreateBlockTemplate {
224            prev_block,
225            account_public_address,
226            extra_nonce,
227        })
228        .await?
229    else {
230        unreachable!();
231    };
232
233    Ok(block_template)
234}
235
236/// [`BlockchainManagerRequest::Sync`]
237pub async fn sync(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> {
238    let BlockchainManagerResponse::Ok = blockchain_manager
239        .ready()
240        .await?
241        .call(BlockchainManagerRequest::Sync)
242        .await?
243    else {
244        unreachable!();
245    };
246
247    Ok(())
248}
249
250/// [`BlockchainManagerRequest::Stop`]
251pub async fn stop(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> {
252    let BlockchainManagerResponse::Ok = blockchain_manager
253        .ready()
254        .await?
255        .call(BlockchainManagerRequest::Stop)
256        .await?
257    else {
258        unreachable!();
259    };
260
261    Ok(())
262}