@@ -689,14 +689,17 @@ impl ApiServer {
689689 Ok ( code. into ( ) )
690690 }
691691
692+ /// Returns the EVM block with the given ethereum hash.
692693 async fn get_block_by_hash (
693694 & self ,
694695 block_hash : B256 ,
695696 hydrated_transactions : bool ,
696697 ) -> Result < Option < Block > > {
697698 node_info ! ( "eth_getBlockByHash" ) ;
698- let Some ( block) =
699- self . eth_rpc_client . block_by_hash ( & H256 :: from_slice ( block_hash. as_slice ( ) ) ) . await ?
699+ let Some ( block) = self
700+ . eth_rpc_client
701+ . block_by_ethereum_hash ( & H256 :: from_slice ( block_hash. as_slice ( ) ) )
702+ . await ?
700703 else {
701704 return Ok ( None ) ;
702705 } ;
@@ -795,8 +798,12 @@ impl ApiServer {
795798 return Err ( Error :: ReviveRpc ( EthRpcError :: InvalidTransaction ) ) ;
796799 } ;
797800
798- let latest_block = self . latest_block ( ) ;
799- let latest_block_id = Some ( BlockId :: hash ( B256 :: from_slice ( latest_block. as_ref ( ) ) ) ) ;
801+ let best_hash = self . latest_block ( ) ;
802+ let best_eth_hash =
803+ self . eth_rpc_client . resolve_ethereum_hash ( & best_hash) . await . ok_or_else ( || {
804+ Error :: InternalError ( "Ethereum block hash of latest block not found" . to_string ( ) )
805+ } ) ?;
806+ let latest_block_id = Some ( BlockId :: hash ( B256 :: from_slice ( best_eth_hash. as_ref ( ) ) ) ) ;
800807 let account = if self . impersonation_manager . is_impersonated ( from) || unsigned_tx {
801808 None
802809 } else {
@@ -824,7 +831,7 @@ impl ApiServer {
824831
825832 if transaction. chain_id . is_none ( ) {
826833 transaction. chain_id =
827- Some ( sp_core:: U256 :: from_big_endian ( & self . chain_id ( latest_block ) . to_be_bytes ( ) ) ) ;
834+ Some ( sp_core:: U256 :: from_big_endian ( & self . chain_id ( best_hash ) . to_be_bytes ( ) ) ) ;
828835 }
829836
830837 let tx = transaction
@@ -935,27 +942,27 @@ impl ApiServer {
935942 node_info ! ( "anvil_nodeInfo" ) ;
936943
937944 let best_hash = self . latest_block ( ) ;
938- let Some ( current_block) =
939- self . get_block_by_hash ( B256 :: from_slice ( best_hash. as_ref ( ) ) , false ) . await ?
940- else {
945+ let Some ( latest_evm_block) = self . get_block_by_substrate_hash ( best_hash) . await ? else {
941946 return Err ( Error :: InternalError ( "Latest block not found" . to_string ( ) ) ) ;
942947 } ;
943948 let current_block_number: u64 =
944- current_block . number . try_into ( ) . map_err ( |_| EthRpcError :: ConversionError ) ?;
949+ latest_evm_block . number . try_into ( ) . map_err ( |_| EthRpcError :: ConversionError ) ?;
945950 let current_block_timestamp: u64 =
946- current_block . timestamp . try_into ( ) . map_err ( |_| EthRpcError :: ConversionError ) ?;
951+ latest_evm_block . timestamp . try_into ( ) . map_err ( |_| EthRpcError :: ConversionError ) ?;
947952 // This is both gas price and base fee, since pallet-revive does not support tips
948953 // https://github.com/paritytech/polkadot-sdk/blob/227c73b5c8810c0f34e87447f00e96743234fa52/substrate/frame/revive/rpc/src/lib.rs#L269
949- let base_fee: u128 =
950- current_block. base_fee_per_gas . try_into ( ) . map_err ( |_| EthRpcError :: ConversionError ) ?;
951- let gas_limit: u64 = current_block. gas_limit . try_into ( ) . unwrap_or ( u64:: MAX ) ;
954+ let base_fee: u128 = latest_evm_block
955+ . base_fee_per_gas
956+ . try_into ( )
957+ . map_err ( |_| EthRpcError :: ConversionError ) ?;
958+ let gas_limit: u64 = latest_evm_block. gas_limit . try_into ( ) . unwrap_or ( u64:: MAX ) ;
952959 // pallet-revive should currently support all opcodes in PRAGUE.
953960 let hard_fork: & str = SpecId :: PRAGUE . into ( ) ;
954961
955962 Ok ( NodeInfo {
956963 current_block_number,
957964 current_block_timestamp,
958- current_block_hash : B256 :: from_slice ( best_hash . as_ref ( ) ) ,
965+ current_block_hash : B256 :: from_slice ( latest_evm_block . hash . as_ref ( ) ) ,
959966 hard_fork : hard_fork. to_string ( ) ,
960967 // pallet-revive does not support tips
961968 transaction_order : "fifo" . to_string ( ) ,
@@ -974,18 +981,16 @@ impl ApiServer {
974981 node_info ! ( "anvil_metadata" ) ;
975982
976983 let best_hash = self . latest_block ( ) ;
977- let Some ( latest_block) =
978- self . get_block_by_hash ( B256 :: from_slice ( best_hash. as_ref ( ) ) , false ) . await ?
979- else {
984+ let Some ( latest_evm_block) = self . get_block_by_substrate_hash ( best_hash) . await ? else {
980985 return Err ( Error :: InternalError ( "Latest block not found" . to_string ( ) ) ) ;
981986 } ;
982987 let latest_block_number: u64 =
983- latest_block . number . try_into ( ) . map_err ( |_| EthRpcError :: ConversionError ) ?;
988+ latest_evm_block . number . try_into ( ) . map_err ( |_| EthRpcError :: ConversionError ) ?;
984989
985990 Ok ( AnvilMetadata {
986991 client_version : CLIENT_VERSION . to_string ( ) ,
987992 chain_id : self . chain_id ( best_hash) ,
988- latest_block_hash : B256 :: from_slice ( best_hash . as_ref ( ) ) ,
993+ latest_block_hash : B256 :: from_slice ( latest_evm_block . hash . as_ref ( ) ) ,
989994 latest_block_number,
990995 instance_id : self . instance_id ,
991996 // Forking is not supported yet in anvil-polkadot
@@ -1472,12 +1477,18 @@ impl ApiServer {
14721477 Ok ( ( ) )
14731478 }
14741479
1480+ // This function translates a block ethereum hash to a substrate hash if needed.
14751481 async fn maybe_get_block_hash_for_tag (
14761482 & self ,
14771483 block_id : Option < BlockId > ,
14781484 ) -> Result < Option < H256 > > {
14791485 match ReviveBlockId :: from ( block_id) . inner ( ) {
1480- BlockNumberOrTagOrHash :: BlockHash ( hash) => Ok ( Some ( hash) ) ,
1486+ BlockNumberOrTagOrHash :: BlockHash ( hash) => {
1487+ // Translate the ethereum hash to a substrate hash.
1488+ Ok ( Some ( self . eth_rpc_client . resolve_substrate_hash ( & hash) . await . ok_or (
1489+ Error :: ReviveRpc ( EthRpcError :: ClientError ( ClientError :: EthereumBlockNotFound ) ) ,
1490+ ) ?) )
1491+ }
14811492 BlockNumberOrTagOrHash :: BlockNumber ( block_number) => {
14821493 let n = block_number. try_into ( ) . map_err ( |_| {
14831494 Error :: InvalidParams ( "Block number conversion failed" . to_string ( ) )
@@ -1495,6 +1506,7 @@ impl ApiServer {
14951506 }
14961507 }
14971508
1509+ /// Returns the substrate block hash for a given block id.
14981510 async fn get_block_hash_for_tag ( & self , block_id : Option < BlockId > ) -> Result < H256 > {
14991511 self . maybe_get_block_hash_for_tag ( block_id)
15001512 . await ?
@@ -1516,6 +1528,19 @@ impl ApiServer {
15161528 self . backend . blockchain ( ) . info ( ) . best_hash
15171529 }
15181530
1531+ /// Returns the EVM block for a given substrate block hash.
1532+ async fn get_block_by_substrate_hash ( & self , block_hash : H256 ) -> Result < Option < Block > > {
1533+ let Some ( substrate_block) = self . eth_rpc_client . block_by_hash ( & block_hash) . await ? else {
1534+ return Ok ( None ) ;
1535+ } ;
1536+ let Some ( evm_block) = self . eth_rpc_client . evm_block ( substrate_block, false ) . await else {
1537+ return Err ( Error :: InternalError (
1538+ "EVM block not found for substrate block" . to_string ( ) ,
1539+ ) ) ;
1540+ } ;
1541+ Ok ( Some ( evm_block) )
1542+ }
1543+
15191544 fn set_frame_system_balance (
15201545 & self ,
15211546 latest_block : H256 ,
@@ -1958,6 +1983,9 @@ async fn create_revive_rpc_client(
19581983 EthRpcClient :: new ( api, rpc_client, rpc, block_provider, receipt_provider)
19591984 . await
19601985 . map_err ( Error :: from) ?;
1986+ // Genesis block is not imported via block import notifications, so we need to subscribe and
1987+ // cache it manually.
1988+ let _ = eth_rpc_client. subscribe_and_cache_blocks ( 1 ) . await ;
19611989
19621990 // Capacity is chosen using random.org
19631991 eth_rpc_client. set_block_notifier ( Some ( tokio:: sync:: broadcast:: channel :: < H256 > ( 50 ) . 0 ) ) ;
0 commit comments