浏览代码

vanityaddr: Replace clap with arg and add standalone Makefile.

parazyd 2 年之前
父节点
当前提交
39e9d77e67
共有 4 个文件被更改,包括 131 次插入90 次删除
  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"
 name = "vanityaddr"
 version = "0.4.1"
 version = "0.4.1"
 homepage = "https://dark.fi"
 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>"]
 authors = ["Dyne.org foundation <foundation@dyne.org>"]
 repository = "https://github.com/darkrenaissance/darkfi"
 repository = "https://github.com/darkrenaissance/darkfi"
 license = "AGPL-3.0-only"
 license = "AGPL-3.0-only"
 edition = "2021"
 edition = "2021"
 
 
 [dependencies]
 [dependencies]
+arg = {git = "https://github.com/parazyd/arg"}
 bs58 = "0.5.0"
 bs58 = "0.5.0"
-clap = {version = "4.3.24", features = ["derive"]}
 ctrlc = "3.4.0"
 ctrlc = "3.4.0"
 darkfi = {path = "../../", features = ["util"]}
 darkfi = {path = "../../", features = ["util"]}
-darkfi-sdk = {path = "../../src/sdk", features = ["async"]}
+darkfi-sdk = {path = "../../src/sdk"}
 rand = "0.8.5"
 rand = "0.8.5"
 rayon = "1.7.0"
 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::{
 use std::{
-    process::exit,
+    process::{exit, ExitCode},
     sync::{mpsc::channel, Arc},
     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 darkfi_sdk::crypto::{ContractId, PublicKey, SecretKey, TokenId};
 use rand::rngs::OsRng;
 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 {
 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() {
         match bs58::decode(prefix).into_vec() {
             Ok(_) => {}
             Ok(_) => {}
             Err(e) => {
             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
     // Handle SIGINT
     let (tx, rx) = channel();
     let (tx, rx) = channel();
     ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel"))
     ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel"))
@@ -180,47 +182,50 @@ fn main() {
     // Something fancy
     // Something fancy
     let progress = Arc::new(ProgressInc::new());
     let progress = Arc::new(ProgressInc::new());
 
 
-    // Fire off the threadpool
+    // Threadpool
     let progress_ = progress.clone();
     let progress_ = progress.clone();
+    let rayon_pool = rayon::ThreadPoolBuilder::new().num_threads(n_threads).build().unwrap();
     rayon_pool.spawn(move || {
     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))
                 .inspect(|_| progress_.inc(1))
                 .map(|create| create())
                 .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();
             let attempts = progress_.position();
             progress_.finish_and_clear();
             progress_.finish_and_clear();
 
 
             println!(
             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))
                 .inspect(|_| progress_.inc(1))
                 .map(|create| create())
                 .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();
             let attempts = progress_.position();
             progress_.finish_and_clear();
             progress_.finish_and_clear();
 
 
             println!(
             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)
             let cid = rayon::iter::repeat(DrkContract::new)
                 .inspect(|_| progress_.inc(1))
                 .inspect(|_| progress_.inc(1))
                 .map(|create| create())
                 .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");
                 .expect("Failed to find a contract ID match");
 
 
             let attempts = progress_.position();
             let attempts = progress_.position();
@@ -239,5 +244,5 @@ fn main() {
     rx.recv().expect("Could not receive from channel");
     rx.recv().expect("Could not receive from channel");
     progress.finish_and_clear();
     progress.finish_and_clear();
     eprintln!("\r\x1b[2KCaught SIGINT, exiting...");
     eprintln!("\r\x1b[2KCaught SIGINT, exiting...");
-    exit(127);
+    ExitCode::FAILURE
 }
 }

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

@@ -1,36 +1,34 @@
 vanityaddr
 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
 ## Usage
 
 
 ```
 ```
 vanityaddr 0.4.1
 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:
 Arguments:
-  [PREFIX]...  Prefixes to search
+  <PREFIX>    Prefixes to search
 
 
 Options:
 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:
 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,
 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.
 number of attempts it took to find the secret key.
 
 
 ```
 ```
-{"address":"DrkZcAiZPQoQUrdii9CUCQC2SNcUrSYEYW4wTj6Nhtp1","attempts":78418,"secret":"BL9zmxqFhCHHU42CPY1G4hj1ahUYh61F54rPBBwLVLVv"}
+{
+  "address": "DRKN9N83iNs34YHu1RuW5nELvBSrV34JSztE64FR8DpX",
+  "attempts": 30999,
+  "secret": "9477oqchtHFMbCswnWqXptXGw9Ax1ynJN7SSLf346w6d"
+}
 ```
 ```