feat: implement stepped proof generation to report progess

ref: mCaptcha/2023-NLnet#8
This commit is contained in:
Aravinth Manivannan 2023-07-04 19:03:32 +05:30
parent debd7805d0
commit 0e96f03166
Signed by: realaravinth
GPG key ID: F8F50389936984FF

View file

@ -50,7 +50,74 @@ pub struct Config {
pub salt: String, pub salt: String,
} }
pub enum SteppedSolve<T> {
Intermediate(u128, u64, Sha256, u128),
Work(PoW<T>),
}
impl Config { impl Config {
pub fn stepped_prove_work<T>(
&self,
t: &T,
difficulty: u32,
step: usize,
inter: Option<SteppedSolve<T>>,
) -> bincode::Result<SteppedSolve<T>>
where
T: Serialize,
{
bincode::serialize(t)
.map(|v| self.stepped_prove_work_serialized(&v, difficulty, step, inter))
}
/// Create Proof of Work on an already serialized item of type T.
/// The input is assumed to be serialized using network byte order.
///
/// Make sure difficulty is not too high. A 64 bit difficulty,
/// for example, takes a long time on a general purpose processor.
pub fn stepped_prove_work_serialized<T>(
&self,
prefix: &[u8],
difficulty: u32,
step: usize,
inter: Option<SteppedSolve<T>>,
) -> SteppedSolve<T>
where
T: Serialize,
{
let (mut result, mut n, prefix_sha, difficulty) = match inter {
Some(SteppedSolve::Intermediate(result, nonce, prefix, difficulty)) => {
(result, nonce, prefix, difficulty)
}
_ => {
let prefix_sha = Sha256::new().chain(&self.salt).chain(prefix);
let n = 0;
let result = 0;
let difficulty = get_difficulty(difficulty);
(result, n, prefix_sha, difficulty)
}
};
let mut count = 0;
// let prefix_sha = Sha256::new().chain(&self.salt).chain(prefix);
// let mut n = 0;
// let mut result = 0;
// let difficulty = get_difficulty(difficulty);
while result < difficulty {
if count > step {
return SteppedSolve::Intermediate(result, n, prefix_sha, difficulty);
} else {
count += 1;
}
n += 1;
result = dev::score(prefix_sha.clone(), n);
}
SteppedSolve::Work(PoW {
nonce: n,
result: result.to_string(),
_spook: PhantomData,
})
}
/// Create Proof of Work over item of type T. /// Create Proof of Work over item of type T.
/// ///
/// Make sure difficulty is not too high. A 64 bit difficulty, /// Make sure difficulty is not too high. A 64 bit difficulty,
@ -262,4 +329,30 @@ mod test {
assert!(config.is_sufficient_difficulty(&message.1, DIFFICULTY)); assert!(config.is_sufficient_difficulty(&message.1, DIFFICULTY));
assert!(config.is_valid_proof(&message.1, &target)); assert!(config.is_valid_proof(&message.1, &target));
} }
#[test]
fn stepped_solve() {
let phrase = "Ex nihilo nihil fit.".to_owned();
let config = get_config();
let mut inter = None;
loop {
match config.stepped_prove_work(&phrase, 50000, 1000, inter) {
Ok(SteppedSolve::Intermediate(result, nonce, prefix, difficulty)) => {
println!("Current nonce {nonce}");
inter = Some(SteppedSolve::Intermediate(
result, nonce, prefix, difficulty,
));
continue;
}
Ok(SteppedSolve::Work(w)) => {
assert!(config.is_valid_proof(&w, &phrase));
assert!(config.is_sufficient_difficulty(&w, DIFFICULTY));
break;
}
Err(e) => panic!("{}", e),
};
}
}
} }