mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 01:05:47 +00:00
process_execution_bid()
This commit is contained in:
@@ -1,8 +1,12 @@
|
|||||||
|
use crate::common::{decrease_balance, increase_balance};
|
||||||
use crate::consensus_context::ConsensusContext;
|
use crate::consensus_context::ConsensusContext;
|
||||||
use errors::{BlockOperationError, BlockProcessingError, HeaderInvalid};
|
use errors::{BlockOperationError, BlockProcessingError, ExecutionBidInvalid, HeaderInvalid};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use safe_arith::{ArithError, SafeArith};
|
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 std::borrow::Cow;
|
||||||
use tree_hash::TreeHash;
|
use tree_hash::TreeHash;
|
||||||
use types::*;
|
use types::*;
|
||||||
@@ -43,8 +47,6 @@ mod verify_exit;
|
|||||||
mod verify_payload_attestation;
|
mod verify_payload_attestation;
|
||||||
mod verify_proposer_slashing;
|
mod verify_proposer_slashing;
|
||||||
|
|
||||||
use crate::common::decrease_balance;
|
|
||||||
|
|
||||||
use crate::common::update_progressive_balances_cache::{
|
use crate::common::update_progressive_balances_cache::{
|
||||||
initialize_progressive_balances_cache, update_progressive_balances_metrics,
|
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_payload::<E, Payload>(state, body, spec)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process_execution_bid(state, block, verify_signatures, spec)?;
|
||||||
|
|
||||||
process_randao(state, block, verify_randao, ctxt, spec)?;
|
process_randao(state, block, verify_randao, ctxt, spec)?;
|
||||||
process_eth1_data(state, block.body().eth1_data())?;
|
process_eth1_data(state, block.body().eth1_data())?;
|
||||||
process_operations(state, block.body(), verify_signatures, ctxt, spec)?;
|
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()"),
|
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(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ pub enum BlockProcessingError {
|
|||||||
SyncAggregateInvalid {
|
SyncAggregateInvalid {
|
||||||
reason: SyncAggregateInvalid,
|
reason: SyncAggregateInvalid,
|
||||||
},
|
},
|
||||||
|
ExecutionBidInvalid {
|
||||||
|
reason: ExecutionBidInvalid,
|
||||||
|
},
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
SignatureSetError(SignatureSetError),
|
SignatureSetError(SignatureSetError),
|
||||||
SszTypesError(ssz_types::Error),
|
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 {
|
impl From<BlockOperationError<HeaderInvalid>> for BlockProcessingError {
|
||||||
fn from(e: BlockOperationError<HeaderInvalid>) -> BlockProcessingError {
|
fn from(e: BlockOperationError<HeaderInvalid>) -> BlockProcessingError {
|
||||||
match e {
|
match e {
|
||||||
@@ -504,3 +513,31 @@ pub enum SyncAggregateInvalid {
|
|||||||
/// The signature is invalid.
|
/// The signature is invalid.
|
||||||
SignatureInvalid,
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ use types::{
|
|||||||
InconsistentFork, IndexedAttestation, IndexedAttestationRef, IndexedPayloadAttestation,
|
InconsistentFork, IndexedAttestation, IndexedAttestationRef, IndexedPayloadAttestation,
|
||||||
ProposerSlashing, PublicKey, PublicKeyBytes, Signature, SignedAggregateAndProof,
|
ProposerSlashing, PublicKey, PublicKeyBytes, Signature, SignedAggregateAndProof,
|
||||||
SignedBeaconBlock, SignedBeaconBlockHeader, SignedBlsToExecutionChange,
|
SignedBeaconBlock, SignedBeaconBlockHeader, SignedBlsToExecutionChange,
|
||||||
SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate,
|
SignedContributionAndProof, SignedExecutionBid, SignedRoot, SignedVoluntaryExit, SigningData,
|
||||||
SyncAggregatorSelectionData, Unsigned,
|
Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
@@ -361,6 +361,34 @@ where
|
|||||||
Ok(SignatureSet::multiple_pubkeys(signature, pubkeys, message))
|
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`.
|
/// Returns the signature set for the given `attester_slashing` and corresponding `pubkeys`.
|
||||||
pub fn attester_slashing_signature_sets<'a, E, F>(
|
pub fn attester_slashing_signature_sets<'a, E, F>(
|
||||||
state: &'a BeaconState<E>,
|
state: &'a BeaconState<E>,
|
||||||
|
|||||||
@@ -21,19 +21,21 @@ use tree_hash_derive::TreeHash;
|
|||||||
#[derivative(PartialEq, Hash)]
|
#[derivative(PartialEq, Hash)]
|
||||||
// This is what Potuz' spec calls an `ExecutionPayload` even though it's clearly a bid.
|
// This is what Potuz' spec calls an `ExecutionPayload` even though it's clearly a bid.
|
||||||
pub struct ExecutionBid {
|
pub struct ExecutionBid {
|
||||||
parent_block_hash: ExecutionBlockHash,
|
pub parent_block_hash: ExecutionBlockHash,
|
||||||
parent_block_root: Hash256,
|
pub parent_block_root: Hash256,
|
||||||
block_hash: ExecutionBlockHash,
|
pub block_hash: ExecutionBlockHash,
|
||||||
#[serde(with = "serde_utils::quoted_u64")]
|
#[serde(with = "serde_utils::quoted_u64")]
|
||||||
gas_limit: u64,
|
pub gas_limit: u64,
|
||||||
#[serde(with = "serde_utils::quoted_u64")]
|
#[serde(with = "serde_utils::quoted_u64")]
|
||||||
builder_index: u64,
|
pub builder_index: u64,
|
||||||
slot: Slot,
|
pub slot: Slot,
|
||||||
#[serde(with = "serde_utils::quoted_u64")]
|
#[serde(with = "serde_utils::quoted_u64")]
|
||||||
value: u64,
|
pub value: u64,
|
||||||
blob_kzg_commitments_root: Hash256,
|
pub blob_kzg_commitments_root: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SignedRoot for ExecutionBid {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
Reference in New Issue
Block a user