@@ -68,24 +68,24 @@ pub fn cli_app() -> Command {
6868pub struct ExitConfig {
6969 pub vc_url : SensitiveUrl ,
7070 pub vc_token_path : PathBuf ,
71- pub validators_to_exit : PublicKeyBytes ,
71+ pub validators_to_exit : Vec < PublicKeyBytes > ,
7272 pub beacon_url : Option < SensitiveUrl > ,
7373 pub exit_epoch : Option < Epoch > ,
7474}
7575
7676impl ExitConfig {
7777 fn from_cli ( matches : & ArgMatches ) -> Result < Self , String > {
78- // let validator_to_exit_str = clap_utils::parse_required::<String>(matches, VALIDATOR_FLAG)?;
78+ let validators_to_exit_str = clap_utils:: parse_required :: < String > ( matches, VALIDATOR_FLAG ) ?;
7979
80- // let validators_to_exit = validators_to_exit_str
81- // .split(',')
82- // .map(|s| s.trim().parse())
83- // .collect::<Result<Vec<PublicKeyBytes>, _>>()?;
80+ let validators_to_exit = validators_to_exit_str
81+ . split ( ',' )
82+ . map ( |s| s. trim ( ) . parse ( ) )
83+ . collect :: < Result < Vec < PublicKeyBytes > , _ > > ( ) ?;
8484
8585 Ok ( Self {
8686 vc_url : clap_utils:: parse_required ( matches, VC_URL_FLAG ) ?,
8787 vc_token_path : clap_utils:: parse_required ( matches, VC_TOKEN_FLAG ) ?,
88- validators_to_exit : clap_utils :: parse_required ( matches , VALIDATOR_FLAG ) ? ,
88+ validators_to_exit,
8989 beacon_url : clap_utils:: parse_optional ( matches, BEACON_URL_FLAG ) ?,
9090 exit_epoch : clap_utils:: parse_optional ( matches, EXIT_EPOCH_FLAG ) ?,
9191 } )
@@ -114,47 +114,50 @@ async fn run(config: ExitConfig) -> Result<(), String> {
114114 let ( http_client, validators) = vc_http_client ( vc_url. clone ( ) , & vc_token_path) . await ?;
115115
116116 // Check that the validators_to_exit is in the validator client
117- if !validators
118- . iter ( )
119- . any ( |validator| validator. validating_pubkey == validators_to_exit)
120- {
121- return Err ( format ! ( "Validator {} doesn't exist" , validators_to_exit) ) ;
117+ for validator_to_exit in & validators_to_exit {
118+ if !validators
119+ . iter ( )
120+ . any ( |validator| & validator. validating_pubkey == validator_to_exit)
121+ {
122+ return Err ( format ! ( "Validator {} doesn't exist" , validator_to_exit) ) ;
123+ }
122124 }
123125
124- let exit_message = http_client
125- . post_validator_voluntary_exit ( & validators_to_exit, exit_epoch)
126- . await
127- . map_err ( |e| format ! ( "Failed to generate voluntary exit message: {}" , e) ) ?;
128-
129- let exit_message_json = serde_json:: to_string ( & exit_message. data ) ;
126+ for validator_to_exit in & validators_to_exit {
127+ let exit_message = http_client
128+ . post_validator_voluntary_exit ( validator_to_exit, exit_epoch)
129+ . await
130+ . map_err ( |e| format ! ( "Failed to generate voluntary exit message: {}" , e) ) ?;
130131
131- match exit_message_json {
132- Ok ( json) => println ! ( "{}" , json) ,
133- Err ( e) => eprintln ! ( "Failed to serialize voluntary exit message: {}" , e) ,
134- }
132+ let exit_message_json = serde_json:: to_string ( & exit_message. data ) ;
135133
136- if beacon_url. is_some ( ) {
137- let beacon_node = if let Some ( beacon_url) = beacon_url {
138- BeaconNodeHttpClient :: new (
139- SensitiveUrl :: parse ( beacon_url. as_ref ( ) )
140- . map_err ( |e| format ! ( "Failed to parse beacon http server: {:?}" , e) ) ?,
141- Timeouts :: set_all ( Duration :: from_secs ( 12 ) ) ,
142- )
143- } else {
144- return Err ( "Beacon URL is not provided" . into ( ) ) ;
145- } ;
134+ match exit_message_json {
135+ Ok ( json) => println ! ( "{}" , json) ,
136+ Err ( e) => eprintln ! ( "Failed to serialize voluntary exit message: {}" , e) ,
137+ }
146138
147- beacon_node
148- . post_beacon_pool_voluntary_exits ( & exit_message. data )
149- . await
150- . map_err ( |e| format ! ( "Failed to publish voluntary exit: {}" , e) ) ?;
151- // tokio::time::sleep(std::time::Duration::from_secs(1)).await; // Provides nicer UX.
152- eprintln ! (
153- "Successfully validated and published voluntary exit for validator {}" ,
154- validators_to_exit
155- ) ;
139+ if beacon_url. is_some ( ) {
140+ let beacon_node = if let Some ( ref beacon_url) = beacon_url {
141+ BeaconNodeHttpClient :: new (
142+ SensitiveUrl :: parse ( beacon_url. as_ref ( ) )
143+ . map_err ( |e| format ! ( "Failed to parse beacon http server: {:?}" , e) ) ?,
144+ Timeouts :: set_all ( Duration :: from_secs ( 12 ) ) ,
145+ )
146+ } else {
147+ return Err ( "Beacon URL is not provided" . into ( ) ) ;
148+ } ;
149+
150+ beacon_node
151+ . post_beacon_pool_voluntary_exits ( & exit_message. data )
152+ . await
153+ . map_err ( |e| format ! ( "Failed to publish voluntary exit: {}" , e) ) ?;
154+ // tokio::time::sleep(std::time::Duration::from_secs(1)).await; // Provides nicer UX.
155+ eprintln ! (
156+ "Successfully validated and published voluntary exit for validator {}" ,
157+ validator_to_exit
158+ ) ;
159+ }
156160 }
157-
158161 Ok ( ( ) )
159162}
160163
0 commit comments