Update ValidatorStatus to match the v1 API (#2149)
## Issue Addressed N/A ## Proposed Changes We are currently a bit off of the standard API spec because we have [this](https://hackmd.io/bQxMDRt1RbS1TLno8K4NPg?view) proposal implemented for validator status. Based on discussion [here](https://github.com/ethereum/eth2.0-APIs/pull/94), it looks like this won't be added to the spec until v2, so this PR implements [this](https://hackmd.io/ofFJ5gOmQpu1jjHilHbdQQ) validator status logic instead ## Additional Info N/A Co-authored-by: realbigsean <seananderson33@gmail.com>
This commit is contained in:
parent
a764c3b247
commit
5bc93869c8
@ -498,7 +498,6 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
state_id
|
||||
.map_state(&chain, |state| {
|
||||
let epoch = state.current_epoch();
|
||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
||||
let far_future_epoch = chain.spec.far_future_epoch;
|
||||
|
||||
Ok(state
|
||||
@ -522,17 +521,18 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
// filter by status(es) if provided and map the result
|
||||
.filter_map(|(index, (validator, balance))| {
|
||||
let status = api_types::ValidatorStatus::from_validator(
|
||||
Some(validator),
|
||||
validator,
|
||||
epoch,
|
||||
finalized_epoch,
|
||||
far_future_epoch,
|
||||
);
|
||||
|
||||
if query
|
||||
.status
|
||||
.as_ref()
|
||||
.map_or(true, |statuses| statuses.0.contains(&status))
|
||||
{
|
||||
let status_matches =
|
||||
query.status.as_ref().map_or(true, |statuses| {
|
||||
statuses.0.contains(&status)
|
||||
|| statuses.0.contains(&status.superstatus())
|
||||
});
|
||||
|
||||
if status_matches {
|
||||
Some(api_types::ValidatorData {
|
||||
index: index as u64,
|
||||
balance: *balance,
|
||||
@ -577,16 +577,14 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
let validator = state.validators.get(index)?;
|
||||
let balance = *state.balances.get(index)?;
|
||||
let epoch = state.current_epoch();
|
||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
||||
let far_future_epoch = chain.spec.far_future_epoch;
|
||||
|
||||
Some(api_types::ValidatorData {
|
||||
index: index as u64,
|
||||
balance,
|
||||
status: api_types::ValidatorStatus::from_validator(
|
||||
Some(validator),
|
||||
validator,
|
||||
epoch,
|
||||
finalized_epoch,
|
||||
far_future_epoch,
|
||||
),
|
||||
validator: validator.clone(),
|
||||
|
@ -638,7 +638,6 @@ impl ApiTester {
|
||||
|
||||
let expected = state_opt.map(|state| {
|
||||
let epoch = state.current_epoch();
|
||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
||||
let far_future_epoch = self.chain.spec.far_future_epoch;
|
||||
|
||||
let mut validators = Vec::with_capacity(validator_indices.len());
|
||||
@ -649,12 +648,14 @@ impl ApiTester {
|
||||
}
|
||||
let validator = state.validators[i as usize].clone();
|
||||
let status = ValidatorStatus::from_validator(
|
||||
Some(&validator),
|
||||
&validator,
|
||||
epoch,
|
||||
finalized_epoch,
|
||||
far_future_epoch,
|
||||
);
|
||||
if statuses.contains(&status) || statuses.is_empty() {
|
||||
if statuses.contains(&status)
|
||||
|| statuses.is_empty()
|
||||
|| statuses.contains(&status.superstatus())
|
||||
{
|
||||
validators.push(ValidatorData {
|
||||
index: i as u64,
|
||||
balance: state.balances[i as usize],
|
||||
@ -706,16 +707,14 @@ impl ApiTester {
|
||||
|
||||
let expected = {
|
||||
let epoch = state.current_epoch();
|
||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
||||
let far_future_epoch = self.chain.spec.far_future_epoch;
|
||||
|
||||
ValidatorData {
|
||||
index: i as u64,
|
||||
balance: state.balances[i],
|
||||
status: ValidatorStatus::from_validator(
|
||||
Some(&validator),
|
||||
&validator,
|
||||
epoch,
|
||||
finalized_epoch,
|
||||
far_future_epoch,
|
||||
),
|
||||
validator: validator.clone(),
|
||||
@ -1444,18 +1443,19 @@ impl ApiTester {
|
||||
vec![],
|
||||
vec![ValidatorStatus::Active],
|
||||
vec![
|
||||
ValidatorStatus::Unknown,
|
||||
ValidatorStatus::WaitingForEligibility,
|
||||
ValidatorStatus::WaitingForFinality,
|
||||
ValidatorStatus::WaitingInQueue,
|
||||
ValidatorStatus::StandbyForActive,
|
||||
ValidatorStatus::Active,
|
||||
ValidatorStatus::ActiveAwaitingVoluntaryExit,
|
||||
ValidatorStatus::ActiveAwaitingSlashedExit,
|
||||
ValidatorStatus::ExitedVoluntarily,
|
||||
ValidatorStatus::PendingInitialized,
|
||||
ValidatorStatus::PendingQueued,
|
||||
ValidatorStatus::ActiveOngoing,
|
||||
ValidatorStatus::ActiveExiting,
|
||||
ValidatorStatus::ActiveSlashed,
|
||||
ValidatorStatus::ExitedUnslashed,
|
||||
ValidatorStatus::ExitedSlashed,
|
||||
ValidatorStatus::Withdrawable,
|
||||
ValidatorStatus::Withdrawn,
|
||||
ValidatorStatus::WithdrawalPossible,
|
||||
ValidatorStatus::WithdrawalDone,
|
||||
ValidatorStatus::Active,
|
||||
ValidatorStatus::Pending,
|
||||
ValidatorStatus::Exited,
|
||||
ValidatorStatus::Withdrawal,
|
||||
],
|
||||
];
|
||||
interesting
|
||||
|
@ -246,66 +246,84 @@ pub struct ValidatorBalanceData {
|
||||
pub balance: u64,
|
||||
}
|
||||
|
||||
// TODO: This does not currently match the spec, but I'm going to try and change the spec using
|
||||
// Implemented according to what is described here:
|
||||
//
|
||||
// https://hackmd.io/ofFJ5gOmQpu1jjHilHbdQQ
|
||||
//
|
||||
// We expect this to be updated in v2 of the standard api to
|
||||
// this proposal:
|
||||
//
|
||||
// https://hackmd.io/bQxMDRt1RbS1TLno8K4NPg?view
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ValidatorStatus {
|
||||
Unknown,
|
||||
WaitingForEligibility,
|
||||
WaitingForFinality,
|
||||
WaitingInQueue,
|
||||
StandbyForActive,
|
||||
Active,
|
||||
ActiveAwaitingVoluntaryExit,
|
||||
ActiveAwaitingSlashedExit,
|
||||
ExitedVoluntarily,
|
||||
PendingInitialized,
|
||||
PendingQueued,
|
||||
ActiveOngoing,
|
||||
ActiveExiting,
|
||||
ActiveSlashed,
|
||||
ExitedUnslashed,
|
||||
ExitedSlashed,
|
||||
Withdrawable,
|
||||
Withdrawn,
|
||||
WithdrawalPossible,
|
||||
WithdrawalDone,
|
||||
Active,
|
||||
Pending,
|
||||
Exited,
|
||||
Withdrawal,
|
||||
}
|
||||
|
||||
impl ValidatorStatus {
|
||||
pub fn from_validator(
|
||||
validator_opt: Option<&Validator>,
|
||||
epoch: Epoch,
|
||||
finalized_epoch: Epoch,
|
||||
far_future_epoch: Epoch,
|
||||
) -> Self {
|
||||
if let Some(validator) = validator_opt {
|
||||
if validator.is_withdrawable_at(epoch) {
|
||||
ValidatorStatus::Withdrawable
|
||||
} else if validator.is_exited_at(epoch) {
|
||||
pub fn from_validator(validator: &Validator, epoch: Epoch, far_future_epoch: Epoch) -> Self {
|
||||
if validator.is_withdrawable_at(epoch) {
|
||||
if validator.effective_balance == 0 {
|
||||
ValidatorStatus::WithdrawalDone
|
||||
} else {
|
||||
ValidatorStatus::WithdrawalPossible
|
||||
}
|
||||
} else if validator.is_exited_at(epoch) && epoch < validator.withdrawable_epoch {
|
||||
if validator.slashed {
|
||||
ValidatorStatus::ExitedSlashed
|
||||
} else {
|
||||
ValidatorStatus::ExitedUnslashed
|
||||
}
|
||||
} else if validator.is_active_at(epoch) {
|
||||
if validator.exit_epoch < far_future_epoch {
|
||||
if validator.slashed {
|
||||
ValidatorStatus::ExitedSlashed
|
||||
ValidatorStatus::ActiveSlashed
|
||||
} else {
|
||||
ValidatorStatus::ExitedVoluntarily
|
||||
}
|
||||
} else if validator.is_active_at(epoch) {
|
||||
if validator.exit_epoch < far_future_epoch {
|
||||
if validator.slashed {
|
||||
ValidatorStatus::ActiveAwaitingSlashedExit
|
||||
} else {
|
||||
ValidatorStatus::ActiveAwaitingVoluntaryExit
|
||||
}
|
||||
} else {
|
||||
ValidatorStatus::Active
|
||||
}
|
||||
} else if validator.activation_epoch < far_future_epoch {
|
||||
ValidatorStatus::StandbyForActive
|
||||
} else if validator.activation_eligibility_epoch < far_future_epoch {
|
||||
if finalized_epoch < validator.activation_eligibility_epoch {
|
||||
ValidatorStatus::WaitingForFinality
|
||||
} else {
|
||||
ValidatorStatus::WaitingInQueue
|
||||
ValidatorStatus::ActiveExiting
|
||||
}
|
||||
} else {
|
||||
ValidatorStatus::WaitingForEligibility
|
||||
ValidatorStatus::ActiveOngoing
|
||||
}
|
||||
// `pending` statuses are specified as validators where `validator.activation_epoch > current_epoch`.
|
||||
// If this code is reached, this criteria must have been met because `validator.is_active_at(epoch)`,
|
||||
// `validator.is_exited_at(epoch)`, and `validator.is_withdrawable_at(epoch)` all returned false.
|
||||
} else if validator.activation_eligibility_epoch == far_future_epoch {
|
||||
ValidatorStatus::PendingInitialized
|
||||
} else {
|
||||
ValidatorStatus::Unknown
|
||||
ValidatorStatus::PendingQueued
|
||||
}
|
||||
}
|
||||
|
||||
pub fn superstatus(&self) -> Self {
|
||||
match self {
|
||||
ValidatorStatus::PendingInitialized | ValidatorStatus::PendingQueued => {
|
||||
ValidatorStatus::Pending
|
||||
}
|
||||
ValidatorStatus::ActiveOngoing
|
||||
| ValidatorStatus::ActiveExiting
|
||||
| ValidatorStatus::ActiveSlashed => ValidatorStatus::Active,
|
||||
ValidatorStatus::ExitedUnslashed | ValidatorStatus::ExitedSlashed => {
|
||||
ValidatorStatus::Exited
|
||||
}
|
||||
ValidatorStatus::WithdrawalPossible | ValidatorStatus::WithdrawalDone => {
|
||||
ValidatorStatus::Withdrawal
|
||||
}
|
||||
ValidatorStatus::Active
|
||||
| ValidatorStatus::Pending
|
||||
| ValidatorStatus::Exited
|
||||
| ValidatorStatus::Withdrawal => *self,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -315,18 +333,19 @@ impl FromStr for ValidatorStatus {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"unknown" => Ok(ValidatorStatus::Unknown),
|
||||
"waiting_for_eligibility" => Ok(ValidatorStatus::WaitingForEligibility),
|
||||
"waiting_for_finality" => Ok(ValidatorStatus::WaitingForFinality),
|
||||
"waiting_in_queue" => Ok(ValidatorStatus::WaitingInQueue),
|
||||
"standby_for_active" => Ok(ValidatorStatus::StandbyForActive),
|
||||
"active" => Ok(ValidatorStatus::Active),
|
||||
"active_awaiting_voluntary_exit" => Ok(ValidatorStatus::ActiveAwaitingVoluntaryExit),
|
||||
"active_awaiting_slashed_exit" => Ok(ValidatorStatus::ActiveAwaitingSlashedExit),
|
||||
"exited_voluntarily" => Ok(ValidatorStatus::ExitedVoluntarily),
|
||||
"pending_initialized" => Ok(ValidatorStatus::PendingInitialized),
|
||||
"pending_queued" => Ok(ValidatorStatus::PendingQueued),
|
||||
"active_ongoing" => Ok(ValidatorStatus::ActiveOngoing),
|
||||
"active_exiting" => Ok(ValidatorStatus::ActiveExiting),
|
||||
"active_slashed" => Ok(ValidatorStatus::ActiveSlashed),
|
||||
"exited_unslashed" => Ok(ValidatorStatus::ExitedUnslashed),
|
||||
"exited_slashed" => Ok(ValidatorStatus::ExitedSlashed),
|
||||
"withdrawable" => Ok(ValidatorStatus::Withdrawable),
|
||||
"withdrawn" => Ok(ValidatorStatus::Withdrawn),
|
||||
"withdrawal_possible" => Ok(ValidatorStatus::WithdrawalPossible),
|
||||
"withdrawal_done" => Ok(ValidatorStatus::WithdrawalDone),
|
||||
"active" => Ok(ValidatorStatus::Active),
|
||||
"pending" => Ok(ValidatorStatus::Pending),
|
||||
"exited" => Ok(ValidatorStatus::Exited),
|
||||
"withdrawal" => Ok(ValidatorStatus::Withdrawal),
|
||||
_ => Err(format!("{} cannot be parsed as a validator status.", s)),
|
||||
}
|
||||
}
|
||||
@ -335,20 +354,19 @@ impl FromStr for ValidatorStatus {
|
||||
impl fmt::Display for ValidatorStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ValidatorStatus::Unknown => write!(f, "unknown"),
|
||||
ValidatorStatus::WaitingForEligibility => write!(f, "waiting_for_eligibility"),
|
||||
ValidatorStatus::WaitingForFinality => write!(f, "waiting_for_finality"),
|
||||
ValidatorStatus::WaitingInQueue => write!(f, "waiting_in_queue"),
|
||||
ValidatorStatus::StandbyForActive => write!(f, "standby_for_active"),
|
||||
ValidatorStatus::Active => write!(f, "active"),
|
||||
ValidatorStatus::ActiveAwaitingVoluntaryExit => {
|
||||
write!(f, "active_awaiting_voluntary_exit")
|
||||
}
|
||||
ValidatorStatus::ActiveAwaitingSlashedExit => write!(f, "active_awaiting_slashed_exit"),
|
||||
ValidatorStatus::ExitedVoluntarily => write!(f, "exited_voluntarily"),
|
||||
ValidatorStatus::PendingInitialized => write!(f, "pending_initialized"),
|
||||
ValidatorStatus::PendingQueued => write!(f, "pending_queued"),
|
||||
ValidatorStatus::ActiveOngoing => write!(f, "active_ongoing"),
|
||||
ValidatorStatus::ActiveExiting => write!(f, "active_exiting"),
|
||||
ValidatorStatus::ActiveSlashed => write!(f, "active_slashed"),
|
||||
ValidatorStatus::ExitedUnslashed => write!(f, "exited_unslashed"),
|
||||
ValidatorStatus::ExitedSlashed => write!(f, "exited_slashed"),
|
||||
ValidatorStatus::Withdrawable => write!(f, "withdrawable"),
|
||||
ValidatorStatus::Withdrawn => write!(f, "withdrawn"),
|
||||
ValidatorStatus::WithdrawalPossible => write!(f, "withdrawal_possible"),
|
||||
ValidatorStatus::WithdrawalDone => write!(f, "withdrawal_done"),
|
||||
ValidatorStatus::Active => write!(f, "active"),
|
||||
ValidatorStatus::Pending => write!(f, "pending"),
|
||||
ValidatorStatus::Exited => write!(f, "exited"),
|
||||
ValidatorStatus::Withdrawal => write!(f, "withdrawal"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user