Fixed Payload Reconstruction Bug (#3796)

This commit is contained in:
ethDreamer 2022-12-13 18:49:30 -06:00 committed by GitHub
parent b1c33361ea
commit 07d6ef749a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 12 deletions

View File

@ -939,6 +939,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
Some(DatabaseBlock::Blinded(block)) => block, Some(DatabaseBlock::Blinded(block)) => block,
None => return Ok(None), None => return Ok(None),
}; };
let fork = blinded_block.fork_name(&self.spec)?;
// If we only have a blinded block, load the execution payload from the EL. // If we only have a blinded block, load the execution payload from the EL.
let block_message = blinded_block.message(); let block_message = blinded_block.message();
@ -953,7 +954,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.execution_layer .execution_layer
.as_ref() .as_ref()
.ok_or(Error::ExecutionLayerMissing)? .ok_or(Error::ExecutionLayerMissing)?
.get_payload_by_block_hash(exec_block_hash) .get_payload_by_block_hash(exec_block_hash, fork)
.await .await
.map_err(|e| Error::ExecutionLayerErrorPayloadReconstruction(exec_block_hash, e))? .map_err(|e| Error::ExecutionLayerErrorPayloadReconstruction(exec_block_hash, e))?
.ok_or(Error::BlockHashMissingFromExecutionLayer(exec_block_hash))?; .ok_or(Error::BlockHashMissingFromExecutionLayer(exec_block_hash))?;

View File

@ -207,6 +207,7 @@ pub enum BeaconChainError {
CommitteePromiseFailed(oneshot_broadcast::Error), CommitteePromiseFailed(oneshot_broadcast::Error),
MaxCommitteePromises(usize), MaxCommitteePromises(usize),
BlsToExecutionChangeBadFork(ForkName), BlsToExecutionChangeBadFork(ForkName),
InconsistentFork(InconsistentFork),
} }
easy_from_to!(SlotProcessingError, BeaconChainError); easy_from_to!(SlotProcessingError, BeaconChainError);
@ -230,6 +231,7 @@ easy_from_to!(ForkChoiceStoreError, BeaconChainError);
easy_from_to!(HistoricalBlockError, BeaconChainError); easy_from_to!(HistoricalBlockError, BeaconChainError);
easy_from_to!(StateAdvanceError, BeaconChainError); easy_from_to!(StateAdvanceError, BeaconChainError);
easy_from_to!(BlockReplayError, BeaconChainError); easy_from_to!(BlockReplayError, BeaconChainError);
easy_from_to!(InconsistentFork, BeaconChainError);
#[derive(Debug)] #[derive(Debug)]
pub enum BlockProductionError { pub enum BlockProductionError {

View File

@ -664,14 +664,41 @@ impl HttpJsonRpc {
pub async fn get_block_by_hash_with_txns<T: EthSpec>( pub async fn get_block_by_hash_with_txns<T: EthSpec>(
&self, &self,
block_hash: ExecutionBlockHash, block_hash: ExecutionBlockHash,
fork: ForkName,
) -> Result<Option<ExecutionBlockWithTransactions<T>>, Error> { ) -> Result<Option<ExecutionBlockWithTransactions<T>>, Error> {
let params = json!([block_hash, true]); let params = json!([block_hash, true]);
Ok(Some(match fork {
ForkName::Merge => ExecutionBlockWithTransactions::Merge(
self.rpc_request( self.rpc_request(
ETH_GET_BLOCK_BY_HASH, ETH_GET_BLOCK_BY_HASH,
params, params,
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier, ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
) )
.await .await?,
),
ForkName::Capella => ExecutionBlockWithTransactions::Capella(
self.rpc_request(
ETH_GET_BLOCK_BY_HASH,
params,
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
)
.await?,
),
ForkName::Eip4844 => ExecutionBlockWithTransactions::Eip4844(
self.rpc_request(
ETH_GET_BLOCK_BY_HASH,
params,
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
)
.await?,
),
ForkName::Base | ForkName::Altair => {
return Err(Error::UnsupportedForkVariant(format!(
"called get_block_by_hash_with_txns with fork {:?}",
fork
)))
}
}))
} }
pub async fn new_payload_v1<T: EthSpec>( pub async fn new_payload_v1<T: EthSpec>(

View File

@ -1550,10 +1550,11 @@ impl<T: EthSpec> ExecutionLayer<T> {
pub async fn get_payload_by_block_hash( pub async fn get_payload_by_block_hash(
&self, &self,
hash: ExecutionBlockHash, hash: ExecutionBlockHash,
fork: ForkName,
) -> Result<Option<ExecutionPayload<T>>, Error> { ) -> Result<Option<ExecutionPayload<T>>, Error> {
self.engine() self.engine()
.request(|engine| async move { .request(|engine| async move {
self.get_payload_by_block_hash_from_engine(engine, hash) self.get_payload_by_block_hash_from_engine(engine, hash, fork)
.await .await
}) })
.await .await
@ -1565,15 +1566,26 @@ impl<T: EthSpec> ExecutionLayer<T> {
&self, &self,
engine: &Engine, engine: &Engine,
hash: ExecutionBlockHash, hash: ExecutionBlockHash,
fork: ForkName,
) -> Result<Option<ExecutionPayload<T>>, ApiError> { ) -> Result<Option<ExecutionPayload<T>>, ApiError> {
let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_GET_PAYLOAD_BY_BLOCK_HASH); let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_GET_PAYLOAD_BY_BLOCK_HASH);
if hash == ExecutionBlockHash::zero() { if hash == ExecutionBlockHash::zero() {
// FIXME: how to handle forks properly here? return match fork {
return Ok(Some(ExecutionPayloadMerge::default().into())); ForkName::Merge => Ok(Some(ExecutionPayloadMerge::default().into())),
ForkName::Capella => Ok(Some(ExecutionPayloadCapella::default().into())),
ForkName::Eip4844 => Ok(Some(ExecutionPayloadEip4844::default().into())),
ForkName::Base | ForkName::Altair => Err(ApiError::UnsupportedForkVariant(
format!("called get_payload_by_block_hash_from_engine with {}", fork),
)),
};
} }
let block = if let Some(block) = engine.api.get_block_by_hash_with_txns::<T>(hash).await? { let block = if let Some(block) = engine
.api
.get_block_by_hash_with_txns::<T>(hash, fork)
.await?
{
block block
} else { } else {
return Ok(None); return Ok(None);

View File

@ -616,7 +616,8 @@ async fn check_payload_reconstruction<E: GenericExecutionEngine>(
) { ) {
let reconstructed = ee let reconstructed = ee
.execution_layer .execution_layer
.get_payload_by_block_hash(payload.block_hash()) // FIXME: handle other forks here?
.get_payload_by_block_hash(payload.block_hash(), ForkName::Merge)
.await .await
.unwrap() .unwrap()
.unwrap(); .unwrap();