Fix voluntary exit to work with latest beacon api (#2257)

## Issue Addressed

Also fixes #1932 

## Proposed Changes

Use `ValidatorStatus::ActiveOngoing` instead of `ValidatorStatus::Active` to filter active validators.
Prints extra information regarding successful voluntary exit.
This commit is contained in:
Pawan Dhananjay 2021-03-17 05:09:58 +00:00
parent 015ab7d0a7
commit aae8bbd130

View File

@ -3,7 +3,7 @@ use bls::{Keypair, PublicKey};
use clap::{App, Arg, ArgMatches}; use clap::{App, Arg, ArgMatches};
use environment::Environment; use environment::Environment;
use eth2::{ use eth2::{
types::{GenesisData, StateId, ValidatorId, ValidatorStatus}, types::{GenesisData, StateId, ValidatorData, ValidatorId, ValidatorStatus},
BeaconNodeHttpClient, Url, BeaconNodeHttpClient, Url,
}; };
use eth2_keystore::Keystore; use eth2_keystore::Keystore;
@ -12,6 +12,7 @@ use safe_arith::SafeArith;
use slot_clock::{SlotClock, SystemTimeSlotClock}; use slot_clock::{SlotClock, SystemTimeSlotClock};
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use tokio::time::sleep;
use types::{ChainSpec, Epoch, EthSpec, Fork, VoluntaryExit}; use types::{ChainSpec, Epoch, EthSpec, Fork, VoluntaryExit};
pub const CMD: &str = "exit"; pub const CMD: &str = "exit";
@ -165,6 +166,44 @@ async fn publish_voluntary_exit<E: EthSpec>(
"Did not publish voluntary exit for validator {}. Please check that you entered the correct exit phrase.", "Did not publish voluntary exit for validator {}. Please check that you entered the correct exit phrase.",
keypair.pk keypair.pk
); );
return Ok(());
}
loop {
// Sleep for a slot duration and then check if voluntary exit was processed
// by checking the validator status.
sleep(Duration::from_secs(spec.seconds_per_slot)).await;
let validator_data = get_validator_data(client, &keypair.pk).await?;
match validator_data.status {
ValidatorStatus::ActiveExiting => {
let exit_epoch = validator_data.validator.exit_epoch;
let withdrawal_epoch = validator_data.validator.withdrawable_epoch;
let current_epoch = get_current_epoch::<E>(genesis_data.genesis_time, spec)
.ok_or("Failed to get current epoch. Please check your system time")?;
eprintln!("Voluntary exit has been accepted into the beacon chain, but not yet finalized. \
Finalization may take several minutes or longer. Before finalization there is a low \
probability that the exit may be reverted.");
eprintln!(
"Current epoch: {}, Exit epoch: {}, Withdrawable epoch: {}",
current_epoch, exit_epoch, withdrawal_epoch
);
eprintln!("Please keep your validator running till exit epoch");
eprintln!(
"Exit epoch in approximately {} secs",
(exit_epoch - current_epoch) * spec.seconds_per_slot * E::slots_per_epoch()
);
break;
}
ValidatorStatus::ExitedSlashed | ValidatorStatus::ExitedUnslashed => {
eprintln!(
"Validator has exited on epoch: {}",
validator_data.validator.exit_epoch
);
break;
}
_ => eprintln!("Waiting for voluntary exit to be accepted into the beacon chain..."),
}
} }
Ok(()) Ok(())
@ -179,24 +218,10 @@ async fn get_validator_index_for_exit(
epoch: Epoch, epoch: Epoch,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<u64, String> { ) -> Result<u64, String> {
let validator_data = client let validator_data = get_validator_data(client, validator_pubkey).await?;
.get_beacon_states_validator_id(
StateId::Head,
&ValidatorId::PublicKey(validator_pubkey.into()),
)
.await
.map_err(|e| format!("Failed to get validator details: {:?}", e))?
.ok_or_else(|| {
format!(
"Validator {} is not present in the beacon state. \
Please ensure that your beacon node is synced and the validator has been deposited.",
validator_pubkey
)
})?
.data;
match validator_data.status { match validator_data.status {
ValidatorStatus::Active => { ValidatorStatus::ActiveOngoing => {
let eligible_epoch = validator_data let eligible_epoch = validator_data
.validator .validator
.activation_epoch .activation_epoch
@ -219,6 +244,28 @@ async fn get_validator_index_for_exit(
} }
} }
/// Returns the validator data by querying the beacon node client.
async fn get_validator_data(
client: &BeaconNodeHttpClient,
validator_pubkey: &PublicKey,
) -> Result<ValidatorData, String> {
Ok(client
.get_beacon_states_validator_id(
StateId::Head,
&ValidatorId::PublicKey(validator_pubkey.into()),
)
.await
.map_err(|e| format!("Failed to get validator details: {:?}", e))?
.ok_or_else(|| {
format!(
"Validator {} is not present in the beacon state. \
Please ensure that your beacon node is synced and the validator has been deposited.",
validator_pubkey
)
})?
.data)
}
/// Get genesis data by querying the beacon node client. /// Get genesis data by querying the beacon node client.
async fn get_geneisis_data(client: &BeaconNodeHttpClient) -> Result<GenesisData, String> { async fn get_geneisis_data(client: &BeaconNodeHttpClient) -> Result<GenesisData, String> {
Ok(client Ok(client