process_execution_bid()

This commit is contained in:
Mark Mackey
2024-09-18 17:43:29 -05:00
parent 4c9e12cfb6
commit 56e2ed5d75
4 changed files with 176 additions and 14 deletions

View File

@@ -1,8 +1,12 @@
use crate::common::{decrease_balance, increase_balance};
use crate::consensus_context::ConsensusContext;
use errors::{BlockOperationError, BlockProcessingError, HeaderInvalid};
use errors::{BlockOperationError, BlockProcessingError, ExecutionBidInvalid, HeaderInvalid};
use rayon::prelude::*;
use safe_arith::{ArithError, SafeArith};
use signature_sets::{block_proposal_signature_set, get_pubkey_from_state, randao_signature_set};
use signature_sets::{
block_proposal_signature_set, execution_bid_signature_set, get_pubkey_from_state,
randao_signature_set,
};
use std::borrow::Cow;
use tree_hash::TreeHash;
use types::*;
@@ -43,8 +47,6 @@ mod verify_exit;
mod verify_payload_attestation;
mod verify_proposer_slashing;
use crate::common::decrease_balance;
use crate::common::update_progressive_balances_cache::{
initialize_progressive_balances_cache, update_progressive_balances_metrics,
};
@@ -178,6 +180,8 @@ pub fn per_block_processing<E: EthSpec, Payload: AbstractExecPayload<E>>(
process_execution_payload::<E, Payload>(state, body, spec)?;
}
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)?;
@@ -671,3 +675,94 @@ pub fn process_withdrawals<E: EthSpec, Payload: AbstractExecPayload<E>>(
BeaconState::EIP7732(_) => todo!("implement potuz' changes to process_withdrawals()"),
}
}
pub fn process_execution_bid<E: EthSpec, Payload: AbstractExecPayload<E>>(
state: &mut BeaconState<E>,
block: BeaconBlockRef<'_, E, Payload>,
verify_signatures: VerifySignatures,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
if !state
.fork_name(&spec)
.map_err(BlockProcessingError::InconsistentStateFork)?
.eip7732_enabled()
{
return Ok(());
}
let signed_bid = block.body().signed_execution_bid()?;
if verify_signatures.is_true() {
// Verify the bid signature
block_verify!(
execution_bid_signature_set(
state,
|i| get_pubkey_from_state(state, i),
signed_bid,
spec
)?
.verify(),
ExecutionBidInvalid::BadSignature.into()
);
}
let bid = &signed_bid.message;
let builder_index = bid.builder_index;
// Verify the bid is for the current slot
block_verify!(
bid.slot == state.slot(),
ExecutionBidInvalid::SlotMismatch {
state_slot: state.slot(),
bid_slot: bid.slot,
}
.into()
);
// Verify the bid is for the correct parent block
let state_block_hash = state.latest_block_hash()?;
block_verify!(
bid.parent_block_hash == state_block_hash,
ExecutionBidInvalid::ParentBlockHashMismatch {
state_block_hash,
bid_parent_hash: bid.parent_block_hash,
}
.into()
);
let block_parent_root = block.parent_root();
block_verify!(
bid.parent_block_root == block_parent_root,
ExecutionBidInvalid::ParentBlockRootMismatch {
block_parent_root,
bid_parent_root: bid.parent_block_root,
}
.into()
);
// Check the builder is active, non-slashed, and has funds to cover the bid
let builder = state.get_validator(builder_index as usize)?;
block_verify!(
builder.is_active_at(state.current_epoch()),
ExecutionBidInvalid::BuilderNotActive(builder_index).into()
);
block_verify!(
!builder.slashed,
ExecutionBidInvalid::BuilderSlashed(builder_index).into()
);
let builder_balance = state.get_balance(builder_index as usize)?;
block_verify!(
builder_balance >= bid.value,
ExecutionBidInvalid::InsufficientBalance {
builder_index,
builder_balance,
bid_value: bid.value,
}
.into()
);
// Transfer the funds from the builder to the proposer
decrease_balance(state, builder_index as usize, bid.value)?;
increase_balance(state, block.proposer_index() as usize, bid.value)?;
*state.latest_execution_bid_eip7732_mut()? = bid.clone();
Ok(())
}

View File

@@ -60,6 +60,9 @@ pub enum BlockProcessingError {
SyncAggregateInvalid {
reason: SyncAggregateInvalid,
},
ExecutionBidInvalid {
reason: ExecutionBidInvalid,
},
BeaconStateError(BeaconStateError),
SignatureSetError(SignatureSetError),
SszTypesError(ssz_types::Error),
@@ -150,6 +153,12 @@ impl From<milhouse::Error> for BlockProcessingError {
}
}
impl From<ExecutionBidInvalid> for BlockProcessingError {
fn from(reason: ExecutionBidInvalid) -> Self {
BlockProcessingError::ExecutionBidInvalid { reason }
}
}
impl From<BlockOperationError<HeaderInvalid>> for BlockProcessingError {
fn from(e: BlockOperationError<HeaderInvalid>) -> BlockProcessingError {
match e {
@@ -504,3 +513,31 @@ pub enum SyncAggregateInvalid {
/// The signature is invalid.
SignatureInvalid,
}
#[derive(Debug, PartialEq, Clone)]
pub enum ExecutionBidInvalid {
/// The signature is invalid.
BadSignature,
/// The builder is not an active validator.
BuilderNotActive(u64),
/// The builder is slashed
BuilderSlashed(u64),
/// The builder has insufficient balance to cover the bid
InsufficientBalance {
builder_index: u64,
builder_balance: u64,
bid_value: u64,
},
/// Bid slot doesn't match state slot
SlotMismatch { state_slot: Slot, bid_slot: Slot },
/// The bid's parent block hash doesn't match the state's latest block hash
ParentBlockHashMismatch {
state_block_hash: ExecutionBlockHash,
bid_parent_hash: ExecutionBlockHash,
},
/// The bid's parent block root doesn't match the block's parent root
ParentBlockRootMismatch {
block_parent_root: Hash256,
bid_parent_root: Hash256,
},
}

View File

@@ -12,8 +12,8 @@ use types::{
InconsistentFork, IndexedAttestation, IndexedAttestationRef, IndexedPayloadAttestation,
ProposerSlashing, PublicKey, PublicKeyBytes, Signature, SignedAggregateAndProof,
SignedBeaconBlock, SignedBeaconBlockHeader, SignedBlsToExecutionChange,
SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate,
SyncAggregatorSelectionData, Unsigned,
SignedContributionAndProof, SignedExecutionBid, SignedRoot, SignedVoluntaryExit, SigningData,
Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned,
};
pub type Result<T> = std::result::Result<T, Error>;
@@ -361,6 +361,34 @@ where
Ok(SignatureSet::multiple_pubkeys(signature, pubkeys, message))
}
pub fn execution_bid_signature_set<'a, E, F>(
state: &'a BeaconState<E>,
get_pubkey: F,
signed_execution_bid: &'a SignedExecutionBid,
spec: &'a ChainSpec,
) -> Result<SignatureSet<'a>>
where
E: EthSpec,
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
{
let domain = spec.get_domain(
state.current_epoch(),
Domain::BeaconBuilder,
&state.fork(),
state.genesis_validators_root(),
);
let execution_bid = &signed_execution_bid.message;
let pubkey = get_pubkey(execution_bid.builder_index as usize)
.ok_or(Error::ValidatorUnknown(execution_bid.builder_index))?;
let message = execution_bid.signing_root(domain);
Ok(SignatureSet::single_pubkey(
&signed_execution_bid.signature,
pubkey,
message,
))
}
/// Returns the signature set for the given `attester_slashing` and corresponding `pubkeys`.
pub fn attester_slashing_signature_sets<'a, E, F>(
state: &'a BeaconState<E>,