@@ -547,8 +547,95 @@ static void test_rangeproof(void) {
547547 }
548548}
549549
550+ static void test_single_value_proof (uint64_t val ) {
551+ unsigned char proof [5000 ];
552+ secp256k1_pedersen_commitment commit ;
553+ unsigned char blind [32 ];
554+ unsigned char blind_out [32 ];
555+ unsigned char nonce [32 ];
556+ const unsigned char message [1 ] = " " ; /* no message will fit into a single-value proof */
557+ unsigned char message_out [sizeof (proof )] = { 0 };
558+ size_t plen = sizeof (proof );
559+ uint64_t min_val_out = 0 ;
560+ uint64_t max_val_out = 0 ;
561+ uint64_t val_out = 0 ;
562+ size_t m_len_out = 0 ;
563+
564+ secp256k1_testrand256 (blind );
565+ secp256k1_testrand256 (nonce );
566+ CHECK (secp256k1_pedersen_commit (ctx , & commit , blind , val , secp256k1_generator_h ));
567+
568+ CHECK (secp256k1_rangeproof_sign (
569+ ctx ,
570+ proof , & plen ,
571+ val , /* min_val */
572+ & commit , blind , nonce ,
573+ -1 , /* exp: -1 is magic value to indicate a single-value proof */
574+ 0 , /* min_bits */
575+ val , /* val */
576+ message , sizeof (message ), /* Will cause this to fail */
577+ NULL , 0 ,
578+ secp256k1_generator_h
579+ ) == 0 );
580+
581+ plen = sizeof (proof );
582+ CHECK (secp256k1_rangeproof_sign (
583+ ctx ,
584+ proof , & plen ,
585+ val , /* min_val */
586+ & commit , blind , nonce ,
587+ -1 , /* exp: -1 is magic value to indicate a single-value proof */
588+ 0 , /* min_bits */
589+ val , /* val */
590+ NULL , 0 ,
591+ NULL , 0 ,
592+ secp256k1_generator_h
593+ ) == 1 );
594+
595+ /* Different proof sizes are unfortunate but is caused by `min_value` of
596+ * zero being special-cased and encoded more efficiently. */
597+ if (val == 0 ) {
598+ CHECK (plen == 65 );
599+ } else {
600+ CHECK (plen == 73 );
601+ }
602+
603+ CHECK (secp256k1_rangeproof_verify (
604+ ctx ,
605+ & min_val_out , & max_val_out ,
606+ & commit ,
607+ proof , plen ,
608+ NULL , 0 ,
609+ secp256k1_generator_h
610+ ) == 1 );
611+ CHECK (min_val_out == val );
612+ CHECK (max_val_out == val );
613+
614+ memset (message_out , 0 , sizeof (message_out ));
615+ m_len_out = sizeof (message_out );
616+ CHECK (secp256k1_rangeproof_rewind (
617+ ctx ,
618+ blind_out , & val_out ,
619+ message_out , & m_len_out ,
620+ nonce ,
621+ & min_val_out , & max_val_out ,
622+ & commit ,
623+ proof , plen ,
624+ NULL , 0 ,
625+ secp256k1_generator_h
626+ ));
627+ CHECK (val_out == val );
628+ CHECK (min_val_out == val );
629+ CHECK (max_val_out == val );
630+ CHECK (m_len_out == 0 );
631+ CHECK (memcmp (blind , blind_out , 32 ) == 0 );
632+ for (m_len_out = 0 ; m_len_out < sizeof (message_out ); m_len_out ++ ) {
633+ CHECK (message_out [m_len_out ] == 0 );
634+ }
635+ }
636+
550637#define MAX_N_GENS 30
551- void test_multiple_generators (void ) {
638+ static void test_multiple_generators (void ) {
552639 const size_t n_inputs = (secp256k1_testrand32 () % (MAX_N_GENS / 2 )) + 1 ;
553640 const size_t n_outputs = (secp256k1_testrand32 () % (MAX_N_GENS / 2 )) + 1 ;
554641 const size_t n_generators = n_inputs + n_outputs ;
@@ -610,7 +697,18 @@ void test_multiple_generators(void) {
610697}
611698
612699void test_rangeproof_fixed_vectors (void ) {
613- const unsigned char vector_1 [] = {
700+ size_t i ;
701+ unsigned char blind [32 ];
702+ uint64_t value ;
703+ uint64_t min_value ;
704+ uint64_t max_value ;
705+ secp256k1_pedersen_commitment pc ;
706+ unsigned char message [4000 ] = {0 };
707+ size_t m_len = sizeof (message );
708+
709+ /* Vector 1: no message */
710+ {
711+ static const unsigned char vector_1 [] = {
614712 0x62 , 0x07 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x56 , 0x02 , 0x2a , 0x5c , 0x42 , 0x0e , 0x1d ,
615713 0x51 , 0xe1 , 0xb7 , 0xf3 , 0x69 , 0x04 , 0xb5 , 0xbb , 0x9b , 0x41 , 0x66 , 0x14 , 0xf3 , 0x64 , 0x42 , 0x26 ,
616714 0xe3 , 0xa7 , 0x6a , 0x06 , 0xbb , 0xa8 , 0x5a , 0x49 , 0x6f , 0x19 , 0x76 , 0xfb , 0xe5 , 0x75 , 0x77 , 0x88 ,
@@ -653,25 +751,175 @@ void test_rangeproof_fixed_vectors(void) {
653751 0xa6 , 0x45 , 0xf6 , 0xce , 0xcf , 0x48 , 0xf6 , 0x1e , 0x3d , 0xd2 , 0xcf , 0xcb , 0x3a , 0xcd , 0xbb , 0x92 ,
654752 0x29 , 0x24 , 0x16 , 0x7f , 0x8a , 0xa8 , 0x5c , 0x0c , 0x45 , 0x71 , 0x33
655753 };
656- const unsigned char commit_1 [] = {
754+ static const unsigned char commit_1 [] = {
657755 0x08 ,
658756 0xf5 , 0x1e , 0x0d , 0xc5 , 0x86 , 0x78 , 0x51 , 0xa9 , 0x00 , 0x00 , 0xef , 0x4d , 0xe2 , 0x94 , 0x60 , 0x89 ,
659757 0x83 , 0x04 , 0xb4 , 0x0e , 0x90 , 0x10 , 0x05 , 0x1c , 0x7f , 0xd7 , 0x33 , 0x92 , 0x1f , 0xe7 , 0x74 , 0x59
660758 };
661- uint64_t min_value_1 ;
662- uint64_t max_value_1 ;
663- secp256k1_pedersen_commitment pc ;
759+ static const unsigned char blind_1 [] = {
760+ 0x98 , 0x44 , 0xfc , 0x7a , 0x64 , 0xa9 , 0xca , 0xdf , 0xf3 , 0x2f , 0x9f , 0x02 , 0xba , 0x46 , 0xc7 , 0xd9 ,
761+ 0x77 , 0x47 , 0xa4 , 0xd3 , 0x53 , 0x17 , 0xc6 , 0x44 , 0x30 , 0x73 , 0x84 , 0xeb , 0x1f , 0xbe , 0xa1 , 0xfb
762+ };
664763
665764 CHECK (secp256k1_pedersen_commitment_parse (ctx , & pc , commit_1 ));
666-
667765 CHECK (secp256k1_rangeproof_verify (
668766 ctx ,
669- & min_value_1 , & max_value_1 ,
767+ & min_value , & max_value ,
670768 & pc ,
671769 vector_1 , sizeof (vector_1 ),
672770 NULL , 0 ,
673771 secp256k1_generator_h
674772 ));
773+ CHECK (min_value == 86 );
774+ CHECK (max_value == 25586 );
775+
776+ CHECK (secp256k1_rangeproof_rewind (
777+ ctx ,
778+ blind , & value ,
779+ message , & m_len ,
780+ pc .data ,
781+ & min_value , & max_value ,
782+ & pc ,
783+ vector_1 , sizeof (vector_1 ),
784+ NULL , 0 ,
785+ secp256k1_generator_h
786+ ));
787+
788+ CHECK (memcmp (blind , blind_1 , 32 ) == 0 );
789+ CHECK (value == 86 );
790+ CHECK (min_value == 86 );
791+ CHECK (max_value == 25586 );
792+ CHECK (m_len == 448 ); /* length of the sidechannel in the proof */
793+ for (i = 0 ; i < m_len ; i ++ ) {
794+ /* No message encoded in this vector */
795+ CHECK (message [i ] == 0 );
796+ }
797+ }
798+
799+ /* Vector 2: embedded message */
800+ {
801+ static const unsigned char vector_2 [] = {
802+ 0x40 , 0x03 , 0x00 , 0x90 , 0x1a , 0x61 , 0x64 , 0xbb , 0x85 , 0x1a , 0x78 , 0x35 , 0x1e , 0xe0 , 0xd5 , 0x96 ,
803+ 0x71 , 0x0f , 0x18 , 0x8e , 0xf3 , 0x33 , 0xf0 , 0x75 , 0xfe , 0xd6 , 0xc6 , 0x11 , 0x6b , 0x42 , 0x89 , 0xea ,
804+ 0xa2 , 0x0c , 0x89 , 0x25 , 0x37 , 0x81 , 0x10 , 0xf9 , 0xf0 , 0x9b , 0xda , 0x68 , 0x2a , 0xd9 , 0x2e , 0x0c ,
805+ 0x45 , 0x17 , 0x54 , 0x6d , 0x02 , 0xd2 , 0x21 , 0x5d , 0xbc , 0x10 , 0xf8 , 0x8f , 0xf1 , 0x92 , 0x40 , 0xa9 ,
806+ 0xc7 , 0x24 , 0x00 , 0x1b , 0xc8 , 0x75 , 0x0f , 0xf6 , 0x8f , 0x93 , 0x8b , 0x78 , 0x62 , 0x73 , 0x3c , 0x86 ,
807+ 0x4b , 0x61 , 0x7c , 0x0f , 0xc6 , 0x41 , 0xc9 , 0xb3 , 0xc1 , 0x30 , 0x7f , 0xd4 , 0xee , 0x9f , 0x37 , 0x08 ,
808+ 0x9b , 0x64 , 0x23 , 0xd5 , 0xe6 , 0x1a , 0x03 , 0x54 , 0x74 , 0x9b , 0x0b , 0xae , 0x6f , 0x2b , 0x1e , 0xf5 ,
809+ 0x40 , 0x44 , 0xaa , 0x12 , 0xe8 , 0xbd , 0xe0 , 0xa6 , 0x85 , 0x89 , 0xf1 , 0xa9 , 0xd0 , 0x3f , 0x2e , 0xc6 ,
810+ 0x1f , 0x11 , 0xf5 , 0x44 , 0x69 , 0x99 , 0x31 , 0x10 , 0x2e , 0x64 , 0xc6 , 0x44 , 0xdb , 0x47 , 0x06 , 0x6d ,
811+ 0xd5 , 0xf2 , 0x8d , 0x19 , 0x00 , 0x39 , 0xb8 , 0xca , 0xda , 0x5c , 0x1d , 0x83 , 0xbd , 0xa3 , 0x6d , 0xbf ,
812+ 0x97 , 0xdd , 0x83 , 0x86 , 0xc9 , 0x56 , 0xe2 , 0xbb , 0x37 , 0x4b , 0x2d , 0xb5 , 0x9d , 0xf2 , 0x7a , 0x6a ,
813+ 0x25 , 0x47 , 0xfa , 0x03 , 0x05 , 0xc5 , 0xda , 0x73 , 0xe1 , 0x96 , 0x15 , 0x21 , 0x23 , 0xe5 , 0xef , 0x55 ,
814+ 0x36 , 0xdd , 0xf1 , 0xb1 , 0x3f , 0x33 , 0x1a , 0x91 , 0x6c , 0x73 , 0x64 , 0xd3 , 0x88 , 0xe7 , 0xc6 , 0xc9 ,
815+ 0x04 , 0x29 , 0xae , 0x55 , 0x27 , 0xa0 , 0x80 , 0x60 , 0xaf , 0x0c , 0x09 , 0x2f , 0xc8 , 0x1b , 0xe6 , 0x16 ,
816+ 0x9e , 0xed , 0x29 , 0xc7 , 0x93 , 0xce , 0xc7 , 0x0d , 0xdf , 0x1f , 0x28 , 0xba , 0xf3 , 0x38 , 0xc3 , 0xaa ,
817+ 0x99 , 0xd9 , 0x21 , 0x41 , 0xb8 , 0x10 , 0xa5 , 0x48 , 0x37 , 0xec , 0x60 , 0xda , 0x64 , 0x5a , 0x73 , 0x55 ,
818+ 0xd7 , 0xff , 0x23 , 0xfa , 0xf6 , 0xc6 , 0xf4 , 0xe2 , 0xca , 0x99 , 0x2f , 0x30 , 0x36 , 0x48 , 0x73 , 0x8b ,
819+ 0x57 , 0xa6 , 0x62 , 0x12 , 0xa3 , 0xe7 , 0x5c , 0xa8 , 0xd1 , 0xe6 , 0x85 , 0x05 , 0x59 , 0xfe , 0x2b , 0x44 ,
820+ 0xe4 , 0x73 , 0x1c , 0xc3 , 0x56 , 0x32 , 0x07 , 0x65 , 0x4a , 0x58 , 0xaf , 0x2b , 0x3f , 0x36 , 0xca , 0xb4 ,
821+ 0x1d , 0x5c , 0x2a , 0x46 , 0x1f , 0xf7 , 0x63 , 0x59 , 0x4f , 0x2b , 0xd0 , 0xf6 , 0xfc , 0xcf , 0x04 , 0x09 ,
822+ 0xb7 , 0x65 , 0x1b
823+ };
824+ static const unsigned char commit_2 [] = {
825+ 0x09 ,
826+ 0x25 , 0xa4 , 0xbd , 0xc4 , 0x57 , 0x69 , 0xeb , 0x4f , 0x34 , 0x0f , 0xea , 0xb8 , 0xe4 , 0x72 , 0x04 , 0x54 ,
827+ 0x06 , 0xe5 , 0xd6 , 0x85 , 0x15 , 0x42 , 0xea , 0x6e , 0x1d , 0x11 , 0x11 , 0x9c , 0x56 , 0xf8 , 0x10 , 0x45
828+ };
829+ static const unsigned char blind_2 [] = {
830+ 0xdc , 0x79 , 0x07 , 0x89 , 0x2d , 0xc4 , 0xe3 , 0x76 , 0xf9 , 0x13 , 0x38 , 0xd6 , 0x4b , 0x46 , 0xed , 0x9d ,
831+ 0x9b , 0xf6 , 0x70 , 0x3d , 0x04 , 0xcf , 0x96 , 0x8c , 0xfd , 0xb5 , 0xff , 0x0a , 0x06 , 0xc7 , 0x08 , 0x8b
832+ };
833+ static const unsigned char message_2 [] = "When I see my own likeness in the depths of someone else's consciousness, I always experience a moment of panic." ;
834+
835+ CHECK (secp256k1_pedersen_commitment_parse (ctx , & pc , commit_2 ));
836+ CHECK (secp256k1_rangeproof_verify (
837+ ctx ,
838+ & min_value , & max_value ,
839+ & pc ,
840+ vector_2 , sizeof (vector_2 ),
841+ NULL , 0 ,
842+ secp256k1_generator_h
843+ ));
844+ CHECK (min_value == 0 );
845+ CHECK (max_value == 15 );
846+
847+ CHECK (secp256k1_rangeproof_rewind (
848+ ctx ,
849+ blind , & value ,
850+ message , & m_len ,
851+ pc .data ,
852+ & min_value , & max_value ,
853+ & pc ,
854+ vector_2 , sizeof (vector_2 ),
855+ NULL , 0 ,
856+ secp256k1_generator_h
857+ ));
858+
859+ CHECK (memcmp (blind , blind_2 , 32 ) == 0 );
860+ CHECK (value == 11 );
861+ CHECK (min_value == 0 );
862+ CHECK (max_value == 15 );
863+ CHECK (m_len == 192 ); /* length of the sidechannel in the proof */
864+ CHECK (memcmp (message , message_2 , sizeof (message_2 )) == 0 );
865+ for (i = sizeof (message_2 ); i < m_len ; i ++ ) {
866+ /* No message encoded in this vector */
867+ CHECK (message [i ] == 0 );
868+ }
869+ }
870+
871+ /* Vector 3: single-value proof of UINT64_MAX */
872+ {
873+ static const unsigned char vector_3 [] = {
874+ 0x20 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xdc , 0x7d , 0x0b , 0x79 , 0x0e , 0xaf , 0x41 ,
875+ 0xa5 , 0x8e , 0x9b , 0x0c , 0x5b , 0xa3 , 0xee , 0x7d , 0xfd , 0x3d , 0x6b , 0xf3 , 0xac , 0x04 , 0x8a , 0x43 ,
876+ 0x75 , 0xb0 , 0xb7 , 0x0e , 0x92 , 0xd7 , 0xdf , 0xf0 , 0x76 , 0xc4 , 0xa5 , 0xb6 , 0x2f , 0xf1 , 0xb5 , 0xfb ,
877+ 0xb4 , 0xb6 , 0x29 , 0xea , 0x34 , 0x9b , 0x16 , 0x30 , 0x0d , 0x06 , 0xf1 , 0xb4 , 0x3f , 0x0d , 0x73 , 0x59 ,
878+ 0x75 , 0xbf , 0x5d , 0x19 , 0x59 , 0xef , 0x11 , 0xf0 , 0xbf
879+ };
880+ static const unsigned char commit_3 [] = {
881+ 0x08 ,
882+ 0xc7 , 0xea , 0x40 , 0x7d , 0x26 , 0x38 , 0xa2 , 0x99 , 0xb9 , 0x40 , 0x22 , 0x78 , 0x17 , 0x57 , 0x65 , 0xb3 ,
883+ 0x36 , 0x82 , 0x18 , 0x42 , 0xc5 , 0x57 , 0x04 , 0x5e , 0x58 , 0x5e , 0xf6 , 0x40 , 0x8b , 0x24 , 0x73 , 0x10
884+ };
885+ static const unsigned char nonce_3 [] = {
886+ 0x84 , 0x50 , 0x94 , 0x69 , 0xa3 , 0x4b , 0x6c , 0x62 , 0x1a , 0xc7 , 0xe2 , 0x0e , 0x07 , 0x9a , 0x6f , 0x85 ,
887+ 0x5f , 0x26 , 0x50 , 0xcd , 0x88 , 0x5a , 0x9f , 0xaa , 0x23 , 0x5e , 0x0a , 0xe0 , 0x7e , 0xc5 , 0xe9 , 0xf1
888+ };
889+ static const unsigned char blind_3 [] = {
890+ 0x68 , 0x89 , 0x47 , 0x8c , 0x77 , 0xec , 0xcc , 0x2b , 0x65 , 0x01 , 0x78 , 0x6b , 0x06 , 0x8b , 0x38 , 0x94 ,
891+ 0xc0 , 0x6b , 0x9b , 0x4c , 0x02 , 0xa6 , 0xc8 , 0xf6 , 0xc0 , 0x34 , 0xea , 0x35 , 0x57 , 0xf4 , 0xe1 , 0x37
892+ };
893+
894+ CHECK (secp256k1_pedersen_commitment_parse (ctx , & pc , commit_3 ));
895+ CHECK (secp256k1_rangeproof_verify (
896+ ctx ,
897+ & min_value , & max_value ,
898+ & pc ,
899+ vector_3 , sizeof (vector_3 ),
900+ NULL , 0 ,
901+ secp256k1_generator_h
902+ ));
903+ CHECK (min_value == UINT64_MAX );
904+ CHECK (max_value == UINT64_MAX );
905+
906+ CHECK (secp256k1_rangeproof_rewind (
907+ ctx ,
908+ blind , & value ,
909+ message , & m_len ,
910+ nonce_3 ,
911+ & min_value , & max_value ,
912+ & pc ,
913+ vector_3 , sizeof (vector_3 ),
914+ NULL , 0 ,
915+ secp256k1_generator_h
916+ ));
917+ CHECK (memcmp (blind , blind_3 , 32 ) == 0 );
918+ CHECK (value == UINT64_MAX );
919+ CHECK (min_value == UINT64_MAX );
920+ CHECK (max_value == UINT64_MAX );
921+ CHECK (m_len == 0 );
922+ }
675923}
676924
677925void test_pedersen_commitment_fixed_vector (void ) {
@@ -696,6 +944,11 @@ void test_pedersen_commitment_fixed_vector(void) {
696944void run_rangeproof_tests (void ) {
697945 int i ;
698946 test_api ();
947+
948+ test_single_value_proof (0 );
949+ test_single_value_proof (12345678 );
950+ test_single_value_proof (UINT64_MAX );
951+
699952 test_rangeproof_fixed_vectors ();
700953 test_pedersen_commitment_fixed_vector ();
701954 for (i = 0 ; i < count / 2 + 1 ; i ++ ) {
0 commit comments