use crate::table::{pow_hit_via_table, Table};
use num_bigint::BigUint;
pub fn target_from_b(b_decimal: &str) -> Option<BigUint> {
b_decimal.parse::<BigUint>().ok()
}
pub fn target_from_difficulty(d: &BigUint) -> BigUint {
let two256 = BigUint::from(1u8) << 256;
two256 / d
}
pub struct Found {
pub nonce: [u8; 8],
pub hit: BigUint,
}
pub fn search(table: &Table, msg: &[u8], start: u64, count: u64, target: &BigUint) -> Option<Found> {
for k in 0..count {
let nonce = start.wrapping_add(k).to_be_bytes();
let hit = pow_hit_via_table(table, msg, &nonce);
if &hit < target {
return Some(Found { nonce, hit });
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use crate::pow_hit;
use blake_bench::reference::blake2b256;
#[test]
fn finds_a_nonce_below_an_easy_target() {
let height = 614400;
let m = crate::big_m();
let n = 4096u32;
let h = crate::height_bytes(height);
let rows: Vec<u8> = (0..n)
.flat_map(|idx| crate::table::gen_element(idx, &h, &m).to_vec())
.collect();
let table = Table { n, rows, h, m: m.clone() };
let msg = blake2b256(b"erga share search test");
let target = BigUint::from(1u8) << 248;
let found = search(&table, &msg, 0, 100_000, &target).expect("a share within 100k nonces");
assert!(found.hit < target);
let recheck = pow_hit(&msg, &found.nonce, &table.h, n, &m);
assert_eq!(recheck, found.hit, "found nonce must verify the recompute way");
assert!(recheck < target, "and clear the target under recompute");
}
}