feat: implement stepped proof generation to report progess
ref: mCaptcha/2023-NLnet#8
This commit is contained in:
parent
debd7805d0
commit
0e96f03166
1 changed files with 93 additions and 0 deletions
93
src/lib.rs
93
src/lib.rs
|
@ -50,7 +50,74 @@ pub struct Config {
|
|||
pub salt: String,
|
||||
}
|
||||
|
||||
pub enum SteppedSolve<T> {
|
||||
Intermediate(u128, u64, Sha256, u128),
|
||||
Work(PoW<T>),
|
||||
}
|
||||
|
||||
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.
|
||||
///
|
||||
/// 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_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),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue