@@ -445,4 +445,264 @@ static void secp256k1_bppp_rangeproof_prove_round3_impl(
445445 }
446446}
447447
448+ /* Round 4 of the proof. Computes the norm proof on the w and l values.
449+ * Can fail only when the norm proof fails.
450+ * This should not happen in our setting because w_vec and l_vec and uniformly
451+ * distributed and thus norm argument can only fail when the lengths are not a
452+ * power of two or if the allocated proof size is not enough.
453+ *
454+ * We check for both of these conditions beforehand, therefore in practice this
455+ * function should never fail because it returns point at infinity during some
456+ * interim calculations. However, since the overall API can fail, we also fail
457+ * if the norm proofs fails for any reason.
458+ */
459+ static int secp256k1_bppp_rangeproof_prove_round4_impl (
460+ const secp256k1_context * ctx ,
461+ secp256k1_scratch_space * scratch ,
462+ const secp256k1_bppp_generators * gens ,
463+ const secp256k1_ge * asset_genp ,
464+ secp256k1_bppp_rangeproof_prover_context * prover_ctx ,
465+ unsigned char * output ,
466+ size_t * output_len ,
467+ secp256k1_sha256 * transcript ,
468+ const secp256k1_scalar * gamma ,
469+ const size_t num_digits ,
470+ const size_t digit_base
471+ ) {
472+ size_t i , scratch_checkpoint ;
473+ size_t g_offset = digit_base > num_digits ? digit_base : num_digits ;
474+ /* Compute w = s + t*m + t^2*d + t^3*r + t^4*alpha_m. Store w in s*/
475+ /* Has capacity 8 because we can re-use it as the c-poly. */
476+ secp256k1_scalar t_pows [8 ];
477+ secp256k1_ge * gs ;
478+ secp256k1_bppp_rangeproof_powers_of_q (& t_pows [0 ], & prover_ctx -> t , 7 ); /* Computes from t^1 to t^7 */
479+
480+ for (i = 0 ; i < g_offset ; i ++ ) {
481+ if (i < num_digits ) {
482+ secp256k1_scalar_mul (& prover_ctx -> r [i ], & prover_ctx -> r [i ], & t_pows [2 ]);
483+ secp256k1_scalar_add (& prover_ctx -> s [i ], & prover_ctx -> s [i ], & prover_ctx -> r [i ]);
484+
485+ secp256k1_scalar_mul (& prover_ctx -> d [i ], & prover_ctx -> d [i ], & t_pows [1 ]);
486+ secp256k1_scalar_add (& prover_ctx -> s [i ], & prover_ctx -> s [i ], & prover_ctx -> d [i ]);
487+ }
488+ if (i < digit_base ) {
489+ secp256k1_scalar_mul (& prover_ctx -> m [i ], & prover_ctx -> m [i ], & t_pows [0 ]);
490+ secp256k1_scalar_add (& prover_ctx -> s [i ], & prover_ctx -> s [i ], & prover_ctx -> m [i ]);
491+
492+ secp256k1_scalar_mul (& prover_ctx -> alpha_m [i ], & prover_ctx -> alpha_m [i ], & t_pows [3 ]);
493+ secp256k1_scalar_add (& prover_ctx -> s [i ], & prover_ctx -> s [i ], & prover_ctx -> alpha_m [i ]);
494+ }
495+ }
496+ /* Compute l = l_s + t*l_m + t^2*l_d + t^3*l_r. Store l in l_s*/
497+ for (i = 0 ; i < 6 ; i ++ ) {
498+ secp256k1_scalar tmp ;
499+ secp256k1_scalar_mul (& tmp , & prover_ctx -> l_m [i ], & t_pows [0 ]);
500+ secp256k1_scalar_add (& prover_ctx -> l_s [i ], & prover_ctx -> l_s [i ], & tmp );
501+ }
502+ /* Manually add l_d2 and l_d4 */
503+ {
504+ secp256k1_scalar tmp ;
505+ secp256k1_scalar_mul (& tmp , & prover_ctx -> l_m [3 ], & t_pows [1 ]);
506+ secp256k1_scalar_negate (& tmp , & tmp );/* l_d2 = -l_m3 */
507+ secp256k1_scalar_add (& prover_ctx -> l_s [2 ], & prover_ctx -> l_s [2 ], & tmp );
508+
509+ secp256k1_scalar_mul (& tmp , & prover_ctx -> l_m [5 ], & t_pows [1 ]);
510+ secp256k1_scalar_negate (& tmp , & tmp );/* l_d4 = -l_m5 */
511+ secp256k1_scalar_add (& prover_ctx -> l_s [4 ], & prover_ctx -> l_s [4 ], & tmp );
512+
513+ /* Add two_gamma * t5 to l_s[0] */
514+ secp256k1_scalar_add (& tmp , & t_pows [4 ], & t_pows [4 ]);
515+ secp256k1_scalar_mul (& tmp , & tmp , gamma );
516+ secp256k1_scalar_add (& prover_ctx -> l_s [0 ], & prover_ctx -> l_s [0 ], & tmp );
517+ }
518+ /* Set non used 7th and 8th l_s to 0 */
519+ secp256k1_scalar_set_int (& prover_ctx -> l_s [6 ], 0 );
520+ secp256k1_scalar_set_int (& prover_ctx -> l_s [7 ], 0 );
521+
522+ /* Make c = y*(T, T^2, T^3, T^4, T^6, T^7, 0, 0) */
523+ t_pows [4 ] = t_pows [5 ];
524+ t_pows [5 ] = t_pows [6 ];
525+ for (i = 0 ; i < 6 ; i ++ ) {
526+ secp256k1_scalar_mul (& t_pows [i ], & t_pows [i ], & prover_ctx -> y );
527+ }
528+ secp256k1_scalar_set_int (& t_pows [6 ], 0 );
529+ secp256k1_scalar_set_int (& t_pows [7 ], 0 );
530+ /* Call the norm argument on w, l */
531+ /* We have completed the blinding, none of part that comes from this point on
532+ needs to constant time. We can safely early return
533+ */
534+ scratch_checkpoint = secp256k1_scratch_checkpoint (& ctx -> error_callback , scratch );
535+ gs = (secp256k1_ge * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , (gens -> n ) * sizeof (secp256k1_ge ));
536+ if (gs == NULL ) {
537+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , scratch_checkpoint );
538+ return 0 ;
539+ }
540+ memcpy (gs , gens -> gens , (gens -> n ) * sizeof (secp256k1_ge ));
541+
542+ return secp256k1_bppp_rangeproof_norm_product_prove (
543+ ctx ,
544+ scratch ,
545+ output ,
546+ output_len ,
547+ transcript ,
548+ & prover_ctx -> q_sqrt ,
549+ gs ,
550+ gens -> n ,
551+ asset_genp ,
552+ prover_ctx -> s ,
553+ g_offset ,
554+ prover_ctx -> l_s ,
555+ 8 ,
556+ t_pows ,
557+ 8
558+ );
559+ }
560+
561+ static int secp256k1_bppp_rangeproof_prove_impl (
562+ const secp256k1_context * ctx ,
563+ secp256k1_scratch_space * scratch ,
564+ const secp256k1_bppp_generators * gens ,
565+ const secp256k1_ge * asset_genp ,
566+ unsigned char * proof ,
567+ size_t * proof_len ,
568+ const size_t n_bits ,
569+ const size_t digit_base ,
570+ const uint64_t value ,
571+ const uint64_t min_value ,
572+ const secp256k1_ge * commitp ,
573+ const secp256k1_scalar * gamma ,
574+ const unsigned char * nonce ,
575+ const unsigned char * extra_commit ,
576+ size_t extra_commit_len
577+ ) {
578+ size_t scratch_checkpoint , n_proof_bytes_written , norm_proof_len ;
579+ secp256k1_sha256 transcript ;
580+ size_t num_digits = n_bits / secp256k1_bppp_log2 (digit_base );
581+ size_t h_len = 8 ;
582+ size_t g_offset = num_digits > digit_base ? num_digits : digit_base ;
583+ size_t log_n = secp256k1_bppp_log2 (g_offset ), log_m = secp256k1_bppp_log2 (h_len );
584+ size_t n_rounds = log_n > log_m ? log_n : log_m ;
585+ int res ;
586+ secp256k1_bppp_rangeproof_prover_context prover_ctx ;
587+ /* Check proof sizes*/
588+ if (* proof_len < 33 * 4 + (65 * n_rounds ) + 64 ) {
589+ return 0 ;
590+ }
591+ if (gens -> n != (g_offset + h_len )) {
592+ return 0 ;
593+ }
594+ if (!secp256k1_is_power_of_two (digit_base ) || !secp256k1_is_power_of_two (num_digits )) {
595+ return 0 ;
596+ }
597+ if (n_bits > 64 ) {
598+ return 0 ;
599+ }
600+ if (value < min_value ) {
601+ return 0 ;
602+ }
603+ if (n_bits < 64 && (value - min_value ) >= (1ull << n_bits )) {
604+ return 0 ;
605+ }
606+ if (extra_commit_len > 0 && extra_commit == NULL ) {
607+ return 0 ;
608+ }
609+
610+ /* Compute the base digits representation of the value */
611+ /* Alloc for prover->ctx */
612+ scratch_checkpoint = secp256k1_scratch_checkpoint (& ctx -> error_callback , scratch );
613+ prover_ctx .s = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , g_offset * sizeof (secp256k1_scalar ));
614+ prover_ctx .d = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , num_digits * sizeof (secp256k1_scalar ));
615+ prover_ctx .m = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , digit_base * sizeof (secp256k1_scalar ));
616+ prover_ctx .r = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , num_digits * sizeof (secp256k1_scalar ));
617+ prover_ctx .alpha_m = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , digit_base * sizeof (secp256k1_scalar ));
618+
619+ prover_ctx .l_m = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , 6 * sizeof (secp256k1_scalar ));
620+ prover_ctx .l_s = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , h_len * sizeof (secp256k1_scalar ));
621+
622+ prover_ctx .q_pows = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , g_offset * sizeof (secp256k1_scalar ));
623+ prover_ctx .q_inv_pows = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , g_offset * sizeof (secp256k1_scalar ));
624+
625+ if ( prover_ctx .s == NULL || prover_ctx .d == NULL || prover_ctx .m == NULL || prover_ctx .r == NULL
626+ || prover_ctx .alpha_m == NULL || prover_ctx .l_m == NULL || prover_ctx .l_s == NULL
627+ || prover_ctx .q_pows == NULL || prover_ctx .q_inv_pows == NULL )
628+ {
629+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , scratch_checkpoint );
630+ return 0 ;
631+ }
632+
633+ /* Initialze the transcript by committing to all the public data */
634+ secp256k1_bppp_commit_initial_data (
635+ & transcript ,
636+ num_digits ,
637+ digit_base ,
638+ min_value ,
639+ commitp ,
640+ asset_genp ,
641+ extra_commit ,
642+ extra_commit_len
643+ );
644+
645+ n_proof_bytes_written = 0 ;
646+ secp256k1_bppp_rangeproof_prove_round1_impl (
647+ & prover_ctx ,
648+ gens ,
649+ asset_genp ,
650+ & proof [n_proof_bytes_written ],
651+ & transcript ,
652+ num_digits ,
653+ digit_base ,
654+ value - min_value ,
655+ nonce
656+ );
657+ n_proof_bytes_written += 33 * 2 ;
658+
659+ secp256k1_bppp_rangeproof_prove_round2_impl (
660+ & prover_ctx ,
661+ gens ,
662+ asset_genp ,
663+ & proof [n_proof_bytes_written ],
664+ & transcript ,
665+ num_digits ,
666+ digit_base ,
667+ nonce
668+ );
669+ n_proof_bytes_written += 33 ;
670+
671+ secp256k1_bppp_rangeproof_prove_round3_impl (
672+ & prover_ctx ,
673+ gens ,
674+ asset_genp ,
675+ & proof [n_proof_bytes_written ],
676+ & transcript ,
677+ num_digits ,
678+ digit_base ,
679+ gamma ,
680+ nonce
681+ );
682+ n_proof_bytes_written += 33 ;
683+
684+ /* Calculate the remaining buffer size. We have already checked that buffer is of correct size */
685+ norm_proof_len = * proof_len - n_proof_bytes_written ;
686+ res = secp256k1_bppp_rangeproof_prove_round4_impl (
687+ ctx ,
688+ scratch ,
689+ gens ,
690+ asset_genp ,
691+ & prover_ctx ,
692+ & proof [n_proof_bytes_written ],
693+ & norm_proof_len ,
694+ & transcript ,
695+ gamma ,
696+ num_digits ,
697+ digit_base
698+ );
699+ /* No need to worry about constant time-ness from this point. All data is public */
700+ if (res ) {
701+ * proof_len = n_proof_bytes_written + norm_proof_len ;
702+ }
703+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , scratch_checkpoint );
704+ return res ;
705+ }
706+
707+
448708#endif
0 commit comments