You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.0 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. extern crate rand;
  2. #[macro_use]
  3. extern crate ff;
  4. use ff::*;
  5. #[derive(PrimeField)]
  6. #[PrimeFieldModulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"]
  7. #[PrimeFieldGenerator = "7"]
  8. pub struct Fr(FrRepr);
  9. extern crate num;
  10. extern crate num_bigint;
  11. use num_bigint::{BigInt, Sign};
  12. use tiny_keccak::Keccak;
  13. const SEED: &str = "mimc";
  14. pub struct Constants {
  15. n_rounds: usize,
  16. cts: Vec<Fr>,
  17. }
  18. pub fn generate_constants(n_rounds: usize) -> Constants {
  19. let cts = get_constants(SEED, n_rounds);
  20. Constants {
  21. n_rounds: n_rounds,
  22. cts: cts,
  23. }
  24. }
  25. pub fn get_constants(seed: &str, n_rounds: usize) -> Vec<Fr> {
  26. let mut cts: Vec<Fr> = Vec::new();
  27. cts.push(Fr::zero());
  28. let mut keccak = Keccak::new_keccak256();
  29. let mut h = [0u8; 32];
  30. keccak.update(seed.as_bytes());
  31. keccak.finalize(&mut h);
  32. let r: BigInt = BigInt::parse_bytes(
  33. b"21888242871839275222246405745257275088548364400416034343698204186575808495617",
  34. 10,
  35. )
  36. .unwrap();
  37. let mut c = BigInt::from_bytes_be(Sign::Plus, &h);
  38. for _ in 1..n_rounds {
  39. let (_, c_bytes) = c.to_bytes_be();
  40. let mut c_bytes32: [u8; 32] = [0; 32];
  41. let diff = c_bytes32.len() - c_bytes.len();
  42. c_bytes32[diff..].copy_from_slice(&c_bytes[..]);
  43. let mut keccak = Keccak::new_keccak256();
  44. let mut h = [0u8; 32];
  45. keccak.update(&c_bytes[..]);
  46. keccak.finalize(&mut h);
  47. c = BigInt::from_bytes_be(Sign::Plus, &h);
  48. let n = modulus(&c, &r);
  49. cts.push(Fr::from_str(&n.to_string()).unwrap());
  50. }
  51. cts
  52. }
  53. pub fn modulus(a: &BigInt, m: &BigInt) -> BigInt {
  54. ((a % m) + m) % m
  55. }
  56. pub struct Mimc7 {
  57. constants: Constants,
  58. }
  59. impl Mimc7 {
  60. pub fn new(n_rounds: usize) -> Mimc7 {
  61. Mimc7 {
  62. constants: generate_constants(n_rounds),
  63. }
  64. }
  65. pub fn hash(&self, x_in: &Fr, k: &Fr) -> Fr {
  66. let mut h: Fr = Fr::zero();
  67. for i in 0..self.constants.n_rounds {
  68. let mut t: Fr;
  69. if i == 0 {
  70. t = x_in.clone();
  71. t.add_assign(k);
  72. } else {
  73. t = h.clone();
  74. t.add_assign(&k);
  75. t.add_assign(&self.constants.cts[i]);
  76. }
  77. let mut t2 = t.clone();
  78. t2.square();
  79. let mut t7 = t2.clone();
  80. t7.square();
  81. t7.mul_assign(&t2);
  82. t7.mul_assign(&t);
  83. h = t7.clone();
  84. }
  85. h.add_assign(&k);
  86. h
  87. }
  88. pub fn multi_hash(&self, arr: Vec<Fr>, key: &Fr) -> Fr {
  89. let mut r = key.clone();
  90. for i in 0..arr.len() {
  91. let h = self.hash(&arr[i], &r);
  92. r.add_assign(&arr[i]);
  93. r.add_assign(&h);
  94. }
  95. r
  96. }
  97. }
  98. #[cfg(test)]
  99. mod tests {
  100. use super::*;
  101. #[test]
  102. fn test_generate_constants() {
  103. let constants = generate_constants(91);
  104. assert_eq!(
  105. "Fr(0x2e2ebbb178296b63d88ec198f0976ad98bc1d4eb0d921ddd2eb86cb7e70a98e5)",
  106. constants.cts[1].to_string()
  107. );
  108. }
  109. #[test]
  110. fn test_mimc() {
  111. let b1: Fr = Fr::from_str("1").unwrap();
  112. let b2: Fr = Fr::from_str("2").unwrap();
  113. let mimc7 = Mimc7::new(91);
  114. let h1 = mimc7.hash(&b1, &b2);
  115. assert_eq!(
  116. h1.to_string(),
  117. "Fr(0x176c6eefc3fdf8d6136002d8e6f7a885bbd1c4e3957b93ddc1ec3ae7859f1a08)"
  118. );
  119. let b3: Fr = Fr::from_str("3").unwrap();
  120. let mut arr: Vec<Fr> = Vec::new();
  121. arr.push(b1.clone());
  122. arr.push(b2.clone());
  123. arr.push(b3.clone());
  124. let h1 = mimc7.multi_hash(arr, &Fr::zero());
  125. assert_eq!(
  126. h1.to_string(),
  127. "Fr(0x25f5a6429a9764564be3955e6f56b0b9143c571528fd30a80ae6c27dc8b4a40c)"
  128. );
  129. let b12: Fr = Fr::from_str("12").unwrap();
  130. let b45: Fr = Fr::from_str("45").unwrap();
  131. let b78: Fr = Fr::from_str("78").unwrap();
  132. let b41: Fr = Fr::from_str("41").unwrap();
  133. let mut big_arr1: Vec<Fr> = Vec::new();
  134. big_arr1.push(b12.clone());
  135. let mimc7 = Mimc7::new(91);
  136. let h1 = mimc7.multi_hash(big_arr1, &Fr::zero());
  137. assert_eq!(
  138. h1.to_string(),
  139. "Fr(0x237c92644dbddb86d8a259e0e923aaab65a93f1ec5758b8799988894ac0958fd)"
  140. );
  141. let mh2 = mimc7.hash(&b12, &b45);
  142. assert_eq!(
  143. mh2.to_string(),
  144. "Fr(0x2ba7ebad3c6b6f5a20bdecba2333c63173ca1a5f2f49d958081d9fa7179c44e4)"
  145. );
  146. let mut big_arr1: Vec<Fr> = Vec::new();
  147. big_arr1.push(b78.clone());
  148. big_arr1.push(b41.clone());
  149. let h2 = mimc7.multi_hash(big_arr1, &Fr::zero());
  150. assert_eq!(
  151. h2.to_string(),
  152. "Fr(0x067f3202335ea256ae6e6aadcd2d5f7f4b06a00b2d1e0de903980d5ab552dc70)"
  153. );
  154. let mut big_arr1: Vec<Fr> = Vec::new();
  155. big_arr1.push(b12.clone());
  156. big_arr1.push(b45.clone());
  157. let h1 = mimc7.multi_hash(big_arr1, &Fr::zero());
  158. assert_eq!(
  159. h1.to_string(),
  160. "Fr(0x15ff7fe9793346a17c3150804bcb36d161c8662b110c50f55ccb7113948d8879)"
  161. );
  162. let mut big_arr1: Vec<Fr> = Vec::new();
  163. big_arr1.push(b12.clone());
  164. big_arr1.push(b45.clone());
  165. big_arr1.push(b78.clone());
  166. big_arr1.push(b41.clone());
  167. let mimc7 = Mimc7::new(91);
  168. let h1 = mimc7.multi_hash(big_arr1, &Fr::zero());
  169. assert_eq!(
  170. h1.to_string(),
  171. "Fr(0x284bc1f34f335933a23a433b6ff3ee179d682cd5e5e2fcdd2d964afa85104beb)"
  172. );
  173. let r_1: Fr = Fr::from_str(
  174. "21888242871839275222246405745257275088548364400416034343698204186575808495616",
  175. )
  176. .unwrap();
  177. let mut big_arr1: Vec<Fr> = Vec::new();
  178. big_arr1.push(r_1.clone());
  179. let mimc7 = Mimc7::new(91);
  180. let h1 = mimc7.multi_hash(big_arr1, &Fr::zero());
  181. assert_eq!(
  182. h1.to_string(),
  183. "Fr(0x0a4fffe99225f9972ec39fd780dd084f349286c723d4dd42ad05e2e7421fef0e)"
  184. );
  185. }
  186. }