@@ -655,6 +655,7 @@ static void test_single_value_proof(uint64_t val) {
655655 uint64_t max_val_out = 0 ;
656656 uint64_t val_out = 0 ;
657657 size_t m_len_out = 0 ;
658+ const int using_exact_value = secp256k1_testrand32 () & 1 ;
658659
659660 secp256k1_testrand256 (blind );
660661 secp256k1_testrand256 (nonce );
@@ -673,19 +674,27 @@ static void test_single_value_proof(uint64_t val) {
673674 secp256k1_generator_h
674675 ) == 0 );
675676
676- plen = sizeof (proof );
677- CHECK (secp256k1_rangeproof_sign (
678- ctx ,
679- proof , & plen ,
680- val , /* min_val */
681- & commit , blind , nonce ,
682- -1 , /* exp: -1 is magic value to indicate a single-value proof */
683- 0 , /* min_bits */
684- val , /* val */
685- NULL , 0 ,
686- NULL , 0 ,
687- secp256k1_generator_h
688- ) == 1 );
677+ if (using_exact_value && val == 0 ) {
678+ plen = 70 ; /* sanity-check that plen can be <73 for 0-value proofs */
679+ } else {
680+ plen = sizeof (proof );
681+ }
682+ if (using_exact_value ) {
683+ CHECK (secp256k1_rangeproof_create_value (ctx , proof , & plen , val , blind , & commit , secp256k1_generator_h ) == 1 );
684+ } else {
685+ CHECK (secp256k1_rangeproof_sign (
686+ ctx ,
687+ proof , & plen ,
688+ val , /* min_val */
689+ & commit , blind , nonce ,
690+ -1 , /* exp: -1 is magic value to indicate a single-value proof */
691+ 0 , /* min_bits */
692+ val , /* val */
693+ NULL , 0 ,
694+ NULL , 0 ,
695+ secp256k1_generator_h
696+ ) == 1 );
697+ }
689698
690699 /* Different proof sizes are unfortunate but is caused by `min_value` of
691700 * zero being special-cased and encoded more efficiently. */
@@ -708,25 +717,29 @@ static void test_single_value_proof(uint64_t val) {
708717
709718 memset (message_out , 0 , sizeof (message_out ));
710719 m_len_out = sizeof (message_out );
711- CHECK (secp256k1_rangeproof_rewind (
712- ctx ,
713- blind_out , & val_out ,
714- message_out , & m_len_out ,
715- nonce ,
716- & min_val_out , & max_val_out ,
717- & commit ,
718- proof , plen ,
719- NULL , 0 ,
720- secp256k1_generator_h
721- ) == 1 );
722- CHECK (val_out == val );
723- CHECK (min_val_out == val );
724- CHECK (max_val_out == val );
725- CHECK (m_len_out == 0 );
726- CHECK (secp256k1_memcmp_var (blind , blind_out , 32 ) == 0 );
727- for (m_len_out = 0 ; m_len_out < sizeof (message_out ); m_len_out ++ ) {
728- CHECK (message_out [m_len_out ] == 0 );
720+ /* exact-value proofs cannot be rewound */
721+ if (!using_exact_value ) {
722+ CHECK (secp256k1_rangeproof_rewind (
723+ ctx ,
724+ blind_out , & val_out ,
725+ message_out , & m_len_out ,
726+ nonce ,
727+ & min_val_out , & max_val_out ,
728+ & commit ,
729+ proof , plen ,
730+ NULL , 0 ,
731+ secp256k1_generator_h
732+ ) == 1 );
733+ CHECK (val_out == val );
734+ CHECK (min_val_out == val );
735+ CHECK (max_val_out == val );
736+ CHECK (m_len_out == 0 );
737+ CHECK (secp256k1_memcmp_var (blind , blind_out , 32 ) == 0 );
738+ for (m_len_out = 0 ; m_len_out < sizeof (message_out ); m_len_out ++ ) {
739+ CHECK (message_out [m_len_out ] == 0 );
740+ }
729741 }
742+ CHECK (secp256k1_rangeproof_verify_value (ctx , proof , plen , val , & commit , secp256k1_generator_h ));
730743}
731744
732745#define MAX_N_GENS 30
@@ -1045,8 +1058,10 @@ void run_rangeproof_tests(void) {
10451058 test_single_value_proof (0 );
10461059 test_single_value_proof (12345678 );
10471060 test_single_value_proof (UINT64_MAX );
1048- test_single_value_proof (secp256k1_testrand32 ());
1049- test_single_value_proof (((uint64_t ) secp256k1_testrand32 () << 32 ) + secp256k1_testrand32 ());
1061+ for (i = 0 ; i < count / 2 ; i ++ ) {
1062+ test_single_value_proof (secp256k1_testrand32 ());
1063+ test_single_value_proof (((uint64_t ) secp256k1_testrand32 () << 32 ) + secp256k1_testrand32 ());
1064+ }
10501065
10511066 test_rangeproof_fixed_vectors ();
10521067 test_pedersen_commitment_fixed_vector ();
0 commit comments