use bitcoin::address::Address;
use bitcoin::key::PrivateKey;
use bitcoin::network::Network;
use chrono::Local;
use clap::{App, Arg};
use hex;
use num::bigint::BigInt;
use num::traits::One;
use num_cpus;
use rand::Rng;
use std::fs::File;
use std::io::{self, Write};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc};
use std::convert::TryInto;
use threadpool::ThreadPool;
fn main() {
// Print the current time when the script starts
let current_time = Local::now();
print!("\x1b[2J\x1b[1;1H");
println!(
"\x1b[38;5;226m[+] Puzzle search\n[+] Script started at:{}",
current_time.format("%Y-%m-%d %H:%M:%S")
);
let matches = App::new("Puzzle Solver")
.version("1.0")
.arg(
Arg::with_name("puzzle")
.short('p')
.long("puzzle")
.value_name("PUZZLE")
.help("Sets the puzzle number")
.required(true)
.takes_value(true),
)
.arg(
Arg::with_name("address")
.short('a')
.long("address")
.value_name("ADDRESS")
.help("Sets the target address")
.required(true)
.takes_value(true),
)
.get_matches();
let puzzle_str = matches.value_of("puzzle").unwrap();
let puzzle: u128 = puzzle_str.parse().expect("Failed to parse puzzle number");
let target_address = Arc::new(matches
.value_of("address")
.expect("Target address is required")
.to_string());
let range_start: BigInt = num::pow(BigInt::from(2), (puzzle - 1) as usize);
let range_end: BigInt = num::pow(BigInt::from(2), puzzle as usize) - BigInt::one();
let num_threads = num_cpus::get() as usize; // Convert to usize
println!(
"[+] concurrency:{}\n[+] puzzle:{}\n[+] from:{} to:{}\n[+] target:{}",
num_threads, puzzle, range_start, range_end, target_address
);
let found_flag = Arc::new(AtomicBool::new(false));
let pool = ThreadPool::new(num_threads.try_into().unwrap()); // Convert to usize
// Handling termination signals
let found_flag_clone = found_flag.clone();
ctrlc::set_handler(move || {
found_flag_clone.store(true, Ordering::Relaxed);
std::process::exit(0); // Terminate the program
})
.expect("Error setting Ctrl-C handler");
for _ in 0..num_threads {
let target_address = Arc::clone(&target_address);
let range_start_clone = range_start.clone();
let range_end_clone = range_end.clone();
let found_flag = found_flag.clone();
let pool_clone = pool.clone();
pool.execute(move || {
random_lookfor(&range_start_clone, &range_end_clone, &target_address, &found_flag, &pool_clone);
});
}
pool.join();
}
fn random_lookfor(
range_start: &BigInt,
range_end: &BigInt,
target_address: &Arc
,
found_flag: &Arc,
_pool: &ThreadPool,
) {
let mut rng = rand::thread_rng();
let secp = bitcoin::secp256k1::Secp256k1::new();
loop {
let key: BigInt = rng.gen_range(range_start.clone()..range_end.clone());
let private_key_hex = format!("{:0>64x}", key);
let private_key_bytes =
hex::decode(&private_key_hex).expect("Failed to decode private key hex");
let private_key = PrivateKey {
compressed: true,
network: Network::Bitcoin,
inner: bitcoin::secp256k1::SecretKey::from_slice(&private_key_bytes)
.expect("Failed to create secret key from slice"),
};
let public_key = private_key.public_key(&secp);
let address = Address::p2pkh(&public_key, Network::Bitcoin).to_string();
print!("[+] key:{}\r", key);
io::stdout().flush().unwrap();
// Check if a match has been found by another thread
if found_flag.load(Ordering::Relaxed) {
break;
}
if address == **target_address {
let current_time = Local::now();
let line_of_dashes = "-".repeat(80);
println!(
"\n[+] {}\n[+] KEY FOUND! {}\n[+] decimal: {} \n[+] private key: {} \n[+] public key: {} \n[+] address: {}\n[+] {}",
line_of_dashes,
current_time.format("%Y-%m-%d %H:%M:%S"),
key,
private_key,
public_key,
address,
line_of_dashes
);
// Set the flag to true to signal other threads to exit
found_flag.store(true, Ordering::Relaxed);
if let Ok(mut file) = File::create("KEYFOUNDKEYFOUND.txt") {
let line_of_dashes = "-".repeat(130);
writeln!(
&mut file,
"\n{}\nKEY FOUND! {}\ndecimal: {} \nprivate key: {} \npublic key: {} \naddress: {}\n{}",
line_of_dashes,
current_time.format("%Y-%m-%d %H:%M:%S"),
key,
private_key,
public_key,
address,
line_of_dashes
)
.expect("Failed to write to file");
} else {
eprintln!("Error: Failed to create or write to KEYFOUNDKEYFOUND.txt");
}
io::stdout().flush().unwrap();
break;
}
}
}RUSTFLAGS="-C target-feature=+ssse3" cargo build --release --target=x86_64-unknown-linux-gnu