diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs new file mode 100644 index 00000000..96166ff9 --- /dev/null +++ b/binaries/cuprated/src/rpc/helper.rs @@ -0,0 +1,163 @@ +//! These are internal helper functions used by the actual RPC handlers. +//! +//! Many of the handlers have bodies with only small differences, +//! the identical code is extracted and reused here in these functions. +//! +//! They typically map to database requests. + +use std::sync::Arc; + +use anyhow::{anyhow, Error}; +use futures::StreamExt; +use tower::{Service, ServiceExt}; + +use cuprate_consensus::BlockchainResponse; +use cuprate_helper::{ + cast::{u64_to_usize, usize_to_u64}, + map::split_u128_into_low_high_bits, +}; +use cuprate_types::{ + blockchain::BlockchainReadRequest, Chain, ExtendedBlockHeader, VerifiedBlockInformation, +}; + +use crate::rpc::{CupratedRpcHandlerState, RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}; + +/// [`BlockchainResponse::ChainHeight`]. +pub(super) async fn chain_height( + state: &mut CupratedRpcHandlerState, +) -> Result<(u64, [u8; 32]), Error> { + let BlockchainResponse::ChainHeight(height, hash) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::ChainHeight) + .await? + else { + unreachable!(); + }; + + Ok((usize_to_u64(height), hash)) +} + +/// [`BlockchainResponse::ChainHeight`] minus 1. +pub(super) async fn top_height( + state: &mut CupratedRpcHandlerState, +) -> Result<(u64, [u8; 32]), Error> { + let BlockchainResponse::ChainHeight(height, hash) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::ChainHeight) + .await? + else { + unreachable!(); + }; + + Ok((usize_to_u64(height), hash)) +} + +/// [`BlockchainResponse::Block`]. +pub(super) async fn block( + state: &mut CupratedRpcHandlerState, + height: u64, +) -> Result { + let BlockchainResponse::Block(block) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::Block(u64_to_usize(height))) + .await? + else { + unreachable!(); + }; + + Ok(block) +} + +/// [`BlockchainResponse::BlockByHash`]. +pub(super) async fn block_by_hash( + state: &mut CupratedRpcHandlerState, + hash: [u8; 32], +) -> Result { + let BlockchainResponse::BlockByHash(block) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::BlockByHash(hash)) + .await? + else { + unreachable!(); + }; + + Ok(block) +} + +/// [`BlockchainResponse::BlockExtendedHeader`]. +pub(super) async fn block_extended_header( + state: &mut CupratedRpcHandlerState, + height: u64, +) -> Result { + let BlockchainResponse::BlockExtendedHeader(header) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::BlockExtendedHeader(u64_to_usize( + height, + ))) + .await? + else { + unreachable!(); + }; + + Ok(header) +} + +/// [`BlockchainResponse::BlockExtendedHeaderByHash`]. +pub(super) async fn block_extended_header_by_hash( + state: &mut CupratedRpcHandlerState, + hash: [u8; 32], +) -> Result { + let BlockchainResponse::BlockExtendedHeaderByHash(header) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::BlockExtendedHeaderByHash(hash)) + .await? + else { + unreachable!(); + }; + + Ok(header) +} + +/// [`BlockchainResponse::BlockHash`] with [`Chain::Main`]. +pub(super) async fn block_hash( + state: &mut CupratedRpcHandlerState, + height: u64, +) -> Result<[u8; 32], Error> { + let BlockchainResponse::BlockHash(hash) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::BlockHash( + u64_to_usize(height), + Chain::Main, + )) + .await? + else { + unreachable!(); + }; + + Ok(hash) +} + +// FindBlock([u8; 32]), +// FilterUnknownHashes(HashSet<[u8; 32]>), +// BlockExtendedHeaderInRange(Range, Chain), +// ChainHeight, +// GeneratedCoins(usize), +// Outputs(HashMap>), +// NumberOutputsWithAmount(Vec), +// KeyImagesSpent(HashSet<[u8; 32]>), +// CompactChainHistory, +// FindFirstUnknown(Vec<[u8; 32]>),