From 98eb2f642bc3db2e28eacc52efc90eb324869cb9 Mon Sep 17 00:00:00 2001
From: "hinto.janai" <hinto.janai@protonmail.com>
Date: Fri, 6 Sep 2024 17:58:40 -0400
Subject: [PATCH] `get_block_count`, `on_get_block_hash`,
 `get_block_header_by_hash` todo

---
 binaries/cuprated/src/rpc.rs      |   7 ++
 binaries/cuprated/src/rpc/json.rs | 156 +++++++++++++++++++++++++-----
 2 files changed, 140 insertions(+), 23 deletions(-)

diff --git a/binaries/cuprated/src/rpc.rs b/binaries/cuprated/src/rpc.rs
index 9ebcd1b..1e61cd1 100644
--- a/binaries/cuprated/src/rpc.rs
+++ b/binaries/cuprated/src/rpc.rs
@@ -3,8 +3,15 @@
 //! Will contain the code to initiate the RPC and a request handler.
 
 mod bin;
+mod constants;
 mod handler;
 mod json;
 mod other;
 
+pub use constants::{
+    DEFAULT_PAYMENT_CREDITS_PER_HASH, DEFAULT_PAYMENT_DIFFICULTY, MAX_RESTRICTED_FAKE_OUTS_COUNT,
+    MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT, OUTPUT_HISTOGRAM_RECENT_CUTOFF_RESTRICTION,
+    RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE, RESTRICTED_SPENT_KEY_IMAGES_COUNT,
+    RESTRICTED_TRANSACTIONS_COUNT,
+};
 pub use handler::{CupratedRpcHandler, CupratedRpcHandlerState};
diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs
index ece925e..5eadbc9 100644
--- a/binaries/cuprated/src/rpc/json.rs
+++ b/binaries/cuprated/src/rpc/json.rs
@@ -1,30 +1,41 @@
 use std::sync::Arc;
 
-use tower::ServiceExt;
+use futures::StreamExt;
+use tower::{Service, ServiceExt};
 
+use cuprate_consensus::BlockchainResponse;
+use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
 use cuprate_rpc_interface::RpcError;
-use cuprate_rpc_types::json::{
-    AddAuxPowRequest, AddAuxPowResponse, BannedRequest, BannedResponse, CalcPowRequest,
-    CalcPowResponse, FlushCacheRequest, FlushCacheResponse, FlushTransactionPoolRequest,
-    FlushTransactionPoolResponse, GenerateBlocksRequest, GenerateBlocksResponse,
-    GetAlternateChainsRequest, GetAlternateChainsResponse, GetBansRequest, GetBansResponse,
-    GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest,
-    GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest, GetBlockHeaderByHeightResponse,
-    GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse, GetBlockRequest, GetBlockResponse,
-    GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse, GetConnectionsRequest,
-    GetConnectionsResponse, GetFeeEstimateRequest, GetFeeEstimateResponse, GetInfoRequest,
-    GetInfoResponse, GetLastBlockHeaderRequest, GetLastBlockHeaderResponse, GetMinerDataRequest,
-    GetMinerDataResponse, GetOutputHistogramRequest, GetOutputHistogramResponse,
-    GetTransactionPoolBacklogRequest, GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest,
-    GetTxIdsLooseResponse, GetVersionRequest, GetVersionResponse, HardForkInfoRequest,
-    HardForkInfoResponse, JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest,
-    OnGetBlockHashResponse, PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest,
-    RelayTxResponse, SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse,
-    SyncInfoRequest, SyncInfoResponse,
+use cuprate_rpc_types::{
+    base::{AccessResponseBase, ResponseBase},
+    json::{
+        AddAuxPowRequest, AddAuxPowResponse, BannedRequest, BannedResponse, CalcPowRequest,
+        CalcPowResponse, FlushCacheRequest, FlushCacheResponse, FlushTransactionPoolRequest,
+        FlushTransactionPoolResponse, GenerateBlocksRequest, GenerateBlocksResponse,
+        GetAlternateChainsRequest, GetAlternateChainsResponse, GetBansRequest, GetBansResponse,
+        GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest,
+        GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest,
+        GetBlockHeaderByHeightResponse, GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse,
+        GetBlockRequest, GetBlockResponse, GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse,
+        GetConnectionsRequest, GetConnectionsResponse, GetFeeEstimateRequest,
+        GetFeeEstimateResponse, GetInfoRequest, GetInfoResponse, GetLastBlockHeaderRequest,
+        GetLastBlockHeaderResponse, GetMinerDataRequest, GetMinerDataResponse,
+        GetOutputHistogramRequest, GetOutputHistogramResponse, GetTransactionPoolBacklogRequest,
+        GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, GetTxIdsLooseResponse,
+        GetVersionRequest, GetVersionResponse, HardForkInfoRequest, HardForkInfoResponse,
+        JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, OnGetBlockHashResponse,
+        PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest, RelayTxResponse,
+        SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest,
+        SyncInfoResponse,
+    },
+    misc::BlockHeader,
 };
+use cuprate_types::{blockchain::BlockchainReadRequest, Chain};
 
 use crate::rpc::CupratedRpcHandlerState;
 
+use super::RESTRICTED_BLOCK_COUNT;
+
 /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`].
 pub(super) async fn map_request(
     state: CupratedRpcHandlerState,
@@ -87,14 +98,38 @@ async fn get_block_count(
     state: CupratedRpcHandlerState,
     request: GetBlockCountRequest,
 ) -> Result<GetBlockCountResponse, RpcError> {
-    todo!()
+    let BlockchainResponse::ChainHeight(count, hash) = state
+        .blockchain
+        .oneshot(BlockchainReadRequest::ChainHeight)
+        .await?
+    else {
+        unreachable!();
+    };
+
+    Ok(GetBlockCountResponse {
+        base: ResponseBase::ok(),
+        count: usize_to_u64(count),
+    })
 }
 
 async fn on_get_block_hash(
     state: CupratedRpcHandlerState,
     request: OnGetBlockHashRequest,
 ) -> Result<OnGetBlockHashResponse, RpcError> {
-    todo!()
+    let BlockchainResponse::BlockHash(hash) = state
+        .blockchain
+        .oneshot(BlockchainReadRequest::BlockHash(
+            u64_to_usize(request.block_height[0]),
+            Chain::Main,
+        ))
+        .await?
+    else {
+        unreachable!();
+    };
+
+    Ok(OnGetBlockHashResponse {
+        block_hash: hex::encode(hash),
+    })
 }
 
 async fn submit_block(
@@ -119,10 +154,85 @@ async fn get_last_block_header(
 }
 
 async fn get_block_header_by_hash(
-    state: CupratedRpcHandlerState,
+    mut state: CupratedRpcHandlerState,
     request: GetBlockHeaderByHashRequest,
 ) -> Result<GetBlockHeaderByHashResponse, RpcError> {
-    todo!()
+    let restricted = todo!();
+    if restricted && request.hashes.len() > RESTRICTED_BLOCK_COUNT {
+        let message = "Too many block headers requested in restricted mode";
+        return Err(todo!());
+    }
+
+    async fn get(
+        state: &mut CupratedRpcHandlerState,
+        hex: String,
+        fill_pow_hash: bool,
+    ) -> Result<BlockHeader, ()> {
+        let Ok(bytes) = hex::decode(&hex) else {
+            let message = format!("Failed to parse hex representation of block hash. Hex = {hex}.");
+            return Err(todo!());
+        };
+
+        let Ok(hash) = bytes.try_into() else {
+            let message = "TODO";
+            return Err(todo!());
+        };
+
+        let ready = state.blockchain.ready().await.expect("TODO");
+
+        let BlockchainResponse::BlockExtendedHeaderByHash(header) = ready
+            .call(BlockchainReadRequest::BlockExtendedHeaderByHash(hash))
+            .await
+            .expect("TODO")
+        else {
+            unreachable!();
+        };
+
+        let block_header = BlockHeader {
+            block_size: todo!(),
+            block_weight: todo!(),
+            cumulative_difficulty_top64: todo!(),
+            cumulative_difficulty: todo!(),
+            depth: todo!(),
+            difficulty_top64: todo!(),
+            difficulty: todo!(),
+            hash: todo!(),
+            height: todo!(),
+            long_term_weight: todo!(),
+            major_version: todo!(),
+            miner_tx_hash: todo!(),
+            minor_version: todo!(),
+            nonce: todo!(),
+            num_txes: todo!(),
+            orphan_status: todo!(),
+            pow_hash: todo!(),
+            prev_hash: todo!(),
+            reward: todo!(),
+            timestamp: todo!(),
+            wide_cumulative_difficulty: todo!(),
+            wide_difficulty: todo!(),
+        };
+
+        Ok(block_header)
+    }
+
+    let block_header = get(&mut state, request.hash, request.fill_pow_hash)
+        .await
+        .unwrap();
+
+    let block_headers = Vec::with_capacity(request.hashes.len());
+    for hash in request.hashes {
+        let hash = get(&mut state, hash, request.fill_pow_hash)
+            .await
+            .expect("TODO");
+        block_headers.push(hash);
+    }
+
+    Ok(GetBlockHeaderByHashResponse {
+        base: AccessResponseBase::ok(),
+        block_header,
+        block_headers,
+    })
 }
 
 async fn get_block_header_by_height(