From 548639b2f697e376a58ea3f15284c19a2d98d6a5 Mon Sep 17 00:00:00 2001
From: "hinto.janai" <hinto.janai@protonmail.com>
Date: Tue, 15 Oct 2024 20:14:15 -0400
Subject: [PATCH] generate_blocks

---
 binaries/cuprated/src/rpc/handler.rs          | 23 ++++++++++++++++-
 binaries/cuprated/src/rpc/json.rs             | 25 ++++++++++++++++---
 .../src/rpc/request/blockchain_manager.rs     | 25 +++++++++++++++++++
 3 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs
index b952bd85..befecfe4 100644
--- a/binaries/cuprated/src/rpc/handler.rs
+++ b/binaries/cuprated/src/rpc/handler.rs
@@ -23,7 +23,6 @@ use crate::rpc::{bin, json, other};
 
 /// TODO: use real type when public.
 #[derive(Clone)]
-#[expect(clippy::large_enum_variant)]
 pub enum BlockchainManagerRequest {
     /// Pop blocks off the top of the blockchain.
     ///
@@ -72,9 +71,23 @@ pub enum BlockchainManagerRequest {
 
     /// TODO
     AddAuxPow {
+        /// TODO
         blocktemplate_blob: Vec<u8>,
+        /// TODO
         aux_pow: Vec<AuxPow>,
     },
+
+    /// TODO
+    GenerateBlocks {
+        /// TODO
+        amount_of_blocks: u64,
+        /// TODO
+        prev_block: [u8; 32],
+        /// TODO
+        starting_nonce: u32,
+        /// TODO
+        wallet_address: String,
+    },
 }
 
 /// TODO: use real type when public.
@@ -113,6 +126,14 @@ pub enum BlockchainManagerResponse {
 
     /// Response to [`BlockchainManagerRequest::AddAuxPow`]
     AddAuxPow(AddAuxPow),
+
+    /// Response to [`BlockchainManagerRequest::GenerateBlocks`]
+    GenerateBlocks {
+        /// TODO
+        blocks: Vec<[u8; 32]>,
+        /// TODO
+        height: usize,
+    },
 }
 
 /// TODO: use real type when public.
diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs
index e8872dfe..24798b30 100644
--- a/binaries/cuprated/src/rpc/json.rs
+++ b/binaries/cuprated/src/rpc/json.rs
@@ -46,7 +46,7 @@ use cuprate_rpc_types::{
     },
     CORE_RPC_VERSION,
 };
-use cuprate_types::HardFork;
+use cuprate_types::{Chain, HardFork};
 
 use crate::rpc::{
     helper,
@@ -161,10 +161,29 @@ async fn generate_blocks(
     state: CupratedRpcHandler,
     request: GenerateBlocksRequest,
 ) -> Result<GenerateBlocksResponse, Error> {
+    if todo!("active cuprated chain") != todo!("regtest chain") {
+        return Err(anyhow!("Regtest required when generating blocks"));
+    }
+
+    // TODO: is this value only used as a local variable in the handler?
+    // it may not be needed in the request type.
+    let prev_block = helper::hex_to_hash(request.prev_block)?;
+
+    let (blocks, height) = blockchain_manager::generate_blocks(
+        &mut state.blockchain_manager,
+        request.amount_of_blocks,
+        prev_block,
+        request.starting_nonce,
+        request.wallet_address,
+    )
+    .await?;
+
+    let blocks = blocks.into_iter().map(hex::encode).collect();
+
     Ok(GenerateBlocksResponse {
         base: ResponseBase::OK,
-        blocks: todo!(),
-        height: todo!(),
+        blocks,
+        height,
     })
 }
 
diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs
index da84b08d..ba281121 100644
--- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs
+++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs
@@ -189,3 +189,28 @@ pub(crate) async fn add_aux_pow(
 
     Ok(response)
 }
+
+/// [`BlockchainManagerRequest::GenerateBlocks`]
+pub(crate) async fn generate_blocks(
+    blockchain_manager: &mut BlockchainManagerHandle,
+    amount_of_blocks: u64,
+    prev_block: [u8; 32],
+    starting_nonce: u32,
+    wallet_address: String,
+) -> Result<(Vec<[u8; 32]>, u64), Error> {
+    let BlockchainManagerResponse::GenerateBlocks { blocks, height } = blockchain_manager
+        .ready()
+        .await?
+        .call(BlockchainManagerRequest::GenerateBlocks {
+            amount_of_blocks,
+            prev_block,
+            starting_nonce,
+            wallet_address,
+        })
+        .await?
+    else {
+        unreachable!();
+    };
+
+    Ok((blocks, usize_to_u64(height)))
+}