فهرست منبع

mmproxy: Working daemon-mode mining

parazyd 2 سال پیش
والد
کامیت
8b615e99b6
5فایلهای تغییر یافته به همراه49 افزوده شده و 23 حذف شده
  1. 1 2
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 3 3
      bin/darkfi-mmproxy/darkfi_mmproxy.toml
  4. 16 13
      bin/darkfi-mmproxy/src/main.rs
  5. 28 5
      bin/darkfi-mmproxy/src/monerod.rs

+ 1 - 2
Cargo.lock

@@ -4018,8 +4018,7 @@ dependencies = [
 [[package]]
 name = "monero"
 version = "0.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdf671c5fd0fa1f1dcc2495b6ca97a83f0aa6b2a737957e773d34c6c6bac0659"
+source = "git+https://github.com/parazyd/monero-rs?branch=blockhashing_blob-fix#3b7ddd075610cbff9a6692ec3e72f7ee88a628f1"
 dependencies = [
  "base58-monero",
  "curve25519-dalek 4.1.1",

+ 1 - 0
Cargo.toml

@@ -319,3 +319,4 @@ zkas = [
 [patch.crates-io]
 halo2_proofs = {git="https://github.com/parazyd/halo2", branch="v4"}
 halo2_gadgets = {git="https://github.com/parazyd/halo2", branch="v4"}
+monero = {git="https://github.com/parazyd/monero-rs", branch="blockhashing_blob-fix"}

+ 3 - 3
bin/darkfi-mmproxy/darkfi_mmproxy.toml

@@ -9,13 +9,13 @@
 #[mmproxy]
 # darkfi-mmproxy daemon listen URL.
 # This is where XMRig can connect to with a daemon (solomining) endpoint.
-#rpc = "http://127.0.0.1:3333"
+#mmproxy_rpc = "http://127.0.0.1:3333"
 
 #[monerod]
 # monerod RPC address.
 # This is the monerod endpoint which is proxied by mmproxy.
-#rpc = "http://127.0.0.1:18081"
+#monero_rpc = "http://127.0.0.1:18081"
 
 # Monero network to use (mainnet/testnet)
 # Used to validate miner reward addresses.
-#network = "mainnet"
+#monero_network = "mainnet"

+ 16 - 13
bin/darkfi-mmproxy/src/main.rs

@@ -61,7 +61,7 @@ struct Args {
 struct MmproxyArgs {
     #[structopt(long, default_value = "http://127.0.0.1:3333")]
     /// darkfi-mmproxy JSON-RPC server listen URL
-    rpc: Url,
+    mmproxy_rpc: Url,
 }
 
 #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
@@ -69,40 +69,43 @@ struct MmproxyArgs {
 struct MonerodArgs {
     #[structopt(long, default_value = "mainnet")]
     /// Monero network type (mainnet/testnet)
-    network: String,
+    monero_network: String,
 
     #[structopt(long, default_value = "http://127.0.0.1:18081")]
     /// monerod JSON-RPC server listen URL
-    rpc: Url,
+    monero_rpc: Url,
 }
 
 /// Mining proxy state
 struct MiningProxy {
-    /// monerod network type
-    monerod_network: monero::Network,
-    /// monerod RPC address
-    monerod_rpc: Url,
+    /// Monero network type
+    monero_network: monero::Network,
+    /// Monero RPC address
+    monero_rpc: Url,
 }
 
 impl MiningProxy {
     /// Instantiate `MiningProxy` state
     async fn new(monerod: MonerodArgs) -> Result<Self> {
-        let monerod_network = match monerod.network.to_lowercase().as_str() {
+        let monero_network = match monerod.monero_network.to_lowercase().as_str() {
             "mainnet" => monero::Network::Mainnet,
             "testnet" => monero::Network::Testnet,
             _ => {
-                error!("Invalid Monero network \"{}\"", monerod.network);
-                return Err(Error::Custom(format!("Invalid Monero network \"{}\"", monerod.network)))
+                error!("Invalid Monero network \"{}\"", monerod.monero_network);
+                return Err(Error::Custom(format!(
+                    "Invalid Monero network \"{}\"",
+                    monerod.monero_network
+                )))
             }
         };
 
         // Test that monerod RPC is reachable
-        if let Err(e) = TcpStream::connect(monerod.rpc.socket_addrs(|| None)?[0]).await {
+        if let Err(e) = TcpStream::connect(monerod.monero_rpc.socket_addrs(|| None)?[0]).await {
             error!("Failed connecting to monerod RPC: {}", e);
             return Err(e.into())
         }
 
-        Ok(Self { monerod_network, monerod_rpc: monerod.rpc })
+        Ok(Self { monero_network, monero_rpc: monerod.monero_rpc })
     }
 }
 
@@ -173,7 +176,7 @@ async fn realmain(args: Args, ex: Arc<Executor<'static>>) -> Result<()> {
         Ok(return_data)
     });
 
-    ex.spawn(async move { app.listen(args.mmproxy.rpc).await.unwrap() }).detach();
+    ex.spawn(async move { app.listen(args.mmproxy.mmproxy_rpc).await.unwrap() }).detach();
     info!("Merge mining proxy ready, waiting for connections");
 
     // Signal handling for graceful termination.

+ 28 - 5
bin/darkfi-mmproxy/src/monerod.rs

@@ -33,7 +33,7 @@ use super::MiningProxy;
 impl MiningProxy {
     /// Perform a JSON-RPC GET request to monerod's endpoint with the given method
     async fn monero_get_request(&self, method: &str) -> Result<JsonValue> {
-        let endpoint = format!("{}{}", self.monerod_rpc, method);
+        let endpoint = format!("{}{}", self.monero_rpc, method);
         debug!(target: "monerod::monero_get_request", "--> {}", endpoint);
 
         let mut rep = match surf::get(&endpoint).await {
@@ -79,7 +79,7 @@ impl MiningProxy {
     /// Perform a JSON-RPC POST request to monerod's endpoint with the given method
     /// and JSON-RPC request
     pub async fn monero_post_request(&self, req: JsonRequest) -> Result<JsonValue> {
-        let endpoint = format!("{}json_rpc", self.monerod_rpc);
+        let endpoint = format!("{}json_rpc", self.monero_rpc);
         debug!(target: "monerod::monero_post_request", "--> {}", endpoint);
 
         let client = surf::Client::new();
@@ -161,6 +161,23 @@ impl MiningProxy {
     /// Proxy the `submitblock` RPC request
     pub async fn monerod_submit_block(&self, req: &JsonValue) -> Result<JsonValue> {
         let request = JsonRequest::try_from(req)?;
+        debug!(target: "monerod::submitblock", "--> {}", req.stringify()?);
+
+        if !request.params.is_array() {
+            return Err(Error::Custom("Invalid request".to_string()))
+        }
+
+        for block in request.params.get::<Vec<JsonValue>>().unwrap() {
+            let Some(block) = block.get::<String>() else {
+                return Err(Error::Custom("Invalid request".to_string()))
+            };
+
+            debug!(
+                target: "monerod::submitblock", "{:#?}",
+                monero::consensus::deserialize::<monero::Block>(&hex::decode(block).unwrap()).unwrap(),
+            );
+        }
+
         let response = self.monero_post_request(request).await?;
         Ok(response)
     }
@@ -169,13 +186,14 @@ impl MiningProxy {
     /// merge mining data.
     pub async fn monerod_getblocktemplate(&self, req: &JsonValue) -> Result<JsonValue> {
         let mut request = JsonRequest::try_from(req)?;
+        debug!(target: "monerod::getblocktemplate", "--> {}", req.stringify()?);
 
         if !request.params.is_object() {
             return Err(Error::Custom("Invalid request".to_string()))
         }
 
         let params: &mut HashMap<String, JsonValue> = request.params.get_mut().unwrap();
-        if !params.contains_key("wallet_address") || !params.contains_key("reserve_size") {
+        if !params.contains_key("wallet_address") {
             return Err(Error::Custom("Invalid request".to_string()))
         }
 
@@ -187,7 +205,7 @@ impl MiningProxy {
             return Err(Error::Custom("Invalid request".to_string()))
         };
 
-        if wallet_address.network != self.monerod_network {
+        if wallet_address.network != self.monero_network {
             return Err(Error::Custom("Monero network address mismatch".to_string()))
         }
 
@@ -203,10 +221,15 @@ impl MiningProxy {
         let tx_extra: RawExtraField = ExtraField(vec![mm_tag]).into();
 
         // Modify the params `reserve_size` to fit our Merge Mining data
-        *params.get_mut("reserve_size").unwrap() = (tx_extra.0.len() as f64).into();
+        debug!(target: "monerod::getblocktemplate", "Inserting \"reserve_size\":{}", tx_extra.0.len());
+        params.insert("reserve_size".to_string(), (tx_extra.0.len() as f64).into());
+
+        // Remove `extra_nonce` from the request, XMRig tends to send this in daemon-mode
+        params.remove("extra_nonce");
 
         // Perform the `getblocktemplate` call:
         let gbt_response = self.monero_post_request(request).await?;
+        debug!(target: "monerod::getblocktemplate", "Got {}", gbt_response.stringify()?);
         let mut gbt_response = JsonResponse::try_from(&gbt_response)?;
         let gbt_result: &mut HashMap<String, JsonValue> = gbt_response.result.get_mut().unwrap();