Răsfoiți Sursa

crypto: Add MiMC VDF.

Luther Blissett 3 ani în urmă
părinte
comite
de7b6e9bd7
4 a modificat fișierele cu 108 adăugiri și 5 ștergeri
  1. 13 0
      Cargo.lock
  2. 4 5
      Cargo.toml
  3. 88 0
      src/crypto/mimc_vdf.rs
  4. 3 0
      src/crypto/mod.rs

+ 13 - 0
Cargo.lock

@@ -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"

+ 4 - 5
Cargo.toml

@@ -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 - 0
src/crypto/mimc_vdf.rs

@@ -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)));
+    }
+}

+ 3 - 0
src/crypto/mod.rs

@@ -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;