Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

138 changes: 95 additions & 43 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ use crate::BeaconSnapshot;
use crate::{metrics, BeaconChainError};
use eth2::types::{EventKind, SseBlock, SyncDuty};
use execution_layer::{
BuilderParams, ChainHealth, ExecutionLayer, FailedCondition, PayloadAttributes, PayloadStatus,
BlockProposalContents, BuilderParams, ChainHealth, ExecutionLayer, FailedCondition,
PayloadAttributes, PayloadAttributesV1, PayloadAttributesV2, PayloadStatus,
};
pub use fork_choice::CountUnrealized;
use fork_choice::{
Expand Down Expand Up @@ -241,7 +242,7 @@ pub trait BeaconChainTypes: Send + Sync + 'static {
}

/// Used internally to split block production into discrete functions.
struct PartialBeaconBlock<E: EthSpec, Payload> {
struct PartialBeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E>> {
state: BeaconState<E>,
slot: Slot,
proposer_index: u64,
Expand All @@ -255,7 +256,7 @@ struct PartialBeaconBlock<E: EthSpec, Payload> {
deposits: Vec<Deposit>,
voluntary_exits: Vec<SignedVoluntaryExit>,
sync_aggregate: Option<SyncAggregate<E>>,
prepare_payload_handle: Option<PreparePayloadHandle<Payload, E>>,
prepare_payload_handle: Option<PreparePayloadHandle<E, Payload>>,
}

pub type BeaconForkChoice<T> = ForkChoice<
Expand Down Expand Up @@ -928,12 +929,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {

// If we only have a blinded block, load the execution payload from the EL.
let block_message = blinded_block.message();
let execution_payload_header = &block_message
let execution_payload_header = block_message
.execution_payload()
.map_err(|_| Error::BlockVariantLacksExecutionPayload(*block_root))?
.execution_payload_header;
.to_execution_payload_header();

let exec_block_hash = execution_payload_header.block_hash;
let exec_block_hash = execution_payload_header.block_hash();

let execution_payload = self
.execution_layer
Expand All @@ -944,10 +945,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.map_err(|e| Error::ExecutionLayerErrorPayloadReconstruction(exec_block_hash, e))?
.ok_or(Error::BlockHashMissingFromExecutionLayer(exec_block_hash))?;

//FIXME(sean) avoid the clone by comparing refs to headers (`as_execution_payload_header` method ?)
let full_payload: FullPayload<T::EthSpec> = execution_payload.clone().into();

// Verify payload integrity.
let header_from_payload = ExecutionPayloadHeader::from(&execution_payload);
if header_from_payload != *execution_payload_header {
for txn in &execution_payload.transactions {
let header_from_payload = full_payload.to_execution_payload_header();
if header_from_payload != execution_payload_header {
for txn in execution_payload.transactions() {
debug!(
self.log,
"Reconstructed txn";
Expand All @@ -960,8 +964,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
exec_block_hash,
canonical_payload_root: execution_payload_header.tree_hash_root(),
reconstructed_payload_root: header_from_payload.tree_hash_root(),
canonical_transactions_root: execution_payload_header.transactions_root,
reconstructed_transactions_root: header_from_payload.transactions_root,
canonical_transactions_root: execution_payload_header.transactions_root(),
reconstructed_transactions_root: header_from_payload.transactions_root(),
});
}

Expand Down Expand Up @@ -3126,7 +3130,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
///
/// The produced block will not be inherently valid, it must be signed by a block producer.
/// Block signing is out of the scope of this function and should be done by a separate program.
pub async fn produce_block<Payload: ExecPayload<T::EthSpec>>(
pub async fn produce_block<Payload: AbstractExecPayload<T::EthSpec> + 'static>(
self: &Arc<Self>,
randao_reveal: Signature,
slot: Slot,
Expand All @@ -3142,7 +3146,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}

/// Same as `produce_block` but allowing for configuration of RANDAO-verification.
pub async fn produce_block_with_verification<Payload: ExecPayload<T::EthSpec>>(
pub async fn produce_block_with_verification<
Payload: AbstractExecPayload<T::EthSpec> + 'static,
>(
self: &Arc<Self>,
randao_reveal: Signature,
slot: Slot,
Expand Down Expand Up @@ -3256,7 +3262,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
/// The provided `state_root_opt` should only ever be set to `Some` if the contained value is
/// equal to the root of `state`. Providing this value will serve as an optimization to avoid
/// performing a tree hash in some scenarios.
pub async fn produce_block_on_state<Payload: ExecPayload<T::EthSpec>>(
pub async fn produce_block_on_state<Payload: AbstractExecPayload<T::EthSpec> + 'static>(
self: &Arc<Self>,
state: BeaconState<T::EthSpec>,
state_root_opt: Option<Hash256>,
Expand Down Expand Up @@ -3291,16 +3297,17 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
//
// Wait for the execution layer to return an execution payload (if one is required).
let prepare_payload_handle = partial_beacon_block.prepare_payload_handle.take();
let (execution_payload, kzg_commitments, blobs) =
if let Some(prepare_payload_handle) = prepare_payload_handle {
let (execution_payload, commitments, blobs) = prepare_payload_handle
.await
.map_err(BlockProductionError::TokioJoin)?
.ok_or(BlockProductionError::ShuttingDown)??;
(execution_payload, commitments, blobs)
} else {
return Err(BlockProductionError::MissingExecutionPayload);
};
let execution_payload = if let Some(prepare_payload_handle) = prepare_payload_handle {
prepare_payload_handle
.await
.map_err(BlockProductionError::TokioJoin)?
.ok_or(BlockProductionError::ShuttingDown)??
} else {
return Err(BlockProductionError::MissingExecutionPayload);
};

//FIXME(sean) waiting for the BN<>EE api for this to stabilize
let kzg_commitments = vec![];

// Part 3/3 (blocking)
//
Expand All @@ -3323,7 +3330,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.map_err(BlockProductionError::TokioJoin)?
}

fn produce_partial_beacon_block<Payload: ExecPayload<T::EthSpec>>(
fn produce_partial_beacon_block<Payload: AbstractExecPayload<T::EthSpec> + 'static>(
self: &Arc<Self>,
mut state: BeaconState<T::EthSpec>,
state_root_opt: Option<Hash256>,
Expand Down Expand Up @@ -3383,7 +3390,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// allows it to run concurrently with things like attestation packing.
let prepare_payload_handle = match &state {
BeaconState::Base(_) | BeaconState::Altair(_) => None,
BeaconState::Merge(_) | BeaconState::Eip4844(_) => {
BeaconState::Merge(_) | BeaconState::Capella(_) | BeaconState::Eip4844(_) => {
let prepare_payload_handle =
get_execution_payload(self.clone(), &state, proposer_index, builder_params)?;
Some(prepare_payload_handle)
Expand Down Expand Up @@ -3556,10 +3563,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
})
}

fn complete_partial_beacon_block<Payload: ExecPayload<T::EthSpec>>(
fn complete_partial_beacon_block<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
partial_beacon_block: PartialBeaconBlock<T::EthSpec, Payload>,
execution_payload: Payload,
block_contents: BlockProposalContents<T::EthSpec, Payload>,
kzg_commitments: Vec<KzgCommitment>,
verification: ProduceBlockVerification,
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
Expand Down Expand Up @@ -3636,7 +3643,32 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
voluntary_exits: voluntary_exits.into(),
sync_aggregate: sync_aggregate
.ok_or(BlockProductionError::MissingSyncAggregate)?,
execution_payload,
execution_payload: block_contents
.to_payload()
.try_into()
.map_err(|_| BlockProductionError::InvalidPayloadFork)?,
},
}),
BeaconState::Capella(_) => BeaconBlock::Capella(BeaconBlockCapella {
slot,
proposer_index,
parent_root,
state_root: Hash256::zero(),
body: BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings: proposer_slashings.into(),
attester_slashings: attester_slashings.into(),
attestations: attestations.into(),
deposits: deposits.into(),
voluntary_exits: voluntary_exits.into(),
sync_aggregate: sync_aggregate
.ok_or(BlockProductionError::MissingSyncAggregate)?,
execution_payload: block_contents
.to_payload()
.try_into()
.map_err(|_| BlockProductionError::InvalidPayloadFork)?,
},
}),
BeaconState::Eip4844(_) => BeaconBlock::Eip4844(BeaconBlockEip4844 {
Expand All @@ -3655,7 +3687,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
voluntary_exits: voluntary_exits.into(),
sync_aggregate: sync_aggregate
.ok_or(BlockProductionError::MissingSyncAggregate)?,
execution_payload,
execution_payload: block_contents
.to_payload()
.try_into()
.map_err(|_| BlockProductionError::InvalidPayloadFork)?,
//FIXME(sean) get blobs
blob_kzg_commitments: VariableList::from(kzg_commitments),
},
Expand Down Expand Up @@ -3973,16 +4008,33 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
return Ok(());
}

let payload_attributes = PayloadAttributes {
timestamp: self
.slot_clock
.start_of(prepare_slot)
.ok_or(Error::InvalidSlot(prepare_slot))?
.as_secs(),
prev_randao: head_random,
suggested_fee_recipient: execution_layer
.get_suggested_fee_recipient(proposer as u64)
.await,
let payload_attributes = match self.spec.fork_name_at_epoch(prepare_epoch) {
ForkName::Base | ForkName::Altair | ForkName::Merge => {
PayloadAttributes::V1(PayloadAttributesV1 {
timestamp: self
.slot_clock
.start_of(prepare_slot)
.ok_or(Error::InvalidSlot(prepare_slot))?
.as_secs(),
prev_randao: head_random,
suggested_fee_recipient: execution_layer
.get_suggested_fee_recipient(proposer as u64)
.await,
})
}
ForkName::Capella | ForkName::Eip4844 => PayloadAttributes::V2(PayloadAttributesV2 {
timestamp: self
.slot_clock
.start_of(prepare_slot)
.ok_or(Error::InvalidSlot(prepare_slot))?
.as_secs(),
prev_randao: head_random,
suggested_fee_recipient: execution_layer
.get_suggested_fee_recipient(proposer as u64)
.await,
//FIXME(sean)
withdrawals: vec![],
}),
};

debug!(
Expand Down Expand Up @@ -4122,7 +4174,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
{
// We are a proposer, check for terminal_pow_block_hash
if let Some(terminal_pow_block_hash) = execution_layer
.get_terminal_pow_block_hash(&self.spec, payload_attributes.timestamp)
.get_terminal_pow_block_hash(&self.spec, payload_attributes.timestamp())
.await
.map_err(Error::ForkchoiceUpdate)?
{
Expand Down Expand Up @@ -4297,7 +4349,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
/// Returns `Ok(false)` if the block is pre-Bellatrix, or has `ExecutionStatus::Valid`.
/// Returns `Ok(true)` if the block has `ExecutionStatus::Optimistic` or has
/// `ExecutionStatus::Invalid`.
pub fn is_optimistic_or_invalid_block<Payload: ExecPayload<T::EthSpec>>(
pub fn is_optimistic_or_invalid_block<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
block: &SignedBeaconBlock<T::EthSpec, Payload>,
) -> Result<bool, BeaconChainError> {
Expand All @@ -4323,7 +4375,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
///
/// There is a potential race condition when syncing where the block_root of `head_block` could
/// be pruned from the fork choice store before being read.
pub fn is_optimistic_or_invalid_head_block<Payload: ExecPayload<T::EthSpec>>(
pub fn is_optimistic_or_invalid_head_block<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
head_block: &SignedBeaconBlock<T::EthSpec, Payload>,
) -> Result<bool, BeaconChainError> {
Expand Down
4 changes: 2 additions & 2 deletions beacon_node/beacon_chain/src/beacon_fork_choice_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::sync::Arc;
use store::{Error as StoreError, HotColdDB, ItemStore};
use superstruct::superstruct;
use types::{
BeaconBlockRef, BeaconState, BeaconStateError, Checkpoint, Epoch, EthSpec, ExecPayload,
AbstractExecPayload, BeaconBlockRef, BeaconState, BeaconStateError, Checkpoint, Epoch, EthSpec,
Hash256, Slot,
};

Expand Down Expand Up @@ -268,7 +268,7 @@ where
self.time = slot
}

fn on_verified_block<Payload: ExecPayload<E>>(
fn on_verified_block<Payload: AbstractExecPayload<E>>(
&mut self,
_block: BeaconBlockRef<E, Payload>,
block_root: Hash256,
Expand Down
6 changes: 3 additions & 3 deletions beacon_node/beacon_chain/src/beacon_snapshot.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use serde_derive::Serialize;
use std::sync::Arc;
use types::{
beacon_state::CloneConfig, BeaconState, EthSpec, ExecPayload, FullPayload, Hash256,
beacon_state::CloneConfig, AbstractExecPayload, BeaconState, EthSpec, FullPayload, Hash256,
SignedBeaconBlock,
};

/// Represents some block and its associated state. Generally, this will be used for tracking the
/// head, justified head and finalized head.
#[derive(Clone, Serialize, PartialEq, Debug)]
pub struct BeaconSnapshot<E: EthSpec, Payload: ExecPayload<E> = FullPayload<E>> {
pub struct BeaconSnapshot<E: EthSpec, Payload: AbstractExecPayload<E> = FullPayload<E>> {
pub beacon_block: Arc<SignedBeaconBlock<E, Payload>>,
pub beacon_block_root: Hash256,
pub beacon_state: BeaconState<E>,
}

impl<E: EthSpec, Payload: ExecPayload<E>> BeaconSnapshot<E, Payload> {
impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconSnapshot<E, Payload> {
/// Create a new checkpoint.
pub fn new(
beacon_block: Arc<SignedBeaconBlock<E, Payload>>,
Expand Down
4 changes: 2 additions & 2 deletions beacon_node/beacon_chain/src/block_reward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use state_processing::{
common::get_attesting_indices_from_state,
per_block_processing::altair::sync_committee::compute_sync_aggregate_rewards,
};
use types::{BeaconBlockRef, BeaconState, EthSpec, ExecPayload, Hash256};
use types::{AbstractExecPayload, BeaconBlockRef, BeaconState, EthSpec, Hash256};

impl<T: BeaconChainTypes> BeaconChain<T> {
pub fn compute_block_reward<Payload: ExecPayload<T::EthSpec>>(
pub fn compute_block_reward<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
block_root: Hash256,
Expand Down
3 changes: 2 additions & 1 deletion beacon_node/beacon_chain/src/block_verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ use std::time::Duration;
use store::{Error as DBError, HotStateSummary, KeyValueStore, StoreOp};
use task_executor::JoinHandle;
use tree_hash::TreeHash;
use types::ExecPayload;
use types::{
BeaconBlockRef, BeaconState, BeaconStateError, BlindedPayload, ChainSpec, CloneConfig, Epoch,
EthSpec, ExecutionBlockHash, Hash256, InconsistentFork, PublicKey, PublicKeyBytes,
Expand Down Expand Up @@ -1235,7 +1236,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
.message()
.body()
.execution_payload()
.map(|full_payload| full_payload.execution_payload.block_hash);
.map(|full_payload| full_payload.block_hash());

// Ensure the block is a candidate for optimistic import.
if !is_optimistic_candidate_block(&chain, block.slot(), block.parent_root()).await?
Expand Down
1 change: 1 addition & 0 deletions beacon_node/beacon_chain/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ pub enum BlockProductionError {
MissingExecutionPayload,
TokioJoin(tokio::task::JoinError),
BeaconChain(BeaconChainError),
InvalidPayloadFork,
}

easy_from_to!(BlockProcessingError, BlockProductionError);
Expand Down
Loading