From 7148ba16687c488925c9bc3ecd3fd8f9cdd94731 Mon Sep 17 00:00:00 2001
From: "hinto.janai" <hinto.janai@protonmail.com>
Date: Tue, 15 Oct 2024 16:45:54 -0400
Subject: [PATCH] add_aux_pow

---
 binaries/cuprated/src/rpc/handler.rs          | 15 ++++--
 binaries/cuprated/src/rpc/json.rs             | 46 +++++++++++++++----
 .../src/rpc/request/blockchain_manager.rs     | 23 +++++++++-
 types/src/blockchain.rs                       |  1 +
 types/src/lib.rs                              |  7 +--
 types/src/types.rs                            | 17 +++++++
 6 files changed, 94 insertions(+), 15 deletions(-)

diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs
index e5f316e5..b952bd85 100644
--- a/binaries/cuprated/src/rpc/handler.rs
+++ b/binaries/cuprated/src/rpc/handler.rs
@@ -3,14 +3,13 @@
 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;
 
 use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
+use cuprate_consensus::BlockChainContextService;
+use cuprate_pruning::PruningSeed;
 use cuprate_rpc_interface::RpcHandler;
 use cuprate_rpc_types::{
     bin::{BinRequest, BinResponse},
@@ -18,6 +17,7 @@ use cuprate_rpc_types::{
     other::{OtherRequest, OtherResponse},
 };
 use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle};
+use cuprate_types::{AddAuxPow, AuxPow, HardFork};
 
 use crate::rpc::{bin, json, other};
 
@@ -69,6 +69,12 @@ pub enum BlockchainManagerRequest {
         /// The seed hash for the proof-of-work.
         seed_hash: [u8; 32],
     },
+
+    /// TODO
+    AddAuxPow {
+        blocktemplate_blob: Vec<u8>,
+        aux_pow: Vec<AuxPow>,
+    },
 }
 
 /// TODO: use real type when public.
@@ -104,6 +110,9 @@ pub enum BlockchainManagerResponse {
 
     /// Response to [`BlockchainManagerRequest::CalculatePow`]
     CalculatePow([u8; 32]),
+
+    /// Response to [`BlockchainManagerRequest::AddAuxPow`]
+    AddAuxPow(AddAuxPow),
 }
 
 /// TODO: use real type when public.
diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs
index ba42af70..b3cb1f2c 100644
--- a/binaries/cuprated/src/rpc/json.rs
+++ b/binaries/cuprated/src/rpc/json.rs
@@ -40,7 +40,10 @@ use cuprate_rpc_types::{
         SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest,
         SyncInfoResponse,
     },
-    misc::{BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, TxBacklogEntry},
+    misc::{
+        AuxPow, BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status,
+        TxBacklogEntry,
+    },
     CORE_RPC_VERSION,
 };
 use cuprate_types::HardFork;
@@ -761,7 +764,7 @@ async fn flush_cache(
     state: CupratedRpcHandler,
     request: FlushCacheRequest,
 ) -> Result<FlushCacheResponse, Error> {
-    todo!();
+    // TODO: cuprated doesn't need this call; decide behavior.
 
     Ok(FlushCacheResponse {
         base: ResponseBase::OK,
@@ -770,16 +773,43 @@ async fn flush_cache(
 
 /// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2072-L2207>
 async fn add_aux_pow(
-    state: CupratedRpcHandler,
+    mut state: CupratedRpcHandler,
     request: AddAuxPowRequest,
 ) -> Result<AddAuxPowResponse, Error> {
+    let blocktemplate_blob = hex::decode(request.blocktemplate_blob)?;
+    let aux_pow = request
+        .aux_pow
+        .into_iter()
+        .map(|aux| {
+            let id = helper::hex_to_hash(aux.id)?;
+            let hash = helper::hex_to_hash(aux.hash)?;
+            Ok(cuprate_types::AuxPow { id, hash })
+        })
+        .collect::<Result<Vec<_>, Error>>()?;
+
+    let resp =
+        blockchain_manager::add_aux_pow(&mut state.blockchain_manager, blocktemplate_blob, aux_pow)
+            .await?;
+
+    let blocktemplate_blob = hex::encode(resp.blocktemplate_blob);
+    let blockhashing_blob = hex::encode(resp.blockhashing_blob);
+    let merkle_root = hex::encode(resp.merkle_root);
+    let aux_pow = resp
+        .aux_pow
+        .into_iter()
+        .map(|aux| AuxPow {
+            id: hex::encode(aux.id),
+            hash: hex::encode(aux.hash),
+        })
+        .collect::<Vec<AuxPow>>();
+
     Ok(AddAuxPowResponse {
         base: ResponseBase::OK,
-        blocktemplate_blob: todo!(),
-        blockhashing_blob: todo!(),
-        merkle_root: todo!(),
-        merkle_tree_depth: todo!(),
-        aux_pow: todo!(),
+        blocktemplate_blob,
+        blockhashing_blob,
+        merkle_root,
+        merkle_tree_depth: resp.merkle_tree_depth,
+        aux_pow,
     })
 }
 
diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs
index bd81cc01..da84b08d 100644
--- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs
+++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs
@@ -1,7 +1,7 @@
 //! Functions for [`BlockchainManagerRequest`] & [`BlockchainManagerResponse`].
 
 use anyhow::Error;
-use cuprate_types::HardFork;
+use cuprate_types::{AddAuxPow, AuxPow, HardFork};
 use monero_serai::block::Block;
 use tower::{Service, ServiceExt};
 
@@ -168,3 +168,24 @@ pub(crate) async fn calculate_pow(
 
     Ok(hash)
 }
+
+/// [`BlockchainManagerRequest::AddAuxPow`]
+pub(crate) async fn add_aux_pow(
+    blockchain_manager: &mut BlockchainManagerHandle,
+    blocktemplate_blob: Vec<u8>,
+    aux_pow: Vec<AuxPow>,
+) -> Result<AddAuxPow, Error> {
+    let BlockchainManagerResponse::AddAuxPow(response) = blockchain_manager
+        .ready()
+        .await?
+        .call(BlockchainManagerRequest::AddAuxPow {
+            blocktemplate_blob,
+            aux_pow,
+        })
+        .await?
+    else {
+        unreachable!();
+    };
+
+    Ok(response)
+}
diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs
index e53619bc..5b408dea 100644
--- a/types/src/blockchain.rs
+++ b/types/src/blockchain.rs
@@ -289,6 +289,7 @@ pub enum BlockchainResponse {
     /// - Value = hardfork version
     HardForks(BTreeMap<usize, HardFork>),
 
+    /// TODO
     AltChains(Vec<ChainInfo>),
 
     //------------------------------------------------------ Writes
diff --git a/types/src/lib.rs b/types/src/lib.rs
index 0fd1ec7b..fa35153b 100644
--- a/types/src/lib.rs
+++ b/types/src/lib.rs
@@ -20,9 +20,10 @@ pub use transaction_verification_data::{
     CachedVerificationState, TransactionVerificationData, TxVersion,
 };
 pub use types::{
-    AltBlockInformation, Chain, ChainId, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader,
-    FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry, OutputHistogramEntry,
-    OutputHistogramInput, OutputOnChain, VerifiedBlockInformation, VerifiedTransactionInformation,
+    AddAuxPow, AltBlockInformation, AuxPow, Chain, ChainId, ChainInfo, CoinbaseTxSum,
+    ExtendedBlockHeader, FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry,
+    OutputHistogramEntry, OutputHistogramInput, OutputOnChain, VerifiedBlockInformation,
+    VerifiedTransactionInformation,
 };
 
 //---------------------------------------------------------------------------------------------------- Feature-gated
diff --git a/types/src/types.rs b/types/src/types.rs
index a6833758..720ad0a7 100644
--- a/types/src/types.rs
+++ b/types/src/types.rs
@@ -242,6 +242,23 @@ pub struct ChainInfo {
     pub main_chain_parent_block: [u8; 32],
 }
 
+/// Used in RPC's `add_aux_pow`.
+#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct AuxPow {
+    pub id: [u8; 32],
+    pub hash: [u8; 32],
+}
+
+/// Used in RPC's `add_aux_pow`.
+#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct AddAuxPow {
+    pub blocktemplate_blob: Vec<u8>,
+    pub blockhashing_blob: Vec<u8>,
+    pub merkle_root: [u8; 32],
+    pub merkle_tree_depth: u64,
+    pub aux_pow: Vec<AuxPow>,
+}
+
 //---------------------------------------------------------------------------------------------------- Tests
 #[cfg(test)]
 mod test {