mimc.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. use bls12_381::Scalar;
  2. use ff::Field;
  3. use drk::{Decodable, ZKContract};
  4. use std::fs::File;
  5. use std::ops::{Add, AddAssign, MulAssign, Neg, SubAssign};
  6. use std::time::Instant;
  7. type Result<T> = std::result::Result<T, failure::Error>;
  8. mod mimc_constants;
  9. use mimc_constants::mimc_constants;
  10. const MIMC_ROUNDS: usize = 322;
  11. fn mimc(mut xl: Scalar, mut xr: Scalar, constants: &[Scalar]) -> Scalar {
  12. assert_eq!(constants.len(), MIMC_ROUNDS);
  13. for i in 0..MIMC_ROUNDS {
  14. let mut tmp1 = xl;
  15. tmp1.add_assign(&constants[i]);
  16. let mut tmp2 = tmp1.square();
  17. tmp2.mul_assign(&tmp1);
  18. tmp2.add_assign(&xr);
  19. xr = xl;
  20. xl = tmp2;
  21. }
  22. xl
  23. }
  24. macro_rules! from_slice {
  25. ($data:expr, $len:literal) => {{
  26. let mut array = [0; $len];
  27. // panics if not enough data
  28. let bytes = &$data[..array.len()];
  29. assert_eq!(bytes.len(), array.len());
  30. for (a, b) in array.iter_mut().rev().zip(bytes.iter()) {
  31. *a = *b;
  32. }
  33. //array.copy_from_slice(bytes.iter().rev());
  34. array
  35. }};
  36. }
  37. fn main() -> Result<()> {
  38. /////////////////////////////////
  39. // Initialize our MiMC constants
  40. let mut constants = Vec::new();
  41. for const_str in mimc_constants() {
  42. let bytes = from_slice!(&hex::decode(const_str).unwrap(), 32);
  43. assert_eq!(bytes.len(), 32);
  44. let constant = Scalar::from_bytes(&bytes).unwrap();
  45. constants.push(constant);
  46. }
  47. /////////////////////////////////
  48. // Load the contract from file
  49. let start = Instant::now();
  50. let file = File::open("mimc.zcd")?;
  51. let mut contract = ZKContract::decode(file)?;
  52. println!(
  53. "Loaded contract '{}': [{:?}]",
  54. contract.name,
  55. start.elapsed()
  56. );
  57. println!("Stats:");
  58. println!(" Constants: {}", contract.vm.constants.len());
  59. println!(" Alloc: {}", contract.vm.alloc.len());
  60. println!(" Operations: {}", contract.vm.ops.len());
  61. println!(
  62. " Constraint Instructions: {}",
  63. contract.vm.constraints.len()
  64. );
  65. // Do the trusted setup
  66. contract.setup("mimc.zts");
  67. // Put in our input parameters
  68. let left = Scalar::from_raw([
  69. 0xb981_9dc8_2d90_607e,
  70. 0xa361_ee3f_d48f_df77,
  71. 0x52a3_5a8c_1908_dd87,
  72. 0x15a3_6d1f_0f39_0d88,
  73. ]);
  74. let right = Scalar::from_raw([
  75. 0x7b0d_c53c_4ebf_1891,
  76. 0x1f3a_beeb_98fa_d3e8,
  77. 0xf789_1142_c001_d925,
  78. 0x015d_8c7f_5b43_fe33,
  79. ]);
  80. println!("----> {:?}", left);
  81. println!("----> {:?}", right);
  82. contract.set_param("left_0", left.clone())?;
  83. contract.set_param("right", right.clone())?;
  84. // Generate the ZK proof
  85. let proof = contract.prove()?;
  86. // Test and show our output values
  87. let mimc_hash = mimc(left, right, &constants);
  88. assert_eq!(proof.public.len(), 1);
  89. // 0x66ced46f14e5616d12b993f60a6e66558d6b6afe4c321ed212e0b9cfbd81061a
  90. assert_eq!(*proof.public.get("hash_result").unwrap(), mimc_hash);
  91. println!(
  92. "hash result = {:?}",
  93. proof.public.get("hash_result").unwrap()
  94. );
  95. // Verify the proof
  96. assert!(contract.verify(&proof));
  97. Ok(())
  98. }