Block v3 endpoint (#4629)

## Issue Addressed

#4582

## Proposed Changes

Add a new v3 block fetching flow that can decide to return a Full OR Blinded payload

## Additional Info



Co-authored-by: Michael Sproul <micsproul@gmail.com>
This commit is contained in:
Eitan Seri-Levi
2023-11-03 00:12:18 +00:00
parent 42da392edc
commit 07f53b18fc
20 changed files with 972 additions and 459 deletions

View File

@@ -33,6 +33,17 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
state.build_committee_cache(RelativeEpoch::Previous, &self.spec)?;
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
self.compute_beacon_block_reward_with_cache(block, block_root, state)
}
// This should only be called after a committee cache has been built
// for both the previous and current epoch
fn compute_beacon_block_reward_with_cache<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
block_root: Hash256,
state: &BeaconState<T::EthSpec>,
) -> Result<StandardBlockReward, BeaconChainError> {
let proposer_index = block.proposer_index();
let sync_aggregate_reward =
@@ -178,7 +189,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
>(
&self,
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
state: &mut BeaconState<T::EthSpec>,
state: &BeaconState<T::EthSpec>,
) -> Result<BeaconBlockSubRewardValue, BeaconChainError> {
let total_active_balance = state.get_total_active_balance()?;
let base_reward_per_increment =
@@ -191,6 +202,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.safe_mul(WEIGHT_DENOMINATOR)?
.safe_div(PROPOSER_WEIGHT)?;
let mut current_epoch_participation = state.current_epoch_participation()?.clone();
let mut previous_epoch_participation = state.previous_epoch_participation()?.clone();
for attestation in block.body().attestations() {
let data = &attestation.data;
let inclusion_delay = state.slot().safe_sub(data.slot)?.as_u64();
@@ -203,13 +217,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
)?;
let attesting_indices = get_attesting_indices_from_state(state, attestation)?;
let mut proposer_reward_numerator = 0;
for index in attesting_indices {
let index = index as usize;
for (flag_index, &weight) in PARTICIPATION_FLAG_WEIGHTS.iter().enumerate() {
let epoch_participation =
state.get_epoch_participation_mut(data.target.epoch)?;
let epoch_participation = if data.target.epoch == state.current_epoch() {
&mut current_epoch_participation
} else {
&mut previous_epoch_participation
};
let validator_participation = epoch_participation
.get_mut(index)
.ok_or(BeaconStateError::ParticipationOutOfBounds(index))?;

View File

@@ -72,8 +72,8 @@ use crate::{
};
use eth2::types::{EventKind, SseBlobSidecar, SseBlock, SseExtendedPayloadAttributes, SyncDuty};
use execution_layer::{
BlockProposalContents, BuilderParams, ChainHealth, ExecutionLayer, FailedCondition,
PayloadAttributes, PayloadStatus,
BlockProposalContents, BlockProposalContentsType, BuilderParams, ChainHealth, ExecutionLayer,
FailedCondition, PayloadAttributes, PayloadStatus,
};
use fork_choice::{
AttestationFromBlock, ExecutionStatus, ForkChoice, ForkchoiceUpdateParameters,
@@ -120,6 +120,7 @@ use tokio_stream::Stream;
use tree_hash::TreeHash;
use types::beacon_state::CloneConfig;
use types::blob_sidecar::{BlobSidecarList, FixedBlobSidecarList};
use types::payload::BlockProductionVersion;
use types::sidecar::BlobItems;
use types::*;
@@ -320,8 +321,7 @@ pub trait BeaconChainTypes: Send + Sync + 'static {
type EthSpec: types::EthSpec;
}
/// Used internally to split block production into discrete functions.
struct PartialBeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E>> {
struct PartialBeaconBlock<E: EthSpec> {
state: BeaconState<E>,
slot: Slot,
proposer_index: u64,
@@ -335,7 +335,7 @@ struct PartialBeaconBlock<E: EthSpec, Payload: AbstractExecPayload<E>> {
deposits: Vec<Deposit>,
voluntary_exits: Vec<SignedVoluntaryExit>,
sync_aggregate: Option<SyncAggregate<E>>,
prepare_payload_handle: Option<PreparePayloadHandle<E, Payload>>,
prepare_payload_handle: Option<PreparePayloadHandle<E>>,
bls_to_execution_changes: Vec<SignedBlsToExecutionChange>,
}
@@ -484,11 +484,18 @@ pub struct BeaconChain<T: BeaconChainTypes> {
pub kzg: Option<Arc<Kzg>>,
}
type BeaconBlockAndState<T, Payload> = (
BeaconBlock<T, Payload>,
BeaconState<T>,
Option<SidecarList<T, <Payload as AbstractExecPayload<T>>::Sidecar>>,
);
pub enum BeaconBlockResponseType<T: EthSpec> {
Full(BeaconBlockResponse<T, FullPayload<T>>),
Blinded(BeaconBlockResponse<T, BlindedPayload<T>>),
}
pub struct BeaconBlockResponse<T: EthSpec, Payload: AbstractExecPayload<T>> {
pub block: BeaconBlock<T, Payload>,
pub state: BeaconState<T>,
pub maybe_side_car: Option<SidecarList<T, <Payload as AbstractExecPayload<T>>::Sidecar>>,
pub execution_payload_value: Option<Uint256>,
pub consensus_block_value: Option<u64>,
}
impl FinalizationAndCanonicity {
pub fn is_finalized(self) -> bool {
@@ -3949,38 +3956,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
Ok(())
}
/// Produce a new block at the given `slot`.
///
/// 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: AbstractExecPayload<T::EthSpec> + 'static>(
self: &Arc<Self>,
randao_reveal: Signature,
slot: Slot,
validator_graffiti: Option<Graffiti>,
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
self.produce_block_with_verification(
randao_reveal,
slot,
validator_graffiti,
ProduceBlockVerification::VerifyRandao,
)
.await
}
/// Same as `produce_block` but allowing for configuration of RANDAO-verification.
pub async fn produce_block_with_verification<
Payload: AbstractExecPayload<T::EthSpec> + 'static,
>(
pub async fn produce_block_with_verification(
self: &Arc<Self>,
randao_reveal: Signature,
slot: Slot,
validator_graffiti: Option<Graffiti>,
verification: ProduceBlockVerification,
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
block_production_version: BlockProductionVersion,
) -> Result<BeaconBlockResponseType<T::EthSpec>, BlockProductionError> {
metrics::inc_counter(&metrics::BLOCK_PRODUCTION_REQUESTS);
let _complete_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_TIMES);
// Part 1/2 (blocking)
//
// Load the parent state from disk.
@@ -3998,13 +3983,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// Part 2/2 (async, with some blocking components)
//
// Produce the block upon the state
self.produce_block_on_state::<Payload>(
self.produce_block_on_state(
state,
state_root_opt,
slot,
randao_reveal,
validator_graffiti,
verification,
block_production_version,
)
.await
}
@@ -4568,7 +4554,8 @@ 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: AbstractExecPayload<T::EthSpec> + 'static>(
#[allow(clippy::too_many_arguments)]
pub async fn produce_block_on_state(
self: &Arc<Self>,
state: BeaconState<T::EthSpec>,
state_root_opt: Option<Hash256>,
@@ -4576,7 +4563,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
randao_reveal: Signature,
validator_graffiti: Option<Graffiti>,
verification: ProduceBlockVerification,
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
block_production_version: BlockProductionVersion,
) -> Result<BeaconBlockResponseType<T::EthSpec>, BlockProductionError> {
// Part 1/3 (blocking)
//
// Perform the state advance and block-packing functions.
@@ -4591,6 +4579,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
produce_at_slot,
randao_reveal,
validator_graffiti,
block_production_version,
)
},
"produce_partial_beacon_block",
@@ -4598,50 +4587,96 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.ok_or(BlockProductionError::ShuttingDown)?
.await
.map_err(BlockProductionError::TokioJoin)??;
// Part 2/3 (async)
//
// 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 block_contents = if let Some(prepare_payload_handle) = prepare_payload_handle {
Some(
prepare_payload_handle
.await
.map_err(BlockProductionError::TokioJoin)?
.ok_or(BlockProductionError::ShuttingDown)??,
)
} else {
None
};
let block_contents_type_option =
if let Some(prepare_payload_handle) = prepare_payload_handle {
Some(
prepare_payload_handle
.await
.map_err(BlockProductionError::TokioJoin)?
.ok_or(BlockProductionError::ShuttingDown)??,
)
} else {
None
};
// Part 3/3 (blocking)
//
// Perform the final steps of combining all the parts and computing the state root.
let chain = self.clone();
self.task_executor
.spawn_blocking_handle(
move || {
chain.complete_partial_beacon_block(
partial_beacon_block,
block_contents,
verification,
)
},
"complete_partial_beacon_block",
)
.ok_or(BlockProductionError::ShuttingDown)?
.await
.map_err(BlockProductionError::TokioJoin)?
if let Some(block_contents_type) = block_contents_type_option {
match block_contents_type {
BlockProposalContentsType::Full(block_contents) => {
let chain = self.clone();
let beacon_block_response = self
.task_executor
.spawn_blocking_handle(
move || {
chain.complete_partial_beacon_block(
partial_beacon_block,
Some(block_contents),
verification,
)
},
"complete_partial_beacon_block",
)
.ok_or(BlockProductionError::ShuttingDown)?
.await
.map_err(BlockProductionError::TokioJoin)??;
Ok(BeaconBlockResponseType::Full(beacon_block_response))
}
BlockProposalContentsType::Blinded(block_contents) => {
let chain = self.clone();
let beacon_block_response = self
.task_executor
.spawn_blocking_handle(
move || {
chain.complete_partial_beacon_block(
partial_beacon_block,
Some(block_contents),
verification,
)
},
"complete_partial_beacon_block",
)
.ok_or(BlockProductionError::ShuttingDown)?
.await
.map_err(BlockProductionError::TokioJoin)??;
Ok(BeaconBlockResponseType::Blinded(beacon_block_response))
}
}
} else {
let chain = self.clone();
let beacon_block_response = self
.task_executor
.spawn_blocking_handle(
move || {
chain.complete_partial_beacon_block(
partial_beacon_block,
None,
verification,
)
},
"complete_partial_beacon_block",
)
.ok_or(BlockProductionError::ShuttingDown)?
.await
.map_err(BlockProductionError::TokioJoin)??;
Ok(BeaconBlockResponseType::Full(beacon_block_response))
}
}
fn produce_partial_beacon_block<Payload: AbstractExecPayload<T::EthSpec> + 'static>(
fn produce_partial_beacon_block(
self: &Arc<Self>,
mut state: BeaconState<T::EthSpec>,
state_root_opt: Option<Hash256>,
produce_at_slot: Slot,
randao_reveal: Signature,
validator_graffiti: Option<Graffiti>,
) -> Result<PartialBeaconBlock<T::EthSpec, Payload>, BlockProductionError> {
block_production_version: BlockProductionVersion,
) -> Result<PartialBeaconBlock<T::EthSpec>, BlockProductionError> {
let eth1_chain = self
.eth1_chain
.as_ref()
@@ -4701,6 +4736,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
parent_root,
proposer_index,
builder_params,
block_production_version,
)?;
Some(prepare_payload_handle)
}
@@ -4710,6 +4746,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.op_pool.get_slashings_and_exits(&state, &self.spec);
let eth1_data = eth1_chain.eth1_data_for_block_production(&state, &self.spec)?;
let deposits = eth1_chain.deposits_for_block_inclusion(&state, &eth1_data, &self.spec)?;
let bls_to_execution_changes = self
@@ -4880,10 +4917,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
fn complete_partial_beacon_block<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
partial_beacon_block: PartialBeaconBlock<T::EthSpec, Payload>,
partial_beacon_block: PartialBeaconBlock<T::EthSpec>,
block_contents: Option<BlockProposalContents<T::EthSpec, Payload>>,
verification: ProduceBlockVerification,
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
) -> Result<BeaconBlockResponse<T::EthSpec, Payload>, BlockProductionError> {
let PartialBeaconBlock {
mut state,
slot,
@@ -4905,7 +4942,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
bls_to_execution_changes,
} = partial_beacon_block;
let (inner_block, blobs_opt, proofs_opt) = match &state {
let (inner_block, blobs_opt, proofs_opt, execution_payload_value) = match &state {
BeaconState::Base(_) => (
BeaconBlock::Base(BeaconBlockBase {
slot,
@@ -4926,6 +4963,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}),
None,
None,
Uint256::zero(),
),
BeaconState::Altair(_) => (
BeaconBlock::Altair(BeaconBlockAltair {
@@ -4949,11 +4987,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}),
None,
None,
Uint256::zero(),
),
BeaconState::Merge(_) => {
let (payload, _, _, _) = block_contents
.ok_or(BlockProductionError::MissingExecutionPayload)?
.deconstruct();
let block_proposal_contents =
block_contents.ok_or(BlockProductionError::MissingExecutionPayload)?;
let execution_payload_value = block_proposal_contents.block_value().to_owned();
(
BeaconBlock::Merge(BeaconBlockMerge {
slot,
@@ -4971,19 +5010,22 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
voluntary_exits: voluntary_exits.into(),
sync_aggregate: sync_aggregate
.ok_or(BlockProductionError::MissingSyncAggregate)?,
execution_payload: payload
execution_payload: block_proposal_contents
.to_payload()
.try_into()
.map_err(|_| BlockProductionError::InvalidPayloadFork)?,
},
}),
None,
None,
execution_payload_value,
)
}
BeaconState::Capella(_) => {
let (payload, _, _, _) = block_contents
.ok_or(BlockProductionError::MissingExecutionPayload)?
.deconstruct();
let block_proposal_contents =
block_contents.ok_or(BlockProductionError::MissingExecutionPayload)?;
let execution_payload_value = block_proposal_contents.block_value().to_owned();
(
BeaconBlock::Capella(BeaconBlockCapella {
slot,
@@ -5001,7 +5043,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
voluntary_exits: voluntary_exits.into(),
sync_aggregate: sync_aggregate
.ok_or(BlockProductionError::MissingSyncAggregate)?,
execution_payload: payload
execution_payload: block_proposal_contents
.to_payload()
.try_into()
.map_err(|_| BlockProductionError::InvalidPayloadFork)?,
bls_to_execution_changes: bls_to_execution_changes.into(),
@@ -5009,12 +5052,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}),
None,
None,
execution_payload_value,
)
}
BeaconState::Deneb(_) => {
let (payload, kzg_commitments, blobs, proofs) = block_contents
.ok_or(BlockProductionError::MissingExecutionPayload)?
.deconstruct();
let (payload, kzg_commitments, blobs, proofs, execution_payload_value) =
block_contents
.ok_or(BlockProductionError::MissingExecutionPayload)?
.deconstruct();
(
BeaconBlock::Deneb(BeaconBlockDeneb {
slot,
@@ -5042,6 +5088,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}),
blobs,
proofs,
execution_payload_value,
)
}
};
@@ -5057,7 +5104,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
self.log,
"Produced block on state";
"block_size" => block_size,
"slot" => block.slot(),
);
metrics::observe(&metrics::BLOCK_SIZE, block_size as f64);
@@ -5075,6 +5121,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// Use a context without block root or proposer index so that both are checked.
let mut ctxt = ConsensusContext::new(block.slot());
let consensus_block_value = self
.compute_beacon_block_reward(block.message(), Hash256::zero(), &mut state)
.map(|reward| reward.total)
.unwrap_or(0);
per_block_processing(
&mut state,
&block,
@@ -5154,7 +5205,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
"slot" => block.slot()
);
Ok((block, state, maybe_sidecar_list))
Ok(BeaconBlockResponse {
block,
state,
maybe_side_car: maybe_sidecar_list,
execution_payload_value: Some(execution_payload_value),
consensus_block_value: Some(consensus_block_value),
})
}
/// This method must be called whenever an execution engine indicates that a payload is

View File

@@ -13,7 +13,8 @@ use crate::{
ExecutionPayloadError,
};
use execution_layer::{
BlockProposalContents, BuilderParams, NewPayloadRequest, PayloadAttributes, PayloadStatus,
BlockProposalContents, BlockProposalContentsType, BuilderParams, NewPayloadRequest,
PayloadAttributes, PayloadStatus,
};
use fork_choice::{InvalidationOperation, PayloadVerificationStatus};
use proto_array::{Block as ProtoBlock, ExecutionStatus};
@@ -26,11 +27,11 @@ use state_processing::per_block_processing::{
use std::sync::Arc;
use tokio::task::JoinHandle;
use tree_hash::TreeHash;
use types::payload::BlockProductionVersion;
use types::*;
pub type PreparePayloadResult<E, Payload> =
Result<BlockProposalContents<E, Payload>, BlockProductionError>;
pub type PreparePayloadHandle<E, Payload> = JoinHandle<Option<PreparePayloadResult<E, Payload>>>;
pub type PreparePayloadResult<E> = Result<BlockProposalContentsType<E>, BlockProductionError>;
pub type PreparePayloadHandle<E> = JoinHandle<Option<PreparePayloadResult<E>>>;
#[derive(PartialEq)]
pub enum AllowOptimisticImport {
@@ -398,16 +399,14 @@ pub fn validate_execution_payload_for_gossip<T: BeaconChainTypes>(
/// Equivalent to the `get_execution_payload` function in the Validator Guide:
///
/// https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/merge/validator.md#block-proposal
pub fn get_execution_payload<
T: BeaconChainTypes,
Payload: AbstractExecPayload<T::EthSpec> + 'static,
>(
pub fn get_execution_payload<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
state: &BeaconState<T::EthSpec>,
parent_block_root: Hash256,
proposer_index: u64,
builder_params: BuilderParams,
) -> Result<PreparePayloadHandle<T::EthSpec, Payload>, BlockProductionError> {
block_production_version: BlockProductionVersion,
) -> Result<PreparePayloadHandle<T::EthSpec>, BlockProductionError> {
// Compute all required values from the `state` now to avoid needing to pass it into a spawned
// task.
let spec = &chain.spec;
@@ -440,7 +439,7 @@ pub fn get_execution_payload<
.clone()
.spawn_handle(
async move {
prepare_execution_payload::<T, Payload>(
prepare_execution_payload::<T>(
&chain,
is_merge_transition_complete,
timestamp,
@@ -450,6 +449,7 @@ pub fn get_execution_payload<
builder_params,
withdrawals,
parent_beacon_block_root,
block_production_version,
)
.await
},
@@ -475,7 +475,7 @@ pub fn get_execution_payload<
///
/// https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/merge/validator.md#block-proposal
#[allow(clippy::too_many_arguments)]
pub async fn prepare_execution_payload<T, Payload>(
pub async fn prepare_execution_payload<T>(
chain: &Arc<BeaconChain<T>>,
is_merge_transition_complete: bool,
timestamp: u64,
@@ -485,10 +485,10 @@ pub async fn prepare_execution_payload<T, Payload>(
builder_params: BuilderParams,
withdrawals: Option<Vec<Withdrawal>>,
parent_beacon_block_root: Option<Hash256>,
) -> Result<BlockProposalContents<T::EthSpec, Payload>, BlockProductionError>
block_production_version: BlockProductionVersion,
) -> Result<BlockProposalContentsType<T::EthSpec>, BlockProductionError>
where
T: BeaconChainTypes,
Payload: AbstractExecPayload<T::EthSpec>,
{
let current_epoch = builder_params.slot.epoch(T::EthSpec::slots_per_epoch());
let spec = &chain.spec;
@@ -506,7 +506,12 @@ where
if is_terminal_block_hash_set && !is_activation_epoch_reached {
// Use the "empty" payload if there's a terminal block hash, but we haven't reached the
// terminal block epoch yet.
return BlockProposalContents::default_at_fork(fork).map_err(Into::into);
return Ok(BlockProposalContentsType::Full(
BlockProposalContents::Payload {
payload: FullPayload::default_at_fork(fork)?,
block_value: Uint256::zero(),
},
));
}
let terminal_pow_block_hash = execution_layer
@@ -519,7 +524,12 @@ where
} else {
// If the merge transition hasn't occurred yet and the EL hasn't found the terminal
// block, return an "empty" payload.
return BlockProposalContents::default_at_fork(fork).map_err(Into::into);
return Ok(BlockProposalContentsType::Full(
BlockProposalContents::Payload {
payload: FullPayload::default_at_fork(fork)?,
block_value: Uint256::zero(),
},
));
}
} else {
latest_execution_payload_header_block_hash
@@ -558,13 +568,14 @@ where
//
// This future is not executed here, it's up to the caller to await it.
let block_contents = execution_layer
.get_payload::<Payload>(
.get_payload(
parent_hash,
&payload_attributes,
forkchoice_update_params,
builder_params,
fork,
&chain.spec,
block_production_version,
)
.await
.map_err(BlockProductionError::GetPayloadFailed)?;

View File

@@ -56,10 +56,10 @@ pub mod validator_monitor;
pub mod validator_pubkey_cache;
pub use self::beacon_chain::{
AttestationProcessingOutcome, AvailabilityProcessingStatus, BeaconChain, BeaconChainTypes,
BeaconStore, ChainSegmentResult, ForkChoiceError, OverrideForkchoiceUpdate,
ProduceBlockVerification, StateSkipConfig, WhenSlotSkipped,
INVALID_FINALIZED_MERGE_TRANSITION_BLOCK_SHUTDOWN_REASON,
AttestationProcessingOutcome, AvailabilityProcessingStatus, BeaconBlockResponse,
BeaconBlockResponseType, BeaconChain, BeaconChainTypes, BeaconStore, ChainSegmentResult,
ForkChoiceError, OverrideForkchoiceUpdate, ProduceBlockVerification, StateSkipConfig,
WhenSlotSkipped, INVALID_FINALIZED_MERGE_TRANSITION_BLOCK_SHUTDOWN_REASON,
INVALID_JUSTIFIED_PAYLOAD_SHUTDOWN_REASON,
};
pub use self::beacon_snapshot::BeaconSnapshot;

View File

@@ -1,6 +1,7 @@
use crate::block_verification_types::{AsBlock, RpcBlock};
use crate::observed_operations::ObservationOutcome;
pub use crate::persisted_beacon_chain::PersistedBeaconChain;
use crate::BeaconBlockResponseType;
pub use crate::{
beacon_chain::{BEACON_CHAIN_DB_KEY, ETH1_CACHE_DB_KEY, FORK_CHOICE_DB_KEY, OP_POOL_DB_KEY},
migrate::MigratorConfig,
@@ -60,6 +61,7 @@ use store::{config::StoreConfig, HotColdDB, ItemStore, LevelDB, MemoryStore};
use task_executor::TaskExecutor;
use task_executor::{test_utils::TestRuntime, ShutdownReason};
use tree_hash::TreeHash;
use types::payload::BlockProductionVersion;
use types::sync_selection_proof::SyncSelectionProof;
pub use types::test_utils::generate_deterministic_keypairs;
use types::test_utils::TestRandom;
@@ -878,7 +880,7 @@ where
let randao_reveal = self.sign_randao_reveal(&state, proposer_index, slot);
let (block, state, maybe_blob_sidecars) = self
let BeaconBlockResponseType::Full(block_response) = self
.chain
.produce_block_on_state(
state,
@@ -887,14 +889,18 @@ where
randao_reveal,
Some(graffiti),
ProduceBlockVerification::VerifyRandao,
BlockProductionVersion::FullV2,
)
.await
.unwrap();
.unwrap()
else {
panic!("Should always be a full payload response");
};
let signed_block = block.sign(
let signed_block = block_response.block.sign(
&self.validator_keypairs[proposer_index].sk,
&state.fork(),
state.genesis_validators_root(),
&block_response.state.fork(),
block_response.state.genesis_validators_root(),
&self.spec,
);
@@ -905,11 +911,13 @@ where
| SignedBeaconBlock::Capella(_) => (signed_block, None),
SignedBeaconBlock::Deneb(_) => (
signed_block,
maybe_blob_sidecars.map(|blobs| self.sign_blobs(blobs, &state, proposer_index)),
block_response
.maybe_side_car
.map(|blobs| self.sign_blobs(blobs, &block_response.state, proposer_index)),
),
};
(block_contents, state)
(block_contents, block_response.state)
}
/// Useful for the `per_block_processing` tests. Creates a block, and returns the state after
@@ -938,7 +946,7 @@ where
let pre_state = state.clone();
let (block, state, maybe_blob_sidecars) = self
let BeaconBlockResponseType::Full(block_response) = self
.chain
.produce_block_on_state(
state,
@@ -947,14 +955,18 @@ where
randao_reveal,
Some(graffiti),
ProduceBlockVerification::VerifyRandao,
BlockProductionVersion::FullV2,
)
.await
.unwrap();
.unwrap()
else {
panic!("Should always be a full payload response");
};
let signed_block = block.sign(
let signed_block = block_response.block.sign(
&self.validator_keypairs[proposer_index].sk,
&state.fork(),
state.genesis_validators_root(),
&block_response.state.fork(),
block_response.state.genesis_validators_root(),
&self.spec,
);
@@ -964,14 +976,14 @@ where
| SignedBeaconBlock::Merge(_)
| SignedBeaconBlock::Capella(_) => (signed_block, None),
SignedBeaconBlock::Deneb(_) => {
if let Some(blobs) = maybe_blob_sidecars {
if let Some(blobs) = block_response.maybe_side_car {
let signed_blobs: SignedSidecarList<E, BlobSidecar<E>> = Vec::from(blobs)
.into_iter()
.map(|blob| {
blob.sign(
&self.validator_keypairs[proposer_index].sk,
&state.fork(),
state.genesis_validators_root(),
&block_response.state.fork(),
block_response.state.genesis_validators_root(),
&self.spec,
)
})
@@ -990,7 +1002,6 @@ where
}
}
};
(block_contents, pre_state)
}