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
|
state_id
|
||||||
.map_state(&chain, |state| {
|
.map_state(&chain, |state| {
|
||||||
let epoch = state.current_epoch();
|
let epoch = state.current_epoch();
|
||||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
|
||||||
let far_future_epoch = chain.spec.far_future_epoch;
|
let far_future_epoch = chain.spec.far_future_epoch;
|
||||||
|
|
||||||
Ok(state
|
Ok(state
|
||||||
@ -522,17 +521,18 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
// filter by status(es) if provided and map the result
|
// filter by status(es) if provided and map the result
|
||||||
.filter_map(|(index, (validator, balance))| {
|
.filter_map(|(index, (validator, balance))| {
|
||||||
let status = api_types::ValidatorStatus::from_validator(
|
let status = api_types::ValidatorStatus::from_validator(
|
||||||
Some(validator),
|
validator,
|
||||||
epoch,
|
epoch,
|
||||||
finalized_epoch,
|
|
||||||
far_future_epoch,
|
far_future_epoch,
|
||||||
);
|
);
|
||||||
|
|
||||||
if query
|
let status_matches =
|
||||||
.status
|
query.status.as_ref().map_or(true, |statuses| {
|
||||||
.as_ref()
|
statuses.0.contains(&status)
|
||||||
.map_or(true, |statuses| statuses.0.contains(&status))
|
|| statuses.0.contains(&status.superstatus())
|
||||||
{
|
});
|
||||||
|
|
||||||
|
if status_matches {
|
||||||
Some(api_types::ValidatorData {
|
Some(api_types::ValidatorData {
|
||||||
index: index as u64,
|
index: index as u64,
|
||||||
balance: *balance,
|
balance: *balance,
|
||||||
@ -577,16 +577,14 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
let validator = state.validators.get(index)?;
|
let validator = state.validators.get(index)?;
|
||||||
let balance = *state.balances.get(index)?;
|
let balance = *state.balances.get(index)?;
|
||||||
let epoch = state.current_epoch();
|
let epoch = state.current_epoch();
|
||||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
|
||||||
let far_future_epoch = chain.spec.far_future_epoch;
|
let far_future_epoch = chain.spec.far_future_epoch;
|
||||||
|
|
||||||
Some(api_types::ValidatorData {
|
Some(api_types::ValidatorData {
|
||||||
index: index as u64,
|
index: index as u64,
|
||||||
balance,
|
balance,
|
||||||
status: api_types::ValidatorStatus::from_validator(
|
status: api_types::ValidatorStatus::from_validator(
|
||||||
Some(validator),
|
validator,
|
||||||
epoch,
|
epoch,
|
||||||
finalized_epoch,
|
|
||||||
far_future_epoch,
|
far_future_epoch,
|
||||||
),
|
),
|
||||||
validator: validator.clone(),
|
validator: validator.clone(),
|
||||||
|
@ -638,7 +638,6 @@ impl ApiTester {
|
|||||||
|
|
||||||
let expected = state_opt.map(|state| {
|
let expected = state_opt.map(|state| {
|
||||||
let epoch = state.current_epoch();
|
let epoch = state.current_epoch();
|
||||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
|
||||||
let far_future_epoch = self.chain.spec.far_future_epoch;
|
let far_future_epoch = self.chain.spec.far_future_epoch;
|
||||||
|
|
||||||
let mut validators = Vec::with_capacity(validator_indices.len());
|
let mut validators = Vec::with_capacity(validator_indices.len());
|
||||||
@ -649,12 +648,14 @@ impl ApiTester {
|
|||||||
}
|
}
|
||||||
let validator = state.validators[i as usize].clone();
|
let validator = state.validators[i as usize].clone();
|
||||||
let status = ValidatorStatus::from_validator(
|
let status = ValidatorStatus::from_validator(
|
||||||
Some(&validator),
|
&validator,
|
||||||
epoch,
|
epoch,
|
||||||
finalized_epoch,
|
|
||||||
far_future_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 {
|
validators.push(ValidatorData {
|
||||||
index: i as u64,
|
index: i as u64,
|
||||||
balance: state.balances[i as usize],
|
balance: state.balances[i as usize],
|
||||||
@ -706,16 +707,14 @@ impl ApiTester {
|
|||||||
|
|
||||||
let expected = {
|
let expected = {
|
||||||
let epoch = state.current_epoch();
|
let epoch = state.current_epoch();
|
||||||
let finalized_epoch = state.finalized_checkpoint.epoch;
|
|
||||||
let far_future_epoch = self.chain.spec.far_future_epoch;
|
let far_future_epoch = self.chain.spec.far_future_epoch;
|
||||||
|
|
||||||
ValidatorData {
|
ValidatorData {
|
||||||
index: i as u64,
|
index: i as u64,
|
||||||
balance: state.balances[i],
|
balance: state.balances[i],
|
||||||
status: ValidatorStatus::from_validator(
|
status: ValidatorStatus::from_validator(
|
||||||
Some(&validator),
|
&validator,
|
||||||
epoch,
|
epoch,
|
||||||
finalized_epoch,
|
|
||||||
far_future_epoch,
|
far_future_epoch,
|
||||||
),
|
),
|
||||||
validator: validator.clone(),
|
validator: validator.clone(),
|
||||||
@ -1444,18 +1443,19 @@ impl ApiTester {
|
|||||||
vec![],
|
vec![],
|
||||||
vec![ValidatorStatus::Active],
|
vec![ValidatorStatus::Active],
|
||||||
vec![
|
vec![
|
||||||
ValidatorStatus::Unknown,
|
ValidatorStatus::PendingInitialized,
|
||||||
ValidatorStatus::WaitingForEligibility,
|
ValidatorStatus::PendingQueued,
|
||||||
ValidatorStatus::WaitingForFinality,
|
ValidatorStatus::ActiveOngoing,
|
||||||
ValidatorStatus::WaitingInQueue,
|
ValidatorStatus::ActiveExiting,
|
||||||
ValidatorStatus::StandbyForActive,
|
ValidatorStatus::ActiveSlashed,
|
||||||
ValidatorStatus::Active,
|
ValidatorStatus::ExitedUnslashed,
|
||||||
ValidatorStatus::ActiveAwaitingVoluntaryExit,
|
|
||||||
ValidatorStatus::ActiveAwaitingSlashedExit,
|
|
||||||
ValidatorStatus::ExitedVoluntarily,
|
|
||||||
ValidatorStatus::ExitedSlashed,
|
ValidatorStatus::ExitedSlashed,
|
||||||
ValidatorStatus::Withdrawable,
|
ValidatorStatus::WithdrawalPossible,
|
||||||
ValidatorStatus::Withdrawn,
|
ValidatorStatus::WithdrawalDone,
|
||||||
|
ValidatorStatus::Active,
|
||||||
|
ValidatorStatus::Pending,
|
||||||
|
ValidatorStatus::Exited,
|
||||||
|
ValidatorStatus::Withdrawal,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
interesting
|
interesting
|
||||||
|
@ -246,66 +246,84 @@ pub struct ValidatorBalanceData {
|
|||||||
pub balance: u64,
|
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:
|
// this proposal:
|
||||||
//
|
//
|
||||||
// https://hackmd.io/bQxMDRt1RbS1TLno8K4NPg?view
|
// https://hackmd.io/bQxMDRt1RbS1TLno8K4NPg?view
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum ValidatorStatus {
|
pub enum ValidatorStatus {
|
||||||
Unknown,
|
PendingInitialized,
|
||||||
WaitingForEligibility,
|
PendingQueued,
|
||||||
WaitingForFinality,
|
ActiveOngoing,
|
||||||
WaitingInQueue,
|
ActiveExiting,
|
||||||
StandbyForActive,
|
ActiveSlashed,
|
||||||
Active,
|
ExitedUnslashed,
|
||||||
ActiveAwaitingVoluntaryExit,
|
|
||||||
ActiveAwaitingSlashedExit,
|
|
||||||
ExitedVoluntarily,
|
|
||||||
ExitedSlashed,
|
ExitedSlashed,
|
||||||
Withdrawable,
|
WithdrawalPossible,
|
||||||
Withdrawn,
|
WithdrawalDone,
|
||||||
|
Active,
|
||||||
|
Pending,
|
||||||
|
Exited,
|
||||||
|
Withdrawal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidatorStatus {
|
impl ValidatorStatus {
|
||||||
pub fn from_validator(
|
pub fn from_validator(validator: &Validator, epoch: Epoch, far_future_epoch: Epoch) -> Self {
|
||||||
validator_opt: Option<&Validator>,
|
if validator.is_withdrawable_at(epoch) {
|
||||||
epoch: Epoch,
|
if validator.effective_balance == 0 {
|
||||||
finalized_epoch: Epoch,
|
ValidatorStatus::WithdrawalDone
|
||||||
far_future_epoch: Epoch,
|
} else {
|
||||||
) -> Self {
|
ValidatorStatus::WithdrawalPossible
|
||||||
if let Some(validator) = validator_opt {
|
}
|
||||||
if validator.is_withdrawable_at(epoch) {
|
} else if validator.is_exited_at(epoch) && epoch < validator.withdrawable_epoch {
|
||||||
ValidatorStatus::Withdrawable
|
if validator.slashed {
|
||||||
} else if validator.is_exited_at(epoch) {
|
ValidatorStatus::ExitedSlashed
|
||||||
|
} else {
|
||||||
|
ValidatorStatus::ExitedUnslashed
|
||||||
|
}
|
||||||
|
} else if validator.is_active_at(epoch) {
|
||||||
|
if validator.exit_epoch < far_future_epoch {
|
||||||
if validator.slashed {
|
if validator.slashed {
|
||||||
ValidatorStatus::ExitedSlashed
|
ValidatorStatus::ActiveSlashed
|
||||||
} else {
|
} else {
|
||||||
ValidatorStatus::ExitedVoluntarily
|
ValidatorStatus::ActiveExiting
|
||||||
}
|
|
||||||
} 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
|
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
} 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> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
match s {
|
||||||
"unknown" => Ok(ValidatorStatus::Unknown),
|
"pending_initialized" => Ok(ValidatorStatus::PendingInitialized),
|
||||||
"waiting_for_eligibility" => Ok(ValidatorStatus::WaitingForEligibility),
|
"pending_queued" => Ok(ValidatorStatus::PendingQueued),
|
||||||
"waiting_for_finality" => Ok(ValidatorStatus::WaitingForFinality),
|
"active_ongoing" => Ok(ValidatorStatus::ActiveOngoing),
|
||||||
"waiting_in_queue" => Ok(ValidatorStatus::WaitingInQueue),
|
"active_exiting" => Ok(ValidatorStatus::ActiveExiting),
|
||||||
"standby_for_active" => Ok(ValidatorStatus::StandbyForActive),
|
"active_slashed" => Ok(ValidatorStatus::ActiveSlashed),
|
||||||
"active" => Ok(ValidatorStatus::Active),
|
"exited_unslashed" => Ok(ValidatorStatus::ExitedUnslashed),
|
||||||
"active_awaiting_voluntary_exit" => Ok(ValidatorStatus::ActiveAwaitingVoluntaryExit),
|
|
||||||
"active_awaiting_slashed_exit" => Ok(ValidatorStatus::ActiveAwaitingSlashedExit),
|
|
||||||
"exited_voluntarily" => Ok(ValidatorStatus::ExitedVoluntarily),
|
|
||||||
"exited_slashed" => Ok(ValidatorStatus::ExitedSlashed),
|
"exited_slashed" => Ok(ValidatorStatus::ExitedSlashed),
|
||||||
"withdrawable" => Ok(ValidatorStatus::Withdrawable),
|
"withdrawal_possible" => Ok(ValidatorStatus::WithdrawalPossible),
|
||||||
"withdrawn" => Ok(ValidatorStatus::Withdrawn),
|
"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)),
|
_ => Err(format!("{} cannot be parsed as a validator status.", s)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,20 +354,19 @@ impl FromStr for ValidatorStatus {
|
|||||||
impl fmt::Display for ValidatorStatus {
|
impl fmt::Display for ValidatorStatus {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ValidatorStatus::Unknown => write!(f, "unknown"),
|
ValidatorStatus::PendingInitialized => write!(f, "pending_initialized"),
|
||||||
ValidatorStatus::WaitingForEligibility => write!(f, "waiting_for_eligibility"),
|
ValidatorStatus::PendingQueued => write!(f, "pending_queued"),
|
||||||
ValidatorStatus::WaitingForFinality => write!(f, "waiting_for_finality"),
|
ValidatorStatus::ActiveOngoing => write!(f, "active_ongoing"),
|
||||||
ValidatorStatus::WaitingInQueue => write!(f, "waiting_in_queue"),
|
ValidatorStatus::ActiveExiting => write!(f, "active_exiting"),
|
||||||
ValidatorStatus::StandbyForActive => write!(f, "standby_for_active"),
|
ValidatorStatus::ActiveSlashed => write!(f, "active_slashed"),
|
||||||
ValidatorStatus::Active => write!(f, "active"),
|
ValidatorStatus::ExitedUnslashed => write!(f, "exited_unslashed"),
|
||||||
ValidatorStatus::ActiveAwaitingVoluntaryExit => {
|
|
||||||
write!(f, "active_awaiting_voluntary_exit")
|
|
||||||
}
|
|
||||||
ValidatorStatus::ActiveAwaitingSlashedExit => write!(f, "active_awaiting_slashed_exit"),
|
|
||||||
ValidatorStatus::ExitedVoluntarily => write!(f, "exited_voluntarily"),
|
|
||||||
ValidatorStatus::ExitedSlashed => write!(f, "exited_slashed"),
|
ValidatorStatus::ExitedSlashed => write!(f, "exited_slashed"),
|
||||||
ValidatorStatus::Withdrawable => write!(f, "withdrawable"),
|
ValidatorStatus::WithdrawalPossible => write!(f, "withdrawal_possible"),
|
||||||
ValidatorStatus::Withdrawn => write!(f, "withdrawn"),
|
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