@@ -4,13 +4,17 @@ use alloy::{
4
4
primitives:: Address ,
5
5
providers:: { Provider , WalletProvider } ,
6
6
} ;
7
- use anyhow:: { Context , Result , bail} ;
8
- use clap:: Parser ;
7
+ use anyhow:: { Context , Result , anyhow, bail} ;
8
+ use clap:: { Parser , ValueEnum } ;
9
+ use reqwest:: Client ;
9
10
use std:: path:: PathBuf ;
11
+ use std:: time:: Duration ;
10
12
use timeboost_config:: CommitteeConfig ;
11
13
use timeboost_contract:: { CommitteeMemberSol , KeyManager , provider:: build_provider} ;
14
+ use timeboost_crypto:: prelude:: ThresholdEncKey ;
15
+ use timeboost_utils:: enc_key:: ThresholdEncKeyCellAccumulator ;
12
16
use timeboost_utils:: types:: logging;
13
- use tracing:: info;
17
+ use tracing:: { info, warn } ;
14
18
use url:: Url ;
15
19
16
20
#[ derive( Clone , Debug , Parser ) ]
@@ -22,7 +26,7 @@ struct Args {
22
26
) ]
23
27
mnemonic : String ,
24
28
25
- #[ clap( short, long) ]
29
+ #[ clap( short, long, default_value_t = 0 ) ]
26
30
index : u32 ,
27
31
28
32
#[ clap( short, long) ]
@@ -35,6 +39,20 @@ struct Args {
35
39
/// Path to the committee.toml config for the next committee
36
40
#[ clap( short, long) ]
37
41
config : PathBuf ,
42
+
43
+ /// What to register (new committee or threshold enc key?)
44
+ #[ clap( long, short, default_value = "new-committee" ) ]
45
+ action : Action ,
46
+ }
47
+
48
+ /// Specific register action
49
+ #[ derive( Clone , Copy , Debug , Default , ValueEnum ) ]
50
+ enum Action {
51
+ /// register the next committee
52
+ #[ default]
53
+ NewCommittee ,
54
+ /// register the threshold encryption key (when ready)
55
+ ThresholdEncKey ,
38
56
}
39
57
40
58
#[ tokio:: main]
@@ -46,8 +64,6 @@ async fn main() -> Result<()> {
46
64
. await
47
65
. context ( format ! ( "Failed to read config file: {:?}" , & args. config) ) ?;
48
66
49
- info ! ( "Start committee registration" ) ;
50
-
51
67
let provider = build_provider ( args. mnemonic . clone ( ) , args. index , args. url . clone ( ) ) ?;
52
68
let addr = args. key_manager_addr ;
53
69
if provider
@@ -63,40 +79,79 @@ async fn main() -> Result<()> {
63
79
64
80
let contract = KeyManager :: new ( addr, provider) ;
65
81
66
- // prepare input argument from config file
67
- let members = config
68
- . members
69
- . iter ( )
70
- . map ( |m| {
71
- Ok :: < _ , anyhow:: Error > ( CommitteeMemberSol {
72
- sigKey : m. signing_key . to_bytes ( ) . into ( ) ,
73
- dhKey : m. dh_key . as_bytes ( ) . into ( ) ,
74
- dkgKey : m. dkg_enc_key . to_bytes ( ) ?. into ( ) ,
75
- networkAddress : m. public_address . to_string ( ) ,
76
- } )
77
- } )
78
- . collect :: < Result < Vec < _ > , _ > > ( ) ?;
79
-
80
- let timestamp: u64 = config
81
- . effective_timestamp
82
- . as_second ( )
83
- . try_into ( )
84
- . with_context ( || {
85
- format ! (
86
- "failed to convert timestamp {} to u64" ,
87
- config. effective_timestamp
88
- )
89
- } ) ?;
90
-
91
- // send tx and invoke the contract
92
- let _tx_receipt = contract
93
- . setNextCommittee ( timestamp, members)
94
- . send ( )
95
- . await ?
96
- . get_receipt ( )
97
- . await ?;
98
-
99
- let registered_cid = contract. nextCommitteeId ( ) . call ( ) . await ? - 1 ;
100
- info ! ( "Registered new committee with id: {registered_cid}" ) ;
82
+ match args. action {
83
+ Action :: NewCommittee => {
84
+ info ! ( "Start committee registration" ) ;
85
+ // prepare input argument from config file
86
+ let members = config
87
+ . members
88
+ . iter ( )
89
+ . map ( |m| {
90
+ Ok :: < _ , anyhow:: Error > ( CommitteeMemberSol {
91
+ sigKey : m. signing_key . to_bytes ( ) . into ( ) ,
92
+ dhKey : m. dh_key . as_bytes ( ) . into ( ) ,
93
+ dkgKey : m. dkg_enc_key . to_bytes ( ) ?. into ( ) ,
94
+ networkAddress : m. public_address . to_string ( ) ,
95
+ } )
96
+ } )
97
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
98
+
99
+ let timestamp: u64 = config
100
+ . effective_timestamp
101
+ . as_second ( )
102
+ . try_into ( )
103
+ . with_context ( || {
104
+ format ! (
105
+ "failed to convert timestamp {} to u64" ,
106
+ config. effective_timestamp
107
+ )
108
+ } ) ?;
109
+
110
+ // send tx and invoke the contract
111
+ let _tx_receipt = contract
112
+ . setNextCommittee ( timestamp, members)
113
+ . send ( )
114
+ . await ?
115
+ . get_receipt ( )
116
+ . await ?;
117
+
118
+ let registered_cid = contract. nextCommitteeId ( ) . call ( ) . await ? - 1 ;
119
+ info ! ( "Registered new committee with id: {registered_cid}" ) ;
120
+ }
121
+ Action :: ThresholdEncKey => {
122
+ info ! ( "Start threshold encryption key registration" ) ;
123
+ let client = Client :: builder ( ) . timeout ( Duration :: from_secs ( 1 ) ) . build ( ) ?;
124
+ let urls = config
125
+ . members
126
+ . iter ( )
127
+ . map ( |m| {
128
+ let addr = m. http_api . clone ( ) ;
129
+ Url :: parse ( & format ! ( "http://{addr}/v1/encryption-key" ) )
130
+ . with_context ( || format ! ( "parsing {addr} into a url" ) )
131
+ } )
132
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
133
+
134
+ let mut acc = ThresholdEncKeyCellAccumulator :: new ( client, urls. into_iter ( ) ) ;
135
+ let Some ( key) = acc. enc_key ( ) . await else {
136
+ warn ! ( "encryption key not available yet" ) ;
137
+ return Err ( anyhow ! (
138
+ "threshold enc key not available on enough nodes, try later"
139
+ ) ) ;
140
+ } ;
141
+
142
+ let _tx_receipt = contract
143
+ . setThresholdEncryptionKey ( key. to_owned ( ) . to_bytes ( ) ?. into ( ) )
144
+ . send ( )
145
+ . await ?
146
+ . get_receipt ( )
147
+ . await ?;
148
+ assert_eq ! (
149
+ & ThresholdEncKey :: from_bytes( & contract. thresholdEncryptionKey( ) . call( ) . await ?. 0 ) ?,
150
+ key
151
+ ) ;
152
+
153
+ info ! ( "Registered threshold encryption key" ) ;
154
+ }
155
+ }
101
156
Ok ( ( ) )
102
157
}
0 commit comments