BeaconState and BeaconBlockBody mods

This commit is contained in:
shane-moore
2025-08-04 17:46:34 -07:00
committed by Mark Mackey
parent 064e8fc23c
commit 4be0b3aaab
30 changed files with 580 additions and 637 deletions

View File

@@ -167,9 +167,8 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
state.fork_mut().previous_version = spec.gloas_fork_version;
// Override latest execution payload header.
if let Some(ExecutionPayloadHeader::Gloas(header)) = execution_payload_header {
*state.latest_execution_payload_header_gloas_mut()? = header.clone();
}
// Here's where we *would* clone the header but there is no header here so..
// TODO(EIP7732): check this
}
// Now that we have our validators, initialize the caches (including the committees)

View File

@@ -30,6 +30,7 @@ pub mod deneb;
pub mod errors;
mod is_valid_indexed_attestation;
pub mod process_operations;
pub mod process_withdrawals;
pub mod signature_sets;
pub mod tests;
mod verify_attestation;
@@ -39,8 +40,6 @@ mod verify_deposit;
mod verify_exit;
mod verify_proposer_slashing;
use crate::common::decrease_balance;
use crate::common::update_progressive_balances_cache::{
initialize_progressive_balances_cache, update_progressive_balances_metrics,
};
@@ -172,10 +171,21 @@ pub fn per_block_processing<E: EthSpec, Payload: AbstractExecPayload<E>>(
// previous block.
if is_execution_enabled(state, block.body()) {
let body = block.body();
process_withdrawals::<E, Payload>(state, body.execution_payload()?, spec)?;
process_execution_payload::<E, Payload>(state, body, spec)?;
if state.fork_name_unchecked().gloas_enabled() {
process_withdrawals::gloas::process_withdrawals::<E>(state, spec)?;
} else {
process_withdrawals::capella::process_withdrawals::<E, Payload>(
state,
body.execution_payload()?,
spec,
)?;
process_execution_payload::<E, Payload>(state, body, spec)?;
}
}
// TODO(EIP-7732): build out process_execution_bid
// process_execution_bid(state, block, verify_signatures, spec)?;
process_randao(state, block, verify_randao, ctxt, spec)?;
process_eth1_data(state, block.body().eth1_data())?;
process_operations(state, block.body(), verify_signatures, ctxt, spec)?;
@@ -452,12 +462,6 @@ pub fn process_execution_payload<E: EthSpec, Payload: AbstractExecPayload<E>>(
_ => return Err(BlockProcessingError::IncorrectStateType),
}
}
ExecutionPayloadHeaderRefMut::Gloas(header_mut) => {
match payload.to_execution_payload_header() {
ExecutionPayloadHeader::Gloas(header) => *header_mut = header,
_ => return Err(BlockProcessingError::IncorrectStateType),
}
}
}
Ok(())
@@ -469,6 +473,7 @@ pub fn process_execution_payload<E: EthSpec, Payload: AbstractExecPayload<E>>(
/// repeatedly write code to treat these errors as false.
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#is_merge_transition_complete
pub fn is_merge_transition_complete<E: EthSpec>(state: &BeaconState<E>) -> bool {
// TODO(EIP7732): check this cause potuz modified this function for god knows what reason
if state.fork_name_unchecked().capella_enabled() {
true
} else if state.fork_name_unchecked().bellatrix_enabled() {
@@ -630,68 +635,3 @@ pub fn get_expected_withdrawals<E: EthSpec>(
Ok((withdrawals.into(), processed_partial_withdrawals_count))
}
/// Apply withdrawals to the state.
pub fn process_withdrawals<E: EthSpec, Payload: AbstractExecPayload<E>>(
state: &mut BeaconState<E>,
payload: Payload::Ref<'_>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
if state.fork_name_unchecked().capella_enabled() {
let (expected_withdrawals, processed_partial_withdrawals_count) =
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,
)?;
}
// Update pending partial withdrawals [New in Electra:EIP7251]
if let Some(processed_partial_withdrawals_count) = processed_partial_withdrawals_count {
state
.pending_partial_withdrawals_mut()?
.pop_front(processed_partial_withdrawals_count)?;
}
// Update the next withdrawal index if this block contained withdrawals
if let Some(latest_withdrawal) = expected_withdrawals.last() {
*state.next_withdrawal_index_mut()? = latest_withdrawal.index.safe_add(1)?;
// Update the next validator index to start the next withdrawal sweep
if expected_withdrawals.len() == E::max_withdrawals_per_payload() {
// Next sweep starts after the latest withdrawal's validator index
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;
}
}
// Advance sweep by the max length of the sweep if there was not a full set of withdrawals
if expected_withdrawals.len() != E::max_withdrawals_per_payload() {
let next_validator_index = state
.next_withdrawal_validator_index()?
.safe_add(spec.max_validators_per_withdrawals_sweep)?
.safe_rem(state.validators().len() as u64)?;
*state.next_withdrawal_validator_index_mut()? = next_validator_index;
}
Ok(())
} else {
// these shouldn't even be encountered but they're here for completeness
Ok(())
}
}

View File

@@ -0,0 +1,105 @@
use super::errors::BlockProcessingError;
use super::get_expected_withdrawals;
use crate::common::decrease_balance;
use safe_arith::SafeArith;
use tree_hash::TreeHash;
use types::{AbstractExecPayload, BeaconState, ChainSpec, EthSpec, ExecPayload, Withdrawals};
fn process_withdrawals_common<E: EthSpec>(
state: &mut BeaconState<E>,
expected_withdrawals: Withdrawals<E>,
partial_withdrawals_count: Option<usize>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
match state {
BeaconState::Capella(_)
| BeaconState::Deneb(_)
| BeaconState::Electra(_)
| BeaconState::Fulu(_)
| BeaconState::Gloas(_) => {
for withdrawal in expected_withdrawals.iter() {
decrease_balance(
state,
withdrawal.validator_index as usize,
withdrawal.amount,
)?;
}
// Update pending partial withdrawals [New in Electra:EIP7251]
if let Some(partial_withdrawals_count) = partial_withdrawals_count {
state
.pending_partial_withdrawals_mut()?
.pop_front(partial_withdrawals_count)?;
}
// Update the next withdrawal index if this block contained withdrawals
if let Some(latest_withdrawal) = expected_withdrawals.last() {
*state.next_withdrawal_index_mut()? = latest_withdrawal.index.safe_add(1)?;
// Update the next validator index to start the next withdrawal sweep
if expected_withdrawals.len() == E::max_withdrawals_per_payload() {
// Next sweep starts after the latest withdrawal's validator index
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;
}
}
// Advance sweep by the max length of the sweep if there was not a full set of withdrawals
if expected_withdrawals.len() != E::max_withdrawals_per_payload() {
let next_validator_index = state
.next_withdrawal_validator_index()?
.safe_add(spec.max_validators_per_withdrawals_sweep)?
.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(_) | BeaconState::Bellatrix(_) => Ok(()),
}
}
pub mod capella {
use super::*;
/// Apply withdrawals to the state.
pub fn process_withdrawals<E: EthSpec, Payload: AbstractExecPayload<E>>(
state: &mut BeaconState<E>,
payload: Payload::Ref<'_>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
let (expected_withdrawals, partial_withdrawals_count) =
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,
});
}
process_withdrawals_common(state, expected_withdrawals, partial_withdrawals_count, spec)
}
}
pub mod gloas {
use super::*;
/// Apply withdrawals to the state.
pub fn process_withdrawals<E: EthSpec>(
state: &mut BeaconState<E>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
if !state.is_parent_block_full() {
return Ok(());
}
let (expected_withdrawals, partial_withdrawals_count) =
get_expected_withdrawals(state, spec)?;
process_withdrawals_common(state, expected_withdrawals, partial_withdrawals_count, spec)
}
}

View File

@@ -1,5 +1,9 @@
use bls::Hash256;
use std::mem;
use types::{BeaconState, BeaconStateError as Error, BeaconStateGloas, ChainSpec, EthSpec, Fork};
use types::{
BeaconState, BeaconStateError as Error, BeaconStateGloas, BitVector, ChainSpec, EthSpec,
ExecutionBid, Fork, List, Vector,
};
/// Transform a `Fulu` state into a `Gloas` state.
pub fn upgrade_to_gloas<E: EthSpec>(
@@ -63,8 +67,8 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
// Sync committees
current_sync_committee: pre.current_sync_committee.clone(),
next_sync_committee: pre.next_sync_committee.clone(),
// Execution
latest_execution_payload_header: pre.latest_execution_payload_header.upgrade_to_gloas(),
// Execution Bid
latest_execution_bid: ExecutionBid::default(),
// Capella
next_withdrawal_index: pre.next_withdrawal_index,
next_withdrawal_validator_index: pre.next_withdrawal_validator_index,
@@ -79,6 +83,13 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
pending_deposits: pre.pending_deposits.clone(),
pending_partial_withdrawals: pre.pending_partial_withdrawals.clone(),
pending_consolidations: pre.pending_consolidations.clone(),
// Gloas
execution_payload_availability: BitVector::default(), // All bits set to false initially
builder_pending_payments: Vector::default(), // Empty vector initially,
builder_pending_withdrawals: List::default(), // Empty list initially,
latest_block_hash: pre.latest_execution_payload_header.block_hash,
latest_full_slot: pre.slot,
latest_withdrawals_root: Hash256::default(),
// Caches
total_active_balance: pre.total_active_balance,
progressive_balances_cache: mem::take(&mut pre.progressive_balances_cache),