darkfi_sdk/crypto/
mimc_vdf.rsuse num_bigint::BigUint;
use num_traits::Num;
const MODULUS: &str =
"115792089237316195423570985008687907853269984665640564039457584006405596119041";
const L_FERMAT_EXPONENT: &str =
"77194726158210796949047323339125271902179989777093709359638389337603730746027";
fn calculate_round_constants() -> [BigUint; 64] {
let mut round_constants: Vec<BigUint> = vec![];
#[allow(clippy::needless_range_loop)]
for i in 0u64..64 {
round_constants.push(BigUint::from(i).pow(7) ^ BigUint::from(42u64));
}
round_constants.try_into().unwrap()
}
fn forward_mimc(num_steps: u64, input: &BigUint) -> BigUint {
let modulus = BigUint::from_str_radix(MODULUS, 10).unwrap();
let round_constants = calculate_round_constants();
let mut result = input.clone();
let three = BigUint::from(3_u64);
for i in 1..num_steps {
result = (result.modpow(&three, &modulus) +
&round_constants[i as usize % round_constants.len()])
.modpow(&BigUint::from(1_u64), &modulus);
}
result
}
fn backward_mimc(num_steps: u64, input: &BigUint) -> BigUint {
let modulus = BigUint::from_str_radix(MODULUS, 10).unwrap();
let l_fermat_exp = BigUint::from_str_radix(L_FERMAT_EXPONENT, 10).unwrap();
let round_constants = calculate_round_constants();
let mut result = input.clone();
for i in (1..num_steps).rev() {
let round_constant = &round_constants[i as usize % round_constants.len()];
result = (&result - round_constant).modpow(&l_fermat_exp, &modulus);
}
result
}
pub fn eval(seed: &BigUint, num_steps: u64) -> BigUint {
backward_mimc(num_steps, seed)
}
pub fn verify(seed: &BigUint, num_steps: u64, witness: &BigUint) -> bool {
forward_mimc(num_steps, witness) == *seed
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mimc_vdf_eval_and_verify() {
let steps = 1000;
let challenge = blake3::hash(b"69420").to_hex();
let challenge = BigUint::from_str_radix(&challenge, 16).unwrap();
let witness = eval(&challenge, steps);
assert!(verify(&challenge, steps, &witness));
assert!(!verify(&(&challenge - 1_u64), steps, &witness));
assert!(!verify(&challenge, steps - 1, &witness));
assert!(!verify(&challenge, steps, &(&witness - 1_u64)));
}
}