Last active
June 19, 2024 22:47
-
-
Save lovasoa/9bb6c50feed7bb264c15ae65c6222b45 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "hash_miner" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
rayon = "1.5" | |
sha2 = "0.10" | |
num_cpus = "1.13" | |
[profile.release] | |
opt-level = 3 | |
debug = false | |
lto = true | |
[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'] | |
rustflags = ["-C", "target-cpu=native"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::sync::atomic::{AtomicU32, Ordering}; | |
use std::sync::Arc; | |
use sha2::{Sha256, Digest}; | |
use rayon::iter::IntoParallelIterator; | |
use rayon::iter::ParallelIterator; | |
const PREFIX: &[u8] = b"x/https+ophir+dev/"; | |
const BLOCK_SIZE: usize = 32; // SHA256 hash size in bytes | |
const CHAR_START: u8 = b'a'; | |
const CHAR_END: u8 = b'z'; | |
/// Function to find the string with the lowest hash (most leading zeroes) | |
fn find_lowest_hash(num_threads: usize) { | |
let max_zeroes = Arc::new(AtomicU32::new(0)); | |
(0..num_threads).into_par_iter().for_each(|thread_idx| { | |
let mut candidate = [CHAR_START; BLOCK_SIZE]; | |
candidate[..PREFIX.len()].copy_from_slice(PREFIX); | |
candidate[PREFIX.len()] = CHAR_START + thread_idx as u8; | |
let mut hasher = Sha256::new(); | |
loop { | |
increment_bytes(&mut candidate); | |
// Compute the SHA256 hash | |
hasher.update(&candidate); | |
let leading_zeroes = count_leading_zeroes(&hasher.finalize_reset()); | |
// Update maximum leading zeroes found | |
let current_max = max_zeroes.load(Ordering::Relaxed); | |
if leading_zeroes > current_max { | |
max_zeroes.store(leading_zeroes, Ordering::Relaxed); | |
println!("New best string: {} with leading zeroes: {}", String::from_utf8_lossy(&candidate), leading_zeroes); | |
} | |
} | |
}); | |
} | |
/// Increments the given byte array by one, wrapping within CHAR_START..CHAR_END | |
fn increment_bytes(arr: &mut [u8; BLOCK_SIZE]) { | |
for byte in arr.iter_mut().rev() { | |
if *byte == CHAR_END { | |
*byte = CHAR_START; | |
} else { | |
*byte += 1; | |
return; // No need to carry over to higher digits | |
} | |
} | |
} | |
/// Counts the number of leading zeroes in a hexadecimal string | |
fn count_leading_zeroes(hash: &[u8]) -> u32 { | |
let mut leading_zeroes = 0; | |
// Count full bytes of leading zeroes | |
for &byte in hash { | |
let zeros = byte.leading_zeros(); | |
leading_zeroes += zeros; | |
if zeros < 8 { | |
break; | |
} | |
} | |
leading_zeroes | |
} | |
fn main() { | |
let num_threads = num_cpus::get(); | |
find_lowest_hash(num_threads); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
RUSTFLAGS="-C target-cpu=native" cargo run --release |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment