use std::{sync::{Arc, Mutex}, thread}; use digest::{FixedOutput, Input}; use rand::rngs::OsRng; use ripemd160::Ripemd160; use secp256k1::{key::PublicKey, Secp256k1}; use sha2::Sha256; fn main() { let args = std::env::args(); if args.len() <= 1 { println!("[ERROR] Need at least one argument, e.g. 1Hatter 1UTF8 ..."); return; } let continue_on_found = std::env::var("CONTINUE_ON_FOUND") .map(|c| c.to_lowercase()) .map(|c| c == "1" || c == "true" || c == "yes" || c == "on") .unwrap_or_else(|_| false); let prefixes: Vec = args.skip(1).collect(); println!("Prefixes: {:?}", prefixes); if continue_on_found { println!("CONTINUE_ON_FOUND is ON"); } else { println!("CONTINUE_ON_FOUND is OFF"); } let loop_count = std::env::var("LOOP_COUNT") .map(|c| c.parse::()) .unwrap_or_else(|_| Ok(10_000_000_u64)) .unwrap_or_else(|_| 10_000_000_u64); println!("LOOP_COUNT={}", loop_count); let num_of_vcpus = num_cpus::get(); let num_of_phycpus = num_cpus::get_physical(); println!("You have {} vCPUs, from {} phyCPUs", num_of_vcpus, num_of_phycpus); let concurrent_count = std::env::var("CONCURRENT_COUNT") .map(|c| c.parse::()) .unwrap_or_else(|_| Ok(num_of_phycpus as u64)) .unwrap_or_else(|_| 1_u64); println!("CONCURRENT_COUNT={}", concurrent_count); let stop_flag = Arc::new(Mutex::new(false)); let mut handles = vec![]; for ind in 0..concurrent_count { println!("- Running task {} of {}", ind, concurrent_count); let the_stop_flag = Arc::clone(&stop_flag); let prefixes = prefixes.clone(); let child = thread::spawn(move || { run_one_task(prefixes, continue_on_found, loop_count, ind, the_stop_flag); }); handles.push(child); } while let Some(h) = handles.pop() { h.join().unwrap(); } println!("Finished!"); } fn run_one_task(prefixes: Vec, continue_on_found: bool, loop_count: u64, ind: u64, the_stop_flag: Arc>) { let secp = Secp256k1::new(); let mut rng = OsRng::new().expect("OsRng"); for i in 0..loop_count { let (secret_key, public_key) = secp.generate_keypair(&mut rng); let s = make_btc_address(&public_key); if i % 1_000 == 0 { if *the_stop_flag.lock().unwrap() { return; } if i > 0 && i % 100_000 == 0 { println!("> {} - {}", ind, i); } } if prefixes.iter().any(|p| s.starts_with(p)) { println!(">> {}\n{}", s, secret_key); if !continue_on_found { *the_stop_flag.lock().unwrap() = true; break; } } } } fn make_btc_address(public_key: &PublicKey) -> String { let public_key_bytes = public_key.serialize_uncompressed().to_vec(); let riphemd160_sha256_pub_key = calc_ripemd160(&calc_sha256(&public_key_bytes)); let mut btc_addr = Vec::::with_capacity(25); btc_addr.push(0x00 as u8); btc_addr.extend_from_slice(&riphemd160_sha256_pub_key); let checksum = &calc_sha256(&calc_sha256(&btc_addr))[0..4]; btc_addr.extend_from_slice(checksum); bs58::encode(&btc_addr).into_string() } #[inline] fn calc_sha256(i: &[u8]) -> Vec { calc_hash(Sha256::default(), i) } #[inline] fn calc_ripemd160(i: &[u8]) -> Vec { calc_hash(Ripemd160::default(), i) } #[inline] fn calc_hash(mut hasher: T, i: &[u8]) -> Vec where T: Input + FixedOutput { hasher.input(&i); hasher.fixed_result().to_vec() }