crypto: Add MiMC VDF.

This commit is contained in:
Luther Blissett
2022-09-21 15:43:02 +02:00
parent 5fc3fc8d29
commit de7b6e9bd7
4 changed files with 108 additions and 5 deletions

13
Cargo.lock generated
View File

@@ -1203,6 +1203,8 @@ dependencies = [
"libsqlite3-sys",
"log",
"native-tls",
"num-bigint",
"num-traits",
"pasta_curves",
"plotters",
"rand",
@@ -2624,6 +2626,17 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "num-bigint"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"

View File

@@ -118,8 +118,8 @@ crypto_api_chachapoly = {version = "0.5.0", optional = true}
incrementalmerkletree = {version = "0.3.0", optional = true}
halo2_proofs = {version = "0.2.0", optional = true}
halo2_gadgets = {version = "0.2.0", optional = true}
#halo2_proofs = {git = "https://github.com/zcash/halo2.git", rev = "a898d65ae3ad3d41987666f6a03cfc15edae01c4", optional = true}
#halo2_gadgets = {git = "https://github.com/zcash/halo2.git", rev = "a898d65ae3ad3d41987666f6a03cfc15edae01c4", optional = true}
num-bigint = {version = "0.4.3", optional = true}
num-traits = {version = "0.2.15", optional = true}
# Smart contract runtime
drk-sdk = {path = "src/sdk", optional = true}
@@ -138,9 +138,6 @@ sled = {version = "0.34.7", optional = true}
clap = {version = "3.2.20", features = ["derive"]}
halo2_proofs = {version = "0.2.0", features = ["dev-graph", "gadget-traces", "sanity-checks"]}
halo2_gadgets = {version = "0.2.0", features = ["dev-graph", "test-dependencies"]}
#halo2_proofs = {git = "https://github.com/zcash/halo2.git", rev = "a898d65ae3ad3d41987666f6a03cfc15edae01c4", features = ["dev-graph", "gadget-traces", "sanity-checks"]}
#halo2_gadgets = {git = "https://github.com/zcash/halo2.git", rev = "a898d65ae3ad3d41987666f6a03cfc15edae01c4", features = ["dev-graph", "test-dependencies"]}
plotters = "0.3.3"
[features]
@@ -241,6 +238,8 @@ crypto = [
"incrementalmerkletree",
"halo2_proofs",
"halo2_gadgets",
"num-bigint",
"num-traits",
"subtle",
"lazy_static",
"group",

88
src/crypto/mimc_vdf.rs Normal file
View File

@@ -0,0 +1,88 @@
//! https://vitalik.ca/general/2018/07/21/starks_part_3.html
use num_bigint::BigUint;
use num_traits::Num;
/// Modulus of prime field 2^256 - 2^32 * 351 + 1
pub const MODULUS: &str =
"115792089237316195423570985008687907853269984665640564039457584006405596119041";
/// An exponent to perform inverse of x^3 on prime field based on Fermat's Little Theorem
pub const L_FERMAT_EXPONENT: &str =
"77194726158210796949047323339125271902179989777093709359638389337603730746027";
/// Calculates set of round constants to perform MiMC-calculation on.
fn calculate_round_constants() -> [u64; 64] {
let mut round_constants = [0u64; 64];
for i in 0usize..64 {
round_constants[i] = (i.pow(7) ^ 42) as u64;
}
round_constants
}
/// Executes `num_steps` of MiMC-calculation in forward direction for the given `input`
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) +
BigUint::from(round_constants[i as usize % round_constants.len()])) %
&modulus;
}
result
}
/// Executes `num_steps` of MiMC-calculation in backward direction for the given `input`.
///
/// The properties of MiMC-scheme guarantees that calculation in backward direction is
/// always slower than in forward for correctly chosen parameters.
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 = BigUint::from(round_constants[i as usize % round_constants.len()]);
result = BigUint::from(&result - &round_constant).modpow(&l_fermat_exp, &modulus);
}
result
}
/// Performs an Eval() step of the MiMC-based VDF
pub fn eval(seed: &BigUint, num_steps: u64) -> BigUint {
let witness = backward_mimc(num_steps, &seed);
witness
}
/// Performs a Verify() step for the MiMC-based VDF result
pub fn verify(seed: &BigUint, num_steps: u64, witness: &BigUint) -> bool {
let result = forward_mimc(num_steps, witness);
result == *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_eq!(false, verify(&(&challenge - 1_u64), steps, &witness));
assert_eq!(false, verify(&challenge, steps - 1, &witness));
assert_eq!(false, verify(&challenge, steps, &(&witness - 1_u64)));
}
}

View File

@@ -17,6 +17,9 @@ pub mod token_list;
pub mod types;
pub mod util;
/// VDF (Verifiable Delay Function) using MiMC
pub mod mimc_vdf;
pub use burn_proof::BurnRevealedValues;
pub use mint_proof::MintRevealedValues;
pub use proof::Proof;