Added Capella Epoch Processing Logic (#3666)

This commit is contained in:
ethDreamer 2022-10-27 16:41:39 -05:00 committed by GitHub
parent 137f230344
commit f1a3b3b01c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 113 additions and 12 deletions

View File

@ -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(),

View File

@ -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};

View 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(())
}

View File

@ -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)?;

View File

@ -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(())
} }

View File

@ -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(())
} }

View File

@ -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

View File

@ -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 {

View File

@ -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,
} }