diff --git a/crates/rpc/rpc-api/src/otterscan.rs b/crates/rpc/rpc-api/src/otterscan.rs index 2156765bb2..ebf3c91327 100644 --- a/crates/rpc/rpc-api/src/otterscan.rs +++ b/crates/rpc/rpc-api/src/otterscan.rs @@ -5,13 +5,23 @@ use reth_rpc_types::{ BlockDetails, ContractCreator, InternalOperation, OtsBlockTransactions, TraceEntry, TransactionsWithReceipts, }, - Transaction, + Header, Transaction, }; /// Otterscan rpc interface. #[cfg_attr(not(feature = "client"), rpc(server, namespace = "ots"))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "ots"))] pub trait Otterscan { + /// Get the block header by block number, required by otterscan. + /// Otterscan currently requires this endpoint, used as: + /// + /// 1. check if the node is Erigon or not + /// 2. get block header instead of the full block + /// + /// Ref: + #[method(name = "getHeaderByNumber", aliases = ["erigon_getHeaderByNumber"])] + async fn get_header_by_number(&self, block_number: u64) -> RpcResult>; + /// Check if a certain address contains a deployed code. #[method(name = "hasCode")] async fn has_code(&self, address: Address, block_number: Option) -> RpcResult; diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index f778dc22a9..0e90eca3e8 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -301,6 +301,8 @@ where let nonce = 1; let block_hash = B256::default(); + OtterscanClient::get_header_by_number(client, 1).await.unwrap(); + OtterscanClient::has_code(client, address, None).await.unwrap(); OtterscanClient::get_api_level(client).await.unwrap(); diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 4088d71ca0..b3ec8baa60 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -10,7 +10,7 @@ use reth_rpc_types::{ BlockDetails, ContractCreator, InternalOperation, OperationType, OtsBlockTransactions, OtsReceipt, OtsTransactionReceipt, TraceEntry, TransactionsWithReceipts, }, - BlockTransactions, Transaction, + BlockTransactions, Header, Transaction, }; use revm_inspectors::transfer::{TransferInspector, TransferKind}; use revm_primitives::ExecutionResult; @@ -35,6 +35,11 @@ impl OtterscanServer for OtterscanApi where Eth: EthApiServer + TraceExt + 'static, { + /// Handler for `{ots,erigon}_getHeaderByNumber` + async fn get_header_by_number(&self, block_number: u64) -> RpcResult> { + self.eth.header_by_number(BlockNumberOrTag::Number(block_number)).await + } + /// Handler for `ots_hasCode` async fn has_code(&self, address: Address, block_number: Option) -> RpcResult { self.eth.get_code(address, block_number).await.map(|code| !code.is_empty())