Here is Rust puzzle script that will work from 1-256bit :
main.rs
use bitcoin::address::Address;
use bitcoin::key::PrivateKey;
use bitcoin::network::NetworkKind;
use chrono::Local;
use clap::{App, Arg};
use hex;
use num::bigint::BigInt;
use num::traits::One;
use num_cpus;
use rand::Rng;
use rand::rngs::StdRng;
use rand::SeedableRng;
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();
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 || {
let mut rng = StdRng::from_entropy();
random_lookfor(&rng.gen_range(range_start_clone.clone()..range_end_clone.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 = StdRng::from_entropy();
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: NetworkKind::Main,
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, NetworkKind::Main).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;
}
}
}
Cargo.toml
[package]
name = "puzzle"
version = "0.1.0"
edition = "2021"
[dependencies]
num = "0.4.1"
num-traits = "0.2"
num-bigint = { version = "0.4.4", features = ["rand"] }
threadpool = "1.8.1"
bitcoin = "0.32.2"
hex = "0.4.3"
rand = "0.8.5"
secp256k1 = "0.29.0"
num_cpus = "1.16.0"
chrono = "0.4.38"
clap = "3.0"
ctrlc = "3.4.4"
Build program
cargo build --release --target=x86_64-unknown-linux-gnu
it will be generated in
./target/x86_64-unknown-linux-gnu/release/puzzle
Usage example
./puzzle -p 20 -a 1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum
./puzzle -p 30 -a 1LHtnpd8nU5VHEMkG2TMYYNUjjLc992bps
./puzzle -p 66 -a 13zb1hQbWVsc2S7ZTZnP2G4undNNpdh5so
./puzzle -p 130 -a 1Fo65aKq8s8iquMt6weF1rku1moWVEd5Ua
it's not exactly like C, but it's 10 times faster than Python.
time ./puzzle -p 30 -a 1LHtnpd8nU5VHEMkG2TMYYNUjjLc992bps
- Puzzle search
- Script started at:2024-07-07 21:45:29
- concurrency:12
- puzzle:30
- from:536870912 to:1073741823
- target:1LHtnpd8nU5VHEMkG2TMYYNUjjLc992bps
- --------------------------------------------------------------------------------
- KEY FOUND! 2024-07-07 21:46:30
- decimal: 1033162084
- private key: KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M8diLSC5MyERoW
- public key: 030d282cf2ff536d2c42f105d0b8588821a915dc3f9a05bd98bb23af67a2e92a5b
- address: 1LHtnpd8nU5VHEMkG2TMYYNUjjLc992bps
- --------------------------------------------------------------------------------
real 1m0.850s
user 10m54.448s
sys 0m0.196s
There are various types of RNGs in Rust, each with its own set of trade-offs and speed.
Here is a list:
https://rust-random.github.io/book/guide-rngs.html
To determine the fastest RNG for this specific use case, you might need to benchmark various RNGs within the context of this application. The next stage is to implement kangaroo full in Rust