mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-01 03:44:30 +00:00
Gloas alpha spec 11 (#9511)
Alpha spec 11 changes Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu> Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
@@ -11,7 +11,10 @@ use signature_sets::{
|
||||
use std::borrow::Cow;
|
||||
use tree_hash::TreeHash;
|
||||
use typenum::Unsigned;
|
||||
use types::{consts::gloas::BUILDER_INDEX_SELF_BUILD, *};
|
||||
use types::{
|
||||
consts::gloas::{BUILDER_INDEX_SELF_BUILD, PAYLOAD_BUILDER_VERSION},
|
||||
*,
|
||||
};
|
||||
|
||||
pub use self::verify_attester_slashing::{
|
||||
get_slashable_indices, get_slashable_indices_modular, verify_attester_slashing,
|
||||
@@ -189,7 +192,8 @@ 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)?;
|
||||
process_execution_payload_bid(state, block, verify_signatures, spec)?;
|
||||
let signed_bid = block.body().signed_execution_payload_bid()?;
|
||||
process_execution_payload_bid(state, signed_bid, verify_signatures, spec)?;
|
||||
} else {
|
||||
if state.fork_name_unchecked().capella_enabled() {
|
||||
withdrawals::capella_electra::process_withdrawals::<E, Payload>(
|
||||
@@ -561,7 +565,7 @@ pub fn process_parent_execution_payload<E: EthSpec, Payload: AbstractExecPayload
|
||||
if bid_parent_block_hash != parent_bid.block_hash {
|
||||
// Parent was EMPTY -- no execution requests expected
|
||||
block_verify!(
|
||||
*requests == ExecutionRequests::default(),
|
||||
*requests == ExecutionRequestsGloas::default(),
|
||||
BlockProcessingError::NonEmptyParentExecutionRequests
|
||||
);
|
||||
return Ok(());
|
||||
@@ -588,7 +592,7 @@ pub fn process_parent_execution_payload<E: EthSpec, Payload: AbstractExecPayload
|
||||
/// 3. Updates `execution_payload_availability` and `latest_block_hash`
|
||||
pub fn apply_parent_execution_payload<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
requests: &ExecutionRequests<E>,
|
||||
requests: &ExecutionRequestsGloas<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
let parent_bid = state.latest_execution_payload_bid()?.clone();
|
||||
@@ -596,9 +600,11 @@ pub fn apply_parent_execution_payload<E: EthSpec>(
|
||||
let parent_epoch = parent_slot.epoch(E::slots_per_epoch());
|
||||
|
||||
// Process execution requests from the parent's payload
|
||||
process_operations::process_deposit_requests_post_gloas(state, &requests.deposits, spec)?;
|
||||
process_operations::process_deposit_requests(state, &requests.deposits, spec)?;
|
||||
process_operations::process_withdrawal_requests(state, &requests.withdrawals, spec)?;
|
||||
process_operations::process_consolidation_requests(state, &requests.consolidations, spec)?;
|
||||
process_operations::process_builder_deposit_requests(state, &requests.builder_deposits, spec)?;
|
||||
process_operations::process_builder_exit_requests(state, &requests.builder_exits, spec)?;
|
||||
|
||||
// Queue the builder payment
|
||||
if parent_epoch == state.current_epoch() {
|
||||
@@ -666,15 +672,13 @@ pub fn settle_builder_payment<E: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_execution_payload_bid<E: EthSpec, Payload: AbstractExecPayload<E>>(
|
||||
pub fn process_execution_payload_bid<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
block: BeaconBlockRef<'_, E, Payload>,
|
||||
signed_bid: &SignedExecutionPayloadBid<E>,
|
||||
verify_signatures: VerifySignatures,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
// Verify the bid signature
|
||||
let signed_bid = block.body().signed_execution_payload_bid()?;
|
||||
|
||||
let bid = &signed_bid.message;
|
||||
let amount = bid.value;
|
||||
let builder_index = bid.builder_index;
|
||||
@@ -698,6 +702,16 @@ pub fn process_execution_payload_bid<E: EthSpec, Payload: AbstractExecPayload<E>
|
||||
ExecutionPayloadBidInvalid::BuilderNotActive(builder_index).into()
|
||||
);
|
||||
|
||||
// Verify that the builder is a payload builder
|
||||
block_verify!(
|
||||
builder.version == PAYLOAD_BUILDER_VERSION,
|
||||
ExecutionPayloadBidInvalid::InvalidBuilderVersion {
|
||||
builder_index,
|
||||
version: builder.version,
|
||||
}
|
||||
.into()
|
||||
);
|
||||
|
||||
// Verify that the builder has funds to cover the bid
|
||||
block_verify!(
|
||||
state.can_builder_cover_bid(builder_index, amount, spec)?,
|
||||
@@ -739,10 +753,10 @@ pub fn process_execution_payload_bid<E: EthSpec, Payload: AbstractExecPayload<E>
|
||||
|
||||
// Verify that the bid is for the current slot
|
||||
block_verify!(
|
||||
bid.slot == block.slot(),
|
||||
bid.slot == state.slot(),
|
||||
ExecutionPayloadBidInvalid::SlotMismatch {
|
||||
bid_slot: bid.slot,
|
||||
block_slot: block.slot(),
|
||||
state_slot: state.slot(),
|
||||
}
|
||||
.into()
|
||||
);
|
||||
@@ -758,10 +772,11 @@ pub fn process_execution_payload_bid<E: EthSpec, Payload: AbstractExecPayload<E>
|
||||
.into()
|
||||
);
|
||||
|
||||
let expected_parent_root = *state.get_block_root(state.slot().safe_sub(1)?)?;
|
||||
block_verify!(
|
||||
bid.parent_block_root == block.parent_root(),
|
||||
bid.parent_block_root == expected_parent_root,
|
||||
ExecutionPayloadBidInvalid::ParentBlockRootMismatch {
|
||||
block_parent_root: block.parent_root(),
|
||||
block_parent_root: expected_parent_root,
|
||||
bid_parent_root: bid.parent_block_root,
|
||||
}
|
||||
.into()
|
||||
@@ -779,6 +794,7 @@ pub fn process_execution_payload_bid<E: EthSpec, Payload: AbstractExecPayload<E>
|
||||
|
||||
// Record the pending payment if there is some payment
|
||||
if amount > 0 {
|
||||
let proposer_index = state.get_beacon_proposer_index(state.slot(), spec)? as u64;
|
||||
let pending_payment = BuilderPendingPayment {
|
||||
weight: 0,
|
||||
withdrawal: BuilderPendingWithdrawal {
|
||||
@@ -786,6 +802,7 @@ pub fn process_execution_payload_bid<E: EthSpec, Payload: AbstractExecPayload<E>
|
||||
amount,
|
||||
builder_index,
|
||||
},
|
||||
proposer_index,
|
||||
};
|
||||
|
||||
let payment_index = E::SlotsPerEpoch::to_usize()
|
||||
|
||||
@@ -527,14 +527,16 @@ pub enum ExecutionPayloadBidInvalid {
|
||||
BadSignature,
|
||||
/// The builder is not active.
|
||||
BuilderNotActive(u64),
|
||||
/// The builder's version is not `PAYLOAD_BUILDER_VERSION`.
|
||||
InvalidBuilderVersion { builder_index: u64, version: u8 },
|
||||
/// The builder has insufficient balance to cover the bid
|
||||
InsufficientBalance {
|
||||
builder_index: u64,
|
||||
builder_balance: u64,
|
||||
bid_value: u64,
|
||||
},
|
||||
/// Bid slot doesn't match block slot
|
||||
SlotMismatch { bid_slot: Slot, block_slot: Slot },
|
||||
/// Bid slot doesn't match state slot
|
||||
SlotMismatch { bid_slot: Slot, state_slot: Slot },
|
||||
/// The bid's parent block hash doesn't match the state's latest block hash
|
||||
ParentBlockHashMismatch {
|
||||
state_block_hash: ExecutionBlockHash,
|
||||
|
||||
@@ -4,13 +4,9 @@ use crate::common::{
|
||||
get_attestation_participation_flag_indices, increase_balance, initiate_validator_exit,
|
||||
slash_validator,
|
||||
};
|
||||
use crate::per_block_processing::builder::{
|
||||
convert_validator_index_to_builder_index, is_builder_index,
|
||||
};
|
||||
use crate::per_block_processing::errors::{BlockProcessingError, ExitInvalid, IntoWithIndex};
|
||||
use crate::per_block_processing::signature_sets::{exit_signature_set, get_pubkey_from_state};
|
||||
use crate::per_block_processing::verify_payload_attestation::verify_payload_attestation;
|
||||
use bls::{PublicKeyBytes, SignatureBytes};
|
||||
use bls::PublicKeyBytes;
|
||||
use ssz_types::FixedVector;
|
||||
use typenum::U33;
|
||||
use types::consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_DENOMINATOR};
|
||||
@@ -54,11 +50,7 @@ pub fn process_operations<E: EthSpec, Payload: AbstractExecPayload<E>>(
|
||||
)?;
|
||||
} else if state.fork_name_unchecked().electra_enabled() {
|
||||
state.update_pubkey_cache()?;
|
||||
process_deposit_requests_pre_gloas(
|
||||
state,
|
||||
&block_body.execution_requests()?.deposits,
|
||||
spec,
|
||||
)?;
|
||||
process_deposit_requests(state, &block_body.execution_requests()?.deposits, spec)?;
|
||||
process_withdrawal_requests(state, &block_body.execution_requests()?.withdrawals, spec)?;
|
||||
process_consolidation_requests(
|
||||
state,
|
||||
@@ -397,7 +389,9 @@ pub fn process_proposer_slashings<E: EthSpec>(
|
||||
|
||||
// [New in Gloas:EIP7732]
|
||||
// Remove the BuilderPendingPayment corresponding to this proposal
|
||||
// if it is still in the 2-epoch window.
|
||||
// if it is still in the 2-epoch window. Only clear it when the slashed validator is
|
||||
// the proposer associated with the payment; otherwise an unrelated same-slot
|
||||
// equivocation could grief an honest proposer's payment.
|
||||
if state.fork_name_unchecked().gloas_enabled() {
|
||||
let slot = proposer_slashing.signed_header_1.message.slot;
|
||||
let proposal_epoch = slot.epoch(E::slots_per_epoch());
|
||||
@@ -416,7 +410,12 @@ pub fn process_proposer_slashings<E: EthSpec>(
|
||||
.builder_pending_payments_mut()?
|
||||
.get_mut(index)
|
||||
.ok_or(BlockProcessingError::BuilderPaymentIndexOutOfBounds(index))?;
|
||||
*payment = BuilderPendingPayment::default();
|
||||
|
||||
if payment.proposer_index
|
||||
== proposer_slashing.signed_header_1.message.proposer_index
|
||||
{
|
||||
*payment = BuilderPendingPayment::default();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,15 +520,6 @@ pub fn process_exits<E: EthSpec>(
|
||||
.into_with_index(i));
|
||||
}
|
||||
|
||||
// [New in Gloas:EIP7732]
|
||||
if state.fork_name_unchecked().gloas_enabled()
|
||||
&& is_builder_index(exit.message.validator_index)
|
||||
{
|
||||
process_builder_voluntary_exit(state, exit, verify_signatures, spec)
|
||||
.map_err(|e| e.into_with_index(i))?;
|
||||
continue;
|
||||
}
|
||||
|
||||
verify_exit(state, Some(current_epoch), exit, verify_signatures, spec)
|
||||
.map_err(|e| e.into_with_index(i))?;
|
||||
|
||||
@@ -538,59 +528,6 @@ pub fn process_exits<E: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Process a builder voluntary exit. [New in Gloas:EIP7732]
|
||||
fn process_builder_voluntary_exit<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
signed_exit: &SignedVoluntaryExit,
|
||||
verify_signatures: VerifySignatures,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockOperationError<ExitInvalid>> {
|
||||
let builder_index =
|
||||
convert_validator_index_to_builder_index(signed_exit.message.validator_index);
|
||||
|
||||
// Verify builder is known
|
||||
state
|
||||
.builders()?
|
||||
.get(builder_index as usize)
|
||||
.cloned()
|
||||
.ok_or(BlockOperationError::invalid(ExitInvalid::ValidatorUnknown(
|
||||
signed_exit.message.validator_index,
|
||||
)))?;
|
||||
|
||||
// Verify the builder is active
|
||||
if !state.is_active_builder(builder_index, spec)? {
|
||||
return Err(BlockOperationError::invalid(ExitInvalid::NotActive(
|
||||
signed_exit.message.validator_index,
|
||||
)));
|
||||
}
|
||||
|
||||
// Only exit builder if it has no pending withdrawals in the queue
|
||||
let pending_balance = state.get_pending_balance_to_withdraw_for_builder(builder_index)?;
|
||||
if pending_balance != 0 {
|
||||
return Err(BlockOperationError::invalid(
|
||||
ExitInvalid::PendingWithdrawalInQueue(signed_exit.message.validator_index),
|
||||
));
|
||||
}
|
||||
|
||||
if verify_signatures.is_true() {
|
||||
verify!(
|
||||
exit_signature_set(
|
||||
state,
|
||||
|i| get_pubkey_from_state(state, i),
|
||||
signed_exit,
|
||||
spec
|
||||
)?
|
||||
.verify(),
|
||||
ExitInvalid::BadSignature
|
||||
);
|
||||
}
|
||||
|
||||
// Initiate builder exit
|
||||
initiate_builder_exit(state, builder_index, spec)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initiate the exit of a builder. [New in Gloas:EIP7732]
|
||||
fn initiate_builder_exit<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
@@ -874,7 +811,7 @@ pub fn process_withdrawal_requests<E: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_deposit_requests_pre_gloas<E: EthSpec>(
|
||||
pub fn process_deposit_requests<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
deposit_requests: &[DepositRequest],
|
||||
spec: &ChainSpec,
|
||||
@@ -904,18 +841,111 @@ pub fn process_deposit_requests_pre_gloas<E: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_deposit_requests_post_gloas<E: EthSpec>(
|
||||
pub fn process_builder_deposit_requests<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
deposit_requests: &[DepositRequest],
|
||||
builder_deposit_requests: &[BuilderDepositRequest],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
for request in deposit_requests {
|
||||
process_deposit_request_post_gloas(state, request, spec)?;
|
||||
for builder_deposit_request in builder_deposit_requests {
|
||||
process_builder_deposit_request(state, builder_deposit_request, spec)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_builder_deposit_request<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
builder_deposit_request: &BuilderDepositRequest,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
let builder_index = state
|
||||
.builders()?
|
||||
.iter()
|
||||
.position(|builder| builder.pubkey == builder_deposit_request.pubkey);
|
||||
|
||||
match builder_index {
|
||||
None => {
|
||||
if builder_deposit_request.is_valid_builder_deposit_signature(spec) {
|
||||
let version = builder_deposit_request
|
||||
.version()
|
||||
.ok_or(BeaconStateError::WithdrawalCredentialMissingVersion)?;
|
||||
let slot = state.slot();
|
||||
state.add_builder_to_registry(
|
||||
builder_deposit_request.pubkey,
|
||||
version,
|
||||
builder_deposit_request.withdrawal_credentials,
|
||||
builder_deposit_request.amount,
|
||||
slot,
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Some(builder_index) => {
|
||||
let current_epoch = state.current_epoch();
|
||||
let builder = state
|
||||
.builders_mut()?
|
||||
.get_mut(builder_index)
|
||||
.ok_or(BeaconStateError::UnknownBuilder(builder_index as u64))?;
|
||||
|
||||
// TODO(gloas): this is already different in `master`, needs an update when we go
|
||||
// to spec 1.7.0-alpha.12+
|
||||
builder
|
||||
.balance
|
||||
.safe_add_assign(builder_deposit_request.amount)?;
|
||||
|
||||
if builder.withdrawable_epoch != spec.far_future_epoch {
|
||||
builder.withdrawable_epoch =
|
||||
current_epoch.safe_add(spec.min_builder_withdrawability_delay)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_builder_exit_requests<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
builder_exit_requests: &[BuilderExitRequest],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
for builder_exit_request in builder_exit_requests {
|
||||
process_builder_exit_request(state, builder_exit_request, spec)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_builder_exit_request<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
builder_exit_request: &BuilderExitRequest,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
let Some(builder_index) = state
|
||||
.builders()?
|
||||
.iter()
|
||||
.position(|builder| builder.pubkey == builder_exit_request.pubkey)
|
||||
.map(|i| i as u64)
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
if !state.is_active_builder(builder_index, spec)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if state.get_builder(builder_index)?.execution_address != builder_exit_request.source_address {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if state.get_pending_balance_to_withdraw_for_builder(builder_index)? != 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
initiate_builder_exit(state, builder_index, spec)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check if there is a pending deposit for a new validator with the given pubkey.
|
||||
// TODO(gloas): cache the deposit signature validation or remove this loop entirely if possible,
|
||||
// it is `O(n * m)` where `n` is max 8192 and `m` is max 128M.
|
||||
@@ -939,107 +969,6 @@ pub fn is_pending_validator<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_deposit_request_post_gloas<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
deposit_request: &DepositRequest,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
// [New in Gloas:EIP7732]
|
||||
// Regardless of the withdrawal credentials prefix, if a builder/validator
|
||||
// already exists with this pubkey, apply the deposit to their balance
|
||||
// TODO(gloas): this could be more efficient in the builder case, see:
|
||||
// https://github.com/sigp/lighthouse/issues/8783
|
||||
let builder_index = state
|
||||
.builders()?
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, builder)| builder.pubkey == deposit_request.pubkey)
|
||||
.map(|(i, _)| i as u64);
|
||||
let is_builder = builder_index.is_some();
|
||||
|
||||
let validator_index = state.get_validator_index(&deposit_request.pubkey)?;
|
||||
let is_validator = validator_index.is_some();
|
||||
|
||||
let has_builder_prefix =
|
||||
is_builder_withdrawal_credential(deposit_request.withdrawal_credentials, spec);
|
||||
|
||||
if is_builder
|
||||
|| (has_builder_prefix
|
||||
&& !is_validator
|
||||
&& !is_pending_validator(state.pending_deposits()?, &deposit_request.pubkey, spec))
|
||||
{
|
||||
// Apply builder deposits immediately
|
||||
apply_deposit_for_builder(
|
||||
state,
|
||||
builder_index,
|
||||
deposit_request.pubkey,
|
||||
deposit_request.withdrawal_credentials,
|
||||
deposit_request.amount,
|
||||
deposit_request.signature.clone(),
|
||||
state.slot(),
|
||||
spec,
|
||||
)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Add validator deposits to the queue
|
||||
let slot = state.slot();
|
||||
state.pending_deposits_mut()?.push(PendingDeposit {
|
||||
pubkey: deposit_request.pubkey,
|
||||
withdrawal_credentials: deposit_request.withdrawal_credentials,
|
||||
amount: deposit_request.amount,
|
||||
signature: deposit_request.signature.clone(),
|
||||
slot,
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn apply_deposit_for_builder<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
builder_index_opt: Option<BuilderIndex>,
|
||||
pubkey: PublicKeyBytes,
|
||||
withdrawal_credentials: Hash256,
|
||||
amount: u64,
|
||||
signature: SignatureBytes,
|
||||
slot: Slot,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Option<BuilderIndex>, BeaconStateError> {
|
||||
match builder_index_opt {
|
||||
None => {
|
||||
// Verify the deposit signature (proof of possession) which is not checked by the deposit contract
|
||||
let deposit_data = DepositData {
|
||||
pubkey,
|
||||
withdrawal_credentials,
|
||||
amount,
|
||||
signature,
|
||||
};
|
||||
if is_valid_deposit_signature(&deposit_data, spec).is_ok() {
|
||||
let builder_index = state.add_builder_to_registry(
|
||||
pubkey,
|
||||
withdrawal_credentials,
|
||||
amount,
|
||||
slot,
|
||||
spec,
|
||||
)?;
|
||||
Ok(Some(builder_index))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
Some(builder_index) => {
|
||||
state
|
||||
.builders_mut()?
|
||||
.get_mut(builder_index as usize)
|
||||
.ok_or(BeaconStateError::UnknownBuilder(builder_index))?
|
||||
.balance
|
||||
.safe_add_assign(amount)?;
|
||||
Ok(Some(builder_index))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure to build the pubkey cache before calling this function
|
||||
pub fn process_consolidation_requests<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
//! validated individually, or alongside in others in a potentially cheaper bulk operation.
|
||||
//!
|
||||
//! This module exposes one function to extract each type of `SignatureSet` from a `BeaconBlock`.
|
||||
use super::builder::{convert_validator_index_to_builder_index, is_builder_index};
|
||||
use bls::{AggregateSignature, PublicKey, PublicKeyBytes, Signature, SignatureSet};
|
||||
use ssz::DecodeError;
|
||||
use std::borrow::Cow;
|
||||
@@ -520,7 +519,10 @@ pub fn deposit_pubkey_signature_message(
|
||||
}
|
||||
|
||||
/// Returns a signature set that is valid if the `SignedVoluntaryExit` was signed by the indicated
|
||||
/// validator (or builder, in the case of a builder exit).
|
||||
/// validator.
|
||||
///
|
||||
/// It is invalid for voluntary exits to be signed by builders. Builder exits are made via execution
|
||||
/// requests per EIP-8282.
|
||||
pub fn exit_signature_set<'a, E, F>(
|
||||
state: &'a BeaconState<E>,
|
||||
get_pubkey: F,
|
||||
@@ -534,16 +536,8 @@ where
|
||||
let exit = &signed_exit.message;
|
||||
let validator_index = exit.validator_index;
|
||||
|
||||
let is_builder_exit =
|
||||
state.fork_name_unchecked().gloas_enabled() && is_builder_index(validator_index);
|
||||
|
||||
let pubkey = if is_builder_exit {
|
||||
let builder_index = convert_validator_index_to_builder_index(validator_index);
|
||||
get_builder_pubkey_from_state(state, builder_index)
|
||||
.ok_or(Error::ValidatorUnknown(validator_index))?
|
||||
} else {
|
||||
get_pubkey(validator_index as usize).ok_or(Error::ValidatorUnknown(validator_index))?
|
||||
};
|
||||
let pubkey =
|
||||
get_pubkey(validator_index as usize).ok_or(Error::ValidatorUnknown(validator_index))?;
|
||||
|
||||
let domain = if state.fork_name_unchecked().deneb_enabled() {
|
||||
// EIP-7044
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
use crate::per_block_processing::process_operations::apply_deposit_for_builder;
|
||||
use crate::per_block_processing::is_valid_deposit_signature;
|
||||
use crate::per_block_processing::process_operations::is_pending_validator;
|
||||
use milhouse::{List, Vector};
|
||||
use safe_arith::SafeArith;
|
||||
use ssz_types::BitVector;
|
||||
use ssz_types::FixedVector;
|
||||
use std::collections::HashMap;
|
||||
use std::mem;
|
||||
use ssz_types::{BitVector, FixedVector};
|
||||
use std::{collections::HashMap, mem};
|
||||
use tree_hash::TreeHash;
|
||||
use typenum::Unsigned;
|
||||
use types::{
|
||||
BeaconState, BeaconStateError as Error, BeaconStateGloas, BuilderPendingPayment, ChainSpec,
|
||||
EthSpec, ExecutionPayloadBid, ExecutionRequests, Fork, is_builder_withdrawal_credential,
|
||||
DepositData, EthSpec, ExecutionPayloadBid, ExecutionRequestsGloas, Fork,
|
||||
consts::gloas::PAYLOAD_BUILDER_VERSION, is_builder_withdrawal_credential,
|
||||
};
|
||||
|
||||
/// Transform a `Fulu` state into a `Gloas` state.
|
||||
@@ -79,7 +78,7 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
|
||||
latest_execution_payload_bid: ExecutionPayloadBid {
|
||||
block_hash: pre.latest_execution_payload_header.block_hash,
|
||||
gas_limit: pre.latest_execution_payload_header.gas_limit,
|
||||
execution_requests_root: ExecutionRequests::<E>::default().tree_hash_root(),
|
||||
execution_requests_root: ExecutionRequestsGloas::<E>::default().tree_hash_root(),
|
||||
..Default::default()
|
||||
},
|
||||
// Capella
|
||||
@@ -187,37 +186,50 @@ fn onboard_builders_from_pending_deposits<E: EthSpec>(
|
||||
continue;
|
||||
}
|
||||
|
||||
if !builder_pubkey_to_index.contains_key(&deposit.pubkey) {
|
||||
// Deposits without builder withdrawal credentials are for new validators.
|
||||
if !is_builder_withdrawal_credential(deposit.withdrawal_credentials, spec) {
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
continue;
|
||||
match builder_pubkey_to_index.get(&deposit.pubkey).copied() {
|
||||
None => {
|
||||
// Deposits without builder withdrawal credentials are for new validators.
|
||||
if !is_builder_withdrawal_credential(deposit.withdrawal_credentials, spec) {
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there is a valid pending deposit for a new validator with this pubkey,
|
||||
// keep this deposit in the pending queue to be applied to that validator later.
|
||||
if is_pending_validator(&pending_deposits, &deposit.pubkey, spec) {
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
continue;
|
||||
}
|
||||
|
||||
let deposit_data = DepositData {
|
||||
pubkey: deposit.pubkey,
|
||||
withdrawal_credentials: deposit.withdrawal_credentials,
|
||||
amount: deposit.amount,
|
||||
signature: deposit.signature.clone(),
|
||||
};
|
||||
if is_valid_deposit_signature(&deposit_data, spec).is_err() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let builder_index = state.add_builder_to_registry(
|
||||
deposit.pubkey,
|
||||
PAYLOAD_BUILDER_VERSION,
|
||||
deposit.withdrawal_credentials,
|
||||
deposit.amount,
|
||||
deposit.slot,
|
||||
spec,
|
||||
)?;
|
||||
builder_pubkey_to_index.insert(deposit.pubkey, builder_index);
|
||||
}
|
||||
Some(builder_index) => {
|
||||
let builder = state
|
||||
.builders_mut()?
|
||||
.get_mut(builder_index as usize)
|
||||
.ok_or(Error::UnknownBuilder(builder_index))?;
|
||||
|
||||
// If there is a valid pending deposit for a new validator with this pubkey,
|
||||
// keep this deposit in the pending queue to be applied to that validator later.
|
||||
if is_pending_validator(&pending_deposits, &deposit.pubkey, spec) {
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
continue;
|
||||
builder.balance.safe_add_assign(deposit.amount)?;
|
||||
}
|
||||
}
|
||||
|
||||
let builder_index = builder_pubkey_to_index.get(&deposit.pubkey).copied();
|
||||
|
||||
if let Some(new_builder_index) = apply_deposit_for_builder(
|
||||
state,
|
||||
builder_index,
|
||||
deposit.pubkey,
|
||||
deposit.withdrawal_credentials,
|
||||
deposit.amount,
|
||||
deposit.signature.clone(),
|
||||
deposit.slot,
|
||||
spec,
|
||||
)? {
|
||||
builder_pubkey_to_index
|
||||
.entry(deposit.pubkey)
|
||||
.or_insert(new_builder_index);
|
||||
}
|
||||
}
|
||||
|
||||
*state.pending_deposits_mut()? = pending_deposits;
|
||||
|
||||
Reference in New Issue
Block a user