diff --git a/binaries/cuprated/src/rpc/blockchain.rs b/binaries/cuprated/src/rpc/blockchain.rs index b96c5618..bda998c5 100644 --- a/binaries/cuprated/src/rpc/blockchain.rs +++ b/binaries/cuprated/src/rpc/blockchain.rs @@ -130,6 +130,24 @@ pub(super) async fn block_hash( Ok(hash) } +/// [`BlockchainResponse::KeyImageSpent`] +pub(super) async fn key_image_spent( + state: &mut CupratedRpcHandlerState, + key_image: [u8; 32], +) -> Result { + let BlockchainResponse::KeyImageSpent(is_spent) = state + .blockchain + .ready() + .await? + .call(BlockchainReadRequest::KeyImageSpent(key_image)) + .await? + else { + unreachable!(); + }; + + Ok(is_spent) +} + // FindBlock([u8; 32]), // FilterUnknownHashes(HashSet<[u8; 32]>), // BlockExtendedHeaderInRange(Range, Chain), diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index 43e6a427..d683ae91 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use anyhow::{anyhow, Error}; -use cuprate_rpc_types::misc::BlockHeader; +use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus}; use futures::StreamExt; use tower::{Service, ServiceExt}; @@ -97,3 +97,17 @@ pub(super) async fn top_height( let height = chain_height.saturating_sub(1); Ok((height, hash)) } + +/// TODO +pub(super) async fn key_image_spent( + state: &mut CupratedRpcHandlerState, + key_image: [u8; 32], +) -> Result { + 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) + } +} diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index fd8cb89b..babfdc34 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -486,7 +486,8 @@ async fn relay_tx( state: CupratedRpcHandlerState, request: RelayTxRequest, ) -> Result { - Ok(RelayTxResponse { status: todo!() }) + todo!(); + Ok(RelayTxResponse { status: Status::Ok }) } /// diff --git a/binaries/cuprated/src/rpc/other.rs b/binaries/cuprated/src/rpc/other.rs index d215ce29..b5650a5e 100644 --- a/binaries/cuprated/src/rpc/other.rs +++ b/binaries/cuprated/src/rpc/other.rs @@ -1,8 +1,8 @@ -use anyhow::Error; +use anyhow::{anyhow, Error}; use cuprate_rpc_types::{ base::{AccessResponseBase, ResponseBase}, - misc::Status, + misc::{KeyImageSpentStatus, Status}, other::{ GetAltBlocksHashesRequest, GetAltBlocksHashesResponse, GetHeightRequest, GetHeightResponse, GetLimitRequest, GetLimitResponse, GetNetStatsRequest, GetNetStatsResponse, GetOutsRequest, @@ -22,7 +22,12 @@ use cuprate_rpc_types::{ }, }; -use crate::rpc::CupratedRpcHandlerState; +use crate::{ + rpc::CupratedRpcHandlerState, + rpc::{blockchain, helper}, +}; + +use super::RESTRICTED_SPENT_KEY_IMAGES_COUNT; /// Map a [`OtherRequest`] to the function that will lead to a [`OtherResponse`]. pub(super) async fn map_request( @@ -77,12 +82,16 @@ pub(super) async fn map_request( /// async fn get_height( - state: CupratedRpcHandlerState, + mut state: CupratedRpcHandlerState, request: GetHeightRequest, ) -> Result { + let (height, hash) = helper::top_height(&mut state).await?; + let hash = hex::encode(hash); + Ok(GetHeightResponse { base: ResponseBase::ok(), - ..todo!() + height, + hash, }) } @@ -110,12 +119,24 @@ async fn get_alt_blocks_hashes( /// async fn is_key_image_spent( - state: CupratedRpcHandlerState, + mut state: CupratedRpcHandlerState, request: IsKeyImageSpentRequest, ) -> Result { + if state.restricted && request.key_images.len() > RESTRICTED_SPENT_KEY_IMAGES_COUNT { + return Err(anyhow!("Too many key images queried in restricted mode")); + } + + 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?; + spent_status.push(status.to_u8()); + } + Ok(IsKeyImageSpentResponse { base: AccessResponseBase::ok(), - ..todo!() + spent_status, }) }