@@ -6,9 +6,8 @@ use std::collections::{BTreeMap, HashMap};
6
6
7
7
#[ cfg( test) ]
8
8
use super :: internal_batch_verify_transactions;
9
-
10
9
use super :: { ProposedTransaction , Transaction , TRANSACTION_PUBLIC_KEY_SIZE } ;
11
-
10
+ use crate :: frost_utils :: account_keys :: derive_account_keys ;
12
11
use crate :: test_util:: create_multisig_identities;
13
12
use crate :: transaction:: tests:: split_spender_key:: split_spender_key;
14
13
use crate :: {
@@ -27,6 +26,8 @@ use crate::{
27
26
} ;
28
27
use ff:: Field ;
29
28
use group:: GroupEncoding ;
29
+ use ironfish_frost:: dkg:: { round1 as round1_dkg, round2 as round2_dkg, round3 as round3_dkg} ;
30
+ use ironfish_frost:: participant:: Secret ;
30
31
use ironfish_frost:: {
31
32
frost:: { round2, round2:: SignatureShare , Identifier , Randomizer } ,
32
33
nonces:: deterministic_signing_nonces,
@@ -915,3 +916,195 @@ fn test_add_signature_by_building_transaction() {
915
916
916
917
verify_transaction ( & signed) . expect ( "should be able to verify transaction" ) ;
917
918
}
919
+
920
+ #[ test]
921
+ fn test_dkg_signing ( ) {
922
+ let secret1 = Secret :: random ( thread_rng ( ) ) ;
923
+ let secret2 = Secret :: random ( thread_rng ( ) ) ;
924
+ let secret3 = Secret :: random ( thread_rng ( ) ) ;
925
+ let identity1 = secret1. to_identity ( ) ;
926
+ let identity2 = secret2. to_identity ( ) ;
927
+ let identity3 = secret3. to_identity ( ) ;
928
+ let identities = & [ identity1. clone ( ) , identity2. clone ( ) , identity3. clone ( ) ] ;
929
+
930
+ let ( round1_secret_package_1, package1) = round1_dkg:: round1 (
931
+ & identity1,
932
+ 2 ,
933
+ [ & identity1, & identity2, & identity3] ,
934
+ thread_rng ( ) ,
935
+ )
936
+ . expect ( "round 1 failed" ) ;
937
+
938
+ let ( round1_secret_package_2, package2) = round1_dkg:: round1 (
939
+ & identity2,
940
+ 2 ,
941
+ [ & identity1, & identity2, & identity3] ,
942
+ thread_rng ( ) ,
943
+ )
944
+ . expect ( "round 1 failed" ) ;
945
+
946
+ let ( round1_secret_package_3, package3) = round1_dkg:: round1 (
947
+ & identity3,
948
+ 2 ,
949
+ [ & identity1, & identity2, & identity3] ,
950
+ thread_rng ( ) ,
951
+ )
952
+ . expect ( "round 1 failed" ) ;
953
+
954
+ let ( encrypted_secret_package_1, round2_public_packages_1) = round2_dkg:: round2 (
955
+ & secret1,
956
+ & round1_secret_package_1,
957
+ [ & package1, & package2, & package3] ,
958
+ thread_rng ( ) ,
959
+ )
960
+ . expect ( "round 2 failed" ) ;
961
+
962
+ let ( encrypted_secret_package_2, round2_public_packages_2) = round2_dkg:: round2 (
963
+ & secret2,
964
+ & round1_secret_package_2,
965
+ [ & package1, & package2, & package3] ,
966
+ thread_rng ( ) ,
967
+ )
968
+ . expect ( "round 2 failed" ) ;
969
+
970
+ let ( encrypted_secret_package_3, round2_public_packages_3) = round2_dkg:: round2 (
971
+ & secret3,
972
+ & round1_secret_package_3,
973
+ [ & package1, & package2, & package3] ,
974
+ thread_rng ( ) ,
975
+ )
976
+ . expect ( "round 2 failed" ) ;
977
+
978
+ let ( key_package_1, public_key_package, group_secret_key) = round3_dkg:: round3 (
979
+ & secret1,
980
+ & encrypted_secret_package_1,
981
+ [ & package1, & package2, & package3] ,
982
+ [ & round2_public_packages_2, & round2_public_packages_3] ,
983
+ )
984
+ . expect ( "round 3 failed" ) ;
985
+
986
+ let ( key_package_2, _, _) = round3_dkg:: round3 (
987
+ & secret2,
988
+ & encrypted_secret_package_2,
989
+ [ & package1, & package2, & package3] ,
990
+ [ & round2_public_packages_1, & round2_public_packages_3] ,
991
+ )
992
+ . expect ( "round 3 failed" ) ;
993
+
994
+ let ( key_package_3, _, _) = round3_dkg:: round3 (
995
+ & secret3,
996
+ & encrypted_secret_package_3,
997
+ [ & package1, & package2, & package3] ,
998
+ [ & round2_public_packages_1, & round2_public_packages_2] ,
999
+ )
1000
+ . expect ( "round 3 failed" ) ;
1001
+
1002
+ let account_keys = derive_account_keys ( public_key_package. verifying_key ( ) , & group_secret_key) ;
1003
+ let public_address = account_keys. public_address ;
1004
+
1005
+ // create raw/proposed transaction
1006
+ let in_note = Note :: new ( public_address, 42 , "" , NATIVE_ASSET , public_address) ;
1007
+ let out_note = Note :: new ( public_address, 40 , "" , NATIVE_ASSET , public_address) ;
1008
+ let asset = Asset :: new ( public_address, "Testcoin" , "A really cool coin" )
1009
+ . expect ( "should be able to create an asset" ) ;
1010
+ let value = 5 ;
1011
+ let mint_out_note = Note :: new ( public_address, value, "" , * asset. id ( ) , public_address) ;
1012
+ let witness = make_fake_witness ( & in_note) ;
1013
+
1014
+ let mut transaction = ProposedTransaction :: new ( TransactionVersion :: latest ( ) ) ;
1015
+ transaction
1016
+ . add_spend ( in_note, & witness)
1017
+ . expect ( "add spend to transaction" ) ;
1018
+ assert_eq ! ( transaction. spends. len( ) , 1 ) ;
1019
+ transaction
1020
+ . add_output ( out_note)
1021
+ . expect ( "add output to transaction" ) ;
1022
+ assert_eq ! ( transaction. outputs. len( ) , 1 ) ;
1023
+ transaction
1024
+ . add_mint ( asset, value)
1025
+ . expect ( "add mint to transaction" ) ;
1026
+ transaction
1027
+ . add_output ( mint_out_note)
1028
+ . expect ( "add mint output to transaction" ) ;
1029
+
1030
+ let intended_fee = 1 ;
1031
+ transaction
1032
+ . add_change_notes ( Some ( public_address) , public_address, intended_fee)
1033
+ . expect ( "should be able to add change notes" ) ;
1034
+
1035
+ // build UnsignedTransaction without signing
1036
+ let mut unsigned_transaction = transaction
1037
+ . build (
1038
+ account_keys. proof_authorizing_key ,
1039
+ account_keys. view_key ,
1040
+ account_keys. outgoing_viewing_key ,
1041
+ intended_fee,
1042
+ Some ( account_keys. public_address ) ,
1043
+ )
1044
+ . expect ( "should be able to build unsigned transaction" ) ;
1045
+
1046
+ let transaction_hash = unsigned_transaction
1047
+ . transaction_signature_hash ( )
1048
+ . expect ( "should be able to compute transaction hash" ) ;
1049
+
1050
+ let mut commitments = HashMap :: new ( ) ;
1051
+
1052
+ // simulate signing
1053
+ // commitment generation
1054
+ let identity_keypackages = [
1055
+ ( identity1, key_package_1) ,
1056
+ ( identity2, key_package_2) ,
1057
+ ( identity3, key_package_3) ,
1058
+ ] ;
1059
+ for ( identity, key_package) in identity_keypackages. iter ( ) {
1060
+ let nonces = deterministic_signing_nonces (
1061
+ key_package. signing_share ( ) ,
1062
+ & transaction_hash,
1063
+ identities,
1064
+ ) ;
1065
+ commitments. insert ( identity. clone ( ) , ( & nonces) . into ( ) ) ;
1066
+ }
1067
+
1068
+ let signing_package = unsigned_transaction
1069
+ . signing_package ( commitments)
1070
+ . expect ( "should be able to create signing package" ) ;
1071
+
1072
+ // simulate round 2
1073
+ let mut signature_shares: BTreeMap < Identifier , SignatureShare > = BTreeMap :: new ( ) ;
1074
+ let randomizer =
1075
+ Randomizer :: deserialize ( & unsigned_transaction. public_key_randomness . to_bytes ( ) )
1076
+ . expect ( "should be able to deserialize randomizer" ) ;
1077
+
1078
+ for ( identity, key_package) in identity_keypackages. iter ( ) {
1079
+ let nonces = deterministic_signing_nonces (
1080
+ key_package. signing_share ( ) ,
1081
+ & transaction_hash,
1082
+ identities,
1083
+ ) ;
1084
+ let signature_share = round2:: sign (
1085
+ & signing_package. frost_signing_package ,
1086
+ & nonces,
1087
+ key_package,
1088
+ randomizer,
1089
+ )
1090
+ . expect ( "should be able to create signature share" ) ;
1091
+ signature_shares. insert ( identity. to_frost_identifier ( ) , signature_share) ;
1092
+ }
1093
+
1094
+ // coordinator creates signed transaction
1095
+ let signed_transaction = unsigned_transaction
1096
+ . aggregate_signature_shares (
1097
+ & public_key_package,
1098
+ & signing_package. frost_signing_package ,
1099
+ signature_shares,
1100
+ )
1101
+ . expect ( "should be able to sign transaction" ) ;
1102
+
1103
+ assert_eq ! ( signed_transaction. spends. len( ) , 1 ) ;
1104
+ assert_eq ! ( signed_transaction. outputs. len( ) , 3 ) ;
1105
+ assert_eq ! ( signed_transaction. mints. len( ) , 1 ) ;
1106
+ assert_eq ! ( signed_transaction. burns. len( ) , 0 ) ;
1107
+
1108
+ // verify transaction
1109
+ verify_transaction ( & signed_transaction) . expect ( "should be able to verify transaction" ) ;
1110
+ }
0 commit comments