mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 04:01:51 +00:00
merge with upstream
This commit is contained in:
@@ -4,7 +4,6 @@ mod get_attesting_indices;
|
||||
mod get_indexed_attestation;
|
||||
mod initiate_validator_exit;
|
||||
mod slash_validator;
|
||||
mod withdraw_balance;
|
||||
|
||||
pub mod altair;
|
||||
pub mod base;
|
||||
@@ -15,8 +14,6 @@ pub use get_attesting_indices::{get_attesting_indices, get_attesting_indices_fro
|
||||
pub use get_indexed_attestation::get_indexed_attestation;
|
||||
pub use initiate_validator_exit::initiate_validator_exit;
|
||||
pub use slash_validator::slash_validator;
|
||||
#[cfg(feature = "withdrawals")]
|
||||
pub use withdraw_balance::withdraw_balance;
|
||||
|
||||
use safe_arith::SafeArith;
|
||||
use types::{BeaconState, BeaconStateError, EthSpec};
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
use crate::common::decrease_balance;
|
||||
use safe_arith::SafeArith;
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
#[cfg(feature = "withdrawals")]
|
||||
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(())
|
||||
}
|
||||
@@ -19,6 +19,8 @@ pub use process_operations::process_operations;
|
||||
pub use verify_attestation::{
|
||||
verify_attestation_for_block_inclusion, verify_attestation_for_state,
|
||||
};
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub use verify_bls_to_execution_change::verify_bls_to_execution_change;
|
||||
pub use verify_deposit::{
|
||||
get_existing_validator_index, verify_deposit_merkle_proof, verify_deposit_signature,
|
||||
};
|
||||
@@ -34,10 +36,15 @@ pub mod signature_sets;
|
||||
pub mod tests;
|
||||
mod verify_attestation;
|
||||
mod verify_attester_slashing;
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
mod verify_bls_to_execution_change;
|
||||
mod verify_deposit;
|
||||
mod verify_exit;
|
||||
mod verify_proposer_slashing;
|
||||
|
||||
#[cfg(feature = "withdrawals-processing")]
|
||||
use crate::common::decrease_balance;
|
||||
|
||||
#[cfg(feature = "arbitrary-fuzz")]
|
||||
use arbitrary::Arbitrary;
|
||||
|
||||
@@ -161,6 +168,8 @@ pub fn per_block_processing<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
// previous block.
|
||||
if is_execution_enabled(state, block.body()) {
|
||||
let payload = block.body().execution_payload()?;
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
process_withdrawals::<T, Payload>(state, payload, spec)?;
|
||||
process_execution_payload::<T, Payload>(state, payload, spec)?;
|
||||
}
|
||||
|
||||
@@ -454,3 +463,100 @@ pub fn compute_timestamp_at_slot<T: EthSpec>(
|
||||
.safe_mul(spec.seconds_per_slot)
|
||||
.and_then(|since_genesis| state.genesis_time().safe_add(since_genesis))
|
||||
}
|
||||
|
||||
/// FIXME: add link to this function once the spec is stable
|
||||
#[cfg(feature = "withdrawals")]
|
||||
pub fn get_expected_withdrawals<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Withdrawals<T>, BlockProcessingError> {
|
||||
let epoch = state.current_epoch();
|
||||
let mut withdrawal_index = state.next_withdrawal_index()?;
|
||||
let mut validator_index = state.next_withdrawal_validator_index()?;
|
||||
let mut withdrawals = vec![];
|
||||
|
||||
if cfg!(not(feature = "withdrawals-processing")) {
|
||||
return Ok(withdrawals.into());
|
||||
}
|
||||
|
||||
for _ in 0..state.validators().len() {
|
||||
let validator = state.get_validator(validator_index as usize)?;
|
||||
let balance = *state.balances().get(validator_index as usize).ok_or(
|
||||
BeaconStateError::BalancesOutOfBounds(validator_index as usize),
|
||||
)?;
|
||||
if validator.is_fully_withdrawable_at(balance, epoch, spec) {
|
||||
withdrawals.push(Withdrawal {
|
||||
index: withdrawal_index,
|
||||
validator_index,
|
||||
address: validator
|
||||
.get_eth1_withdrawal_address(spec)
|
||||
.ok_or(BlockProcessingError::WithdrawalCredentialsInvalid)?,
|
||||
amount: balance,
|
||||
});
|
||||
withdrawal_index.safe_add_assign(1)?;
|
||||
} else if validator.is_partially_withdrawable_validator(balance, spec) {
|
||||
withdrawals.push(Withdrawal {
|
||||
index: withdrawal_index,
|
||||
validator_index,
|
||||
address: validator
|
||||
.get_eth1_withdrawal_address(spec)
|
||||
.ok_or(BlockProcessingError::WithdrawalCredentialsInvalid)?,
|
||||
amount: balance.safe_sub(spec.max_effective_balance)?,
|
||||
});
|
||||
withdrawal_index.safe_add_assign(1)?;
|
||||
}
|
||||
if withdrawals.len() == T::max_withdrawals_per_payload() {
|
||||
break;
|
||||
}
|
||||
validator_index = validator_index
|
||||
.safe_add(1)?
|
||||
.safe_rem(state.validators().len() as u64)?;
|
||||
}
|
||||
|
||||
Ok(withdrawals.into())
|
||||
}
|
||||
|
||||
/// FIXME: add link to this function once the spec is stable
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub fn process_withdrawals<'payload, T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
state: &mut BeaconState<T>,
|
||||
payload: Payload::Ref<'payload>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
match state {
|
||||
BeaconState::Merge(_) => Ok(()),
|
||||
BeaconState::Capella(_) | BeaconState::Eip4844(_) => {
|
||||
let expected_withdrawals = get_expected_withdrawals(state, spec)?;
|
||||
let expected_root = expected_withdrawals.tree_hash_root();
|
||||
let withdrawals_root = payload.withdrawals_root()?;
|
||||
|
||||
if expected_root != withdrawals_root {
|
||||
return Err(BlockProcessingError::WithdrawalsRootMismatch {
|
||||
expected: expected_root,
|
||||
found: withdrawals_root,
|
||||
});
|
||||
}
|
||||
|
||||
for withdrawal in expected_withdrawals.iter() {
|
||||
decrease_balance(
|
||||
state,
|
||||
withdrawal.validator_index as usize,
|
||||
withdrawal.amount,
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(latest_withdrawal) = expected_withdrawals.last() {
|
||||
*state.next_withdrawal_index_mut()? = latest_withdrawal.index.safe_add(1)?;
|
||||
let next_validator_index = latest_withdrawal
|
||||
.validator_index
|
||||
.safe_add(1)?
|
||||
.safe_rem(state.validators().len() as u64)?;
|
||||
*state.next_withdrawal_validator_index_mut()? = next_validator_index;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// these shouldn't even be encountered but they're here for completeness
|
||||
BeaconState::Base(_) | BeaconState::Altair(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
#[allow(clippy::module_inception)]
|
||||
pub mod eip4844;
|
||||
|
||||
@@ -6,8 +6,8 @@ use ssz::Decode;
|
||||
use ssz_types::VariableList;
|
||||
use types::consts::eip4844::{BLOB_TX_TYPE, VERSIONED_HASH_VERSION_KZG};
|
||||
use types::{
|
||||
AbstractExecPayload, BeaconBlockBodyRef, EthSpec, ExecPayload, FullPayload, FullPayloadRef,
|
||||
KzgCommitment, Transaction, Transactions, VersionedHash,
|
||||
AbstractExecPayload, BeaconBlockBodyRef, EthSpec, ExecPayload, KzgCommitment, Transaction,
|
||||
Transactions, VersionedHash,
|
||||
};
|
||||
|
||||
pub fn process_blob_kzg_commitments<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
@@ -35,7 +35,7 @@ pub fn verify_kzg_commitments_against_transactions<T: EthSpec>(
|
||||
let nested_iter = transactions
|
||||
.into_iter()
|
||||
.filter(|tx| {
|
||||
tx.get(0)
|
||||
tx.first()
|
||||
.map(|tx_type| *tx_type == BLOB_TX_TYPE)
|
||||
.unwrap_or(false)
|
||||
})
|
||||
|
||||
@@ -49,6 +49,10 @@ pub enum BlockProcessingError {
|
||||
index: usize,
|
||||
reason: ExitInvalid,
|
||||
},
|
||||
BlsExecutionChangeInvalid {
|
||||
index: usize,
|
||||
reason: BlsExecutionChangeInvalid,
|
||||
},
|
||||
SyncAggregateInvalid {
|
||||
reason: SyncAggregateInvalid,
|
||||
},
|
||||
@@ -74,6 +78,10 @@ pub enum BlockProcessingError {
|
||||
},
|
||||
ExecutionInvalid,
|
||||
ConsensusContext(ContextError),
|
||||
WithdrawalsRootMismatch {
|
||||
expected: Hash256,
|
||||
found: Hash256,
|
||||
},
|
||||
BlobVersionHashMismatch,
|
||||
/// The number of commitments in blob transactions in the payload does not match the number
|
||||
/// of commitments in the block.
|
||||
@@ -86,6 +94,7 @@ pub enum BlockProcessingError {
|
||||
index: usize,
|
||||
length: usize,
|
||||
},
|
||||
WithdrawalCredentialsInvalid,
|
||||
}
|
||||
|
||||
impl From<BeaconStateError> for BlockProcessingError {
|
||||
@@ -180,7 +189,8 @@ impl_into_block_processing_error_with_index!(
|
||||
IndexedAttestationInvalid,
|
||||
AttestationInvalid,
|
||||
DepositInvalid,
|
||||
ExitInvalid
|
||||
ExitInvalid,
|
||||
BlsExecutionChangeInvalid
|
||||
);
|
||||
|
||||
pub type HeaderValidationError = BlockOperationError<HeaderInvalid>;
|
||||
@@ -190,6 +200,7 @@ pub type AttestationValidationError = BlockOperationError<AttestationInvalid>;
|
||||
pub type SyncCommitteeMessageValidationError = BlockOperationError<SyncAggregateInvalid>;
|
||||
pub type DepositValidationError = BlockOperationError<DepositInvalid>;
|
||||
pub type ExitValidationError = BlockOperationError<ExitInvalid>;
|
||||
pub type BlsExecutionChangeValidationError = BlockOperationError<BlsExecutionChangeInvalid>;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum BlockOperationError<T> {
|
||||
@@ -405,6 +416,18 @@ pub enum ExitInvalid {
|
||||
SignatureSetError(SignatureSetError),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum BlsExecutionChangeInvalid {
|
||||
/// The specified validator is not in the state's validator registry.
|
||||
ValidatorUnknown(u64),
|
||||
/// Validator does not have BLS Withdrawal credentials before this change
|
||||
NonBlsWithdrawalCredentials,
|
||||
/// Provided BLS pubkey does not match withdrawal credentials
|
||||
WithdrawalCredentialsMismatch,
|
||||
/// The signature is invalid
|
||||
BadSignature,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SyncAggregateInvalid {
|
||||
/// One or more of the aggregate public keys is invalid.
|
||||
|
||||
@@ -33,6 +33,12 @@ pub fn process_operations<'a, T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
process_attestations(state, block_body, verify_signatures, ctxt, spec)?;
|
||||
process_deposits(state, block_body.deposits(), spec)?;
|
||||
process_exits(state, block_body.voluntary_exits(), verify_signatures, spec)?;
|
||||
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
if let Ok(bls_to_execution_changes) = block_body.bls_to_execution_changes() {
|
||||
process_bls_to_execution_changes(state, bls_to_execution_changes, verify_signatures, spec)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -279,6 +285,32 @@ pub fn process_exits<T: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validates each `bls_to_execution_change` and updates the state
|
||||
///
|
||||
/// Returns `Ok(())` if the validation and state updates completed successfully. Otherwise returs
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub fn process_bls_to_execution_changes<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
bls_to_execution_changes: &[SignedBlsToExecutionChange],
|
||||
verify_signatures: VerifySignatures,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
for (i, signed_address_change) in bls_to_execution_changes.iter().enumerate() {
|
||||
verify_bls_to_execution_change(state, signed_address_change, verify_signatures, spec)
|
||||
.map_err(|e| e.into_with_index(i))?;
|
||||
|
||||
state
|
||||
.get_validator_mut(signed_address_change.message.validator_index as usize)?
|
||||
.change_withdrawal_credentials(
|
||||
&signed_address_change.message.to_execution_address,
|
||||
spec,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validates each `Deposit` and updates the state, short-circuiting on an invalid object.
|
||||
///
|
||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||
|
||||
@@ -11,8 +11,8 @@ use types::{
|
||||
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256,
|
||||
InconsistentFork, IndexedAttestation, ProposerSlashing, PublicKey, PublicKeyBytes, Signature,
|
||||
SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader,
|
||||
SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate,
|
||||
SyncAggregatorSelectionData, Unsigned,
|
||||
SignedBlsToExecutionChange, SignedContributionAndProof, SignedRoot, SignedVoluntaryExit,
|
||||
SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned,
|
||||
};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
@@ -156,6 +156,33 @@ where
|
||||
))
|
||||
}
|
||||
|
||||
pub fn bls_execution_change_signature_set<'a, T: EthSpec>(
|
||||
state: &'a BeaconState<T>,
|
||||
signed_address_change: &'a SignedBlsToExecutionChange,
|
||||
spec: &'a ChainSpec,
|
||||
) -> Result<SignatureSet<'a>> {
|
||||
let domain = spec.get_domain(
|
||||
state.current_epoch(),
|
||||
Domain::BlsToExecutionChange,
|
||||
&state.fork(),
|
||||
state.genesis_validators_root(),
|
||||
);
|
||||
let message = signed_address_change.message.signing_root(domain);
|
||||
let signing_key = Cow::Owned(
|
||||
signed_address_change
|
||||
.message
|
||||
.from_bls_pubkey
|
||||
.decompress()
|
||||
.map_err(|_| Error::PublicKeyDecompressionFailed)?,
|
||||
);
|
||||
|
||||
Ok(SignatureSet::single_pubkey(
|
||||
&signed_address_change.signature,
|
||||
signing_key,
|
||||
message,
|
||||
))
|
||||
}
|
||||
|
||||
/// A signature set that is valid if the block proposers randao reveal signature is correct.
|
||||
pub fn randao_signature_set<'a, T, F, Payload: AbstractExecPayload<T>>(
|
||||
state: &'a BeaconState<T>,
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
use super::errors::{BlockOperationError, BlsExecutionChangeInvalid as Invalid};
|
||||
use crate::per_block_processing::signature_sets::bls_execution_change_signature_set;
|
||||
use crate::VerifySignatures;
|
||||
use eth2_hashing::hash;
|
||||
use types::*;
|
||||
|
||||
type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
|
||||
|
||||
fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
||||
BlockOperationError::invalid(reason)
|
||||
}
|
||||
|
||||
/// Indicates if a `BlsToExecutionChange` is valid to be included in a block in the current epoch of the given
|
||||
/// state.
|
||||
///
|
||||
/// Returns `Ok(())` if the `SignedBlsToExecutionChange` is valid, otherwise indicates the reason for invalidity.
|
||||
pub fn verify_bls_to_execution_change<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
signed_address_change: &SignedBlsToExecutionChange,
|
||||
verify_signatures: VerifySignatures,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<()> {
|
||||
let address_change = &signed_address_change.message;
|
||||
|
||||
let validator = state
|
||||
.validators()
|
||||
.get(address_change.validator_index as usize)
|
||||
.ok_or_else(|| error(Invalid::ValidatorUnknown(address_change.validator_index)))?;
|
||||
|
||||
verify!(
|
||||
validator
|
||||
.withdrawal_credentials
|
||||
.as_bytes()
|
||||
.first()
|
||||
.map(|byte| *byte == spec.bls_withdrawal_prefix_byte)
|
||||
.unwrap_or(false),
|
||||
Invalid::NonBlsWithdrawalCredentials
|
||||
);
|
||||
|
||||
let pubkey_hash = hash(address_change.from_bls_pubkey.as_serialized());
|
||||
|
||||
// FIXME: Should this check be put inside the verify_signatures.is_true() condition?
|
||||
// I believe that's used for fuzzing so this is a Mehdi question..
|
||||
verify!(
|
||||
validator.withdrawal_credentials.as_bytes().get(1..) == pubkey_hash.get(1..),
|
||||
Invalid::WithdrawalCredentialsMismatch
|
||||
);
|
||||
|
||||
if verify_signatures.is_true() {
|
||||
verify!(
|
||||
bls_execution_change_signature_set(state, signed_address_change, spec)?.verify(),
|
||||
Invalid::BadSignature
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -11,7 +11,6 @@ pub use weigh_justification_and_finalization::weigh_justification_and_finalizati
|
||||
|
||||
pub mod altair;
|
||||
pub mod base;
|
||||
pub mod capella;
|
||||
pub mod effective_balance_updates;
|
||||
pub mod epoch_processing_summary;
|
||||
pub mod errors;
|
||||
@@ -38,8 +37,10 @@ pub fn process_epoch<T: EthSpec>(
|
||||
|
||||
match state {
|
||||
BeaconState::Base(_) => base::process_epoch(state, spec),
|
||||
BeaconState::Altair(_) | BeaconState::Merge(_) => altair::process_epoch(state, spec),
|
||||
BeaconState::Capella(_) | BeaconState::Eip4844(_) => capella::process_epoch(state, spec),
|
||||
BeaconState::Altair(_)
|
||||
| BeaconState::Merge(_)
|
||||
| BeaconState::Capella(_)
|
||||
| BeaconState::Eip4844(_) => altair::process_epoch(state, spec),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
use super::{process_registry_updates, process_slashings, EpochProcessingSummary, Error};
|
||||
use crate::per_epoch_processing::{
|
||||
altair,
|
||||
effective_balance_updates::process_effective_balance_updates,
|
||||
historical_roots_update::process_historical_roots_update,
|
||||
resets::{process_eth1_data_reset, process_randao_mixes_reset, process_slashings_reset},
|
||||
};
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub use full_withdrawals::process_full_withdrawals;
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub use partial_withdrawals::process_partial_withdrawals;
|
||||
use types::{BeaconState, ChainSpec, EthSpec, RelativeEpoch};
|
||||
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub mod full_withdrawals;
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub mod partial_withdrawals;
|
||||
|
||||
pub fn process_epoch<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<EpochProcessingSummary<T>, Error> {
|
||||
// Ensure the committee caches are built.
|
||||
state.build_committee_cache(RelativeEpoch::Previous, spec)?;
|
||||
state.build_committee_cache(RelativeEpoch::Current, spec)?;
|
||||
state.build_committee_cache(RelativeEpoch::Next, spec)?;
|
||||
|
||||
// Pre-compute participating indices and total balances.
|
||||
let participation_cache = altair::ParticipationCache::new(state, spec)?;
|
||||
let sync_committee = state.current_sync_committee()?.clone();
|
||||
|
||||
// Justification and finalization.
|
||||
let justification_and_finalization_state =
|
||||
altair::process_justification_and_finalization(state, &participation_cache)?;
|
||||
justification_and_finalization_state.apply_changes_to_state(state);
|
||||
|
||||
altair::process_inactivity_updates(state, &participation_cache, spec)?;
|
||||
|
||||
// Rewards and Penalties.
|
||||
altair::process_rewards_and_penalties(state, &participation_cache, spec)?;
|
||||
|
||||
// Registry Updates.
|
||||
process_registry_updates(state, spec)?;
|
||||
|
||||
// Slashings.
|
||||
process_slashings(
|
||||
state,
|
||||
participation_cache.current_epoch_total_active_balance(),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
// Reset eth1 data votes.
|
||||
process_eth1_data_reset(state)?;
|
||||
|
||||
// Update effective balances with hysteresis (lag).
|
||||
process_effective_balance_updates(state, spec)?;
|
||||
|
||||
// Reset slashings
|
||||
process_slashings_reset(state)?;
|
||||
|
||||
// Set randao mix
|
||||
process_randao_mixes_reset(state)?;
|
||||
|
||||
// Set historical root accumulator
|
||||
process_historical_roots_update(state)?;
|
||||
|
||||
// Rotate current/previous epoch participation
|
||||
altair::process_participation_flag_updates(state)?;
|
||||
|
||||
altair::process_sync_committee_updates(state, spec)?;
|
||||
|
||||
// Withdrawals
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
process_full_withdrawals(state, spec)?;
|
||||
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
process_partial_withdrawals(state, spec)?;
|
||||
|
||||
// Rotate the epoch caches to suit the epoch transition.
|
||||
state.advance_caches(spec)?;
|
||||
|
||||
// FIXME: do we need a Capella variant for this?
|
||||
Ok(EpochProcessingSummary::Altair {
|
||||
participation_cache,
|
||||
sync_committee,
|
||||
})
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
use crate::common::withdraw_balance;
|
||||
use crate::EpochProcessingError;
|
||||
use types::{beacon_state::BeaconState, eth_spec::EthSpec, ChainSpec};
|
||||
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub fn process_full_withdrawals<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), EpochProcessingError> {
|
||||
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(())
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
use crate::common::withdraw_balance;
|
||||
use crate::EpochProcessingError;
|
||||
use safe_arith::SafeArith;
|
||||
use types::{beacon_state::BeaconState, eth_spec::EthSpec, ChainSpec};
|
||||
|
||||
#[cfg(all(feature = "withdrawals", feature = "withdrawals-processing"))]
|
||||
pub fn process_partial_withdrawals<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), EpochProcessingError> {
|
||||
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(())
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
use crate::upgrade::{upgrade_to_altair, upgrade_to_bellatrix};
|
||||
use crate::upgrade::{
|
||||
upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella, upgrade_to_eip4844,
|
||||
};
|
||||
use crate::{per_epoch_processing::EpochProcessingSummary, *};
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use types::*;
|
||||
@@ -55,6 +57,14 @@ pub fn per_slot_processing<T: EthSpec>(
|
||||
if spec.bellatrix_fork_epoch == Some(state.current_epoch()) {
|
||||
upgrade_to_bellatrix(state, spec)?;
|
||||
}
|
||||
// Capella.
|
||||
if spec.capella_fork_epoch == Some(state.current_epoch()) {
|
||||
upgrade_to_capella(state, spec)?;
|
||||
}
|
||||
// Eip4844
|
||||
if spec.eip4844_fork_epoch == Some(state.current_epoch()) {
|
||||
upgrade_to_eip4844(state, spec)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(summary)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use ssz_types::VariableList;
|
||||
use std::mem;
|
||||
use types::{BeaconState, BeaconStateCapella, BeaconStateError as Error, ChainSpec, EthSpec, Fork};
|
||||
|
||||
@@ -58,11 +57,9 @@ pub fn upgrade_to_capella<E: EthSpec>(
|
||||
latest_execution_payload_header: pre.latest_execution_payload_header.upgrade_to_capella(),
|
||||
// Withdrawals
|
||||
#[cfg(feature = "withdrawals")]
|
||||
withdrawal_queue: VariableList::empty(),
|
||||
#[cfg(feature = "withdrawals")]
|
||||
next_withdrawal_index: 0,
|
||||
#[cfg(feature = "withdrawals")]
|
||||
next_partial_withdrawal_validator_index: 0,
|
||||
next_withdrawal_validator_index: 0,
|
||||
// Caches
|
||||
total_active_balance: pre.total_active_balance,
|
||||
committee_caches: mem::take(&mut pre.committee_caches),
|
||||
|
||||
@@ -65,11 +65,9 @@ pub fn upgrade_to_eip4844<E: EthSpec>(
|
||||
latest_execution_payload_header: pre.latest_execution_payload_header.upgrade_to_eip4844(),
|
||||
// Withdrawals
|
||||
#[cfg(feature = "withdrawals")]
|
||||
withdrawal_queue: mem::take(&mut pre.withdrawal_queue),
|
||||
#[cfg(feature = "withdrawals")]
|
||||
next_withdrawal_index: pre.next_withdrawal_index,
|
||||
#[cfg(feature = "withdrawals")]
|
||||
next_partial_withdrawal_validator_index: pre.next_partial_withdrawal_validator_index,
|
||||
next_withdrawal_validator_index: 0,
|
||||
// Caches
|
||||
total_active_balance: pre.total_active_balance,
|
||||
committee_caches: mem::take(&mut pre.committee_caches),
|
||||
|
||||
Reference in New Issue
Block a user