@@ -224,4 +224,225 @@ static void secp256k1_bppp_rangeproof_prove_round2_impl(
224224 }
225225}
226226
227+ /* Choose of the co-effs of poly and len of co-effs w = s + mT + dT^2 + rT^3 */
228+ static const secp256k1_scalar * secp256k1_bppp_w_coeff (
229+ unsigned int * len ,
230+ size_t idx ,
231+ const secp256k1_scalar * s ,
232+ const secp256k1_scalar * m ,
233+ const secp256k1_scalar * d ,
234+ const secp256k1_scalar * r ,
235+ const secp256k1_scalar * alpha_m ,
236+ size_t digit_base ,
237+ size_t num_digits
238+ ) {
239+ switch (idx ) {
240+ case 0 :
241+ * len = num_digits > digit_base ? num_digits : digit_base ;
242+ return s ;
243+ case 1 :
244+ * len = digit_base ;
245+ return m ;
246+ case 2 :
247+ * len = num_digits ;
248+ return d ;
249+ case 3 :
250+ * len = num_digits ;
251+ return r ;
252+ case 4 :
253+ * len = digit_base ;
254+ return alpha_m ;
255+ default :
256+ VERIFY_CHECK (0 );
257+ }
258+ return NULL ;
259+ }
260+
261+ /* Compute the q-norm square of w = s + mT + dT^2 + rT^3 + alpha_mT^4.
262+ Since this is a degree 4 polynomial, we can hard code the expansion
263+ to get improve performance.
264+ |w|^2 =
265+ alpha_m**2*t**8 +
266+ 2*alpha_m*r*t**7 +
267+ t**6*(2*alpha_m*d + r**2) +
268+ t**5*(2*alpha_m*m + 2*d*r) +
269+ t**4*(2*alpha_m*s + d**2 + 2*m*r) +
270+ t**3*(2*d*m + 2*r*s) +
271+ t**2*(2*d*s + m**2) +
272+ 2*m*s*t +
273+ s**2
274+ */
275+ static void secp256k1_bppp_rangeproof_w_w_q (
276+ secp256k1_scalar * w , /* size G_len = max(digits_base, num_digits)*/
277+ const secp256k1_scalar * s , /* size G_len */
278+ const secp256k1_scalar * m , /* size digits_base */
279+ const secp256k1_scalar * d , /* size num_digits */
280+ const secp256k1_scalar * r , /* size num_digits */
281+ const secp256k1_scalar * alpha_m , /* size digits_base */
282+ const secp256k1_scalar * q_pows , /* size G_len */
283+ size_t digit_base ,
284+ size_t num_digits
285+ ) {
286+ size_t i , j , k ;
287+ for (i = 0 ; i < 9 ; i ++ ) {
288+ secp256k1_scalar_clear (& w [i ]);
289+ }
290+
291+ for (i = 0 ; i < 5 ; i ++ ) {
292+ for (j = 0 ; j < 5 ; j ++ ) {
293+ /* Can add an optimization to skip the last term if i + j >= 8 */
294+ unsigned int a_len , b_len ;
295+ const secp256k1_scalar * a_coeffs =
296+ secp256k1_bppp_w_coeff (& a_len , i , s , m , d , r , alpha_m , digit_base , num_digits );
297+ const secp256k1_scalar * b_coeffs =
298+ secp256k1_bppp_w_coeff (& b_len , j , s , m , d , r , alpha_m , digit_base , num_digits );
299+ /* Compute w[i + j] += Sum(a[k] * b[k] * q_pows[k]) */
300+ unsigned int len = a_len < b_len ? a_len : b_len ;
301+ for (k = 0 ; k < len ; k ++ ) {
302+ secp256k1_scalar tmp ;
303+ secp256k1_scalar_mul (& tmp , & a_coeffs [k ], & b_coeffs [k ]);
304+ secp256k1_scalar_mul (& tmp , & tmp , & q_pows [k ]);
305+ secp256k1_scalar_add (& w [i + j ], & w [i + j ], & tmp );
306+ }
307+ }
308+ }
309+ }
310+
311+ /* Round 3 of the proof. Computes the S value.
312+ * Serialized as 33 byte compressed point.
313+ * Always succeeds.
314+ */
315+ static void secp256k1_bppp_rangeproof_prove_round3_impl (
316+ secp256k1_bppp_rangeproof_prover_context * prover_ctx ,
317+ const secp256k1_bppp_generators * gens ,
318+ const secp256k1_ge * asset_genp ,
319+ unsigned char * output ,
320+ secp256k1_sha256 * transcript ,
321+ const size_t num_digits ,
322+ const size_t digit_base ,
323+ const secp256k1_scalar * gamma ,
324+ const unsigned char * nonce
325+ ) {
326+ size_t i ;
327+ size_t g_offset = digit_base > num_digits ? digit_base : num_digits ;
328+ secp256k1_gej s_commj ;
329+
330+ /* We don't need only one value in this round, ignore the second value. */
331+ for (i = 0 ; i < g_offset /2 ; i ++ ) {
332+ secp256k1_scalar_chacha20 (& prover_ctx -> s [2 * i ], & prover_ctx -> s [2 * i + 1 ], nonce , i + 4 );
333+ }
334+
335+ /* The l values must be computed adaptively in order to satisfy the following relation for all Ts. */
336+ {
337+ /* Add public values alpha_r=(-x*q^-(i + 1) + e) to to d */
338+ secp256k1_scalar tmp , b_pow_i , base ;
339+ for (i = 0 ; i < num_digits ; i ++ ) {
340+ secp256k1_scalar_negate (& tmp , & prover_ctx -> x );
341+ secp256k1_scalar_mul (& tmp , & tmp , & prover_ctx -> q_inv_pows [i ]);
342+ secp256k1_scalar_add (& tmp , & tmp , & prover_ctx -> e );
343+ secp256k1_scalar_add (& prover_ctx -> d [i ], & prover_ctx -> d [i ], & tmp );
344+ }
345+
346+ /* Add public values alpha_d=(b^i*q_inv^(i+1)) to to r */
347+ secp256k1_scalar_set_int (& b_pow_i , 1 );
348+ secp256k1_scalar_set_int (& base , digit_base );
349+ for (i = 0 ; i < num_digits ; i ++ ) {
350+ secp256k1_scalar_mul (& tmp , & b_pow_i , & prover_ctx -> q_inv_pows [i ]);
351+ secp256k1_scalar_add (& prover_ctx -> r [i ], & prover_ctx -> r [i ], & tmp );
352+ secp256k1_scalar_mul (& b_pow_i , & b_pow_i , & base );
353+ }
354+ }
355+
356+ /* Adaptively compute l_s to balance out the w_w_q + Y*<l, c> is zero is
357+ in all powers of T where c = (T, T^2, T^3, T^4, T^6, T^7).
358+ Note the absence of T**5 in this equation. T^0 is balanced by b_s.
359+ T^5 is balanced only if all the constraints in the rangeproof are correctly satisfied.
360+ l = l_s + l_m*T + l_d*T^2 + l_r*T^3 + 2*gamma*T^5. Only the values l_m_i are sampled randomly.
361+ All other values but ld4 = -lm5 and lm2 = -lm3 are zero. Therefore, the resultant
362+ <l-l_s, c> = T**8*(ld4 + lm5) + T**7*lm4 + T**6(2*gamma) + T**5*(ld2 + lm3) + T**4*lm2 + T**3*lm1 + T**2*lm0
363+ = T**7*lm4 + T**6(2*gamma) + T**4*lm2 + T**3*lm1 + T**2*lm0
364+ We add these terms times challenge X to respective coeffs in w_w_q. l_s is the obtained by
365+ w_w_q + y*<l - l_s, c> + y*<l_s, c> = 0
366+ */
367+ {
368+ secp256k1_scalar w_w_q [9 ];
369+ secp256k1_scalar y_inv , two_gamma ;
370+ secp256k1_bppp_rangeproof_w_w_q (
371+ w_w_q ,
372+ prover_ctx -> s ,
373+ prover_ctx -> m ,
374+ prover_ctx -> d ,
375+ prover_ctx -> r ,
376+ prover_ctx -> alpha_m ,
377+ prover_ctx -> q_pows ,
378+ digit_base ,
379+ num_digits
380+ );
381+
382+ /* Add b_i values to w_w_q. b_m*T + b_d*T^2 + b_r*T^3 */
383+ secp256k1_scalar_negate (& prover_ctx -> b_m , & prover_ctx -> b_m );
384+ secp256k1_scalar_negate (& prover_ctx -> b_d , & prover_ctx -> b_d );
385+ secp256k1_scalar_negate (& prover_ctx -> b_r , & prover_ctx -> b_r );
386+
387+ secp256k1_scalar_add (& w_w_q [1 ], & w_w_q [1 ], & prover_ctx -> b_m );
388+ secp256k1_scalar_add (& w_w_q [2 ], & w_w_q [2 ], & prover_ctx -> b_d );
389+ secp256k1_scalar_add (& w_w_q [3 ], & w_w_q [3 ], & prover_ctx -> b_r );
390+
391+ secp256k1_scalar_inverse_var (& y_inv , & prover_ctx -> y );
392+
393+ /* Balance out b_s = q^(i+1)*s[i]*s[i] = w_w_q[0] */
394+ prover_ctx -> b_s = w_w_q [0 ];
395+ /* Note the limits on i from 1 to 8.*/
396+ for (i = 1 ; i < 8 ; i ++ ) {
397+ secp256k1_scalar_mul (& w_w_q [i ], & w_w_q [i ], & y_inv );
398+ }
399+ secp256k1_scalar_add (& w_w_q [7 ], & w_w_q [7 ], & prover_ctx -> l_m [4 ]);
400+ secp256k1_scalar_add (& w_w_q [4 ], & w_w_q [4 ], & prover_ctx -> l_m [2 ]);
401+ secp256k1_scalar_add (& w_w_q [3 ], & w_w_q [3 ], & prover_ctx -> l_m [1 ]);
402+ secp256k1_scalar_add (& w_w_q [2 ], & w_w_q [2 ], & prover_ctx -> l_m [0 ]);
403+
404+ secp256k1_scalar_set_int (& two_gamma , 2 );
405+ secp256k1_scalar_mul (& two_gamma , & two_gamma , gamma );
406+ secp256k1_scalar_add (& w_w_q [6 ], & w_w_q [6 ], & two_gamma );
407+
408+ /* Set all l_s values as negation of w_w_q */
409+ secp256k1_scalar_negate (& prover_ctx -> l_s [0 ], & w_w_q [1 ]);
410+ secp256k1_scalar_negate (& prover_ctx -> l_s [1 ], & w_w_q [2 ]);
411+ secp256k1_scalar_negate (& prover_ctx -> l_s [2 ], & w_w_q [3 ]);
412+ secp256k1_scalar_negate (& prover_ctx -> l_s [3 ], & w_w_q [4 ]);
413+ secp256k1_scalar_negate (& prover_ctx -> l_s [4 ], & w_w_q [6 ]);
414+ secp256k1_scalar_negate (& prover_ctx -> l_s [5 ], & w_w_q [7 ]);
415+ }
416+ /* Commit to the vector s in gens, with b_s along asset and l in H_vec */
417+ secp256k1_ecmult_const (& s_commj , asset_genp , & prover_ctx -> b_s , 256 );
418+ for (i = 0 ; i < g_offset ; i ++ ) {
419+ secp256k1_gej resj ;
420+ secp256k1_ge s_comm ;
421+ secp256k1_ecmult_const (& resj , & gens -> gens [i ], & prover_ctx -> s [i ], 256 );
422+ secp256k1_ge_set_gej (& s_comm , & s_commj );
423+ secp256k1_gej_add_ge (& s_commj , & resj , & s_comm ); /* s_comm cannot be 0 */
424+ }
425+
426+ for (i = 0 ; i < 6 ; i ++ ) {
427+ secp256k1_gej resj ;
428+ secp256k1_ge s_comm ;
429+ secp256k1_ecmult_const (& resj , & gens -> gens [g_offset + i ], & prover_ctx -> l_s [i ], 256 );
430+ secp256k1_ge_set_gej (& s_comm , & s_commj );
431+ secp256k1_gej_add_ge (& s_commj , & resj , & s_comm ); /* s_comm cannot be 0 */
432+ }
433+
434+ {
435+ secp256k1_ge s_comm ;
436+ /* All s values are non-zero(computed by inverse), scommj must be non-zero */
437+ VERIFY_CHECK (secp256k1_gej_is_infinity (& s_commj ) == 0 );
438+ secp256k1_ge_set_gej_var (& s_comm , & s_commj );
439+ secp256k1_fe_normalize_var (& s_comm .x );
440+ secp256k1_fe_normalize_var (& s_comm .y );
441+ secp256k1_bppp_serialize_pt (& output [0 ], & s_comm );
442+
443+ secp256k1_sha256_write (transcript , output , 33 );
444+ secp256k1_bppp_challenge_scalar (& prover_ctx -> t , transcript , 0 );
445+ }
446+ }
447+
227448#endif
0 commit comments