cfx_rpc_cfx_impl/
cfx_handler.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use std::{sync::Arc, thread, time::Duration};
6
7use async_trait::async_trait;
8use bigdecimal::BigDecimal;
9use blockgen::BlockGeneratorTestApi;
10use cfx_addr::Network;
11use cfx_execute_helper::estimation::{
12    decode_error, EstimateExt, EstimateRequest,
13};
14use cfx_executor::{
15    executive::{ExecutionError, ExecutionOutcome, TxDropError},
16    internal_contract::storage_point_prop,
17    state::State,
18};
19use cfx_parameters::{
20    consensus_internal::REWARD_EPOCH_COUNT,
21    genesis::{
22        genesis_contract_address_four_year, genesis_contract_address_two_year,
23    },
24    rpc::GAS_PRICE_DEFAULT_VALUE,
25    staking::{BLOCKS_PER_YEAR, DRIPS_PER_STORAGE_COLLATERAL_UNIT},
26};
27use cfx_rpc_cfx_api::{CfxDebugRpcServer, CfxRpcServer};
28use cfx_rpc_cfx_types::{
29    address::{check_rpc_address_network, check_two_rpc_address_network_match},
30    pos::PoSEpochReward,
31    receipt::Receipt as RpcReceipt,
32    transaction::PackedOrExecuted,
33    Account as RpcAccount, AccountPendingInfo, AccountPendingTransactions,
34    Block as RpcBlock, BlockHashOrEpochNumber, Bytes, CfxFeeHistory,
35    CfxRpcLogFilter, CheckBalanceAgainstTransactionResponse, EpochNumber,
36    EstimateGasAndCollateralResponse, Log as RpcLog, PoSEconomics,
37    RewardInfo as RpcRewardInfo, RpcAddress, RpcImplConfiguration, SponsorInfo,
38    Status as RpcStatus, StorageCollateralInfo, TokenSupplyInfo,
39    Transaction as RpcTransaction, TransactionRequest, VoteParamsInfo,
40};
41use cfx_rpc_eth_types::FeeHistory;
42use cfx_rpc_primitives::U64 as HexU64;
43use cfx_rpc_utils::error::jsonrpsee_error_helpers::{
44    call_execution_error, internal_error, internal_error_with_data,
45    invalid_params, invalid_params_check, invalid_params_detail,
46    invalid_params_msg, invalid_params_rpc_err, pivot_assumption_failed,
47    request_rejected_in_catch_up_mode,
48};
49use cfx_statedb::{
50    global_params::{
51        AccumulateInterestRate, BaseFeeProp, DistributablePoSInterest,
52        InterestRate, LastDistributeBlock, PowBaseReward, TotalBurnt1559,
53        TotalPosStaking,
54    },
55    StateDbExt,
56};
57use cfx_storage::state::StateDbGetOriginalMethods;
58use cfx_types::{
59    Address, AddressSpaceUtil, BigEndianHash, Space, H160, H256, H520, U128,
60    U256, U64,
61};
62use cfx_util_macros::bail;
63use cfx_vm_types::Error as VmError;
64use cfxcore::{
65    block_data_manager::BlockDataManager,
66    consensus::{
67        pos_handler::PosVerifier, MaybeExecutedTxExtraInfo, TransactionInfo,
68    },
69    consensus_parameters::DEFERRED_STATE_EPOCH_COUNT,
70    errors::{
71        account_result_to_rpc_result, Error as CoreError, Result as CoreResult,
72    },
73    ConsensusGraph, SharedConsensusGraph, SharedSynchronizationService,
74    SharedTransactionPool,
75};
76use cfxcore_accounts::AccountProvider;
77use cfxkey::Password;
78use diem_crypto::hash::HashValue;
79use jsonrpsee::{core::RpcResult, types::ErrorObjectOwned};
80use log::{debug, info, trace, warn};
81use num_bigint::{BigInt, ToBigInt};
82use primitives::{
83    filter::LogFilter, Account, Block, BlockHeader, BlockReceipts, DepositInfo,
84    EpochNumber as PrimitiveEpochNumber, StorageKey, StorageRoot, StorageValue,
85    TransactionIndex, TransactionStatus, TransactionWithSignature,
86    VoteStakeInfo,
87};
88use rustc_hex::ToHex;
89use storage_interface::DBReaderForPoW;
90
91use crate::{
92    eth_data_hash, helpers::build_block,
93    pos_handler::convert_to_pos_epoch_reward,
94};
95
96fn into_rpc_err<E>(e: E) -> ErrorObjectOwned
97where CoreError: From<E> {
98    ErrorObjectOwned::from(CoreError::from(e))
99}
100
101/// Helper struct to track block execution info for receipt construction
102#[derive(Debug)]
103struct BlockExecInfo {
104    block_receipts: Arc<BlockReceipts>,
105    block: Arc<Block>,
106    epoch_number: u64,
107    maybe_state_root: Option<H256>,
108    pivot_header: Arc<BlockHeader>,
109}
110
111pub struct CfxHandler {
112    pub config: RpcImplConfiguration,
113    pub consensus: SharedConsensusGraph,
114    pub sync: SharedSynchronizationService,
115    pub tx_pool: SharedTransactionPool,
116    pub accounts: Arc<AccountProvider>,
117    pub data_man: Arc<BlockDataManager>,
118    pub network_type: Network,
119    pub pos_handler: Arc<PosVerifier>,
120    block_gen: BlockGeneratorTestApi,
121}
122
123impl CfxHandler {
124    pub fn new(
125        config: RpcImplConfiguration, consensus: SharedConsensusGraph,
126        sync: SharedSynchronizationService, tx_pool: SharedTransactionPool,
127        accounts: Arc<AccountProvider>, pos_handler: Arc<PosVerifier>,
128        block_gen: BlockGeneratorTestApi,
129    ) -> Self {
130        let data_man = consensus.data_manager().clone();
131        let network_type = *sync.network.get_network_type();
132        CfxHandler {
133            config,
134            consensus,
135            sync,
136            tx_pool,
137            accounts,
138            data_man,
139            network_type,
140            pos_handler,
141            block_gen,
142        }
143    }
144
145    fn consensus_graph(&self) -> &ConsensusGraph { &self.consensus }
146
147    fn check_address_network(&self, network: Network) -> RpcResult<()> {
148        invalid_params_check(
149            "address",
150            check_rpc_address_network(Some(network), &self.network_type),
151        )
152    }
153
154    fn get_epoch_number_with_pivot_check(
155        &self, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
156    ) -> CoreResult<EpochNumber> {
157        match block_hash_or_epoch_number {
158            Some(BlockHashOrEpochNumber::BlockHashWithOption {
159                hash,
160                require_pivot,
161            }) => {
162                let epoch_number = self
163                    .consensus_graph()
164                    .get_block_epoch_number_with_pivot_check(
165                        &hash,
166                        require_pivot.unwrap_or(true),
167                    )?;
168                Ok(EpochNumber::Num(U64::from(epoch_number)))
169            }
170            Some(BlockHashOrEpochNumber::EpochNumber(epoch_number)) => {
171                Ok(epoch_number)
172            }
173            None => Ok(EpochNumber::LatestState),
174        }
175    }
176
177    fn get_block_execution_info(
178        &self, block_hash: &H256,
179    ) -> CoreResult<Option<BlockExecInfo>> {
180        let consensus_graph = self.consensus_graph();
181        let (pivot_hash, block_receipts, maybe_state_root) =
182            match consensus_graph.get_block_execution_info(block_hash) {
183                None => return Ok(None),
184                Some((exec_res, maybe_state_root)) => {
185                    (exec_res.0, exec_res.1.block_receipts, maybe_state_root)
186                }
187            };
188
189        let epoch_number = self
190            .consensus
191            .data_manager()
192            .block_header_by_hash(&pivot_hash)
193            .ok_or("Inconsistent state")?
194            .height();
195
196        if epoch_number > consensus_graph.best_executed_state_epoch_number() {
197            return Ok(None);
198        }
199
200        let block = self
201            .consensus
202            .data_manager()
203            .block_by_hash(&block_hash, false)
204            .ok_or("Inconsistent state")?;
205
206        if block_receipts.receipts.len() != block.transactions.len() {
207            bail!("Inconsistent state");
208        }
209
210        let pivot_header = match self
211            .consensus
212            .data_manager()
213            .block_header_by_hash(&pivot_hash)
214        {
215            Some(x) => x,
216            None => {
217                warn!("Cannot find pivot header when get block execution info: pivot hash {:?}", pivot_hash);
218                return Ok(None);
219            }
220        };
221
222        Ok(Some(BlockExecInfo {
223            block_receipts,
224            block,
225            epoch_number,
226            maybe_state_root,
227            pivot_header,
228        }))
229    }
230
231    fn construct_rpc_receipt(
232        &self, tx_index: TransactionIndex, exec_info: &BlockExecInfo,
233        include_eth_receipt: bool, include_accumulated_gas_used: bool,
234    ) -> CoreResult<Option<RpcReceipt>> {
235        let id = tx_index.real_index;
236
237        if id >= exec_info.block.transactions.len()
238            || id >= exec_info.block_receipts.receipts.len()
239            || id >= exec_info.block_receipts.tx_execution_error_messages.len()
240        {
241            bail!("Inconsistent state");
242        }
243
244        let tx = &exec_info.block.transactions[id];
245
246        if !include_eth_receipt
247            && (tx.space() == Space::Ethereum || tx_index.is_phantom)
248        {
249            return Ok(None);
250        }
251
252        let prior_gas_used = match id {
253            0 => U256::zero(),
254            id => {
255                exec_info.block_receipts.receipts[id - 1].accumulated_gas_used
256            }
257        };
258
259        let tx_exec_error_msg =
260            match &exec_info.block_receipts.tx_execution_error_messages[id] {
261                msg if msg.is_empty() => None,
262                msg => Some(msg.clone()),
263            };
264
265        let receipt = RpcReceipt::new(
266            (**tx).clone(),
267            exec_info.block_receipts.receipts[id].clone(),
268            tx_index,
269            prior_gas_used,
270            Some(exec_info.epoch_number),
271            exec_info.pivot_header.base_price(),
272            exec_info.maybe_state_root.clone(),
273            tx_exec_error_msg,
274            self.network_type,
275            include_eth_receipt,
276            include_accumulated_gas_used,
277        )?;
278
279        Ok(Some(receipt))
280    }
281
282    fn prepare_receipt(&self, tx_hash: H256) -> CoreResult<Option<RpcReceipt>> {
283        let tx_index = match self
284            .consensus
285            .data_manager()
286            .transaction_index_by_hash(&tx_hash, false)
287        {
288            None => return Ok(None),
289            Some(tx_index) => tx_index,
290        };
291
292        if tx_index.is_phantom {
293            return Ok(None);
294        }
295
296        let exec_info =
297            match self.get_block_execution_info(&tx_index.block_hash)? {
298                None => return Ok(None),
299                Some(res) => res,
300            };
301
302        let receipt =
303            self.construct_rpc_receipt(tx_index, &exec_info, false, true)?;
304        if let Some(r) = &receipt {
305            if r.outcome_status
306                == TransactionStatus::Skipped.in_space(Space::Native).into()
307            {
308                return Ok(None);
309            }
310        }
311        Ok(receipt)
312    }
313
314    fn prepare_block_receipts(
315        &self, block_hash: H256, pivot_assumption: H256,
316        include_eth_receipt: bool,
317    ) -> CoreResult<Option<Vec<RpcReceipt>>> {
318        let exec_info = match self.get_block_execution_info(&block_hash)? {
319            None => return Ok(None),
320            Some(res) => res,
321        };
322
323        if pivot_assumption != exec_info.pivot_header.hash() {
324            bail!(pivot_assumption_failed(
325                pivot_assumption,
326                exec_info.pivot_header.hash()
327            ));
328        }
329
330        let mut rpc_receipts = vec![];
331
332        let iter = exec_info
333            .block
334            .transactions
335            .iter()
336            .enumerate()
337            .filter(|(_, tx)| {
338                if include_eth_receipt {
339                    true
340                } else {
341                    tx.space() == Space::Native
342                }
343            })
344            .enumerate();
345
346        for (new_index, (original_index, _)) in iter {
347            if let Some(receipt) = self.construct_rpc_receipt(
348                TransactionIndex {
349                    block_hash,
350                    real_index: original_index,
351                    is_phantom: false,
352                    rpc_index: Some(new_index),
353                },
354                &exec_info,
355                include_eth_receipt,
356                true,
357            )? {
358                rpc_receipts.push(receipt);
359            }
360        }
361
362        Ok(Some(rpc_receipts))
363    }
364
365    fn exec_transaction(
366        &self, request: TransactionRequest, epoch: Option<EpochNumber>,
367    ) -> CoreResult<(ExecutionOutcome, EstimateExt)> {
368        let rpc_request_network = invalid_params_check(
369            "request",
370            check_two_rpc_address_network_match(
371                request.from.as_ref(),
372                request.to.as_ref(),
373            ),
374        )?;
375
376        invalid_params_check(
377            "request",
378            check_rpc_address_network(rpc_request_network, &self.network_type),
379        )?;
380
381        let consensus_graph = self.consensus_graph();
382        let epoch = epoch.unwrap_or(EpochNumber::LatestState);
383
384        let estimate_request = EstimateRequest {
385            has_sender: request.from.is_some(),
386            has_gas_limit: request.gas.is_some(),
387            has_gas_price: request.has_gas_price(),
388            has_nonce: request.nonce.is_some(),
389            has_storage_limit: request.storage_limit.is_some(),
390            collect_access_list: false,
391        };
392
393        let epoch_height = consensus_graph
394            .get_height_from_epoch_number(epoch.clone().into())?;
395        let chain_id = consensus_graph.best_chain_id();
396        let signed_tx = request.sign_call(
397            epoch_height,
398            chain_id.in_native_space(),
399            self.config.max_estimation_gas_limit,
400        )?;
401        trace!("call tx {:?}", signed_tx);
402
403        consensus_graph.call_virtual(
404            &signed_tx,
405            epoch.into(),
406            estimate_request,
407            Default::default(),
408        )
409    }
410
411    fn send_transaction_with_signature(
412        &self, tx: TransactionWithSignature,
413    ) -> CoreResult<H256> {
414        if self.sync.catch_up_mode() {
415            warn!("Ignore send_transaction request {}. Cannot send transaction when the node is still in catch-up mode.", tx.hash());
416            bail!(request_rejected_in_catch_up_mode(None));
417        }
418        let (signed_trans, failed_trans) =
419            self.tx_pool.insert_new_transactions(vec![tx]);
420
421        match (signed_trans.len(), failed_trans.len()) {
422            (0, 0) => {
423                debug!("insert_new_transactions ignores inserted transactions");
424                bail!(invalid_params_detail("tx", "tx already exist"))
425            }
426            (0, 1) => {
427                let tx_err = failed_trans.values().next().unwrap();
428                bail!(invalid_params_detail("tx", tx_err.to_string()))
429            }
430            (1, 0) => {
431                let tx_hash = signed_trans[0].hash();
432                self.sync.append_received_transactions(signed_trans);
433                Ok(tx_hash)
434            }
435            _ => {
436                bail!(internal_error_with_data(format!(
437                    "unexpected insert result, {} returned items",
438                    signed_trans.len() + failed_trans.len()
439                )))
440            }
441        }
442    }
443
444    fn prepare_transaction(
445        &self, mut tx: TransactionRequest, password: Option<String>,
446    ) -> CoreResult<TransactionWithSignature> {
447        let consensus_graph = self.consensus_graph();
448        tx.check_rpc_address_network("tx", &self.network_type)?;
449
450        if tx.nonce.is_none() {
451            let nonce = consensus_graph.next_nonce(
452                Address::from(tx.from.clone().ok_or("from should have")?)
453                    .with_native_space(),
454                BlockHashOrEpochNumber::EpochNumber(EpochNumber::LatestState)
455                    .into(),
456                "internal EpochNumber::LatestState",
457            )?;
458            tx.nonce.replace(nonce.into());
459            debug!("after loading nonce in latest state, tx = {:?}", tx);
460        }
461
462        let epoch_height = consensus_graph.best_epoch_number();
463        let chain_id = consensus_graph.best_chain_id();
464
465        if tx.gas.is_none() || tx.storage_limit.is_none() {
466            let estimate =
467                self.estimate_gas_and_collateral_impl(tx.clone(), None)?;
468
469            if tx.gas.is_none() {
470                tx.gas.replace(estimate.gas_used);
471            }
472
473            if tx.storage_limit.is_none() {
474                tx.storage_limit.replace(estimate.storage_collateralized);
475            }
476        }
477
478        if tx.transaction_type.is_none() && tx.gas_price.is_none() {
479            let gas_price = consensus_graph.gas_price(Space::Native);
480            if gas_price.is_some() {
481                tx.gas_price.replace(gas_price.unwrap());
482            }
483        }
484
485        tx.sign_with(
486            epoch_height,
487            chain_id.in_native_space(),
488            password,
489            self.accounts.clone(),
490        )
491        .map_err(Into::into)
492    }
493
494    fn estimate_gas_and_collateral_impl(
495        &self, request: TransactionRequest, epoch: Option<EpochNumber>,
496    ) -> CoreResult<EstimateGasAndCollateralResponse> {
497        let (execution_outcome, estimation) =
498            self.exec_transaction(request, epoch)?;
499        match execution_outcome {
500            ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
501                expected,
502                got,
503            )) => bail!(call_execution_error(
504                "Can not estimate: transaction can not be executed".into(),
505                format! {"nonce is too old expected {:?} got {:?}", expected, got}
506            )),
507            ExecutionOutcome::NotExecutedDrop(
508                TxDropError::InvalidRecipientAddress(recipient),
509            ) => bail!(call_execution_error(
510                "Can not estimate: transaction can not be executed".into(),
511                format! {"invalid recipient address {:?}", recipient}
512            )),
513            ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
514                address,
515            )) => bail!(call_execution_error(
516                "Can not estimate: transaction sender has code".into(),
517                format! {"transaction sender has code {:?}", address}
518            )),
519            ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
520                bail!(call_execution_error(
521                    "Can not estimate: transaction can not be executed".into(),
522                    format! {"{:?}", e}
523                ))
524            }
525            ExecutionOutcome::NotExecutedDrop(
526                TxDropError::NotEnoughGasLimit { expected, got },
527            ) => bail!(call_execution_error(
528                "Can not estimate: transaction can not be executed".into(),
529                format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
530            )),
531            ExecutionOutcome::ExecutionErrorBumpNonce(
532                ExecutionError::VmError(VmError::Reverted),
533                executed,
534            ) => {
535                let (revert_error, innermost_error, errors) =
536                    decode_error(&executed, |addr| {
537                        RpcAddress::try_from_h160(
538                            addr.clone(),
539                            self.network_type,
540                        )
541                        .unwrap()
542                        .base32_address
543                    });
544                bail!(call_execution_error(
545                    format!("Estimation isn't accurate: transaction is reverted{}{}",
546                        revert_error, innermost_error),
547                    errors.join("\n"),
548                ))
549            }
550            ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
551                bail!(call_execution_error(
552                    format! {"Can not estimate: transaction execution failed, \
553                    all gas will be charged (execution error: {:?})", e}
554                    .into(),
555                    format! {"{:?}", e}
556                ))
557            }
558            ExecutionOutcome::Finished(_) => {}
559        };
560        let storage_collateralized =
561            U64::from(estimation.estimated_storage_limit);
562        let estimated_gas_used = estimation.estimated_gas_limit;
563        Ok(EstimateGasAndCollateralResponse {
564            gas_limit: estimated_gas_used,
565            gas_used: estimated_gas_used,
566            storage_collateralized,
567        })
568    }
569
570    fn check_response_size<T: serde::Serialize>(
571        &self, response: &T,
572    ) -> CoreResult<()> {
573        let max_size = self.config.max_payload_bytes.saturating_sub(50);
574        let payload_size = serde_json::to_vec(&response)
575            .map_err(|_| "Unexpected serialization error")?
576            .len();
577
578        if payload_size > max_size {
579            bail!(invalid_params(
580                "epoch",
581                Some(format!(
582                    "Oversized payload: size = {}, max = {}",
583                    payload_size, max_size
584                ))
585            ));
586        }
587        Ok(())
588    }
589
590    fn generate_one_block(
591        &self, num_txs: usize, block_size_limit: usize,
592    ) -> CoreResult<H256> {
593        info!("RPC Request: generate_one_block()");
594        Ok(self
595            .block_gen
596            .generate_block(num_txs, block_size_limit, vec![]))
597    }
598}
599
600#[async_trait]
601impl CfxRpcServer for CfxHandler {
602    async fn gas_price(&self) -> RpcResult<U256> {
603        let consensus_graph = self.consensus_graph();
604        info!("RPC Request: cfx_gasPrice()");
605        let consensus_gas_price = consensus_graph
606            .gas_price(Space::Native)
607            .unwrap_or(GAS_PRICE_DEFAULT_VALUE.into())
608            .into();
609        Ok(std::cmp::max(
610            consensus_gas_price,
611            self.tx_pool.config.min_native_tx_price.into(),
612        ))
613    }
614
615    async fn max_priority_fee_per_gas(&self) -> RpcResult<U256> {
616        info!("RPC Request: max_priority_fee_per_gas");
617        let fee_history = self
618            .fee_history(
619                HexU64::from(300),
620                EpochNumber::LatestState,
621                Some(vec![50f64]),
622            )
623            .await?;
624        let total_reward: U256 = fee_history
625            .reward()
626            .iter()
627            .map(|x| x.first().unwrap())
628            .fold(U256::zero(), |x, y| x + *y);
629        Ok(total_reward / 300)
630    }
631
632    async fn epoch_number(
633        &self, epoch_num: Option<EpochNumber>,
634    ) -> RpcResult<U256> {
635        let consensus_graph = self.consensus_graph();
636        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestMined);
637        info!("RPC Request: cfx_epochNumber({:?})", epoch_num);
638        consensus_graph
639            .get_height_from_epoch_number(epoch_num.into())
640            .map(|h| h.into())
641            .map_err(|e| invalid_params_rpc_err(e, None::<()>))
642    }
643
644    async fn balance(
645        &self, addr: RpcAddress,
646        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
647    ) -> RpcResult<U256> {
648        self.check_address_network(addr.network)?;
649        let epoch_num = self
650            .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
651            .into();
652        info!(
653            "RPC Request: cfx_getBalance address={:?} epoch_num={:?}",
654            addr, epoch_num
655        );
656        let state_db = self
657            .consensus
658            .get_state_db_by_epoch_number(epoch_num, "num")?;
659        let acc = state_db
660            .get_account(&addr.hex_address.with_native_space())
661            .map_err(into_rpc_err)?;
662        Ok(acc.map_or(U256::zero(), |acc| acc.balance).into())
663    }
664
665    async fn admin(
666        &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
667    ) -> RpcResult<Option<RpcAddress>> {
668        self.check_address_network(addr.network)?;
669        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
670        let network = addr.network;
671        info!(
672            "RPC Request: cfx_getAdmin address={:?} epoch_num={:?}",
673            addr, epoch_num
674        );
675        let state_db = self
676            .consensus
677            .get_state_db_by_epoch_number(epoch_num, "num")?;
678        match state_db
679            .get_account(&addr.hex_address.with_native_space())
680            .map_err(into_rpc_err)?
681        {
682            None => Ok(None),
683            Some(acc) => Ok(Some(
684                RpcAddress::try_from_h160(acc.admin, network)
685                    .map_err(into_rpc_err)?,
686            )),
687        }
688    }
689
690    async fn sponsor_info(
691        &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
692    ) -> RpcResult<SponsorInfo> {
693        self.check_address_network(addr.network)?;
694        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
695        let network = addr.network;
696        info!(
697            "RPC Request: cfx_getSponsorInfo address={:?} epoch_num={:?}",
698            addr, epoch_num
699        );
700        let state_db = self
701            .consensus
702            .get_state_db_by_epoch_number(epoch_num, "num")?;
703        match state_db
704            .get_account(&addr.hex_address.with_native_space())
705            .map_err(into_rpc_err)?
706        {
707            None => SponsorInfo::default(network).map_err(into_rpc_err),
708            Some(acc) => SponsorInfo::try_from(acc.sponsor_info, network)
709                .map_err(into_rpc_err),
710        }
711    }
712
713    async fn staking_balance(
714        &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
715    ) -> RpcResult<U256> {
716        self.check_address_network(addr.network)?;
717        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
718        info!(
719            "RPC Request: cfx_getStakingBalance address={:?} epoch_num={:?}",
720            addr, epoch_num
721        );
722        let state_db = self
723            .consensus
724            .get_state_db_by_epoch_number(epoch_num, "num")?;
725        let acc = state_db
726            .get_account(&addr.hex_address.with_native_space())
727            .map_err(into_rpc_err)?;
728        Ok(acc.map_or(U256::zero(), |acc| acc.staking_balance).into())
729    }
730
731    async fn deposit_list(
732        &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
733    ) -> RpcResult<Vec<DepositInfo>> {
734        self.check_address_network(addr.network)?;
735        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
736        info!(
737            "RPC Request: cfx_getDepositList address={:?} epoch_num={:?}",
738            addr, epoch_num
739        );
740        let state_db = self
741            .consensus
742            .get_state_db_by_epoch_number(epoch_num, "num")?;
743        match state_db
744            .get_deposit_list(&addr.hex_address.with_native_space())
745            .map_err(into_rpc_err)?
746        {
747            None => Ok(vec![]),
748            Some(deposit_list) => Ok(deposit_list.0),
749        }
750    }
751
752    async fn vote_list(
753        &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
754    ) -> RpcResult<Vec<VoteStakeInfo>> {
755        self.check_address_network(addr.network)?;
756        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
757        info!(
758            "RPC Request: cfx_getVoteList address={:?} epoch_num={:?}",
759            addr, epoch_num
760        );
761        let state_db = self
762            .consensus
763            .get_state_db_by_epoch_number(epoch_num, "num")?;
764        match state_db
765            .get_vote_list(&addr.hex_address.with_native_space())
766            .map_err(into_rpc_err)?
767        {
768            None => Ok(vec![]),
769            Some(vote_list) => Ok(vote_list.0),
770        }
771    }
772
773    async fn collateral_for_storage(
774        &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
775    ) -> RpcResult<U256> {
776        self.check_address_network(addr.network)?;
777        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
778        info!(
779            "RPC Request: cfx_getCollateralForStorage address={:?} epoch_num={:?}",
780            addr, epoch_num
781        );
782        let state_db = self
783            .consensus
784            .get_state_db_by_epoch_number(epoch_num, "num")?;
785        let acc = state_db
786            .get_account(&addr.hex_address.with_native_space())
787            .map_err(into_rpc_err)?;
788        Ok(acc
789            .map_or(U256::zero(), |acc| acc.collateral_for_storage)
790            .into())
791    }
792
793    async fn code(
794        &self, addr: RpcAddress,
795        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
796    ) -> RpcResult<Bytes> {
797        self.check_address_network(addr.network)?;
798        let epoch_num = self
799            .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)
800            .map_err(into_rpc_err)?
801            .into();
802        info!(
803            "RPC Request: cfx_getCode address={:?} epoch_num={:?}",
804            addr, epoch_num
805        );
806        let state_db = self
807            .consensus
808            .get_state_db_by_epoch_number(epoch_num, "num")?;
809        let address = addr.hex_address.with_native_space();
810        let code = match state_db.get_account(&address).map_err(into_rpc_err)? {
811            Some(acc) => match state_db
812                .get_code(&address, &acc.code_hash)
813                .map_err(into_rpc_err)?
814            {
815                Some(code) => (*code.code).clone(),
816                _ => vec![],
817            },
818            None => vec![],
819        };
820        Ok(Bytes::new(code))
821    }
822
823    async fn storage_at(
824        &self, addr: RpcAddress, pos: U256,
825        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
826    ) -> RpcResult<Option<H256>> {
827        self.check_address_network(addr.network)?;
828        let epoch_num = self
829            .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)
830            .map_err(into_rpc_err)?
831            .into();
832        info!(
833            "RPC Request: cfx_getStorageAt address={:?}, position={:?}, epoch_num={:?})",
834            addr, pos, epoch_num
835        );
836        let state_db = self
837            .consensus
838            .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
839        let position: H256 = H256::from_uint(&pos);
840        let key =
841            StorageKey::new_storage_key(&addr.hex_address, position.as_ref())
842                .with_native_space();
843        Ok(
844            match state_db.get::<StorageValue>(key).map_err(into_rpc_err)? {
845                Some(entry) => {
846                    let h: H256 = H256::from_uint(&entry.value);
847                    Some(h.into())
848                }
849                None => None,
850            },
851        )
852    }
853
854    async fn storage_root(
855        &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
856    ) -> RpcResult<Option<StorageRoot>> {
857        self.check_address_network(address.network)?;
858        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
859        info!(
860            "RPC Request: cfx_getStorageRoot address={:?} epoch={:?}",
861            address, epoch_num
862        );
863        let root = self
864            .consensus
865            .get_storage_state_by_epoch_number(epoch_num, "epoch_num")?
866            .get_original_storage_root(&address.hex_address.with_native_space())
867            .map_err(into_rpc_err)?;
868        Ok(Some(root))
869    }
870
871    async fn block_by_hash(
872        &self, block_hash: H256, include_txs: bool,
873    ) -> RpcResult<Option<RpcBlock>> {
874        let consensus_graph = self.consensus_graph();
875        info!(
876            "RPC Request: cfx_getBlockByHash hash={:?} include_txs={:?}",
877            block_hash, include_txs
878        );
879        let inner = &*consensus_graph.inner.read();
880        let maybe_block = self.data_man.block_by_hash(&block_hash, false);
881        match maybe_block {
882            None => Ok(None),
883            Some(b) => Ok(Some(
884                build_block(
885                    &*b,
886                    self.network_type,
887                    consensus_graph,
888                    inner,
889                    &self.data_man,
890                    include_txs,
891                    Some(Space::Native),
892                )
893                .map_err(into_rpc_err)?,
894            )),
895        }
896    }
897
898    async fn block_by_hash_with_pivot_assumption(
899        &self, block_hash: H256, pivot_hash: H256, epoch_number: U64,
900    ) -> RpcResult<RpcBlock> {
901        let consensus_graph = self.consensus_graph();
902        let inner = &*consensus_graph.inner.read();
903        let epoch_number = epoch_number.as_usize() as u64;
904        info!(
905            "RPC Request: cfx_getBlockByHashWithPivotAssumption block_hash={:?} pivot_hash={:?} epoch_number={:?}",
906            block_hash, pivot_hash, epoch_number
907        );
908
909        let genesis = self.consensus.data_manager().true_genesis.hash();
910
911        if block_hash == genesis && (pivot_hash != genesis || epoch_number != 0)
912        {
913            return Err(invalid_params_msg("pivot chain assumption failed"));
914        }
915
916        if block_hash != genesis
917            && (consensus_graph.get_block_epoch_number(&block_hash)
918                != epoch_number.into())
919        {
920            return Err(invalid_params_msg("pivot chain assumption failed"));
921        }
922
923        inner
924            .check_block_pivot_assumption(&pivot_hash, epoch_number)
925            .map_err(|e| invalid_params_msg(&e.to_string()))?;
926
927        let block = self
928            .data_man
929            .block_by_hash(&block_hash, false)
930            .ok_or(invalid_params_msg("Block not found"))?;
931
932        debug!("Build RpcBlock {}", block.hash());
933        build_block(
934            &*block,
935            self.network_type,
936            consensus_graph,
937            inner,
938            &self.data_man,
939            true,
940            Some(Space::Native),
941        )
942        .map_err(into_rpc_err)
943    }
944
945    async fn block_by_epoch_number(
946        &self, epoch_number: EpochNumber, include_txs: bool,
947    ) -> RpcResult<Option<RpcBlock>> {
948        info!("RPC Request: cfx_getBlockByEpochNumber epoch_number={:?} include_txs={:?}", epoch_number, include_txs);
949        let consensus_graph = self.consensus_graph();
950        let inner = &*consensus_graph.inner.read();
951
952        let epoch_height = consensus_graph
953            .get_height_from_epoch_number(epoch_number.into())
954            .map_err(|e| invalid_params_msg(&e.to_string()))?;
955
956        let pivot_hash = inner
957            .get_pivot_hash_from_epoch_number(epoch_height)
958            .map_err(|e| invalid_params_msg(&e.to_string()))?;
959
960        let maybe_block = self.data_man.block_by_hash(&pivot_hash, false);
961        match maybe_block {
962            None => Ok(None),
963            Some(b) => Ok(Some(
964                build_block(
965                    &*b,
966                    self.network_type,
967                    consensus_graph,
968                    inner,
969                    &self.data_man,
970                    include_txs,
971                    Some(Space::Native),
972                )
973                .map_err(into_rpc_err)?,
974            )),
975        }
976    }
977
978    async fn block_by_block_number(
979        &self, block_number: U64, include_txs: bool,
980    ) -> RpcResult<Option<RpcBlock>> {
981        let block_number = block_number.as_u64();
982        let consensus_graph = self.consensus_graph();
983        info!(
984            "RPC Request: cfx_getBlockByBlockNumber block_number={:?} include_txs={:?}",
985            block_number, include_txs
986        );
987        let inner = &*consensus_graph.inner.read();
988        let block_hash =
989            match self.data_man.hash_by_block_number(block_number, true) {
990                None => return Ok(None),
991                Some(h) => h,
992            };
993        let maybe_block = self.data_man.block_by_hash(&block_hash, false);
994        match maybe_block {
995            None => Ok(None),
996            Some(b) => Ok(Some(
997                build_block(
998                    &*b,
999                    self.network_type,
1000                    consensus_graph,
1001                    inner,
1002                    &self.data_man,
1003                    include_txs,
1004                    Some(Space::Native),
1005                )
1006                .map_err(into_rpc_err)?,
1007            )),
1008        }
1009    }
1010
1011    async fn best_block_hash(&self) -> RpcResult<H256> {
1012        info!("RPC Request: cfx_getBestBlockHash()");
1013        Ok(self.consensus.best_block_hash().into())
1014    }
1015
1016    async fn next_nonce(
1017        &self, addr: RpcAddress, num: Option<BlockHashOrEpochNumber>,
1018    ) -> RpcResult<U256> {
1019        self.check_address_network(addr.network)?;
1020        let consensus_graph = self.consensus_graph();
1021        let num = num.unwrap_or(BlockHashOrEpochNumber::EpochNumber(
1022            EpochNumber::LatestState,
1023        ));
1024        info!(
1025            "RPC Request: cfx_getNextNonce address={:?} epoch_num={:?}",
1026            addr, num
1027        );
1028        consensus_graph
1029            .next_nonce(addr.hex_address.with_native_space(), num.into(), "num")
1030            .map_err(into_rpc_err)
1031    }
1032
1033    async fn send_raw_transaction(&self, raw_tx: Bytes) -> RpcResult<H256> {
1034        info!(
1035            "RPC Request: cfx_sendRawTransaction len={:?}",
1036            raw_tx.0.len()
1037        );
1038        debug!("RawTransaction bytes={:?}", raw_tx);
1039
1040        let tx: TransactionWithSignature = invalid_params_check(
1041            "raw",
1042            TransactionWithSignature::from_raw(&raw_tx.into_vec()),
1043        )?;
1044
1045        if tx.recover_public().is_err() {
1046            return Err(invalid_params_detail(
1047                "tx",
1048                "Can not recover pubkey for Ethereum like tx",
1049            ));
1050        }
1051
1052        let r = self
1053            .send_transaction_with_signature(tx)
1054            .map_err(into_rpc_err);
1055
1056        if r.is_ok() && self.config.dev_pack_tx_immediately {
1057            // Try to pack and execute this new tx.
1058            for _ in 0..DEFERRED_STATE_EPOCH_COUNT {
1059                let generated = self.generate_one_block(
1060                    1, /* num_txs */
1061                    self.sync
1062                        .get_synchronization_graph()
1063                        .verification_config
1064                        .max_block_size_in_bytes,
1065                )?;
1066                loop {
1067                    // Wait for the new block to be fully processed, so all
1068                    // generated blocks form a chain for
1069                    // `tx` to be executed.
1070                    if self.consensus.best_block_hash() == generated {
1071                        break;
1072                    } else {
1073                        thread::sleep(Duration::from_millis(10));
1074                    }
1075                }
1076            }
1077        }
1078
1079        r
1080    }
1081
1082    async fn call(
1083        &self, tx: TransactionRequest,
1084        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
1085    ) -> RpcResult<Bytes> {
1086        let epoch = Some(
1087            self.get_epoch_number_with_pivot_check(block_hash_or_epoch_number)
1088                .map_err(into_rpc_err)?,
1089        );
1090        let (execution_outcome, _estimation) =
1091            self.exec_transaction(tx, epoch).map_err(into_rpc_err)?;
1092        match execution_outcome {
1093            ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1094                expected,
1095                got,
1096            )) => Err(call_execution_error(
1097                "Transaction can not be executed".into(),
1098                format! {"nonce is too old expected {:?} got {:?}", expected, got},
1099            )),
1100            ExecutionOutcome::NotExecutedDrop(
1101                TxDropError::InvalidRecipientAddress(recipient),
1102            ) => Err(call_execution_error(
1103                "Transaction can not be executed".into(),
1104                format! {"invalid recipient address {:?}", recipient},
1105            )),
1106            ExecutionOutcome::NotExecutedDrop(
1107                TxDropError::NotEnoughGasLimit { expected, got },
1108            ) => Err(call_execution_error(
1109                "Transaction can not be executed".into(),
1110                format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got},
1111            )),
1112            ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1113                address,
1114            )) => Err(call_execution_error(
1115                "Transaction can not be executed".into(),
1116                format! {"tx sender has contract code: {:?}", address},
1117            )),
1118            ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1119                Err(call_execution_error(
1120                    "Transaction can not be executed".into(),
1121                    format! {"{:?}", e},
1122                ))
1123            }
1124            ExecutionOutcome::ExecutionErrorBumpNonce(
1125                ExecutionError::VmError(VmError::Reverted),
1126                executed,
1127            ) => Err(call_execution_error(
1128                "Transaction reverted".into(),
1129                format!("0x{}", executed.output.to_hex::<String>()),
1130            )),
1131            ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1132                Err(call_execution_error(
1133                    "Transaction execution failed".into(),
1134                    format! {"{:?}", e},
1135                ))
1136            }
1137            ExecutionOutcome::Finished(executed) => Ok(executed.output.into()),
1138        }
1139    }
1140
1141    async fn get_logs(
1142        &self, filter: CfxRpcLogFilter,
1143    ) -> RpcResult<Vec<RpcLog>> {
1144        if let Some(addresses) = &filter.address {
1145            for address in addresses.iter() {
1146                invalid_params_check(
1147                    "filter.address",
1148                    check_rpc_address_network(
1149                        Some(address.network),
1150                        &self.network_type,
1151                    ),
1152                )?;
1153            }
1154        }
1155
1156        let consensus_graph = self.consensus_graph();
1157        info!("RPC Request: cfx_getLogs({:?})", filter);
1158
1159        let filter: LogFilter = filter.into_primitive()?;
1160
1161        let logs = consensus_graph
1162            .logs(filter)
1163            .map_err(into_rpc_err)?
1164            .iter()
1165            .cloned()
1166            .map(|l| RpcLog::try_from_localized(l, self.network_type))
1167            .collect::<Result<Vec<_>, _>>()
1168            .map_err(into_rpc_err)?;
1169
1170        if let Some(max_limit) = self.config.get_logs_filter_max_limit {
1171            if logs.len() > max_limit {
1172                return Err(invalid_params_rpc_err(
1173                    "filter",
1174                    Some(format!(
1175                        "This query results in too many logs, max limitation is {}, please filter results by a smaller epoch/block range",
1176                        max_limit
1177                    )),
1178                ));
1179            }
1180        }
1181
1182        Ok(logs)
1183    }
1184
1185    async fn transaction_by_hash(
1186        &self, tx_hash: H256,
1187    ) -> RpcResult<Option<RpcTransaction>> {
1188        info!("RPC Request: cfx_getTransactionByHash({:?})", tx_hash);
1189
1190        if let Some((
1191            tx,
1192            TransactionInfo {
1193                tx_index,
1194                maybe_executed_extra_info,
1195            },
1196        )) = self.consensus.get_signed_tx_and_tx_info(&tx_hash)
1197        {
1198            if tx.space() == Space::Ethereum || tx_index.is_phantom {
1199                return Ok(None);
1200            }
1201
1202            let packed_or_executed = match maybe_executed_extra_info {
1203                None => PackedOrExecuted::Packed(tx_index),
1204                Some(MaybeExecutedTxExtraInfo {
1205                    receipt,
1206                    block_number: _,
1207                    prior_gas_used,
1208                    tx_exec_error_msg,
1209                }) => {
1210                    let epoch_number = self
1211                        .consensus
1212                        .get_block_epoch_number(&tx_index.block_hash);
1213
1214                    let maybe_state_root = self
1215                        .consensus
1216                        .data_manager()
1217                        .get_executed_state_root(&tx_index.block_hash);
1218
1219                    let maybe_base_price = self
1220                        .consensus
1221                        .data_manager()
1222                        .block_header_by_hash(&tx_index.block_hash)
1223                        .and_then(|x| x.base_price());
1224
1225                    PackedOrExecuted::Executed(
1226                        RpcReceipt::new(
1227                            tx.clone(),
1228                            receipt,
1229                            tx_index,
1230                            prior_gas_used,
1231                            epoch_number,
1232                            maybe_base_price,
1233                            maybe_state_root,
1234                            tx_exec_error_msg,
1235                            self.network_type,
1236                            false,
1237                            false,
1238                        )
1239                        .map_err(into_rpc_err)?,
1240                    )
1241                }
1242            };
1243
1244            let rpc_tx = RpcTransaction::from_signed(
1245                &tx,
1246                Some(packed_or_executed),
1247                self.network_type,
1248            )
1249            .map_err(into_rpc_err)?;
1250
1251            return Ok(Some(rpc_tx));
1252        }
1253
1254        if let Some(tx) = self.tx_pool.get_transaction(&tx_hash) {
1255            if tx.space() == Space::Ethereum {
1256                return Ok(None);
1257            }
1258            let rpc_tx =
1259                RpcTransaction::from_signed(&tx, None, self.network_type)
1260                    .map_err(into_rpc_err)?;
1261            return Ok(Some(rpc_tx));
1262        }
1263
1264        Ok(None)
1265    }
1266
1267    async fn estimate_gas_and_collateral(
1268        &self, request: TransactionRequest, epoch_number: Option<EpochNumber>,
1269    ) -> RpcResult<EstimateGasAndCollateralResponse> {
1270        info!(
1271            "RPC Request: cfx_estimateGasAndCollateral request={:?}, epoch={:?}",
1272            request, epoch_number
1273        );
1274        self.estimate_gas_and_collateral_impl(request, epoch_number)
1275            .map_err(into_rpc_err)
1276    }
1277
1278    async fn fee_history(
1279        &self, block_count: HexU64, newest_block: EpochNumber,
1280        reward_percentiles: Option<Vec<f64>>,
1281    ) -> RpcResult<CfxFeeHistory> {
1282        use crate::helpers::MAX_FEE_HISTORY_CACHE_BLOCK_COUNT;
1283
1284        if newest_block == EpochNumber::LatestMined {
1285            return Err(invalid_params_rpc_err(
1286                "newestBlock cannot be 'LatestMined'",
1287                None::<bool>,
1288            ));
1289        }
1290
1291        info!(
1292            "RPC Request: cfx_feeHistory: block_count={}, newest_block={:?}, reward_percentiles={:?}",
1293            block_count, newest_block, reward_percentiles
1294        );
1295
1296        let mut block_count = block_count;
1297
1298        if block_count.as_u64() == 0 {
1299            return Ok(FeeHistory::new().into());
1300        }
1301
1302        if block_count.as_u64() > MAX_FEE_HISTORY_CACHE_BLOCK_COUNT {
1303            block_count = HexU64::from(MAX_FEE_HISTORY_CACHE_BLOCK_COUNT);
1304        }
1305
1306        let inner = self.consensus_graph().inner.read();
1307
1308        let fetch_block = |height| {
1309            let pivot_hash = inner
1310                .get_pivot_hash_from_epoch_number(height)
1311                .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?;
1312            let maybe_block = self.data_man.block_by_hash(&pivot_hash, false);
1313            if let Some(block) = maybe_block {
1314                Ok(block)
1315            } else {
1316                Err(internal_error())
1317            }
1318        };
1319
1320        let start_height: u64 = self
1321            .consensus_graph()
1322            .get_height_from_epoch_number(newest_block.into())
1323            .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?;
1324
1325        let reward_percentiles = reward_percentiles.unwrap_or_default();
1326        let mut current_height = start_height;
1327
1328        let mut fee_history = FeeHistory::new();
1329        while current_height
1330            >= start_height.saturating_sub(block_count.as_u64() - 1)
1331        {
1332            let block = fetch_block(current_height)?;
1333            let transactions = block
1334                .transactions
1335                .iter()
1336                .filter(|tx| tx.space() == Space::Native)
1337                .map(|x| &**x);
1338            fee_history
1339                .push_front_block(
1340                    Space::Native,
1341                    &reward_percentiles,
1342                    &block.block_header,
1343                    transactions,
1344                )
1345                .map_err(|_| internal_error())?;
1346
1347            if current_height == 0 {
1348                break;
1349            } else {
1350                current_height -= 1;
1351            }
1352        }
1353
1354        let block = fetch_block(start_height + 1)?;
1355        let oldest_block = if current_height == 0 {
1356            0
1357        } else {
1358            current_height + 1
1359        };
1360        fee_history.finish(
1361            oldest_block,
1362            block.block_header.base_price().as_ref(),
1363            Space::Native,
1364        );
1365
1366        Ok(fee_history.into())
1367    }
1368
1369    async fn check_balance_against_transaction(
1370        &self, account_addr: RpcAddress, contract_addr: RpcAddress,
1371        gas_limit: U256, gas_price: U256, storage_limit: U256,
1372        epoch: Option<EpochNumber>,
1373    ) -> RpcResult<CheckBalanceAgainstTransactionResponse> {
1374        self.check_address_network(account_addr.network)?;
1375        self.check_address_network(contract_addr.network)?;
1376
1377        let epoch: PrimitiveEpochNumber =
1378            epoch.unwrap_or(EpochNumber::LatestState).into();
1379
1380        info!(
1381            "RPC Request: cfx_checkBalanceAgainstTransaction account_addr={:?} contract_addr={:?} gas_limit={:?} gas_price={:?} storage_limit={:?} epoch={:?}",
1382            account_addr, contract_addr, gas_limit, gas_price, storage_limit, epoch
1383        );
1384
1385        let account_addr_spaced = account_addr.hex_address.with_native_space();
1386        let contract_addr_spaced =
1387            contract_addr.hex_address.with_native_space();
1388
1389        if storage_limit > U256::from(std::u64::MAX) {
1390            return Err(invalid_params_rpc_err(
1391                format!(
1392                    "storage_limit has to be within the range of u64 but {} supplied!",
1393                    storage_limit
1394                ),
1395                None::<bool>,
1396            ));
1397        }
1398
1399        let state_db = self
1400            .consensus
1401            .get_state_db_by_epoch_number(epoch, "epoch")
1402            .map_err(into_rpc_err)?;
1403
1404        let user_account = state_db
1405            .get_account(&account_addr_spaced)
1406            .map_err(into_rpc_err)?;
1407        let contract_account = state_db
1408            .get_account(&contract_addr_spaced)
1409            .map_err(into_rpc_err)?;
1410        let state = State::new(state_db).map_err(into_rpc_err)?;
1411        let is_sponsored = state
1412            .check_contract_whitelist(
1413                &contract_addr_spaced.address,
1414                &account_addr_spaced.address,
1415            )
1416            .map_err(into_rpc_err)?;
1417
1418        Ok(check_balance_against_transaction(
1419            user_account,
1420            contract_account,
1421            is_sponsored,
1422            gas_limit,
1423            gas_price,
1424            storage_limit,
1425        ))
1426    }
1427
1428    async fn blocks_by_epoch(
1429        &self, epoch_number: EpochNumber,
1430    ) -> RpcResult<Vec<H256>> {
1431        info!(
1432            "RPC Request: cfx_getBlocksByEpoch epoch_number={:?}",
1433            epoch_number
1434        );
1435        self.consensus
1436            .get_block_hashes_by_epoch(epoch_number.into())
1437            .map_err(|e| invalid_params_rpc_err(e, None::<bool>))
1438            .and_then(|vec| Ok(vec.into_iter().map(|x| x.into()).collect()))
1439    }
1440
1441    async fn skipped_blocks_by_epoch(
1442        &self, epoch_number: EpochNumber,
1443    ) -> RpcResult<Vec<H256>> {
1444        info!(
1445            "RPC Request: cfx_getSkippedBlocksByEpoch epoch_number={:?}",
1446            epoch_number
1447        );
1448        self.consensus
1449            .get_skipped_block_hashes_by_epoch(epoch_number.into())
1450            .map_err(|e| invalid_params_rpc_err(e, None::<bool>))
1451            .and_then(|vec| Ok(vec.into_iter().map(|x| x.into()).collect()))
1452    }
1453
1454    async fn transaction_receipt(
1455        &self, tx_hash: H256,
1456    ) -> RpcResult<Option<RpcReceipt>> {
1457        info!("RPC Request: cfx_getTransactionReceipt({:?})", tx_hash);
1458        self.prepare_receipt(tx_hash).map_err(into_rpc_err)
1459    }
1460
1461    async fn account(
1462        &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
1463    ) -> RpcResult<RpcAccount> {
1464        self.check_address_network(address.network)?;
1465        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
1466        let network = address.network;
1467        info!(
1468            "RPC Request: cfx_getAccount address={:?} epoch_num={:?}",
1469            address, epoch_num
1470        );
1471        let addr = &address.hex_address;
1472        let state_db = self
1473            .consensus
1474            .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1475            .map_err(into_rpc_err)?;
1476        let account = match state_db
1477            .get_account(&addr.with_native_space())
1478            .map_err(into_rpc_err)?
1479        {
1480            Some(t) => t,
1481            None => account_result_to_rpc_result(
1482                "address",
1483                Ok(Account::new_empty_with_balance(
1484                    &addr.with_native_space(),
1485                    &U256::zero(),
1486                    &U256::zero(),
1487                )),
1488            )
1489            .map_err(into_rpc_err)?,
1490        };
1491        RpcAccount::try_from(account, network)
1492            .map_err(|e| invalid_params_rpc_err(e, None::<bool>))
1493    }
1494
1495    async fn interest_rate(
1496        &self, epoch_number: Option<EpochNumber>,
1497    ) -> RpcResult<U256> {
1498        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1499        let state_db = self
1500            .consensus
1501            .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1502            .map_err(into_rpc_err)?;
1503        Ok(state_db
1504            .get_global_param::<InterestRate>()
1505            .map_err(into_rpc_err)?
1506            .into())
1507    }
1508
1509    async fn accumulate_interest_rate(
1510        &self, epoch_number: Option<EpochNumber>,
1511    ) -> RpcResult<U256> {
1512        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1513        let state_db = self
1514            .consensus
1515            .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1516            .map_err(into_rpc_err)?;
1517        Ok(state_db
1518            .get_global_param::<AccumulateInterestRate>()
1519            .map_err(into_rpc_err)?
1520            .into())
1521    }
1522
1523    async fn pos_economics(
1524        &self, epoch_number: Option<EpochNumber>,
1525    ) -> RpcResult<PoSEconomics> {
1526        let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1527        let state_db = self
1528            .consensus
1529            .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1530            .map_err(into_rpc_err)?;
1531        Ok(PoSEconomics {
1532            total_pos_staking_tokens: state_db
1533                .get_global_param::<TotalPosStaking>()
1534                .map_err(into_rpc_err)?,
1535            distributable_pos_interest: state_db
1536                .get_global_param::<DistributablePoSInterest>()
1537                .map_err(into_rpc_err)?,
1538            last_distribute_block: U64::from(
1539                state_db
1540                    .get_global_param::<LastDistributeBlock>()
1541                    .map_err(into_rpc_err)?
1542                    .as_u64(),
1543            ),
1544        })
1545    }
1546
1547    async fn confirmation_risk_by_hash(
1548        &self, block_hash: H256,
1549    ) -> RpcResult<Option<U256>> {
1550        let consensus_graph = self.consensus_graph();
1551        let inner = &*consensus_graph.inner.read();
1552        let result = consensus_graph
1553            .confirmation_meter
1554            .confirmation_risk_by_hash(inner, block_hash.into());
1555        if result.is_none() {
1556            return Ok(None);
1557        }
1558        let risk: BigDecimal = result.unwrap().into();
1559        let scale = BigInt::parse_bytes(
1560            b"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
1561            16,
1562        )
1563        .expect("failed to unwrap U256::max into bigInt");
1564        let scaled_risk: BigInt = (risk * scale)
1565            .to_bigint()
1566            .expect("failed to convert scaled risk to bigInt");
1567        let (sign, big_endian_bytes) = scaled_risk.to_bytes_be();
1568        assert_ne!(sign, num_bigint::Sign::Minus);
1569        let rpc_result = U256::from(big_endian_bytes.as_slice());
1570        Ok(Some(rpc_result.into()))
1571    }
1572
1573    async fn get_status(&self) -> RpcResult<RpcStatus> {
1574        let consensus_graph = self.consensus_graph();
1575        let (best_info, block_number) = {
1576            let _inner = &*consensus_graph.inner.read();
1577            let best_info = self.consensus.best_info();
1578            let block_number = self
1579                .consensus
1580                .get_block_number(&best_info.best_block_hash)
1581                .map_err(into_rpc_err)?
1582                .ok_or_else(|| internal_error())?
1583                + 1;
1584            (best_info, block_number)
1585        };
1586
1587        let tx_count = self.tx_pool.total_unpacked();
1588
1589        let latest_checkpoint = consensus_graph
1590            .get_height_from_epoch_number(EpochNumber::LatestCheckpoint.into())
1591            .map_err(into_rpc_err)?
1592            .into();
1593
1594        let latest_confirmed = consensus_graph
1595            .get_height_from_epoch_number(EpochNumber::LatestConfirmed.into())
1596            .map_err(into_rpc_err)?
1597            .into();
1598
1599        let latest_state = consensus_graph
1600            .get_height_from_epoch_number(EpochNumber::LatestState.into())
1601            .map_err(into_rpc_err)?
1602            .into();
1603
1604        let latest_finalized = consensus_graph
1605            .get_height_from_epoch_number(EpochNumber::LatestFinalized.into())
1606            .map_err(into_rpc_err)?
1607            .into();
1608
1609        Ok(RpcStatus {
1610            best_hash: best_info.best_block_hash.into(),
1611            block_number: block_number.into(),
1612            chain_id: best_info.chain_id.in_native_space().into(),
1613            ethereum_space_chain_id: best_info
1614                .chain_id
1615                .in_space(Space::Ethereum)
1616                .into(),
1617            epoch_number: best_info.best_epoch_number.into(),
1618            latest_checkpoint,
1619            latest_confirmed,
1620            latest_finalized,
1621            latest_state,
1622            network_id: self.sync.network.network_id().into(),
1623            pending_tx_number: tx_count.into(),
1624        })
1625    }
1626
1627    async fn get_block_reward_info(
1628        &self, num: EpochNumber,
1629    ) -> RpcResult<Vec<RpcRewardInfo>> {
1630        info!("RPC Request: cfx_getBlockRewardInfo epoch_number={:?}", num);
1631        let epoch_height: U64 = self
1632            .consensus_graph()
1633            .get_height_from_epoch_number(num.clone().into_primitive())
1634            .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?
1635            .into();
1636        let (epoch_later_number, overflow) =
1637            epoch_height.overflowing_add(REWARD_EPOCH_COUNT.into());
1638        if overflow {
1639            return Err(invalid_params(
1640                "epoch",
1641                Some("Epoch number overflows!"),
1642            ));
1643        }
1644        let epoch_later = match self.consensus.get_hash_from_epoch_number(
1645            EpochNumber::Num(epoch_later_number).into_primitive(),
1646        ) {
1647            Ok(hash) => hash,
1648            Err(e) => {
1649                debug!(
1650                    "get_block_reward_info: get_hash_from_epoch_number returns error: {}",
1651                    e
1652                );
1653                return Err(invalid_params(
1654                    "epoch",
1655                    Some("Reward not calculated yet!"),
1656                ));
1657            }
1658        };
1659
1660        let blocks = self
1661            .consensus
1662            .get_block_hashes_by_epoch(num.into())
1663            .map_err(into_rpc_err)?;
1664
1665        let mut ret = Vec::new();
1666        for b in blocks {
1667            if let Some(reward_result) = self
1668                .consensus
1669                .data_manager()
1670                .block_reward_result_by_hash_with_epoch(
1671                    &b,
1672                    &epoch_later,
1673                    false,
1674                    true,
1675                )
1676            {
1677                if let Some(block_header) =
1678                    self.consensus.data_manager().block_header_by_hash(&b)
1679                {
1680                    let author = RpcAddress::try_from_h160(
1681                        *block_header.author(),
1682                        self.network_type,
1683                    )
1684                    .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?;
1685
1686                    ret.push(RpcRewardInfo {
1687                        block_hash: b.into(),
1688                        author,
1689                        total_reward: reward_result.total_reward.into(),
1690                        base_reward: reward_result.base_reward.into(),
1691                        tx_fee: reward_result.tx_fee.into(),
1692                    })
1693                }
1694            }
1695        }
1696        Ok(ret)
1697    }
1698
1699    async fn get_client_version(&self) -> RpcResult<String> {
1700        Ok(parity_version::conflux_client_version!())
1701    }
1702
1703    async fn get_supply_info(
1704        &self, epoch_number: Option<EpochNumber>,
1705    ) -> RpcResult<TokenSupplyInfo> {
1706        let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1707        let state = State::new(
1708            self.consensus
1709                .get_state_db_by_epoch_number(epoch, "epoch")
1710                .map_err(into_rpc_err)?,
1711        )
1712        .map_err(into_rpc_err)?;
1713        let total_issued = state.total_issued_tokens();
1714        let total_staking = state.total_staking_tokens();
1715        let total_collateral = state.total_storage_tokens();
1716        let two_year_unlock_address = genesis_contract_address_two_year();
1717        let four_year_unlock_address = genesis_contract_address_four_year();
1718        let two_year_locked = state
1719            .balance(&two_year_unlock_address)
1720            .unwrap_or(U256::zero());
1721        let four_year_locked = state
1722            .balance(&four_year_unlock_address)
1723            .unwrap_or(U256::zero());
1724        let total_circulating =
1725            total_issued - two_year_locked - four_year_locked;
1726        let total_espace_tokens = state.total_espace_tokens();
1727        Ok(TokenSupplyInfo {
1728            total_circulating,
1729            total_issued,
1730            total_staking,
1731            total_collateral,
1732            total_espace_tokens,
1733        })
1734    }
1735
1736    async fn get_collateral_info(
1737        &self, epoch_number: Option<EpochNumber>,
1738    ) -> RpcResult<StorageCollateralInfo> {
1739        let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1740        let state = State::new(
1741            self.consensus
1742                .get_state_db_by_epoch_number(epoch, "epoch")
1743                .map_err(into_rpc_err)?,
1744        )
1745        .map_err(into_rpc_err)?;
1746        let total_storage_tokens = state.total_storage_tokens();
1747        let converted_storage_points = state.converted_storage_points()
1748            / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1749        let used_storage_points =
1750            state.used_storage_points() / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1751        Ok(StorageCollateralInfo {
1752            total_storage_tokens,
1753            converted_storage_points,
1754            used_storage_points,
1755        })
1756    }
1757
1758    async fn get_fee_burnt(
1759        &self, epoch_number: Option<EpochNumber>,
1760    ) -> RpcResult<U256> {
1761        let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1762        let state_db = self
1763            .consensus
1764            .get_state_db_by_epoch_number(epoch, "epoch_num")
1765            .map_err(into_rpc_err)?;
1766        Ok(state_db
1767            .get_global_param::<TotalBurnt1559>()
1768            .map_err(into_rpc_err)?)
1769    }
1770
1771    async fn get_pos_reward_by_epoch(
1772        &self, epoch: EpochNumber,
1773    ) -> RpcResult<Option<PoSEpochReward>> {
1774        let maybe_block = {
1775            let consensus_graph = self.consensus_graph();
1776            let inner = &*consensus_graph.inner.read();
1777            let epoch_height = match consensus_graph
1778                .get_height_from_epoch_number(epoch.into())
1779                .ok()
1780            {
1781                None => return Ok(None),
1782                Some(v) => v,
1783            };
1784            let pivot_hash =
1785                match inner.get_pivot_hash_from_epoch_number(epoch_height).ok()
1786                {
1787                    None => return Ok(None),
1788                    Some(v) => v,
1789                };
1790            self.data_man.block_by_hash(&pivot_hash, false)
1791        };
1792
1793        if maybe_block.is_none() {
1794            return Ok(None);
1795        }
1796        let block = maybe_block.unwrap();
1797        if block.block_header.pos_reference().is_none() {
1798            return Ok(None);
1799        }
1800        match self
1801            .data_man
1802            .block_by_hash(block.block_header.parent_hash(), false)
1803        {
1804            None => Ok(None),
1805            Some(parent_block) => {
1806                if parent_block.block_header.pos_reference().is_none() {
1807                    return Ok(None);
1808                }
1809                let block_pos_ref = block.block_header.pos_reference().unwrap();
1810                let parent_pos_ref =
1811                    parent_block.block_header.pos_reference().unwrap();
1812
1813                if block_pos_ref == parent_pos_ref {
1814                    return Ok(None);
1815                }
1816
1817                let hash = HashValue::from_slice(parent_pos_ref.as_bytes())
1818                    .map_err(|_| internal_error())?;
1819                let pos_block = self
1820                    .pos_handler
1821                    .pos_ledger_db()
1822                    .get_committed_block_by_hash(&hash)
1823                    .map_err(|_| internal_error())?;
1824                let maybe_epoch_rewards =
1825                    self.data_man.pos_reward_by_pos_epoch(pos_block.epoch);
1826                if maybe_epoch_rewards.is_none() {
1827                    return Ok(None);
1828                }
1829                let epoch_rewards = maybe_epoch_rewards.unwrap();
1830                if epoch_rewards.execution_epoch_hash
1831                    != block.block_header.hash()
1832                {
1833                    return Ok(None);
1834                }
1835                let reward_info: PoSEpochReward = convert_to_pos_epoch_reward(
1836                    epoch_rewards,
1837                    self.network_type,
1838                )
1839                .map_err(|_| internal_error())?;
1840                Ok(Some(reward_info))
1841            }
1842        }
1843    }
1844
1845    async fn get_vote_params(
1846        &self, epoch_number: Option<EpochNumber>,
1847    ) -> RpcResult<VoteParamsInfo> {
1848        let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1849        let state_db = self
1850            .consensus
1851            .get_state_db_by_epoch_number(epoch, "epoch_num")
1852            .map_err(into_rpc_err)?;
1853        let interest_rate = state_db
1854            .get_global_param::<InterestRate>()
1855            .map_err(into_rpc_err)?
1856            / U256::from(BLOCKS_PER_YEAR);
1857        let pow_base_reward = state_db
1858            .get_global_param::<PowBaseReward>()
1859            .map_err(into_rpc_err)?;
1860        let storage_point_prop = state_db
1861            .get_system_storage(&storage_point_prop())
1862            .map_err(into_rpc_err)?;
1863        let base_fee_share_prop = state_db
1864            .get_global_param::<BaseFeeProp>()
1865            .map_err(into_rpc_err)?;
1866        Ok(VoteParamsInfo {
1867            pow_base_reward,
1868            interest_rate,
1869            storage_point_prop,
1870            base_fee_share_prop,
1871        })
1872    }
1873}
1874
1875/// Check balance against transaction helper
1876pub fn check_balance_against_transaction(
1877    user_account: Option<Account>, contract_account: Option<Account>,
1878    is_sponsored: bool, gas_limit: U256, gas_price: U256, storage_limit: U256,
1879) -> CheckBalanceAgainstTransactionResponse {
1880    let sponsor_for_gas = contract_account
1881        .as_ref()
1882        .map(|a| a.sponsor_info.sponsor_for_gas)
1883        .unwrap_or_default();
1884
1885    let gas_bound: cfx_types::U512 = contract_account
1886        .as_ref()
1887        .map(|a| a.sponsor_info.sponsor_gas_bound)
1888        .unwrap_or_default()
1889        .into();
1890
1891    let balance_for_gas: cfx_types::U512 = contract_account
1892        .as_ref()
1893        .map(|a| a.sponsor_info.sponsor_balance_for_gas)
1894        .unwrap_or_default()
1895        .into();
1896
1897    let sponsor_for_collateral = contract_account
1898        .as_ref()
1899        .map(|a| a.sponsor_info.sponsor_for_collateral)
1900        .unwrap_or_default();
1901
1902    let balance_for_collateral: cfx_types::U512 = contract_account
1903        .as_ref()
1904        .map(|a| {
1905            a.sponsor_info.sponsor_balance_for_collateral
1906                + a.sponsor_info.unused_storage_points()
1907        })
1908        .unwrap_or_default()
1909        .into();
1910
1911    let user_balance: cfx_types::U512 =
1912        user_account.map(|a| a.balance).unwrap_or_default().into();
1913
1914    let gas_cost_in_drip = gas_limit.full_mul(gas_price);
1915    let storage_cost_in_drip =
1916        storage_limit.full_mul(*DRIPS_PER_STORAGE_COLLATERAL_UNIT);
1917
1918    let will_pay_tx_fee = !is_sponsored
1919        || sponsor_for_gas.is_zero()
1920        || (gas_cost_in_drip > gas_bound)
1921        || (gas_cost_in_drip > balance_for_gas);
1922
1923    let will_pay_collateral = !is_sponsored
1924        || sponsor_for_collateral.is_zero()
1925        || (storage_cost_in_drip > balance_for_collateral);
1926
1927    let minimum_balance = match (will_pay_tx_fee, will_pay_collateral) {
1928        (false, false) => 0.into(),
1929        (true, false) => gas_cost_in_drip,
1930        (false, true) => storage_cost_in_drip,
1931        (true, true) => gas_cost_in_drip + storage_cost_in_drip,
1932    };
1933
1934    let is_balance_enough = user_balance >= minimum_balance;
1935
1936    CheckBalanceAgainstTransactionResponse {
1937        will_pay_tx_fee,
1938        will_pay_collateral,
1939        is_balance_enough,
1940    }
1941}
1942
1943#[async_trait]
1944impl CfxDebugRpcServer for CfxHandler {
1945    async fn send_transaction(
1946        &self, tx: TransactionRequest, password: Option<String>,
1947    ) -> RpcResult<H256> {
1948        info!("RPC Request: cfx_sendTransaction, tx = {:?}", tx);
1949        let signed = self
1950            .prepare_transaction(tx, password)
1951            .map_err(into_rpc_err)?;
1952        self.send_transaction_with_signature(signed)
1953            .map_err(into_rpc_err)
1954    }
1955
1956    async fn accounts(&self) -> RpcResult<Vec<RpcAddress>> {
1957        let accounts: Vec<Address> = self.accounts.accounts().map_err(|e| {
1958            into_rpc_err(format!(
1959                "Could not fetch accounts. With error {:?}",
1960                e
1961            ))
1962        })?;
1963        Ok(accounts
1964            .into_iter()
1965            .map(|addr| RpcAddress::try_from_h160(addr, self.network_type))
1966            .collect::<Result<_, _>>()
1967            .map_err(|e| into_rpc_err(e))?)
1968    }
1969
1970    async fn new_account(&self, password: String) -> RpcResult<RpcAddress> {
1971        let address =
1972            self.accounts.new_account(&password.into()).map_err(|e| {
1973                into_rpc_err(format!(
1974                    "Could not create account. With error {:?}",
1975                    e
1976                ))
1977            })?;
1978        RpcAddress::try_from_h160(address, self.network_type)
1979            .map_err(into_rpc_err)
1980    }
1981
1982    async fn unlock_account(
1983        &self, address: RpcAddress, password: String, duration: Option<U128>,
1984    ) -> RpcResult<bool> {
1985        self.check_address_network(address.network)?;
1986        let account: H160 = address.into();
1987        let store = self.accounts.clone();
1988
1989        let duration = match duration {
1990            None => None,
1991            Some(duration) => {
1992                let duration: U128 = duration.into();
1993                let v = duration.low_u64() as u32;
1994                if duration != v.into() {
1995                    return Err(invalid_params_msg("invalid duration number"));
1996                } else {
1997                    Some(v)
1998                }
1999            }
2000        };
2001
2002        let r = match duration {
2003            Some(0) => {
2004                store.unlock_account_permanently(account, password.into())
2005            }
2006            Some(d) => store.unlock_account_timed(
2007                account,
2008                password.into(),
2009                Duration::from_secs(d.into()),
2010            ),
2011            None => store.unlock_account_timed(
2012                account,
2013                password.into(),
2014                Duration::from_secs(300),
2015            ),
2016        };
2017        match r {
2018            Ok(_) => Ok(true),
2019            Err(err) => {
2020                warn!("Unable to unlock the account. With error {:?}", err);
2021                Err(internal_error())
2022            }
2023        }
2024    }
2025
2026    async fn lock_account(&self, address: RpcAddress) -> RpcResult<bool> {
2027        self.check_address_network(address.network)?;
2028        match self.accounts.lock_account(address.into()) {
2029            Ok(_) => Ok(true),
2030            Err(err) => {
2031                warn!("Unable to lock the account. With error {:?}", err);
2032                Err(internal_error())
2033            }
2034        }
2035    }
2036
2037    fn sign(
2038        &self, data: Bytes, address: RpcAddress, password: Option<String>,
2039    ) -> RpcResult<H520> {
2040        self.check_address_network(address.network)?;
2041        let message = eth_data_hash(data.0);
2042        let password = password.map(Password::from);
2043        let signature =
2044            match self.accounts.sign(address.into(), password, message) {
2045                Ok(signature) => signature,
2046                Err(err) => {
2047                    warn!("Unable to sign the message. With error {:?}", err);
2048                    return Err(internal_error());
2049                }
2050            };
2051        Ok(H520(signature.into()))
2052    }
2053
2054    fn sign_transaction(
2055        &self, tx: TransactionRequest, password: Option<String>,
2056    ) -> RpcResult<String> {
2057        let tx = self.prepare_transaction(tx, password).map_err(|e| {
2058            invalid_params(
2059                "tx",
2060                Some(format!("failed to sign transaction: {:?}", e)),
2061            )
2062        })?;
2063        let raw_tx = rlp::encode(&tx);
2064        Ok(format!("0x{}", raw_tx.to_hex::<String>()))
2065    }
2066
2067    async fn epoch_receipts(
2068        &self, epoch: BlockHashOrEpochNumber,
2069        include_eth_receipts: Option<bool>,
2070    ) -> RpcResult<Option<Vec<Vec<RpcReceipt>>>> {
2071        info!("RPC Request: cfx_getEpochReceipts({:?})", epoch);
2072
2073        let hashes = self
2074            .consensus
2075            .get_block_hashes_by_epoch_or_block_hash(epoch.into())
2076            .map_err(into_rpc_err)?;
2077
2078        let pivot_hash =
2079            *hashes.last().ok_or(into_rpc_err("Inconsistent state"))?;
2080        let mut epoch_receipts = vec![];
2081
2082        for h in hashes {
2083            epoch_receipts.push(
2084                match self
2085                    .prepare_block_receipts(
2086                        h,
2087                        pivot_hash,
2088                        include_eth_receipts.unwrap_or(false),
2089                    )
2090                    .map_err(into_rpc_err)?
2091                {
2092                    None => return Ok(None),
2093                    Some(rs) => rs,
2094                },
2095            );
2096        }
2097
2098        self.check_response_size(&epoch_receipts)
2099            .map_err(into_rpc_err)?;
2100
2101        Ok(Some(epoch_receipts))
2102    }
2103
2104    async fn account_pending_info(
2105        &self, address: RpcAddress,
2106    ) -> RpcResult<Option<AccountPendingInfo>> {
2107        info!("RPC Request: cfx_getAccountPendingInfo({:?})", address);
2108        self.check_address_network(address.network)?;
2109
2110        match self.tx_pool.get_account_pending_info(
2111            &Address::from(address).with_native_space(),
2112        ) {
2113            None => Ok(None),
2114            Some((
2115                local_nonce,
2116                pending_count,
2117                pending_nonce,
2118                next_pending_tx,
2119            )) => Ok(Some(AccountPendingInfo {
2120                local_nonce: local_nonce.into(),
2121                pending_count: pending_count.into(),
2122                pending_nonce: pending_nonce.into(),
2123                next_pending_tx: next_pending_tx.into(),
2124            })),
2125        }
2126    }
2127
2128    async fn account_pending_transactions(
2129        &self, address: RpcAddress, maybe_start_nonce: Option<U256>,
2130        maybe_limit: Option<U64>,
2131    ) -> RpcResult<AccountPendingTransactions> {
2132        info!(
2133            "RPC Request: cfx_getAccountPendingTransactions(addr={:?}, start_nonce={:?}, limit={:?})",
2134            address, maybe_start_nonce, maybe_limit
2135        );
2136        self.check_address_network(address.network)?;
2137
2138        let (pending_txs, tx_status, pending_count) = self
2139            .tx_pool
2140            .get_account_pending_transactions(
2141                &Address::from(address).with_native_space(),
2142                maybe_start_nonce,
2143                maybe_limit.map(|limit| limit.as_usize()),
2144                self.consensus.best_epoch_number(),
2145            )
2146            .map_err(into_rpc_err)?;
2147
2148        Ok(AccountPendingTransactions {
2149            pending_transactions: pending_txs
2150                .into_iter()
2151                .map(|tx| {
2152                    RpcTransaction::from_signed(&tx, None, self.network_type)
2153                })
2154                .collect::<Result<Vec<RpcTransaction>, String>>()
2155                .map_err(|e| into_rpc_err(e))?,
2156            first_tx_status: tx_status,
2157            pending_count: pending_count.into(),
2158        })
2159    }
2160}