Parcourir la source

vanityaddr: Replace clap with arg and add standalone Makefile.

parazyd il y a 2 ans
Parent
commit
39e9d77e67
4 fichiers modifiés avec 131 ajouts et 90 suppressions
  1. 3 3
      bin/vanityaddr/Cargo.toml
  2. 34 0
      bin/vanityaddr/Makefile
  3. 76 71
      bin/vanityaddr/src/main.rs
  4. 18 16
      doc/src/misc/vanityaddr.md

+ 3 - 3
bin/vanityaddr/Cargo.toml

@@ -2,17 +2,17 @@
 name = "vanityaddr"
 version = "0.4.1"
 homepage = "https://dark.fi"
-description = "Vanity address generation tool for DarkFi keypairs and token IDs"
+description = "Vanity address generation tool for DarkFi keypairs, contract IDs, and token IDs"
 authors = ["Dyne.org foundation <foundation@dyne.org>"]
 repository = "https://github.com/darkrenaissance/darkfi"
 license = "AGPL-3.0-only"
 edition = "2021"
 
 [dependencies]
+arg = {git = "https://github.com/parazyd/arg"}
 bs58 = "0.5.0"
-clap = {version = "4.3.24", features = ["derive"]}
 ctrlc = "3.4.0"
 darkfi = {path = "../../", features = ["util"]}
-darkfi-sdk = {path = "../../src/sdk", features = ["async"]}
+darkfi-sdk = {path = "../../src/sdk"}
 rand = "0.8.5"
 rayon = "1.7.0"

+ 34 - 0
bin/vanityaddr/Makefile

@@ -0,0 +1,34 @@
+.POSIX:
+
+# Install prefix
+PREFIX = $(HOME)/.cargo
+
+# Cargo binary
+CARGO = cargo +nightly
+
+SRC = \
+	Cargo.toml \
+	../../Cargo.toml \
+	$(shell find src -type f) \
+	$(shell find ../../src -type f) \
+
+BIN = ../../vanityaddr
+
+all: $(BIN)
+
+$(BIN): $(SRC)
+	$(CARGO) build $(TARGET_PRFX)$(RUST_TARGET) --release --package vanityaddr
+	cp -f ../../target/$(RUST_TARGET)/release/vanityaddr $@
+
+clean:
+	rm -f $(BIN)
+
+install: all
+	mkdir -p $(DESTDIR)$(PREFIX)/bin
+	cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin
+	chmod 755 $(DESTDIR)$(PREFIX)/bin/vanityaddr
+
+uninstall:
+	rm -f $(DESTDIR)$(PREFIX)/bin/vanityaddr
+
+.PHONY: all clean install uninstall

+ 76 - 71
bin/vanityaddr/src/main.rs

@@ -17,44 +17,36 @@
  */
 
 use std::{
-    process::exit,
+    process::{exit, ExitCode},
     sync::{mpsc::channel, Arc},
+    thread::available_parallelism,
 };
 
-use clap::Parser;
-use darkfi::util::cli::ProgressInc;
+use arg::Args;
+use darkfi::{util::cli::ProgressInc, ANSI_LOGO};
 use darkfi_sdk::crypto::{ContractId, PublicKey, SecretKey, TokenId};
 use rand::rngs::OsRng;
-use rayon::prelude::*;
+use rayon::iter::ParallelIterator;
 
-use darkfi::cli_desc;
+const ABOUT: &str =
+    concat!("vanityaddr ", env!("CARGO_PKG_VERSION"), '\n', env!("CARGO_PKG_DESCRIPTION"));
 
-#[derive(Parser)]
-#[clap(name = "vanityaddr", about = cli_desc!(), version)]
-#[clap(arg_required_else_help(true))]
-struct Args {
-    /// Prefixes to search
-    prefix: Vec<String>,
+const USAGE: &str = r#"
+Usage: vanityaddr [OPTIONS] <PREFIX> <PREFIX> ...
 
-    /// Should the search be case-sensitive
-    #[clap(short)]
-    case_sensitive: bool,
+Arguments:
+  <PREFIX>    Prefixes to search
 
-    /// Search for an Address
-    #[clap(long)]
-    address: bool,
+Options:
+  -c    Make the search case-sensitive
+  -t    Number of threads to use (defaults to number of available CPUs)
+  -A    Search for an address
+  -C    Search for a Contract ID
+  -T    Search for a Token ID
+"#;
 
-    /// Search for a Token ID
-    #[clap(long)]
-    token_id: bool,
-
-    /// Search for a Contract ID
-    #[clap(long)]
-    contract_id: bool,
-
-    /// Number of threads to use (defaults to number of available CPUs)
-    #[clap(short)]
-    threads: Option<usize>,
+fn usage() {
+    print!("{}{}\n{}", ANSI_LOGO, ABOUT, USAGE);
 }
 
 struct DrkAddr {
@@ -138,40 +130,50 @@ impl Prefixable for DrkContract {
     }
 }
 
-fn main() {
-    let args = Args::parse();
+fn main() -> ExitCode {
+    let argv;
+    let mut hflag = false;
+    let mut cflag = false;
+    let mut addrflag = false;
+    let mut toknflag = false;
+    let mut ctrcflag = false;
+
+    let mut n_threads = available_parallelism().unwrap().get();
 
-    if !((args.address ^ args.contract_id ^ args.token_id) &&
-        !(args.address && args.contract_id && args.token_id))
     {
-        eprintln!("Error: Can only search for one of Address/ContractId/TokenId");
-        exit(1);
+        let mut args = Args::new().with_cb(|args, flag| match flag {
+            'c' => cflag = true,
+            'A' => addrflag = true,
+            'T' => toknflag = true,
+            'C' => ctrcflag = true,
+            't' => n_threads = args.eargf().parse::<usize>().unwrap(),
+            _ => hflag = true,
+        });
+
+        argv = args.parse();
+    }
+
+    if hflag || argv.is_empty() {
+        usage();
+        return ExitCode::FAILURE
     }
 
-    if args.prefix.is_empty() {
-        eprintln!("Error: No prefix given to search.");
-        exit(1);
+    if (addrflag as u8 + toknflag as u8 + ctrcflag as u8) != 1 {
+        eprintln!("The search flags are mutually exclusive. Use only one of -A/-C/-T.");
+        return ExitCode::FAILURE
     }
 
-    // Check if prefixes are valid base58
-    for (idx, prefix) in args.prefix.iter().enumerate() {
+    // Validate search prefixes
+    for (idx, prefix) in argv.iter().enumerate() {
         match bs58::decode(prefix).into_vec() {
             Ok(_) => {}
             Err(e) => {
-                eprintln!("Error: Invalid base58 for prefix {}: {}", idx, e);
-                exit(1);
+                eprintln!("Error: Invalid base58 for prefix #{}: {}", idx, e);
+                return ExitCode::FAILURE
             }
-        };
+        }
     }
 
-    // Threadpool
-    let num_threads = if args.threads.is_some() {
-        args.threads.unwrap()
-    } else {
-        std::thread::available_parallelism().unwrap().get()
-    };
-    let rayon_pool = rayon::ThreadPoolBuilder::new().num_threads(num_threads).build().unwrap();
-
     // Handle SIGINT
     let (tx, rx) = channel();
     ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel"))
@@ -180,47 +182,50 @@ fn main() {
     // Something fancy
     let progress = Arc::new(ProgressInc::new());
 
-    // Fire off the threadpool
+    // Threadpool
     let progress_ = progress.clone();
+    let rayon_pool = rayon::ThreadPoolBuilder::new().num_threads(n_threads).build().unwrap();
     rayon_pool.spawn(move || {
-        if args.token_id {
-            let tid = rayon::iter::repeat(DrkToken::new)
+        if addrflag {
+            let addr = rayon::iter::repeat(DrkAddr::new)
                 .inspect(|_| progress_.inc(1))
                 .map(|create| create())
-                .find_any(|token_id| token_id.starts_with_any(&args.prefix, args.case_sensitive))
-                .expect("Failed to find a token ID match");
+                .find_any(|address| address.starts_with_any(&argv, cflag))
+                .expect("Failed to find an address match");
 
-            // The above will keep running until it finds a match or until the
-            // program terminates. Only if a match is found shall the following
-            // code be executed and the program exit successfully:
+            // The above will keep running until it finds a match or until
+            // the program terminates. Only if a match is found shall the
+            // following code be executed and the program exit successfully:
             let attempts = progress_.position();
             progress_.finish_and_clear();
 
             println!(
-                "{{\"token_id\":\"{}\",\"attempts\":{},\"secret\":\"{}\"}}",
-                tid.token_id, attempts, tid.secret,
+                "{{\"address\":\"{}\",\"attempts\":{},\"secret\":\"{}\"}}",
+                addr.public, attempts, addr.secret,
             );
-        } else if args.address {
-            let addr = rayon::iter::repeat(DrkAddr::new)
+        }
+
+        if toknflag {
+            let tid = rayon::iter::repeat(DrkToken::new)
                 .inspect(|_| progress_.inc(1))
                 .map(|create| create())
-                .find_any(|address| address.starts_with_any(&args.prefix, args.case_sensitive))
-                .expect("Failed to find an address match");
+                .find_any(|token_id| token_id.starts_with_any(&argv, cflag))
+                .expect("Failed to find a token ID match");
 
             let attempts = progress_.position();
             progress_.finish_and_clear();
 
             println!(
-                "{{\"address\":\"{}\",\"attempts\":{},\"secret\":\"{}\"}}",
-                addr.public, attempts, addr.secret,
+                "{{\"token_id\":\"{}\",\"attempts\":{},\"secret\":\"{}\"}}",
+                tid.token_id, attempts, tid.secret,
             );
-        } else if args.contract_id {
+        }
+
+        if ctrcflag {
             let cid = rayon::iter::repeat(DrkContract::new)
                 .inspect(|_| progress_.inc(1))
                 .map(|create| create())
-                .find_any(|contract_id| {
-                    contract_id.starts_with_any(&args.prefix, args.case_sensitive)
-                })
+                .find_any(|contract_id| contract_id.starts_with_any(&argv, cflag))
                 .expect("Failed to find a contract ID match");
 
             let attempts = progress_.position();
@@ -239,5 +244,5 @@ fn main() {
     rx.recv().expect("Could not receive from channel");
     progress.finish_and_clear();
     eprintln!("\r\x1b[2KCaught SIGINT, exiting...");
-    exit(127);
+    ExitCode::FAILURE
 }

+ 18 - 16
doc/src/misc/vanityaddr.md

@@ -1,36 +1,34 @@
 vanityaddr
 ==========
 
-A tool for Vanity address generation for DarkFi keypairs and token IDs.
-Given some prefix, the tool will bruteforce secret keys to find one
-which, when derived, starts with a given prefix.
+A tool for Vanity address generation for DarkFi keypairs, contract IDs,
+and token IDs. Given some prefix, the tool will bruteforce secret keys
+to find one which, when derived, starts with a given prefix.
 
 ## Usage
 
 ```
 vanityaddr 0.4.1
-Vanity address generation tool for DarkFi keypairs and token IDs
+Vanity address generation tool for DarkFi keypairs, contract IDs, and token IDs
 
-Usage: vanityaddr [OPTIONS] [PREFIX]...
+Usage: vanityaddr [OPTIONS] <PREFIX> <PREFIX> ...
 
 Arguments:
-  [PREFIX]...  Prefixes to search
+  <PREFIX>    Prefixes to search
 
 Options:
-  -c                 Should the search be case-sensitive
-      --address      Search for an Address
-      --token-id     Search for a Token ID
-      --contract-id  Search for a Contract ID
-  -t <THREADS>       Number of threads to use (defaults to number of available CPUs)
-  -h, --help         Print help
-  -V, --version      Print version
+  -c    Make the search case-sensitive
+  -t    Number of threads to use (defaults to number of available CPUs)
+  -A    Search for an address
+  -C    Search for a Contract ID
+  -T    Search for a Token ID
 ```
 
 We can use the tool in our command line:
 
 ```
-% vanityaddr drk
-[00:00:05] 53370 attempts
+$ vanityaddr -A drk | jq
+[1.214124215s] 53370 attempts
 ```
 
 And the program will start crunching numbers. After a period of time,
@@ -38,5 +36,9 @@ we will get JSON output containing an address, secret key, and the
 number of attempts it took to find the secret key.
 
 ```
-{"address":"DrkZcAiZPQoQUrdii9CUCQC2SNcUrSYEYW4wTj6Nhtp1","attempts":78418,"secret":"BL9zmxqFhCHHU42CPY1G4hj1ahUYh61F54rPBBwLVLVv"}
+{
+  "address": "DRKN9N83iNs34YHu1RuW5nELvBSrV34JSztE64FR8DpX",
+  "attempts": 30999,
+  "secret": "9477oqchtHFMbCswnWqXptXGw9Ax1ynJN7SSLf346w6d"
+}
 ```