mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-12 02:14:10 +00:00
Retrospective invalidation of exec. payloads for opt. sync (#2837)
## Issue Addressed
NA
## Proposed Changes
Adds the functionality to allow blocks to be validated/invalidated after their import as per the [optimistic sync spec](https://github.com/ethereum/consensus-specs/blob/dev/sync/optimistic.md#how-to-optimistically-import-blocks). This means:
- Updating `ProtoArray` to allow flipping the `execution_status` of ancestors/descendants based on payload validity updates.
- Creating separation between `execution_layer` and the `beacon_chain` by creating a `PayloadStatus` struct.
- Refactoring how the `execution_layer` selects a `PayloadStatus` from the multiple statuses returned from multiple EEs.
- Adding testing framework for optimistic imports.
- Add `ExecutionBlockHash(Hash256)` new-type struct to avoid confusion between *beacon block roots* and *execution payload hashes*.
- Add `merge` to [`FORKS`](c3a793fd73/Makefile (L17)) in the `Makefile` to ensure we test the beacon chain with merge settings.
- Fix some tests here that were failing due to a missing execution layer.
## TODO
- [ ] Balance tests
Co-authored-by: Mark Mackey <mark@sigmaprime.io>
This commit is contained in:
@@ -11,7 +11,7 @@ use crate::{
|
||||
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, BlockProductionError,
|
||||
ExecutionPayloadError,
|
||||
};
|
||||
use execution_layer::PayloadStatusV1Status;
|
||||
use execution_layer::PayloadStatus;
|
||||
use fork_choice::PayloadVerificationStatus;
|
||||
use proto_array::{Block as ProtoBlock, ExecutionStatus};
|
||||
use slog::debug;
|
||||
@@ -57,22 +57,26 @@ pub fn notify_new_payload<T: BeaconChainTypes>(
|
||||
.block_on(|execution_layer| execution_layer.notify_new_payload(execution_payload));
|
||||
|
||||
match new_payload_response {
|
||||
Ok((status, latest_valid_hash)) => match status {
|
||||
PayloadStatusV1Status::Valid => Ok(PayloadVerificationStatus::Verified),
|
||||
PayloadStatusV1Status::Syncing | PayloadStatusV1Status::Accepted => {
|
||||
Ok(status) => match status {
|
||||
PayloadStatus::Valid => Ok(PayloadVerificationStatus::Verified),
|
||||
PayloadStatus::Syncing | PayloadStatus::Accepted => {
|
||||
Ok(PayloadVerificationStatus::NotVerified)
|
||||
}
|
||||
PayloadStatusV1Status::Invalid
|
||||
| PayloadStatusV1Status::InvalidTerminalBlock
|
||||
| PayloadStatusV1Status::InvalidBlockHash => {
|
||||
// TODO(bellatrix): process the invalid payload.
|
||||
//
|
||||
// See: https://github.com/sigp/lighthouse/pull/2837
|
||||
Err(ExecutionPayloadError::RejectedByExecutionEngine {
|
||||
status,
|
||||
latest_valid_hash,
|
||||
}
|
||||
.into())
|
||||
PayloadStatus::Invalid {
|
||||
latest_valid_hash, ..
|
||||
} => {
|
||||
// This block has not yet been applied to fork choice, so the latest block that was
|
||||
// imported to fork choice was the parent.
|
||||
let latest_root = block.parent_root();
|
||||
chain.process_invalid_execution_payload(latest_root, Some(latest_valid_hash))?;
|
||||
|
||||
Err(ExecutionPayloadError::RejectedByExecutionEngine { status }.into())
|
||||
}
|
||||
PayloadStatus::InvalidTerminalBlock { .. } | PayloadStatus::InvalidBlockHash { .. } => {
|
||||
// Returning an error here should be sufficient to invalidate the block. We have no
|
||||
// information to indicate its parent is invalid, so no need to run
|
||||
// `BeaconChain::process_invalid_execution_payload`.
|
||||
Err(ExecutionPayloadError::RejectedByExecutionEngine { status }.into())
|
||||
}
|
||||
},
|
||||
Err(e) => Err(ExecutionPayloadError::RequestFailed(e).into()),
|
||||
@@ -99,7 +103,7 @@ pub fn validate_merge_block<T: BeaconChainTypes>(
|
||||
let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
|
||||
let execution_payload = block.execution_payload()?;
|
||||
|
||||
if spec.terminal_block_hash != Hash256::zero() {
|
||||
if spec.terminal_block_hash != ExecutionBlockHash::zero() {
|
||||
if block_epoch < spec.terminal_block_hash_activation_epoch {
|
||||
return Err(ExecutionPayloadError::InvalidActivationEpoch {
|
||||
activation_epoch: spec.terminal_block_hash_activation_epoch,
|
||||
@@ -263,7 +267,7 @@ pub async fn prepare_execution_payload<T: BeaconChainTypes>(
|
||||
.ok_or(BlockProductionError::ExecutionLayerMissing)?;
|
||||
|
||||
let parent_hash = if !is_merge_transition_complete(state) {
|
||||
let is_terminal_block_hash_set = spec.terminal_block_hash != Hash256::zero();
|
||||
let is_terminal_block_hash_set = spec.terminal_block_hash != ExecutionBlockHash::zero();
|
||||
let is_activation_epoch_reached =
|
||||
state.current_epoch() >= spec.terminal_block_hash_activation_epoch;
|
||||
|
||||
@@ -314,7 +318,7 @@ pub async fn prepare_execution_payload<T: BeaconChainTypes>(
|
||||
parent_hash,
|
||||
timestamp,
|
||||
random,
|
||||
finalized_block_hash.unwrap_or_else(Hash256::zero),
|
||||
finalized_block_hash.unwrap_or_else(ExecutionBlockHash::zero),
|
||||
proposer_index,
|
||||
)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user