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