|
@@ -19,7 +19,7 @@
|
|
|
use std::{process::exit, sync::mpsc::channel};
|
|
use std::{process::exit, sync::mpsc::channel};
|
|
|
|
|
|
|
|
use clap::Parser;
|
|
use clap::Parser;
|
|
|
-use darkfi_sdk::crypto::{Keypair, SecretKey};
|
|
|
|
|
|
|
+use darkfi_sdk::crypto::{PublicKey, SecretKey, TokenId};
|
|
|
use indicatif::{ProgressBar, ProgressStyle};
|
|
use indicatif::{ProgressBar, ProgressStyle};
|
|
|
use rand::rngs::OsRng;
|
|
use rand::rngs::OsRng;
|
|
|
use rayon::prelude::*;
|
|
use rayon::prelude::*;
|
|
@@ -37,28 +37,64 @@ struct Args {
|
|
|
#[clap(short)]
|
|
#[clap(short)]
|
|
|
case_sensitive: bool,
|
|
case_sensitive: bool,
|
|
|
|
|
|
|
|
|
|
+ /// Search for TokenId instead of an address
|
|
|
|
|
+ #[clap(long)]
|
|
|
|
|
+ token_id: bool,
|
|
|
|
|
+
|
|
|
/// Number of threads to use (defaults to number of available CPUs)
|
|
/// Number of threads to use (defaults to number of available CPUs)
|
|
|
#[clap(short)]
|
|
#[clap(short)]
|
|
|
threads: Option<usize>,
|
|
threads: Option<usize>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct DrkAddr {
|
|
struct DrkAddr {
|
|
|
- pub address: String,
|
|
|
|
|
|
|
+ pub public: PublicKey,
|
|
|
pub secret: SecretKey,
|
|
pub secret: SecretKey,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl DrkAddr {
|
|
impl DrkAddr {
|
|
|
pub fn new() -> Self {
|
|
pub fn new() -> Self {
|
|
|
- let kp = Keypair::random(&mut OsRng);
|
|
|
|
|
|
|
+ let secret = SecretKey::random(&mut OsRng);
|
|
|
|
|
+ let public = PublicKey::from_secret(secret);
|
|
|
|
|
+
|
|
|
|
|
+ Self { public, secret }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn starts_with(&self, prefix: &str, case_sensitive: bool) -> bool {
|
|
|
|
|
+ if case_sensitive {
|
|
|
|
|
+ self.public.to_string().starts_with(prefix)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ self.public.to_string().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
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct DrkToken {
|
|
|
|
|
+ pub token_id: TokenId,
|
|
|
|
|
+ pub secret: SecretKey,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl DrkToken {
|
|
|
|
|
+ pub fn new() -> Self {
|
|
|
|
|
+ let secret = SecretKey::random(&mut OsRng);
|
|
|
|
|
+ let token_id = TokenId::derive(secret);
|
|
|
|
|
|
|
|
- Self { secret: kp.secret, address: format!("{}", kp.public) }
|
|
|
|
|
|
|
+ Self { token_id, secret }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn starts_with(&self, prefix: &str, case_sensitive: bool) -> bool {
|
|
pub fn starts_with(&self, prefix: &str, case_sensitive: bool) -> bool {
|
|
|
if case_sensitive {
|
|
if case_sensitive {
|
|
|
- self.address.starts_with(prefix)
|
|
|
|
|
|
|
+ self.token_id.to_string().starts_with(prefix)
|
|
|
} else {
|
|
} else {
|
|
|
- self.address.to_lowercase().starts_with(prefix.to_lowercase().as_str())
|
|
|
|
|
|
|
+ self.token_id.to_string().to_lowercase().starts_with(prefix.to_lowercase().as_str())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -108,24 +144,38 @@ fn main() {
|
|
|
|
|
|
|
|
// Fire off the threadpool
|
|
// Fire off the threadpool
|
|
|
rayon_pool.spawn(move || {
|
|
rayon_pool.spawn(move || {
|
|
|
- let addr = rayon::iter::repeat(DrkAddr::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");
|
|
|
|
|
-
|
|
|
|
|
- // 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!(
|
|
|
|
|
- "{{\"address\":\"{}\",\"attempts\":{},\"secret\":\"{:?}\"}}",
|
|
|
|
|
- addr.address,
|
|
|
|
|
- attempts,
|
|
|
|
|
- addr.secret.inner()
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ if args.token_id {
|
|
|
|
|
+ let tid = rayon::iter::repeat(DrkToken::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");
|
|
|
|
|
+
|
|
|
|
|
+ // 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,
|
|
|
|
|
+ );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ let addr = rayon::iter::repeat(DrkAddr::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");
|
|
|
|
|
+
|
|
|
|
|
+ let attempts = progress.position();
|
|
|
|
|
+ progress.finish_and_clear();
|
|
|
|
|
+
|
|
|
|
|
+ println!(
|
|
|
|
|
+ "{{\"address\":\"{}\",\"attempts\":{},\"secret\":\"{}\"}}",
|
|
|
|
|
+ addr.public, attempts, addr.secret,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
exit(0);
|
|
exit(0);
|
|
|
});
|
|
});
|