Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Electra epoch processing #387

Merged
merged 20 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2a110b1
Create `epoch_processing` module and `process_registry_updates()`
EchoAlice Apr 22, 2024
41856d0
Refactor `process_registry_updates()`
EchoAlice Apr 22, 2024
e2f5360
Iterates on feedback
EchoAlice Apr 23, 2024
716ec88
Create `process_pending_balance_deposits()`
EchoAlice Apr 23, 2024
7c399d7
Change return type for functions. Remove .vscode dir
EchoAlice Apr 24, 2024
8c743f9
Remove .vscode from .gitignore
EchoAlice Apr 24, 2024
43141fa
Refactor `process_pending_balance_deposits()`. Add empty line to end…
EchoAlice Apr 26, 2024
9e15072
Implement `process_pending_consolidations()`
EchoAlice Apr 26, 2024
a40929a
Refactor state field lists to use `.drain()`. Convert `== 0` check t…
EchoAlice Apr 26, 2024
05fe2eb
Rebase
EchoAlice Apr 29, 2024
10cd7a3
Run spec-gen
EchoAlice Apr 29, 2024
8bde8d2
Add `execution_engine` back to `mod.rs`. Remove const generic params …
EchoAlice Apr 29, 2024
f4000a7
Replace `unwrap()` with `map_err()`
EchoAlice Apr 29, 2024
9d1fccf
Refactor imports into a fully-qualified manner from the crate root
EchoAlice Apr 30, 2024
fae6e60
Refactor logic using `.drain()`
EchoAlice Apr 30, 2024
5b9172f
Implement `process_epoch`. Remove unnessesary const generics from `p…
EchoAlice May 6, 2024
3ef9f22
Create `process_effective_balance_updates()`
EchoAlice May 6, 2024
193d28f
Remove `process_epoch` and `process_effective_balance_updates` from `…
EchoAlice May 6, 2024
f5e8328
Leverage `context` to import balance constants
EchoAlice May 7, 2024
d4d8249
Fix clippy warning
EchoAlice May 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
296 changes: 296 additions & 0 deletions ethereum-consensus/src/electra/epoch_processing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
use crate::{
electra::{
compute_activation_exit_epoch, decrease_balance, get_current_epoch,
has_compounding_withdrawal_credential,
helpers::{
get_activation_exit_churn_limit, get_active_balance, initiate_validator_exit,
is_eligible_for_activation_queue, switch_to_compounding_validator,
},
increase_balance, is_active_validator, is_eligible_for_activation, process_eth1_data_reset,
process_historical_summaries_update, process_inactivity_updates,
process_justification_and_finalization, process_participation_flag_updates,
process_randao_mixes_reset, process_rewards_and_penalties, process_slashings,
process_slashings_reset, process_sync_committee_updates, BeaconState, Context, Error,
},
primitives::Gwei,
};

pub fn process_epoch<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
const ETH1_DATA_VOTES_BOUND: usize,
const VALIDATOR_REGISTRY_LIMIT: usize,
const EPOCHS_PER_HISTORICAL_VECTOR: usize,
const EPOCHS_PER_SLASHINGS_VECTOR: usize,
const MAX_VALIDATORS_PER_COMMITTEE: usize,
const SYNC_COMMITTEE_SIZE: usize,
const BYTES_PER_LOGS_BLOOM: usize,
const MAX_EXTRA_DATA_BYTES: usize,
const PENDING_BALANCE_DEPOSITS_LIMIT: usize,
const PENDING_PARTIAL_WITHDRAWALS_LIMIT: usize,
const PENDING_CONSOLIDATIONS_LIMIT: usize,
>(
state: &mut BeaconState<
SLOTS_PER_HISTORICAL_ROOT,
HISTORICAL_ROOTS_LIMIT,
ETH1_DATA_VOTES_BOUND,
VALIDATOR_REGISTRY_LIMIT,
EPOCHS_PER_HISTORICAL_VECTOR,
EPOCHS_PER_SLASHINGS_VECTOR,
MAX_VALIDATORS_PER_COMMITTEE,
SYNC_COMMITTEE_SIZE,
BYTES_PER_LOGS_BLOOM,
MAX_EXTRA_DATA_BYTES,
PENDING_BALANCE_DEPOSITS_LIMIT,
PENDING_PARTIAL_WITHDRAWALS_LIMIT,
PENDING_CONSOLIDATIONS_LIMIT,
>,
context: &Context,
) -> Result<(), Error> {
process_justification_and_finalization(state, context)?;
process_inactivity_updates(state, context)?;
process_rewards_and_penalties(state, context)?;
process_registry_updates(state, context)?;
process_slashings(state, context)?;
process_eth1_data_reset(state, context);
process_pending_balance_deposits(state, context)?;
process_pending_consolidations(state, context)?;
process_effective_balance_updates(state, context);
process_slashings_reset(state, context);
process_randao_mixes_reset(state, context);
process_historical_summaries_update(state, context)?;
process_participation_flag_updates(state)?;
process_sync_committee_updates(state, context)?;
Ok(())
}

pub fn process_registry_updates<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
const ETH1_DATA_VOTES_BOUND: usize,
const VALIDATOR_REGISTRY_LIMIT: usize,
const EPOCHS_PER_HISTORICAL_VECTOR: usize,
const EPOCHS_PER_SLASHINGS_VECTOR: usize,
const MAX_VALIDATORS_PER_COMMITTEE: usize,
const SYNC_COMMITTEE_SIZE: usize,
const BYTES_PER_LOGS_BLOOM: usize,
const MAX_EXTRA_DATA_BYTES: usize,
const PENDING_BALANCE_DEPOSITS_LIMIT: usize,
const PENDING_PARTIAL_WITHDRAWALS_LIMIT: usize,
const PENDING_CONSOLIDATIONS_LIMIT: usize,
>(
state: &mut BeaconState<
SLOTS_PER_HISTORICAL_ROOT,
HISTORICAL_ROOTS_LIMIT,
ETH1_DATA_VOTES_BOUND,
VALIDATOR_REGISTRY_LIMIT,
EPOCHS_PER_HISTORICAL_VECTOR,
EPOCHS_PER_SLASHINGS_VECTOR,
MAX_VALIDATORS_PER_COMMITTEE,
SYNC_COMMITTEE_SIZE,
BYTES_PER_LOGS_BLOOM,
MAX_EXTRA_DATA_BYTES,
PENDING_BALANCE_DEPOSITS_LIMIT,
PENDING_PARTIAL_WITHDRAWALS_LIMIT,
PENDING_CONSOLIDATIONS_LIMIT,
>,
context: &Context,
) -> Result<(), Error> {
let current_epoch = get_current_epoch(state, context);
for i in 0..state.validators.len() {
let validator = &mut state.validators[i];
if is_eligible_for_activation_queue(validator, context) {
validator.activation_eligibility_epoch = current_epoch + 1;
}
if is_active_validator(validator, current_epoch) &&
validator.effective_balance <= context.ejection_balance
{
initiate_validator_exit(state, i, context)?;
}
}

let activation_epoch = compute_activation_exit_epoch(current_epoch, context);
for i in 0..state.validators.len() {
let validator = &state.validators[i];
if is_eligible_for_activation(state, validator) {
let validator = &mut state.validators[i];
validator.activation_epoch = activation_epoch;
ralexstokes marked this conversation as resolved.
Show resolved Hide resolved
}
}

Ok(())
}

pub fn process_pending_balance_deposits<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
const ETH1_DATA_VOTES_BOUND: usize,
const VALIDATOR_REGISTRY_LIMIT: usize,
const EPOCHS_PER_HISTORICAL_VECTOR: usize,
const EPOCHS_PER_SLASHINGS_VECTOR: usize,
const MAX_VALIDATORS_PER_COMMITTEE: usize,
const SYNC_COMMITTEE_SIZE: usize,
const BYTES_PER_LOGS_BLOOM: usize,
const MAX_EXTRA_DATA_BYTES: usize,
const PENDING_BALANCE_DEPOSITS_LIMIT: usize,
const PENDING_PARTIAL_WITHDRAWALS_LIMIT: usize,
const PENDING_CONSOLIDATIONS_LIMIT: usize,
>(
state: &mut BeaconState<
SLOTS_PER_HISTORICAL_ROOT,
HISTORICAL_ROOTS_LIMIT,
ETH1_DATA_VOTES_BOUND,
VALIDATOR_REGISTRY_LIMIT,
EPOCHS_PER_HISTORICAL_VECTOR,
EPOCHS_PER_SLASHINGS_VECTOR,
MAX_VALIDATORS_PER_COMMITTEE,
SYNC_COMMITTEE_SIZE,
BYTES_PER_LOGS_BLOOM,
MAX_EXTRA_DATA_BYTES,
PENDING_BALANCE_DEPOSITS_LIMIT,
PENDING_PARTIAL_WITHDRAWALS_LIMIT,
PENDING_CONSOLIDATIONS_LIMIT,
>,
context: &Context,
) -> Result<(), Error> {
let available_for_processing =
state.deposit_balance_to_consume + get_activation_exit_churn_limit(state, context)?;
let mut processed_amount = 0;
let mut next_deposit_index = 0;

for i in 0..state.pending_balance_deposits.len() {
let deposit = &state.pending_balance_deposits[i];
let index = deposit.index;
let amount = deposit.amount;
if processed_amount + deposit.amount > available_for_processing {
break
}
increase_balance(state, index, amount);
processed_amount += amount;
next_deposit_index += 1;
}

state.pending_balance_deposits.drain(..next_deposit_index);

if state.pending_balance_deposits.is_empty() {
state.deposit_balance_to_consume = 0;
} else {
state.deposit_balance_to_consume = available_for_processing - processed_amount;
}

Ok(())
}

pub fn process_pending_consolidations<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
const ETH1_DATA_VOTES_BOUND: usize,
const VALIDATOR_REGISTRY_LIMIT: usize,
const EPOCHS_PER_HISTORICAL_VECTOR: usize,
const EPOCHS_PER_SLASHINGS_VECTOR: usize,
const MAX_VALIDATORS_PER_COMMITTEE: usize,
const SYNC_COMMITTEE_SIZE: usize,
const BYTES_PER_LOGS_BLOOM: usize,
const MAX_EXTRA_DATA_BYTES: usize,
const PENDING_BALANCE_DEPOSITS_LIMIT: usize,
const PENDING_PARTIAL_WITHDRAWALS_LIMIT: usize,
const PENDING_CONSOLIDATIONS_LIMIT: usize,
>(
state: &mut BeaconState<
SLOTS_PER_HISTORICAL_ROOT,
HISTORICAL_ROOTS_LIMIT,
ETH1_DATA_VOTES_BOUND,
VALIDATOR_REGISTRY_LIMIT,
EPOCHS_PER_HISTORICAL_VECTOR,
EPOCHS_PER_SLASHINGS_VECTOR,
MAX_VALIDATORS_PER_COMMITTEE,
SYNC_COMMITTEE_SIZE,
BYTES_PER_LOGS_BLOOM,
MAX_EXTRA_DATA_BYTES,
PENDING_BALANCE_DEPOSITS_LIMIT,
PENDING_PARTIAL_WITHDRAWALS_LIMIT,
PENDING_CONSOLIDATIONS_LIMIT,
>,
context: &Context,
) -> Result<(), Error> {
let mut next_pending_consolidation = 0;
for i in 0..state.pending_consolidations.len() {
let pending_consolidation = &state.pending_consolidations[i];
let source_index = pending_consolidation.source_index;
let target_index = pending_consolidation.target_index;
let source_validator = &state.validators[source_index];
if source_validator.slashed {
next_pending_consolidation += 1;
continue
}
if source_validator.withdrawable_epoch > get_current_epoch(state, context) {
break
}

switch_to_compounding_validator(state, target_index, context)?;
let active_balance = get_active_balance(state, source_index, context);
decrease_balance(state, source_index, active_balance);
increase_balance(state, target_index, active_balance);
next_pending_consolidation += 1;
}

state.pending_consolidations.drain(..next_pending_consolidation);

Ok(())
}

pub fn process_effective_balance_updates<
const SLOTS_PER_HISTORICAL_ROOT: usize,
const HISTORICAL_ROOTS_LIMIT: usize,
const ETH1_DATA_VOTES_BOUND: usize,
const VALIDATOR_REGISTRY_LIMIT: usize,
const EPOCHS_PER_HISTORICAL_VECTOR: usize,
const EPOCHS_PER_SLASHINGS_VECTOR: usize,
const MAX_VALIDATORS_PER_COMMITTEE: usize,
const SYNC_COMMITTEE_SIZE: usize,
const BYTES_PER_LOGS_BLOOM: usize,
const MAX_EXTRA_DATA_BYTES: usize,
const PENDING_BALANCE_DEPOSITS_LIMIT: usize,
const PENDING_PARTIAL_WITHDRAWALS_LIMIT: usize,
const PENDING_CONSOLIDATIONS_LIMIT: usize,
>(
state: &mut BeaconState<
SLOTS_PER_HISTORICAL_ROOT,
HISTORICAL_ROOTS_LIMIT,
ETH1_DATA_VOTES_BOUND,
VALIDATOR_REGISTRY_LIMIT,
EPOCHS_PER_HISTORICAL_VECTOR,
EPOCHS_PER_SLASHINGS_VECTOR,
MAX_VALIDATORS_PER_COMMITTEE,
SYNC_COMMITTEE_SIZE,
BYTES_PER_LOGS_BLOOM,
MAX_EXTRA_DATA_BYTES,
PENDING_BALANCE_DEPOSITS_LIMIT,
PENDING_PARTIAL_WITHDRAWALS_LIMIT,
PENDING_CONSOLIDATIONS_LIMIT,
>,
context: &Context,
) {
// Update effective balances with hysteresis
let hysteresis_increment = context.effective_balance_increment / context.hysteresis_quotient;
let downward_threshold = hysteresis_increment * context.hysteresis_downward_multiplier;
let upward_threshold = hysteresis_increment * context.hysteresis_upward_multiplier;
for i in 0..state.validators.len() {
let validator = &mut state.validators[i];
let balance = state.balances[i];
let effective_balance_limit = if has_compounding_withdrawal_credential(validator) {
context.max_effective_balance_electra
} else {
context.min_activation_balance
};

if balance + downward_threshold < validator.effective_balance ||
validator.effective_balance + upward_threshold < balance
{
validator.effective_balance = Gwei::min(
balance - balance % context.effective_balance_increment,
effective_balance_limit,
);
}
}
}
1 change: 1 addition & 0 deletions ethereum-consensus/src/electra/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod beacon_block;
pub mod beacon_state;
pub mod block_processing;
pub mod constants;
pub mod epoch_processing;
pub mod execution_engine;
pub mod execution_payload;
pub mod fork;
Expand Down
Loading
Loading