1#![allow(non_snake_case)]
2use ark_bls12_381::{Fr, G1Affine, G1Projective};
3use ark_ec::AffineCurve;
4use ark_ec::ProjectiveCurve;
5use ark_ff::PrimeField;
6use ark_ff::{batch_inversion, Field, One};
7use ark_std::rand::RngCore;
8
9use crate::transcript::CurdleproofsTranscript;
10use merlin::Transcript;
11
12use crate::errors::ProofError;
13use crate::msm_accumulator::MsmAccumulator;
14use crate::util::{
15 generate_blinders, get_verification_scalars_bitstring, msm, msm_from_projective,
16};
17
18#[derive(Clone, Debug)]
20pub struct SameMultiscalarProof {
21 B_a: G1Projective,
22 B_t: G1Projective,
23 B_u: G1Projective,
24
25 vec_L_A: Vec<G1Projective>,
26 vec_L_T: Vec<G1Projective>,
27 vec_L_U: Vec<G1Projective>,
28 vec_R_A: Vec<G1Projective>,
29 vec_R_T: Vec<G1Projective>,
30 vec_R_U: Vec<G1Projective>,
31
32 x_final: Fr,
33}
34
35impl SameMultiscalarProof {
36 pub fn new<T: RngCore>(
48 mut crs_G_vec: Vec<G1Affine>,
49
50 A: G1Projective,
51 Z_t: G1Projective,
52 Z_u: G1Projective,
53 mut vec_T: Vec<G1Affine>,
54 mut vec_U: Vec<G1Affine>,
55
56 mut vec_x: Vec<Fr>,
57
58 transcript: &mut Transcript,
59 rng: &mut T,
60 ) -> SameMultiscalarProof {
61 let mut n = vec_x.len();
62 let lg_n = ark_std::log2(n) as usize;
63
64 let mut vec_L_T = Vec::with_capacity(lg_n);
65 let mut vec_R_T = Vec::with_capacity(lg_n);
66 let mut vec_L_U = Vec::with_capacity(lg_n);
67 let mut vec_R_U = Vec::with_capacity(lg_n);
68 let mut vec_L_A = Vec::with_capacity(lg_n);
69 let mut vec_R_A = Vec::with_capacity(lg_n);
70
71 let vec_r: Vec<Fr> = generate_blinders(rng, n);
72
73 let B_a = msm(&crs_G_vec, &vec_r);
74 let B_t = msm(&vec_T, &vec_r);
75 let B_u = msm(&vec_U, &vec_r);
76
77 transcript.append_list(b"same_msm_step1", &[&A, &Z_t, &Z_u]);
78 transcript.append_list(b"same_msm_step1", &[&vec_T, &vec_U]);
79 transcript.append_list(b"same_msm_step1", &[&B_a, &B_t, &B_u]);
80 let alpha = transcript.get_and_append_challenge(b"same_msm_alpha");
81
82 for i in 0..n {
83 vec_x[i] = vec_r[i] + (alpha * vec_x[i]);
84 }
85
86 let mut slice_x = &mut vec_x[..];
87 let mut slice_T = &mut vec_T[..];
88 let mut slice_U = &mut vec_U[..];
89 let mut slice_G = &mut crs_G_vec[..];
90
91 while slice_x.len() > 1 {
93 n /= 2;
94
95 let (x_L, x_R) = slice_x.split_at_mut(n);
96 let (T_L, T_R) = slice_T.split_at_mut(n);
97 let (U_L, U_R) = slice_U.split_at_mut(n);
98 let (G_L, G_R) = slice_G.split_at_mut(n);
99
100 let L_A = msm(G_R, x_L);
101 let L_T = msm(T_R, x_L);
102 let L_U = msm(U_R, x_L);
103 let R_A = msm(G_L, x_R);
104 let R_T = msm(T_L, x_R);
105 let R_U = msm(U_L, x_R);
106
107 vec_L_A.push(L_A);
108 vec_L_T.push(L_T);
109 vec_L_U.push(L_U);
110 vec_R_A.push(R_A);
111 vec_R_T.push(R_T);
112 vec_R_U.push(R_U);
113
114 transcript.append_list(b"same_msm_loop", &[&L_A, &L_T, &L_U, &R_A, &R_T, &R_U]);
115 let gamma = transcript.get_and_append_challenge(b"same_msm_gamma");
116 let gamma_inv = gamma.inverse().expect("gamma must have an inverse");
117
118 for i in 0..n {
120 x_L[i] += gamma_inv * x_R[i];
121 T_L[i] = T_L[i] + T_R[i].mul(gamma.into_repr()).into_affine();
122 U_L[i] = U_L[i] + U_R[i].mul(gamma.into_repr()).into_affine();
123 G_L[i] = G_L[i] + G_R[i].mul(gamma.into_repr()).into_affine();
124 }
125 slice_x = x_L;
126 slice_T = T_L;
127 slice_U = U_L;
128 slice_G = G_L;
129 }
130
131 SameMultiscalarProof {
132 B_a,
133 B_t,
134 B_u,
135 vec_L_A,
136 vec_L_T,
137 vec_L_U,
138 vec_R_A,
139 vec_R_T,
140 vec_R_U,
141 x_final: slice_x[0],
142 }
143 }
144
145 fn verification_scalars(
147 &self,
148 n: usize,
149 transcript: &mut Transcript,
150 ) -> Result<(Vec<Fr>, Vec<Fr>, Vec<Fr>), ProofError> {
151 let lg_n = self.vec_L_A.len();
152 if lg_n >= 32 {
153 return Err(ProofError::VerificationError);
154 }
155 if n != (1 << lg_n) {
156 return Err(ProofError::VerificationError);
157 }
158
159 let bitstring = get_verification_scalars_bitstring(n, lg_n);
160
161 let mut challenges: Vec<Fr> = Vec::with_capacity(lg_n);
163 for i in 0..self.vec_L_A.len() {
164 transcript.append_list(
165 b"same_msm_loop",
166 &[
167 &self.vec_L_A[i],
168 &self.vec_L_T[i],
169 &self.vec_L_U[i],
170 &self.vec_R_A[i],
171 &self.vec_R_T[i],
172 &self.vec_R_U[i],
173 ],
174 );
175 challenges.push(transcript.get_and_append_challenge(b"same_msm_gamma"));
176 }
177
178 let mut challenges_inv: Vec<Fr> = challenges.clone();
180 batch_inversion(&mut challenges_inv);
181
182 let mut vec_s: Vec<Fr> = Vec::with_capacity(n);
184 for i in 0..n {
185 vec_s.push(Fr::one());
186 for j in 0..bitstring[i].len() {
187 vec_s[i] *= challenges[bitstring[i][j]]
188 }
189 }
190
191 Ok((challenges, challenges_inv, vec_s))
192 }
193
194 pub fn verify<T: RngCore>(
205 &self,
206 crs_G_vec: &[G1Affine],
207
208 A: G1Projective,
209 Z_t: G1Projective,
210 Z_u: G1Projective,
211 vec_T: &Vec<G1Affine>,
212 vec_U: &Vec<G1Affine>,
213
214 transcript: &mut Transcript,
215 msm_accumulator: &mut MsmAccumulator,
216 rng: &mut T,
217 ) -> Result<(), ProofError> {
218 let n = vec_T.len();
219
220 transcript.append_list(b"same_msm_step1", &[&A, &Z_t, &Z_u]);
222 transcript.append_list(b"same_msm_step1", &[vec_T, vec_U]);
223 transcript.append_list(b"same_msm_step1", &[&self.B_a, &self.B_t, &self.B_u]);
224 let alpha = transcript.get_and_append_challenge(b"same_msm_alpha");
225
226 let (vec_gamma, vec_gamma_inv, vec_s) = self.verification_scalars(n, transcript)?;
228
229 let vec_x_times_s: Vec<Fr> = vec_s.iter().map(|s_i| self.x_final * *s_i).collect();
231
232 let A_a = self.B_a + A.mul(alpha.into_repr());
234 let Z_t_a = self.B_t + Z_t.mul(alpha.into_repr());
235 let Z_u_a = self.B_u + Z_u.mul(alpha.into_repr());
236
237 let point_lhs = msm_from_projective(&self.vec_L_A, &vec_gamma)
238 + A_a
239 + msm_from_projective(&self.vec_R_A, &vec_gamma_inv);
240 msm_accumulator.accumulate_check(&point_lhs, &vec_x_times_s, crs_G_vec, rng);
241
242 let point_lhs = msm_from_projective(&self.vec_L_T, &vec_gamma)
243 + Z_t_a
244 + msm_from_projective(&self.vec_R_T, &vec_gamma_inv);
245 msm_accumulator.accumulate_check(&point_lhs, &vec_x_times_s, vec_T, rng);
246
247 let point_lhs = msm_from_projective(&self.vec_L_U, &vec_gamma)
248 + Z_u_a
249 + msm_from_projective(&self.vec_R_U, &vec_gamma_inv);
250 msm_accumulator.accumulate_check(&point_lhs, &vec_x_times_s, vec_U, rng);
251 Ok(())
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258 use ark_ec::ProjectiveCurve;
259 use ark_std::rand::{rngs::StdRng, Rng, SeedableRng};
260 use ark_std::UniformRand;
261 use core::iter;
262
263 #[test]
264 fn test_same_msm_argument() {
265 let mut rng = StdRng::seed_from_u64(0u64);
266 let mut transcript_prover = merlin::Transcript::new(b"same_msm");
267
268 let n = 128;
269
270 let crs_G_vec: Vec<_> = iter::repeat_with(|| G1Projective::rand(&mut rng).into_affine())
271 .take(n)
272 .collect();
273
274 let vec_T: Vec<_> = iter::repeat_with(|| G1Projective::rand(&mut rng).into_affine())
275 .take(n)
276 .collect();
277 let vec_U: Vec<_> = iter::repeat_with(|| G1Projective::rand(&mut rng).into_affine())
278 .take(n)
279 .collect();
280
281 let vec_x: Vec<Fr> = iter::repeat_with(|| rng.gen()).take(n).collect();
282
283 let A = msm(&crs_G_vec, &vec_x);
284 let Z_t = msm(&vec_T, &vec_x);
285 let Z_u = msm(&vec_U, &vec_x);
286
287 let proof = SameMultiscalarProof::new(
288 crs_G_vec.clone(),
289 A.clone(),
290 Z_t.clone(),
291 Z_u.clone(),
292 vec_T.clone(),
293 vec_U.clone(),
294 vec_x,
295 &mut transcript_prover,
296 &mut rng,
297 );
298
299 let mut transcript_verifier = merlin::Transcript::new(b"same_msm");
301 let mut msm_accumulator = MsmAccumulator::new();
302
303 assert!(proof
304 .verify(
305 &crs_G_vec,
306 A,
307 Z_t,
308 Z_u,
309 &vec_T,
310 &vec_U,
311 &mut transcript_verifier,
312 &mut msm_accumulator,
313 &mut rng,
314 )
315 .is_ok());
316
317 assert!(msm_accumulator.verify().is_ok())
318 }
319}