1#![allow(non_snake_case)]
2
3use curv::arithmetic::traits::*;
21use curv::cryptographic_primitives::hashing::{Digest, DigestExt};
22use curv::elliptic::curves::{secp256_k1::Secp256k1, Curve, ECPoint, Point, Scalar};
23use curv::BigInt;
24use sha2::Sha256;
25
26use generic_array::{typenum::Unsigned, GenericArray};
27use itertools::iterate;
28use proofs::inner_product::InnerProductArg;
29use std::ops::{Shl, Shr};
30use Errors::{self, RangeProofError};
31
32#[derive(Clone, Debug, Serialize, Deserialize)]
33pub struct RangeProof {
34 A: Point<Secp256k1>,
35 S: Point<Secp256k1>,
36 T1: Point<Secp256k1>,
37 T2: Point<Secp256k1>,
38 tau_x: Scalar<Secp256k1>,
39 miu: Scalar<Secp256k1>,
40 tx: Scalar<Secp256k1>,
41 inner_product_proof: InnerProductArg,
42}
43
44impl RangeProof {
45 pub fn prove(
46 g_vec: &[Point<Secp256k1>],
47 h_vec: &[Point<Secp256k1>],
48 G: &Point<Secp256k1>,
49 H: &Point<Secp256k1>,
50 mut secret: Vec<Scalar<Secp256k1>>,
51 blinding: &[Scalar<Secp256k1>],
52 bit_length: usize,
53 ) -> RangeProof {
54 let num_of_proofs = secret.len();
55 let nm = num_of_proofs * bit_length;
57 let alpha = Scalar::<Secp256k1>::random();
58 let rho = Scalar::<Secp256k1>::random();
59
60 let g_vec = g_vec.to_vec();
61 let h_vec = h_vec.to_vec();
62
63 let mut A = H * α
64 let mut S = H * ρ
65 let two = BigInt::from(2);
66 let one = BigInt::from(1);
67 let order = Scalar::<Secp256k1>::group_order();
68
69 secret.reverse();
71 let secret_agg = secret
72 .iter()
73 .fold(BigInt::zero(), |acc, x| acc.shl(bit_length) + x.to_bigint());
74
75 let aL = (0..nm)
76 .map(|i| {
77 let shr_secret = secret_agg.clone().shr(i);
78 shr_secret.modulus(&two)
79 })
80 .collect::<Vec<BigInt>>();
81 let aR = (0..nm)
82 .map(|i| BigInt::mod_sub(&aL[i], &one, order))
83 .collect::<Vec<BigInt>>();
84
85 let secret_bits = (0..nm)
86 .map(|i| {
87 let bignum_bit: BigInt = aL[i].clone() & BigInt::one();
88 let byte = BigInt::to_bytes(&bignum_bit);
89 byte[0] == 1
90 })
91 .collect::<Vec<bool>>();
92 let mut index: usize = 0;
93 A = g_vec.iter().zip(secret_bits.clone()).fold(
94 A,
95 |acc, x| {
96 if x.1 {
97 acc + x.0
98 } else {
99 acc
100 }
101 },
102 );
103
104 A = h_vec
105 .iter()
106 .zip(secret_bits)
107 .fold(A, |acc, x| if !x.1 { acc - x.0 } else { acc });
108
109 let SR = (0..nm)
110 .map(|_| Scalar::<Secp256k1>::random())
111 .collect::<Vec<Scalar<Secp256k1>>>();
112 let SL = (0..nm)
113 .map(|_| Scalar::<Secp256k1>::random())
114 .collect::<Vec<Scalar<Secp256k1>>>();
115
116 S = SL.iter().zip(&SR).fold(S, |acc, x| {
117 let g_vec_i_SLi = &g_vec[index] * x.0;
118 let h_vec_i_SRi = &h_vec[index] * x.1;
119 index += 1;
120 let SRhi_plus_SLgi = h_vec_i_SRi + g_vec_i_SLi;
121 acc + SRhi_plus_SLgi
122 });
123
124 let y = Sha256::new().chain_points([&A, &S]).result_scalar();
125 let base_point = Point::<Secp256k1>::generator();
126 let yG: Point<Secp256k1> = base_point * &y;
127 let z: Scalar<Secp256k1> = Sha256::new().chain_points([&yG]).result_scalar();
128 let z_bn = z.to_bigint();
129
130 let one_fe = Scalar::<Secp256k1>::from(&one);
131 let yi = iterate(one_fe.clone(), |i| i.clone() * &y)
132 .take(nm)
133 .collect::<Vec<Scalar<Secp256k1>>>();
134
135 let t2 = (0..nm)
136 .map(|i| SR[i].clone() * &yi[i] * &SL[i])
137 .fold(Scalar::<Secp256k1>::zero(), |acc, x| acc + x);
138 let t2 = t2.to_bigint();
139
140 let two_fe = Scalar::<Secp256k1>::from(&two);
141 let vec_2n = iterate(one_fe, |i| i.clone() * &two_fe)
142 .take(bit_length)
143 .collect::<Vec<Scalar<Secp256k1>>>();
144
145 let t1 = (0..nm)
146 .map(|i| {
147 let t1_1 = BigInt::mod_add(&aR[i], &z_bn, order);
148 let t1_2 = BigInt::mod_mul(&t1_1, &yi[i].to_bigint(), order);
149 let t1_3 = BigInt::mod_mul(&SL[i].to_bigint(), &t1_2, order);
150 let t1_4 = BigInt::mod_sub(&aL[i], &z_bn, order);
151 let t1_5 = BigInt::mod_mul(&SR[i].to_bigint(), &yi[i].to_bigint(), order);
152 let t1_6 = BigInt::mod_mul(&t1_4, &t1_5, order);
153 let j = i / bit_length + 2;
154 let k = i % bit_length;
155 let z_index = BigInt::mod_pow(&z_bn, &BigInt::from(j as u32), order);
156 let two_to_the_i = vec_2n[k].clone().to_bigint();
157 let t1_7 = BigInt::mod_mul(&z_index, &two_to_the_i, order);
158 let t1_8 = BigInt::mod_mul(&t1_7, &SL[i].to_bigint(), order);
159 let t1_68 = BigInt::mod_add(&t1_6, &t1_8, order);
160 BigInt::mod_add(&t1_3, &t1_68, order)
161 })
162 .fold(BigInt::zero(), |acc, x| BigInt::mod_add(&acc, &x, order));
163
164 let tau1 = Scalar::<Secp256k1>::random();
165 let tau2 = Scalar::<Secp256k1>::random();
166 let t1_fe = Scalar::<Secp256k1>::from(&t1);
167 let t2_fe = Scalar::<Secp256k1>::from(&t2);
168 let T1 = G * &t1_fe + H * &tau1;
169 let T2 = G * &t2_fe + H * &tau2;
170
171 let fs_challenge = Sha256::new().chain_points([&T1, &T2, G, H]).result_scalar();
172 let fs_challenge_square = &fs_challenge * &fs_challenge;
173 let taux_1 = &fs_challenge * &tau1;
174 let taux_2 = fs_challenge_square * &tau2;
175 let taux_3 = (0..num_of_proofs)
176 .map(|i| {
177 let j = BigInt::mod_add(&two, &BigInt::from(i as u32), order);
178 let z_j = BigInt::mod_pow(&z_bn, &j, order);
179 let z_j_fe = Scalar::<Secp256k1>::from(&z_j);
180 z_j_fe * &blinding[i]
181 })
182 .fold(taux_2, |acc, x| acc + &x);
183 let tau_x = taux_1 + &taux_3;
184 let miu = (rho * &fs_challenge) + α
185
186 let Lp = (0..nm)
187 .map(|i| {
188 let Lp_1 = (&SL[i] * &fs_challenge).to_bigint();
189 let Lp_2 = BigInt::mod_sub(&aL[i], &z_bn, order);
190 BigInt::mod_add(&Lp_1, &Lp_2, order)
191 })
192 .collect::<Vec<BigInt>>();
193
194 let Rp = (0..nm)
195 .map(|i| {
196 let Rp_1 = (&SR[i] * &fs_challenge).to_bigint();
197
198 let j = i / bit_length + 2;
199 let k = i % bit_length;
200 let z_index = BigInt::mod_pow(&z_bn, &BigInt::from(j as u32), order);
201 let two_to_the_i = vec_2n[k].clone().to_bigint();
202 let Rp_2 = BigInt::mod_mul(&z_index, &two_to_the_i, order);
203 let Rp_3 = BigInt::mod_add(&BigInt::mod_add(&z_bn, &aR[i], order), &Rp_1, order);
204 let Rp_4 = BigInt::mod_mul(&yi[i].to_bigint(), &Rp_3, order);
205 BigInt::mod_add(&Rp_4, &Rp_2, order)
206 })
207 .collect::<Vec<BigInt>>();
208 let tx = Lp.iter().zip(&Rp).fold(BigInt::zero(), |acc, x| {
209 let Lp_iRp_i = BigInt::mod_mul(x.0, x.1, order);
210 BigInt::mod_add(&acc, &Lp_iRp_i, order)
211 });
212 let tx_fe = Scalar::<Secp256k1>::from(&tx);
213
214 let challenge_x: Scalar<Secp256k1> = Sha256::new()
215 .chain_bigint(&tau_x.to_bigint())
216 .chain_bigint(&miu.to_bigint())
217 .chain_bigint(&tx)
218 .result_scalar();
219 let Gx = G * &challenge_x;
220 let P = &Gx * &tx_fe;
222
223 let yi_inv = (0..nm)
224 .map(|i| {
225 yi[i].invert().unwrap()
228 })
229 .collect::<Vec<Scalar<Secp256k1>>>();
230
231 let hi_tag = (0..nm)
232 .map(|i| &h_vec[i] * &yi_inv[i])
233 .collect::<Vec<Point<Secp256k1>>>();
234
235 let P = g_vec.iter().zip(&Lp).fold(P, |acc, x| {
237 let g_vec_i_lp_i = x.0 * &Scalar::<Secp256k1>::from(x.1);
238 acc + g_vec_i_lp_i
239 });
240 let P = hi_tag.iter().zip(&Rp).fold(P, |acc, x| {
242 let h_vec_i_rp_i = x.0 * &Scalar::<Secp256k1>::from(x.1);
243 acc + h_vec_i_rp_i
244 });
245 let L_vec = Vec::with_capacity(nm);
249 let R_vec = Vec::with_capacity(nm);
250 let inner_product_proof =
251 InnerProductArg::prove(&g_vec, &hi_tag, &Gx, &P, &Lp, &Rp, L_vec, R_vec);
252
253 RangeProof {
254 A,
255 S,
256 T1,
257 T2,
258 tau_x,
259 miu,
260 tx: tx_fe,
261 inner_product_proof,
262 }
263 }
264
265 pub fn verify(
266 &self,
267 g_vec: &[Point<Secp256k1>],
268 h_vec: &[Point<Secp256k1>],
269 G: &Point<Secp256k1>,
270 H: &Point<Secp256k1>,
271 ped_com: &[Point<Secp256k1>],
272 bit_length: usize,
273 ) -> Result<(), Errors> {
274 let num_of_proofs = ped_com.len();
275 let nm = num_of_proofs * bit_length;
276
277 let y = Sha256::new()
278 .chain_points([&self.A, &self.S])
279 .result_scalar();
280 let base_point = Point::<Secp256k1>::generator();
281 let yG: Point<Secp256k1> = base_point * &y;
282 let z: Scalar<Secp256k1> = Sha256::new().chain_points([&yG]).result_scalar();
283 let z_bn = z.to_bigint();
284 let order = Scalar::<Secp256k1>::group_order();
285 let z_minus = BigInt::mod_sub(order, &z.to_bigint(), order);
286 let z_minus_fe = Scalar::<Secp256k1>::from(&z_minus);
287 let z_squared = BigInt::mod_pow(&z.to_bigint(), &BigInt::from(2), order);
288 let one_bn = BigInt::one();
290 let one_fe = Scalar::<Secp256k1>::from(&one_bn);
291 let yi = iterate(one_fe.clone(), |i| i.clone() * &y)
292 .take(nm)
293 .collect::<Vec<Scalar<Secp256k1>>>();
294
295 let scalar_mul_yn = yi
296 .iter()
297 .fold(Scalar::<Secp256k1>::zero(), |acc, x| acc + x);
298 let scalar_mul_yn = scalar_mul_yn.to_bigint();
299 let two = BigInt::from(2);
300
301 let two_fe = Scalar::<Secp256k1>::from(&two);
302 let vec_2n = iterate(one_fe, |i| i.clone() * &two_fe)
303 .take(bit_length)
304 .collect::<Vec<Scalar<Secp256k1>>>();
305
306 let scalar_mul_2n = vec_2n
307 .iter()
308 .fold(Scalar::<Secp256k1>::zero(), |acc, x| acc + x);
309 let scalar_mul_2n = scalar_mul_2n.to_bigint();
310
311 let z_cubed_scalar_mul_2n = (0..num_of_proofs)
312 .map(|i| {
313 let j = BigInt::mod_add(&BigInt::from(3), &BigInt::from(i as u32), order);
314 let z_j = BigInt::mod_pow(&z_bn, &j, order);
315 BigInt::mod_mul(&z_j, &scalar_mul_2n, order)
316 })
317 .fold(BigInt::zero(), |acc, x| BigInt::mod_add(&acc, &x, order));
318
319 let z_minus_zsq = BigInt::mod_sub(&z_bn, &z_squared, order);
320 let z_minus_zsq_scalar_mul_yn = BigInt::mod_mul(&z_minus_zsq, &scalar_mul_yn, order);
321 let delta = BigInt::mod_sub(&z_minus_zsq_scalar_mul_yn, &z_cubed_scalar_mul_2n, order);
322
323 let yi_inv = (0..nm)
324 .map(|i| yi[i].invert().unwrap())
325 .collect::<Vec<Scalar<Secp256k1>>>();
326
327 let hi_tag = (0..nm)
328 .map(|i| &h_vec[i] * &yi_inv[i])
329 .collect::<Vec<Point<Secp256k1>>>();
330
331 let fs_challenge = Sha256::new()
332 .chain_points([&self.T1, &self.T2, G, H])
333 .result_scalar();
334 let fs_challenge_square = &fs_challenge * &fs_challenge;
335
336 let Gtx = G * &self.tx;
338 let Htaux = H * &self.tau_x;
339 let left_side = Gtx + Htaux;
340 let delta_fe = Scalar::<Secp256k1>::from(&delta);
341 let Gdelta = G * &delta_fe;
342 let Tx = &self.T1 * &fs_challenge;
343 let Tx_sq = &self.T2 * &fs_challenge_square;
344
345 let mut vec_ped_zm = (0..num_of_proofs)
346 .map(|i| {
347 let z_2_m = BigInt::mod_pow(&z_bn, &BigInt::from((2 + i) as u32), order);
348 let z_2_m_fe = Scalar::<Secp256k1>::from(&z_2_m);
349 &ped_com[i] * &z_2_m_fe
350 })
351 .collect::<Vec<Point<Secp256k1>>>();
352 let vec_ped_zm_1 = vec_ped_zm.remove(0);
353 let ped_com_sum = vec_ped_zm.iter().fold(vec_ped_zm_1, |acc, x| acc + x);
354 let right_side = ped_com_sum + Gdelta + Tx + Tx_sq;
355
356 let challenge_x = Sha256::new()
357 .chain_bigint(&self.tau_x.to_bigint())
358 .chain_bigint(&self.miu.to_bigint())
359 .chain_bigint(&self.tx.to_bigint())
360 .result_scalar();
361 let Gx = G * &challenge_x;
362 let P = &Gx * &self.tx;
365 let minus_miu = BigInt::mod_sub(
366 Scalar::<Secp256k1>::group_order(),
367 &self.miu.to_bigint(),
368 Scalar::<Secp256k1>::group_order(),
369 );
370 let minus_miu_fe = Scalar::<Secp256k1>::from(&minus_miu);
371 let Hmiu = H * &minus_miu_fe;
372 let Sx = &self.S * &fs_challenge;
373 let P = Hmiu + P + self.A.clone() + Sx;
374
375 let P1 = (0..nm)
376 .map(|i| {
377 let z_yn = BigInt::mod_mul(&z_bn, &yi[i].to_bigint(), order);
378 let j = i / bit_length;
379 let k = i % bit_length;
380 let z_j = BigInt::mod_pow(&z_bn, &BigInt::from((2 + j) as u32), order);
381 let z_j_2_n = BigInt::mod_mul(&z_j, &vec_2n[k].to_bigint(), order);
382 let zyn_zsq2n = BigInt::mod_add(&z_yn, &z_j_2_n, order);
384 let zyn_zsq2n_fe = Scalar::<Secp256k1>::from(&zyn_zsq2n);
385 &hi_tag[i] * &zyn_zsq2n_fe
386 })
387 .fold(P, |acc, x| acc + x);
388
389 let P = (0..nm)
390 .map(|i| &g_vec[i] * &z_minus_fe)
391 .fold(P1, |acc, x| acc + x);
392 let verify = self.inner_product_proof.verify(g_vec, &hi_tag, &Gx, &P);
393 if verify.is_ok() && left_side == right_side {
394 Ok(())
395 } else {
396 Err(RangeProofError)
397 }
398 }
399
400 pub fn fast_verify(
401 &self,
402 g_vec: &[Point<Secp256k1>],
403 h_vec: &[Point<Secp256k1>],
404 G: &Point<Secp256k1>,
405 H: &Point<Secp256k1>,
406 ped_com: &[Point<Secp256k1>],
407 bit_length: usize,
408 ) -> Result<(), Errors> {
409 let num_of_proofs = ped_com.len();
410 let nm = num_of_proofs * bit_length;
411
412 let y = Sha256::new()
413 .chain_points([&self.A, &self.S])
414 .result_scalar();
415 let base_point = Point::<Secp256k1>::generator();
416 let yG: Point<Secp256k1> = base_point * &y;
417 let z: Scalar<Secp256k1> = Sha256::new().chain_points([&yG]).result_scalar();
418 let z_bn = z.to_bigint();
419 let order = Scalar::<Secp256k1>::group_order();
420 let z_minus = BigInt::mod_sub(order, &z.to_bigint(), order);
421 let z_minus_fe = Scalar::<Secp256k1>::from(&z_minus);
422 let z_squared = BigInt::mod_pow(&z.to_bigint(), &BigInt::from(2), order);
423 let one_bn = BigInt::one();
425 let one_fe = Scalar::<Secp256k1>::from(&one_bn);
426 let yi = iterate(one_fe.clone(), |i| i.clone() * &y)
427 .take(nm)
428 .collect::<Vec<Scalar<Secp256k1>>>();
429
430 let scalar_mul_yn = yi
431 .iter()
432 .fold(Scalar::<Secp256k1>::zero(), |acc, x| acc + x);
433 let scalar_mul_yn = scalar_mul_yn.to_bigint();
434 let two = BigInt::from(2);
435
436 let two_fe = Scalar::<Secp256k1>::from(&two);
437 let vec_2n = iterate(one_fe, |i| i.clone() * &two_fe)
438 .take(bit_length)
439 .collect::<Vec<Scalar<Secp256k1>>>();
440
441 let scalar_mul_2n = vec_2n
442 .iter()
443 .fold(Scalar::<Secp256k1>::zero(), |acc, x| acc + x);
444 let scalar_mul_2n = scalar_mul_2n.to_bigint();
445
446 let z_cubed_scalar_mul_2n = (0..num_of_proofs)
447 .map(|i| {
448 let j = BigInt::mod_add(&BigInt::from(3), &BigInt::from(i as u32), order);
449 let z_j = BigInt::mod_pow(&z_bn, &j, order);
450 BigInt::mod_mul(&z_j, &scalar_mul_2n, order)
451 })
452 .fold(BigInt::zero(), |acc, x| BigInt::mod_add(&acc, &x, order));
453
454 let z_minus_zsq = BigInt::mod_sub(&z_bn, &z_squared, order);
455 let z_minus_zsq_scalar_mul_yn = BigInt::mod_mul(&z_minus_zsq, &scalar_mul_yn, order);
456 let delta = BigInt::mod_sub(&z_minus_zsq_scalar_mul_yn, &z_cubed_scalar_mul_2n, order);
457
458 let yi_inv = (0..nm)
459 .map(|i| yi[i].invert().unwrap())
460 .collect::<Vec<Scalar<Secp256k1>>>();
461
462 let hi_tag = (0..nm)
463 .map(|i| &h_vec[i] * &yi_inv[i])
464 .collect::<Vec<Point<Secp256k1>>>();
465
466 let fs_challenge = Sha256::new()
467 .chain_points([&self.T1, &self.T2, G, H])
468 .result_scalar();
469 let fs_challenge_square = &fs_challenge * &fs_challenge;
470
471 let Gtx = G * &self.tx;
473 let Htaux = H * &self.tau_x;
474 let left_side = Gtx + Htaux;
475 let delta_fe = Scalar::<Secp256k1>::from(&delta);
476 let Gdelta = G * &delta_fe;
477 let Tx = &self.T1 * &fs_challenge;
478 let Tx_sq = &self.T2 * &fs_challenge_square;
479
480 let mut vec_ped_zm = (0..num_of_proofs)
481 .map(|i| {
482 let z_2_m = BigInt::mod_pow(&z_bn, &BigInt::from((2 + i) as u32), order);
483 let z_2_m_fe = Scalar::<Secp256k1>::from(&z_2_m);
484 &ped_com[i] * &z_2_m_fe
485 })
486 .collect::<Vec<Point<Secp256k1>>>();
487 let vec_ped_zm_1 = vec_ped_zm.remove(0);
488 let ped_com_sum = vec_ped_zm.iter().fold(vec_ped_zm_1, |acc, x| acc + x);
489 let right_side = ped_com_sum + Gdelta + Tx + Tx_sq;
490
491 let challenge_x = Sha256::new()
492 .chain_bigint(&self.tau_x.to_bigint())
493 .chain_bigint(&self.miu.to_bigint())
494 .chain_bigint(&self.tx.to_bigint())
495 .result_scalar();
496 let Gx = G * &challenge_x;
497 let P = &Gx * &self.tx;
500 let minus_miu = BigInt::mod_sub(
501 Scalar::<Secp256k1>::group_order(),
502 &self.miu.to_bigint(),
503 Scalar::<Secp256k1>::group_order(),
504 );
505 let minus_miu_fe = Scalar::<Secp256k1>::from(&minus_miu);
506 let Hmiu = H * &minus_miu_fe;
507 let Sx = &self.S * &fs_challenge;
508 let P = Hmiu + P + self.A.clone() + Sx;
509
510 let P1 = (0..nm)
511 .map(|i| {
512 let z_yn = BigInt::mod_mul(&z_bn, &yi[i].to_bigint(), order);
513 let j = i / bit_length;
514 let k = i % bit_length;
515 let z_j = BigInt::mod_pow(&z_bn, &BigInt::from((2 + j) as u32), order);
516 let z_j_2_n = BigInt::mod_mul(&z_j, &vec_2n[k].to_bigint(), order);
517 let zyn_zsq2n = BigInt::mod_add(&z_yn, &z_j_2_n, order);
519 let zyn_zsq2n_fe = Scalar::<Secp256k1>::from(&zyn_zsq2n);
520 &hi_tag[i] * &zyn_zsq2n_fe
521 })
522 .fold(P, |acc, x| acc + x);
523
524 let P = (0..nm)
525 .map(|i| &g_vec[i] * &z_minus_fe)
526 .fold(P1, |acc, x| acc + x);
527 let verify = self
528 .inner_product_proof
529 .fast_verify(g_vec, &hi_tag, &Gx, &P);
530 if verify.is_ok() && left_side == right_side {
531 Ok(())
532 } else {
533 Err(RangeProofError)
534 }
535 }
536
537 pub fn aggregated_verify(
538 &self,
539 g_vec: &[Point<Secp256k1>],
540 h_vec: &[Point<Secp256k1>],
541 G: &Point<Secp256k1>,
542 H: &Point<Secp256k1>,
543 ped_com: &[Point<Secp256k1>],
544 bit_length: usize,
545 ) -> Result<(), Errors> {
546 let n = bit_length;
547 let m = ped_com.len();
548 let nm = m * n;
549 let lg_nm = self.inner_product_proof.L.len();
550 let order = Scalar::<Secp256k1>::group_order();
551 let two = BigInt::from(2);
552 let one = BigInt::from(1);
553 let zero = BigInt::zero();
554
555 assert_eq!(g_vec.len(), nm);
557 assert_eq!(h_vec.len(), nm);
558 assert!(nm.is_power_of_two(), "(n*m) must be a power of two!");
559 assert!(
560 lg_nm <= 64,
561 "Not compatible for vector sizes greater than 2^64!"
562 );
563
564 let y = Sha256::new()
566 .chain_points([&self.A, &self.S])
567 .result_scalar();
568 let y_bn = y.to_bigint();
569 let y_inv_bn = BigInt::mod_inv(&y_bn, order).unwrap();
570 let base_point = Point::<Secp256k1>::generator();
571 let yG: Point<Secp256k1> = base_point * &y;
572 let z: Scalar<Secp256k1> = Sha256::new().chain_points([&yG]).result_scalar();
573 let z_bn = z.to_bigint();
574 let z_squared = BigInt::mod_pow(&z_bn, &BigInt::from(2), order);
575
576 let challenge_x: Scalar<Secp256k1> = Sha256::new()
577 .chain_points([&self.T1, &self.T2, G, H])
578 .result_scalar();
579 let challenge_x_sq = &challenge_x * &challenge_x;
580
581 let x_u_fe = Sha256::new()
582 .chain_bigint(&self.tau_x.to_bigint())
583 .chain_bigint(&self.miu.to_bigint())
584 .chain_bigint(&self.tx.to_bigint())
585 .result_scalar();
586
587 let ux = G * &x_u_fe;
589
590 let challenge_ver: Scalar<Secp256k1> = Sha256::new()
592 .chain_points([&self.A, &self.S, &self.T1, &self.T2, G, H])
593 .result_scalar();
594 let challenge_ver_bn = challenge_ver.to_bigint();
595
596 let z2_vec = iterate(z_squared.clone(), |i| i.clone() * &z_bn)
598 .take(m)
599 .collect::<Vec<BigInt>>();
600
601 let y_vec = iterate(one.clone(), |i| i.clone() * &y_bn)
603 .take(nm)
604 .collect::<Vec<BigInt>>();
605
606 let sum_y_pow = y_vec
608 .iter()
609 .fold(zero.clone(), |acc, x| BigInt::mod_add(&acc, x, order));
610
611 let vec_2n = iterate(one.clone(), |i| i.clone() * &two)
613 .take(n)
614 .collect::<Vec<BigInt>>();
615
616 let y_inv_vec = iterate(one, |i| i.clone() * &y_inv_bn)
618 .take(nm)
619 .collect::<Vec<BigInt>>();
620
621 let d = (0..nm)
624 .map(|i| {
625 let k = i % n;
626 let two_i = vec_2n[k].clone();
627 let j = i / n;
628 let z_j_2 = z2_vec[j].clone();
629 BigInt::mod_mul(&two_i, &z_j_2, order)
630 })
631 .collect::<Vec<BigInt>>();
632
633 let sum_d = d
635 .iter()
636 .fold(zero.clone(), |acc, x| BigInt::mod_add(&acc, x, order));
637
638 let z_minus_zsq = BigInt::mod_sub(&z_bn, &z_squared, order);
640 let z_minus_zsq_sum_y = BigInt::mod_mul(&z_minus_zsq, &sum_y_pow, order);
641 let sum_d_z = BigInt::mod_mul(&sum_d, &z_bn, order);
642 let delta = BigInt::mod_sub(&z_minus_zsq_sum_y, &sum_d_z, order);
643
644 let mut x_sq_vec: Vec<BigInt> = Vec::with_capacity(lg_nm);
646 let mut x_inv_sq_vec: Vec<BigInt> = Vec::with_capacity(lg_nm);
647 let mut minus_x_sq_vec: Vec<BigInt> = Vec::with_capacity(lg_nm);
648 let mut minus_x_inv_sq_vec: Vec<BigInt> = Vec::with_capacity(lg_nm);
649 let mut allinv = BigInt::one();
650 for (Li, Ri) in self
651 .inner_product_proof
652 .L
653 .iter()
654 .zip(self.inner_product_proof.R.iter())
655 {
656 let x: Scalar<Secp256k1> = Sha256::new().chain_points([Li, Ri, &ux]).result_scalar();
657 let x_bn = x.to_bigint();
658 let x_inv_fe = x.invert().unwrap();
659 let x_inv_bn = x_inv_fe.to_bigint();
660 let x_sq_bn = BigInt::mod_mul(&x_bn, &x_bn, order);
661 let x_inv_sq_bn = BigInt::mod_mul(&x_inv_fe.to_bigint(), &x_inv_fe.to_bigint(), order);
662
663 x_sq_vec.push(x_sq_bn.clone());
664 x_inv_sq_vec.push(x_inv_sq_bn.clone());
665 minus_x_sq_vec.push(BigInt::mod_sub(&BigInt::zero(), &x_sq_bn, order));
666 minus_x_inv_sq_vec.push(BigInt::mod_sub(&BigInt::zero(), &x_inv_sq_bn, order));
667 allinv *= x_inv_bn;
668 }
669
670 let mut s: Vec<BigInt> = Vec::with_capacity(nm);
671 s.push(allinv);
672 for i in 1..nm {
673 let lg_i =
674 (std::mem::size_of_val(&nm) * 8) - 1 - ((i as usize).leading_zeros() as usize);
675 let k = 1 << lg_i;
676 let x_lg_i_sq = x_sq_vec[(lg_nm - 1) - lg_i].clone();
679 s.push(s[i - k].clone() * x_lg_i_sq);
680 }
681
682 let a_times_s: Vec<BigInt> = (0..nm)
683 .map(|i| BigInt::mod_mul(&s[i], &self.inner_product_proof.a_tag, order))
684 .collect();
685
686 let b_times_sinv: Vec<BigInt> = (0..nm)
687 .map(|i| {
688 let s_inv_i = BigInt::mod_inv(&s[i], order).unwrap();
689 BigInt::mod_mul(&s_inv_i, &self.inner_product_proof.b_tag, order)
690 })
691 .collect();
692
693 let scalar_g_vec: Vec<BigInt> = (0..nm)
695 .map(|i| BigInt::mod_add(&a_times_s[i], &z_bn, order))
696 .collect();
697
698 let scalar_h_vec: Vec<BigInt> = (0..nm)
700 .map(|i| {
701 let b_sinv_plus_di = BigInt::mod_sub(&b_times_sinv[i], &d[i], order);
702 let y_inv_b_sinv_plus_di = BigInt::mod_mul(&y_inv_vec[i], &b_sinv_plus_di, order);
703 BigInt::mod_sub(&y_inv_b_sinv_plus_di, &z_bn, order)
704 })
705 .collect();
706
707 let ab = BigInt::mod_mul(
709 &self.inner_product_proof.a_tag,
710 &self.inner_product_proof.b_tag,
711 order,
712 );
713 let ab_minus_tx = BigInt::mod_sub(&ab, &self.tx.to_bigint(), order);
714 let scalar_G1 = BigInt::mod_mul(&x_u_fe.to_bigint(), &ab_minus_tx, order);
715
716 let delta_minus_tx = BigInt::mod_sub(&delta, &self.tx.to_bigint(), order);
717 let scalar_G2 = BigInt::mod_mul(&challenge_ver_bn, &delta_minus_tx, order);
718
719 let scalar_G = BigInt::mod_add(&scalar_G1, &scalar_G2, order);
720
721 let c_times_taux = BigInt::mod_mul(&challenge_ver_bn, &self.tau_x.to_bigint(), order);
723 let scalar_H = BigInt::mod_sub(&self.miu.to_bigint(), &c_times_taux, order);
724
725 let scalar_S = BigInt::mod_sub(&zero, &challenge_x.to_bigint(), order);
728
729 let scalar_L = minus_x_sq_vec.clone();
731 let scalar_R = minus_x_inv_sq_vec.clone();
732
733 let scalar_coms: Vec<BigInt> = (0..m)
735 .map(|i| BigInt::mod_mul(&challenge_ver_bn, &z2_vec[i], order))
736 .collect();
737
738 let scalar_T1 = BigInt::mod_mul(&challenge_ver_bn, &challenge_x.to_bigint(), order);
740 let scalar_T2 = BigInt::mod_mul(&challenge_ver_bn, &challenge_x_sq.to_bigint(), order);
741
742 let mut scalars: Vec<BigInt> = Vec::with_capacity(2 * nm + 2 * lg_nm + m + 6);
744 scalars.extend_from_slice(&scalar_g_vec);
745 scalars.extend_from_slice(&scalar_h_vec);
746 scalars.push(scalar_G);
747 scalars.push(scalar_S);
750 scalars.extend_from_slice(&scalar_L);
751 scalars.extend_from_slice(&scalar_R);
752 scalars.extend_from_slice(&scalar_coms);
753 scalars.push(scalar_T1);
754 scalars.push(scalar_T2);
755
756 let mut points: Vec<Point<Secp256k1>> = Vec::with_capacity(2 * nm + 2 * lg_nm + m + 6);
758 points.extend_from_slice(g_vec);
759 points.extend_from_slice(h_vec);
760 points.push(G.clone());
761 points.push(self.S.clone());
764 points.extend_from_slice(&self.inner_product_proof.L);
765 points.extend_from_slice(&self.inner_product_proof.R);
766 points.extend_from_slice(ped_com);
767 points.push(self.T1.clone());
768 points.push(self.T2.clone());
769
770 let H_times_scalar_H = H * &Scalar::<Secp256k1>::from(&scalar_H);
771 let tot_len = points.len();
772 let lhs = (0..tot_len)
773 .map(|i| &points[i] * &Scalar::<Secp256k1>::from(&scalars[i]))
774 .fold(H_times_scalar_H, |acc, x| acc + x as Point<Secp256k1>);
775
776 if lhs == self.A {
778 Ok(())
779 } else {
780 Err(RangeProofError)
781 }
782 }
783}
784
785pub fn generate_random_point(bytes: &[u8]) -> Point<Secp256k1> {
786 let compressed_point_len =
787 <<Secp256k1 as Curve>::Point as ECPoint>::CompressedPointLength::USIZE;
788 let truncated = if bytes.len() > compressed_point_len - 1 {
789 &bytes[0..compressed_point_len - 1]
790 } else {
791 &bytes
792 };
793 let mut buffer = GenericArray::<
794 u8,
795 <<Secp256k1 as Curve>::Point as ECPoint>::CompressedPointLength,
796 >::default();
797 buffer.as_mut_slice()[0] = 0x2;
798 buffer.as_mut_slice()[1..1 + truncated.len()].copy_from_slice(truncated);
799 if let Ok(point) = Point::from_bytes(buffer.as_slice()) {
800 return point;
801 }
802
803 let bn = BigInt::from_bytes(bytes);
804 let two = BigInt::from(2);
805 let bn_times_two = BigInt::mod_mul(&bn, &two, Scalar::<Secp256k1>::group_order());
806 let bytes = BigInt::to_bytes(&bn_times_two);
807 generate_random_point(&bytes)
808}
809
810#[cfg(test)]
811mod tests {
812 use curv::arithmetic::traits::*;
813 use curv::cryptographic_primitives::hashing::{Digest, DigestExt};
814 use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar};
815 use curv::BigInt;
816 use sha2::Sha512;
817
818 use curv::elliptic::curves::secp256_k1::hash_to_curve::generate_random_point;
819 use proofs::range_proof::RangeProof;
820
821 pub fn test_helper(seed: &BigInt, n: usize, m: usize) {
822 let nm = n * m;
823 let G = Point::<Secp256k1>::generator();
824 let label = BigInt::from(1);
825 let hash = Sha512::new().chain_bigint(&label).result_bigint();
826 let H = generate_random_point(&Converter::to_bytes(&hash));
827
828 let g_vec = (0..nm)
829 .map(|i| {
830 let kzen_label_i = BigInt::from(i as u32) + seed;
831 let hash_i = Sha512::new().chain_bigint(&kzen_label_i).result_bigint();
832 generate_random_point(&Converter::to_bytes(&hash_i))
833 })
834 .collect::<Vec<Point<Secp256k1>>>();
835
836 let h_vec = (0..nm)
838 .map(|i| {
839 let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + seed;
840 let hash_j = Sha512::new().chain_bigint(&kzen_label_j).result_bigint();
841 generate_random_point(&Converter::to_bytes(&hash_j))
842 })
843 .collect::<Vec<Point<Secp256k1>>>();
844
845 let range = BigInt::from(2).pow(n as u32);
846 let v_vec = (0..m)
847 .map(|_| Scalar::<Secp256k1>::from(&BigInt::sample_below(&range)))
848 .collect::<Vec<Scalar<Secp256k1>>>();
849
850 let r_vec = (0..m)
851 .map(|_| Scalar::<Secp256k1>::random())
852 .collect::<Vec<Scalar<Secp256k1>>>();
853
854 let ped_com_vec = (0..m)
855 .map(|i| &*G * &v_vec[i] + &H * &r_vec[i])
856 .collect::<Vec<Point<Secp256k1>>>();
857
858 let range_proof = RangeProof::prove(&g_vec, &h_vec, &G, &H, v_vec, &r_vec, n);
859 let result = RangeProof::verify(&range_proof, &g_vec, &h_vec, &G, &H, &ped_com_vec, n);
860 assert!(result.is_ok());
861 }
862
863 pub fn test_helper_aggregated(seed: &BigInt, n: usize, m: usize) {
864 let nm = n * m;
865 let G = Point::<Secp256k1>::generator();
866 let label = BigInt::from(1);
867 let hash = Sha512::new().chain_bigint(&label).result_bigint();
868 let H = generate_random_point(&Converter::to_bytes(&hash));
869
870 let g_vec = (0..nm)
871 .map(|i| {
872 let kzen_label_i = BigInt::from(i as u32) + seed;
873 let hash_i = Sha512::new().chain_bigint(&kzen_label_i).result_bigint();
874 generate_random_point(&Converter::to_bytes(&hash_i))
875 })
876 .collect::<Vec<Point<Secp256k1>>>();
877
878 let h_vec = (0..nm)
880 .map(|i| {
881 let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + seed;
882 let hash_j = Sha512::new().chain_bigint(&kzen_label_j).result_bigint();
883 generate_random_point(&Converter::to_bytes(&hash_j))
884 })
885 .collect::<Vec<Point<Secp256k1>>>();
886
887 let range = BigInt::from(2).pow(n as u32);
888 let v_vec = (0..m)
889 .map(|_| Scalar::<Secp256k1>::from(&BigInt::sample_below(&range)))
890 .collect::<Vec<Scalar<Secp256k1>>>();
891
892 let r_vec = (0..m)
893 .map(|_| Scalar::<Secp256k1>::random())
894 .collect::<Vec<Scalar<Secp256k1>>>();
895
896 let ped_com_vec = (0..m)
897 .map(|i| &*G * &v_vec[i] + &H * &r_vec[i])
898 .collect::<Vec<Point<Secp256k1>>>();
899
900 let range_proof = RangeProof::prove(&g_vec, &h_vec, &G, &H, v_vec, &r_vec, n);
901 let result =
902 RangeProof::aggregated_verify(&range_proof, &g_vec, &h_vec, &G, &H, &ped_com_vec, n);
903 assert!(result.is_ok());
904 }
905
906 #[test]
907 pub fn test_batch_4_range_proof_32() {
908 let n = 32;
909 let m = 4;
911 let nm = n * m;
912 let KZen: &[u8] = &[75, 90, 101, 110];
913 let kzen_label = BigInt::from_bytes(KZen);
914
915 let G = Point::<Secp256k1>::generator();
916 let label = BigInt::from(1);
917 let hash = Sha512::new().chain_bigint(&label).result_bigint();
918 let H = generate_random_point(&Converter::to_bytes(&hash));
919
920 let g_vec = (0..nm)
921 .map(|i| {
922 let kzen_label_i = BigInt::from(i as u32) + &kzen_label;
923 let hash_i = Sha512::new().chain_bigint(&kzen_label_i).result_bigint();
924 generate_random_point(&Converter::to_bytes(&hash_i))
925 })
926 .collect::<Vec<Point<Secp256k1>>>();
927
928 let h_vec = (0..nm)
930 .map(|i| {
931 let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + &kzen_label;
932 let hash_j = Sha512::new().chain_bigint(&kzen_label_j).result_bigint();
933 generate_random_point(&Converter::to_bytes(&hash_j))
934 })
935 .collect::<Vec<Point<Secp256k1>>>();
936
937 let range = BigInt::from(2).pow(n as u32);
938 let v_vec = (0..m)
939 .map(|_| Scalar::<Secp256k1>::from(&BigInt::sample_below(&range)))
940 .collect::<Vec<Scalar<Secp256k1>>>();
941
942 let r_vec = (0..m)
943 .map(|_| Scalar::<Secp256k1>::random())
944 .collect::<Vec<Scalar<Secp256k1>>>();
945
946 let ped_com_vec = (0..m)
947 .map(|i| &*G * &v_vec[i] + &H * &r_vec[i])
948 .collect::<Vec<Point<Secp256k1>>>();
949
950 let range_proof = RangeProof::prove(&g_vec, &h_vec, &G, &H, v_vec, &r_vec, n);
951 let result = RangeProof::verify(&range_proof, &g_vec, &h_vec, &G, &H, &ped_com_vec, n);
952 assert!(result.is_ok());
953 }
954
955 #[test]
956 #[should_panic]
957 pub fn test_batch_4_range_proof_32_out_of_range() {
958 let n = 32;
959 let m = 4;
961 let nm = n * m;
962 let KZen: &[u8] = &[75, 90, 101, 110];
963 let kzen_label = BigInt::from_bytes(KZen);
964
965 let G = Point::<Secp256k1>::generator();
966 let label = BigInt::from(1);
967 let hash = Sha512::new().chain_bigint(&label).result_bigint();
968 let H = generate_random_point(&Converter::to_bytes(&hash));
969
970 let g_vec = (0..nm)
971 .map(|i| {
972 let kzen_label_i = BigInt::from(i as u32) + &kzen_label;
973 let hash_i = Sha512::new().chain_bigint(&kzen_label_i).result_bigint();
974 generate_random_point(&Converter::to_bytes(&hash_i))
975 })
976 .collect::<Vec<Point<Secp256k1>>>();
977
978 let h_vec = (0..nm)
980 .map(|i| {
981 let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + &kzen_label;
982 let hash_j = Sha512::new().chain_bigint(&kzen_label_j).result_bigint();
983 generate_random_point(&Converter::to_bytes(&hash_j))
984 })
985 .collect::<Vec<Point<Secp256k1>>>();
986
987 let range = BigInt::from(2).pow(n as u32);
988 let mut v_vec = (0..m - 1)
989 .map(|_| Scalar::<Secp256k1>::from(&BigInt::sample_below(&range)))
990 .collect::<Vec<Scalar<Secp256k1>>>();
991
992 let bad_v = BigInt::from(2).pow(33);
993 v_vec.push(Scalar::<Secp256k1>::from(&bad_v));
994
995 let r_vec = (0..m)
996 .map(|_| Scalar::<Secp256k1>::random())
997 .collect::<Vec<Scalar<Secp256k1>>>();
998
999 let ped_com_vec = (0..m)
1000 .map(|i| &*G * &v_vec[i] + &H * &r_vec[i])
1001 .collect::<Vec<Point<Secp256k1>>>();
1002
1003 let range_proof = RangeProof::prove(&g_vec, &h_vec, &G, &H, v_vec, &r_vec, n);
1004 let result = RangeProof::verify(&range_proof, &g_vec, &h_vec, &G, &H, &ped_com_vec, n);
1005 assert!(result.is_ok());
1006 }
1007
1008 #[test]
1009 pub fn test_batch_2_range_proof_16() {
1010 let n = 16;
1011 let m = 2;
1013 let nm = n * m;
1014 let KZen: &[u8] = &[75, 90, 101, 110];
1015 let kzen_label = BigInt::from_bytes(KZen);
1016
1017 let G = Point::<Secp256k1>::generator();
1018 let label = BigInt::from(1);
1019 let hash = Sha512::new().chain_bigint(&label).result_bigint();
1020 let H = generate_random_point(&Converter::to_bytes(&hash));
1021
1022 let g_vec = (0..nm)
1023 .map(|i| {
1024 let kzen_label_i = BigInt::from(i as u32) + &kzen_label;
1025 let hash_i = Sha512::new().chain_bigint(&kzen_label_i).result_bigint();
1026 generate_random_point(&Converter::to_bytes(&hash_i))
1027 })
1028 .collect::<Vec<Point<Secp256k1>>>();
1029
1030 let h_vec = (0..nm)
1032 .map(|i| {
1033 let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + &kzen_label;
1034 let hash_j = Sha512::new().chain_bigint(&kzen_label_j).result_bigint();
1035 generate_random_point(&Converter::to_bytes(&hash_j))
1036 })
1037 .collect::<Vec<Point<Secp256k1>>>();
1038
1039 let range = BigInt::from(2).pow(n as u32);
1040 let v_vec = (0..m)
1041 .map(|_| Scalar::<Secp256k1>::from(&BigInt::sample_below(&range)))
1042 .collect::<Vec<Scalar<Secp256k1>>>();
1043
1044 let r_vec = (0..m)
1045 .map(|_| Scalar::<Secp256k1>::random())
1046 .collect::<Vec<Scalar<Secp256k1>>>();
1047
1048 let ped_com_vec = (0..m)
1049 .map(|i| &*G * &v_vec[i] + &H * &r_vec[i])
1050 .collect::<Vec<Point<Secp256k1>>>();
1051
1052 let range_proof = RangeProof::prove(&g_vec, &h_vec, &G, &H, v_vec, &r_vec, n);
1053 let result = RangeProof::verify(&range_proof, &g_vec, &h_vec, &G, &H, &ped_com_vec, n);
1054 assert!(result.is_ok());
1055 }
1056
1057 #[test]
1058 pub fn test_batch_1_range_proof_8() {
1059 let n = 8;
1061 let m = 1;
1063 let nm = n * m;
1064 let KZen: &[u8] = &[75, 90, 101, 110];
1066 let kzen_label = BigInt::from_bytes(KZen);
1067
1068 let G = Point::<Secp256k1>::generator();
1070 let label = BigInt::from(1);
1071 let hash = Sha512::new().chain_bigint(&label).result_bigint();
1072 let H = generate_random_point(&Converter::to_bytes(&hash));
1073
1074 let g_vec = (0..nm)
1075 .map(|i| {
1076 let kzen_label_i = BigInt::from(i as u32) + &kzen_label;
1077 let hash_i = Sha512::new().chain_bigint(&kzen_label_i).result_bigint();
1078 generate_random_point(&Converter::to_bytes(&hash_i))
1079 })
1080 .collect::<Vec<Point<Secp256k1>>>();
1081
1082 let h_vec = (0..nm)
1084 .map(|i| {
1085 let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + &kzen_label;
1086 let hash_j = Sha512::new().chain_bigint(&kzen_label_j).result_bigint();
1087 generate_random_point(&Converter::to_bytes(&hash_j))
1088 })
1089 .collect::<Vec<Point<Secp256k1>>>();
1090
1091 let range = BigInt::from(2).pow(n as u32);
1092 let v_vec = (0..m)
1093 .map(|_| Scalar::<Secp256k1>::from(&BigInt::sample_below(&range)))
1094 .collect::<Vec<Scalar<Secp256k1>>>();
1095
1096 let r_vec = (0..m)
1097 .map(|_| Scalar::<Secp256k1>::random())
1098 .collect::<Vec<Scalar<Secp256k1>>>();
1099
1100 let ped_com_vec = (0..m)
1101 .map(|i| &*G * &v_vec[i] + &H * &r_vec[i])
1102 .collect::<Vec<Point<Secp256k1>>>();
1103
1104 let range_proof = RangeProof::prove(&g_vec, &h_vec, &G, &H, v_vec, &r_vec, n);
1105 let result = RangeProof::verify(&range_proof, &g_vec, &h_vec, &G, &H, &ped_com_vec, n);
1106 assert!(result.is_ok());
1107 }
1108
1109 #[test]
1110 pub fn test_batch_4_range_proof_64() {
1111 let KZen: &[u8] = &[75, 90, 101, 110];
1112 let kzen_label = BigInt::from_bytes(KZen);
1113 test_helper(&kzen_label, 64, 4);
1114 }
1115
1116 #[test]
1117 pub fn test_agg_batch_4_range_proof_64() {
1118 let KZen: &[u8] = &[75, 90, 101, 110];
1119 let kzen_label = BigInt::from_bytes(KZen);
1120 test_helper_aggregated(&kzen_label, 64, 4);
1121 }
1122}