Skip to content

Commit

Permalink
feat: Implemented the process_registry_updates function (#90)
Browse files Browse the repository at this point in the history
* feat: Implemented the process_registry_updates function

* fix: moved validator functions and removed clone

* fix: fixed requested changes
  • Loading branch information
Kayden-ML authored Feb 10, 2025
1 parent 004aafe commit 41f8fce
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 21 deletions.
108 changes: 95 additions & 13 deletions crates/common/consensus/src/deneb/beacon_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;

use super::{
beacon_block::BeaconBlock, beacon_block_body::BeaconBlockBody,
execution_payload::ExecutionPayload, execution_payload_header::ExecutionPayloadHeader,
beacon_block::{BeaconBlock, SignedBeaconBlock},
beacon_block_body::BeaconBlockBody,
execution_payload::ExecutionPayload,
execution_payload_header::ExecutionPayloadHeader,
};
use crate::{
attestation::Attestation,
Expand All @@ -38,13 +40,14 @@ use crate::{
BASE_REWARD_FACTOR, BLS_WITHDRAWAL_PREFIX, CAPELLA_FORK_VERSION, CHURN_LIMIT_QUOTIENT,
DEPOSIT_CONTRACT_TREE_DEPTH, DOMAIN_BEACON_ATTESTER, DOMAIN_BEACON_PROPOSER,
DOMAIN_BLS_TO_EXECUTION_CHANGE, DOMAIN_DEPOSIT, DOMAIN_RANDAO, DOMAIN_SYNC_COMMITTEE,
DOMAIN_VOLUNTARY_EXIT, EFFECTIVE_BALANCE_INCREMENT, EPOCHS_PER_ETH1_VOTING_PERIOD,
EPOCHS_PER_HISTORICAL_VECTOR, EPOCHS_PER_SLASHINGS_VECTOR, ETH1_ADDRESS_WITHDRAWAL_PREFIX,
FAR_FUTURE_EPOCH, G2_POINT_AT_INFINITY, GENESIS_EPOCH, GENESIS_SLOT,
HYSTERESIS_DOWNWARD_MULTIPLIER, HYSTERESIS_QUOTIENT, HYSTERESIS_UPWARD_MULTIPLIER,
INACTIVITY_PENALTY_QUOTIENT_ALTAIR, INACTIVITY_SCORE_BIAS, INACTIVITY_SCORE_RECOVERY_RATE,
JUSTIFICATION_BITS_LENGTH, MAX_COMMITTEES_PER_SLOT, MAX_DEPOSITS, MAX_EFFECTIVE_BALANCE,
MAX_RANDOM_BYTE, MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP, MAX_WITHDRAWALS_PER_PAYLOAD,
DOMAIN_VOLUNTARY_EXIT, EFFECTIVE_BALANCE_INCREMENT, EJECTION_BALANCE,
EPOCHS_PER_ETH1_VOTING_PERIOD, EPOCHS_PER_HISTORICAL_VECTOR, EPOCHS_PER_SLASHINGS_VECTOR,
ETH1_ADDRESS_WITHDRAWAL_PREFIX, FAR_FUTURE_EPOCH, G2_POINT_AT_INFINITY, GENESIS_EPOCH,
GENESIS_SLOT, HYSTERESIS_DOWNWARD_MULTIPLIER, HYSTERESIS_QUOTIENT,
HYSTERESIS_UPWARD_MULTIPLIER, INACTIVITY_PENALTY_QUOTIENT_ALTAIR, INACTIVITY_SCORE_BIAS,
INACTIVITY_SCORE_RECOVERY_RATE, JUSTIFICATION_BITS_LENGTH, MAX_COMMITTEES_PER_SLOT,
MAX_DEPOSITS, MAX_EFFECTIVE_BALANCE, MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, MAX_RANDOM_BYTE,
MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP, MAX_WITHDRAWALS_PER_PAYLOAD,
MIN_ATTESTATION_INCLUSION_DELAY, MIN_EPOCHS_TO_INACTIVITY_PENALTY,
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT, MIN_GENESIS_TIME, MIN_PER_EPOCH_CHURN_LIMIT,
MIN_SEED_LOOKAHEAD, MIN_SLASHING_PENALTY_QUOTIENT, MIN_VALIDATOR_WITHDRAWABILITY_DELAY,
Expand All @@ -54,7 +57,7 @@ use crate::{
TARGET_COMMITTEE_SIZE, TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX,
TIMELY_TARGET_FLAG_INDEX, WEIGHT_DENOMINATOR, WHISTLEBLOWER_REWARD_QUOTIENT,
},
helpers::{is_active_validator, xor},
helpers::xor,
historical_summary::HistoricalSummary,
indexed_attestation::IndexedAttestation,
misc::{
Expand Down Expand Up @@ -177,7 +180,7 @@ impl BeaconState {
.iter()
.enumerate()
.filter_map(|(i, v)| {
if is_active_validator(v, epoch) {
if v.is_active_validator(epoch) {
Some(i as u64)
} else {
None
Expand Down Expand Up @@ -606,7 +609,7 @@ impl BeaconState {
let previous_epoch = self.get_previous_epoch();
let mut validator_indices = vec![];
for (index, v) in self.validators.iter().enumerate() {
if is_active_validator(v, previous_epoch)
if v.is_active_validator(previous_epoch)
|| v.slashed && previous_epoch + 1 < v.withdrawable_epoch
{
validator_indices.push(index as u64)
Expand Down Expand Up @@ -925,7 +928,7 @@ impl BeaconState {

// Verify the validator is active
ensure!(
is_active_validator(validator, self.get_current_epoch()),
validator.is_active_validator(self.get_current_epoch()),
"Validator is not active"
);

Expand Down Expand Up @@ -1527,6 +1530,85 @@ impl BeaconState {

Ok(())
}

pub fn verify_block_signature(&self, signed_block: SignedBeaconBlock) -> anyhow::Result<bool> {
let proposer = &self.validators[signed_block.message.proposer_index as usize];
let signing_root = compute_signing_root(
signed_block.message,
self.get_domain(DOMAIN_BEACON_PROPOSER, None)?,
);
let sig = blst::min_pk::Signature::from_bytes(&signed_block.signature.signature).map_err(
|err| {
anyhow!(
"Failed to convert signature to BLS Signature type, {:?}",
err
)
},
)?;
let public_key = PublicKey::from_bytes(&proposer.pubkey.inner)
.map_err(|err| anyhow!("Failed to convert pubkey to BLS PublicKey type, {:?}", err))?;
let verification_result =
sig.fast_aggregate_verify(true, signing_root.as_ref(), DST, &[&public_key]);
Ok(matches!(
verification_result,
blst::BLST_ERROR::BLST_SUCCESS
))
}

/// Check if ``validator`` is eligible for activation.
pub fn is_eligible_for_activation(&self, validator: &Validator) -> bool {
// Placement in queue is finalized
validator.activation_eligibility_epoch <= self.finalized_checkpoint.epoch
&& validator.activation_epoch == FAR_FUTURE_EPOCH
}

/// Return the validator activation churn limit for the current epoch.
pub fn get_validator_activation_churn_limit(&self) -> u64 {
min(
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT,
self.get_validator_churn_limit(),
)
}

pub fn process_registry_updates(&mut self) -> anyhow::Result<()> {
let current_epoch = self.get_current_epoch();
let mut initiate_validator = vec![];

// Process activation eligibility and ejections
for (index, validator) in self.validators.iter_mut().enumerate() {
if validator.is_eligible_for_activation_queue() {
validator.activation_eligibility_epoch = current_epoch + 1;
}

if validator.is_active_validator(current_epoch)
&& validator.effective_balance <= EJECTION_BALANCE
{
initiate_validator.push(index as u64);
}
}

for index in initiate_validator {
self.initiate_validator_exit(index);
}

// Queue validators eligible for activation and not yet dequeued for activation
let mut activation_queue: Vec<usize> = (0..self.validators.len())
// Order by the sequence of activation_eligibility_epoch setting and then index
.filter(|&index| self.is_eligible_for_activation(&self.validators[index]))
.collect();

activation_queue
.sort_by_key(|&index| (self.validators[index].activation_eligibility_epoch, index));

// Dequeued validators for activation up to activation churn limit
// [Modified in Deneb:EIP7514]
for index in activation_queue[..self.get_validator_activation_churn_limit() as usize].iter()
{
self.validators[*index].activation_epoch = compute_activation_exit_epoch(current_epoch);
}

Ok(())
}
}

/// Check if ``leaf`` at ``index`` verifies against the Merkle ``root`` and ``branch``.
Expand Down
2 changes: 2 additions & 0 deletions crates/common/consensus/src/fork_choice/helpers/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub const DOMAIN_RANDAO: B32 = fixed_bytes!("0x02000000");
pub const DOMAIN_SYNC_COMMITTEE: B32 = fixed_bytes!("0x07000000");
pub const DOMAIN_VOLUNTARY_EXIT: B32 = fixed_bytes!("0x04000000");
pub const EFFECTIVE_BALANCE_INCREMENT: u64 = 1_000_000_000;
pub const EJECTION_BALANCE: u64 = 16000000000;
pub const EPOCHS_PER_HISTORICAL_VECTOR: u64 = 65536;
pub const EPOCHS_PER_SLASHINGS_VECTOR: u64 = 8192;
pub const EPOCHS_PER_ETH1_VOTING_PERIOD: u64 = 64;
Expand Down Expand Up @@ -45,6 +46,7 @@ pub const MAX_COMMITTEES_PER_SLOT: u64 = 64;
pub const MAX_DEPOSITS: u64 = 16;
pub const MAX_SEED_LOOKAHEAD: u64 = 4;
pub const MAX_EFFECTIVE_BALANCE: u64 = 32_000_000_000;
pub const MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: u64 = 8;
pub const MAX_RANDOM_BYTE: u64 = 255;
pub const MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: usize = 16384;
pub const MAX_WITHDRAWALS_PER_PAYLOAD: u64 = 16;
Expand Down
5 changes: 0 additions & 5 deletions crates/common/consensus/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,8 @@ use crate::{
store::Store,
},
misc::compute_epoch_at_slot,
validator::Validator,
};

pub fn is_active_validator(validator: &Validator, epoch: u64) -> bool {
validator.activation_eligibility_epoch <= epoch && epoch < validator.exit_epoch
}

pub fn get_total_balance(state: &BeaconState, indices: Vec<u64>) -> u64 {
let sum = indices
.iter()
Expand Down
17 changes: 14 additions & 3 deletions crates/common/consensus/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use ssz_derive::{Decode, Encode};
use tree_hash_derive::TreeHash;

use crate::{
fork_choice::helpers::constants::{ETH1_ADDRESS_WITHDRAWAL_PREFIX, MAX_EFFECTIVE_BALANCE},
fork_choice::helpers::constants::{
ETH1_ADDRESS_WITHDRAWAL_PREFIX, FAR_FUTURE_EPOCH, MAX_EFFECTIVE_BALANCE,
},
pubkey::PubKey,
};

Expand Down Expand Up @@ -45,9 +47,18 @@ impl Validator {
&& self.effective_balance == MAX_EFFECTIVE_BALANCE
&& balance > MAX_EFFECTIVE_BALANCE
}
}
impl Validator {

pub fn is_slashable_validator(&self, epoch: u64) -> bool {
!self.slashed && self.activation_epoch <= epoch && epoch < self.withdrawable_epoch
}

pub fn is_active_validator(&self, epoch: u64) -> bool {
self.activation_eligibility_epoch <= epoch && epoch < self.exit_epoch
}

/// Check if ``validator`` is eligible to be placed into the activation queue.
pub fn is_eligible_for_activation_queue(&self) -> bool {
self.activation_eligibility_epoch == FAR_FUTURE_EPOCH
&& self.effective_balance == MAX_EFFECTIVE_BALANCE
}
}

0 comments on commit 41f8fce

Please sign in to comment.