mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 19:49:33 +00:00
json_rpc: get_block_template
This commit is contained in:
parent
1719d7db84
commit
b402c82557
9 changed files with 137 additions and 81 deletions
|
@ -3,6 +3,7 @@
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use cuprate_types::BlockTemplate;
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use monero_serai::block::Block;
|
use monero_serai::block::Block;
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
|
@ -84,6 +85,13 @@ pub enum BlockchainManagerRequest {
|
||||||
//
|
//
|
||||||
/// Get the next [`PruningSeed`] needed for a pruned sync.
|
/// Get the next [`PruningSeed`] needed for a pruned sync.
|
||||||
NextNeededPruningSeed,
|
NextNeededPruningSeed,
|
||||||
|
|
||||||
|
/// TODO
|
||||||
|
CreateBlockTemplate {
|
||||||
|
prev_block: [u8; 32],
|
||||||
|
account_public_address: String,
|
||||||
|
extra_nonce: Vec<u8>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: use real type when public.
|
/// TODO: use real type when public.
|
||||||
|
@ -129,6 +137,9 @@ pub enum BlockchainManagerResponse {
|
||||||
// Spans(Vec<Span<Z::Addr>>),
|
// Spans(Vec<Span<Z::Addr>>),
|
||||||
/// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`].
|
/// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`].
|
||||||
NextNeededPruningSeed(PruningSeed),
|
NextNeededPruningSeed(PruningSeed),
|
||||||
|
|
||||||
|
/// Response to [`BlockchainManagerRequest::CreateBlockTemplate`].
|
||||||
|
CreateBlockTemplate(Box<BlockTemplate>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: use real type when public.
|
/// TODO: use real type when public.
|
||||||
|
|
|
@ -20,6 +20,7 @@ use cuprate_constants::{
|
||||||
};
|
};
|
||||||
use cuprate_helper::{
|
use cuprate_helper::{
|
||||||
cast::{u32_to_usize, u64_to_usize, usize_to_u64},
|
cast::{u32_to_usize, u64_to_usize, usize_to_u64},
|
||||||
|
fmt::HexPrefix,
|
||||||
map::split_u128_into_low_high_bits,
|
map::split_u128_into_low_high_bits,
|
||||||
};
|
};
|
||||||
use cuprate_hex::Hex;
|
use cuprate_hex::Hex;
|
||||||
|
@ -53,7 +54,7 @@ use cuprate_rpc_types::{
|
||||||
};
|
};
|
||||||
use cuprate_types::{
|
use cuprate_types::{
|
||||||
rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry},
|
rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry},
|
||||||
HardFork,
|
BlockTemplate, HardFork,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -160,65 +161,50 @@ async fn get_block_template(
|
||||||
return Err(anyhow!("Mining to subaddress is not supported yet"));
|
return Err(anyhow!("Mining to subaddress is not supported yet"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// block b;
|
let blob_reserve = hex::decode(request.extra_nonce)?;
|
||||||
// cryptonote::blobdata blob_reserve;
|
let prev_block = helper::hex_to_hash(request.prev_block)?;
|
||||||
// size_t reserved_offset;
|
let extra_nonce = hex::decode(request.extra_nonce)?;
|
||||||
// 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);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// res.reserved_offset = reserved_offset;
|
let BlockTemplate {
|
||||||
// store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64);
|
block,
|
||||||
// blobdata block_blob = t_serializable_object_to_blob(b);
|
reserved_offset,
|
||||||
// blobdata hashing_blob = get_block_hashing_blob(b);
|
difficulty,
|
||||||
// res.prev_hash = string_tools::pod_to_hex(b.prev_id);
|
height,
|
||||||
// res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
|
expected_reward,
|
||||||
// res.blockhashing_blob = string_tools::buff_to_hex_nodelimer(hashing_blob);
|
seed_height,
|
||||||
// res.status = CORE_RPC_STATUS_OK;
|
seed_hash,
|
||||||
// return true;
|
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 {
|
Ok(GetBlockTemplateResponse {
|
||||||
base: ResponseBase::OK,
|
base: ResponseBase::OK,
|
||||||
blockhashing_blob: todo!(),
|
blockhashing_blob,
|
||||||
blocktemplate_blob: todo!(),
|
blocktemplate_blob,
|
||||||
difficulty_top64: todo!(),
|
difficulty_top64,
|
||||||
difficulty: todo!(),
|
difficulty,
|
||||||
expected_reward: todo!(),
|
expected_reward,
|
||||||
height: todo!(),
|
height,
|
||||||
next_seed_hash: todo!(),
|
next_seed_hash,
|
||||||
prev_hash: todo!(),
|
prev_hash,
|
||||||
reserved_offset: todo!(),
|
reserved_offset,
|
||||||
seed_hash: todo!(),
|
seed_hash,
|
||||||
seed_height: todo!(),
|
seed_height,
|
||||||
wide_difficulty: todo!(),
|
wide_difficulty,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ use cuprate_constants::rpc::{
|
||||||
MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT, RESTRICTED_SPENT_KEY_IMAGES_COUNT,
|
MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT, RESTRICTED_SPENT_KEY_IMAGES_COUNT,
|
||||||
};
|
};
|
||||||
use cuprate_helper::cast::usize_to_u64;
|
use cuprate_helper::cast::usize_to_u64;
|
||||||
|
use cuprate_hex::Hex;
|
||||||
use cuprate_rpc_interface::RpcHandler;
|
use cuprate_rpc_interface::RpcHandler;
|
||||||
use cuprate_rpc_types::{
|
use cuprate_rpc_types::{
|
||||||
base::{AccessResponseBase, ResponseBase},
|
base::{AccessResponseBase, ResponseBase},
|
||||||
|
@ -100,7 +101,7 @@ async fn get_height(
|
||||||
request: GetHeightRequest,
|
request: GetHeightRequest,
|
||||||
) -> Result<GetHeightResponse, Error> {
|
) -> Result<GetHeightResponse, Error> {
|
||||||
let (height, hash) = helper::top_height(&mut state).await?;
|
let (height, hash) = helper::top_height(&mut state).await?;
|
||||||
let hash = hex::encode(hash);
|
let hash = Hex(hash);
|
||||||
|
|
||||||
Ok(GetHeightResponse {
|
Ok(GetHeightResponse {
|
||||||
base: ResponseBase::OK,
|
base: ResponseBase::OK,
|
||||||
|
@ -142,9 +143,8 @@ async fn is_key_image_spent(
|
||||||
|
|
||||||
let mut spent_status = Vec::with_capacity(request.key_images.len());
|
let mut spent_status = Vec::with_capacity(request.key_images.len());
|
||||||
|
|
||||||
for hex in request.key_images {
|
for key_image in request.key_images {
|
||||||
let key_image = helper::hex_to_hash(hex)?;
|
let status = helper::key_image_spent(&mut state, key_image.0).await?;
|
||||||
let status = helper::key_image_spent(&mut state, key_image).await?;
|
|
||||||
spent_status.push(status.to_u8());
|
spent_status.push(status.to_u8());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Functions to send [`BlockchainManagerRequest`]s.
|
//! Functions to send [`BlockchainManagerRequest`]s.
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use cuprate_types::BlockTemplate;
|
||||||
use monero_serai::block::Block;
|
use monero_serai::block::Block;
|
||||||
use tower::{Service, ServiceExt};
|
use tower::{Service, ServiceExt};
|
||||||
|
|
||||||
|
@ -218,3 +219,26 @@ pub(crate) async fn next_needed_pruning_seed(
|
||||||
|
|
||||||
Ok(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)
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,41 @@
|
||||||
//! Formatting.
|
//! 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`.
|
macro_rules! impl_hex_prefix {
|
||||||
///
|
($(
|
||||||
/// ```rust
|
$t:ty
|
||||||
/// # use cuprate_helper::fmt::hex_prefix_u128;
|
),*) => {
|
||||||
/// assert_eq!(hex_prefix_u128(0, 0), "0x0");
|
$(
|
||||||
/// assert_eq!(hex_prefix_u128(0, u64::MAX), "0xffffffffffffffff0000000000000000");
|
impl HexPrefix for $t {
|
||||||
/// assert_eq!(hex_prefix_u128(u64::MAX, 0), "0xffffffffffffffff");
|
fn hex_prefix(self) -> String {
|
||||||
/// assert_eq!(hex_prefix_u128(u64::MAX, u64::MAX), "0xffffffffffffffffffffffffffffffff");
|
format!("{:#x}", self)
|
||||||
/// ```
|
}
|
||||||
pub fn hex_prefix_u128(low_bits: u64, high_bits: u64) -> String {
|
}
|
||||||
format!("{:#x}", combine_low_high_bits_to_u128(low_bits, high_bits))
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::{
|
||||||
time::Duration,
|
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_hex::Hex;
|
||||||
use cuprate_p2p_core::{
|
use cuprate_p2p_core::{
|
||||||
types::{ConnectionId, ConnectionInfo, SetBan, Span},
|
types::{ConnectionId, ConnectionInfo, SetBan, Span},
|
||||||
|
@ -40,11 +40,9 @@ impl From<BlockHeader> for crate::misc::BlockHeader {
|
||||||
timestamp: x.timestamp,
|
timestamp: x.timestamp,
|
||||||
// FIXME: if we made a type that automatically did `hex_prefix_u128`,
|
// FIXME: if we made a type that automatically did `hex_prefix_u128`,
|
||||||
// we wouldn't need `crate::misc::BlockHeader`.
|
// we wouldn't need `crate::misc::BlockHeader`.
|
||||||
wide_cumulative_difficulty: hex_prefix_u128(
|
wide_cumulative_difficulty: (x.cumulative_difficulty, x.cumulative_difficulty_top64)
|
||||||
x.cumulative_difficulty,
|
.hex_prefix(),
|
||||||
x.cumulative_difficulty_top64,
|
wide_difficulty: (x.difficulty, x.difficulty_top64).hex_prefix(),
|
||||||
),
|
|
||||||
wide_difficulty: hex_prefix_u128(x.difficulty, x.difficulty_top64),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +130,7 @@ impl From<ChainInfo> for crate::misc::ChainInfo {
|
||||||
height: x.height,
|
height: x.height,
|
||||||
length: x.length,
|
length: x.length,
|
||||||
main_chain_parent_block: Hex(x.main_chain_parent_block),
|
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
1
types/hex/src/prefix.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -24,8 +24,8 @@ pub use transaction_verification_data::{
|
||||||
CachedVerificationState, TransactionVerificationData, TxVersion,
|
CachedVerificationState, TransactionVerificationData, TxVersion,
|
||||||
};
|
};
|
||||||
pub use types::{
|
pub use types::{
|
||||||
AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, OutputOnChain, TxsInBlock,
|
AltBlockInformation, BlockTemplate, Chain, ChainId, ExtendedBlockHeader, OutputOnChain,
|
||||||
VerifiedBlockInformation, VerifiedTransactionInformation,
|
TxsInBlock, VerifiedBlockInformation, VerifiedTransactionInformation,
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Feature-gated
|
//---------------------------------------------------------------------------------------------------- Feature-gated
|
||||||
|
|
|
@ -154,6 +154,19 @@ pub struct TxsInBlock {
|
||||||
pub txs: Vec<Vec<u8>>,
|
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
|
//---------------------------------------------------------------------------------------------------- Tests
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
Loading…
Reference in a new issue