json_rpc: get_block_template

This commit is contained in:
hinto.janai 2024-12-11 16:30:37 -05:00
parent 1719d7db84
commit b402c82557
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
9 changed files with 137 additions and 81 deletions

View file

@ -3,6 +3,7 @@
use std::task::{Context, Poll};
use anyhow::Error;
use cuprate_types::BlockTemplate;
use futures::future::BoxFuture;
use monero_serai::block::Block;
use tower::Service;
@ -84,6 +85,13 @@ pub enum BlockchainManagerRequest {
//
/// Get the next [`PruningSeed`] needed for a pruned sync.
NextNeededPruningSeed,
/// TODO
CreateBlockTemplate {
prev_block: [u8; 32],
account_public_address: String,
extra_nonce: Vec<u8>,
},
}
/// TODO: use real type when public.
@ -129,6 +137,9 @@ pub enum BlockchainManagerResponse {
// Spans(Vec<Span<Z::Addr>>),
/// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`].
NextNeededPruningSeed(PruningSeed),
/// Response to [`BlockchainManagerRequest::CreateBlockTemplate`].
CreateBlockTemplate(Box<BlockTemplate>),
}
/// TODO: use real type when public.

View file

@ -20,6 +20,7 @@ use cuprate_constants::{
};
use cuprate_helper::{
cast::{u32_to_usize, u64_to_usize, usize_to_u64},
fmt::HexPrefix,
map::split_u128_into_low_high_bits,
};
use cuprate_hex::Hex;
@ -53,7 +54,7 @@ use cuprate_rpc_types::{
};
use cuprate_types::{
rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry},
HardFork,
BlockTemplate, HardFork,
};
use crate::{
@ -160,65 +161,50 @@ async fn get_block_template(
return Err(anyhow!("Mining to subaddress is not supported yet"));
}
// block b;
// cryptonote::blobdata blob_reserve;
// size_t reserved_offset;
// if(!request.extra_nonce.empty())
// {
// if(!string_tools::parse_hexstr_to_binbuff(request.extra_nonce, blob_reserve))
// {
// error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
// error_resp.message = "Parameter extra_nonce should be a hex string";
// return false;
// }
// }
// else
// blob_reserve.resize(request.reserve_size, 0);
// cryptonote::difficulty_type wdiff;
// crypto::hash prev_block;
// if (!request.prev_block.empty())
// {
// if (!epee::string_tools::hex_to_pod(request.prev_block, prev_block))
// {
// error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
// error_resp.message = "Invalid prev_block";
// return false;
// }
// }
// crypto::hash seed_hash, next_seed_hash;
// if (!get_block_template(info.address, request.prev_block.empty() ? NULL : &prev_block, blob_reserve, reserved_offset, wdiff, res.height, res.expected_reward, res.cumulative_weight, b, res.seed_height, seed_hash, next_seed_hash, error_resp))
// return false;
// if (b.major_version >= RX_BLOCK_VERSION)
// {
// res.seed_hash = string_tools::pod_to_hex(seed_hash);
// if (seed_hash != next_seed_hash)
// res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash);
// }
let blob_reserve = hex::decode(request.extra_nonce)?;
let prev_block = helper::hex_to_hash(request.prev_block)?;
let extra_nonce = hex::decode(request.extra_nonce)?;
// res.reserved_offset = reserved_offset;
// store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64);
// blobdata block_blob = t_serializable_object_to_blob(b);
// blobdata hashing_blob = get_block_hashing_blob(b);
// res.prev_hash = string_tools::pod_to_hex(b.prev_id);
// res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
// res.blockhashing_blob = string_tools::buff_to_hex_nodelimer(hashing_blob);
// res.status = CORE_RPC_STATUS_OK;
// return true;
let BlockTemplate {
block,
reserved_offset,
difficulty,
height,
expected_reward,
seed_height,
seed_hash,
next_seed_hash,
} = *blockchain_manager::create_block_template(
&mut state.blockchain_manager,
prev_block,
request.wallet_address,
extra_nonce,
)
.await?;
let blockhashing_blob = hex::encode(block.serialize_pow_hash());
let blocktemplate_blob = hex::encode(block.serialize());
let (difficulty, difficulty_top64) = split_u128_into_low_high_bits(difficulty);
// let next_seed_hash = Hex(next_seed_hash);
let next_seed_hash = hex::encode(next_seed_hash);
let prev_hash = Hex(block.header.previous);
let seed_hash = Hex(seed_hash);
let wide_difficulty = (difficulty, difficulty_top64).hex_prefix();
Ok(GetBlockTemplateResponse {
base: ResponseBase::OK,
blockhashing_blob: todo!(),
blocktemplate_blob: todo!(),
difficulty_top64: todo!(),
difficulty: todo!(),
expected_reward: todo!(),
height: todo!(),
next_seed_hash: todo!(),
prev_hash: todo!(),
reserved_offset: todo!(),
seed_hash: todo!(),
seed_height: todo!(),
wide_difficulty: todo!(),
blockhashing_blob,
blocktemplate_blob,
difficulty_top64,
difficulty,
expected_reward,
height,
next_seed_hash,
prev_hash,
reserved_offset,
seed_hash,
seed_height,
wide_difficulty,
})
}

View file

@ -8,6 +8,7 @@ use cuprate_constants::rpc::{
MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT, RESTRICTED_SPENT_KEY_IMAGES_COUNT,
};
use cuprate_helper::cast::usize_to_u64;
use cuprate_hex::Hex;
use cuprate_rpc_interface::RpcHandler;
use cuprate_rpc_types::{
base::{AccessResponseBase, ResponseBase},
@ -100,7 +101,7 @@ async fn get_height(
request: GetHeightRequest,
) -> Result<GetHeightResponse, Error> {
let (height, hash) = helper::top_height(&mut state).await?;
let hash = hex::encode(hash);
let hash = Hex(hash);
Ok(GetHeightResponse {
base: ResponseBase::OK,
@ -142,9 +143,8 @@ async fn is_key_image_spent(
let mut spent_status = Vec::with_capacity(request.key_images.len());
for hex in request.key_images {
let key_image = helper::hex_to_hash(hex)?;
let status = helper::key_image_spent(&mut state, key_image).await?;
for key_image in request.key_images {
let status = helper::key_image_spent(&mut state, key_image.0).await?;
spent_status.push(status.to_u8());
}

View file

@ -1,6 +1,7 @@
//! Functions to send [`BlockchainManagerRequest`]s.
use anyhow::Error;
use cuprate_types::BlockTemplate;
use monero_serai::block::Block;
use tower::{Service, ServiceExt};
@ -218,3 +219,26 @@ pub(crate) async fn next_needed_pruning_seed(
Ok(seed)
}
/// [`BlockchainManagerRequest::CreateBlockTemplate`]
pub(crate) async fn create_block_template(
blockchain_manager: &mut BlockchainManagerHandle,
prev_block: [u8; 32],
account_public_address: String,
extra_nonce: Vec<u8>,
) -> Result<Box<BlockTemplate>, Error> {
let BlockchainManagerResponse::CreateBlockTemplate(block_template) = blockchain_manager
.ready()
.await?
.call(BlockchainManagerRequest::CreateBlockTemplate {
prev_block,
account_public_address,
extra_nonce,
})
.await?
else {
unreachable!();
};
Ok(block_template)
}

View file

@ -1,18 +1,41 @@
//! Formatting.
use crate::map::combine_low_high_bits_to_u128;
pub trait HexPrefix {
fn hex_prefix(self) -> String;
}
/// Format two [`u64`]'s as a [`u128`] as a lower-case hexadecimal string prefixed with `0x`.
///
/// ```rust
/// # use cuprate_helper::fmt::hex_prefix_u128;
/// assert_eq!(hex_prefix_u128(0, 0), "0x0");
/// assert_eq!(hex_prefix_u128(0, u64::MAX), "0xffffffffffffffff0000000000000000");
/// assert_eq!(hex_prefix_u128(u64::MAX, 0), "0xffffffffffffffff");
/// assert_eq!(hex_prefix_u128(u64::MAX, u64::MAX), "0xffffffffffffffffffffffffffffffff");
/// ```
pub fn hex_prefix_u128(low_bits: u64, high_bits: u64) -> String {
format!("{:#x}", combine_low_high_bits_to_u128(low_bits, high_bits))
macro_rules! impl_hex_prefix {
($(
$t:ty
),*) => {
$(
impl HexPrefix for $t {
fn hex_prefix(self) -> String {
format!("{:#x}", self)
}
}
)*
};
}
impl_hex_prefix!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize);
impl HexPrefix for (u64, u64) {
/// Combine the low and high bits of a [`u128`] as a lower-case hexadecimal string prefixed with `0x`.
///
/// ```rust
/// # use cuprate_helper::fmt::HexPrefix;
/// assert_eq!((0, 0).hex_prefix(), "0x0");
/// assert_eq!((0, u64::MAX).hex_prefix(), "0xffffffffffffffff0000000000000000");
/// assert_eq!((u64::MAX, 0).hex_prefix(), "0xffffffffffffffff");
/// assert_eq!((u64::MAX, u64::MAX).hex_prefix(), "0xffffffffffffffffffffffffffffffff");
/// ```
fn hex_prefix(self) -> String {
format!(
"{:#x}",
crate::map::combine_low_high_bits_to_u128(self.0, self.1)
)
}
}
#[cfg(test)]

View file

@ -7,7 +7,7 @@ use std::{
time::Duration,
};
use cuprate_helper::{fmt::hex_prefix_u128, map::ipv4_from_u32};
use cuprate_helper::{fmt::HexPrefix, map::ipv4_from_u32};
use cuprate_hex::Hex;
use cuprate_p2p_core::{
types::{ConnectionId, ConnectionInfo, SetBan, Span},
@ -40,11 +40,9 @@ impl From<BlockHeader> for crate::misc::BlockHeader {
timestamp: x.timestamp,
// FIXME: if we made a type that automatically did `hex_prefix_u128`,
// we wouldn't need `crate::misc::BlockHeader`.
wide_cumulative_difficulty: hex_prefix_u128(
x.cumulative_difficulty,
x.cumulative_difficulty_top64,
),
wide_difficulty: hex_prefix_u128(x.difficulty, x.difficulty_top64),
wide_cumulative_difficulty: (x.cumulative_difficulty, x.cumulative_difficulty_top64)
.hex_prefix(),
wide_difficulty: (x.difficulty, x.difficulty_top64).hex_prefix(),
}
}
}
@ -132,7 +130,7 @@ impl From<ChainInfo> for crate::misc::ChainInfo {
height: x.height,
length: x.length,
main_chain_parent_block: Hex(x.main_chain_parent_block),
wide_difficulty: hex_prefix_u128(x.difficulty, x.difficulty_top64),
wide_difficulty: (x.difficulty, x.difficulty_top64).hex_prefix(),
}
}
}

1
types/hex/src/prefix.rs Normal file
View file

@ -0,0 +1 @@

View file

@ -24,8 +24,8 @@ pub use transaction_verification_data::{
CachedVerificationState, TransactionVerificationData, TxVersion,
};
pub use types::{
AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, OutputOnChain, TxsInBlock,
VerifiedBlockInformation, VerifiedTransactionInformation,
AltBlockInformation, BlockTemplate, Chain, ChainId, ExtendedBlockHeader, OutputOnChain,
TxsInBlock, VerifiedBlockInformation, VerifiedTransactionInformation,
};
//---------------------------------------------------------------------------------------------------- Feature-gated

View file

@ -154,6 +154,19 @@ pub struct TxsInBlock {
pub txs: Vec<Vec<u8>>,
}
/// A block template, used in RPC's `get_block_template`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BlockTemplate {
pub block: Block,
pub reserved_offset: u64,
pub difficulty: u128,
pub height: u64,
pub expected_reward: u64,
pub seed_height: u64,
pub seed_hash: [u8; 32],
pub next_seed_hash: [u8; 32],
}
//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {