@@ -547,8 +547,95 @@ static void test_rangeproof(void) {
547
547
}
548
548
}
549
549
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
+
550
637
#define MAX_N_GENS 30
551
- void test_multiple_generators (void ) {
638
+ static void test_multiple_generators (void ) {
552
639
const size_t n_inputs = (secp256k1_testrand32 () % (MAX_N_GENS / 2 )) + 1 ;
553
640
const size_t n_outputs = (secp256k1_testrand32 () % (MAX_N_GENS / 2 )) + 1 ;
554
641
const size_t n_generators = n_inputs + n_outputs ;
@@ -610,7 +697,18 @@ void test_multiple_generators(void) {
610
697
}
611
698
612
699
void 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 [] = {
614
712
0x62 , 0x07 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x56 , 0x02 , 0x2a , 0x5c , 0x42 , 0x0e , 0x1d ,
615
713
0x51 , 0xe1 , 0xb7 , 0xf3 , 0x69 , 0x04 , 0xb5 , 0xbb , 0x9b , 0x41 , 0x66 , 0x14 , 0xf3 , 0x64 , 0x42 , 0x26 ,
616
714
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) {
653
751
0xa6 , 0x45 , 0xf6 , 0xce , 0xcf , 0x48 , 0xf6 , 0x1e , 0x3d , 0xd2 , 0xcf , 0xcb , 0x3a , 0xcd , 0xbb , 0x92 ,
654
752
0x29 , 0x24 , 0x16 , 0x7f , 0x8a , 0xa8 , 0x5c , 0x0c , 0x45 , 0x71 , 0x33
655
753
};
656
- const unsigned char commit_1 [] = {
754
+ static const unsigned char commit_1 [] = {
657
755
0x08 ,
658
756
0xf5 , 0x1e , 0x0d , 0xc5 , 0x86 , 0x78 , 0x51 , 0xa9 , 0x00 , 0x00 , 0xef , 0x4d , 0xe2 , 0x94 , 0x60 , 0x89 ,
659
757
0x83 , 0x04 , 0xb4 , 0x0e , 0x90 , 0x10 , 0x05 , 0x1c , 0x7f , 0xd7 , 0x33 , 0x92 , 0x1f , 0xe7 , 0x74 , 0x59
660
758
};
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
+ };
664
763
665
764
CHECK (secp256k1_pedersen_commitment_parse (ctx , & pc , commit_1 ));
666
-
667
765
CHECK (secp256k1_rangeproof_verify (
668
766
ctx ,
669
- & min_value_1 , & max_value_1 ,
767
+ & min_value , & max_value ,
670
768
& pc ,
671
769
vector_1 , sizeof (vector_1 ),
672
770
NULL , 0 ,
673
771
secp256k1_generator_h
674
772
));
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
+ }
675
923
}
676
924
677
925
void test_pedersen_commitment_fixed_vector (void ) {
@@ -696,6 +944,11 @@ void test_pedersen_commitment_fixed_vector(void) {
696
944
void run_rangeproof_tests (void ) {
697
945
int i ;
698
946
test_api ();
947
+
948
+ test_single_value_proof (0 );
949
+ test_single_value_proof (12345678 );
950
+ test_single_value_proof (UINT64_MAX );
951
+
699
952
test_rangeproof_fixed_vectors ();
700
953
test_pedersen_commitment_fixed_vector ();
701
954
for (i = 0 ; i < count / 2 + 1 ; i ++ ) {
0 commit comments