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