cuprated/rpc/
handler.rs

1//! Dummy implementation of [`RpcHandler`].
2
3use std::task::{Context, Poll};
4
5use anyhow::Error;
6use futures::future::BoxFuture;
7use monero_serai::block::Block;
8use tower::Service;
9
10use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
11use cuprate_consensus::BlockchainContextService;
12use cuprate_pruning::PruningSeed;
13use cuprate_rpc_interface::RpcHandler;
14use cuprate_rpc_types::{
15    bin::{BinRequest, BinResponse},
16    json::{JsonRpcRequest, JsonRpcResponse},
17    other::{OtherRequest, OtherResponse},
18};
19use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle};
20use cuprate_types::{AddAuxPow, AuxPow, HardFork};
21
22use crate::rpc::{bin, json, other};
23
24/// TODO: use real type when public.
25#[derive(Clone)]
26#[expect(clippy::large_enum_variant)]
27pub enum BlockchainManagerRequest {
28    /// Pop blocks off the top of the blockchain.
29    ///
30    /// Input is the amount of blocks to pop.
31    PopBlocks { amount: usize },
32
33    /// Start pruning the blockchain.
34    Prune,
35
36    /// Is the blockchain pruned?
37    Pruned,
38
39    /// Relay a block to the network.
40    RelayBlock(Block),
41
42    /// Is the blockchain in the middle of syncing?
43    ///
44    /// This returning `false` does not necessarily
45    /// mean [`BlockchainManagerRequest::Synced`] will
46    /// return `true`, for example, if the network has been
47    /// cut off and we have no peers, this will return `false`,
48    /// however, [`BlockchainManagerRequest::Synced`] may return
49    /// `true` if the latest known chain tip is equal to our height.
50    Syncing,
51
52    /// Is the blockchain fully synced?
53    Synced,
54
55    /// Current target block time.
56    Target,
57
58    /// The height of the next block in the chain.
59    TargetHeight,
60
61    /// Generate new blocks.
62    ///
63    /// This request is only for regtest, see RPC's `generateblocks`.
64    GenerateBlocks {
65        /// Number of the blocks to be generated.
66        amount_of_blocks: u64,
67        /// The previous block's hash.
68        prev_block: [u8; 32],
69        /// The starting value for the nonce.
70        starting_nonce: u32,
71        /// The address that will receive the coinbase reward.
72        wallet_address: String,
73    },
74
75    //    // TODO: the below requests actually belong to the block downloader/syncer:
76    //    // <https://github.com/Cuprate/cuprate/pull/320#discussion_r1811089758>
77    //    /// Get [`Span`] data.
78    //    ///
79    //    /// This is data that describes an active downloading process,
80    //    /// if we are fully synced, this will return an empty [`Vec`].
81    //    Spans,
82
83    //
84    /// Get the next [`PruningSeed`] needed for a pruned sync.
85    NextNeededPruningSeed,
86}
87
88/// TODO: use real type when public.
89#[derive(Clone)]
90pub enum BlockchainManagerResponse {
91    /// General OK response.
92    ///
93    /// Response to:
94    /// - [`BlockchainManagerRequest::Prune`]
95    /// - [`BlockchainManagerRequest::RelayBlock`]
96    Ok,
97
98    /// Response to [`BlockchainManagerRequest::PopBlocks`]
99    PopBlocks { new_height: usize },
100
101    /// Response to [`BlockchainManagerRequest::Prune`]
102    Prune(PruningSeed),
103
104    /// Response to [`BlockchainManagerRequest::Pruned`]
105    Pruned(bool),
106
107    /// Response to [`BlockchainManagerRequest::Syncing`]
108    Syncing(bool),
109
110    /// Response to [`BlockchainManagerRequest::Synced`]
111    Synced(bool),
112
113    /// Response to [`BlockchainManagerRequest::Target`]
114    Target(std::time::Duration),
115
116    /// Response to [`BlockchainManagerRequest::TargetHeight`]
117    TargetHeight { height: usize },
118
119    /// Response to [`BlockchainManagerRequest::GenerateBlocks`]
120    GenerateBlocks {
121        /// Hashes of the blocks generated.
122        blocks: Vec<[u8; 32]>,
123        /// The new top height. (TODO: is this correct?)
124        height: usize,
125    },
126
127    //    /// Response to [`BlockchainManagerRequest::Spans`].
128    //    Spans(Vec<Span<Z::Addr>>),
129    /// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`].
130    NextNeededPruningSeed(PruningSeed),
131}
132
133/// TODO: use real type when public.
134pub type BlockchainManagerHandle = cuprate_database_service::DatabaseReadService<
135    BlockchainManagerRequest,
136    BlockchainManagerResponse,
137>;
138
139/// TODO
140#[derive(Clone)]
141pub struct CupratedRpcHandler {
142    /// Should this RPC server be [restricted](RpcHandler::restricted)?
143    ///
144    /// This is not `pub` on purpose, as it should not be mutated after [`Self::new`].
145    restricted: bool,
146
147    /// Read handle to the blockchain database.
148    pub blockchain_read: BlockchainReadHandle,
149
150    /// Handle to the blockchain context service.
151    pub blockchain_context: BlockchainContextService,
152
153    /// Handle to the blockchain manager.
154    pub blockchain_manager: BlockchainManagerHandle,
155
156    /// Read handle to the transaction pool database.
157    pub txpool_read: TxpoolReadHandle,
158
159    /// TODO: handle to txpool service.
160    pub txpool_manager: std::convert::Infallible,
161}
162
163impl CupratedRpcHandler {
164    /// Create a new [`Self`].
165    pub const fn new(
166        restricted: bool,
167        blockchain_read: BlockchainReadHandle,
168        blockchain_context: BlockchainContextService,
169        blockchain_manager: BlockchainManagerHandle,
170        txpool_read: TxpoolReadHandle,
171        txpool_manager: std::convert::Infallible,
172    ) -> Self {
173        Self {
174            restricted,
175            blockchain_read,
176            blockchain_context,
177            blockchain_manager,
178            txpool_read,
179            txpool_manager,
180        }
181    }
182}
183
184impl RpcHandler for CupratedRpcHandler {
185    fn restricted(&self) -> bool {
186        self.restricted
187    }
188}
189
190impl Service<JsonRpcRequest> for CupratedRpcHandler {
191    type Response = JsonRpcResponse;
192    type Error = Error;
193    type Future = BoxFuture<'static, Result<JsonRpcResponse, Error>>;
194
195    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
196        Poll::Ready(Ok(()))
197    }
198
199    fn call(&mut self, request: JsonRpcRequest) -> Self::Future {
200        let state = self.clone();
201        Box::pin(json::map_request(state, request))
202    }
203}
204
205impl Service<BinRequest> for CupratedRpcHandler {
206    type Response = BinResponse;
207    type Error = Error;
208    type Future = BoxFuture<'static, Result<BinResponse, Error>>;
209
210    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
211        Poll::Ready(Ok(()))
212    }
213
214    fn call(&mut self, request: BinRequest) -> Self::Future {
215        let state = self.clone();
216        Box::pin(bin::map_request(state, request))
217    }
218}
219
220impl Service<OtherRequest> for CupratedRpcHandler {
221    type Response = OtherResponse;
222    type Error = Error;
223    type Future = BoxFuture<'static, Result<OtherResponse, Error>>;
224
225    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
226        Poll::Ready(Ok(()))
227    }
228
229    fn call(&mut self, request: OtherRequest) -> Self::Future {
230        let state = self.clone();
231        Box::pin(other::map_request(state, request))
232    }
233}