Ver código fonte

vanityaddr: Improve and add progress.

parazyd 4 anos atrás
pai
commit
b9fa52d363

+ 1 - 0
Cargo.lock

@@ -6375,6 +6375,7 @@ dependencies = [
  "bs58",
  "clap 3.1.6",
  "darkfi",
+ "indicatif",
  "num_cpus",
  "rand 0.8.5",
  "rayon",

+ 8 - 5
bin/vanityaddr/Cargo.toml

@@ -1,15 +1,18 @@
 [package]
 name = "vanityaddr"
 version = "0.3.0"
+homepage = "https://dark.fi"
+description = "Vanity address generation tool for DarkFi keypairs."
+authors = ["darkfi <dev@dark.fi>"]
+repository = "https://github.com/darkrenaissance/darkfi"
+license = "AGPL-3.0-only"
 edition = "2021"
 
-[dependencies.darkfi]
-path = "../../"
-features = ["crypto", "util"]
-
 [dependencies]
-clap = {version = "3.1.6", features = ["derive"]}
 bs58 = "0.4.0"
+clap = {version = "3.1.6", features = ["derive"]}
+darkfi = {path = "../../", features = ["crypto", "util"]}
+indicatif = "0.16.2"
 num_cpus = "1.13.1"
 rand = "0.8.5"
 rayon = "1.5.1"

+ 1 - 0
bin/vanityaddr/README.md

@@ -0,0 +1 @@
+../../doc/src/misc/vanityaddr.md

+ 75 - 33
bin/vanityaddr/src/main.rs

@@ -1,25 +1,35 @@
+use std::process::exit;
+
 use clap::Parser;
-use darkfi::{
-    crypto::{
-        address::Address,
-        keypair::{Keypair, SecretKey},
-    },
-    Error, Result,
-};
+use indicatif::{ProgressBar, ProgressStyle};
 use rand::rngs::OsRng;
 use rayon::prelude::*;
 use serde_json::json;
 
+use darkfi::crypto::{
+    address::Address,
+    keypair::{Keypair, SecretKey},
+};
+
 #[derive(Parser)]
-#[clap(version)]
+#[clap(name = "vanityaddr", about, version)]
+#[clap(arg_required_else_help(true))]
 struct Args {
-    /// Prefix to search (must start with 1)
-    prefix: String,
+    /// Prefixes to search (must start with 1)
+    prefix: Vec<String>,
+
+    /// Should the search be case-sensitive
+    #[clap(short)]
+    case_sensitive: bool,
+
+    /// Number of threads to use (defaults to number of available CPUs)
+    #[clap(short)]
+    threads: Option<String>,
 }
 
 struct DrkAddr {
-    pub secret: SecretKey,
     pub address: String,
+    pub secret: SecretKey,
 }
 
 impl DrkAddr {
@@ -30,50 +40,82 @@ impl DrkAddr {
         Self { secret: kp.secret, address: format!("{}", addr) }
     }
 
-    pub fn starts_with(&self, prefix: &str, is_case_sensitive: bool) -> bool {
-        if is_case_sensitive {
+    pub fn starts_with(&self, prefix: &str, case_sensitive: bool) -> bool {
+        if case_sensitive {
             self.address.starts_with(prefix)
         } else {
             self.address.to_lowercase().starts_with(prefix.to_lowercase().as_str())
         }
     }
+
+    pub fn starts_with_any(&self, prefixes: &[String], case_sensitive: bool) -> bool {
+        for prefix in prefixes {
+            if self.starts_with(prefix, case_sensitive) {
+                return true
+            }
+        }
+        false
+    }
 }
 
-fn main() -> Result<()> {
+fn main() {
     let args = Args::parse();
 
-    if !args.prefix.starts_with('1') {
-        return Err(Error::ParseFailed("Address prefix must start with '1'"))
+    for (idx, prefix) in args.prefix.iter().enumerate() {
+        if !prefix.starts_with('1') {
+            eprintln!("Error: Address prefix at index {} must start with \"1\".", idx);
+            exit(1);
+        }
     }
 
-    let is_case_sensitive = false;
+    // Check if prefixes are valid base58
+    for (idx, prefix) in args.prefix.iter().enumerate() {
+        match bs58::decode(prefix).into_vec() {
+            Ok(_) => {}
+            Err(e) => {
+                eprintln!("Error: Invalid base58 for prefix {}: {}", idx, e);
+                exit(1);
+            }
+        };
+    }
 
-    // Check if prefix is valid base58
-    match bs58::decode(args.prefix.clone()).into_vec() {
-        Ok(_) => {}
-        Err(_) => return Err(Error::ParseFailed("Invalid base58 for prefix")),
+    // Threadpool
+    let num_threads = if args.threads.is_some() {
+        match args.threads.unwrap().parse::<usize>() {
+            Ok(v) => v,
+            Err(e) => {
+                eprintln!("Error: Invalid thread number: {}", e);
+                exit(1);
+            }
+        }
+    } else {
+        num_cpus::get()
     };
 
-    // Threadpool
-    let num_threads = num_cpus::get();
-    let rayon_pool = rayon::ThreadPoolBuilder::new()
-        .num_threads(num_threads)
-        .build()
-        .expect("Unable to create threadpool");
+    let rayon_pool = rayon::ThreadPoolBuilder::new().num_threads(num_threads).build().unwrap();
+
+    // Something fancy
+    let progress = ProgressBar::new_spinner();
+    progress.set_style(ProgressStyle::default_bar().template("[{elapsed_precise}] {pos} attempts"));
+    progress.set_draw_rate(10);
 
-    let drkaddr: DrkAddr = rayon_pool.install(|| {
+    // Fire off the threadpool
+    let addr = rayon_pool.install(|| {
         rayon::iter::repeat(DrkAddr::new)
+            .inspect(|_| progress.inc(1))
             .map(|create| create())
-            .find_any(|address| address.starts_with(&args.prefix, is_case_sensitive))
+            .find_any(|address| address.starts_with_any(&args.prefix, args.case_sensitive))
             .expect("Failed to find an address match")
     });
 
+    let attempts = progress.position();
+    progress.finish_and_clear();
+
     let result = json!({
-        "secret_key": format!("{:?}", drkaddr.secret.0),
-        "address": drkaddr.address,
+        "address": addr.address,
+        "secret": format!("{:?}", addr.secret.0),
+        "attempts": attempts,
     });
 
     println!("{}", result);
-
-    Ok(())
 }

+ 2 - 0
doc/src/SUMMARY.md

@@ -15,3 +15,5 @@
   - [Examples](zkas/examples.md)
     - [Sapling scheme](zkas/examples/sapling.md)
     - [Anonymous voting](zkas/examples/voting.md)
+- [Miscellaneous tools](misc/misc.md)
+  - [vanityaddr](misc/vanityaddr.md)

+ 5 - 0
doc/src/misc/misc.md

@@ -0,0 +1,5 @@
+Miscellaneous tools
+===================
+
+This section documents some miscellaneous tools provided in the DarkFi
+ecosystem.

+ 40 - 0
doc/src/misc/vanityaddr.md

@@ -0,0 +1,40 @@
+vanityaddr
+==========
+
+A tool for Vanity address generation for DarkFi keypairs. Given some
+prefix, the tool will bruteforce secret keys to find one which, when
+derived into an address, starts with a given prefix.
+
+## Usage
+
+```
+vanityaddr 0.3.0
+Vanity address generation tool for DarkFi keypairs.
+
+USAGE:
+    vanityaddr [OPTIONS] <PREFIX>
+
+ARGS:
+    <PREFIX>    Prefix to search (must start with 1)
+
+OPTIONS:
+    -c                  Should the search be case-sensitive
+    -h, --help          Print help information
+    -t <THREADS>        Number of threads to use (defaults to number of available CPUs)
+    -V, --version       Print version information
+```
+
+We can use the tool in our command line:
+
+```
+% vanityaddr 1Foo
+[00:00:05] 53370 attempts
+```
+
+And the program will start crunching numbers. After a period of time,
+we will get JSON output containing an address, secret key, and the
+number of attempts it took to find the secret key.
+
+```
+{"address":"1FoomByzBBQywKaeBB5XPkAm5eCboh8K4CBhBe9uKbJm3kEiCS","attempts":78418,"secret":"0x16545da4a401adcd035ef51c8040acf5f4f1c66c0dd290bb5ec9e95991ae3615"}
+```