@@ -103,6 +103,8 @@ pub enum Error {
103103 transactions_root : Hash256 ,
104104 } ,
105105 InvalidJWTSecret ( String ) ,
106+ InvalidForkForPayload ,
107+ InvalidPayloadBody ( String ) ,
106108 BeaconStateError ( BeaconStateError ) ,
107109}
108110
@@ -1602,22 +1604,67 @@ impl<T: EthSpec> ExecutionLayer<T> {
16021604 . map_err ( Error :: EngineError )
16031605 }
16041606
1605- pub async fn get_payload_by_block_hash (
1607+ /// Fetch a full payload from the execution node.
1608+ ///
1609+ /// This will fail if the payload is not from the finalized portion of the chain.
1610+ pub async fn get_payload_for_header (
1611+ & self ,
1612+ header : & ExecutionPayloadHeader < T > ,
1613+ fork : ForkName ,
1614+ ) -> Result < Option < ExecutionPayload < T > > , Error > {
1615+ let hash = header. block_hash ( ) ;
1616+ let block_number = header. block_number ( ) ;
1617+
1618+ // Handle default payload body.
1619+ if header. block_hash ( ) == ExecutionBlockHash :: zero ( ) {
1620+ let payload = match fork {
1621+ ForkName :: Merge => ExecutionPayloadMerge :: default ( ) . into ( ) ,
1622+ ForkName :: Capella => ExecutionPayloadCapella :: default ( ) . into ( ) ,
1623+ ForkName :: Base | ForkName :: Altair => {
1624+ return Err ( Error :: InvalidForkForPayload ) ;
1625+ }
1626+ } ;
1627+ return Ok ( Some ( payload) ) ;
1628+ }
1629+
1630+ // Use efficient payload bodies by range method if supported.
1631+ let capabilities = self . get_engine_capabilities ( None ) . await ?;
1632+ if capabilities. get_payload_bodies_by_range_v1 {
1633+ let mut payload_bodies = self . get_payload_bodies_by_range ( block_number, 1 ) . await ?;
1634+
1635+ if payload_bodies. len ( ) != 1 {
1636+ return Ok ( None ) ;
1637+ }
1638+
1639+ let opt_payload_body = payload_bodies. pop ( ) . flatten ( ) ;
1640+ opt_payload_body
1641+ . map ( |body| {
1642+ body. to_payload ( header. clone ( ) )
1643+ . map_err ( Error :: InvalidPayloadBody )
1644+ } )
1645+ . transpose ( )
1646+ } else {
1647+ // Fall back to eth_blockByHash.
1648+ self . get_payload_by_hash_legacy ( hash, fork) . await
1649+ }
1650+ }
1651+
1652+ pub async fn get_payload_by_hash_legacy (
16061653 & self ,
16071654 hash : ExecutionBlockHash ,
16081655 fork : ForkName ,
16091656 ) -> Result < Option < ExecutionPayload < T > > , Error > {
16101657 self . engine ( )
16111658 . request ( |engine| async move {
1612- self . get_payload_by_block_hash_from_engine ( engine, hash, fork)
1659+ self . get_payload_by_hash_from_engine ( engine, hash, fork)
16131660 . await
16141661 } )
16151662 . await
16161663 . map_err ( Box :: new)
16171664 . map_err ( Error :: EngineError )
16181665 }
16191666
1620- async fn get_payload_by_block_hash_from_engine (
1667+ async fn get_payload_by_hash_from_engine (
16211668 & self ,
16221669 engine : & Engine ,
16231670 hash : ExecutionBlockHash ,
@@ -1630,7 +1677,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
16301677 ForkName :: Merge => Ok ( Some ( ExecutionPayloadMerge :: default ( ) . into ( ) ) ) ,
16311678 ForkName :: Capella => Ok ( Some ( ExecutionPayloadCapella :: default ( ) . into ( ) ) ) ,
16321679 ForkName :: Base | ForkName :: Altair => Err ( ApiError :: UnsupportedForkVariant (
1633- format ! ( "called get_payload_by_block_hash_from_engine with {}" , fork) ,
1680+ format ! ( "called get_payload_by_hash_from_engine with {}" , fork) ,
16341681 ) ) ,
16351682 } ;
16361683 }
0 commit comments