Use efficient payload reconstruction for HTTP API (#4102)
## Proposed Changes Builds on #4028 to use the new payload bodies methods in the HTTP API as well. ## Caveats The payloads by range method only works for the finalized chain, so it can't be used in the execution engine integration tests because we try to reconstruct unfinalized payloads there.
This commit is contained in:
parent
dd124b2d68
commit
1d92e3f77c
@ -1043,7 +1043,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, fork)
|
.get_payload_for_header(&execution_payload_header, fork)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
Error::ExecutionLayerErrorPayloadReconstruction(exec_block_hash, Box::new(e))
|
Error::ExecutionLayerErrorPayloadReconstruction(exec_block_hash, Box::new(e))
|
||||||
|
@ -103,6 +103,8 @@ pub enum Error {
|
|||||||
transactions_root: Hash256,
|
transactions_root: Hash256,
|
||||||
},
|
},
|
||||||
InvalidJWTSecret(String),
|
InvalidJWTSecret(String),
|
||||||
|
InvalidForkForPayload,
|
||||||
|
InvalidPayloadBody(String),
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1602,14 +1604,59 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
.map_err(Error::EngineError)
|
.map_err(Error::EngineError)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_payload_by_block_hash(
|
/// Fetch a full payload from the execution node.
|
||||||
|
///
|
||||||
|
/// This will fail if the payload is not from the finalized portion of the chain.
|
||||||
|
pub async fn get_payload_for_header(
|
||||||
|
&self,
|
||||||
|
header: &ExecutionPayloadHeader<T>,
|
||||||
|
fork: ForkName,
|
||||||
|
) -> Result<Option<ExecutionPayload<T>>, Error> {
|
||||||
|
let hash = header.block_hash();
|
||||||
|
let block_number = header.block_number();
|
||||||
|
|
||||||
|
// Handle default payload body.
|
||||||
|
if header.block_hash() == ExecutionBlockHash::zero() {
|
||||||
|
let payload = match fork {
|
||||||
|
ForkName::Merge => ExecutionPayloadMerge::default().into(),
|
||||||
|
ForkName::Capella => ExecutionPayloadCapella::default().into(),
|
||||||
|
ForkName::Base | ForkName::Altair => {
|
||||||
|
return Err(Error::InvalidForkForPayload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Ok(Some(payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use efficient payload bodies by range method if supported.
|
||||||
|
let capabilities = self.get_engine_capabilities(None).await?;
|
||||||
|
if capabilities.get_payload_bodies_by_range_v1 {
|
||||||
|
let mut payload_bodies = self.get_payload_bodies_by_range(block_number, 1).await?;
|
||||||
|
|
||||||
|
if payload_bodies.len() != 1 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let opt_payload_body = payload_bodies.pop().flatten();
|
||||||
|
opt_payload_body
|
||||||
|
.map(|body| {
|
||||||
|
body.to_payload(header.clone())
|
||||||
|
.map_err(Error::InvalidPayloadBody)
|
||||||
|
})
|
||||||
|
.transpose()
|
||||||
|
} else {
|
||||||
|
// Fall back to eth_blockByHash.
|
||||||
|
self.get_payload_by_hash_legacy(hash, fork).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_payload_by_hash_legacy(
|
||||||
&self,
|
&self,
|
||||||
hash: ExecutionBlockHash,
|
hash: ExecutionBlockHash,
|
||||||
fork: ForkName,
|
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, fork)
|
self.get_payload_by_hash_from_engine(engine, hash, fork)
|
||||||
.await
|
.await
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -1617,7 +1664,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
.map_err(Error::EngineError)
|
.map_err(Error::EngineError)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_payload_by_block_hash_from_engine(
|
async fn get_payload_by_hash_from_engine(
|
||||||
&self,
|
&self,
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
hash: ExecutionBlockHash,
|
hash: ExecutionBlockHash,
|
||||||
@ -1630,7 +1677,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
|||||||
ForkName::Merge => Ok(Some(ExecutionPayloadMerge::default().into())),
|
ForkName::Merge => Ok(Some(ExecutionPayloadMerge::default().into())),
|
||||||
ForkName::Capella => Ok(Some(ExecutionPayloadCapella::default().into())),
|
ForkName::Capella => Ok(Some(ExecutionPayloadCapella::default().into())),
|
||||||
ForkName::Base | ForkName::Altair => Err(ApiError::UnsupportedForkVariant(
|
ForkName::Base | ForkName::Altair => Err(ApiError::UnsupportedForkVariant(
|
||||||
format!("called get_payload_by_block_hash_from_engine with {}", fork),
|
format!("called get_payload_by_hash_from_engine with {}", fork),
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -626,9 +626,10 @@ async fn check_payload_reconstruction<E: GenericExecutionEngine>(
|
|||||||
ee: &ExecutionPair<E, MainnetEthSpec>,
|
ee: &ExecutionPair<E, MainnetEthSpec>,
|
||||||
payload: &ExecutionPayload<MainnetEthSpec>,
|
payload: &ExecutionPayload<MainnetEthSpec>,
|
||||||
) {
|
) {
|
||||||
|
// check via legacy eth_getBlockByHash
|
||||||
let reconstructed = ee
|
let reconstructed = ee
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.get_payload_by_block_hash(payload.block_hash(), payload.fork_name())
|
.get_payload_by_hash_legacy(payload.block_hash(), payload.fork_name())
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user