mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-16 11:22:56 +00:00
Gloas consensus: epoch processing, block signature verification, more tests (#8808)
- [x] Implement `process_builder_pending_payments` in epoch processing for Gloas. Enable the new EF tests for this sub-component as well. - [x] Update `include_all_signatures_except_proposal` for Gloas to safely include the execution payload bid signature (this was an omission in the previous bid PR). - [x] Enable Gloas for _all_ remaining EF tests by default. They all pass with the exception of the finality tests (see below). Co-Authored-By: Michael Sproul <michael@sigmaprime.io> Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com>
This commit is contained in:
@@ -181,7 +181,7 @@ pub fn per_block_processing<E: EthSpec, Payload: AbstractExecPayload<E>>(
|
||||
let body = block.body();
|
||||
if state.fork_name_unchecked().gloas_enabled() {
|
||||
withdrawals::gloas::process_withdrawals::<E>(state, spec)?;
|
||||
// TODO(EIP-7732): process execution payload bid
|
||||
process_execution_payload_bid(state, block, verify_signatures, spec)?;
|
||||
} else {
|
||||
if state.fork_name_unchecked().capella_enabled() {
|
||||
withdrawals::capella_electra::process_withdrawals::<E, Payload>(
|
||||
|
||||
@@ -170,6 +170,7 @@ where
|
||||
self.include_exits(block)?;
|
||||
self.include_sync_aggregate(block)?;
|
||||
self.include_bls_to_execution_changes(block)?;
|
||||
self.include_execution_payload_bid(block)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -357,6 +358,27 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Include the signature of the block's execution payload bid.
|
||||
pub fn include_execution_payload_bid<Payload: AbstractExecPayload<E>>(
|
||||
&mut self,
|
||||
block: &'a SignedBeaconBlock<E, Payload>,
|
||||
) -> Result<()> {
|
||||
if let Ok(signed_execution_payload_bid) =
|
||||
block.message().body().signed_execution_payload_bid()
|
||||
{
|
||||
// TODO(gloas): if we implement a global builder pubkey cache we need to inject it here
|
||||
if let Some(signature_set) = execution_payload_bid_signature_set(
|
||||
self.state,
|
||||
|builder_index| get_builder_pubkey_from_state(self.state, builder_index),
|
||||
signed_execution_payload_bid,
|
||||
self.spec,
|
||||
)? {
|
||||
self.sets.push(signature_set);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verify all the signatures that have been included in `self`, returning `true` if and only if
|
||||
/// all the signatures are valid.
|
||||
///
|
||||
|
||||
@@ -15,9 +15,9 @@ use std::collections::{BTreeSet, HashMap};
|
||||
use tracing::instrument;
|
||||
use typenum::Unsigned;
|
||||
use types::{
|
||||
ActivationQueue, BeaconState, BeaconStateError, ChainSpec, Checkpoint, DepositData, Epoch,
|
||||
EthSpec, ExitCache, ForkName, ParticipationFlags, PendingDeposit, ProgressiveBalancesCache,
|
||||
RelativeEpoch, Validator,
|
||||
ActivationQueue, BeaconState, BeaconStateError, BuilderPendingPayment, ChainSpec, Checkpoint,
|
||||
DepositData, Epoch, EthSpec, ExitCache, ForkName, ParticipationFlags, PendingDeposit,
|
||||
ProgressiveBalancesCache, RelativeEpoch, Validator,
|
||||
consts::altair::{
|
||||
NUM_FLAG_INDICES, PARTICIPATION_FLAG_WEIGHTS, TIMELY_HEAD_FLAG_INDEX,
|
||||
TIMELY_TARGET_FLAG_INDEX, WEIGHT_DENOMINATOR,
|
||||
@@ -33,6 +33,7 @@ pub struct SinglePassConfig {
|
||||
pub pending_consolidations: bool,
|
||||
pub effective_balance_updates: bool,
|
||||
pub proposer_lookahead: bool,
|
||||
pub builder_pending_payments: bool,
|
||||
}
|
||||
|
||||
impl Default for SinglePassConfig {
|
||||
@@ -52,6 +53,7 @@ impl SinglePassConfig {
|
||||
pending_consolidations: true,
|
||||
effective_balance_updates: true,
|
||||
proposer_lookahead: true,
|
||||
builder_pending_payments: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +67,7 @@ impl SinglePassConfig {
|
||||
pending_consolidations: false,
|
||||
effective_balance_updates: false,
|
||||
proposer_lookahead: false,
|
||||
builder_pending_payments: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,6 +458,12 @@ pub fn process_epoch_single_pass<E: EthSpec>(
|
||||
)?;
|
||||
}
|
||||
|
||||
// Process builder pending payments outside the single-pass loop, as they depend on balances for
|
||||
// multiple validators and cannot be computed accurately inside the loop.
|
||||
if fork_name.gloas_enabled() && conf.builder_pending_payments {
|
||||
process_builder_pending_payments(state, state_ctxt, spec)?;
|
||||
}
|
||||
|
||||
// Finally, finish updating effective balance caches. We need this to happen *after* processing
|
||||
// of pending consolidations, which recomputes some effective balances.
|
||||
if conf.effective_balance_updates {
|
||||
@@ -503,6 +512,58 @@ pub fn process_proposer_lookahead<E: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Calculate the quorum threshold for builder payments based on total active balance.
|
||||
fn get_builder_payment_quorum_threshold<E: EthSpec>(
|
||||
state_ctxt: &StateContext,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<u64, Error> {
|
||||
let per_slot_balance = state_ctxt
|
||||
.total_active_balance
|
||||
.safe_div(E::slots_per_epoch())?;
|
||||
let quorum = per_slot_balance.safe_mul(spec.builder_payment_threshold_numerator)?;
|
||||
quorum
|
||||
.safe_div(spec.builder_payment_threshold_denominator)
|
||||
.map_err(Error::from)
|
||||
}
|
||||
|
||||
/// Processes the builder pending payments from the previous epoch.
|
||||
fn process_builder_pending_payments<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
state_ctxt: &StateContext,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let quorum = get_builder_payment_quorum_threshold::<E>(state_ctxt, spec)?;
|
||||
|
||||
// Collect qualifying payments and append to `builder_pending_withdrawals`.
|
||||
// We use this pattern rather than a loop to avoid multiple borrows of the state's fields.
|
||||
let new_pending_builder_withdrawals = state
|
||||
.builder_pending_payments()?
|
||||
.iter()
|
||||
.take(E::SlotsPerEpoch::to_usize())
|
||||
.filter(|payment| payment.weight >= quorum)
|
||||
.map(|payment| payment.withdrawal.clone())
|
||||
.collect::<Vec<_>>();
|
||||
for payment_withdrawal in new_pending_builder_withdrawals {
|
||||
state
|
||||
.builder_pending_withdrawals_mut()?
|
||||
.push(payment_withdrawal)?;
|
||||
}
|
||||
|
||||
// NOTE: this could be a little more memory-efficient with some juggling to reuse parts
|
||||
// of the persistent tree (could convert to list, use pop_front, convert back).
|
||||
let updated_payments = state
|
||||
.builder_pending_payments()?
|
||||
.iter()
|
||||
.skip(E::SlotsPerEpoch::to_usize())
|
||||
.cloned()
|
||||
.chain((0..E::SlotsPerEpoch::to_usize()).map(|_| BuilderPendingPayment::default()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
*state.builder_pending_payments_mut()? = Vector::new(updated_payments)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_single_inactivity_update(
|
||||
inactivity_score: &mut Cow<u64>,
|
||||
validator_info: &ValidatorInfo,
|
||||
|
||||
@@ -14,6 +14,7 @@ pub enum Error {
|
||||
EpochProcessingError(EpochProcessingError),
|
||||
ArithError(ArithError),
|
||||
InconsistentStateFork(InconsistentFork),
|
||||
BitfieldError(ssz::BitfieldError),
|
||||
}
|
||||
|
||||
impl From<ArithError> for Error {
|
||||
@@ -22,6 +23,12 @@ impl From<ArithError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ssz::BitfieldError> for Error {
|
||||
fn from(e: ssz::BitfieldError) -> Self {
|
||||
Self::BitfieldError(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Advances a state forward by one slot, performing per-epoch processing if required.
|
||||
///
|
||||
/// If the root of the supplied `state` is known, then it can be passed as `state_root`. If
|
||||
@@ -48,6 +55,18 @@ pub fn per_slot_processing<E: EthSpec>(
|
||||
None
|
||||
};
|
||||
|
||||
// Unset the next payload availability
|
||||
if state.fork_name_unchecked().gloas_enabled() {
|
||||
let next_slot_index = state
|
||||
.slot()
|
||||
.as_usize()
|
||||
.safe_add(1)?
|
||||
.safe_rem(E::slots_per_historical_root())?;
|
||||
state
|
||||
.execution_payload_availability_mut()?
|
||||
.set(next_slot_index, false)?;
|
||||
}
|
||||
|
||||
state.slot_mut().safe_add_assign(1)?;
|
||||
|
||||
// Process fork upgrades here. Note that multiple upgrades can potentially run
|
||||
|
||||
Reference in New Issue
Block a user