Added Capella Epoch Processing Logic (#3666)
This commit is contained in:
parent
137f230344
commit
f1a3b3b01c
@ -381,6 +381,8 @@ impl<T: EthSpec> From<ExecutionPayload<T>> for JsonExecutionPayload<T> {
|
|||||||
pub struct JsonWithdrawal {
|
pub struct JsonWithdrawal {
|
||||||
#[serde(with = "eth2_serde_utils::u64_hex_be")]
|
#[serde(with = "eth2_serde_utils::u64_hex_be")]
|
||||||
pub index: u64,
|
pub index: u64,
|
||||||
|
#[serde(with = "eth2_serde_utils::u64_hex_be")]
|
||||||
|
pub validator_index: u64,
|
||||||
pub address: Address,
|
pub address: Address,
|
||||||
#[serde(with = "eth2_serde_utils::u256_hex_be")]
|
#[serde(with = "eth2_serde_utils::u256_hex_be")]
|
||||||
pub amount: Uint256,
|
pub amount: Uint256,
|
||||||
@ -390,6 +392,7 @@ impl From<Withdrawal> for JsonWithdrawal {
|
|||||||
fn from(withdrawal: Withdrawal) -> Self {
|
fn from(withdrawal: Withdrawal) -> Self {
|
||||||
Self {
|
Self {
|
||||||
index: withdrawal.index,
|
index: withdrawal.index,
|
||||||
|
validator_index: withdrawal.validator_index,
|
||||||
address: withdrawal.address,
|
address: withdrawal.address,
|
||||||
amount: Uint256::from((withdrawal.amount as u128) * 1000000000u128),
|
amount: Uint256::from((withdrawal.amount as u128) * 1000000000u128),
|
||||||
}
|
}
|
||||||
@ -400,6 +403,7 @@ impl From<JsonWithdrawal> for Withdrawal {
|
|||||||
fn from(jw: JsonWithdrawal) -> Self {
|
fn from(jw: JsonWithdrawal) -> Self {
|
||||||
Self {
|
Self {
|
||||||
index: jw.index,
|
index: jw.index,
|
||||||
|
validator_index: jw.validator_index,
|
||||||
address: jw.address,
|
address: jw.address,
|
||||||
//FIXME(sean) if EE gives us too large a number this panics
|
//FIXME(sean) if EE gives us too large a number this panics
|
||||||
amount: (jw.amount / 1000000000).as_u64(),
|
amount: (jw.amount / 1000000000).as_u64(),
|
||||||
|
@ -4,6 +4,7 @@ mod get_attesting_indices;
|
|||||||
mod get_indexed_attestation;
|
mod get_indexed_attestation;
|
||||||
mod initiate_validator_exit;
|
mod initiate_validator_exit;
|
||||||
mod slash_validator;
|
mod slash_validator;
|
||||||
|
mod withdraw_balance;
|
||||||
|
|
||||||
pub mod altair;
|
pub mod altair;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
@ -14,6 +15,7 @@ pub use get_attesting_indices::{get_attesting_indices, get_attesting_indices_fro
|
|||||||
pub use get_indexed_attestation::get_indexed_attestation;
|
pub use get_indexed_attestation::get_indexed_attestation;
|
||||||
pub use initiate_validator_exit::initiate_validator_exit;
|
pub use initiate_validator_exit::initiate_validator_exit;
|
||||||
pub use slash_validator::slash_validator;
|
pub use slash_validator::slash_validator;
|
||||||
|
pub use withdraw_balance::withdraw_balance;
|
||||||
|
|
||||||
use safe_arith::SafeArith;
|
use safe_arith::SafeArith;
|
||||||
use types::{BeaconState, BeaconStateError, EthSpec};
|
use types::{BeaconState, BeaconStateError, EthSpec};
|
||||||
|
28
consensus/state_processing/src/common/withdraw_balance.rs
Normal file
28
consensus/state_processing/src/common/withdraw_balance.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use crate::common::decrease_balance;
|
||||||
|
use safe_arith::SafeArith;
|
||||||
|
use types::{BeaconStateError as Error, *};
|
||||||
|
|
||||||
|
pub fn withdraw_balance<T: EthSpec>(
|
||||||
|
state: &mut BeaconState<T>,
|
||||||
|
validator_index: usize,
|
||||||
|
amount: u64,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
decrease_balance(state, validator_index as usize, amount)?;
|
||||||
|
|
||||||
|
let withdrawal_address = Address::from_slice(
|
||||||
|
&state
|
||||||
|
.get_validator(validator_index)?
|
||||||
|
.withdrawal_credentials
|
||||||
|
.as_bytes()[12..],
|
||||||
|
);
|
||||||
|
let withdrawal = Withdrawal {
|
||||||
|
index: *state.next_withdrawal_index()?,
|
||||||
|
validator_index: validator_index as u64,
|
||||||
|
address: withdrawal_address,
|
||||||
|
amount,
|
||||||
|
};
|
||||||
|
state.next_withdrawal_index_mut()?.safe_add_assign(1)?;
|
||||||
|
state.withdrawal_queue_mut()?.push(withdrawal)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -66,9 +66,9 @@ pub fn process_epoch<T: EthSpec>(
|
|||||||
altair::process_sync_committee_updates(state, spec)?;
|
altair::process_sync_committee_updates(state, spec)?;
|
||||||
|
|
||||||
// Withdrawals
|
// Withdrawals
|
||||||
process_full_withdrawals(state)?;
|
process_full_withdrawals(state, spec)?;
|
||||||
|
|
||||||
process_partial_withdrawals(state)?;
|
process_partial_withdrawals(state, spec)?;
|
||||||
|
|
||||||
// Rotate the epoch caches to suit the epoch transition.
|
// Rotate the epoch caches to suit the epoch transition.
|
||||||
state.advance_caches(spec)?;
|
state.advance_caches(spec)?;
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
|
use crate::common::withdraw_balance;
|
||||||
use crate::EpochProcessingError;
|
use crate::EpochProcessingError;
|
||||||
use types::beacon_state::BeaconState;
|
use types::{beacon_state::BeaconState, eth_spec::EthSpec, ChainSpec};
|
||||||
use types::eth_spec::EthSpec;
|
|
||||||
|
|
||||||
pub fn process_full_withdrawals<T: EthSpec>(
|
pub fn process_full_withdrawals<T: EthSpec>(
|
||||||
_state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
|
spec: &ChainSpec,
|
||||||
) -> Result<(), EpochProcessingError> {
|
) -> Result<(), EpochProcessingError> {
|
||||||
todo!("implement this");
|
let current_epoch = state.current_epoch();
|
||||||
|
// FIXME: is this the most efficient way to do this?
|
||||||
|
for validator_index in 0..state.validators().len() {
|
||||||
|
// TODO: is this the correct way to handle validators not existing?
|
||||||
|
if let (Some(validator), Some(balance)) = (
|
||||||
|
state.validators().get(validator_index),
|
||||||
|
state.balances().get(validator_index),
|
||||||
|
) {
|
||||||
|
if validator.is_fully_withdrawable_at(*balance, current_epoch, spec) {
|
||||||
|
withdraw_balance(state, validator_index, *balance)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,39 @@
|
|||||||
|
use crate::common::withdraw_balance;
|
||||||
use crate::EpochProcessingError;
|
use crate::EpochProcessingError;
|
||||||
use types::beacon_state::BeaconState;
|
use safe_arith::SafeArith;
|
||||||
use types::eth_spec::EthSpec;
|
use types::{beacon_state::BeaconState, eth_spec::EthSpec, ChainSpec};
|
||||||
|
|
||||||
pub fn process_partial_withdrawals<T: EthSpec>(
|
pub fn process_partial_withdrawals<T: EthSpec>(
|
||||||
_state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
|
spec: &ChainSpec,
|
||||||
) -> Result<(), EpochProcessingError> {
|
) -> Result<(), EpochProcessingError> {
|
||||||
todo!("implement this");
|
let mut partial_withdrawals_count = 0;
|
||||||
|
let mut validator_index = *state.next_partial_withdrawal_validator_index()? as usize;
|
||||||
|
|
||||||
|
let n_validators = state.validators().len();
|
||||||
|
// FIXME: is this the most efficient way to do this?
|
||||||
|
for _ in 0..n_validators {
|
||||||
|
// TODO: is this the correct way to handle validators not existing?
|
||||||
|
if let (Some(validator), Some(balance)) = (
|
||||||
|
state.validators().get(validator_index),
|
||||||
|
state.balances().get(validator_index),
|
||||||
|
) {
|
||||||
|
if validator.is_partially_withdrawable_validator(*balance, spec) {
|
||||||
|
withdraw_balance(
|
||||||
|
state,
|
||||||
|
validator_index,
|
||||||
|
*balance - spec.max_effective_balance,
|
||||||
|
)?;
|
||||||
|
partial_withdrawals_count.safe_add_assign(1)?;
|
||||||
|
|
||||||
|
validator_index = validator_index.safe_add(1)? % n_validators;
|
||||||
|
if partial_withdrawals_count == T::max_partial_withdrawals_per_epoch() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*state.next_partial_withdrawal_validator_index_mut()? = validator_index as u64;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@ pub struct ChainSpec {
|
|||||||
*/
|
*/
|
||||||
pub genesis_fork_version: [u8; 4],
|
pub genesis_fork_version: [u8; 4],
|
||||||
pub bls_withdrawal_prefix_byte: u8,
|
pub bls_withdrawal_prefix_byte: u8,
|
||||||
|
pub eth1_address_withdrawal_prefix_byte: u8,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Time parameters
|
* Time parameters
|
||||||
@ -519,7 +520,8 @@ impl ChainSpec {
|
|||||||
* Initial Values
|
* Initial Values
|
||||||
*/
|
*/
|
||||||
genesis_fork_version: [0; 4],
|
genesis_fork_version: [0; 4],
|
||||||
bls_withdrawal_prefix_byte: 0,
|
bls_withdrawal_prefix_byte: 0x00,
|
||||||
|
eth1_address_withdrawal_prefix_byte: 0x01,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Time parameters
|
* Time parameters
|
||||||
@ -748,7 +750,8 @@ impl ChainSpec {
|
|||||||
* Initial Values
|
* Initial Values
|
||||||
*/
|
*/
|
||||||
genesis_fork_version: [0x00, 0x00, 0x00, 0x64],
|
genesis_fork_version: [0x00, 0x00, 0x00, 0x64],
|
||||||
bls_withdrawal_prefix_byte: 0,
|
bls_withdrawal_prefix_byte: 0x00,
|
||||||
|
eth1_address_withdrawal_prefix_byte: 0x01,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Time parameters
|
* Time parameters
|
||||||
|
@ -65,6 +65,27 @@ impl Validator {
|
|||||||
// Has not yet been activated
|
// Has not yet been activated
|
||||||
&& self.activation_epoch == spec.far_future_epoch
|
&& self.activation_epoch == spec.far_future_epoch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the validator has eth1 withdrawal credential
|
||||||
|
pub fn has_eth1_withdrawal_credential(&self, spec: &ChainSpec) -> bool {
|
||||||
|
self.withdrawal_credentials
|
||||||
|
.as_bytes()
|
||||||
|
.first()
|
||||||
|
.map(|byte| *byte == spec.eth1_address_withdrawal_prefix_byte)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the validator is fully withdrawable at some epoch
|
||||||
|
pub fn is_fully_withdrawable_at(&self, balance: u64, epoch: Epoch, spec: &ChainSpec) -> bool {
|
||||||
|
self.has_eth1_withdrawal_credential(spec) && self.withdrawable_epoch <= epoch && balance > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the validator is partially withdrawable
|
||||||
|
pub fn is_partially_withdrawable_validator(&self, balance: u64, spec: &ChainSpec) -> bool {
|
||||||
|
self.has_eth1_withdrawal_credential(spec)
|
||||||
|
&& self.effective_balance == spec.max_effective_balance
|
||||||
|
&& balance > spec.max_effective_balance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Validator {
|
impl Default for Validator {
|
||||||
|
@ -15,6 +15,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
pub struct Withdrawal {
|
pub struct Withdrawal {
|
||||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||||
pub index: u64,
|
pub index: u64,
|
||||||
|
pub validator_index: u64,
|
||||||
pub address: Address,
|
pub address: Address,
|
||||||
pub amount: u64,
|
pub amount: u64,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user