@@ -103,6 +103,8 @@ pub enum Error {
103
103
transactions_root : Hash256 ,
104
104
} ,
105
105
InvalidJWTSecret ( String ) ,
106
+ InvalidForkForPayload ,
107
+ InvalidPayloadBody ( String ) ,
106
108
BeaconStateError ( BeaconStateError ) ,
107
109
}
108
110
@@ -1602,22 +1604,67 @@ impl<T: EthSpec> ExecutionLayer<T> {
1602
1604
. map_err ( Error :: EngineError )
1603
1605
}
1604
1606
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 (
1606
1653
& self ,
1607
1654
hash : ExecutionBlockHash ,
1608
1655
fork : ForkName ,
1609
1656
) -> Result < Option < ExecutionPayload < T > > , Error > {
1610
1657
self . engine ( )
1611
1658
. 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)
1613
1660
. await
1614
1661
} )
1615
1662
. await
1616
1663
. map_err ( Box :: new)
1617
1664
. map_err ( Error :: EngineError )
1618
1665
}
1619
1666
1620
- async fn get_payload_by_block_hash_from_engine (
1667
+ async fn get_payload_by_hash_from_engine (
1621
1668
& self ,
1622
1669
engine : & Engine ,
1623
1670
hash : ExecutionBlockHash ,
@@ -1630,7 +1677,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
1630
1677
ForkName :: Merge => Ok ( Some ( ExecutionPayloadMerge :: default ( ) . into ( ) ) ) ,
1631
1678
ForkName :: Capella => Ok ( Some ( ExecutionPayloadCapella :: default ( ) . into ( ) ) ) ,
1632
1679
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) ,
1634
1681
) ) ,
1635
1682
} ;
1636
1683
}
0 commit comments