add consolidation processing

This commit is contained in:
realbigsean
2024-05-07 14:01:44 -04:00
parent 32357d8f0a
commit c40bec9319
7 changed files with 274 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ use crate::common::{
slash_validator,
};
use crate::per_block_processing::errors::{BlockProcessingError, IntoWithIndex};
use crate::signature_sets::consolidation_signature_set;
use crate::VerifySignatures;
use types::consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_DENOMINATOR};
use types::typenum::U33;
@@ -640,3 +641,161 @@ pub fn process_deposit_receipts<E: EthSpec>(
Ok(())
}
pub fn process_consolidations<E: EthSpec>(
state: &mut BeaconState<E>,
consolidations: &[SignedConsolidation],
verify_signatures: VerifySignatures,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
// If the pending consolidations queue is full, no consolidations are allowed in the block
let pending_consolidations = state.pending_consolidations()?.len();
let pending_consolidations_limit = E::pending_consolidations_limit();
block_verify! {
pending_consolidations < pending_consolidations_limit,
BlockProcessingError::TooManyPendingConsolidations {
consolidations: pending_consolidations,
limit: pending_consolidations_limit
}
}
// If there is too little available consolidation churn limit, no consolidations are allowed in the block
let churn_limit = state.get_consolidation_churn_limit(spec)?;
block_verify! {
churn_limit > spec.min_activation_balance,
BlockProcessingError::ConsolidationChurnLimitTooLow {
churn_limit,
minimum: spec.min_activation_balance
}
}
for signed_consolidation in consolidations {
let consolidation = signed_consolidation.message.clone();
// Verify that source != target, so a consolidation cannot be used as an exit.
block_verify! {
consolidation.source_index != consolidation.target_index,
BlockProcessingError::MatchingSourceTargetConsolidation {
index: consolidation.source_index
}
}
let source_validator = state
.validators()
.get(consolidation.source_index as usize)
.ok_or(BeaconStateError::UnknownValidator(
consolidation.source_index as usize,
))?;
let target_validator = state
.validators()
.get(consolidation.target_index as usize)
.ok_or(BeaconStateError::UnknownValidator(
consolidation.target_index as usize,
))?;
// Verify the source and the target are active
let current_epoch = state.current_epoch();
block_verify! {
source_validator.is_active_at(current_epoch),
BlockProcessingError::InactiveConsolidationSource{
index: consolidation.source_index,
current_epoch
}
}
block_verify! {
target_validator.is_active_at(current_epoch),
BlockProcessingError::InactiveConsolidationTarget{
index: consolidation.target_index,
current_epoch
}
}
// Verify exits for source and target have not been initiated
block_verify! {
source_validator.exit_epoch == spec.far_future_epoch,
BlockProcessingError::SourceValidatorExiting{
index: consolidation.source_index,
}
}
block_verify! {
target_validator.exit_epoch == spec.far_future_epoch,
BlockProcessingError::TargetValidatorExiting{
index: consolidation.target_index,
}
}
// Consolidations must specify an epoch when they become valid; they are not valid before then
block_verify! {
current_epoch >= consolidation.epoch,
BlockProcessingError::FutureConsolidationEpoch {
current_epoch,
consolidation_epoch: consolidation.epoch
}
}
// Verify the source and the target have Execution layer withdrawal credentials
block_verify! {
source_validator.has_execution_withdrawal_credential(spec),
BlockProcessingError::NoSourceExecutionWithdrawalCredential {
index: consolidation.source_index,
}
}
block_verify! {
target_validator.has_execution_withdrawal_credential(spec),
BlockProcessingError::NoTargetExecutionWithdrawalCredential {
index: consolidation.target_index,
}
}
// Verify the same withdrawal address
let source_address = source_validator
.get_execution_withdrawal_address(spec)
.ok_or(BeaconStateError::NonExecutionAddresWithdrawalCredential)?;
let target_address = target_validator
.get_execution_withdrawal_address(spec)
.ok_or(BeaconStateError::NonExecutionAddresWithdrawalCredential)?;
block_verify! {
source_address == target_address,
BlockProcessingError::MismatchedWithdrawalCredentials {
source_address,
target_address
}
}
if verify_signatures.is_true() {
let signature_set = consolidation_signature_set(
state,
|i| get_pubkey_from_state(state, i),
signed_consolidation,
spec,
)?;
block_verify! {
signature_set.verify(),
BlockProcessingError::InavlidConsolidationSignature
}
}
let exit_epoch = state.compute_consolidation_epoch_and_update_churn(
source_validator.effective_balance,
spec,
)?;
let source_validator = state
.validators_mut()
.get_mut(consolidation.source_index as usize)
.ok_or(BeaconStateError::UnknownValidator(
consolidation.source_index as usize,
))?;
// Initiate source validator exit and append pending consolidation
source_validator.exit_epoch = exit_epoch;
source_validator.withdrawable_epoch = source_validator
.exit_epoch
.safe_add(spec.min_validator_withdrawability_delay)?;
state
.pending_consolidations_mut()?
.push(PendingConsolidation {
source_index: consolidation.source_index,
target_index: consolidation.target_index,
})?;
}
Ok(())
}