import diffs

This commit is contained in:
hinto.janai 2024-10-09 20:47:17 -04:00
parent 9923d8d69d
commit d170b46180
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
7 changed files with 627 additions and 99 deletions

1
Cargo.lock generated
View file

@ -972,6 +972,7 @@ dependencies = [
"cuprate-blockchain",
"cuprate-consensus",
"cuprate-consensus-rules",
"cuprate-constants",
"cuprate-cryptonight",
"cuprate-dandelion-tower",
"cuprate-database",

View file

@ -12,6 +12,7 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/binaries/cuprated"
cuprate-consensus = { path = "../../consensus" }
cuprate-fast-sync = { path = "../../consensus/fast-sync" }
cuprate-consensus-rules = { path = "../../consensus/rules" }
cuprate-constants = { path = "../../constants", features = ["build", "rpc"] }
cuprate-cryptonight = { path = "../../cryptonight" }
cuprate-helper = { path = "../../helper" }
cuprate-epee-encoding = { path = "../../net/epee-encoding" }

View file

@ -7,5 +7,6 @@ mod handler;
mod json;
mod other;
mod request;
mod helper;
pub use handler::CupratedRpcHandler;

View file

@ -0,0 +1,168 @@
//! 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.
//!
//! These build on-top of [`crate::rpc::request`] functions.
use std::sync::Arc;
use anyhow::{anyhow, Error};
use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus};
use futures::StreamExt;
use monero_serai::block::Block;
use tower::{Service, ServiceExt};
use cuprate_consensus::BlockchainResponse;
use cuprate_constants::rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE};
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::request::blockchain, rpc::CupratedRpcHandler};
fn into_block_header(
height: u64,
top_height: u64,
fill_pow_hash: bool,
block: Block,
header: ExtendedBlockHeader,
) -> BlockHeader {
let block_weight = usize_to_u64(header.block_weight);
let depth = top_height.saturating_sub(height);
let (cumulative_difficulty_top64, cumulative_difficulty) =
split_u128_into_low_high_bits(header.cumulative_difficulty);
BlockHeader {
block_size: block_weight,
block_weight,
cumulative_difficulty_top64,
cumulative_difficulty,
depth,
difficulty_top64: todo!(),
difficulty: todo!(),
hash: hex::encode(block.hash()),
height,
long_term_weight: usize_to_u64(header.long_term_weight),
major_version: header.version.as_u8(),
miner_tx_hash: hex::encode(block.miner_transaction.hash()),
minor_version: header.vote,
nonce: block.header.nonce,
num_txes: usize_to_u64(block.transactions.len()),
orphan_status: todo!(),
pow_hash: if fill_pow_hash {
todo!()
} else {
String::new()
},
prev_hash: hex::encode(block.header.previous),
reward: todo!(),
timestamp: block.header.timestamp,
wide_cumulative_difficulty: hex::encode(u128::to_le_bytes(header.cumulative_difficulty)),
wide_difficulty: todo!(),
}
}
/// Get a [`VerifiedBlockInformation`] and map it to a [`BlockHeader`].
pub(super) async fn block_header(
state: &mut CupratedRpcHandler,
height: u64,
fill_pow_hash: bool,
) -> Result<BlockHeader, Error> {
let (top_height, _) = top_height(state).await?;
let block = blockchain::block(&mut state.blockchain_read, height).await?;
let header = blockchain::block_extended_header(&mut state.blockchain_read, height).await?;
let block_header = into_block_header(height, top_height, fill_pow_hash, block, header);
Ok(block_header)
}
/// Same as [`block_header`] but with the block's hash.
pub(super) async fn block_header_by_hash(
state: &mut CupratedRpcHandler,
hash: [u8; 32],
fill_pow_hash: bool,
) -> Result<BlockHeader, Error> {
let (top_height, _) = top_height(state).await?;
let block = blockchain::block_by_hash(&mut state.blockchain_read, hash).await?;
let header: ExtendedBlockHeader = todo!(); //blockchain::block_extended_header_by_hash(state.blockchain_read, hash).await?;
let block_header = into_block_header(header.height, top_height, fill_pow_hash, block, header);
Ok(block_header)
}
/// TODO
pub(super) async fn top_block_header(
state: &mut CupratedRpcHandler,
fill_pow_hash: bool,
) -> Result<BlockHeader, Error> {
let block: Block = todo!();
let header: ExtendedBlockHeader = todo!();
let block_header =
into_block_header(header.height, header.height, fill_pow_hash, block, header);
Ok(block_header)
}
/// 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 CupratedRpcHandler,
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());
};
let Ok(hash) = bytes.try_into() else {
return Err(error());
};
Ok(hash)
}
/// [`BlockchainResponse::ChainHeight`] minus 1.
pub(super) async fn top_height(state: &mut CupratedRpcHandler) -> Result<(u64, [u8; 32]), Error> {
let (chain_height, hash) = blockchain::chain_height(state).await?;
let height = chain_height.saturating_sub(1);
Ok((height, hash))
}
/// TODO
pub(super) async fn key_image_spent(
state: &mut CupratedRpcHandler,
key_image: [u8; 32],
) -> Result<KeyImageSpentStatus, Error> {
if blockchain::key_image_spent(state, key_image).await? {
Ok(KeyImageSpentStatus::SpentInBlockchain)
} else if todo!("key image is spent in tx pool") {
Ok(KeyImageSpentStatus::SpentInPool)
} else {
Ok(KeyImageSpentStatus::Unspent)
}
}

View file

@ -1,29 +1,43 @@
use std::sync::Arc;
use anyhow::Error;
use tower::ServiceExt;
use anyhow::{anyhow, Error};
use cuprate_types::HardFork;
use monero_serai::block::Block;
use tower::{Service, ServiceExt};
use cuprate_rpc_types::json::{
AddAuxPowRequest, AddAuxPowResponse, BannedRequest, BannedResponse, CalcPowRequest,
CalcPowResponse, FlushCacheRequest, FlushCacheResponse, FlushTransactionPoolRequest,
FlushTransactionPoolResponse, GenerateBlocksRequest, GenerateBlocksResponse,
GetAlternateChainsRequest, GetAlternateChainsResponse, GetBansRequest, GetBansResponse,
GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest,
GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest, GetBlockHeaderByHeightResponse,
GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse, GetBlockRequest, GetBlockResponse,
GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse, GetConnectionsRequest,
GetConnectionsResponse, GetFeeEstimateRequest, GetFeeEstimateResponse, GetInfoRequest,
GetInfoResponse, GetLastBlockHeaderRequest, GetLastBlockHeaderResponse, GetMinerDataRequest,
GetMinerDataResponse, GetOutputHistogramRequest, GetOutputHistogramResponse,
GetTransactionPoolBacklogRequest, GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest,
GetTxIdsLooseResponse, GetVersionRequest, GetVersionResponse, HardForkInfoRequest,
HardForkInfoResponse, JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest,
OnGetBlockHashResponse, PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest,
RelayTxResponse, SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse,
SyncInfoRequest, SyncInfoResponse,
use cuprate_consensus::{BlockchainReadRequest, BlockchainResponse};
use cuprate_constants::{
build::RELEASE,
rpc::{BLOCK_SIZE_SANITY_LEEWAY, RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE},
};
use cuprate_helper::cast::u64_to_usize;
use cuprate_rpc_types::{
base::{AccessResponseBase, ResponseBase},
json::{
AddAuxPowRequest, AddAuxPowResponse, BannedRequest, BannedResponse, CalcPowRequest,
CalcPowResponse, FlushCacheRequest, FlushCacheResponse, FlushTransactionPoolRequest,
FlushTransactionPoolResponse, GenerateBlocksRequest, GenerateBlocksResponse,
GetAlternateChainsRequest, GetAlternateChainsResponse, GetBansRequest, GetBansResponse,
GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest,
GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest,
GetBlockHeaderByHeightResponse, GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse,
GetBlockRequest, GetBlockResponse, GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse,
GetConnectionsRequest, GetConnectionsResponse, GetFeeEstimateRequest,
GetFeeEstimateResponse, GetInfoRequest, GetInfoResponse, GetLastBlockHeaderRequest,
GetLastBlockHeaderResponse, GetMinerDataRequest, GetMinerDataResponse,
GetOutputHistogramRequest, GetOutputHistogramResponse, GetTransactionPoolBacklogRequest,
GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, GetTxIdsLooseResponse,
GetVersionRequest, GetVersionResponse, HardForkInfoRequest, HardForkInfoResponse,
JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, OnGetBlockHashResponse,
PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest, RelayTxResponse,
SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest,
SyncInfoResponse,
},
misc::{BlockHeader, Status},
CORE_RPC_VERSION,
};
use crate::rpc::CupratedRpcHandler;
use crate::rpc::{helper, request::blockchain, CupratedRpcHandler};
/// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`].
pub(super) async fn map_request(
@ -83,212 +97,518 @@ pub(super) async fn map_request(
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L1790-L1804>
async fn get_block_count(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: GetBlockCountRequest,
) -> Result<GetBlockCountResponse, Error> {
todo!()
Ok(GetBlockCountResponse {
base: ResponseBase::ok(),
count: helper::top_height(&mut state).await?.0,
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L1806-L1831>
async fn on_get_block_hash(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: OnGetBlockHashRequest,
) -> Result<OnGetBlockHashResponse, Error> {
todo!()
let [height] = request.block_height;
let hash = blockchain::block_hash(&mut state, height).await?;
let block_hash = hex::encode(hash);
Ok(OnGetBlockHashResponse { block_hash })
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2209-L2266>
async fn submit_block(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: SubmitBlockRequest,
) -> Result<SubmitBlockResponse, Error> {
todo!()
let [blob] = request.block_blob;
let limit = blockchain::cumulative_block_weight_limit(&mut state).await?;
if blob.len() > limit + BLOCK_SIZE_SANITY_LEEWAY {
return Err(anyhow!("Block size is too big, rejecting block"));
}
let bytes = hex::decode(blob)?;
let block = Block::read(&mut bytes.as_slice())?;
// <https://github.com/monero-project/monero/blob/master/src/cryptonote_core/cryptonote_core.cpp#L1540>
let block_id = todo!("submit block to DB");
todo!("relay to P2P");
todo!("send to txpool");
Ok(SubmitBlockResponse {
base: ResponseBase::ok(),
block_id,
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2268-L2340>
async fn generate_blocks(
state: CupratedRpcHandler,
request: GenerateBlocksRequest,
) -> Result<GenerateBlocksResponse, Error> {
todo!()
Ok(GenerateBlocksResponse {
base: ResponseBase::ok(),
blocks: todo!(),
height: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2468-L2498>
async fn get_last_block_header(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: GetLastBlockHeaderRequest,
) -> Result<GetLastBlockHeaderResponse, Error> {
todo!()
let (height, _) = helper::top_height(&mut state).await?;
let block_header = helper::block_header(&mut state, height, request.fill_pow_hash).await?;
Ok(GetLastBlockHeaderResponse {
base: AccessResponseBase::ok(),
block_header,
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2468-L2498>
async fn get_block_header_by_hash(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: GetBlockHeaderByHashRequest,
) -> Result<GetBlockHeaderByHashResponse, Error> {
todo!()
if state.restricted && request.hashes.len() > RESTRICTED_BLOCK_COUNT {
return Err(anyhow!(
"Too many block headers requested in restricted mode"
));
}
async fn get(
state: &mut CupratedRpcHandler,
hex: String,
fill_pow_hash: bool,
) -> Result<BlockHeader, Error> {
let hash = helper::hex_to_hash(hex)?;
let block_header = helper::block_header_by_hash(state, hash, fill_pow_hash).await?;
Ok(block_header)
}
let block_header = get(&mut state, request.hash, request.fill_pow_hash).await?;
// FIXME PERF: could make a `Vec` on await on all tasks at the same time.
let mut block_headers = Vec::with_capacity(request.hashes.len());
for hash in request.hashes {
let hash = get(&mut state, hash, request.fill_pow_hash).await?;
block_headers.push(hash);
}
Ok(GetBlockHeaderByHashResponse {
base: AccessResponseBase::ok(),
block_header,
block_headers,
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2629-L2662>
async fn get_block_header_by_height(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: GetBlockHeaderByHeightRequest,
) -> Result<GetBlockHeaderByHeightResponse, Error> {
todo!()
helper::check_height(&mut state, request.height).await?;
let block_header =
helper::block_header(&mut state, request.height, request.fill_pow_hash).await?;
Ok(GetBlockHeaderByHeightResponse {
base: AccessResponseBase::ok(),
block_header,
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2569-L2627>
async fn get_block_headers_range(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: GetBlockHeadersRangeRequest,
) -> Result<GetBlockHeadersRangeResponse, Error> {
todo!()
let (top_height, _) = helper::top_height(&mut state).await?;
if request.start_height >= top_height
|| request.end_height >= top_height
|| request.start_height > request.end_height
{
return Err(anyhow!("Invalid start/end heights"));
}
if state.restricted
&& request.end_height.saturating_sub(request.start_height) + 1
> RESTRICTED_BLOCK_HEADER_RANGE
{
return Err(anyhow!("Too many block headers requested."));
}
let block_len = u64_to_usize(request.end_height.saturating_sub(request.start_height));
let mut tasks = Vec::with_capacity(block_len);
let mut headers = Vec::with_capacity(block_len);
{
let ready = state.blockchain_read.ready().await?;
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);
}
}
for task in tasks {
let BlockchainResponse::Block(header) = task.await?? else {
unreachable!();
};
// headers.push((&header).into());
headers.push(todo!());
}
Ok(GetBlockHeadersRangeResponse {
base: AccessResponseBase::ok(),
headers,
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2664-L2727>
async fn get_block(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: GetBlockRequest,
) -> Result<GetBlockResponse, Error> {
todo!()
let block = if request.hash.is_empty() {
helper::check_height(&mut state, request.height).await?;
blockchain::block(&mut state, request.height).await?
} else {
let hash = helper::hex_to_hash(request.hash)?;
blockchain::block_by_hash(&mut state, hash).await?
};
Ok(todo!())
// let block_header = (&block).into();
// let blob = hex::encode(block.block_blob);
// let miner_tx_hash = hex::encode(block.block.miner_transaction.hash());
// let tx_hashes = block
// .txs
// .into_iter()
// .map(|tx| hex::encode(tx.tx_hash))
// .collect();
// Ok(GetBlockResponse {
// base: AccessResponseBase::ok(),
// blob,
// json: todo!(), // TODO: make `JSON` type in `cuprate_rpc_types`
// miner_tx_hash,
// tx_hashes,
// block_header,
// })
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2729-L2738>
async fn get_connections(
state: CupratedRpcHandler,
request: GetConnectionsRequest,
) -> Result<GetConnectionsResponse, Error> {
todo!()
Ok(GetConnectionsResponse {
base: ResponseBase::ok(),
connections: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L501-L582>
async fn get_info(
state: CupratedRpcHandler,
request: GetInfoRequest,
) -> Result<GetInfoResponse, Error> {
todo!()
Ok(GetInfoResponse {
base: AccessResponseBase::ok(),
adjusted_time: todo!(),
alt_blocks_count: todo!(),
block_size_limit: todo!(),
block_size_median: todo!(),
block_weight_limit: todo!(),
block_weight_median: todo!(),
bootstrap_daemon_address: todo!(),
busy_syncing: todo!(),
cumulative_difficulty_top64: todo!(),
cumulative_difficulty: todo!(),
database_size: todo!(),
difficulty_top64: todo!(),
difficulty: todo!(),
free_space: todo!(),
grey_peerlist_size: todo!(),
height: todo!(),
height_without_bootstrap: todo!(),
incoming_connections_count: todo!(),
mainnet: todo!(),
nettype: todo!(),
offline: todo!(),
outgoing_connections_count: todo!(),
restricted: todo!(),
rpc_connections_count: todo!(),
stagenet: todo!(),
start_time: todo!(),
synchronized: todo!(),
target_height: todo!(),
target: todo!(),
testnet: todo!(),
top_block_hash: todo!(),
tx_count: todo!(),
tx_pool_size: todo!(),
update_available: todo!(),
version: todo!(),
was_bootstrap_ever_used: todo!(),
white_peerlist_size: todo!(),
wide_cumulative_difficulty: todo!(),
wide_difficulty: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2751-L2766>
async fn hard_fork_info(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: HardForkInfoRequest,
) -> Result<HardForkInfoResponse, Error> {
todo!()
let hard_fork = if request.version > 0 {
HardFork::from_version(request.version)?
} else {
blockchain::current_hard_fork(&mut state).await?
};
Ok(HardForkInfoResponse {
base: AccessResponseBase::ok(),
earliest_height: todo!(),
enabled: hard_fork.is_current(),
state: todo!(),
threshold: todo!(),
version: hard_fork.as_u8(),
votes: todo!(),
voting: todo!(),
window: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2832-L2878>
async fn set_bans(
state: CupratedRpcHandler,
request: SetBansRequest,
) -> Result<SetBansResponse, Error> {
todo!()
todo!();
Ok(SetBansResponse {
base: ResponseBase::ok(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2768-L2801>
async fn get_bans(
state: CupratedRpcHandler,
request: GetBansRequest,
) -> Result<GetBansResponse, Error> {
todo!()
Ok(GetBansResponse {
base: ResponseBase::ok(),
bans: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2803-L2830>
async fn banned(
state: CupratedRpcHandler,
request: BannedRequest,
) -> Result<BannedResponse, Error> {
todo!()
Ok(BannedResponse {
banned: todo!(),
seconds: todo!(),
status: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2880-L2932>
async fn flush_transaction_pool(
state: CupratedRpcHandler,
request: FlushTransactionPoolRequest,
) -> Result<FlushTransactionPoolResponse, Error> {
todo!()
todo!();
Ok(FlushTransactionPoolResponse { status: Status::Ok })
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2934-L2979>
async fn get_output_histogram(
state: CupratedRpcHandler,
request: GetOutputHistogramRequest,
) -> Result<GetOutputHistogramResponse, Error> {
todo!()
Ok(GetOutputHistogramResponse {
base: AccessResponseBase::ok(),
histogram: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2998-L3013>
async fn get_coinbase_tx_sum(
state: CupratedRpcHandler,
request: GetCoinbaseTxSumRequest,
) -> Result<GetCoinbaseTxSumResponse, Error> {
todo!()
Ok(GetCoinbaseTxSumResponse {
base: AccessResponseBase::ok(),
emission_amount: todo!(),
emission_amount_top64: todo!(),
fee_amount: todo!(),
fee_amount_top64: todo!(),
wide_emission_amount: todo!(),
wide_fee_amount: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2981-L2996>
async fn get_version(
state: CupratedRpcHandler,
mut state: CupratedRpcHandler,
request: GetVersionRequest,
) -> Result<GetVersionResponse, Error> {
todo!()
Ok(GetVersionResponse {
base: ResponseBase::ok(),
version: CORE_RPC_VERSION,
release: RELEASE,
current_height: helper::top_height(&mut state).await?.0,
target_height: todo!(),
hard_forks: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3015-L3031>
async fn get_fee_estimate(
state: CupratedRpcHandler,
request: GetFeeEstimateRequest,
) -> Result<GetFeeEstimateResponse, Error> {
todo!()
Ok(GetFeeEstimateResponse {
base: AccessResponseBase::ok(),
fee: todo!(),
fees: todo!(),
quantization_mask: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3033-L3064>
async fn get_alternate_chains(
state: CupratedRpcHandler,
request: GetAlternateChainsRequest,
) -> Result<GetAlternateChainsResponse, Error> {
todo!()
Ok(GetAlternateChainsResponse {
base: ResponseBase::ok(),
chains: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3254-L3304>
async fn relay_tx(
state: CupratedRpcHandler,
request: RelayTxRequest,
) -> Result<RelayTxResponse, Error> {
todo!()
todo!();
Ok(RelayTxResponse { status: Status::Ok })
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3306-L3330>
async fn sync_info(
state: CupratedRpcHandler,
request: SyncInfoRequest,
) -> Result<SyncInfoResponse, Error> {
todo!()
Ok(SyncInfoResponse {
base: AccessResponseBase::ok(),
height: todo!(),
next_needed_pruning_seed: todo!(),
overview: todo!(),
peers: todo!(),
spans: todo!(),
target_height: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3332-L3350>
async fn get_transaction_pool_backlog(
state: CupratedRpcHandler,
request: GetTransactionPoolBacklogRequest,
) -> Result<GetTransactionPoolBacklogResponse, Error> {
todo!()
Ok(GetTransactionPoolBacklogResponse {
base: ResponseBase::ok(),
backlog: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L1998-L2033>
async fn get_miner_data(
state: CupratedRpcHandler,
request: GetMinerDataRequest,
) -> Result<GetMinerDataResponse, Error> {
todo!()
Ok(GetMinerDataResponse {
base: ResponseBase::ok(),
major_version: todo!(),
height: todo!(),
prev_id: todo!(),
seed_hash: todo!(),
difficulty: todo!(),
median_weight: todo!(),
already_generated_coins: todo!(),
tx_backlog: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3453-L3476>
async fn prune_blockchain(
state: CupratedRpcHandler,
request: PruneBlockchainRequest,
) -> Result<PruneBlockchainResponse, Error> {
todo!()
Ok(PruneBlockchainResponse {
base: ResponseBase::ok(),
pruned: todo!(),
pruning_seed: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2035-L2070>
async fn calc_pow(
state: CupratedRpcHandler,
request: CalcPowRequest,
) -> Result<CalcPowResponse, Error> {
todo!()
Ok(CalcPowResponse { pow_hash: todo!() })
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3542-L3551>
async fn flush_cache(
state: CupratedRpcHandler,
request: FlushCacheRequest,
) -> Result<FlushCacheResponse, Error> {
todo!()
todo!();
Ok(FlushCacheResponse {
base: ResponseBase::ok(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2072-L2207>
async fn add_aux_pow(
state: CupratedRpcHandler,
request: AddAuxPowRequest,
) -> Result<AddAuxPowResponse, Error> {
todo!()
Ok(AddAuxPowResponse {
base: ResponseBase::ok(),
blocktemplate_blob: todo!(),
blockhashing_blob: todo!(),
merkle_root: todo!(),
merkle_tree_depth: todo!(),
aux_pow: todo!(),
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3553-L3627>
async fn get_tx_ids_loose(
state: CupratedRpcHandler,
request: GetTxIdsLooseRequest,
) -> Result<GetTxIdsLooseResponse, Error> {
todo!()
Ok(GetTxIdsLooseResponse {
base: ResponseBase::ok(),
txids: todo!(),
})
}

View file

@ -12,8 +12,8 @@
//! the [`blockchain`] modules contains methods for the
//! blockchain database [`tower::Service`] API.
mod address_book;
mod blockchain;
mod blockchain_context;
mod blockchain_manager;
mod txpool;
pub(super) mod address_book;
pub(super) mod blockchain;
pub(super) mod blockchain_context;
pub(super) mod blockchain_manager;
pub(super) mod txpool;

View file

@ -6,9 +6,10 @@ use std::{
};
use anyhow::Error;
use cuprate_blockchain::service::BlockchainReadHandle;
use monero_serai::block::Block;
use tower::{Service, ServiceExt};
use cuprate_blockchain::service::BlockchainReadHandle;
use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
use cuprate_types::{
blockchain::{BlockchainReadRequest, BlockchainResponse},
@ -16,9 +17,45 @@ use cuprate_types::{
OutputHistogramInput, OutputOnChain,
};
/// [`BlockchainReadRequest::Block`].
pub(crate) async fn block(
blockchain_read: &mut BlockchainReadHandle,
height: u64,
) -> Result<Block, Error> {
let BlockchainResponse::Block(block) = blockchain_read
.ready()
.await?
.call(BlockchainReadRequest::Block {
height: u64_to_usize(height),
})
.await?
else {
unreachable!();
};
Ok(block)
}
/// [`BlockchainReadRequest::BlockByHash`].
pub(crate) async fn block_by_hash(
blockchain_read: &mut BlockchainReadHandle,
hash: [u8; 32],
) -> Result<Block, Error> {
let BlockchainResponse::Block(block) = blockchain_read
.ready()
.await?
.call(BlockchainReadRequest::BlockByHash(hash))
.await?
else {
unreachable!();
};
Ok(block)
}
/// [`BlockchainReadRequest::BlockExtendedHeader`].
pub(super) async fn block_extended_header(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn block_extended_header(
blockchain_read: &mut BlockchainReadHandle,
height: u64,
) -> Result<ExtendedBlockHeader, Error> {
let BlockchainResponse::BlockExtendedHeader(header) = blockchain_read
@ -36,8 +73,8 @@ pub(super) async fn block_extended_header(
}
/// [`BlockchainReadRequest::BlockHash`].
pub(super) async fn block_hash(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn block_hash(
blockchain_read: &mut BlockchainReadHandle,
height: u64,
chain: Chain,
) -> Result<[u8; 32], Error> {
@ -57,8 +94,8 @@ pub(super) async fn block_hash(
}
/// [`BlockchainReadRequest::FindBlock`].
pub(super) async fn find_block(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn find_block(
blockchain_read: &mut BlockchainReadHandle,
block_hash: [u8; 32],
) -> Result<Option<(Chain, usize)>, Error> {
let BlockchainResponse::FindBlock(option) = blockchain_read
@ -74,8 +111,8 @@ pub(super) async fn find_block(
}
/// [`BlockchainReadRequest::FilterUnknownHashes`].
pub(super) async fn filter_unknown_hashes(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn filter_unknown_hashes(
blockchain_read: &mut BlockchainReadHandle,
block_hashes: HashSet<[u8; 32]>,
) -> Result<HashSet<[u8; 32]>, Error> {
let BlockchainResponse::FilterUnknownHashes(output) = blockchain_read
@ -91,8 +128,8 @@ pub(super) async fn filter_unknown_hashes(
}
/// [`BlockchainReadRequest::BlockExtendedHeaderInRange`]
pub(super) async fn block_extended_header_in_range(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn block_extended_header_in_range(
blockchain_read: &mut BlockchainReadHandle,
range: Range<usize>,
chain: Chain,
) -> Result<Vec<ExtendedBlockHeader>, Error> {
@ -111,8 +148,8 @@ pub(super) async fn block_extended_header_in_range(
}
/// [`BlockchainReadRequest::ChainHeight`].
pub(super) async fn chain_height(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn chain_height(
blockchain_read: &mut BlockchainReadHandle,
) -> Result<(u64, [u8; 32]), Error> {
let BlockchainResponse::ChainHeight(height, hash) = blockchain_read
.ready()
@ -127,8 +164,8 @@ pub(super) async fn chain_height(
}
/// [`BlockchainReadRequest::GeneratedCoins`].
pub(super) async fn generated_coins(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn generated_coins(
blockchain_read: &mut BlockchainReadHandle,
block_height: u64,
) -> Result<u64, Error> {
let BlockchainResponse::GeneratedCoins(generated_coins) = blockchain_read
@ -146,8 +183,8 @@ pub(super) async fn generated_coins(
}
/// [`BlockchainReadRequest::Outputs`]
pub(super) async fn outputs(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn outputs(
blockchain_read: &mut BlockchainReadHandle,
outputs: HashMap<u64, HashSet<u64>>,
) -> Result<HashMap<u64, HashMap<u64, OutputOnChain>>, Error> {
let BlockchainResponse::Outputs(outputs) = blockchain_read
@ -163,8 +200,8 @@ pub(super) async fn outputs(
}
/// [`BlockchainReadRequest::NumberOutputsWithAmount`]
pub(super) async fn number_outputs_with_amount(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn number_outputs_with_amount(
blockchain_read: &mut BlockchainReadHandle,
output_amounts: Vec<u64>,
) -> Result<HashMap<u64, usize>, Error> {
let BlockchainResponse::NumberOutputsWithAmount(map) = blockchain_read
@ -182,8 +219,8 @@ pub(super) async fn number_outputs_with_amount(
}
/// [`BlockchainReadRequest::KeyImagesSpent`]
pub(super) async fn key_images_spent(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn key_images_spent(
blockchain_read: &mut BlockchainReadHandle,
key_images: HashSet<[u8; 32]>,
) -> Result<bool, Error> {
let BlockchainResponse::KeyImagesSpent(is_spent) = blockchain_read
@ -199,8 +236,8 @@ pub(super) async fn key_images_spent(
}
/// [`BlockchainReadRequest::CompactChainHistory`]
pub(super) async fn compact_chain_history(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn compact_chain_history(
blockchain_read: &mut BlockchainReadHandle,
) -> Result<(Vec<[u8; 32]>, u128), Error> {
let BlockchainResponse::CompactChainHistory {
block_ids,
@ -218,8 +255,8 @@ pub(super) async fn compact_chain_history(
}
/// [`BlockchainReadRequest::FindFirstUnknown`]
pub(super) async fn find_first_unknown(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn find_first_unknown(
blockchain_read: &mut BlockchainReadHandle,
hashes: Vec<[u8; 32]>,
) -> Result<Option<(usize, u64)>, Error> {
let BlockchainResponse::FindFirstUnknown(resp) = blockchain_read
@ -235,8 +272,8 @@ pub(super) async fn find_first_unknown(
}
/// [`BlockchainReadRequest::TotalTxCount`]
pub(super) async fn total_tx_count(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn total_tx_count(
blockchain_read: &mut BlockchainReadHandle,
) -> Result<u64, Error> {
let BlockchainResponse::TotalTxCount(tx_count) = blockchain_read
.ready()
@ -251,8 +288,8 @@ pub(super) async fn total_tx_count(
}
/// [`BlockchainReadRequest::DatabaseSize`]
pub(super) async fn database_size(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn database_size(
blockchain_read: &mut BlockchainReadHandle,
) -> Result<(u64, u64), Error> {
let BlockchainResponse::DatabaseSize {
database_size,
@ -270,8 +307,8 @@ pub(super) async fn database_size(
}
/// [`BlockchainReadRequest::OutputHistogram`]
pub(super) async fn output_histogram(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn output_histogram(
blockchain_read: &mut BlockchainReadHandle,
input: OutputHistogramInput,
) -> Result<Vec<OutputHistogramEntry>, Error> {
let BlockchainResponse::OutputHistogram(histogram) = blockchain_read
@ -287,8 +324,8 @@ pub(super) async fn output_histogram(
}
/// [`BlockchainReadRequest::CoinbaseTxSum`]
pub(super) async fn coinbase_tx_sum(
mut blockchain_read: BlockchainReadHandle,
pub(crate) async fn coinbase_tx_sum(
blockchain_read: &mut BlockchainReadHandle,
height: u64,
count: u64,
) -> Result<CoinbaseTxSum, Error> {