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