diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index a9bbba6..e5f316e 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -5,6 +5,7 @@ use std::task::{Context, Poll}; use anyhow::Error; use cuprate_consensus::BlockChainContextService; use cuprate_pruning::PruningSeed; +use cuprate_types::HardFork; use futures::future::BoxFuture; use monero_serai::block::Block; use tower::Service; @@ -56,6 +57,18 @@ pub enum BlockchainManagerRequest { /// The height of the next block in the chain. TargetHeight, + + /// Calculate proof-of-work for this block. + CalculatePow { + /// The hardfork of the protocol at this block height. + hardfork: HardFork, + /// The height of the block. + height: usize, + /// The block data. + block: Block, + /// The seed hash for the proof-of-work. + seed_hash: [u8; 32], + }, } /// TODO: use real type when public. @@ -88,6 +101,9 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::TargetHeight`] TargetHeight { height: usize }, + + /// Response to [`BlockchainManagerRequest::CalculatePow`] + CalculatePow([u8; 32]), } /// TODO: use real type when public. diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 65bc64e..ba42af7 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -734,10 +734,26 @@ async fn prune_blockchain( /// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2035-L2070> async fn calc_pow( - state: CupratedRpcHandler, - request: CalcPowRequest, + mut state: CupratedRpcHandler, + mut request: CalcPowRequest, ) -> Result<CalcPowResponse, Error> { - Ok(CalcPowResponse { pow_hash: todo!() }) + let hardfork = HardFork::from_version(request.major_version)?; + let mut block_blob: Vec<u8> = hex::decode(request.block_blob)?; + let block = Block::read(&mut block_blob.as_slice())?; + let seed_hash = helper::hex_to_hash(request.seed_hash)?; + + let pow_hash = blockchain_manager::calculate_pow( + &mut state.blockchain_manager, + hardfork, + request.height, + block, + seed_hash, + ) + .await?; + + let hex = hex::encode(pow_hash); + + Ok(CalcPowResponse { pow_hash: hex }) } /// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3542-L3551> diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 96547ba..bd81cc0 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -1,6 +1,7 @@ //! Functions for [`BlockchainManagerRequest`] & [`BlockchainManagerResponse`]. use anyhow::Error; +use cuprate_types::HardFork; use monero_serai::block::Block; use tower::{Service, ServiceExt}; @@ -142,3 +143,28 @@ pub(crate) async fn target_height( Ok(usize_to_u64(height)) } + +/// [`BlockchainManagerRequest::CalculatePow`] +pub(crate) async fn calculate_pow( + blockchain_manager: &mut BlockchainManagerHandle, + hardfork: HardFork, + height: u64, + block: Block, + seed_hash: [u8; 32], +) -> Result<[u8; 32], Error> { + let BlockchainManagerResponse::CalculatePow(hash) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::CalculatePow { + hardfork, + height: u64_to_usize(height), + block, + seed_hash, + }) + .await? + else { + unreachable!(); + }; + + Ok(hash) +}