mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-29 10:54:24 +00:00
Engine API v1.0.0.alpha.6 + interop tests (#3024)
## Issue Addressed NA ## Proposed Changes This PR extends #3018 to address my review comments there and add automated integration tests with Geth (and other implementations, in the future). I've also de-duplicated the "unused port" logic by creating an `common/unused_port` crate. ## Additional Info I'm not sure if we want to merge this PR, or update #3018 and merge that. I don't mind, I'm primarily opening this PR to make sure CI works. Co-authored-by: Mark Mackey <mark@sigmaprime.io>
This commit is contained in:
@@ -52,7 +52,7 @@ use crate::{metrics, BeaconChainError};
|
||||
use eth2::types::{
|
||||
EventKind, SseBlock, SseChainReorg, SseFinalizedCheckpoint, SseHead, SseLateHead, SyncDuty,
|
||||
};
|
||||
use execution_layer::ExecutionLayer;
|
||||
use execution_layer::{ExecutionLayer, PayloadStatusV1Status};
|
||||
use fork_choice::{AttestationFromBlock, ForkChoice};
|
||||
use futures::channel::mpsc::Sender;
|
||||
use itertools::process_results;
|
||||
@@ -3590,10 +3590,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
store,
|
||||
new_finalized_checkpoint.root,
|
||||
new_head_execution_block_hash,
|
||||
&log,
|
||||
)
|
||||
.await
|
||||
{
|
||||
debug!(
|
||||
crit!(
|
||||
log,
|
||||
"Failed to update execution head";
|
||||
"error" => ?e
|
||||
@@ -3613,6 +3614,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
store: BeaconStore<T>,
|
||||
finalized_beacon_block_root: Hash256,
|
||||
head_execution_block_hash: Hash256,
|
||||
log: &Logger,
|
||||
) -> Result<(), Error> {
|
||||
// Loading the finalized block from the store is not ideal. Perhaps it would be better to
|
||||
// store it on fork-choice so we can do a lookup without hitting the database.
|
||||
@@ -3630,14 +3632,45 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.map(|ep| ep.block_hash)
|
||||
.unwrap_or_else(Hash256::zero);
|
||||
|
||||
execution_layer
|
||||
let forkchoice_updated_response = execution_layer
|
||||
.notify_forkchoice_updated(
|
||||
head_execution_block_hash,
|
||||
finalized_execution_block_hash,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(Error::ExecutionForkChoiceUpdateFailed)
|
||||
.map_err(Error::ExecutionForkChoiceUpdateFailed);
|
||||
|
||||
match forkchoice_updated_response {
|
||||
Ok((status, latest_valid_hash)) => match status {
|
||||
PayloadStatusV1Status::Valid | PayloadStatusV1Status::Syncing => Ok(()),
|
||||
// The specification doesn't list `ACCEPTED` as a valid response to a fork choice
|
||||
// update. This response *seems* innocent enough, so we won't return early with an
|
||||
// error. However, we create a log to bring attention to the issue.
|
||||
PayloadStatusV1Status::Accepted => {
|
||||
warn!(
|
||||
log,
|
||||
"Fork choice update received ACCEPTED";
|
||||
"msg" => "execution engine provided an unexpected response to a fork \
|
||||
choice update. although this is not a serious issue, please raise \
|
||||
an issue."
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
PayloadStatusV1Status::Invalid
|
||||
| PayloadStatusV1Status::InvalidTerminalBlock
|
||||
| PayloadStatusV1Status::InvalidBlockHash => {
|
||||
// TODO(bellatrix): process the invalid payload.
|
||||
//
|
||||
// See: https://github.com/sigp/lighthouse/pull/2837
|
||||
Err(BeaconChainError::ExecutionForkChoiceUpdateInvalid {
|
||||
status,
|
||||
latest_valid_hash,
|
||||
})
|
||||
}
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the status of the current head block, regarding the validity of the execution
|
||||
|
||||
@@ -54,6 +54,7 @@ use crate::{
|
||||
metrics, BeaconChain, BeaconChainError, BeaconChainTypes,
|
||||
};
|
||||
use eth2::types::EventKind;
|
||||
use execution_layer::PayloadStatusV1Status;
|
||||
use fork_choice::{ForkChoice, ForkChoiceStore, PayloadVerificationStatus};
|
||||
use parking_lot::RwLockReadGuard;
|
||||
use proto_array::Block as ProtoBlock;
|
||||
@@ -269,7 +270,10 @@ pub enum ExecutionPayloadError {
|
||||
/// ## Peer scoring
|
||||
///
|
||||
/// The block is invalid and the peer is faulty
|
||||
RejectedByExecutionEngine,
|
||||
RejectedByExecutionEngine {
|
||||
status: PayloadStatusV1Status,
|
||||
latest_valid_hash: Option<Vec<Hash256>>,
|
||||
},
|
||||
/// The execution payload timestamp does not match the slot
|
||||
///
|
||||
/// ## Peer scoring
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::naive_aggregation_pool::Error as NaiveAggregationError;
|
||||
use crate::observed_aggregates::Error as ObservedAttestationsError;
|
||||
use crate::observed_attesters::Error as ObservedAttestersError;
|
||||
use crate::observed_block_producers::Error as ObservedBlockProducersError;
|
||||
use execution_layer::PayloadStatusV1Status;
|
||||
use futures::channel::mpsc::TrySendError;
|
||||
use operation_pool::OpPoolError;
|
||||
use safe_arith::ArithError;
|
||||
@@ -137,6 +138,10 @@ pub enum BeaconChainError {
|
||||
AltairForkDisabled,
|
||||
ExecutionLayerMissing,
|
||||
ExecutionForkChoiceUpdateFailed(execution_layer::Error),
|
||||
ExecutionForkChoiceUpdateInvalid {
|
||||
status: PayloadStatusV1Status,
|
||||
latest_valid_hash: Option<Vec<Hash256>>,
|
||||
},
|
||||
BlockRewardSlotError,
|
||||
BlockRewardAttestationError,
|
||||
BlockRewardSyncError,
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, BlockProductionError,
|
||||
ExecutionPayloadError,
|
||||
};
|
||||
use execution_layer::ExecutePayloadResponseStatus;
|
||||
use execution_layer::PayloadStatusV1Status;
|
||||
use fork_choice::PayloadVerificationStatus;
|
||||
use proto_array::{Block as ProtoBlock, ExecutionStatus};
|
||||
use slog::debug;
|
||||
@@ -53,19 +53,29 @@ pub fn notify_new_payload<T: BeaconChainTypes>(
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
|
||||
let notify_new_payload_response = execution_layer
|
||||
let new_payload_response = execution_layer
|
||||
.block_on(|execution_layer| execution_layer.notify_new_payload(execution_payload));
|
||||
|
||||
match notify_new_payload_response {
|
||||
Ok((status, _latest_valid_hash)) => match status {
|
||||
ExecutePayloadResponseStatus::Valid => Ok(PayloadVerificationStatus::Verified),
|
||||
// TODO(merge): invalidate any invalid ancestors of this block in fork choice.
|
||||
ExecutePayloadResponseStatus::Invalid => {
|
||||
Err(ExecutionPayloadError::RejectedByExecutionEngine.into())
|
||||
match new_payload_response {
|
||||
Ok((status, latest_valid_hash)) => match status {
|
||||
PayloadStatusV1Status::Valid => Ok(PayloadVerificationStatus::Verified),
|
||||
PayloadStatusV1Status::Syncing | PayloadStatusV1Status::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())
|
||||
}
|
||||
ExecutePayloadResponseStatus::Syncing => Ok(PayloadVerificationStatus::NotVerified),
|
||||
},
|
||||
Err(_) => Err(ExecutionPayloadError::RejectedByExecutionEngine.into()),
|
||||
Err(e) => Err(ExecutionPayloadError::RequestFailed(e).into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user