Procházet zdrojové kódy

drk: aux subcommand to display a base64 encoded mining configuration added

skoupidi před 7 měsíci
rodič
revize
c82f8666ed
3 změnil soubory, kde provedl 141 přidání a 11 odebrání
  1. 96 3
      bin/drk/src/cli_util.rs
  2. 30 6
      bin/drk/src/interactive.rs
  3. 15 2
      bin/drk/src/main.rs

+ 96 - 3
bin/drk/src/cli_util.rs

@@ -33,6 +33,10 @@ use darkfi::{
     Error, Result,
 };
 use darkfi_money_contract::model::TokenId;
+use darkfi_sdk::{
+    crypto::{keypair::Address, pasta_prelude::PrimeField, FuncId},
+    pasta::pallas,
+};
 use darkfi_serial::deserialize_async;
 
 use crate::{money::BALANCE_BASE10_DECIMALS, Drk};
@@ -414,9 +418,18 @@ pub fn generate_completions(shell: &str) -> Result<String> {
         .about("Fetch scanned blocks records")
         .args(&[height]);
 
-    let explorer = SubCommand::with_name("explorer")
-        .about("Explorer related subcommands")
-        .subcommands(vec![fetch_tx, simulate_tx, txs_history, clear_reverted, scanned_blocks]);
+    let mining_config = SubCommand::with_name("mining-config")
+        .about("Read a mining configuration from stdin and display its parts");
+
+    let explorer =
+        SubCommand::with_name("explorer").about("Explorer related subcommands").subcommands(vec![
+            fetch_tx,
+            simulate_tx,
+            txs_history,
+            clear_reverted,
+            scanned_blocks,
+            mining_config,
+        ]);
 
     // Alias
     let alias = Arg::with_name("alias").help("Token alias");
@@ -631,3 +644,83 @@ pub async fn append_or_print(
         buf.push(msg);
     }
 }
+
+/// Auxiliary function to parse a base64 encoded mining configuration
+/// from stdin.
+pub async fn parse_mining_config_from_stdin(
+) -> Result<(String, String, Option<String>, Option<String>)> {
+    let mut buf = String::new();
+    stdin().read_to_string(&mut buf)?;
+    let config = buf.trim();
+    let (recipient, spend_hook, user_data) = match base64::decode(config) {
+        Some(bytes) => deserialize_async(&bytes).await?,
+        None => return Err(Error::ParseFailed("Failed to decode mining configuration")),
+    };
+    Ok((config.to_string(), recipient, spend_hook, user_data))
+}
+
+/// Auxiliary function to parse a base64 encoded mining configuration
+/// from provided input or fallback to stdin if its empty.
+pub async fn parse_mining_config_from_input(
+    input: &[String],
+) -> Result<(String, String, Option<String>, Option<String>)> {
+    match input.len() {
+        0 => parse_mining_config_from_stdin().await,
+        1 => {
+            let config = input[0].trim();
+            let (recipient, spend_hook, user_data) = match base64::decode(config) {
+                Some(bytes) => deserialize_async(&bytes).await?,
+                None => return Err(Error::ParseFailed("Failed to decode mining configuration")),
+            };
+            Ok((config.to_string(), recipient, spend_hook, user_data))
+        }
+        _ => Err(Error::ParseFailed("Multiline input provided")),
+    }
+}
+
+/// Auxiliary function to display the parts of a mining configuration.
+pub fn display_mining_config(
+    config: &str,
+    recipient_str: &str,
+    spend_hook: &Option<String>,
+    user_data: &Option<String>,
+    output: &mut Vec<String>,
+) {
+    output.push(format!("Mining configuration: {config}"));
+
+    match Address::from_str(recipient_str) {
+        Ok(recipient) => {
+            output.push(format!("Recipient: {recipient_str}"));
+            output.push(format!("Public key: {}", recipient.public_key()));
+            output.push(format!("Network: {:?}", recipient.network()));
+        }
+        Err(e) => output.push(format!("Recipient: Invalid ({e})")),
+    }
+
+    let spend_hook = match spend_hook {
+        Some(spend_hook_str) => match FuncId::from_str(spend_hook_str) {
+            Ok(_) => String::from(spend_hook_str),
+            Err(e) => format!("Invalid ({e})"),
+        },
+        None => String::from("-"),
+    };
+    output.push(format!("Spend hook: {spend_hook}"));
+
+    let user_data = match user_data {
+        Some(user_data_str) => match bs58::decode(&user_data_str).into_vec() {
+            Ok(bytes) => match bytes.try_into() {
+                Ok(bytes) => {
+                    if pallas::Base::from_repr(bytes).is_some().into() {
+                        String::from(user_data_str)
+                    } else {
+                        String::from("Invalid")
+                    }
+                }
+                Err(e) => format!("Invalid ({e:?})"),
+            },
+            Err(e) => format!("Invalid ({e})"),
+        },
+        None => String::from("-"),
+    };
+    output.push(format!("User data: {user_data}"));
+}

+ 30 - 6
bin/drk/src/interactive.rs

@@ -59,8 +59,9 @@ use darkfi_serial::{deserialize_async, serialize_async};
 
 use crate::{
     cli_util::{
-        append_or_print, generate_completions, kaching, parse_token_pair, parse_tx_from_input,
-        parse_value_pair, print_output,
+        append_or_print, display_mining_config, generate_completions, kaching,
+        parse_mining_config_from_input, parse_token_pair, parse_tx_from_input, parse_value_pair,
+        print_output,
     },
     common::*,
     dao::{DaoParams, ProposalRecord},
@@ -248,7 +249,8 @@ fn completion(buffer: &str, lc: &mut Vec<String>) {
         lc.push(prefix.clone() + "explorer simulate-tx");
         lc.push(prefix.clone() + "explorer txs-history");
         lc.push(prefix.clone() + "explorer clear-reverted");
-        lc.push(prefix + "explorer scanned-blocks");
+        lc.push(prefix.clone() + "explorer scanned-blocks");
+        lc.push(prefix + "explorer mining-config");
         return
     }
 
@@ -359,7 +361,7 @@ fn hints(buffer: &str) -> Option<(String, i32, bool)> {
         "dao mining-config " => Some(("<name>".to_string(), color, bold)),
         "scan " => Some(("[--reset]".to_string(), color, bold)),
         "scan --reset " => Some(("<height>".to_string(), color, bold)),
-        "explorer " => Some(("(fetch-tx|simulate-tx|txs-history|clear-reverted|scanned-blocks)".to_string(), color, bold)),
+        "explorer " => Some(("(fetch-tx|simulate-tx|txs-history|clear-reverted|scanned-blocks|mining-config)".to_string(), color, bold)),
         "explorer fetch-tx " => Some(("[--encode] <tx-hash>".to_string(), color, bold)),
         "explorer txs-history " => Some(("[--encode] [tx-hash]".to_string(), color, bold)),
         "explorer scanned-blocks " => Some(("[height]".to_string(), color, bold)),
@@ -2480,7 +2482,7 @@ async fn handle_explorer(drk: &DrkPtr, parts: &[&str], input: &[String], output:
     if parts.len() < 2 {
         output.push(String::from("Malformed `explorer` command"));
         output.push(String::from(
-            "Usage: explorer (fetch-tx|simulate-tx|txs-history|clear-reverted|scanned-blocks)",
+            "Usage: explorer (fetch-tx|simulate-tx|txs-history|clear-reverted|scanned-blocks|mining-config)",
         ));
         return
     }
@@ -2492,10 +2494,11 @@ async fn handle_explorer(drk: &DrkPtr, parts: &[&str], input: &[String], output:
         "txs-history" => handle_explorer_txs_history(drk, parts, output).await,
         "clear-reverted" => handle_explorer_clear_reverted(drk, parts, output).await,
         "scanned-blocks" => handle_explorer_scanned_blocks(drk, parts, output).await,
+        "mining-config" => handle_explorer_mining_config(parts, input, output).await,
         _ => {
             output.push(format!("Unrecognized explorer subcommand: {}", parts[1]));
             output.push(String::from(
-                "Usage: explorer (fetch-tx|simulate-tx|txs-history|clear-reverted|scanned-blocks)",
+                "Usage: explorer (fetch-tx|simulate-tx|txs-history|clear-reverted|scanned-blocks|mining-config)",
             ));
         }
     }
@@ -2715,6 +2718,27 @@ async fn handle_explorer_scanned_blocks(drk: &DrkPtr, parts: &[&str], output: &m
     }
 }
 
+/// Auxiliary function to define the explorer mining config subcommand handling.
+async fn handle_explorer_mining_config(parts: &[&str], input: &[String], output: &mut Vec<String>) {
+    // Check correct subcommand structure
+    if parts.len() != 2 {
+        output.push(String::from("Malformed `explorer mining-config` subcommand"));
+        output.push(String::from("Usage: explorer mining-config"));
+        return
+    }
+
+    let (config, recipient, spend_hook, user_data) =
+        match parse_mining_config_from_input(input).await {
+            Ok(c) => c,
+            Err(e) => {
+                output.push(format!("Error while parsing mining config: {e}"));
+                return
+            }
+        };
+
+    display_mining_config(&config, &recipient, &spend_hook, &user_data, output)
+}
+
 /// Auxiliary function to define the alias command handling.
 async fn handle_alias(drk: &DrkPtr, parts: &[&str], output: &mut Vec<String>) {
     // Check correct command structure

+ 15 - 2
bin/drk/src/main.rs

@@ -57,8 +57,8 @@ use darkfi_serial::{deserialize_async, serialize_async};
 
 use drk::{
     cli_util::{
-        generate_completions, kaching, parse_token_pair, parse_tx_from_stdin, parse_value_pair,
-        print_output,
+        display_mining_config, generate_completions, kaching, parse_mining_config_from_stdin,
+        parse_token_pair, parse_tx_from_stdin, parse_value_pair, print_output,
     },
     common::*,
     dao::{DaoParams, ProposalRecord},
@@ -459,6 +459,9 @@ enum ExplorerSubcmd {
         /// Fetch specific height record (optional)
         height: Option<u32>,
     },
+
+    /// Read a mining configuration from stdin and display its parts
+    MiningConfig,
 }
 
 #[derive(Clone, Debug, Deserialize, StructOpt)]
@@ -2291,6 +2294,16 @@ async fn realmain(args: Args, ex: ExecutorPtr) -> Result<()> {
 
                 Ok(())
             }
+
+            ExplorerSubcmd::MiningConfig => {
+                let (config, recipient, spend_hook, user_data) =
+                    parse_mining_config_from_stdin().await?;
+                let mut output = vec![];
+                display_mining_config(&config, &recipient, &spend_hook, &user_data, &mut output);
+                print_output(&output);
+
+                Ok(())
+            }
         },
 
         Subcmd::Alias { command } => match command {