mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-23 12:09:52 +00:00
helper::block_header
This commit is contained in:
parent
86f2dd1586
commit
de7abfc3f0
2 changed files with 97 additions and 52 deletions
|
@ -9,35 +9,93 @@ use anyhow::{anyhow, Error};
|
||||||
use monero_serai::block::Block;
|
use monero_serai::block::Block;
|
||||||
|
|
||||||
use cuprate_consensus::{BlockChainContext, BlockChainContextService};
|
use cuprate_consensus::{BlockChainContext, BlockChainContextService};
|
||||||
use cuprate_helper::{cast::usize_to_u64, map::split_u128_into_low_high_bits};
|
use cuprate_helper::{
|
||||||
|
cast::{u64_to_usize, usize_to_u64},
|
||||||
|
map::split_u128_into_low_high_bits,
|
||||||
|
};
|
||||||
use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus};
|
use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus};
|
||||||
use cuprate_types::ExtendedBlockHeader;
|
use cuprate_types::{ExtendedBlockHeader, HardFork};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
rpc::request::{blockchain, blockchain_context},
|
rpc::request::{blockchain, blockchain_context},
|
||||||
rpc::CupratedRpcHandler,
|
rpc::CupratedRpcHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn into_block_header(
|
/// Map some data into a [`BlockHeader`].
|
||||||
|
///
|
||||||
|
/// Sort of equivalent to:
|
||||||
|
/// <https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/src/rpc/core_rpc_server.cpp#L2361>.
|
||||||
|
pub(super) async fn block_header(
|
||||||
|
state: &mut CupratedRpcHandler,
|
||||||
height: u64,
|
height: u64,
|
||||||
top_height: u64,
|
|
||||||
fill_pow_hash: bool,
|
fill_pow_hash: bool,
|
||||||
block: Block,
|
) -> Result<BlockHeader, Error> {
|
||||||
header: ExtendedBlockHeader,
|
let block = blockchain::block(&mut state.blockchain_read, height).await?;
|
||||||
) -> BlockHeader {
|
let header = blockchain::block_extended_header(&mut state.blockchain_read, height).await?;
|
||||||
|
let hardfork = HardFork::from_vote(header.vote);
|
||||||
|
let (top_height, _) = top_height(state).await?;
|
||||||
|
|
||||||
|
// TODO: if the request block is not on the main chain,
|
||||||
|
// we must get the alt block and this variable will be `true`.
|
||||||
|
let orphan_status = false;
|
||||||
|
|
||||||
|
// FIXME: is there a cheaper way to get this?
|
||||||
|
let difficulty = blockchain_context::batch_get_difficulties(
|
||||||
|
&mut state.blockchain_context,
|
||||||
|
vec![(height, hardfork)],
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.first()
|
||||||
|
.copied()
|
||||||
|
.ok_or_else(|| anyhow!("Failed to get block difficulty"))?;
|
||||||
|
|
||||||
|
let pow_hash = if fill_pow_hash {
|
||||||
|
let seed_height =
|
||||||
|
cuprate_consensus_rules::blocks::randomx_seed_height(u64_to_usize(height));
|
||||||
|
let seed_hash = blockchain::block_hash(
|
||||||
|
&mut state.blockchain_read,
|
||||||
|
height,
|
||||||
|
todo!("access to `cuprated`'s Chain"),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let pow_hash = blockchain_context::calculate_pow(
|
||||||
|
&mut state.blockchain_context,
|
||||||
|
hardfork,
|
||||||
|
block,
|
||||||
|
seed_hash,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
hex::encode(pow_hash)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
|
||||||
let block_weight = usize_to_u64(header.block_weight);
|
let block_weight = usize_to_u64(header.block_weight);
|
||||||
let depth = top_height.saturating_sub(height);
|
let depth = top_height.saturating_sub(height);
|
||||||
|
|
||||||
let (cumulative_difficulty_top64, cumulative_difficulty) =
|
let (cumulative_difficulty_top64, cumulative_difficulty) =
|
||||||
split_u128_into_low_high_bits(header.cumulative_difficulty);
|
split_u128_into_low_high_bits(header.cumulative_difficulty);
|
||||||
|
let (difficulty_top64, difficulty) = split_u128_into_low_high_bits(difficulty);
|
||||||
|
let wide_difficulty = hex::encode(difficulty.to_ne_bytes());
|
||||||
|
|
||||||
BlockHeader {
|
let reward = block
|
||||||
|
.miner_transaction
|
||||||
|
.prefix()
|
||||||
|
.outputs
|
||||||
|
.iter()
|
||||||
|
.map(|o| o.amount.expect("coinbase is transparent"))
|
||||||
|
.sum::<u64>();
|
||||||
|
|
||||||
|
Ok(BlockHeader {
|
||||||
block_size: block_weight,
|
block_size: block_weight,
|
||||||
block_weight,
|
block_weight,
|
||||||
cumulative_difficulty_top64,
|
cumulative_difficulty_top64,
|
||||||
cumulative_difficulty,
|
cumulative_difficulty,
|
||||||
depth,
|
depth,
|
||||||
difficulty_top64: todo!(),
|
difficulty_top64,
|
||||||
difficulty: todo!(),
|
difficulty,
|
||||||
hash: hex::encode(block.hash()),
|
hash: hex::encode(block.hash()),
|
||||||
height,
|
height,
|
||||||
long_term_weight: usize_to_u64(header.long_term_weight),
|
long_term_weight: usize_to_u64(header.long_term_weight),
|
||||||
|
@ -46,33 +104,14 @@ pub(super) fn into_block_header(
|
||||||
minor_version: header.vote,
|
minor_version: header.vote,
|
||||||
nonce: block.header.nonce,
|
nonce: block.header.nonce,
|
||||||
num_txes: usize_to_u64(block.transactions.len()),
|
num_txes: usize_to_u64(block.transactions.len()),
|
||||||
orphan_status: todo!(),
|
orphan_status,
|
||||||
pow_hash: if fill_pow_hash {
|
pow_hash,
|
||||||
todo!()
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
},
|
|
||||||
prev_hash: hex::encode(block.header.previous),
|
prev_hash: hex::encode(block.header.previous),
|
||||||
reward: todo!(),
|
reward,
|
||||||
timestamp: block.header.timestamp,
|
timestamp: block.header.timestamp,
|
||||||
wide_cumulative_difficulty: hex::encode(u128::to_le_bytes(header.cumulative_difficulty)),
|
wide_cumulative_difficulty: hex::encode(u128::to_le_bytes(header.cumulative_difficulty)),
|
||||||
wide_difficulty: todo!(),
|
wide_difficulty,
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
/// 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.
|
/// Same as [`block_header`] but with the block's hash.
|
||||||
|
@ -81,24 +120,11 @@ pub(super) async fn block_header_by_hash(
|
||||||
hash: [u8; 32],
|
hash: [u8; 32],
|
||||||
fill_pow_hash: bool,
|
fill_pow_hash: bool,
|
||||||
) -> Result<BlockHeader, Error> {
|
) -> Result<BlockHeader, Error> {
|
||||||
let (top_height, _) = top_height(state).await?;
|
let (_, height) = blockchain::find_block(&mut state.blockchain_read, hash)
|
||||||
let block = blockchain::block_by_hash(&mut state.blockchain_read, hash).await?;
|
.await?
|
||||||
let header: ExtendedBlockHeader = todo!(); //blockchain::block_extended_header_by_hash(state.blockchain_read, hash).await?;
|
.ok_or_else(|| anyhow!("Block did not exist."))?;
|
||||||
|
|
||||||
let block_header = into_block_header(todo!(), top_height, fill_pow_hash, block, header);
|
let block_header = block_header(state, usize_to_u64(height), fill_pow_hash).await?;
|
||||||
|
|
||||||
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(todo!(), todo!(), fill_pow_hash, block, header);
|
|
||||||
|
|
||||||
Ok(block_header)
|
Ok(block_header)
|
||||||
}
|
}
|
||||||
|
@ -145,7 +171,7 @@ pub(super) async fn top_height(state: &mut CupratedRpcHandler) -> Result<(u64, [
|
||||||
Ok((height, hash))
|
Ok((height, hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Check if a key image is spent.
|
||||||
pub(super) async fn key_image_spent(
|
pub(super) async fn key_image_spent(
|
||||||
state: &mut CupratedRpcHandler,
|
state: &mut CupratedRpcHandler,
|
||||||
key_image: [u8; 32],
|
key_image: [u8; 32],
|
||||||
|
|
|
@ -100,3 +100,22 @@ pub(crate) async fn calculate_pow(
|
||||||
|
|
||||||
Ok(hash)
|
Ok(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [`BlockChainContextRequest::BatchGetDifficulties`]
|
||||||
|
pub(crate) async fn batch_get_difficulties(
|
||||||
|
blockchain_context: &mut BlockChainContextService,
|
||||||
|
difficulties: Vec<(u64, HardFork)>,
|
||||||
|
) -> Result<Vec<u128>, Error> {
|
||||||
|
let BlockChainContextResponse::BatchDifficulties(resp) = blockchain_context
|
||||||
|
.ready()
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!(e))?
|
||||||
|
.call(BlockChainContextRequest::BatchGetDifficulties(difficulties))
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!(e))?
|
||||||
|
else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(resp)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue