//! 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]>),