16
16
// along with Frost-Federation. If not, see
17
17
// <https://www.gnu.org/licenses/>.
18
18
19
- use crate :: node:: echo_broadcast:: service:: EchoBroadcast ;
20
19
#[ mockall_double:: double]
21
20
use crate :: node:: echo_broadcast:: EchoBroadcastHandle ;
22
21
use crate :: node:: protocol:: { dkg, Protocol } ;
23
22
#[ mockall_double:: double]
24
23
use crate :: node:: reliable_sender:: ReliableSenderHandle ;
25
24
use crate :: node:: State ;
25
+ use crate :: node:: { echo_broadcast:: service:: EchoBroadcast , protocol:: Message } ;
26
26
use frost_secp256k1 as frost;
27
27
use tokio:: time:: { Duration , Instant } ;
28
28
use tower:: ServiceExt ;
@@ -52,40 +52,66 @@ pub async fn run_dkg_trigger(
52
52
}
53
53
}
54
54
55
- /// Triggers the DKG round one protocol.
56
- /// This will return once the round package has been successfully sent to all members .
57
- pub ( crate ) async fn trigger_dkg_round_one (
55
+ /// Build round1 future that the trigger function can use to compose the DKG protocol
56
+ /// This wraps the EchoBroadcast service which further wraps the round_one::Package service .
57
+ fn build_round1_future (
58
58
node_id : String ,
59
- state : State ,
59
+ protocol_service : Protocol ,
60
60
echo_broadcast_handle : EchoBroadcastHandle ,
61
- reliable_sender_handle : ReliableSenderHandle ,
62
- ) {
63
- let protocol_service: Protocol =
64
- Protocol :: new ( node_id. clone ( ) , state. clone ( ) , reliable_sender_handle) ;
61
+ state : State ,
62
+ ) -> impl std:: future:: Future < Output = Result < ( ) , tower:: BoxError > > {
65
63
let echo_broadcast_service = EchoBroadcast :: new (
66
64
protocol_service. clone ( ) ,
67
65
echo_broadcast_handle,
68
- state. clone ( ) ,
66
+ state,
69
67
node_id. clone ( ) ,
70
68
) ;
71
69
70
+ // Build round1 service as future
72
71
log:: info!( "Sending DKG echo broadcast" ) ;
73
72
let echo_broadcast_timeout_service = tower:: ServiceBuilder :: new ( )
74
73
. timeout ( Duration :: from_secs ( 10 ) )
75
74
. service ( echo_broadcast_service) ;
76
75
77
- let round1_future = echo_broadcast_timeout_service
78
- . oneshot ( dkg:: round_one:: PackageMessage :: new ( node_id. clone ( ) , None ) . into ( ) ) ;
79
- // log::info!("DKG Echo broadcast finished");
76
+ echo_broadcast_timeout_service
77
+ . oneshot ( dkg:: round_one:: PackageMessage :: new ( node_id, None ) . into ( ) )
78
+ }
80
79
80
+ /// Build round2 future for use in trigger
81
+ /// This wraps the round_two::Package service into a tower timeout service
82
+ fn build_round2_future (
83
+ node_id : String ,
84
+ protocol_service : Protocol ,
85
+ ) -> impl std:: future:: Future < Output = Result < Option < Message > , tower:: BoxError > > {
86
+ // Build round2 service as future
81
87
log:: info!( "Sending DKG round two message" ) ;
82
88
let round_two_timeout_service = tower:: ServiceBuilder :: new ( )
83
89
. timeout ( Duration :: from_secs ( 10 ) )
84
90
. service ( protocol_service) ;
85
91
86
- let round2_future = round_two_timeout_service
87
- . oneshot ( dkg:: round_two:: PackageMessage :: new ( node_id, None ) . into ( ) ) ;
88
- log:: info!( "DKG round two message finished" ) ;
92
+ round_two_timeout_service. oneshot ( dkg:: round_two:: PackageMessage :: new ( node_id, None ) . into ( ) )
93
+ }
94
+
95
+ /// Triggers the DKG round one protocol.
96
+ /// This will return once the round package has been successfully sent to all members.
97
+ pub ( crate ) async fn trigger_dkg_round_one (
98
+ node_id : String ,
99
+ state : State ,
100
+ echo_broadcast_handle : EchoBroadcastHandle ,
101
+ reliable_sender_handle : ReliableSenderHandle ,
102
+ ) {
103
+ let protocol_service: Protocol =
104
+ Protocol :: new ( node_id. clone ( ) , state. clone ( ) , reliable_sender_handle) ;
105
+
106
+ let round1_future = build_round1_future (
107
+ node_id. clone ( ) ,
108
+ protocol_service. clone ( ) ,
109
+ echo_broadcast_handle,
110
+ state. clone ( ) ,
111
+ ) ;
112
+
113
+ let round2_future = build_round2_future ( node_id. clone ( ) , protocol_service. clone ( ) ) ;
114
+
89
115
let sleep_future = tokio:: time:: sleep ( Duration :: from_secs ( 5 ) ) ;
90
116
91
117
// TODO Improve this to allow round1 to finish as soon as all other parties have sent their round1 message
@@ -107,35 +133,37 @@ pub(crate) async fn trigger_dkg_round_one(
107
133
}
108
134
log:: info!( "Round 2 finished" ) ;
109
135
136
+ // Get packages required to run part3
137
+ match build_key_packages ( & state) . await {
138
+ Ok ( ( key_package, pubkey_package) ) => {
139
+ log:: info!(
140
+ "DKG part3 finished. key_package = {:?}, pubkey_package = {:?}" ,
141
+ key_package,
142
+ pubkey_package
143
+ ) ;
144
+ }
145
+ Err ( e) => {
146
+ log:: error!( "Error running DKG part3: {:?}" , e) ;
147
+ }
148
+ }
149
+ }
150
+
151
+ /// Build final key packages using frost dkg round3
152
+ /// Get all the required packages from node::state::dkg_state and then build the key package.
153
+ /// The function returns any error as they are, so they should be handled by the caller.
154
+ async fn build_key_packages (
155
+ state : & State ,
156
+ ) -> Result < ( frost:: keys:: KeyPackage , frost:: keys:: PublicKeyPackage ) , Box < dyn std:: error:: Error > > {
110
157
let round2_secret_package = state
111
158
. dkg_state
112
159
. get_round2_secret_package ( )
113
- . await
114
- . unwrap ( )
115
- . unwrap ( ) ;
116
- let round1_packages = state
117
- . dkg_state
118
- . get_received_round1_packages ( )
119
- . await
120
- . unwrap ( ) ;
121
- let round2_packages = state
122
- . dkg_state
123
- . get_received_round2_packages ( )
124
- . await
125
- . unwrap ( ) ;
126
- let dkg_result =
127
- frost:: keys:: dkg:: part3 ( & round2_secret_package, & round1_packages, & round2_packages) ;
128
-
129
- if dkg_result. is_err ( ) {
130
- log:: error!( "Error running DKG part3 {:?}" , dkg_result. err( ) ) ;
131
- return ;
132
- }
133
- let ( key_package, pubkey_package) = dkg_result. unwrap ( ) ;
134
- log:: info!(
135
- "DKG part3 finished. key_package = {:?}, pubkey_package = {:?}" ,
136
- key_package,
137
- pubkey_package
138
- ) ;
160
+ . await ?
161
+ . ok_or ( "No round2 secret package" ) ?;
162
+ let round1_packages = state. dkg_state . get_received_round1_packages ( ) . await ?;
163
+ let round2_packages = state. dkg_state . get_received_round2_packages ( ) . await ?;
164
+
165
+ frost:: keys:: dkg:: part3 ( & round2_secret_package, & round1_packages, & round2_packages)
166
+ . map_err ( |e| e. into ( ) )
139
167
}
140
168
141
169
#[ cfg( test) ]
0 commit comments