use anyhow::Context;
use base64::{Engine as _, engine::general_purpose::STANDARD_NO_PAD};
pub fn solve_puzzle(puzzle: &str, difficulty: u16, on_progress: impl Fn(f64)) -> String {
STANDARD_NO_PAD.encode(
melpow::Proof::generate_with_progress(
puzzle.as_bytes(),
difficulty as _,
on_progress,
Blake3HashFunction,
)
.to_bytes(),
)
}
pub fn verify_puzzle_solution(puzzle: &str, difficulty: u16, solution: &str) -> anyhow::Result<()> {
let solution = STANDARD_NO_PAD.decode(solution)?;
let solution = melpow::Proof::from_bytes(&solution).context("invalid solution format")?;
if !solution.verify(puzzle.as_bytes(), difficulty as _, Blake3HashFunction) {
anyhow::bail!("invalid solution to puzzle")
}
Ok(())
}
struct Blake3HashFunction;
impl melpow::HashFunction for Blake3HashFunction {
fn hash(&self, b: &[u8], k: &[u8]) -> melpow::SVec<u8> {
melpow::SVec::from_slice(blake3::keyed_hash(blake3::hash(k).as_bytes(), b).as_bytes())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_progress_callback_invoked() {
let puzzle = "progress test";
let difficulty = 15;
let res = solve_puzzle(puzzle, difficulty, |progress| {
dbg!(progress);
});
dbg!(res.len());
}
}