cfx_rpc/
eth.rs

1use crate::helpers::{FeeHistoryCache, MAX_FEE_HISTORY_CACHE_BLOCK_COUNT};
2use async_trait::async_trait;
3use cfx_execute_helper::estimation::EstimateRequest;
4use cfx_executor::executive::{
5    Executed, ExecutionError, ExecutionOutcome, ToRepackError, TxDropError,
6};
7use cfx_parameters::rpc::GAS_PRICE_DEFAULT_VALUE;
8use cfx_rpc_cfx_types::{
9    traits::BlockProvider, PhantomBlock, RpcImplConfiguration,
10};
11use cfx_rpc_eth_api::EthApiServer;
12use cfx_rpc_eth_types::{
13    AccessListResult, AccountOverride, AccountPendingTransactions, Block,
14    BlockId, BlockOverrides, Bundle, Error, EthCallResponse, EthRpcLogFilter,
15    EthRpcLogFilter as Filter, EvmOverrides, FeeHistory, Header, Log, LogData,
16    Receipt, RpcStateOverride, SimulatePayload, SimulatedBlock, StateContext,
17    SyncInfo, SyncStatus, Transaction, TransactionRequest,
18};
19use cfx_rpc_primitives::{Bytes, Index, U64 as HexU64};
20use cfx_rpc_utils::{
21    error::{
22        errors::*, jsonrpc_error_helpers::*,
23        jsonrpsee_error_helpers::internal_error as jsonrpsee_internal_error,
24    },
25    helpers::SpawnBlocking,
26};
27use cfx_statedb::StateDbExt;
28use cfx_tasks::{TaskExecutor, TaskSpawner};
29use cfx_types::{
30    Address, AddressSpaceUtil, BigEndianHash, Space, H160, H256, H64, U256, U64,
31};
32use cfx_util_macros::bail;
33use cfx_vm_types::Error as VmError;
34use cfxcore::{
35    errors::{Error as CoreError, Result as CoreResult},
36    ConsensusGraph, SharedConsensusGraph, SharedSynchronizationService,
37    SharedTransactionPool,
38};
39use cfxcore_errors::ProviderBlockError;
40use jsonrpc_core::Error as RpcError;
41use jsonrpsee::{core::RpcResult, types::ErrorObjectOwned};
42use primitives::{
43    filter::LogFilter, receipt::EVM_SPACE_SUCCESS, Action, EpochNumber,
44    StorageKey, StorageValue, TransactionStatus, TransactionWithSignature,
45};
46use rustc_hex::ToHex;
47use solidity_abi::string_revert_reason_decode;
48use std::{collections::HashMap, future::Future};
49
50type BlockNumber = BlockId;
51type BlockNumberOrTag = BlockId;
52
53type JsonStorageKey = U256;
54type RpcBlock = Block;
55
56#[derive(Clone)]
57pub struct EthApi {
58    config: RpcImplConfiguration,
59    consensus: SharedConsensusGraph,
60    sync: SharedSynchronizationService,
61    tx_pool: SharedTransactionPool,
62    fee_history_cache: FeeHistoryCache,
63    executor: TaskExecutor,
64}
65
66impl EthApi {
67    pub fn new(
68        config: RpcImplConfiguration, consensus: SharedConsensusGraph,
69        sync: SharedSynchronizationService, tx_pool: SharedTransactionPool,
70        executor: TaskExecutor,
71    ) -> Self {
72        EthApi {
73            config,
74            consensus,
75            sync,
76            tx_pool,
77            fee_history_cache: FeeHistoryCache::new(),
78            executor,
79        }
80    }
81
82    pub fn consensus_graph(&self) -> &ConsensusGraph { &self.consensus }
83
84    pub fn tx_pool(&self) -> &SharedTransactionPool { &self.tx_pool }
85
86    pub fn fetch_block_by_height(
87        &self, height: u64,
88    ) -> Result<PhantomBlock, ProviderBlockError> {
89        self.consensus_graph()
90            .get_phantom_block_by_number(
91                EpochNumber::Number(height),
92                None,
93                false,
94            )?
95            .ok_or(
96                format!("Specified block does not exist, height={}", height)
97                    .into(),
98            )
99    }
100
101    pub fn fetch_block_by_hash(
102        &self, hash: &H256,
103    ) -> Result<PhantomBlock, ProviderBlockError> {
104        self.consensus_graph()
105            .get_phantom_block_by_hash(hash, false)?
106            .ok_or(
107                format!("Specified block does not exist, hash={:?}", hash)
108                    .into(),
109            )
110    }
111
112    fn convert_block_number_to_epoch_number(
113        &self, block_number: BlockNumber,
114    ) -> Result<EpochNumber, String> {
115        if let BlockNumber::Hash { hash, .. } = block_number {
116            let consensus_graph = self.consensus_graph();
117            match consensus_graph.get_block_epoch_number(&hash) {
118                Some(num) => {
119                    // do not expose non-pivot blocks in eth RPC
120                    let pivot = consensus_graph
121                        .get_block_hashes_by_epoch(EpochNumber::Number(num))?
122                        .last()
123                        .cloned();
124
125                    if Some(hash) != pivot {
126                        return Err(format!("Block {} not found", hash));
127                    }
128
129                    Ok(EpochNumber::Number(num))
130                }
131                None => return Err(format!("Block {} not found", hash)),
132            }
133        } else {
134            block_number.try_into().map_err(|e: Error| e.to_string())
135        }
136    }
137
138    pub fn exec_transaction(
139        &self, mut request: TransactionRequest,
140        block_number_or_hash: Option<BlockNumber>,
141        state_overrides: Option<RpcStateOverride>,
142        block_overrides: Option<Box<BlockOverrides>>,
143    ) -> CoreResult<(Executed, U256)> {
144        let consensus_graph = self.consensus_graph();
145
146        if request.gas_price.is_some()
147            && request.max_priority_fee_per_gas.is_some()
148        {
149            return Err(RpcError::from(
150                EthApiError::ConflictingFeeFieldsInRequest,
151            )
152            .into());
153        }
154
155        if request.max_fee_per_gas.is_some()
156            && request.max_priority_fee_per_gas.is_some()
157        {
158            if request.max_fee_per_gas.unwrap()
159                < request.max_priority_fee_per_gas.unwrap()
160            {
161                return Err(RpcError::from(
162                    RpcInvalidTransactionError::TipAboveFeeCap,
163                )
164                .into());
165            }
166        }
167
168        let state_overrides = match state_overrides {
169            Some(states) => {
170                let mut state_overrides = HashMap::new();
171                for (address, rpc_account_override) in states {
172                    let account_override =
173                        AccountOverride::try_from(rpc_account_override)
174                            .map_err(|err| {
175                                CoreError::InvalidParam(
176                                    err.into(),
177                                    Default::default(),
178                                )
179                            })?;
180                    state_overrides.insert(address, account_override);
181                }
182                Some(state_overrides)
183            }
184            None => None,
185        };
186        let evm_overrides = EvmOverrides::new(state_overrides, block_overrides);
187
188        let epoch = self.convert_block_number_to_epoch_number(
189            block_number_or_hash.unwrap_or_default(),
190        )?;
191
192        // if gas_price and gas is zero, it is considered as not set
193        request.unset_zero_gas_and_price();
194
195        let estimate_request = EstimateRequest {
196            has_sender: request.from.is_some(),
197            has_gas_limit: request.gas.is_some(),
198            has_gas_price: request.has_gas_price(),
199            has_nonce: request.nonce.is_some(),
200            has_storage_limit: false,
201        };
202
203        let chain_id = self.consensus.best_chain_id();
204
205        let max_gas = self.config.max_estimation_gas_limit;
206        let signed_tx = request.sign_call(chain_id.in_evm_space(), max_gas)?;
207
208        let (execution_outcome, estimation) = consensus_graph.call_virtual(
209            &signed_tx,
210            epoch,
211            estimate_request,
212            evm_overrides,
213        )?;
214
215        let executed = match execution_outcome {
216            ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
217                expected,
218                got,
219            )) => bail!(invalid_input_rpc_err(
220                format! {"nonce is too old expected {:?} got {:?}", expected, got}
221            )),
222            ExecutionOutcome::NotExecutedDrop(
223                TxDropError::InvalidRecipientAddress(recipient),
224            ) => bail!(invalid_input_rpc_err(
225                format! {"invalid recipient address {:?}", recipient}
226            )),
227            ExecutionOutcome::NotExecutedDrop(
228                TxDropError::NotEnoughGasLimit { expected, got },
229            ) => bail!(invalid_input_rpc_err(
230                format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
231            )),
232            ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
233                address,
234            )) => bail!(invalid_input_rpc_err(
235                format! {"tx sender has contract code: {:?}", address}
236            )),
237            ExecutionOutcome::NotExecutedToReconsiderPacking(
238                ToRepackError::SenderDoesNotExist,
239            ) => {
240                bail!(RpcError::from(
241                    RpcInvalidTransactionError::InsufficientFunds
242                ))
243            }
244            ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
245                bail!(invalid_input_rpc_err(format! {"err: {:?}", e}))
246            }
247            ExecutionOutcome::ExecutionErrorBumpNonce(
248                ExecutionError::NotEnoughCash { .. },
249                _executed,
250            ) => {
251                bail!(RpcError::from(
252                    RpcInvalidTransactionError::InsufficientFunds
253                ))
254            }
255            ExecutionOutcome::ExecutionErrorBumpNonce(
256                ExecutionError::NonceOverflow(addr),
257                _executed,
258            ) => {
259                bail!(geth_call_execution_error(
260                    format!("address nonce overflow: {})", addr),
261                    "".into()
262                ))
263            }
264            ExecutionOutcome::ExecutionErrorBumpNonce(
265                ExecutionError::VmError(VmError::Reverted),
266                executed,
267            ) => bail!(geth_call_execution_error(
268                format!(
269                    "execution reverted: revert: {}",
270                    string_revert_reason_decode(&executed.output)
271                ),
272                format!("0x{}", executed.output.to_hex::<String>())
273            )),
274            ExecutionOutcome::ExecutionErrorBumpNonce(
275                ExecutionError::VmError(e),
276                _executed,
277            ) => bail!(geth_call_execution_error(
278                format!("execution reverted: {}", e),
279                "".into()
280            )),
281            ExecutionOutcome::Finished(executed) => executed,
282        };
283
284        Ok((executed, estimation.estimated_gas_limit))
285    }
286
287    pub fn send_transaction_with_signature(
288        &self, tx: TransactionWithSignature,
289    ) -> CoreResult<H256> {
290        if self.sync.catch_up_mode() {
291            bail!(request_rejected_in_catch_up_mode(None));
292        }
293        let (signed_trans, failed_trans) =
294            self.tx_pool.insert_new_transactions(vec![tx]);
295        if signed_trans.len() + failed_trans.len() > 1 {
296            // This should never happen
297            Ok(H256::zero().into())
298        } else if signed_trans.len() + failed_trans.len() == 0 {
299            // For tx in transactions_pubkey_cache, we simply ignore them
300            bail!(RpcError::from(EthApiError::PoolError(
301                RpcPoolError::AlreadyKnown
302            )));
303        } else if signed_trans.is_empty() {
304            let tx_err = failed_trans.into_iter().next().expect("Not empty").1;
305            bail!(RpcError::from(EthApiError::from(tx_err)))
306        } else {
307            let tx_hash = signed_trans[0].hash();
308            self.sync.append_received_transactions(signed_trans);
309            Ok(tx_hash.into())
310        }
311    }
312
313    pub fn construct_rpc_receipt(
314        &self, b: &PhantomBlock, idx: usize, prior_log_index: &mut usize,
315    ) -> CoreResult<Receipt> {
316        if b.transactions.len() != b.receipts.len() {
317            return Err(internal_error(
318                "Inconsistent state: transactions and receipts length mismatch",
319            )
320            .into());
321        }
322
323        if b.transactions.len() != b.errors.len() {
324            return Err(internal_error(
325                "Inconsistent state: transactions and errors length mismatch",
326            )
327            .into());
328        }
329
330        if idx >= b.transactions.len() {
331            return Err(internal_error(
332                "Inconsistent state: tx index out of bound",
333            )
334            .into());
335        }
336
337        let tx = &b.transactions[idx];
338        let receipt = &b.receipts[idx];
339
340        if receipt.logs.iter().any(|l| l.space != Space::Ethereum) {
341            return Err(internal_error(
342                "Inconsistent state: native tx in phantom block",
343            )
344            .into());
345        }
346
347        let contract_address = match receipt.outcome_status {
348            TransactionStatus::Success => {
349                Transaction::deployed_contract_address(tx)
350            }
351            _ => None,
352        };
353
354        let transaction_hash = tx.hash();
355        let transaction_index: U256 = idx.into();
356        let block_hash = b.pivot_header.hash();
357        let block_height: U256 = b.pivot_header.height().into();
358
359        let logs: Vec<_> = receipt
360            .logs
361            .iter()
362            .cloned()
363            .enumerate()
364            .map(|(idx, log)| Log {
365                inner: LogData {
366                    address: log.address,
367                    topics: log.topics,
368                    data: log.data.into(),
369                },
370                block_hash,
371                block_number: block_height,
372                transaction_hash,
373                transaction_index,
374                block_timestamp: Some(b.pivot_header.timestamp().into()),
375                log_index: Some((*prior_log_index + idx).into()),
376                transaction_log_index: Some(idx.into()),
377                removed: false,
378            })
379            .collect();
380
381        *prior_log_index += logs.len();
382
383        let gas_used = match idx {
384            0 => receipt.accumulated_gas_used,
385            idx => {
386                receipt.accumulated_gas_used
387                    - b.receipts[idx - 1].accumulated_gas_used
388            }
389        };
390
391        let tx_exec_error_msg = if b.errors[idx].is_empty() {
392            None
393        } else {
394            Some(b.errors[idx].clone())
395        };
396
397        let effective_gas_price =
398            if let Some(base_price) = b.pivot_header.base_price() {
399                let base_price = base_price[tx.space()];
400                if *tx.gas_price() < base_price {
401                    *tx.gas_price()
402                } else {
403                    tx.effective_gas_price(&base_price)
404                }
405            } else {
406                *tx.gas_price()
407            };
408
409        Ok(Receipt {
410            transaction_hash,
411            transaction_index,
412            block_hash,
413            from: tx.sender().address,
414            to: match tx.action() {
415                Action::Create => None,
416                Action::Call(addr) => Some(addr),
417            },
418            block_number: block_height,
419            cumulative_gas_used: receipt.accumulated_gas_used,
420            gas_used,
421            gas_fee: receipt.gas_fee,
422            contract_address,
423            logs,
424            logs_bloom: receipt.log_bloom,
425            status_code: receipt
426                .outcome_status
427                .in_space(Space::Ethereum)
428                .into(),
429            effective_gas_price,
430            tx_exec_error_msg,
431            transaction_type: receipt
432                .burnt_gas_fee
433                .is_some()
434                .then_some(U64::from(tx.type_id())),
435            burnt_gas_fee: receipt.burnt_gas_fee,
436        })
437    }
438
439    pub fn get_tx_from_txpool(&self, hash: H256) -> Option<Transaction> {
440        let tx = self.tx_pool.get_transaction(&hash)?;
441
442        if tx.space() == Space::Ethereum {
443            Some(Transaction::from_signed(
444                &tx,
445                (None, None, None),
446                (None, None),
447            ))
448        } else {
449            None
450        }
451    }
452
453    pub fn get_block_receipts(
454        &self, block_num: BlockNumber,
455    ) -> CoreResult<Vec<Receipt>> {
456        let b = {
457            let phantom_block = self.phantom_block_by_number(block_num)?;
458
459            match phantom_block {
460                None => return Err(unknown_block().into()),
461                Some(b) => b,
462            }
463        };
464
465        let mut block_receipts = vec![];
466        let mut prior_log_index = 0;
467
468        for idx in 0..b.receipts.len() {
469            block_receipts.push(self.construct_rpc_receipt(
470                &b,
471                idx,
472                &mut prior_log_index,
473            )?);
474        }
475
476        return Ok(block_receipts);
477    }
478
479    pub fn block_tx_by_index(
480        phantom_block: Option<PhantomBlock>, idx: usize,
481    ) -> Option<Transaction> {
482        match phantom_block {
483            None => None,
484            Some(pb) => match pb.transactions.get(idx) {
485                None => None,
486                Some(tx) => {
487                    let block_number = Some(pb.pivot_header.height().into());
488                    let receipt = pb.receipts.get(idx).unwrap();
489                    let status =
490                        receipt.outcome_status.in_space(Space::Ethereum);
491                    let contract_address = match status == EVM_SPACE_SUCCESS {
492                        true => Transaction::deployed_contract_address(&tx),
493                        false => None,
494                    };
495                    Some(Transaction::from_signed(
496                        &tx,
497                        (
498                            Some(pb.pivot_header.hash()),
499                            block_number,
500                            Some(idx.into()),
501                        ),
502                        (Some(status.into()), contract_address),
503                    ))
504                }
505            },
506        }
507    }
508
509    pub fn sync_status(&self) -> SyncStatus {
510        if self.sync.catch_up_mode() {
511            SyncStatus::Info(SyncInfo {
512                starting_block: U256::from(self.consensus.block_count()),
513                current_block: U256::from(self.consensus.block_count()),
514                highest_block: U256::from(
515                    self.sync.get_synchronization_graph().block_count(),
516                ),
517                warp_chunks_amount: None,
518                warp_chunks_processed: None,
519            })
520        } else {
521            SyncStatus::None
522        }
523    }
524
525    pub fn chain_id(&self) -> u32 {
526        self.consensus.best_chain_id().in_evm_space()
527    }
528
529    pub fn gas_price(&self) -> U256 {
530        let (_, maybe_base_price) =
531            self.tx_pool.get_best_info_with_parent_base_price();
532        if let Some(base_price) = maybe_base_price {
533            return base_price[Space::Ethereum];
534        }
535
536        let consensus_gas_price = self
537            .consensus_graph()
538            .gas_price(Space::Ethereum)
539            .unwrap_or(GAS_PRICE_DEFAULT_VALUE.into());
540        std::cmp::max(
541            consensus_gas_price,
542            self.tx_pool.config.min_eth_tx_price.into(),
543        )
544    }
545
546    pub fn latest_block_number(&self) -> CoreResult<U256> {
547        let consensus_graph = self.consensus_graph();
548        let epoch_num = EpochNumber::LatestState;
549        match consensus_graph.get_height_from_epoch_number(epoch_num.into()) {
550            Ok(height) => Ok(height.into()),
551            Err(e) => Err(RpcError::invalid_params(e).into()),
552        }
553    }
554
555    pub fn best_epoch_number(&self) -> u64 {
556        self.consensus.best_epoch_number()
557    }
558
559    pub fn user_balance(
560        &self, address: H160, num: Option<BlockNumber>,
561    ) -> CoreResult<U256> {
562        let epoch_num =
563            self.convert_block_number_to_epoch_number(num.unwrap_or_default())?;
564        let state_db = self
565            .consensus
566            .get_eth_state_db_by_epoch_number(epoch_num, "num")?;
567        let acc = state_db
568            .get_account(&address.with_evm_space())
569            .map_err(|err| CoreError::from(err))?;
570
571        Ok(acc.map_or(U256::zero(), |acc| acc.balance).into())
572    }
573
574    pub fn storage_at(
575        &self, address: H160, position: U256, block_num: Option<BlockNumber>,
576    ) -> CoreResult<H256> {
577        let epoch_num = self.convert_block_number_to_epoch_number(
578            block_num.unwrap_or_default(),
579        )?;
580
581        let state_db = self
582            .consensus
583            .get_eth_state_db_by_epoch_number(epoch_num, "epoch_number")?;
584
585        let position: H256 = H256::from_uint(&position);
586
587        let key = StorageKey::new_storage_key(&address, position.as_ref())
588            .with_evm_space();
589
590        Ok(
591            match state_db
592                .get::<StorageValue>(key)
593                .map_err(|err| CoreError::from(err))?
594            {
595                Some(entry) => H256::from_uint(&entry.value).into(),
596                None => H256::zero(),
597            },
598        )
599    }
600
601    pub fn phantom_block_by_hash(
602        &self, hash: H256,
603    ) -> CoreResult<Option<PhantomBlock>> {
604        self.phantom_block_by_number(BlockNumber::Hash {
605            hash,
606            require_canonical: None,
607        })
608    }
609
610    pub fn phantom_block_by_number(
611        &self, block_num: BlockNumber,
612    ) -> CoreResult<Option<PhantomBlock>> {
613        let phantom_block = {
614            // keep read lock to ensure consistent view
615            let _inner = self.consensus_graph().inner.read();
616
617            match block_num {
618                BlockNumber::Hash { hash, .. } => {
619                    self.consensus_graph()
620                        .get_phantom_block_by_hash(
621                            &hash, false, /* include_traces */
622                        )
623                        .map_err(RpcError::invalid_params)?
624                }
625                _ => {
626                    match self.consensus_graph().get_phantom_block_by_number(
627                        block_num.try_into()?,
628                        None,
629                        false, /* include_traces */
630                    ) {
631                        Ok(pb) => pb,
632                        Err(e) => match e {
633                            ProviderBlockError::Common(e) => {
634                                return Err(RpcError::invalid_params(e).into());
635                            }
636                            ProviderBlockError::EpochNumberTooLarge => None,
637                        },
638                    }
639                }
640            }
641        };
642
643        Ok(phantom_block)
644    }
645
646    pub fn block_by_hash(
647        &self, hash: H256, include_txs: bool,
648    ) -> CoreResult<Option<RpcBlock>> {
649        let phantom_block = self.phantom_block_by_hash(hash)?;
650
651        match phantom_block {
652            None => Ok(None),
653            Some(pb) => Ok(Some(RpcBlock::from_phantom(&pb, include_txs))),
654        }
655    }
656
657    pub fn block_by_number(
658        &self, block_num: BlockNumber, include_txs: bool,
659    ) -> CoreResult<Option<RpcBlock>> {
660        let phantom_block = self.phantom_block_by_number(block_num)?;
661
662        match phantom_block {
663            None => Ok(None),
664            Some(pb) => Ok(Some(RpcBlock::from_phantom(&pb, include_txs))),
665        }
666    }
667
668    pub fn next_nonce(
669        &self, address: H160, num: Option<BlockNumber>,
670    ) -> CoreResult<U256> {
671        let nonce = match num {
672            Some(BlockNumber::Pending) => {
673                self.tx_pool.get_next_nonce(&address.with_evm_space())
674            }
675            _ => self.consensus_graph().next_nonce(
676                address.with_evm_space(),
677                num.unwrap_or_default().into(),
678                "num",
679            )?,
680        };
681
682        Ok(nonce)
683    }
684
685    pub fn block_transaction_count_by_hash(
686        &self, hash: H256,
687    ) -> CoreResult<Option<U256>> {
688        let phantom_block = self.phantom_block_by_hash(hash)?;
689
690        match phantom_block {
691            None => Ok(None),
692            Some(pb) => Ok(Some(pb.transactions.len().into())),
693        }
694    }
695
696    pub fn block_transaction_count_by_number(
697        &self, block_num: BlockNumber,
698    ) -> CoreResult<Option<U256>> {
699        let phantom_block = self.phantom_block_by_number(block_num)?;
700
701        match phantom_block {
702            None => Ok(None),
703            Some(pb) => Ok(Some(pb.transactions.len().into())),
704        }
705    }
706
707    pub fn block_uncles_count_by_hash(
708        &self, hash: H256,
709    ) -> CoreResult<Option<U256>> {
710        let epoch_num = match self.consensus.get_block_epoch_number(&hash) {
711            None => return Ok(None),
712            Some(n) => n,
713        };
714
715        let maybe_pivot_hash = self
716            .consensus
717            .get_block_hashes_by_epoch(epoch_num.into())
718            .ok()
719            .and_then(|hs| hs.last().cloned());
720
721        match maybe_pivot_hash {
722            Some(h) if h == hash => Ok(Some(0.into())),
723            _ => Ok(None),
724        }
725    }
726
727    pub fn block_uncles_count_by_number(
728        &self, block_num: BlockNumber,
729    ) -> CoreResult<Option<U256>> {
730        let epoch_num = self.convert_block_number_to_epoch_number(block_num)?;
731        let maybe_epoch =
732            self.consensus.get_block_hashes_by_epoch(epoch_num).ok();
733
734        Ok(maybe_epoch.map(|_| 0.into()))
735    }
736
737    pub fn code_at(
738        &self, address: H160, block_num: Option<BlockNumber>,
739    ) -> CoreResult<Bytes> {
740        let epoch_num = self.convert_block_number_to_epoch_number(
741            block_num.unwrap_or_default(),
742        )?;
743
744        let state_db = self
745            .consensus
746            .get_eth_state_db_by_epoch_number(epoch_num, "num")?;
747
748        let address = address.with_evm_space();
749
750        let code = match state_db
751            .get_account(&address)
752            .map_err(|err| CoreError::from(err))?
753        {
754            Some(acc) => match state_db
755                .get_code(&address, &acc.code_hash)
756                .map_err(|err| CoreError::from(err))?
757            {
758                Some(code) => (*code.code).clone(),
759                _ => vec![],
760            },
761            None => vec![],
762        };
763
764        Ok(Bytes::new(code))
765    }
766
767    pub fn fee_history(
768        &self, mut block_count: HexU64, newest_block: BlockNumber,
769        reward_percentiles: Option<Vec<f64>>,
770    ) -> CoreResult<FeeHistory> {
771        if block_count.as_u64() == 0 || newest_block == BlockNumber::Pending {
772            return Ok(FeeHistory::new());
773        }
774
775        if block_count.as_u64() > MAX_FEE_HISTORY_CACHE_BLOCK_COUNT {
776            block_count = HexU64::from(MAX_FEE_HISTORY_CACHE_BLOCK_COUNT);
777        }
778
779        if let Some(percentiles) = &reward_percentiles {
780            if percentiles.windows(2).any(|w| w[0] > w[1] || w[0] > 100.) {
781                return Err(RpcError::from(
782                    EthApiError::InvalidRewardPercentiles,
783                )
784                .into());
785            }
786        }
787        let reward_percentiles = reward_percentiles.unwrap_or_default();
788
789        // keep read lock to ensure consistent view
790        let _consensus = self.consensus_graph().inner.read();
791
792        let epoch_num =
793            self.convert_block_number_to_epoch_number(newest_block)?;
794        let newest_height: u64 = self
795            .consensus_graph()
796            .get_height_from_epoch_number(epoch_num)
797            .map_err(RpcError::invalid_params)?;
798
799        if newest_block == BlockNumber::Latest {
800            let fetch_block_by_hash = |height| {
801                self.fetch_block_by_hash(&height).map_err(|e| e.to_string())
802            };
803
804            let latest_block = self
805                .fetch_block_by_height(newest_height)
806                .map_err(|e| internal_rpc_err(e.to_string()))?;
807
808            self.fee_history_cache
809                .update_to_latest_block(
810                    newest_height,
811                    latest_block.pivot_header.hash(),
812                    block_count.as_u64(),
813                    fetch_block_by_hash,
814                )
815                .map_err(|e| internal_rpc_err(e.to_string()))?;
816        }
817
818        let mut fee_history = FeeHistory::new();
819
820        let end_block = newest_height;
821        let start_block = if end_block >= block_count.as_u64() {
822            end_block - block_count.as_u64() + 1
823        } else {
824            0
825        };
826
827        let mut cached_fee_history_entries = self
828            .fee_history_cache
829            .get_history_with_missing_info(start_block, end_block);
830
831        cached_fee_history_entries.reverse();
832        for (i, entry) in cached_fee_history_entries.into_iter().enumerate() {
833            if entry.is_none() {
834                let height = end_block - i as u64;
835                let block = self
836                    .fetch_block_by_height(height)
837                    .map_err(RpcError::invalid_params)?;
838
839                // Internal error happens only if the fetch header has
840                // inconsistent block height
841                fee_history
842                    .push_front_block(
843                        Space::Ethereum,
844                        &reward_percentiles,
845                        &block.pivot_header,
846                        block.transactions.iter().map(|x| &**x),
847                    )
848                    .map_err(|_| RpcError::internal_error())?;
849            } else {
850                fee_history
851                    .push_front_entry(&entry.unwrap(), &reward_percentiles)
852                    .expect("always success");
853            }
854        }
855
856        let last_hash = self
857            .consensus_graph()
858            .get_hash_from_epoch_number((end_block + 1).into())?;
859        let last_header = self
860            .consensus_graph()
861            .data_manager()
862            .block_header_by_hash(&last_hash)
863            .ok_or_else(|| {
864                format!("last block missing, height={}", end_block + 1)
865            })?;
866
867        fee_history.finish(
868            start_block,
869            last_header.base_price().as_ref(),
870            Space::Ethereum,
871        );
872
873        Ok(fee_history)
874    }
875
876    pub fn transaction_by_hash(
877        &self, hash: H256,
878    ) -> CoreResult<Option<Transaction>> {
879        let tx_index = match self
880            .consensus
881            .data_manager()
882            .transaction_index_by_hash(&hash, false /* update_cache */)
883        {
884            None => return Ok(self.get_tx_from_txpool(hash)),
885            Some(tx_index) => tx_index,
886        };
887
888        let epoch_num =
889            match self.consensus.get_block_epoch_number(&tx_index.block_hash) {
890                None => return Ok(self.get_tx_from_txpool(hash)),
891                Some(n) => n,
892            };
893
894        let maybe_block = self
895            .consensus_graph()
896            .get_phantom_block_by_number(
897                EpochNumber::Number(epoch_num),
898                None,
899                false, /* include_traces */
900            )
901            .map_err(RpcError::invalid_params)?;
902
903        let phantom_block = match maybe_block {
904            None => return Ok(self.get_tx_from_txpool(hash)),
905            Some(b) => b,
906        };
907
908        for (idx, tx) in phantom_block.transactions.iter().enumerate() {
909            if tx.hash() == hash {
910                let tx = Self::block_tx_by_index(Some(phantom_block), idx);
911                if let Some(tx_ref) = &tx {
912                    if tx_ref.status
913                        == Some(
914                            TransactionStatus::Skipped
915                                .in_space(Space::Ethereum)
916                                .into(),
917                        )
918                    {
919                        // A skipped transaction is not available to clients if
920                        // accessed by its hash.
921                        return Ok(None);
922                    }
923                }
924                return Ok(tx);
925            }
926        }
927
928        Ok(self.get_tx_from_txpool(hash))
929    }
930
931    pub fn transaction_receipt(
932        &self, tx_hash: H256,
933    ) -> CoreResult<Option<Receipt>> {
934        let tx_index =
935            match self.consensus.data_manager().transaction_index_by_hash(
936                &tx_hash, false, /* update_cache */
937            ) {
938                None => return Ok(None),
939                Some(tx_index) => tx_index,
940            };
941
942        let epoch_num =
943            match self.consensus.get_block_epoch_number(&tx_index.block_hash) {
944                None => return Ok(None),
945                Some(n) => n,
946            };
947
948        if epoch_num > self.consensus_graph().best_executed_state_epoch_number()
949        {
950            // The receipt is only visible to optimistic execution.
951            return Ok(None);
952        }
953
954        let maybe_block = self
955            .consensus_graph()
956            .get_phantom_block_by_number(
957                EpochNumber::Number(epoch_num),
958                None,
959                false, /* include_traces */
960            )
961            .map_err(RpcError::invalid_params)?;
962
963        let phantom_block = match maybe_block {
964            None => return Ok(None),
965            Some(b) => b,
966        };
967
968        let mut prior_log_index = 0;
969
970        for (idx, tx) in phantom_block.transactions.iter().enumerate() {
971            if tx.hash() == tx_hash {
972                let receipt = self.construct_rpc_receipt(
973                    &phantom_block,
974                    idx,
975                    &mut prior_log_index,
976                )?;
977                // A skipped transaction is not available to clients if accessed
978                // by its hash.
979                if receipt.status_code
980                    == TransactionStatus::Skipped
981                        .in_space(Space::Ethereum)
982                        .into()
983                {
984                    return Ok(None);
985                }
986
987                return Ok(Some(receipt));
988            }
989
990            // if the if-branch was not entered, we do the bookkeeping here
991            prior_log_index += phantom_block.receipts[idx].logs.len();
992        }
993
994        Ok(None)
995    }
996
997    pub fn logs(&self, filter: EthRpcLogFilter) -> CoreResult<Vec<Log>> {
998        let filter: LogFilter = filter.into_primitive(self)?;
999
1000        let logs = self
1001            .consensus_graph()
1002            .logs(filter)
1003            .map_err(|err| CoreError::from(err))?;
1004
1005        // If the results does not fit into `max_limit`, report an error
1006        if let Some(max_limit) = self.config.get_logs_filter_max_limit {
1007            if logs.len() > max_limit {
1008                bail!(invalid_params("filter", format!("This query results in too many logs, max limitation is {}, please use a smaller block range", max_limit)));
1009            }
1010        }
1011
1012        Ok(logs
1013            .iter()
1014            .cloned()
1015            .map(|l| Log::try_from_localized(l, self, false))
1016            .collect::<Result<_, _>>()?)
1017    }
1018
1019    pub fn max_priority_fee_per_gas(&self) -> CoreResult<U256> {
1020        let evm_ratio =
1021            self.tx_pool.machine().params().evm_transaction_block_ratio
1022                as usize;
1023
1024        let fee_history = self.fee_history(
1025            HexU64::from(300),
1026            BlockNumber::Latest,
1027            Some(vec![50f64]),
1028        )?;
1029
1030        let total_reward: U256 = fee_history
1031            .reward()
1032            .iter()
1033            .map(|x| x.first().unwrap())
1034            .fold(U256::zero(), |x, y| x + *y);
1035
1036        Ok(total_reward * evm_ratio / 300)
1037    }
1038
1039    pub fn account_pending_transactions(
1040        &self, address: Address, maybe_start_nonce: Option<U256>,
1041        maybe_limit: Option<U64>,
1042    ) -> CoreResult<AccountPendingTransactions> {
1043        let (pending_txs, tx_status, pending_count) = self
1044            .tx_pool()
1045            .get_account_pending_transactions(
1046                &Address::from(address).with_evm_space(),
1047                maybe_start_nonce,
1048                maybe_limit.map(|limit| limit.as_usize()),
1049                self.best_epoch_number(),
1050            )
1051            .map_err(|e| CoreError::from(e))?;
1052        Ok(AccountPendingTransactions {
1053            pending_transactions: pending_txs
1054                .into_iter()
1055                .map(|tx| {
1056                    Transaction::from_signed(
1057                        &tx,
1058                        (None, None, None),
1059                        (None, None),
1060                    )
1061                })
1062                .collect(),
1063            first_tx_status: tx_status,
1064            pending_count: pending_count.into(),
1065        })
1066    }
1067}
1068
1069impl SpawnBlocking for EthApi {
1070    fn io_task_spawner(&self) -> impl TaskSpawner { self.executor.clone() }
1071}
1072
1073impl EthApi {
1074    pub fn async_transaction_by_hash(
1075        &self, hash: H256,
1076    ) -> impl Future<Output = Result<Option<Transaction>, ErrorObjectOwned>> + Send
1077    {
1078        let self_clone = self.clone();
1079        async move {
1080            let resp = self_clone
1081                .spawn_blocking_io(move |this| {
1082                    this.transaction_by_hash(hash).map_err(|err| err.into())
1083                })
1084                .await;
1085            resp
1086        }
1087    }
1088}
1089
1090impl BlockProvider for &EthApi {
1091    fn get_block_epoch_number(&self, hash: &H256) -> Option<u64> {
1092        self.consensus_graph().get_block_epoch_number(hash)
1093    }
1094
1095    fn get_block_hashes_by_epoch(
1096        &self, epoch_number: EpochNumber,
1097    ) -> Result<Vec<H256>, String> {
1098        self.consensus_graph()
1099            .get_block_hashes_by_epoch(epoch_number)
1100            .map_err(|e| e.to_string())
1101    }
1102}
1103
1104#[async_trait]
1105impl EthApiServer for EthApi {
1106    /// Returns the protocol version encoded as a string.
1107    async fn protocol_version(&self) -> RpcResult<U64> { Ok(U64::from(65)) }
1108
1109    /// Returns an object with data about the sync status or false.
1110    fn syncing(&self) -> RpcResult<SyncStatus> { Ok(self.sync_status()) }
1111
1112    /// Returns the client coinbase address.
1113    async fn author(&self) -> RpcResult<Address> { Ok(H160::zero()) }
1114
1115    /// Returns a list of addresses owned by client.
1116    fn accounts(&self) -> RpcResult<Vec<Address>> { Ok(vec![]) }
1117
1118    /// Returns the number of most recent block.
1119    fn block_number(&self) -> RpcResult<U256> {
1120        self.latest_block_number().map_err(|err| err.into())
1121    }
1122
1123    /// Returns the chain ID of the current network.
1124    async fn chain_id(&self) -> RpcResult<Option<U64>> {
1125        Ok(Some(self.chain_id().into()))
1126    }
1127
1128    /// Returns information about a block by hash.
1129    async fn block_by_hash(
1130        &self, hash: H256, full: bool,
1131    ) -> RpcResult<Option<Block>> {
1132        self.block_by_hash(hash, full).map_err(|err| err.into())
1133    }
1134
1135    /// Returns information about a block by number.
1136    async fn block_by_number(
1137        &self, number: BlockNumberOrTag, full: bool,
1138    ) -> RpcResult<Option<Block>> {
1139        self.block_by_number(number, full).map_err(|err| err.into())
1140    }
1141
1142    /// Returns the number of transactions in a block from a block matching the
1143    /// given block hash.
1144    async fn block_transaction_count_by_hash(
1145        &self, hash: H256,
1146    ) -> RpcResult<Option<U256>> {
1147        self.block_transaction_count_by_hash(hash)
1148            .map_err(|err| err.into())
1149    }
1150
1151    /// Returns the number of transactions in a block matching the given block
1152    /// number.
1153    async fn block_transaction_count_by_number(
1154        &self, number: BlockNumberOrTag,
1155    ) -> RpcResult<Option<U256>> {
1156        self.block_transaction_count_by_number(number)
1157            .map_err(|err| err.into())
1158    }
1159
1160    /// Returns the number of uncles in a block from a block matching the given
1161    /// block hash.
1162    async fn block_uncles_count_by_hash(
1163        &self, hash: H256,
1164    ) -> RpcResult<Option<U256>> {
1165        self.block_uncles_count_by_hash(hash)
1166            .map_err(|err| err.into())
1167    }
1168
1169    /// Returns the number of uncles in a block with given block number.
1170    async fn block_uncles_count_by_number(
1171        &self, number: BlockNumberOrTag,
1172    ) -> RpcResult<Option<U256>> {
1173        self.block_uncles_count_by_number(number)
1174            .map_err(|err| err.into())
1175    }
1176
1177    /// Returns all transaction receipts for a given block.
1178    async fn block_receipts(
1179        &self, block_id: BlockId,
1180    ) -> RpcResult<Option<Vec<Receipt>>> {
1181        self.get_block_receipts(block_id)
1182            .map(|val| Some(val))
1183            .map_err(|e| e.into())
1184    }
1185
1186    /// Returns an uncle block of the given block and index.
1187    async fn uncle_by_block_hash_and_index(
1188        &self, hash: H256, index: Index,
1189    ) -> RpcResult<Option<Block>> {
1190        let _ = (hash, index);
1191        Ok(None)
1192    }
1193
1194    /// Returns an uncle block of the given block and index.
1195    async fn uncle_by_block_number_and_index(
1196        &self, number: BlockNumberOrTag, index: Index,
1197    ) -> RpcResult<Option<Block>> {
1198        let _ = (number, index);
1199        Ok(None)
1200    }
1201
1202    /// Returns the EIP-2718 encoded transaction if it exists.
1203    ///
1204    /// If this is a EIP-4844 transaction that is in the pool it will include
1205    /// the sidecar.
1206    async fn raw_transaction_by_hash(
1207        &self, hash: H256,
1208    ) -> RpcResult<Option<Bytes>> {
1209        let _ = hash;
1210        Err(jsonrpsee_internal_error("Not implemented"))
1211    }
1212
1213    /// Returns the information about a transaction requested by transaction
1214    /// hash.
1215    async fn transaction_by_hash(
1216        &self, hash: H256,
1217    ) -> RpcResult<Option<Transaction>> {
1218        self.async_transaction_by_hash(hash).await
1219    }
1220
1221    /// Returns information about a raw transaction by block hash and
1222    /// transaction index position.
1223    async fn raw_transaction_by_block_hash_and_index(
1224        &self, hash: H256, index: Index,
1225    ) -> RpcResult<Option<Bytes>> {
1226        let _ = (hash, index);
1227        Err(jsonrpsee_internal_error("Not implemented"))
1228    }
1229
1230    /// Returns information about a transaction by block hash and transaction
1231    /// index position.
1232    async fn transaction_by_block_hash_and_index(
1233        &self, hash: H256, index: Index,
1234    ) -> RpcResult<Option<Transaction>> {
1235        let phantom_block = self.phantom_block_by_hash(hash)?;
1236
1237        Ok(EthApi::block_tx_by_index(phantom_block, index.value()))
1238    }
1239
1240    /// Returns information about a raw transaction by block number and
1241    /// transaction index position.
1242    async fn raw_transaction_by_block_number_and_index(
1243        &self, number: BlockNumberOrTag, index: Index,
1244    ) -> RpcResult<Option<Bytes>> {
1245        let _ = (number, index);
1246        Err(jsonrpsee_internal_error("Not implemented"))
1247    }
1248
1249    /// Returns information about a transaction by block number and transaction
1250    /// index position.
1251    async fn transaction_by_block_number_and_index(
1252        &self, number: BlockNumberOrTag, index: Index,
1253    ) -> RpcResult<Option<Transaction>> {
1254        let phantom_block = self.phantom_block_by_number(number)?;
1255
1256        Ok(EthApi::block_tx_by_index(phantom_block, index.value()))
1257    }
1258
1259    /// Returns information about a transaction by sender and nonce.
1260    async fn transaction_by_sender_and_nonce(
1261        &self, address: Address, nonce: U64,
1262    ) -> RpcResult<Option<Transaction>> {
1263        let _ = (address, nonce);
1264        Err(jsonrpsee_internal_error("Not implemented"))
1265    }
1266
1267    /// Returns the receipt of a transaction by transaction hash.
1268    async fn transaction_receipt(
1269        &self, hash: H256,
1270    ) -> RpcResult<Option<Receipt>> {
1271        self.transaction_receipt(hash).map_err(|err| err.into())
1272    }
1273
1274    /// Returns the balance of the account of given address.
1275    async fn balance(
1276        &self, address: Address, block_number: Option<BlockId>,
1277    ) -> RpcResult<U256> {
1278        self.user_balance(address, block_number)
1279            .map_err(|err| err.into())
1280    }
1281
1282    /// Returns the value from a storage position at a given address
1283    async fn storage_at(
1284        &self, address: Address, index: JsonStorageKey,
1285        block_number: Option<BlockId>,
1286    ) -> RpcResult<H256> {
1287        self.storage_at(address, index, block_number)
1288            .map_err(|err| err.into())
1289    }
1290
1291    /// Returns the number of transactions sent from an address at given block
1292    /// number.
1293    async fn transaction_count(
1294        &self, address: Address, block_number: Option<BlockId>,
1295    ) -> RpcResult<U256> {
1296        self.next_nonce(address, block_number)
1297            .map_err(|err| err.into())
1298    }
1299
1300    /// Returns code at a given address at given block number.
1301    async fn get_code(
1302        &self, address: Address, block_number: Option<BlockId>,
1303    ) -> RpcResult<Bytes> {
1304        self.code_at(address, block_number)
1305            .map_err(|err| err.into())
1306    }
1307
1308    /// Returns the block's header at given number.
1309    async fn header_by_number(
1310        &self, hash: BlockNumberOrTag,
1311    ) -> RpcResult<Option<Header>> {
1312        let _ = hash;
1313        Err(jsonrpsee_internal_error("Not implemented"))
1314    }
1315
1316    /// Returns the block's header at given hash.
1317    async fn header_by_hash(&self, hash: H256) -> RpcResult<Option<Header>> {
1318        let _ = hash;
1319        Err(jsonrpsee_internal_error("Not implemented"))
1320    }
1321
1322    /// `eth_simulateV1` executes an arbitrary number of transactions on top of
1323    /// the requested state. The transactions are packed into individual
1324    /// blocks. Overrides can be provided.
1325    async fn simulate_v1(
1326        &self, opts: SimulatePayload, block_number: Option<BlockId>,
1327    ) -> RpcResult<Vec<SimulatedBlock>> {
1328        let _ = block_number;
1329        let _ = opts;
1330        Err(jsonrpsee_internal_error("Not implemented"))
1331    }
1332
1333    /// Executes a new message call immediately without creating a transaction
1334    /// on the block chain.
1335    async fn call(
1336        &self, request: TransactionRequest, block_number: Option<BlockId>,
1337        state_overrides: Option<RpcStateOverride>,
1338        block_overrides: Option<Box<BlockOverrides>>,
1339    ) -> RpcResult<Bytes> {
1340        let (execution, _estimation) = self.exec_transaction(
1341            request,
1342            block_number,
1343            state_overrides,
1344            block_overrides,
1345        )?;
1346
1347        Ok(execution.output.into())
1348    }
1349
1350    /// Simulate arbitrary number of transactions at an arbitrary blockchain
1351    /// index, with the optionality of state overrides
1352    async fn call_many(
1353        &self, bundle: Bundle, state_context: Option<StateContext>,
1354        state_override: Option<RpcStateOverride>,
1355    ) -> RpcResult<Vec<EthCallResponse>> {
1356        let _ = bundle;
1357        let _ = state_context;
1358        let _ = state_override;
1359        Err(jsonrpsee_internal_error("Not implemented"))
1360    }
1361
1362    /// Generates an access list for a transaction.
1363    ///
1364    /// This method creates an [EIP2930](https://eips.ethereum.org/EIPS/eip-2930) type accessList based on a given Transaction.
1365    ///
1366    /// An access list contains all storage slots and addresses touched by the
1367    /// transaction, except for the sender account and the chain's
1368    /// precompiles.
1369    ///
1370    /// It returns list of addresses and storage keys used by the transaction,
1371    /// plus the gas consumed when the access list is added. That is, it
1372    /// gives you the list of addresses and storage keys that will be used
1373    /// by that transaction, plus the gas consumed if the access
1374    /// list is included. Like eth_estimateGas, this is an estimation; the list
1375    /// could change when the transaction is actually mined. Adding an
1376    /// accessList to your transaction does not necessary result in lower
1377    /// gas usage compared to a transaction without an access list.
1378    async fn create_access_list(
1379        &self, request: TransactionRequest, block_number: Option<BlockId>,
1380    ) -> RpcResult<AccessListResult> {
1381        let _ = block_number;
1382        let _ = request;
1383        Err(jsonrpsee_internal_error("Not implemented"))
1384    }
1385
1386    /// Generates and returns an estimate of how much gas is necessary to allow
1387    /// the transaction to complete.
1388    async fn estimate_gas(
1389        &self, request: TransactionRequest, block_number: Option<BlockId>,
1390        state_overrides: Option<RpcStateOverride>,
1391    ) -> RpcResult<U256> {
1392        let (_, estimated_gas) = self.exec_transaction(
1393            request,
1394            block_number,
1395            state_overrides,
1396            None,
1397        )?;
1398
1399        Ok(estimated_gas)
1400    }
1401
1402    /// Returns the current price per gas in wei.
1403    async fn gas_price(&self) -> RpcResult<U256> { Ok(self.gas_price()) }
1404
1405    /// Returns the account details by specifying an address and a block
1406    /// number/tag
1407    // async fn get_account(
1408    //     &self,
1409    //     address: Address,
1410    //     block: BlockId,
1411    // ) -> RpcResult<Option<reth_rpc_types::Account>>;
1412
1413    /// Introduced in EIP-1559, returns suggestion for the priority for dynamic
1414    /// fee transactions.
1415    async fn max_priority_fee_per_gas(&self) -> RpcResult<U256> {
1416        self.max_priority_fee_per_gas().map_err(|err| err.into())
1417    }
1418
1419    /// Introduced in EIP-4844, returns the current blob base fee in wei.
1420    // async fn blob_base_fee(&self) -> RpcResult<U256>;
1421
1422    /// Returns the Transaction fee history
1423    ///
1424    /// Introduced in EIP-1559 for getting information on the appropriate
1425    /// priority fee to use.
1426    ///
1427    /// Returns transaction base fee per gas and effective priority fee per gas
1428    /// for the requested/supported block range. The returned Fee history
1429    /// for the returned block range can be a subsection of the requested
1430    /// range if not all blocks are available.
1431    async fn fee_history(
1432        &self, block_count: U64, newest_block: BlockNumberOrTag,
1433        reward_percentiles: Option<Vec<f64>>,
1434    ) -> RpcResult<FeeHistory> {
1435        self.fee_history(
1436            block_count.as_u64().into(),
1437            newest_block,
1438            reward_percentiles,
1439        )
1440        .map_err(|err| err.into())
1441    }
1442
1443    /// Returns whether the client is actively mining new blocks.
1444    async fn is_mining(&self) -> RpcResult<bool> { Ok(false) }
1445
1446    /// Returns the number of hashes per second that the node is mining with.
1447    async fn hashrate(&self) -> RpcResult<U256> { Ok(U256::zero()) }
1448
1449    /// Returns the hash of the current block, the seedHash, and the boundary
1450    /// condition to be met (“target”)
1451    // async fn get_work(&self) -> RpcResult<Work>;
1452
1453    /// Used for submitting mining hashrate.
1454    ///
1455    /// Can be used for remote miners to submit their hash rate.
1456    /// It accepts the miner hash rate and an identifier which must be unique
1457    /// between nodes. Returns `true` if the block was successfully
1458    /// submitted, `false` otherwise.
1459    async fn submit_hashrate(
1460        &self, hashrate: U256, id: H256,
1461    ) -> RpcResult<bool> {
1462        let _ = (hashrate, id);
1463        Ok(false)
1464    }
1465
1466    /// Used for submitting a proof-of-work solution.
1467    async fn submit_work(
1468        &self, nonce: H64, pow_hash: H256, mix_digest: H256,
1469    ) -> RpcResult<bool> {
1470        let _ = (nonce, pow_hash, mix_digest);
1471        Ok(false)
1472    }
1473
1474    /// Sends transaction; will block waiting for signer to return the
1475    /// transaction hash.
1476    async fn send_transaction(
1477        &self, request: TransactionRequest,
1478    ) -> RpcResult<H256> {
1479        let _ = request;
1480        Err(jsonrpsee_internal_error("Not implemented"))
1481    }
1482
1483    /// Sends signed transaction, returning its hash.
1484    async fn send_raw_transaction(&self, bytes: Bytes) -> RpcResult<H256> {
1485        let tx = if let Ok(tx) =
1486            TransactionWithSignature::from_raw(&bytes.into_vec())
1487        {
1488            tx
1489        } else {
1490            bail!(EthApiError::FailedToDecodeSignedTransaction)
1491        };
1492
1493        if tx.space() != Space::Ethereum {
1494            bail!(EthApiError::Other(
1495                "Incorrect transaction space".to_string()
1496            ));
1497        }
1498
1499        if tx.recover_public().is_err() {
1500            bail!(EthApiError::InvalidTransactionSignature);
1501        }
1502
1503        let r = self.send_transaction_with_signature(tx)?;
1504        Ok(r)
1505    }
1506
1507    async fn submit_transaction(&self, raw: Bytes) -> RpcResult<H256> {
1508        self.send_raw_transaction(raw).await
1509    }
1510
1511    /// Returns an Ethereum specific signature with:
1512    /// sign(keccak256("\x19Ethereum Signed Message:\n"
1513    /// + len(message) + message))).
1514    async fn sign(&self, address: Address, message: Bytes) -> RpcResult<Bytes> {
1515        let _ = (address, message);
1516        Err(jsonrpsee_internal_error("Not implemented"))
1517    }
1518
1519    /// Signs a transaction that can be submitted to the network at a later time
1520    /// using with `sendRawTransaction.`
1521    async fn sign_transaction(
1522        &self, transaction: TransactionRequest,
1523    ) -> RpcResult<Bytes> {
1524        let _ = transaction;
1525        Err(jsonrpsee_internal_error("Not implemented"))
1526    }
1527
1528    async fn logs(&self, filter: Filter) -> RpcResult<Vec<Log>> {
1529        self.logs(filter).map_err(|err| err.into())
1530    }
1531
1532    async fn account_pending_transactions(
1533        &self, address: Address, maybe_start_nonce: Option<U256>,
1534        maybe_limit: Option<U64>,
1535    ) -> RpcResult<AccountPendingTransactions> {
1536        self.account_pending_transactions(
1537            address,
1538            maybe_start_nonce,
1539            maybe_limit,
1540        )
1541        .map_err(|err| err.into())
1542    }
1543}