@@ -860,7 +860,9 @@ impl From<spongefish::DomainSeparatorMismatch> for VessError {
860
860
#[ cfg( test) ]
861
861
mod tests {
862
862
use super :: * ;
863
+ use crate :: traits:: dkg:: KeyResharing ;
863
864
use ark_bls12_381:: { Fr , G1Projective } ;
865
+ use ark_ec:: PrimeGroup ;
864
866
use ark_std:: {
865
867
UniformRand ,
866
868
rand:: { SeedableRng , rngs:: StdRng } ,
@@ -872,22 +874,25 @@ mod tests {
872
874
873
875
type Vss = FeldmanVss < G1Projective > ;
874
876
877
+ /// Helper function to create a test committee with specified parameters
878
+ fn create_test_committee ( epoch : u64 , size : usize ) -> multisig:: Committee {
879
+ let keypairs: Vec < multisig:: Keypair > =
880
+ ( 0 ..size) . map ( |_| multisig:: Keypair :: generate ( ) ) . collect ( ) ;
881
+ multisig:: Committee :: new (
882
+ epoch,
883
+ keypairs
884
+ . iter ( )
885
+ . enumerate ( )
886
+ . map ( |( i, kp) | ( i as u8 , kp. public_key ( ) ) ) ,
887
+ )
888
+ }
889
+
875
890
fn test_vess_correctness_helper ( vess : ShoupVess < G1Projective > ) {
876
891
let rng = & mut StdRng :: seed_from_u64 ( 0 ) ;
877
892
let secret = Fr :: rand ( rng) ;
878
893
879
894
// Create a test committee
880
- let committee_size = 13 ;
881
- let keypairs: Vec < multisig:: Keypair > = ( 0 ..committee_size)
882
- . map ( |_| multisig:: Keypair :: generate ( ) )
883
- . collect ( ) ;
884
- let committee = multisig:: Committee :: new (
885
- 0u64 ,
886
- keypairs
887
- . iter ( )
888
- . enumerate ( )
889
- . map ( |( i, kp) | ( i as u8 , kp. public_key ( ) ) ) ,
890
- ) ;
895
+ let committee = create_test_committee ( 0 , 13 ) ;
891
896
let n = committee. size ( ) . get ( ) ;
892
897
893
898
let recv_sks: Vec < mre:: DecryptionKey < G1Projective > > =
@@ -945,4 +950,185 @@ mod tests {
945
950
assert ! ( subsets. insert( subset) ) ;
946
951
}
947
952
}
953
+
954
+ /// Test VESS resharing functionality with comprehensive verification
955
+ #[ test]
956
+ fn test_vess_resharing_correctness ( ) {
957
+ test_vess_resharing_helper ( ShoupVess :: new_fast ( ) ) ;
958
+ test_vess_resharing_helper ( ShoupVess :: new_short ( ) ) ;
959
+ }
960
+
961
+ /// Helper function for testing VESS resharing with different parameter sets
962
+ fn test_vess_resharing_helper ( vess : ShoupVess < G1Projective > ) {
963
+ let rng = & mut StdRng :: seed_from_u64 ( 42 ) ;
964
+
965
+ // Test multiple scenarios with different committee sizes
966
+ let test_scenarios = vec ! [
967
+ ( 7 , 7 ) , // Same committee size
968
+ ( 5 , 8 ) , // Expanding committee
969
+ ( 9 , 6 ) , // Shrinking committee
970
+ ( 6 , 7 ) , // Mixed changes
971
+ ] ;
972
+
973
+ for ( old_n, new_n) in test_scenarios {
974
+ run_vess_resharing_scenario ( & vess, old_n, new_n, rng) ;
975
+ }
976
+ }
977
+
978
+ /// Core test logic for a single VESS resharing scenario
979
+ fn run_vess_resharing_scenario (
980
+ vess : & ShoupVess < G1Projective > ,
981
+ old_n : usize ,
982
+ new_n : usize ,
983
+ rng : & mut StdRng ,
984
+ ) {
985
+ // Step 1: Set up old committee and perform initial VSS
986
+ let old_committee = create_test_committee ( 0 , old_n) ;
987
+ let secret = Fr :: rand ( rng) ;
988
+ let old_vss_pp = FeldmanVssPublicParam :: from ( & old_committee) ;
989
+ let ( old_shares, old_commitment) = Vss :: share ( & old_vss_pp, rng, secret) ;
990
+
991
+ // Step 2: Set up new committee
992
+ let new_committee = create_test_committee ( 1 , new_n) ;
993
+ let new_vss_pp = FeldmanVssPublicParam :: from ( & new_committee) ;
994
+
995
+ // Generate encryption keys for new committee members
996
+ let new_recv_sks: Vec < mre:: DecryptionKey < G1Projective > > =
997
+ repeat_with ( || mre:: DecryptionKey :: rand ( rng) )
998
+ . take ( new_n)
999
+ . collect ( ) ;
1000
+ let new_recv_pks: BTreeMap < usize , mre:: EncryptionKey < G1Projective > > = new_recv_sks
1001
+ . iter ( )
1002
+ . enumerate ( )
1003
+ . map ( |( i, sk) | ( i, mre:: EncryptionKey :: from ( sk) ) )
1004
+ . collect ( ) ;
1005
+ let new_labeled_sks: Vec < LabeledDecryptionKey < G1Projective > > = new_recv_sks
1006
+ . into_iter ( )
1007
+ . enumerate ( )
1008
+ . map ( |( i, sk) | sk. label ( i) )
1009
+ . collect ( ) ;
1010
+
1011
+ // Step 3: Perform resharing for each old committee member
1012
+ let aad = b"reshare_test_associated_data" ;
1013
+ let mut reshare_dealings = Vec :: new ( ) ;
1014
+
1015
+ // Each old committee member creates encrypted reshares
1016
+ for ( sender_idx, old_share) in old_shares. iter ( ) . enumerate ( ) {
1017
+ // Derive the public share for this sender from the old committee
1018
+ let sender_pub_share = G1Projective :: generator ( ) * old_shares[ sender_idx] ;
1019
+
1020
+ // Create VESS encrypted reshares using the public encrypt_reshares API
1021
+ let ( reshare_ct, reshare_comm) = vess
1022
+ . encrypt_reshares ( & new_committee, new_recv_pks. values ( ) , * old_share, aad)
1023
+ . expect ( "Reshare encryption should succeed" ) ;
1024
+
1025
+ // Step 4: Verify the encrypted reshares
1026
+ assert ! (
1027
+ vess. verify_reshares(
1028
+ & new_committee,
1029
+ new_recv_pks. values( ) ,
1030
+ & reshare_ct,
1031
+ & reshare_comm,
1032
+ aad,
1033
+ sender_pub_share,
1034
+ )
1035
+ . is_ok( ) ,
1036
+ "Reshare verification should succeed for sender {sender_idx}"
1037
+ ) ;
1038
+
1039
+ reshare_dealings. push ( ( reshare_ct, reshare_comm, sender_pub_share) ) ;
1040
+ }
1041
+
1042
+ // Step 5: Decrypt reshares and verify they pass FeldmanVss::verify_reshare
1043
+ for ( new_member_idx, new_labeled_sk) in new_labeled_sks. iter ( ) . enumerate ( ) {
1044
+ // Decrypt reshares from each old committee member
1045
+ for ( sender_idx, ( reshare_ct, reshare_comm, sender_pub_share) ) in
1046
+ reshare_dealings. iter ( ) . enumerate ( )
1047
+ {
1048
+ let decrypted_reshare = vess
1049
+ . decrypt_reshare (
1050
+ & new_committee,
1051
+ new_labeled_sk,
1052
+ reshare_ct,
1053
+ aad,
1054
+ * sender_pub_share,
1055
+ )
1056
+ . expect (
1057
+ "Decrypt should succeed, sender: {sender_idx}, receiver: {new_member_idx}" ,
1058
+ ) ;
1059
+
1060
+ assert ! (
1061
+ Vss :: verify_reshare(
1062
+ & old_vss_pp,
1063
+ & new_vss_pp,
1064
+ sender_idx,
1065
+ new_member_idx,
1066
+ & old_commitment,
1067
+ reshare_comm,
1068
+ & decrypted_reshare,
1069
+ )
1070
+ . is_ok( ) ,
1071
+ "Verification should pass, sender: {sender_idx}, receiver: {new_member_idx}"
1072
+ ) ;
1073
+ }
1074
+ }
1075
+ }
1076
+
1077
+ /// Test invalid scenarios that should fail verification
1078
+ #[ test]
1079
+ fn test_vess_resharing_basic_soundness ( ) {
1080
+ let vess = ShoupVess :: new_fast ( ) ;
1081
+ let rng = & mut StdRng :: seed_from_u64 ( 456 ) ;
1082
+
1083
+ // Set up committees
1084
+ let old_committee = create_test_committee ( 0 , 3 ) ;
1085
+ let new_committee = create_test_committee ( 1 , 4 ) ;
1086
+
1087
+ let secret = Fr :: rand ( rng) ;
1088
+ let old_vss_pp = FeldmanVssPublicParam :: from ( & old_committee) ;
1089
+ let ( old_shares, old_commitment) = Vss :: share ( & old_vss_pp, rng, secret) ;
1090
+
1091
+ // Create recipient keys
1092
+ let new_recv_pks: Vec < mre:: EncryptionKey < G1Projective > > = ( 0 ..4 )
1093
+ . map ( |_| mre:: EncryptionKey :: from ( & mre:: DecryptionKey :: rand ( rng) ) )
1094
+ . collect ( ) ;
1095
+
1096
+ let sender_pub_share = Vss :: derive_public_share_unchecked ( 0 , & old_commitment) ;
1097
+ let aad = b"test_failure_cases" ;
1098
+
1099
+ // Create valid encrypted reshares
1100
+ let ( reshare_ct, reshare_comm) = vess
1101
+ . encrypt_reshares ( & new_committee, & new_recv_pks, old_shares[ 0 ] , aad)
1102
+ . unwrap ( ) ;
1103
+
1104
+ // Test 1: Wrong public share should fail verification
1105
+ let wrong_pub_share = G1Projective :: generator ( ) * Fr :: rand ( rng) ;
1106
+ assert ! (
1107
+ vess. verify_reshares(
1108
+ & new_committee,
1109
+ & new_recv_pks,
1110
+ & reshare_ct,
1111
+ & reshare_comm,
1112
+ aad,
1113
+ wrong_pub_share,
1114
+ )
1115
+ . is_err( ) ,
1116
+ "Verification with wrong public share should fail"
1117
+ ) ;
1118
+
1119
+ // Test 2: Wrong AAD should fail verification
1120
+ let wrong_aad = b"wrong_associated_data" ;
1121
+ assert ! (
1122
+ vess. verify_reshares(
1123
+ & new_committee,
1124
+ & new_recv_pks,
1125
+ & reshare_ct,
1126
+ & reshare_comm,
1127
+ wrong_aad,
1128
+ sender_pub_share,
1129
+ )
1130
+ . is_err( ) ,
1131
+ "Verification with wrong AAD should fail"
1132
+ ) ;
1133
+ }
948
1134
}
0 commit comments