From ecf27eae38c04691e770b04998cd5c1ae43b4953 Mon Sep 17 00:00:00 2001 From: parazyd Date: Fri, 9 May 2025 11:29:46 +0200 Subject: [PATCH] darkfi-mmproxy: Remove obsolete code --- Makefile | 8 - bin/darkfi-mmproxy/Cargo.toml | 42 --- bin/darkfi-mmproxy/Makefile | 41 --- bin/darkfi-mmproxy/contrib/.gitignore | 1 - bin/darkfi-mmproxy/contrib/build-monerod.sh | 11 - bin/darkfi-mmproxy/contrib/generate-blocks.sh | 25 -- bin/darkfi-mmproxy/contrib/start-monerod.sh | 18 -- bin/darkfi-mmproxy/darkfi_mmproxy.toml | 21 -- bin/darkfi-mmproxy/src/main.rs | 242 ------------------ bin/darkfi-mmproxy/src/monerod.rs | 210 --------------- 10 files changed, 619 deletions(-) delete mode 100644 bin/darkfi-mmproxy/Cargo.toml delete mode 100644 bin/darkfi-mmproxy/Makefile delete mode 100644 bin/darkfi-mmproxy/contrib/.gitignore delete mode 100755 bin/darkfi-mmproxy/contrib/build-monerod.sh delete mode 100755 bin/darkfi-mmproxy/contrib/generate-blocks.sh delete mode 100755 bin/darkfi-mmproxy/contrib/start-monerod.sh delete mode 100644 bin/darkfi-mmproxy/darkfi_mmproxy.toml delete mode 100644 bin/darkfi-mmproxy/src/main.rs delete mode 100644 bin/darkfi-mmproxy/src/monerod.rs diff --git a/Makefile b/Makefile index ab80f9350..5855aa597 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,6 @@ PROOFS_BIN = $(PROOFS_SRC:=.bin) BINS = \ zkas \ darkfid \ - darkfi-mmproxy \ minerd \ drk \ darkirc \ @@ -66,13 +65,6 @@ minerd: contracts RUST_TARGET="$(RUST_TARGET)" \ RUSTFLAGS="$(RUSTFLAGS)" -darkfi-mmproxy: - $(MAKE) -C bin/$@ \ - PREFIX="$(PREFIX)" \ - CARGO="$(CARGO)" \ - RUST_TARGET="$(RUST_TARGET)" \ - RUSTFLAGS="$(RUSTFLAGS)" - drk: contracts $(MAKE) -C bin/$@ \ PREFIX="$(PREFIX)" \ diff --git a/bin/darkfi-mmproxy/Cargo.toml b/bin/darkfi-mmproxy/Cargo.toml deleted file mode 100644 index 156d78a10..000000000 --- a/bin/darkfi-mmproxy/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "darkfi-mmproxy" -version = "0.4.1" -homepage = "https://dark.fi" -description = "Proxy server for DarkFi/Monero merge mining" -authors = ["Dyne.org foundation "] -repository = "https://codeberg.org/darkrenaissance/darkfi" -license = "AGPL-3.0-only" -edition = "2021" - -[dependencies] -darkfi = {path = "../../", features = ["async-daemonize", "async-serial", "system", "util", "rpc"]} -darkfi-serial = {version = "0.4.2", features = ["async"]} - -# Misc -log = "0.4.27" - -# Monero -monero = {version = "0.21.0", features = ["full"]} - -# HTTP RPC -surf = "2.3.2" -tide = "0.17.0-beta.1" - -# Encoding -hex = "0.4.3" -url = "2.5.4" - -# Daemon -easy-parallel = "3.3.1" -signal-hook-async-std = "0.3.0" -signal-hook = "0.3.17" -simplelog = "0.12.2" -smol = "2.0.2" - -# Argument parsing -serde = {version = "1.0.219", features = ["derive"]} -structopt = "0.3.26" -structopt-toml = "0.5.1" - -[lints] -workspace = true diff --git a/bin/darkfi-mmproxy/Makefile b/bin/darkfi-mmproxy/Makefile deleted file mode 100644 index 8264a8f6c..000000000 --- a/bin/darkfi-mmproxy/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -.POSIX: - -# Install prefix -PREFIX = $(HOME)/.cargo - -# Cargo binary -CARGO = cargo - -# Compile target -RUST_TARGET = $(shell rustc -Vv | grep '^host: ' | cut -d' ' -f2) -# Uncomment when doing musl static builds -#RUSTFLAGS = -C target-feature=+crt-static -C link-self-contained=yes - -SRC = \ - Cargo.toml \ - ../../Cargo.toml \ - $(shell find src -type f -name '*.rs') \ - $(shell find ../../src -type f -name '*.rs') \ - -BIN = $(shell grep '^name = ' Cargo.toml | cut -d' ' -f3 | tr -d '"') - -all: $(BIN) - -$(BIN): $(SRC) - RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build --target=$(RUST_TARGET) --release --package $@ - cp -f ../../target/$(RUST_TARGET)/release/$@ $@ - cp -f ../../target/$(RUST_TARGET)/release/$@ ../../$@ - -clean: - RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) clean --target=$(RUST_TARGET) --release --package $(BIN) - rm -f $(BIN) ../../$(BIN) - -install: all - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/$(BIN) - -uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) - -.PHONY: all clean install uninstall diff --git a/bin/darkfi-mmproxy/contrib/.gitignore b/bin/darkfi-mmproxy/contrib/.gitignore deleted file mode 100644 index 772084db0..000000000 --- a/bin/darkfi-mmproxy/contrib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -monero \ No newline at end of file diff --git a/bin/darkfi-mmproxy/contrib/build-monerod.sh b/bin/darkfi-mmproxy/contrib/build-monerod.sh deleted file mode 100755 index b19edc93d..000000000 --- a/bin/darkfi-mmproxy/contrib/build-monerod.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -set -e - -MONERO_VERSION="0.18" - -if ! [ -d "monero" ]; then - git clone "https://github.com/monero-project/monero" \ - -b "release-v${MONERO_VERSION}" monero --recursive -fi - -make -C monero release diff --git a/bin/darkfi-mmproxy/contrib/generate-blocks.sh b/bin/darkfi-mmproxy/contrib/generate-blocks.sh deleted file mode 100755 index 55b642cff..000000000 --- a/bin/darkfi-mmproxy/contrib/generate-blocks.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -set -e - -DATA=' - { - "jsonrpc": "2.0", - "id": 0, - "method": "generateblocks", - "params": { - "amount_of_blocks": 2000000, - "wallet_address": "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A", - "starting_nonce": 0 - } - } -' - -curl "http://127.0.0.1:18081/json_rpc" -d "$DATA" \ - -H 'Content-Type: application/json' & - -cat <. - */ - -use std::{collections::HashMap, sync::Arc}; - -use darkfi::{ - async_daemonize, cli_desc, - rpc::{ - jsonrpc::{JsonRequest, JsonResponse}, - util::JsonValue, - }, - Error, Result, -}; -use log::{debug, error, info}; -use serde::Deserialize; -use smol::{stream::StreamExt, Executor}; -use structopt::StructOpt; -use structopt_toml::StructOptToml; -use surf::StatusCode; -use url::Url; - -const CONFIG_FILE: &str = "darkfi_mmproxy.toml"; -const CONFIG_FILE_CONTENTS: &str = include_str!("../darkfi_mmproxy.toml"); - -/// Monero RPC functions -mod monerod; -use monerod::MonerodRequest; - -#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)] -#[serde(default)] -#[structopt(name = "darkfi-mmproxy", about = cli_desc!())] -struct Args { - #[structopt(short, parse(from_occurrences))] - /// Increase verbosity (-vvv supported) - verbose: u8, - - #[structopt(short, long)] - /// Configuration file to use - config: Option, - - #[structopt(long)] - /// Set log file output - log: Option, - - #[structopt(flatten)] - mmproxy: MmproxyArgs, - - #[structopt(flatten)] - monerod: MonerodArgs, -} - -#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)] -#[structopt()] -struct MmproxyArgs { - #[structopt(long, default_value = "http://127.0.0.1:3333")] - /// darkfi-mmproxy JSON-RPC server listen URL - mmproxy_rpc: Url, -} - -#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)] -#[structopt()] -struct MonerodArgs { - #[structopt(long, default_value = "mainnet")] - /// Monero network type (mainnet/testnet) - monero_network: String, - - #[structopt(long, default_value = "http://127.0.0.1:18081")] - /// monerod JSON-RPC server listen URL - monero_rpc: Url, -} - -/// Mining proxy state -struct MiningProxy { - /// Monero network type - monero_network: monero::Network, - /// Monero RPC address - monero_rpc: Url, -} - -impl MiningProxy { - /// Instantiate `MiningProxy` state - async fn new(monerod: MonerodArgs) -> Result { - let monero_network = match monerod.monero_network.to_lowercase().as_str() { - "mainnet" => monero::Network::Mainnet, - "testnet" => monero::Network::Testnet, - _ => { - error!("Invalid Monero network \"{}\"", monerod.monero_network); - return Err(Error::Custom(format!( - "Invalid Monero network \"{}\"", - monerod.monero_network - ))) - } - }; - - // Test that monerod RPC is reachable and is configured - // with the matching network - let self_ = Self { monero_network, monero_rpc: monerod.monero_rpc }; - - let req = JsonRequest::new("getinfo", vec![].into()); - let rep: JsonResponse = match self_.monero_request(MonerodRequest::Post(req)).await { - Ok(v) => JsonResponse::try_from(&v)?, - Err(e) => { - error!("Failed connecting to monerod RPC: {}", e); - return Err(e) - } - }; - - let Some(result) = rep.result.get::>() else { - error!("Invalid response from monerod RPC"); - return Err(Error::Custom("Invalid response from monerod RPC".to_string())) - }; - - let nettype = result.get("nettype").unwrap().get::().unwrap(); - - let mut xmr_is_mainnet = false; - let mut xmr_is_testnet = false; - - match nettype.as_str() { - // Here we allow fakechain, which we get with monerod --regtest - "mainnet" | "fakechain" => xmr_is_mainnet = true, - "testnet" => xmr_is_testnet = true, - _ => unimplemented!("Missing handler for network {}", nettype), - } - - if xmr_is_mainnet && monero_network != monero::Network::Mainnet { - error!("mmproxy requested testnet, but monerod is mainnet"); - return Err(Error::Custom("Monero network mismatch".to_string())) - } - - if xmr_is_testnet && monero_network != monero::Network::Testnet { - error!("mmproxy requested mainnet, but monerod is testnet"); - return Err(Error::Custom("Monero network mismatch".to_string())) - } - - Ok(self_) - } -} - -async_daemonize!(realmain); -async fn realmain(args: Args, ex: Arc>) -> Result<()> { - info!("Starting DarkFi x Monero merge mining proxy"); - - let mmproxy = Arc::new(MiningProxy::new(args.monerod).await?); - let mut app = tide::with_state(mmproxy); - - // monerod `/getheight` endpoint proxy [HTTP GET] - app.at("/getheight").get(|req: tide::Request>| async move { - debug!(target: "monerod::getheight", "--> /getheight"); - let mmproxy = req.state(); - let return_data = mmproxy.monerod_get_height().await?; - let return_data = return_data.stringify()?; - debug!(target: "monerod::getheight", "<-- {}", return_data); - Ok(return_data) - }); - - // monerod `/getinfo` endpoint proxy [HTTP GET] - app.at("/getinfo").get(|req: tide::Request>| async move { - debug!(target: "monerod::getinfo", "--> /getinfo"); - let mmproxy = req.state(); - let return_data = mmproxy.monerod_get_info().await?; - let return_data = return_data.stringify()?; - debug!(target: "monerod::getinfo", "<-- {}", return_data); - Ok(return_data) - }); - - // monerod `/json_rpc` endpoint proxy [HTTP POST] - app.at("/json_rpc").post(|mut req: tide::Request>| async move { - let body_string = match req.body_string().await { - Ok(v) => v, - Err(e) => { - error!(target: "monerod::json_rpc", "Failed reading request body: {}", e); - return Err(surf::Error::new(StatusCode::BadRequest, Error::Custom(e.to_string()))) - } - }; - debug!(target: "monerod::json_rpc", "--> {}", body_string); - - let json_str: JsonValue = match body_string.parse() { - Ok(v) => v, - Err(e) => { - error!(target: "monerod::json_rpc", "Failed parsing JSON body: {}", e); - return Err(surf::Error::new(StatusCode::BadRequest, Error::Custom(e.to_string()))) - } - }; - - let JsonValue::Object(ref request) = json_str else { - return Err(surf::Error::new( - StatusCode::BadRequest, - Error::Custom("Invalid JSONRPC request".to_string()), - )) - }; - - if !request.contains_key("method") || !request["method"].is_string() { - return Err(surf::Error::new( - StatusCode::BadRequest, - Error::Custom("Invalid JSONRPC request".to_string()), - )) - } - - let mmproxy = req.state(); - - // For XMRig we only have to handle 2 methods: - let return_data: JsonValue = match request["method"].get::().unwrap().as_str() { - "getblocktemplate" => mmproxy.monerod_getblocktemplate(&json_str).await?, - "submitblock" => mmproxy.monerod_submit_block(&json_str).await?, - _ => { - return Err(surf::Error::new( - StatusCode::BadRequest, - Error::Custom("Invalid JSONRPC request".to_string()), - )) - } - }; - - let return_data = return_data.stringify()?; - debug!(target: "monerod::json_rpc", "<-- {}", return_data); - Ok(return_data) - }); - - 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. - let (signals_handler, signals_task) = SignalHandler::new(ex)?; - signals_handler.wait_termination(signals_task).await?; - info!("Caught termination signal, cleaning up and exiting"); - - Ok(()) -} diff --git a/bin/darkfi-mmproxy/src/monerod.rs b/bin/darkfi-mmproxy/src/monerod.rs deleted file mode 100644 index 65b7b75db..000000000 --- a/bin/darkfi-mmproxy/src/monerod.rs +++ /dev/null @@ -1,210 +0,0 @@ -/* This file is part of DarkFi (https://dark.fi) - * - * Copyright (C) 2020-2025 Dyne.org foundation - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -use std::{collections::HashMap, str::FromStr}; - -use darkfi::{ - rpc::{ - jsonrpc::{JsonRequest, JsonResponse}, - util::JsonValue, - }, - Error, Result, -}; -use log::{debug, error, info}; -use monero::blockdata::transaction::{ExtraField, RawExtraField, SubField::MergeMining}; - -use super::MiningProxy; - -/// Types of requests that can be sent to monerod -pub(crate) enum MonerodRequest { - Get(String), - Post(JsonRequest), -} - -impl MiningProxy { - /// Perform a JSON-RPC request to monerod's endpoint with the given method - pub(crate) async fn monero_request(&self, req: MonerodRequest) -> Result { - let mut rep = match req { - MonerodRequest::Get(method) => { - let endpoint = format!("{}{}", self.monero_rpc, method); - - match surf::get(&endpoint).await { - Ok(v) => v, - Err(e) => { - let e = format!("Failed sending monerod GET request: {}", e); - error!(target: "monerod::monero_request", "{}", e); - return Err(Error::Custom(e)) - } - } - } - MonerodRequest::Post(data) => { - let endpoint = format!("{}json_rpc", self.monero_rpc); - let client = surf::Client::new(); - - match client - .get(endpoint) - .header("Content-Type", "application/json") - .body(data.stringify().unwrap()) - .send() - .await - { - Ok(v) => v, - Err(e) => { - let e = format!("Failed sending monerod POST request: {}", e); - error!(target: "monerod::monero_request", "{}", e); - return Err(Error::Custom(e)) - } - } - } - }; - - let json_rep: JsonValue = match rep.body_string().await { - Ok(v) => match v.parse() { - Ok(v) => v, - Err(e) => { - let e = format!("Failed parsing JSON string from monerod response: {}", e); - error!(target: "monerod::monero_request", "{}", e); - return Err(Error::Custom(e)) - } - }, - Err(e) => { - let e = format!("Failed parsing body string from monerod response: {}", e); - error!(target: "monerod::monero_request", "{}", e); - return Err(Error::Custom(e)) - } - }; - - Ok(json_rep) - } - - /// Proxy the `/getheight` RPC request - pub async fn monerod_get_height(&self) -> Result { - info!(target: "monerod::getheight", "Proxying /getheight request"); - let rep = self.monero_request(MonerodRequest::Get("getheight".to_string())).await?; - Ok(rep) - } - - /// Proxy the `/getinfo` RPC request - pub async fn monerod_get_info(&self) -> Result { - info!(target: "monerod::getinfo", "Proxying /getinfo request"); - let rep = self.monero_request(MonerodRequest::Get("getinfo".to_string())).await?; - Ok(rep) - } - - /// Proxy the `submitblock` RPC request - pub async fn monerod_submit_block(&self, req: &JsonValue) -> Result { - info!(target: "monerod::submitblock", "Proxying submitblock request"); - let request = JsonRequest::try_from(req)?; - - if !request.params.is_array() { - return Err(Error::Custom("Invalid request".to_string())) - } - - for block in request.params.get::>().unwrap() { - let Some(block) = block.get::() else { - return Err(Error::Custom("Invalid request".to_string())) - }; - - debug!( - target: "monerod::submitblock", "{:#?}", - monero::consensus::deserialize::(&hex::decode(block).unwrap()).unwrap(), - ); - } - - let response = self.monero_request(MonerodRequest::Post(request)).await?; - Ok(response) - } - - /// Perform the `getblocktemplate` request and modify it with the necessary - /// merge mining data. - pub async fn monerod_getblocktemplate(&self, req: &JsonValue) -> Result { - info!(target: "monerod::getblocktemplate", "Proxying getblocktemplate request"); - let mut request = JsonRequest::try_from(req)?; - - if !request.params.is_object() { - return Err(Error::Custom("Invalid request".to_string())) - } - - let params: &mut HashMap = request.params.get_mut().unwrap(); - if !params.contains_key("wallet_address") { - return Err(Error::Custom("Invalid request".to_string())) - } - - let Some(wallet_address) = params["wallet_address"].get::() else { - return Err(Error::Custom("Invalid request".to_string())) - }; - - let Ok(wallet_address) = monero::Address::from_str(wallet_address) else { - return Err(Error::Custom("Invalid request".to_string())) - }; - - if wallet_address.network != self.monero_network { - return Err(Error::Custom("Monero network address mismatch".to_string())) - } - - if wallet_address.addr_type != monero::AddressType::Standard { - return Err(Error::Custom("Non-standard Monero address".to_string())) - } - - // Create the Merge Mining data - // TODO: This is where we're gonna include the necessary DarkFi data - // that has to end up in Monero blocks. - let mm_tag = MergeMining(monero::VarInt(32), monero::Hash([0_u8; 32])); - - // Construct `tx_extra` from all the extra fields we have to add to - // the coinbase transaction in the block we're mining. - let tx_extra: RawExtraField = ExtraField(vec![mm_tag]).into(); - - // Modify the params `reserve_size` to fit our Merge Mining data - 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_request(MonerodRequest::Post(request)).await?; - debug!(target: "monerod::getblocktemplate", "Got {}", gbt_response.stringify()?); - let mut gbt_response = JsonResponse::try_from(&gbt_response)?; - let gbt_result: &mut HashMap = gbt_response.result.get_mut().unwrap(); - - // Now we have to modify the block template: - let mut block_template = monero::consensus::deserialize::( - &hex::decode(gbt_result["blocktemplate_blob"].get::().unwrap()).unwrap(), - ) - .unwrap(); - - // Update coinbase tx with our extra field - block_template.miner_tx.prefix.extra = tx_extra; - - // Update `blocktemplate_blob` with the modified block: - gbt_result.insert( - "blocktemplate_blob".to_string(), - hex::encode(monero::consensus::serialize(&block_template)).into(), - ); - - // Update `blockhashing_blob` in order to perform correct PoW: - gbt_result.insert( - "blockhashing_blob".to_string(), - hex::encode(block_template.serialize_hashable()).into(), - ); - - // Return the modified JSON response - Ok((&gbt_response).into()) - } -}