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.

362 lines
9.5 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. extern crate ark_ed_on_bn254;
  2. use ark_ec::ProjectiveCurve;
  3. use ark_ed_on_bn254::{EdwardsProjective, Fr};
  4. use ark_ff::{fields::PrimeField, Field};
  5. use ark_std::{One, UniformRand, Zero};
  6. #[allow(non_snake_case)]
  7. pub struct IPA {
  8. d: u32,
  9. H: EdwardsProjective,
  10. Gs: Vec<EdwardsProjective>,
  11. rng: rand::rngs::ThreadRng,
  12. }
  13. #[allow(non_snake_case)]
  14. pub struct Proof {
  15. a: Fr,
  16. l: Vec<Fr>,
  17. r: Vec<Fr>,
  18. L: Vec<EdwardsProjective>,
  19. R: Vec<EdwardsProjective>,
  20. }
  21. #[allow(non_snake_case)]
  22. #[allow(clippy::many_single_char_names)]
  23. impl IPA {
  24. pub fn new(d: u32) -> IPA {
  25. let mut rng = ark_std::rand::thread_rng();
  26. let mut gs: Vec<EdwardsProjective> = Vec::new();
  27. for _ in 0..d {
  28. gs.push(EdwardsProjective::rand(&mut rng));
  29. }
  30. IPA {
  31. d,
  32. H: EdwardsProjective::rand(&mut rng),
  33. Gs: gs,
  34. rng,
  35. }
  36. }
  37. pub fn commit(&self, a: &[Fr], r: Fr) -> Result<EdwardsProjective, String> {
  38. Ok(inner_product_point(a, &self.Gs)? + self.H.mul(r.into_repr()))
  39. }
  40. pub fn prove(
  41. &mut self,
  42. a: &[Fr],
  43. b: &[Fr],
  44. u: &[Fr],
  45. U: &EdwardsProjective,
  46. ) -> Result<Proof, String> {
  47. let mut a = a.to_owned();
  48. let mut b = b.to_owned();
  49. let mut G = self.Gs.clone();
  50. let k = (f64::from(self.d as u32).log2()) as usize;
  51. let mut l: Vec<Fr> = vec![Fr::zero(); k];
  52. let mut r: Vec<Fr> = vec![Fr::zero(); k];
  53. let mut L: Vec<EdwardsProjective> = vec![EdwardsProjective::zero(); k];
  54. let mut R: Vec<EdwardsProjective> = vec![EdwardsProjective::zero(); k];
  55. for j in (0..k).rev() {
  56. let m = a.len() / 2;
  57. let a_lo = a[..m].to_vec();
  58. let a_hi = a[m..].to_vec();
  59. let b_lo = b[..m].to_vec();
  60. let b_hi = b[m..].to_vec();
  61. let G_lo = G[..m].to_vec();
  62. let G_hi = G[m..].to_vec();
  63. l[j] = Fr::rand(&mut self.rng);
  64. r[j] = Fr::rand(&mut self.rng);
  65. L[j] = inner_product_point(&a_lo, &G_hi)?
  66. + self.H.mul(l[j].into_repr())
  67. + U.mul(inner_product_field(&a_lo, &b_hi)?.into_repr());
  68. R[j] = inner_product_point(&a_hi, &G_lo)?
  69. + self.H.mul(r[j].into_repr())
  70. + U.mul(inner_product_field(&a_hi, &b_lo)?.into_repr());
  71. let uj = u[j];
  72. let uj_inv = u[j].inverse().unwrap();
  73. a = vec_add(
  74. &vec_scalar_mul_field(&a_lo, &uj),
  75. &vec_scalar_mul_field(&a_hi, &uj_inv),
  76. )?;
  77. b = vec_add(
  78. &vec_scalar_mul_field(&b_lo, &uj_inv),
  79. &vec_scalar_mul_field(&b_hi, &uj),
  80. )?;
  81. G = vec_add_point(
  82. &vec_scalar_mul_point(&G_lo, &uj_inv),
  83. &vec_scalar_mul_point(&G_hi, &uj),
  84. )?;
  85. }
  86. if a.len() != 1 {
  87. return Err(format!("a.len() should be 1, a.len()={}", a.len()));
  88. }
  89. if b.len() != 1 {
  90. return Err(format!("b.len() should be 1, b.len()={}", b.len()));
  91. }
  92. if G.len() != 1 {
  93. return Err(format!("G.len() should be 1, G.len()={}", G.len()));
  94. }
  95. Ok(Proof {
  96. a: a[0],
  97. l,
  98. r,
  99. L,
  100. R,
  101. })
  102. }
  103. pub fn verify(
  104. &self,
  105. x: &Fr,
  106. v: &Fr,
  107. P: &EdwardsProjective,
  108. p: &Proof,
  109. r: &Fr,
  110. u: &[Fr],
  111. U: &EdwardsProjective,
  112. ) -> Result<bool, String> {
  113. let P = *P + U.mul(v.into_repr());
  114. let mut q_0 = P;
  115. let mut r = *r;
  116. // compute b & G from s
  117. let s = build_s(u, self.d as usize);
  118. let bs = powers_of(*x, self.d);
  119. let b = inner_product_field(&s, &bs)?;
  120. let G = inner_product_point(&s, &self.Gs)?;
  121. #[allow(clippy::needless_range_loop)]
  122. for j in 0..u.len() {
  123. let uj2 = u[j].square();
  124. let uj_inv2 = u[j].inverse().unwrap().square();
  125. q_0 = q_0 + p.L[j].mul(uj2.into_repr()) + p.R[j].mul(uj_inv2.into_repr());
  126. r = r + p.l[j] * uj2 + p.r[j] * uj_inv2;
  127. }
  128. let q_1 = G.mul(p.a.into_repr()) + self.H.mul(r.into_repr()) + U.mul((p.a * b).into_repr());
  129. Ok(q_0 == q_1)
  130. }
  131. }
  132. // s = (
  133. // u₁⁻¹ u₂⁻¹ … uₖ⁻¹,
  134. // u₁ u₂⁻¹ … uₖ⁻¹,
  135. // u₁⁻¹ u₂ … uₖ⁻¹,
  136. // u₁ u₂ … uₖ⁻¹,
  137. // ⋮ ⋮ ⋮
  138. // u₁ u₂ … uₖ
  139. // )
  140. fn build_s(u: &[Fr], d: usize) -> Vec<Fr> {
  141. let k = (f64::from(d as u32).log2()) as usize;
  142. let mut s: Vec<Fr> = vec![Fr::one(); d];
  143. let mut t = d;
  144. for j in (0..k).rev() {
  145. t /= 2;
  146. let mut c = 0;
  147. #[allow(clippy::needless_range_loop)]
  148. for i in 0..d {
  149. if c < t {
  150. s[i] *= u[j].inverse().unwrap();
  151. } else {
  152. s[i] *= u[j];
  153. }
  154. c += 1;
  155. if c >= t * 2 {
  156. c = 0;
  157. }
  158. }
  159. }
  160. s
  161. }
  162. fn inner_product_field(a: &[Fr], b: &[Fr]) -> Result<Fr, String> {
  163. if a.len() != b.len() {
  164. return Err(format!(
  165. "a.len()={} must be equal to b.len()={}",
  166. a.len(),
  167. b.len()
  168. ));
  169. }
  170. let mut c: Fr = Fr::zero();
  171. for i in 0..a.len() {
  172. c += a[i] * b[i];
  173. }
  174. Ok(c)
  175. }
  176. fn inner_product_point(a: &[Fr], b: &[EdwardsProjective]) -> Result<EdwardsProjective, String> {
  177. if a.len() != b.len() {
  178. return Err(format!(
  179. "a.len()={} must be equal to b.len()={}",
  180. a.len(),
  181. b.len()
  182. ));
  183. }
  184. let mut c: EdwardsProjective = EdwardsProjective::zero();
  185. for i in 0..a.len() {
  186. c += b[i].mul(a[i].into_repr());
  187. }
  188. Ok(c)
  189. }
  190. fn vec_add(a: &[Fr], b: &[Fr]) -> Result<Vec<Fr>, String> {
  191. if a.len() != b.len() {
  192. return Err(format!(
  193. "a.len()={} must be equal to b.len()={}",
  194. a.len(),
  195. b.len()
  196. ));
  197. }
  198. let mut c: Vec<Fr> = vec![Fr::zero(); a.len()];
  199. for i in 0..a.len() {
  200. c[i] = a[i] + b[i];
  201. }
  202. Ok(c)
  203. }
  204. fn vec_add_point(
  205. a: &[EdwardsProjective],
  206. b: &[EdwardsProjective],
  207. ) -> Result<Vec<EdwardsProjective>, String> {
  208. if a.len() != b.len() {
  209. return Err(format!(
  210. "a.len()={} must be equal to b.len()={}",
  211. a.len(),
  212. b.len()
  213. ));
  214. }
  215. let mut c: Vec<EdwardsProjective> = vec![EdwardsProjective::zero(); a.len()];
  216. for i in 0..a.len() {
  217. c[i] = a[i] + b[i];
  218. }
  219. Ok(c)
  220. }
  221. fn vec_scalar_mul_field(a: &[Fr], b: &Fr) -> Vec<Fr> {
  222. let mut c: Vec<Fr> = vec![Fr::zero(); a.len()];
  223. for i in 0..a.len() {
  224. c[i] = a[i] * b;
  225. }
  226. c
  227. }
  228. fn vec_scalar_mul_point(a: &[EdwardsProjective], b: &Fr) -> Vec<EdwardsProjective> {
  229. let mut c: Vec<EdwardsProjective> = vec![EdwardsProjective::zero(); a.len()];
  230. for i in 0..a.len() {
  231. c[i] = a[i].mul(b.into_repr());
  232. }
  233. c
  234. }
  235. fn powers_of(x: Fr, d: u32) -> Vec<Fr> {
  236. let mut c: Vec<Fr> = vec![Fr::zero(); d as usize];
  237. c[0] = x;
  238. for i in 1..d as usize {
  239. c[i] = c[i - 1] * x;
  240. }
  241. c
  242. }
  243. #[cfg(test)]
  244. #[allow(non_snake_case)]
  245. mod tests {
  246. use super::*;
  247. #[test]
  248. fn test_utils() {
  249. let a = vec![
  250. Fr::from(1 as u32),
  251. Fr::from(2 as u32),
  252. Fr::from(3 as u32),
  253. Fr::from(4 as u32),
  254. ];
  255. let b = vec![
  256. Fr::from(1 as u32),
  257. Fr::from(2 as u32),
  258. Fr::from(3 as u32),
  259. Fr::from(4 as u32),
  260. ];
  261. let c = inner_product_field(&a, &b).unwrap();
  262. assert_eq!(c, Fr::from(30 as u32));
  263. }
  264. #[test]
  265. fn test_homomorphic_property() {
  266. let d = 8;
  267. let ipa = IPA::new(d);
  268. let a = vec![
  269. Fr::from(1 as u32),
  270. Fr::from(2 as u32),
  271. Fr::from(3 as u32),
  272. Fr::from(4 as u32),
  273. Fr::from(5 as u32),
  274. Fr::from(6 as u32),
  275. Fr::from(7 as u32),
  276. Fr::from(8 as u32),
  277. ];
  278. let b = a.clone();
  279. let mut rng = ark_std::rand::thread_rng();
  280. let r = Fr::rand(&mut rng);
  281. let s = Fr::rand(&mut rng);
  282. let vc_a = ipa.commit(&a, r).unwrap();
  283. let vc_b = ipa.commit(&b, s).unwrap();
  284. let expected_vc_c = ipa.commit(&vec_add(&a, &b).unwrap(), r + s).unwrap();
  285. let vc_c = vc_a + vc_b;
  286. assert_eq!(vc_c, expected_vc_c);
  287. }
  288. #[test]
  289. fn test_inner_product_argument_proof() {
  290. let d = 8;
  291. let mut ipa = IPA::new(d);
  292. let a = vec![
  293. Fr::from(1 as u32),
  294. Fr::from(2 as u32),
  295. Fr::from(3 as u32),
  296. Fr::from(4 as u32),
  297. Fr::from(5 as u32),
  298. Fr::from(6 as u32),
  299. Fr::from(7 as u32),
  300. Fr::from(8 as u32),
  301. ];
  302. let r = Fr::rand(&mut ipa.rng);
  303. // prover commits
  304. let P = ipa.commit(&a, r).unwrap();
  305. // verifier sets challenges
  306. let U = EdwardsProjective::rand(&mut ipa.rng);
  307. let k = (f64::from(ipa.d as u32).log2()) as usize;
  308. let mut u: Vec<Fr> = vec![Fr::zero(); k];
  309. for j in 0..k {
  310. u[j] = Fr::rand(&mut ipa.rng);
  311. }
  312. let x = Fr::from(3 as u32);
  313. // prover opens at the challenges
  314. let b = powers_of(x, ipa.d);
  315. let v = inner_product_field(&a, &b).unwrap();
  316. let proof = ipa.prove(&a, &b, &u, &U).unwrap();
  317. // verifier
  318. let verif = ipa.verify(&x, &v, &P, &proof, &r, &u, &U).unwrap();
  319. assert!(verif);
  320. }
  321. }