mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-24 20:49:35 +00:00
split blockchain/helper
functions
This commit is contained in:
parent
06b583e97d
commit
136e9b70a6
4 changed files with 203 additions and 189 deletions
|
@ -3,6 +3,7 @@
|
|||
//! Will contain the code to initiate the RPC and a request handler.
|
||||
|
||||
mod bin;
|
||||
mod blockchain;
|
||||
mod constants;
|
||||
mod handler;
|
||||
mod helper;
|
||||
|
|
142
binaries/cuprated/src/rpc/blockchain.rs
Normal file
142
binaries/cuprated/src/rpc/blockchain.rs
Normal file
|
@ -0,0 +1,142 @@
|
|||
//! These are convenience functions that make
|
||||
//! sending [`BlockchainReadRequest`] less verbose.
|
||||
|
||||
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::Block`].
|
||||
pub(super) async fn block(
|
||||
state: &mut CupratedRpcHandlerState,
|
||||
height: u64,
|
||||
) -> Result<VerifiedBlockInformation, Error> {
|
||||
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<VerifiedBlockInformation, Error> {
|
||||
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<ExtendedBlockHeader, Error> {
|
||||
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<ExtendedBlockHeader, Error> {
|
||||
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<usize>, Chain),
|
||||
// ChainHeight,
|
||||
// GeneratedCoins(usize),
|
||||
// Outputs(HashMap<u64, HashSet<u64>>),
|
||||
// NumberOutputsWithAmount(Vec<u64>),
|
||||
// KeyImagesSpent(HashSet<[u8; 32]>),
|
||||
// CompactChainHistory,
|
||||
// FindFirstUnknown(Vec<[u8; 32]>),
|
|
@ -3,7 +3,7 @@
|
|||
//! 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.
|
||||
//! These build on-top of [`crate::rpc::blockchain`] functions.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -20,144 +20,51 @@ use cuprate_types::{
|
|||
blockchain::BlockchainReadRequest, Chain, ExtendedBlockHeader, VerifiedBlockInformation,
|
||||
};
|
||||
|
||||
use crate::rpc::{CupratedRpcHandlerState, RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE};
|
||||
use crate::{
|
||||
rpc::helper,
|
||||
rpc::{CupratedRpcHandlerState, RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE},
|
||||
};
|
||||
|
||||
/// [`BlockchainResponse::ChainHeight`].
|
||||
pub(super) async fn chain_height(
|
||||
/// Check if `height` is greater than the [`top_height`].
|
||||
///
|
||||
/// # Errors
|
||||
/// This returns the [`top_height`] on [`Ok`] and
|
||||
/// returns [`Error`] if `height` is greater than [`top_height`].
|
||||
pub(super) async fn check_height(
|
||||
state: &mut CupratedRpcHandlerState,
|
||||
) -> Result<(u64, [u8; 32]), Error> {
|
||||
let BlockchainResponse::ChainHeight(height, hash) = state
|
||||
.blockchain
|
||||
.ready()
|
||||
.await?
|
||||
.call(BlockchainReadRequest::ChainHeight)
|
||||
.await?
|
||||
else {
|
||||
unreachable!();
|
||||
height: u64,
|
||||
) -> Result<u64, Error> {
|
||||
let (top_height, _) = top_height(state).await?;
|
||||
|
||||
if height > top_height {
|
||||
return Err(anyhow!(
|
||||
"Requested block height: {height} greater than current top block height: {top_height}",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(top_height)
|
||||
}
|
||||
|
||||
/// Parse a hexadecimal [`String`] as a 32-byte hash.
|
||||
pub(super) fn hex_to_hash(hex: String) -> Result<[u8; 32], Error> {
|
||||
let error = || anyhow!("Failed to parse hex representation of hash. Hex = {hex}.");
|
||||
|
||||
let Ok(bytes) = hex::decode(&hex) else {
|
||||
return Err(error());
|
||||
};
|
||||
|
||||
Ok((usize_to_u64(height), hash))
|
||||
let Ok(hash) = bytes.try_into() else {
|
||||
return Err(error());
|
||||
};
|
||||
|
||||
Ok(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!();
|
||||
};
|
||||
|
||||
let (chain_height, hash) = helper::chain_height().await?;
|
||||
let height = chain_height.saturating_sub(1);
|
||||
Ok((usize_to_u64(height), hash))
|
||||
}
|
||||
|
||||
/// [`BlockchainResponse::Block`].
|
||||
pub(super) async fn block(
|
||||
state: &mut CupratedRpcHandlerState,
|
||||
height: u64,
|
||||
) -> Result<VerifiedBlockInformation, Error> {
|
||||
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<VerifiedBlockInformation, Error> {
|
||||
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<ExtendedBlockHeader, Error> {
|
||||
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<ExtendedBlockHeader, Error> {
|
||||
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<usize>, Chain),
|
||||
// ChainHeight,
|
||||
// GeneratedCoins(usize),
|
||||
// Outputs(HashMap<u64, HashSet<u64>>),
|
||||
// NumberOutputsWithAmount(Vec<u64>),
|
||||
// KeyImagesSpent(HashSet<[u8; 32]>),
|
||||
// CompactChainHistory,
|
||||
// FindFirstUnknown(Vec<[u8; 32]>),
|
||||
|
|
|
@ -36,7 +36,7 @@ use cuprate_rpc_types::{
|
|||
use cuprate_types::{blockchain::BlockchainReadRequest, Chain};
|
||||
|
||||
use crate::{
|
||||
rpc::helper,
|
||||
rpc::{blockchain, helper},
|
||||
rpc::{CupratedRpcHandlerState, RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE},
|
||||
};
|
||||
|
||||
|
@ -104,7 +104,7 @@ async fn get_block_count(
|
|||
) -> Result<GetBlockCountResponse, Error> {
|
||||
Ok(GetBlockCountResponse {
|
||||
base: ResponseBase::ok(),
|
||||
count: helper::top_height(&mut state).await?,
|
||||
count: helper::top_height(&mut state).await?.0,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ async fn on_get_block_hash(
|
|||
request: OnGetBlockHashRequest,
|
||||
) -> Result<OnGetBlockHashResponse, Error> {
|
||||
let [height] = request.block_height;
|
||||
let hash = helper::block_hash(&mut state, height).await?;
|
||||
let hash = blockchain::block_hash(&mut state, height).await?;
|
||||
let block_hash = hex::encode(hash);
|
||||
|
||||
Ok(OnGetBlockHashResponse { block_hash })
|
||||
|
@ -145,7 +145,7 @@ async fn get_last_block_header(
|
|||
request: GetLastBlockHeaderRequest,
|
||||
) -> Result<GetLastBlockHeaderResponse, Error> {
|
||||
Ok(GetLastBlockHeaderResponse {
|
||||
base: ResponseBase::ok(),
|
||||
base: AccessResponseBase::ok(),
|
||||
block_header: todo!(),
|
||||
})
|
||||
}
|
||||
|
@ -165,17 +165,8 @@ async fn get_block_header_by_hash(
|
|||
hex: String,
|
||||
fill_pow_hash: bool,
|
||||
) -> Result<BlockHeader, Error> {
|
||||
let Ok(bytes) = hex::decode(&hex) else {
|
||||
return Err(anyhow!(
|
||||
"Failed to parse hex representation of block hash. Hex = {hex}."
|
||||
));
|
||||
};
|
||||
|
||||
let Ok(hash) = bytes.try_into() else {
|
||||
return Err(anyhow!("TODO"));
|
||||
};
|
||||
|
||||
let block = helper::block_by_hash(state, hash).await?;
|
||||
let hash = helper::hex_to_hash(hex)?;
|
||||
let block = blockchain::block_by_hash(state, hash).await?;
|
||||
let block_header = BlockHeader::from(&block);
|
||||
|
||||
Ok(block_header)
|
||||
|
@ -200,16 +191,8 @@ async fn get_block_header_by_height(
|
|||
mut state: CupratedRpcHandlerState,
|
||||
request: GetBlockHeaderByHeightRequest,
|
||||
) -> Result<GetBlockHeaderByHeightResponse, Error> {
|
||||
let (height, _) = helper::top_height(&mut state).await?;
|
||||
|
||||
if request.height > height {
|
||||
return Err(anyhow!(
|
||||
"Requested block height: {} greater than current top block height: {height}",
|
||||
request.height
|
||||
));
|
||||
}
|
||||
|
||||
let block = helper::block(&mut state, height).await?;
|
||||
helper::check_height(&mut state, request.height).await?;
|
||||
let block = blockchain::block(&mut state, request.height).await?;
|
||||
|
||||
Ok(GetBlockHeaderByHeightResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
|
@ -221,10 +204,10 @@ async fn get_block_headers_range(
|
|||
mut state: CupratedRpcHandlerState,
|
||||
request: GetBlockHeadersRangeRequest,
|
||||
) -> Result<GetBlockHeadersRangeResponse, Error> {
|
||||
let (height, _) = helper::top_height(&mut state).await?;
|
||||
let (top_height, _) = helper::top_height(&mut state).await?;
|
||||
|
||||
if request.start_height >= height
|
||||
|| request.end_height >= height
|
||||
if request.start_height >= top_height
|
||||
|| request.end_height >= top_height
|
||||
|| request.start_height > request.end_height
|
||||
{
|
||||
return Err(anyhow!("Invalid start/end heights"));
|
||||
|
@ -243,8 +226,8 @@ async fn get_block_headers_range(
|
|||
|
||||
{
|
||||
let ready = state.blockchain.ready().await?;
|
||||
let height = u64_to_usize(height);
|
||||
for block in request.start_height..=request.end_height {
|
||||
for height in request.start_height..=request.end_height {
|
||||
let height = u64_to_usize(height);
|
||||
let task = tokio::task::spawn(ready.call(BlockchainReadRequest::Block(height)));
|
||||
tasks.push(task);
|
||||
}
|
||||
|
@ -267,31 +250,12 @@ async fn get_block(
|
|||
mut state: CupratedRpcHandlerState,
|
||||
request: GetBlockRequest,
|
||||
) -> Result<GetBlockResponse, Error> {
|
||||
let block = if !request.hash.is_empty() {
|
||||
let hex = request.hash;
|
||||
|
||||
let Ok(bytes) = hex::decode(&hex) else {
|
||||
return Err(anyhow!(
|
||||
"Failed to parse hex representation of block hash. Hex = {hex}."
|
||||
));
|
||||
};
|
||||
|
||||
let Ok(hash) = bytes.try_into() else {
|
||||
return Err(anyhow!("TODO"));
|
||||
};
|
||||
|
||||
helper::block_by_hash(&mut state, hash).await?
|
||||
let block = if request.hash.is_empty() {
|
||||
helper::check_height(&mut state, request.height).await?;
|
||||
blockchain::block(&mut state, request.height).await?
|
||||
} else {
|
||||
let (height, _) = helper::top_height(&mut state).await?;
|
||||
|
||||
if request.height > height {
|
||||
return Err(anyhow!(
|
||||
"Requested block height: {} greater than current top block height: {height}",
|
||||
request.height
|
||||
));
|
||||
}
|
||||
|
||||
helper::block(&mut state, height).await?
|
||||
let hash = helper::hex_to_hash(request.hash)?;
|
||||
blockchain::block_by_hash(&mut state, hash).await?
|
||||
};
|
||||
|
||||
let block_header = (&block).into();
|
||||
|
@ -458,7 +422,7 @@ async fn get_version(
|
|||
request: GetVersionRequest,
|
||||
) -> Result<GetVersionResponse, Error> {
|
||||
Ok(GetVersionResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
base: ResponseBase::ok(),
|
||||
version: todo!(),
|
||||
release: todo!(),
|
||||
current_height: todo!(),
|
||||
|
@ -484,7 +448,7 @@ async fn get_alternate_chains(
|
|||
request: GetAlternateChainsRequest,
|
||||
) -> Result<GetAlternateChainsResponse, Error> {
|
||||
Ok(GetAlternateChainsResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
base: ResponseBase::ok(),
|
||||
chains: todo!(),
|
||||
})
|
||||
}
|
||||
|
@ -516,7 +480,7 @@ async fn get_transaction_pool_backlog(
|
|||
request: GetTransactionPoolBacklogRequest,
|
||||
) -> Result<GetTransactionPoolBacklogResponse, Error> {
|
||||
Ok(GetTransactionPoolBacklogResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
base: ResponseBase::ok(),
|
||||
backlog: todo!(),
|
||||
})
|
||||
}
|
||||
|
@ -526,7 +490,7 @@ async fn get_miner_data(
|
|||
request: GetMinerDataRequest,
|
||||
) -> Result<GetMinerDataResponse, Error> {
|
||||
Ok(GetMinerDataResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
base: ResponseBase::ok(),
|
||||
major_version: todo!(),
|
||||
height: todo!(),
|
||||
prev_id: todo!(),
|
||||
|
@ -543,7 +507,7 @@ async fn prune_blockchain(
|
|||
request: PruneBlockchainRequest,
|
||||
) -> Result<PruneBlockchainResponse, Error> {
|
||||
Ok(PruneBlockchainResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
base: ResponseBase::ok(),
|
||||
pruned: todo!(),
|
||||
pruning_seed: todo!(),
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue