@@ -704,5 +704,267 @@ static int secp256k1_bppp_rangeproof_prove_impl(
704704 return res ;
705705}
706706
707+ typedef struct secp256k1_bppp_verify_cb_data {
708+ const unsigned char * proof ;
709+ const secp256k1_scalar * g_vec_pub_deltas ;
710+ const secp256k1_scalar * t_pows ;
711+ const secp256k1_scalar * v ;
712+ const secp256k1_ge * asset_genp ;
713+ const secp256k1_ge * commit ;
714+ const secp256k1_ge * g_gens ;
715+ } secp256k1_bppp_verify_cb_data ;
716+
717+ static int secp256k1_bppp_verify_cb (secp256k1_scalar * sc , secp256k1_ge * pt , size_t idx , void * cbdata ) {
718+ secp256k1_bppp_verify_cb_data * data = (secp256k1_bppp_verify_cb_data * ) cbdata ;
719+ switch (idx ) {
720+ case 0 : /* v * asset_genp */
721+ * pt = * data -> asset_genp ;
722+ * sc = * data -> v ;
723+ break ;
724+ case 1 : /* t * M */
725+ if (!secp256k1_eckey_pubkey_parse (pt , data -> proof , 33 )) {
726+ return 0 ;
727+ }
728+ * sc = data -> t_pows [0 ];
729+ break ;
730+ case 2 : /* t^2 D */
731+ if (!secp256k1_eckey_pubkey_parse (pt , & data -> proof [33 ], 33 )) {
732+ return 0 ;
733+ }
734+ * sc = data -> t_pows [1 ];
735+ break ;
736+ case 3 : /* t^3 R */
737+ if (!secp256k1_eckey_pubkey_parse (pt , & data -> proof [33 * 2 ], 33 )) {
738+ return 0 ;
739+ }
740+ * sc = data -> t_pows [2 ];
741+ break ;
742+ case 4 : /* 1. S */
743+ if (!secp256k1_eckey_pubkey_parse (pt , & data -> proof [33 * 3 ], 33 )) {
744+ return 0 ;
745+ }
746+ secp256k1_scalar_set_int (sc , 1 );
747+ break ;
748+ case 5 : /* 2t^5 V(commit) */
749+ * pt = * data -> commit ;
750+ * sc = data -> t_pows [4 ];
751+ secp256k1_scalar_add (sc , sc , sc );
752+ break ;
753+ default :
754+ idx -= 6 ;
755+ * pt = data -> g_gens [idx ];
756+ * sc = data -> g_vec_pub_deltas [idx ];
757+ break ;
758+ }
759+ return 1 ;
760+ }
761+
762+ static int secp256k1_bppp_rangeproof_verify_impl (
763+ const secp256k1_context * ctx ,
764+ secp256k1_scratch_space * scratch ,
765+ const secp256k1_bppp_generators * gens ,
766+ const secp256k1_ge * asset_genp ,
767+ const unsigned char * proof ,
768+ const size_t proof_len ,
769+ const size_t n_bits ,
770+ const size_t digit_base ,
771+ const uint64_t min_value ,
772+ const secp256k1_ge * commitp ,
773+ const unsigned char * extra_commit ,
774+ size_t extra_commit_len
775+ ) {
776+ size_t scratch_checkpoint ;
777+ secp256k1_sha256 transcript ;
778+ size_t num_digits = n_bits / secp256k1_bppp_log2 (digit_base );
779+ size_t h_len = 8 , i ;
780+ size_t g_offset = num_digits > digit_base ? num_digits : digit_base ;
781+ size_t log_n = secp256k1_bppp_log2 (g_offset ), log_m = secp256k1_bppp_log2 (h_len );
782+ size_t n_rounds = log_n > log_m ? log_n : log_m ;
783+ secp256k1_scalar v_g ;
784+ secp256k1_scalar * q_pows , * q_inv_pows , * g_vec_pub_deltas ;
785+ secp256k1_scalar e , q_sqrt , q , q_inv , x , y , t ;
786+ /* To be re-used as c_vec later */
787+ secp256k1_scalar t_pows [8 ];
788+
789+ /* Check proof sizes*/
790+ if (proof_len != 33 * 4 + (65 * n_rounds ) + 64 ) {
791+ return 0 ;
792+ }
793+ if (gens -> n != (g_offset + h_len )) {
794+ return 0 ;
795+ }
796+ if (!secp256k1_is_power_of_two (digit_base ) || !secp256k1_is_power_of_two (num_digits ) || !secp256k1_is_power_of_two (n_bits )) {
797+ return 0 ;
798+ }
799+ if (n_bits > 64 ) {
800+ return 0 ;
801+ }
802+ if (extra_commit_len > 0 && extra_commit == NULL ) {
803+ return 0 ;
804+ }
805+
806+ scratch_checkpoint = secp256k1_scratch_checkpoint (& ctx -> error_callback , scratch );
807+ q_pows = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , g_offset * sizeof (secp256k1_scalar ));
808+ q_inv_pows = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , g_offset * sizeof (secp256k1_scalar ));
809+ g_vec_pub_deltas = (secp256k1_scalar * )secp256k1_scratch_alloc (& ctx -> error_callback , scratch , g_offset * sizeof (secp256k1_scalar ));
810+
811+ if ( q_pows == NULL || q_inv_pows == NULL ) {
812+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , scratch_checkpoint );
813+ return 0 ;
814+ }
815+
816+ /* Obtain the challenges */
817+ secp256k1_bppp_commit_initial_data (
818+ & transcript ,
819+ num_digits ,
820+ digit_base ,
821+ min_value ,
822+ commitp ,
823+ asset_genp ,
824+ extra_commit ,
825+ extra_commit_len
826+ );
827+
828+ /* Verify round 1 */
829+ secp256k1_sha256_write (& transcript , proof , 66 );
830+ secp256k1_bppp_challenge_scalar (& e , & transcript , 0 );
831+
832+ /* Verify round 2 */
833+ secp256k1_sha256_write (& transcript , & proof [33 * 2 ], 33 );
834+ secp256k1_bppp_challenge_scalar (& q_sqrt , & transcript , 0 );
835+ secp256k1_bppp_challenge_scalar (& x , & transcript , 1 );
836+ secp256k1_bppp_challenge_scalar (& y , & transcript , 2 );
837+ secp256k1_scalar_sqr (& q , & q_sqrt );
838+ secp256k1_scalar_inverse_var (& q_inv , & q );
839+
840+ /* Verify round 3 */
841+ secp256k1_sha256_write (& transcript , & proof [33 * 3 ], 33 );
842+ secp256k1_bppp_challenge_scalar (& t , & transcript , 0 );
843+
844+ secp256k1_bppp_rangeproof_powers_of_q (q_pows , & q , g_offset );
845+ secp256k1_bppp_rangeproof_powers_of_q (q_inv_pows , & q_inv , g_offset );
846+
847+ /* Computes from t^1 to t^7, Others unneeded, will be set to 0 later */
848+ secp256k1_bppp_rangeproof_powers_of_q (& t_pows [0 ], & t , 7 );
849+ {
850+ /* g_vec_pub_delta[i] = (b^i*t^3 + (-x)*t^2 + (x/e+i)*t^4)*q_inv^i + e*t^2 */
851+ secp256k1_scalar b_pow_i_t3 , neg_x_t2 , x_t4 , e_t2 , base ;
852+ b_pow_i_t3 = t_pows [2 ];
853+ secp256k1_scalar_negate (& neg_x_t2 , & x );
854+ secp256k1_scalar_mul (& neg_x_t2 , & neg_x_t2 , & t_pows [1 ]);
855+ x_t4 = t_pows [3 ];
856+ secp256k1_scalar_mul (& x_t4 , & x_t4 , & x );
857+ e_t2 = t_pows [1 ];
858+ secp256k1_scalar_mul (& e_t2 , & e_t2 , & e );
859+ secp256k1_scalar_set_int (& base , digit_base );
860+
861+ for (i = 0 ; i < g_offset ; i ++ ) {
862+ secp256k1_scalar_clear (& g_vec_pub_deltas [i ]);
863+ if (i < num_digits ) {
864+ secp256k1_scalar_add (& g_vec_pub_deltas [i ], & b_pow_i_t3 , & neg_x_t2 ); /* g_vec_pub_delta[i] = b^i*t^3 + (-x)*t^2 */
865+ secp256k1_scalar_mul (& b_pow_i_t3 , & b_pow_i_t3 , & base );
866+ }
867+
868+ if (i < digit_base ) {
869+ secp256k1_scalar e_plus_i_inv ;
870+ secp256k1_scalar_set_int (& e_plus_i_inv , i ); /* digit base is less than 2^32, can directly set*/
871+ secp256k1_scalar_add (& e_plus_i_inv , & e_plus_i_inv , & e ); /* (e + i)*/
872+ secp256k1_scalar_inverse_var (& e_plus_i_inv , & e_plus_i_inv ); /* 1/(e +i)*/
873+ secp256k1_scalar_mul (& e_plus_i_inv , & e_plus_i_inv , & x_t4 ); /* xt^4/(e+i) */
874+
875+ secp256k1_scalar_add (& g_vec_pub_deltas [i ], & g_vec_pub_deltas [i ], & e_plus_i_inv ); /*g_vec_pub_delta[i] = b^i*t^3 + (-x)*t^2 + xt^4/(e+i)*/
876+ }
877+
878+ secp256k1_scalar_mul (& g_vec_pub_deltas [i ], & g_vec_pub_deltas [i ], & q_inv_pows [i ]); /* g_vec_pub_delta[i] = (b^i*t^3 + (-x)*t^2 + xt^4/(e+i))*q_inv^i */
879+ if (i < num_digits ) {
880+ secp256k1_scalar_add (& g_vec_pub_deltas [i ], & g_vec_pub_deltas [i ], & e_t2 ); /* g_vec_pub_delta[i] = (b^i*t^3 + (-x)*t^2 + xt^4/(e+i))*q_inv^i + e*t^2 */
881+ }
882+ }
883+ }
884+
885+ {
886+ /* v = 2*t5(<one_vec, q^(i+1)> + <b^i, e> + <b^i, -x*q^-(i+1)>) + x^2t^8(<q^-(i+1)/(e+i), 1/(e+i)>) */
887+ secp256k1_scalar two_t5 , x2_t8 , b_pow_i , neg_x_q_inv_pow_plus_e , e_plus_i_inv , base , v_g1 , v_g2 , sc_min_v ;
888+ secp256k1_scalar_set_int (& two_t5 , 2 );
889+ secp256k1_scalar_mul (& two_t5 , & two_t5 , & t_pows [4 ]);
890+ secp256k1_scalar_mul (& x2_t8 , & t_pows [3 ], & x );
891+ secp256k1_scalar_sqr (& x2_t8 , & x2_t8 );
892+ secp256k1_scalar_set_int (& b_pow_i , 1 );
893+ secp256k1_scalar_clear (& v_g1 );
894+ secp256k1_scalar_clear (& v_g2 );
895+ secp256k1_scalar_set_int (& base , digit_base );
896+
897+ /* Compute v_g1 = 2*t5(<one_vec, q^(i+1)> + <b^i, e> + <b^i, -x*q^-(i+1)>) */
898+ for (i = 0 ; i < num_digits ; i ++ ) {
899+ secp256k1_scalar_add (& v_g1 , & v_g1 , & q_pows [i ]); /* v_g1 = <q^(i+1), 1> */
900+ secp256k1_scalar_negate (& neg_x_q_inv_pow_plus_e , & x ); /* -x */
901+ secp256k1_scalar_mul (& neg_x_q_inv_pow_plus_e , & q_inv_pows [i ], & neg_x_q_inv_pow_plus_e ); /* -x*q^-(i+1) */
902+ secp256k1_scalar_add (& neg_x_q_inv_pow_plus_e , & neg_x_q_inv_pow_plus_e , & e ); /* -x*q^-(i+1) + e */
903+ secp256k1_scalar_mul (& neg_x_q_inv_pow_plus_e , & neg_x_q_inv_pow_plus_e , & b_pow_i ); /* <b^i, -x*q^-(i+1) + e> */
904+ secp256k1_scalar_add (& v_g1 , & v_g1 , & neg_x_q_inv_pow_plus_e ); /* v_g1 = <q^(i+1), 1> + <b^i, -x*q^-(i+1) + e> */
905+ secp256k1_scalar_mul (& b_pow_i , & b_pow_i , & base );
906+ }
907+ secp256k1_scalar_set_int (& sc_min_v , min_value );
908+ secp256k1_scalar_negate (& sc_min_v , & sc_min_v );
909+ secp256k1_scalar_add (& v_g1 , & v_g1 , & sc_min_v ); /* v_g1 = <q^(i+1), 1> + <b^i, -x*q^-(i+1) + e> - min_value */
910+ secp256k1_scalar_mul (& v_g1 , & v_g1 , & two_t5 ); /* v_g1 = 2*t5(<one_vec, q^(i+1)> + <b^i, e> + <b^i, -x*q^-(i+1)> - min_value) */
911+
912+ /* Compute v_g2 = x^2t^8(<q^-(i+1)/(e+i), 1/(e+i)>) */
913+ for (i = 0 ; i < digit_base ; i ++ ) {
914+ secp256k1_scalar_set_int (& e_plus_i_inv , i ); /* digit base is less than 2^32, can directly set*/
915+ secp256k1_scalar_add (& e_plus_i_inv , & e_plus_i_inv , & e ); /* (e + i)*/
916+ secp256k1_scalar_inverse_var (& e_plus_i_inv , & e_plus_i_inv ); /* 1/(e +i)*/
917+ secp256k1_scalar_sqr (& e_plus_i_inv , & e_plus_i_inv ); /* 1/(e +i)^2 */
918+ secp256k1_scalar_mul (& e_plus_i_inv , & e_plus_i_inv , & q_inv_pows [i ]); /* q^-(i+1)/(e+i)^2 */
919+ secp256k1_scalar_add (& v_g2 , & v_g2 , & e_plus_i_inv ); /* v_g2 = <q^-(i+1)/(e+i), 1/(e+i)> */
920+ }
921+ secp256k1_scalar_mul (& v_g2 , & v_g2 , & x2_t8 ); /* v_g2 = x^2t^8(<q^-(i+1)/(e+i), 1/(e+i)>) */
922+ secp256k1_scalar_add (& v_g , & v_g1 , & v_g2 ); /* v_g = v_g1 + v_g2 */
923+ }
924+ /* Ecmult to compute C = S + tM + t^2D + t^3R + 2t^5V + <g_vec_pub_deltas, G_vec> + v_g*A(asset_genP) */
925+ {
926+ secp256k1_bppp_verify_cb_data cb_data ;
927+ secp256k1_gej c_commj ;
928+ secp256k1_ge c_comm ;
929+ size_t num_points ;
930+ cb_data .g_vec_pub_deltas = g_vec_pub_deltas ;
931+ cb_data .v = & v_g ;
932+ cb_data .asset_genp = asset_genp ;
933+ cb_data .commit = commitp ;
934+ cb_data .g_gens = gens -> gens ;
935+ cb_data .proof = proof ;
936+ cb_data .t_pows = t_pows ;
937+ num_points = 6 + g_offset ;
938+
939+ if (!secp256k1_ecmult_multi_var (& ctx -> error_callback , scratch , & c_commj , NULL , secp256k1_bppp_verify_cb , (void * ) & cb_data , num_points )) {
940+ return 0 ;
941+ }
942+
943+ secp256k1_ge_set_gej_var (& c_comm , & c_commj );
944+ /* Make c = y*(T, T^2, T^3, T^4, T^6, T^7, 0, 0) */
945+ t_pows [4 ] = t_pows [5 ];
946+ t_pows [5 ] = t_pows [6 ];
947+ for (i = 0 ; i < 6 ; i ++ ) {
948+ secp256k1_scalar_mul (& t_pows [i ], & t_pows [i ], & y );
949+ }
950+ secp256k1_scalar_clear (& t_pows [6 ]);
951+ secp256k1_scalar_clear (& t_pows [7 ]);
952+
953+ return secp256k1_bppp_rangeproof_norm_product_verify (
954+ ctx ,
955+ scratch ,
956+ & proof [33 * 4 ],
957+ proof_len - 33 * 4 ,
958+ & transcript ,
959+ & q_sqrt ,
960+ gens ,
961+ asset_genp ,
962+ g_offset ,
963+ t_pows ,
964+ 8 ,
965+ & c_comm
966+ );
967+ }
968+ }
707969
708970#endif
0 commit comments