client/rpc/impls/cfx/
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 crate::rpc::{
6    errors::{
7        internal_error_msg, invalid_params_check, invalid_params_detail,
8        invalid_params_msg,
9    },
10    types::{
11        cfx::{
12            check_rpc_address_network, check_two_rpc_address_network_match,
13            CfxFeeHistory,
14        },
15        pos::PoSEpochReward,
16        PoSEconomics, RpcAddress, SponsorInfo, StatOnGasLoad, TokenSupplyInfo,
17        VoteParamsInfo, WrapTransaction, U64 as HexU64,
18    },
19};
20use blockgen::BlockGeneratorTestApi;
21use cfx_execute_helper::estimation::{decode_error, EstimateExt};
22use cfx_executor::{
23    executive::{ExecutionError, ExecutionOutcome, TxDropError},
24    internal_contract::storage_point_prop,
25};
26use cfx_rpc_eth_types::Transaction as EthTransaction;
27use cfx_rpc_utils::error::jsonrpc_error_helpers::error_object_owned_to_jsonrpc_error;
28use cfx_statedb::{
29    global_params::{
30        AccumulateInterestRate, BaseFeeProp, DistributablePoSInterest,
31        InterestRate, LastDistributeBlock, PowBaseReward, TotalBurnt1559,
32        TotalPosStaking,
33    },
34    StateDbExt,
35};
36use cfx_types::{
37    Address, AddressSpaceUtil, BigEndianHash, Space, H256, H520, U128, U256,
38    U64,
39};
40use cfx_util_macros::bail;
41use cfx_vm_types::Error as VmError;
42use cfxcore::{
43    block_data_manager::BlockExecutionResult,
44    errors::account_result_to_rpc_result,
45    state_exposer::STATE_EXPOSER,
46    transaction_pool::TransactionPoolError,
47    verification::{compute_epoch_receipt_proof, EpochReceiptProof},
48    ConsensusGraph, PeerInfo, SharedConsensusGraph,
49    SharedSynchronizationService, SharedTransactionPool,
50};
51use cfxcore_accounts::AccountProvider;
52use delegate::delegate;
53use diem_types::transaction::TransactionPayload;
54use jsonrpc_core::{BoxFuture, Error as JsonRpcError, Result as JsonRpcResult};
55use log::{debug, error, info, trace, warn};
56use network::{
57    node_table::{Node, NodeId},
58    throttling, SessionDetails, UpdateNodeOperation,
59};
60use parking_lot::Mutex;
61use primitives::{
62    filter::LogFilter, receipt::EVM_SPACE_SUCCESS, Account, Block, BlockHeader,
63    BlockReceipts, DepositInfo, SignedTransaction, StorageKey, StorageRoot,
64    StorageValue, TransactionIndex, TransactionStatus,
65    TransactionWithSignature, VoteStakeInfo,
66};
67use random_crash::*;
68use rlp::Rlp;
69use rustc_hex::ToHex;
70use std::{
71    collections::BTreeMap, net::SocketAddr, sync::Arc, thread, time::Duration,
72};
73use txgen::{DirectTransactionGenerator, TransactionGenerator};
74// To convert from RpcResult to BoxFuture by delegate! macro automatically.
75use crate::{
76    common::delegate_convert,
77    rpc::{
78        errors::{
79            call_execution_error, internal_error, invalid_params,
80            pivot_assumption_failed, request_rejected_in_catch_up_mode,
81        },
82        impls::{
83            common::{self, RpcImpl as CommonImpl},
84            RpcImplConfiguration,
85        },
86        traits::{cfx::Cfx, debug::LocalRpc, test::TestRpc},
87        types::{
88            pos::Block as PosBlock, Account as RpcAccount, AccountPendingInfo,
89            AccountPendingTransactions, BlameInfo, Block as RpcBlock,
90            BlockHashOrEpochNumber, Bytes, CfxRpcLogFilter,
91            CheckBalanceAgainstTransactionResponse,
92            ConsensusGraphBlockExecutionState, ConsensusGraphBlockState,
93            ConsensusGraphStates, EpochNumber,
94            EstimateGasAndCollateralResponse, Log as RpcLog, PackedOrExecuted,
95            Receipt as RpcReceipt, RewardInfo as RpcRewardInfo,
96            Status as RpcStatus, StorageCollateralInfo, SyncGraphBlockState,
97            SyncGraphStates, Transaction as RpcTransaction, TransactionRequest,
98        },
99        CoreResult,
100    },
101};
102use cfx_addr::Network;
103use cfx_execute_helper::estimation::EstimateRequest;
104use cfx_executor::state::State;
105use cfx_parameters::{
106    consensus_internal::REWARD_EPOCH_COUNT,
107    genesis::{
108        genesis_contract_address_four_year, genesis_contract_address_two_year,
109    },
110    staking::{BLOCKS_PER_YEAR, DRIPS_PER_STORAGE_COLLATERAL_UNIT},
111};
112use cfx_storage::state::StateDbGetOriginalMethods;
113use cfxcore::{
114    consensus::{MaybeExecutedTxExtraInfo, TransactionInfo},
115    consensus_parameters::DEFERRED_STATE_EPOCH_COUNT,
116};
117use diem_types::account_address::AccountAddress;
118use serde::Serialize;
119
120#[derive(Debug)]
121pub(crate) struct BlockExecInfo {
122    pub(crate) block_receipts: Arc<BlockReceipts>,
123    pub(crate) block: Arc<Block>,
124    pub(crate) epoch_number: u64,
125    pub(crate) maybe_state_root: Option<H256>,
126    pub(crate) pivot_header: Arc<BlockHeader>,
127}
128
129pub struct RpcImpl {
130    pub config: RpcImplConfiguration,
131    pub consensus: SharedConsensusGraph,
132    pub sync: SharedSynchronizationService,
133    block_gen: BlockGeneratorTestApi,
134    pub tx_pool: SharedTransactionPool,
135    maybe_txgen: Option<Arc<TransactionGenerator>>,
136    maybe_direct_txgen: Option<Arc<Mutex<DirectTransactionGenerator>>>,
137    accounts: Arc<AccountProvider>,
138}
139
140impl RpcImpl {
141    pub fn new(
142        consensus: SharedConsensusGraph, sync: SharedSynchronizationService,
143        block_gen: BlockGeneratorTestApi, tx_pool: SharedTransactionPool,
144        maybe_txgen: Option<Arc<TransactionGenerator>>,
145        maybe_direct_txgen: Option<Arc<Mutex<DirectTransactionGenerator>>>,
146        config: RpcImplConfiguration, accounts: Arc<AccountProvider>,
147    ) -> Self {
148        RpcImpl {
149            consensus,
150            sync,
151            block_gen,
152            tx_pool,
153            maybe_txgen,
154            maybe_direct_txgen,
155            config,
156            accounts,
157        }
158    }
159
160    fn consensus_graph(&self) -> &ConsensusGraph { &self.consensus }
161
162    fn check_address_network(&self, network: Network) -> CoreResult<()> {
163        invalid_params_check(
164            "address",
165            check_rpc_address_network(
166                Some(network),
167                self.sync.network.get_network_type(),
168            ),
169        )
170        .map_err(|e| e.into())
171    }
172
173    /// This function is used to simplify the replacement of current EpochNumber
174    /// with BlockHashOrEpochNumber Note that using this function is likely
175    /// not to be the most efficient way for related imlemention
176    /// more optimization could be made if some perfermance throttle is met
177    fn get_epoch_number_with_pivot_check(
178        &self, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
179    ) -> CoreResult<EpochNumber> {
180        match block_hash_or_epoch_number {
181            Some(BlockHashOrEpochNumber::BlockHashWithOption {
182                hash,
183                require_pivot,
184            }) => {
185                // TODO: check if out of range
186                let epoch_number = self
187                    .consensus_graph()
188                    .get_block_epoch_number_with_pivot_check(
189                        &hash,
190                        require_pivot.unwrap_or(true),
191                    )?;
192                Ok(EpochNumber::Num(U64::from(epoch_number)))
193            }
194            Some(BlockHashOrEpochNumber::EpochNumber(epoch_number)) => {
195                Ok(epoch_number)
196            }
197            None => Ok(EpochNumber::LatestState),
198        }
199    }
200
201    fn code(
202        &self, address: RpcAddress,
203        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
204    ) -> CoreResult<Bytes> {
205        self.check_address_network(address.network)?;
206        let epoch_num = self
207            .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
208            .into();
209
210        info!(
211            "RPC Request: cfx_getCode address={:?} epoch_num={:?}",
212            address, epoch_num
213        );
214
215        let state_db = self
216            .consensus
217            .get_state_db_by_epoch_number(epoch_num, "num")?;
218
219        let address = address.hex_address.with_native_space();
220
221        let code = match state_db.get_account(&address)? {
222            Some(acc) => match state_db.get_code(&address, &acc.code_hash)? {
223                Some(code) => (*code.code).clone(),
224                _ => vec![],
225            },
226            None => vec![],
227        };
228
229        Ok(Bytes::new(code))
230    }
231
232    fn balance(
233        &self, address: RpcAddress,
234        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
235    ) -> CoreResult<U256> {
236        self.check_address_network(address.network)?;
237        let epoch_num = self
238            .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
239            .into();
240        // num.unwrap_or(EpochNumber::LatestState).into();
241
242        info!(
243            "RPC Request: cfx_getBalance address={:?} epoch_num={:?}",
244            address, epoch_num
245        );
246
247        let state_db = self
248            .consensus
249            .get_state_db_by_epoch_number(epoch_num, "num")?;
250        let acc =
251            state_db.get_account(&address.hex_address.with_native_space())?;
252
253        Ok(acc.map_or(U256::zero(), |acc| acc.balance).into())
254    }
255
256    fn admin(
257        &self, address: RpcAddress, num: Option<EpochNumber>,
258    ) -> CoreResult<Option<RpcAddress>> {
259        self.check_address_network(address.network)?;
260        let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
261        let network = address.network;
262
263        info!(
264            "RPC Request: cfx_getAdmin address={:?} epoch_num={:?}",
265            address, epoch_num
266        );
267
268        let state_db = self
269            .consensus
270            .get_state_db_by_epoch_number(epoch_num, "num")?;
271
272        match state_db.get_account(&address.hex_address.with_native_space())? {
273            None => Ok(None),
274            Some(acc) => {
275                Ok(Some(RpcAddress::try_from_h160(acc.admin, network)?))
276            }
277        }
278    }
279
280    fn sponsor_info(
281        &self, address: RpcAddress, num: Option<EpochNumber>,
282    ) -> CoreResult<SponsorInfo> {
283        self.check_address_network(address.network)?;
284        let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
285        let network = address.network;
286
287        info!(
288            "RPC Request: cfx_getSponsorInfo address={:?} epoch_num={:?}",
289            address, epoch_num
290        );
291
292        let state_db = self
293            .consensus
294            .get_state_db_by_epoch_number(epoch_num, "num")?;
295
296        match state_db.get_account(&address.hex_address.with_native_space())? {
297            None => Ok(SponsorInfo::default(network)?),
298            Some(acc) => Ok(SponsorInfo::try_from(acc.sponsor_info, network)?),
299        }
300    }
301
302    fn staking_balance(
303        &self, address: RpcAddress, num: Option<EpochNumber>,
304    ) -> CoreResult<U256> {
305        self.check_address_network(address.network)?;
306        let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
307
308        info!(
309            "RPC Request: cfx_getStakingBalance address={:?} epoch_num={:?}",
310            address, epoch_num
311        );
312
313        let state_db = self
314            .consensus
315            .get_state_db_by_epoch_number(epoch_num, "num")?;
316        let acc =
317            state_db.get_account(&address.hex_address.with_native_space())?;
318
319        Ok(acc.map_or(U256::zero(), |acc| acc.staking_balance).into())
320    }
321
322    fn deposit_list(
323        &self, address: RpcAddress, num: Option<EpochNumber>,
324    ) -> CoreResult<Vec<DepositInfo>> {
325        self.check_address_network(address.network)?;
326        let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
327
328        info!(
329            "RPC Request: cfx_getDepositList address={:?} epoch_num={:?}",
330            address, epoch_num
331        );
332
333        let state_db = self
334            .consensus
335            .get_state_db_by_epoch_number(epoch_num, "num")?;
336
337        match state_db
338            .get_deposit_list(&address.hex_address.with_native_space())?
339        {
340            None => Ok(vec![]),
341            Some(deposit_list) => Ok(deposit_list.0),
342        }
343    }
344
345    fn vote_list(
346        &self, address: RpcAddress, num: Option<EpochNumber>,
347    ) -> CoreResult<Vec<VoteStakeInfo>> {
348        self.check_address_network(address.network)?;
349        let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
350
351        info!(
352            "RPC Request: cfx_getVoteList address={:?} epoch_num={:?}",
353            address, epoch_num
354        );
355
356        let state_db = self
357            .consensus
358            .get_state_db_by_epoch_number(epoch_num, "num")?;
359
360        match state_db
361            .get_vote_list(&address.hex_address.with_native_space())?
362        {
363            None => Ok(vec![]),
364            Some(vote_list) => Ok(vote_list.0),
365        }
366    }
367
368    fn collateral_for_storage(
369        &self, address: RpcAddress, num: Option<EpochNumber>,
370    ) -> CoreResult<U256> {
371        self.check_address_network(address.network)?;
372        let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
373
374        info!(
375            "RPC Request: cfx_getCollateralForStorage address={:?} epoch_num={:?}",
376            address, epoch_num
377        );
378
379        let state_db = self
380            .consensus
381            .get_state_db_by_epoch_number(epoch_num, "num")?;
382        let acc =
383            state_db.get_account(&address.hex_address.with_native_space())?;
384
385        Ok(acc
386            .map_or(U256::zero(), |acc| acc.collateral_for_storage)
387            .into())
388    }
389
390    /// Return account related states of the given account
391    fn account(
392        &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
393    ) -> CoreResult<RpcAccount> {
394        self.check_address_network(address.network)?;
395        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
396        let network = address.network;
397
398        info!(
399            "RPC Request: cfx_getAccount address={:?} epoch_num={:?}",
400            address, epoch_num
401        );
402
403        let address = &address.hex_address;
404
405        let state_db = self
406            .consensus
407            .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
408
409        let account =
410            match state_db.get_account(&address.with_native_space())? {
411                Some(t) => t,
412                None => account_result_to_rpc_result(
413                    "address",
414                    Ok(Account::new_empty_with_balance(
415                        &address.with_native_space(),
416                        &U256::zero(), /* balance */
417                        &U256::zero(), /* nonce */
418                    )),
419                )?,
420            };
421
422        Ok(RpcAccount::try_from(account, network)?)
423    }
424
425    /// Returns interest rate of the given epoch
426    fn interest_rate(
427        &self, epoch_num: Option<EpochNumber>,
428    ) -> CoreResult<U256> {
429        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
430        let state_db = self
431            .consensus
432            .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
433
434        Ok(state_db.get_global_param::<InterestRate>()?.into())
435    }
436
437    /// Returns accumulate interest rate of the given epoch
438    fn accumulate_interest_rate(
439        &self, epoch_num: Option<EpochNumber>,
440    ) -> CoreResult<U256> {
441        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
442        let state_db = self
443            .consensus
444            .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
445
446        Ok(state_db
447            .get_global_param::<AccumulateInterestRate>()?
448            .into())
449    }
450
451    /// Returns accumulate interest rate of the given epoch
452    fn pos_economics(
453        &self, epoch_num: Option<EpochNumber>,
454    ) -> CoreResult<PoSEconomics> {
455        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
456        let state_db = self
457            .consensus
458            .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
459
460        Ok(PoSEconomics {
461            total_pos_staking_tokens: state_db
462                .get_global_param::<TotalPosStaking>()?,
463            distributable_pos_interest: state_db
464                .get_global_param::<DistributablePoSInterest>()?,
465            last_distribute_block: U64::from(
466                state_db.get_global_param::<LastDistributeBlock>()?.as_u64(),
467            ),
468        })
469    }
470
471    fn send_raw_transaction(&self, raw: Bytes) -> CoreResult<H256> {
472        info!("RPC Request: cfx_sendRawTransaction len={:?}", raw.0.len());
473        debug!("RawTransaction bytes={:?}", raw);
474
475        let tx: TransactionWithSignature = invalid_params_check(
476            "raw",
477            TransactionWithSignature::from_raw(&raw.into_vec()),
478        )?;
479
480        if tx.recover_public().is_err() {
481            bail!(invalid_params_detail(
482                "tx",
483                "Can not recover pubkey for Ethereum like tx"
484            ));
485        }
486
487        let r = self.send_transaction_with_signature(tx);
488        if r.is_ok() && self.config.dev_pack_tx_immediately {
489            // Try to pack and execute this new tx.
490            for _ in 0..DEFERRED_STATE_EPOCH_COUNT {
491                let generated = self.generate_one_block(
492                    1, /* num_txs */
493                    self.sync
494                        .get_synchronization_graph()
495                        .verification_config
496                        .max_block_size_in_bytes,
497                )?;
498                loop {
499                    // Wait for the new block to be fully processed, so all
500                    // generated blocks form a chain for
501                    // `tx` to be executed.
502                    if self.consensus.best_block_hash() == generated {
503                        break;
504                    } else {
505                        thread::sleep(Duration::from_millis(10));
506                    }
507                }
508            }
509        }
510        r
511    }
512
513    fn storage_at(
514        &self, address: RpcAddress, position: U256,
515        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
516    ) -> CoreResult<Option<H256>> {
517        self.check_address_network(address.network)?;
518        let epoch_num = self
519            .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
520            .into();
521
522        info!(
523            "RPC Request: cfx_getStorageAt address={:?}, position={:?}, epoch_num={:?})",
524            address, position, epoch_num
525        );
526
527        let state_db = self
528            .consensus
529            .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
530
531        let position: H256 = H256::from_uint(&position);
532
533        let key = StorageKey::new_storage_key(
534            &address.hex_address,
535            position.as_ref(),
536        )
537        .with_native_space();
538
539        Ok(match state_db.get::<StorageValue>(key)? {
540            Some(entry) => Some(H256::from_uint(&entry.value).into()),
541            None => None,
542        })
543    }
544
545    fn send_transaction_with_signature(
546        &self, tx: TransactionWithSignature,
547    ) -> CoreResult<H256> {
548        if self.sync.catch_up_mode() {
549            warn!("Ignore send_transaction request {}. Cannot send transaction when the node is still in catch-up mode.", tx.hash());
550            bail!(request_rejected_in_catch_up_mode(None));
551        }
552        let (signed_trans, failed_trans) =
553            self.tx_pool.insert_new_transactions(vec![tx]);
554
555        match (signed_trans.len(), failed_trans.len()) {
556            (0, 0) => {
557                debug!("insert_new_transactions ignores inserted transactions");
558                bail!(invalid_params_detail("tx", "tx already exist"))
559            }
560            (0, 1) => {
561                let tx_err = failed_trans.values().next().unwrap();
562                if let TransactionPoolError::StateDbError(err) = tx_err {
563                    bail!(internal_error(err))
564                } else {
565                    bail!(invalid_params_detail("tx", tx_err.to_string()))
566                }
567            }
568            (1, 0) => {
569                let tx_hash = signed_trans[0].hash();
570                self.sync.append_received_transactions(signed_trans);
571                Ok(tx_hash)
572            }
573            _ => {
574                // This should never happen
575                error!("insert_new_transactions failed, invalid length of returned result vector {}", signed_trans.len() + failed_trans.len());
576                bail!(internal_error(format!(
577                    "unexpected insert result, {} returned items",
578                    signed_trans.len() + failed_trans.len()
579                )))
580            }
581        }
582    }
583
584    fn prepare_transaction(
585        &self, mut tx: TransactionRequest, password: Option<String>,
586    ) -> CoreResult<TransactionWithSignature> {
587        let consensus_graph = self.consensus_graph();
588        tx.check_rpc_address_network(
589            "tx",
590            self.sync.network.get_network_type(),
591        )
592        .map_err(error_object_owned_to_jsonrpc_error)?;
593
594        if tx.nonce.is_none() {
595            let nonce = consensus_graph.next_nonce(
596                Address::from(tx.from.clone().ok_or("from should have")?)
597                    .with_native_space(),
598                BlockHashOrEpochNumber::EpochNumber(EpochNumber::LatestState)
599                    .into_primitive(),
600                // For an invalid_params error, the name of the params should
601                // be provided. the "next_nonce" function may return
602                // invalid_params error on an unsupported epoch_number.
603                "internal EpochNumber::LatestState",
604            )?;
605            tx.nonce.replace(nonce.into());
606            debug!("after loading nonce in latest state, tx = {:?}", tx);
607        }
608
609        let epoch_height = consensus_graph.best_epoch_number();
610        let chain_id = consensus_graph.best_chain_id();
611
612        if tx.gas.is_none() || tx.storage_limit.is_none() {
613            let estimate =
614                self.estimate_gas_and_collateral(tx.clone(), None)?;
615
616            if tx.gas.is_none() {
617                tx.gas.replace(estimate.gas_used);
618            }
619
620            if tx.storage_limit.is_none() {
621                tx.storage_limit.replace(estimate.storage_collateralized);
622            }
623        }
624
625        // default deal as 155 tx
626        if tx.transaction_type.is_none() && tx.gas_price.is_none() {
627            let gas_price = consensus_graph.gas_price(Space::Native);
628            if gas_price.is_some() {
629                tx.gas_price.replace(gas_price.unwrap());
630            }
631        }
632
633        tx.sign_with(
634            epoch_height,
635            chain_id.in_native_space(),
636            password,
637            self.accounts.clone(),
638        )
639        .map_err(Into::into)
640    }
641
642    fn send_transaction(
643        &self, tx: TransactionRequest, password: Option<String>,
644    ) -> CoreResult<H256> {
645        info!("RPC Request: cfx_sendTransaction, tx = {:?}", tx);
646
647        self.prepare_transaction(tx, password)
648            .and_then(|tx| self.send_transaction_with_signature(tx))
649    }
650
651    pub fn sign_transaction(
652        &self, tx: TransactionRequest, password: Option<String>,
653    ) -> CoreResult<String> {
654        let tx = self.prepare_transaction(tx, password).map_err(|e| {
655            invalid_params("tx", format!("failed to sign transaction: {:?}", e))
656        })?;
657        let raw_tx = rlp::encode(&tx);
658        Ok(format!("0x{}", raw_tx.to_hex::<String>()))
659    }
660
661    fn storage_root(
662        &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
663    ) -> CoreResult<Option<StorageRoot>> {
664        self.check_address_network(address.network)?;
665        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
666
667        info!(
668            "RPC Request: cfx_getStorageRoot address={:?} epoch={:?}",
669            address, epoch_num
670        );
671
672        let root = self
673            .consensus
674            .get_storage_state_by_epoch_number(epoch_num, "epoch_num")?
675            .get_original_storage_root(
676                &address.hex_address.with_native_space(),
677            )?;
678
679        Ok(Some(root))
680    }
681
682    fn send_usable_genesis_accounts(
683        &self, account_start_index: usize,
684    ) -> CoreResult<Bytes> {
685        info!(
686            "RPC Request: send_usable_genesis_accounts start from {:?}",
687            account_start_index
688        );
689        match self.maybe_txgen.as_ref() {
690            None => {
691                // FIXME: method_not_found
692                let mut rpc_error = JsonRpcError::method_not_found();
693                rpc_error.message = "send_usable_genesis_accounts only allowed in test or dev mode with txgen set.".into();
694                bail!(rpc_error)
695            }
696            Some(txgen) => {
697                txgen.set_genesis_accounts_start_index(account_start_index);
698                Ok(Bytes::new("1".into()))
699            }
700        }
701    }
702
703    pub fn transaction_by_hash(
704        &self, hash: H256,
705    ) -> CoreResult<Option<RpcTransaction>> {
706        let hash: H256 = hash.into();
707        info!("RPC Request: cfx_getTransactionByHash({:?})", hash);
708
709        if let Some((
710            tx,
711            TransactionInfo {
712                tx_index,
713                maybe_executed_extra_info,
714            },
715        )) = self.consensus.get_signed_tx_and_tx_info(&hash)
716        {
717            if tx.space() == Space::Ethereum || tx_index.is_phantom {
718                return Ok(None);
719            }
720
721            let packed_or_executed = match maybe_executed_extra_info {
722                None => PackedOrExecuted::Packed(tx_index),
723                Some(MaybeExecutedTxExtraInfo {
724                    receipt,
725                    block_number: _,
726                    prior_gas_used,
727                    tx_exec_error_msg,
728                }) => {
729                    let epoch_number = self
730                        .consensus
731                        .get_block_epoch_number(&tx_index.block_hash);
732
733                    let maybe_state_root = self
734                        .consensus
735                        .data_manager()
736                        .get_executed_state_root(&tx_index.block_hash);
737
738                    // Acutally, the return value of `block_header_by_hash`
739                    // should not be none.
740                    let maybe_base_price = self
741                        .consensus
742                        .data_manager()
743                        .block_header_by_hash(&tx_index.block_hash)
744                        .and_then(|x| x.base_price());
745
746                    PackedOrExecuted::Executed(RpcReceipt::new(
747                        tx.clone(),
748                        receipt,
749                        tx_index,
750                        prior_gas_used,
751                        epoch_number,
752                        maybe_base_price,
753                        maybe_state_root,
754                        tx_exec_error_msg,
755                        *self.sync.network.get_network_type(),
756                        false,
757                        false,
758                    )?)
759                }
760            };
761            let rpc_tx = RpcTransaction::from_signed(
762                &tx,
763                Some(packed_or_executed),
764                *self.sync.network.get_network_type(),
765            )?;
766
767            return Ok(Some(rpc_tx));
768        }
769
770        if let Some(tx) = self.tx_pool.get_transaction(&hash) {
771            if tx.space() == Space::Ethereum {
772                return Ok(None);
773            }
774
775            let rpc_tx = RpcTransaction::from_signed(
776                &tx,
777                None,
778                *self.sync.network.get_network_type(),
779            )?;
780            return Ok(Some(rpc_tx));
781        }
782
783        Ok(None)
784    }
785
786    fn get_block_execution_info(
787        &self, block_hash: &H256,
788    ) -> CoreResult<Option<BlockExecInfo>> {
789        let consensus_graph = self.consensus_graph();
790
791        let (pivot_hash, block_receipts, maybe_state_root) =
792            match consensus_graph.get_block_execution_info(block_hash) {
793                None => return Ok(None),
794                Some((exec_res, maybe_state_root)) => {
795                    (exec_res.0, exec_res.1.block_receipts, maybe_state_root)
796                }
797            };
798
799        let epoch_number = self
800            .consensus
801            .data_manager()
802            .block_header_by_hash(&pivot_hash)
803            // FIXME: server error, client should request another server.
804            .ok_or("Inconsistent state")?
805            .height();
806
807        if epoch_number > consensus_graph.best_executed_state_epoch_number() {
808            // The receipt is only visible to optimistic execution.
809            return Ok(None);
810        }
811
812        let block = self
813            .consensus
814            .data_manager()
815            .block_by_hash(&block_hash, false /* update_cache */)
816            // FIXME: server error, client should request another server.
817            .ok_or("Inconsistent state")?;
818
819        if block_receipts.receipts.len() != block.transactions.len() {
820            bail!("Inconsistent state");
821        }
822
823        let pivot_header = if let Some(x) = self
824            .consensus
825            .data_manager()
826            .block_header_by_hash(&pivot_hash)
827        {
828            x
829        } else {
830            warn!("Cannot find pivot header when get block execution info: pivot hash {:?}", pivot_hash);
831            return Ok(None);
832        };
833
834        Ok(Some(BlockExecInfo {
835            block_receipts,
836            block,
837            epoch_number,
838            maybe_state_root,
839            pivot_header,
840        }))
841    }
842
843    fn construct_rpc_receipt(
844        &self, tx_index: TransactionIndex, exec_info: &BlockExecInfo,
845        include_eth_receipt: bool, include_accumulated_gas_used: bool,
846    ) -> CoreResult<Option<RpcReceipt>> {
847        let id = tx_index.real_index;
848
849        if id >= exec_info.block.transactions.len()
850            || id >= exec_info.block_receipts.receipts.len()
851            || id >= exec_info.block_receipts.tx_execution_error_messages.len()
852        {
853            bail!("Inconsistent state");
854        }
855
856        let tx = &exec_info.block.transactions[id];
857
858        if !include_eth_receipt
859            && (tx.space() == Space::Ethereum || tx_index.is_phantom)
860        {
861            return Ok(None);
862        }
863
864        let prior_gas_used = match id {
865            0 => U256::zero(),
866            id => {
867                exec_info.block_receipts.receipts[id - 1].accumulated_gas_used
868            }
869        };
870
871        let tx_exec_error_msg =
872            match &exec_info.block_receipts.tx_execution_error_messages[id] {
873                msg if msg.is_empty() => None,
874                msg => Some(msg.clone()),
875            };
876
877        let receipt = RpcReceipt::new(
878            (**tx).clone(),
879            exec_info.block_receipts.receipts[id].clone(),
880            tx_index,
881            prior_gas_used,
882            Some(exec_info.epoch_number),
883            exec_info.pivot_header.base_price(),
884            exec_info.maybe_state_root.clone(),
885            tx_exec_error_msg,
886            *self.sync.network.get_network_type(),
887            include_eth_receipt,
888            include_accumulated_gas_used,
889        )?;
890
891        Ok(Some(receipt))
892    }
893
894    fn prepare_receipt(&self, tx_hash: H256) -> CoreResult<Option<RpcReceipt>> {
895        // Note: `transaction_index_by_hash` might return outdated results if
896        // there was a pivot chain reorg but the tx was not re-executed yet. In
897        // this case, `block_execution_results_by_hash` will detect that the
898        // execution results do not match the current pivot view and return
899        // None. If the tx was re-executed in another block on the new pivot
900        // chain, `transaction_index_by_hash` will return the updated result.
901        let tx_index =
902            match self.consensus.data_manager().transaction_index_by_hash(
903                &tx_hash, false, /* update_cache */
904            ) {
905                None => return Ok(None),
906                Some(tx_index) => tx_index,
907            };
908
909        if tx_index.is_phantom {
910            return Ok(None);
911        }
912
913        let exec_info =
914            match self.get_block_execution_info(&tx_index.block_hash)? {
915                None => return Ok(None),
916                Some(res) => res,
917            };
918
919        let receipt =
920            self.construct_rpc_receipt(tx_index, &exec_info, false, true)?;
921        if let Some(r) = &receipt {
922            // A skipped transaction is not available to clients if accessed by
923            // its hash.
924            if r.outcome_status
925                == TransactionStatus::Skipped.in_space(Space::Native).into()
926            {
927                return Ok(None);
928            }
929        }
930        Ok(receipt)
931    }
932
933    fn prepare_block_receipts(
934        &self, block_hash: H256, pivot_assumption: H256,
935        include_eth_receipt: bool,
936    ) -> CoreResult<Option<Vec<RpcReceipt>>> {
937        let exec_info = match self.get_block_execution_info(&block_hash)? {
938            None => return Ok(None), // not executed
939            Some(res) => res,
940        };
941
942        // pivot chain reorg
943        if pivot_assumption != exec_info.pivot_header.hash() {
944            bail!(pivot_assumption_failed(
945                pivot_assumption,
946                exec_info.pivot_header.hash()
947            ));
948        }
949
950        let mut rpc_receipts = vec![];
951
952        let iter = exec_info
953            .block
954            .transactions
955            .iter()
956            .enumerate()
957            .filter(|(_, tx)| {
958                if include_eth_receipt {
959                    true
960                } else {
961                    tx.space() == Space::Native
962                }
963            })
964            .enumerate();
965
966        for (new_index, (original_index, _)) in iter {
967            if let Some(receipt) = self.construct_rpc_receipt(
968                TransactionIndex {
969                    block_hash,
970                    real_index: original_index,
971                    is_phantom: false,
972                    rpc_index: Some(new_index),
973                },
974                &exec_info,
975                include_eth_receipt,
976                true,
977            )? {
978                rpc_receipts.push(receipt);
979            }
980        }
981
982        Ok(Some(rpc_receipts))
983    }
984
985    fn transaction_receipt(
986        &self, tx_hash: H256,
987    ) -> CoreResult<Option<RpcReceipt>> {
988        let hash: H256 = tx_hash.into();
989        info!("RPC Request: cfx_getTransactionReceipt({:?})", hash);
990        self.prepare_receipt(hash)
991    }
992
993    fn generate_empty_blocks(
994        &self, num_blocks: usize,
995    ) -> CoreResult<Vec<H256>> {
996        info!("RPC Request: generate({:?})", num_blocks);
997        let mut hashes = Vec::new();
998        for _i in 0..num_blocks {
999            hashes.push(
1000                self.block_gen.generate_block(
1001                    0,
1002                    self.sync
1003                        .get_synchronization_graph()
1004                        .verification_config
1005                        .max_block_size_in_bytes,
1006                    vec![],
1007                ),
1008            );
1009        }
1010        Ok(hashes)
1011    }
1012
1013    fn generate_fixed_block(
1014        &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize,
1015        adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>,
1016    ) -> CoreResult<H256> {
1017        info!(
1018            "RPC Request: generate_fixed_block({:?}, {:?}, {:?}, {:?}, {:?})",
1019            parent_hash, referee, num_txs, difficulty, pos_reference,
1020        );
1021
1022        Ok(self.block_gen.generate_fixed_block(
1023            parent_hash,
1024            referee,
1025            num_txs,
1026            difficulty.unwrap_or(0),
1027            adaptive,
1028            pos_reference,
1029        )?)
1030    }
1031
1032    fn generate_one_block(
1033        &self, num_txs: usize, block_size_limit: usize,
1034    ) -> CoreResult<H256> {
1035        info!("RPC Request: generate_one_block()");
1036        Ok(self
1037            .block_gen
1038            .generate_block(num_txs, block_size_limit, vec![]))
1039    }
1040
1041    fn generate_one_block_with_direct_txgen(
1042        &self, num_txs: usize, mut block_size_limit: usize,
1043        num_txs_simple: usize, num_txs_erc20: usize,
1044    ) -> CoreResult<H256> {
1045        info!("RPC Request: generate_one_block_with_direct_txgen()");
1046
1047        let block_gen = &self.block_gen;
1048        match self.maybe_direct_txgen.as_ref() {
1049            None => {
1050                // FIXME: create helper function.
1051                let mut rpc_error = JsonRpcError::method_not_found();
1052                rpc_error.message = "generate_one_block_with_direct_txgen only allowed in test or dev mode.".into();
1053                bail!(rpc_error)
1054            }
1055            Some(direct_txgen) => {
1056                let generated_transactions =
1057                    direct_txgen.lock().generate_transactions(
1058                        &mut block_size_limit,
1059                        num_txs_simple,
1060                        num_txs_erc20,
1061                        self.consensus.best_chain_id().in_native_space(),
1062                    );
1063
1064                Ok(block_gen.generate_block(
1065                    num_txs,
1066                    block_size_limit,
1067                    generated_transactions,
1068                ))
1069            }
1070        }
1071    }
1072
1073    fn generate_custom_block(
1074        &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes,
1075        adaptive: Option<bool>, custom: Option<Vec<Bytes>>,
1076    ) -> CoreResult<H256> {
1077        info!("RPC Request: generate_custom_block()");
1078
1079        let transactions = self.decode_raw_txs(raw_txs, 0)?;
1080
1081        Ok(self.block_gen.generate_custom_block_with_parent(
1082            parent_hash,
1083            referee,
1084            transactions,
1085            adaptive.unwrap_or(false),
1086            custom.map(|list| list.into_iter().map(|bytes| bytes.0).collect()),
1087        )?)
1088    }
1089
1090    fn generate_block_with_nonce_and_timestamp(
1091        &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256,
1092        timestamp: u64, adaptive: bool,
1093    ) -> CoreResult<H256> {
1094        let transactions = self.decode_raw_txs(raw, 0)?;
1095        self.block_gen
1096            .generate_block_with_nonce_and_timestamp(
1097                parent,
1098                referees,
1099                transactions,
1100                nonce,
1101                timestamp,
1102                adaptive,
1103            )
1104            .map_err(Into::into)
1105    }
1106
1107    fn decode_raw_txs(
1108        &self, raw_txs: Bytes, tx_data_len: usize,
1109    ) -> CoreResult<Vec<Arc<SignedTransaction>>> {
1110        let txs: Vec<TransactionWithSignature> =
1111            Rlp::new(&raw_txs.into_vec()).as_list().map_err(|err| {
1112                invalid_params("raw_txs", format!("Decode error: {:?}", err))
1113            })?;
1114
1115        let mut transactions = Vec::new();
1116
1117        for tx in txs {
1118            let public = match tx.recover_public() {
1119                Ok(public) => public,
1120                Err(e) => {
1121                    bail!(invalid_params(
1122                        &format!("raw_txs, tx {:?}", tx),
1123                        format!("Recover public error: {:?}", e),
1124                    ));
1125                }
1126            };
1127
1128            let mut signed_tx = SignedTransaction::new(public, tx);
1129
1130            // set fake data for latency tests
1131            if tx_data_len > 0 {
1132                *signed_tx.transaction.transaction.unsigned.data_mut() =
1133                    vec![0; tx_data_len];
1134            }
1135
1136            transactions.push(Arc::new(signed_tx));
1137        }
1138
1139        Ok(transactions)
1140    }
1141
1142    fn generate_block_with_fake_txs(
1143        &self, raw_txs_without_data: Bytes, adaptive: Option<bool>,
1144        tx_data_len: Option<usize>,
1145    ) -> CoreResult<H256> {
1146        let transactions = self
1147            .decode_raw_txs(raw_txs_without_data, tx_data_len.unwrap_or(0))?;
1148        Ok(self.block_gen.generate_custom_block(transactions, adaptive))
1149    }
1150
1151    fn generate_block_with_blame_info(
1152        &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo,
1153    ) -> CoreResult<H256> {
1154        Ok(self.block_gen.generate_block_with_blame_info(
1155            num_txs,
1156            block_size_limit,
1157            vec![],
1158            blame_info.blame.map(|x| x.as_u32()),
1159            blame_info.deferred_state_root.map(|x| x.into()),
1160            blame_info.deferred_receipts_root.map(|x| x.into()),
1161            blame_info.deferred_logs_bloom_hash.map(|x| x.into()),
1162        ))
1163    }
1164
1165    fn get_logs(&self, filter: CfxRpcLogFilter) -> CoreResult<Vec<RpcLog>> {
1166        // all addresses specified should be for the correct network
1167        if let Some(addresses) = &filter.address {
1168            for address in addresses.iter() {
1169                invalid_params_check(
1170                    "filter.address",
1171                    check_rpc_address_network(
1172                        Some(address.network),
1173                        self.sync.network.get_network_type(),
1174                    ),
1175                )?;
1176            }
1177        }
1178
1179        let consensus_graph = self.consensus_graph();
1180
1181        info!("RPC Request: cfx_getLogs({:?})", filter);
1182        let filter: LogFilter = filter
1183            .into_primitive()
1184            .map_err(error_object_owned_to_jsonrpc_error)?;
1185
1186        let logs = consensus_graph
1187            .logs(filter)?
1188            .iter()
1189            .cloned()
1190            .map(|l| {
1191                RpcLog::try_from_localized(
1192                    l,
1193                    *self.sync.network.get_network_type(),
1194                )
1195            })
1196            .collect::<Result<Vec<_>, _>>()?;
1197
1198        // If the results does not fit into `max_limit`, report an error
1199        if let Some(max_limit) = self.config.get_logs_filter_max_limit {
1200            if logs.len() > max_limit {
1201                bail!(invalid_params("filter", format!("This query results in too many logs, max limitation is {}, please filter results by a smaller epoch/block range", max_limit)));
1202            }
1203        }
1204
1205        Ok(logs)
1206    }
1207
1208    fn get_block_reward_info(
1209        &self, epoch: EpochNumber,
1210    ) -> CoreResult<Vec<RpcRewardInfo>> {
1211        info!(
1212            "RPC Request: cfx_getBlockRewardInfo epoch_number={:?}",
1213            epoch
1214        );
1215        let epoch_height: U64 = self
1216            .consensus_graph()
1217            .get_height_from_epoch_number(epoch.clone().into_primitive())?
1218            .into();
1219        let (epoch_later_number, overflow) =
1220            epoch_height.overflowing_add(REWARD_EPOCH_COUNT.into());
1221        if overflow {
1222            bail!(invalid_params("epoch", "Epoch number overflows!"));
1223        }
1224        let epoch_later = match self.consensus.get_hash_from_epoch_number(
1225            EpochNumber::Num(epoch_later_number).into_primitive(),
1226        ) {
1227            Ok(hash) => hash,
1228            Err(e) => {
1229                debug!("get_block_reward_info: get_hash_from_epoch_number returns error: {}", e);
1230                bail!(invalid_params("epoch", "Reward not calculated yet!"))
1231            }
1232        };
1233
1234        let blocks = self.consensus.get_block_hashes_by_epoch(epoch.into())?;
1235
1236        let mut ret = Vec::new();
1237        for b in blocks {
1238            if let Some(reward_result) = self
1239                .consensus
1240                .data_manager()
1241                .block_reward_result_by_hash_with_epoch(
1242                    &b,
1243                    &epoch_later,
1244                    false, // update_pivot_assumption
1245                    true,  // update_cache
1246                )
1247            {
1248                if let Some(block_header) =
1249                    self.consensus.data_manager().block_header_by_hash(&b)
1250                {
1251                    let author = RpcAddress::try_from_h160(
1252                        *block_header.author(),
1253                        *self.sync.network.get_network_type(),
1254                    )?;
1255
1256                    ret.push(RpcRewardInfo {
1257                        block_hash: b.into(),
1258                        author,
1259                        total_reward: reward_result.total_reward.into(),
1260                        base_reward: reward_result.base_reward.into(),
1261                        tx_fee: reward_result.tx_fee.into(),
1262                    })
1263                }
1264            }
1265        }
1266        Ok(ret)
1267    }
1268
1269    fn call(
1270        &self, request: TransactionRequest,
1271        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
1272    ) -> CoreResult<Bytes> {
1273        let epoch = Some(
1274            self.get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?,
1275        );
1276        let (execution_outcome, _estimation) =
1277            self.exec_transaction(request, epoch)?;
1278        match execution_outcome {
1279            ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1280                expected,
1281                got,
1282            )) => bail!(call_execution_error(
1283                "Transaction can not be executed".into(),
1284                format! {"nonce is too old expected {:?} got {:?}", expected, got}
1285            )),
1286            ExecutionOutcome::NotExecutedDrop(
1287                TxDropError::InvalidRecipientAddress(recipient),
1288            ) => bail!(call_execution_error(
1289                "Transaction can not be executed".into(),
1290                format! {"invalid recipient address {:?}", recipient}
1291            )),
1292            ExecutionOutcome::NotExecutedDrop(
1293                TxDropError::NotEnoughGasLimit { expected, got },
1294            ) => bail!(call_execution_error(
1295                "Transaction can not be executed".into(),
1296                format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1297            )),
1298            ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1299                address,
1300            )) => bail!(call_execution_error(
1301                "Transaction can not be executed".into(),
1302                format! {"tx sender has contract code: {:?}", address}
1303            )),
1304            ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1305                bail!(call_execution_error(
1306                    "Transaction can not be executed".into(),
1307                    format! {"{:?}", e}
1308                ))
1309            }
1310            ExecutionOutcome::ExecutionErrorBumpNonce(
1311                ExecutionError::VmError(VmError::Reverted),
1312                executed,
1313            ) => bail!(call_execution_error(
1314                "Transaction reverted".into(),
1315                format!("0x{}", executed.output.to_hex::<String>())
1316            )),
1317            ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1318                bail!(call_execution_error(
1319                    "Transaction execution failed".into(),
1320                    format! {"{:?}", e}
1321                ))
1322            }
1323            ExecutionOutcome::Finished(executed) => Ok(executed.output.into()),
1324        }
1325    }
1326
1327    fn estimate_gas_and_collateral(
1328        &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1329    ) -> CoreResult<EstimateGasAndCollateralResponse> {
1330        info!(
1331            "RPC Request: cfx_estimateGasAndCollateral request={:?}, epoch={:?}",request,epoch
1332        );
1333        let (execution_outcome, estimation) =
1334            self.exec_transaction(request, epoch)?;
1335        match execution_outcome {
1336            ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1337                expected,
1338                got,
1339            )) => bail!(call_execution_error(
1340                "Can not estimate: transaction can not be executed".into(),
1341                format! {"nonce is too old expected {:?} got {:?}", expected, got}
1342            )),
1343            ExecutionOutcome::NotExecutedDrop(
1344                TxDropError::InvalidRecipientAddress(recipient),
1345            ) => bail!(call_execution_error(
1346                "Can not estimate: transaction can not be executed".into(),
1347                format! {"invalid recipient address {:?}", recipient}
1348            )),
1349            ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1350                address,
1351            )) => bail!(call_execution_error(
1352                "Can not estimate: transaction sender has code".into(),
1353                format! {"transaction sender has code {:?}", address}
1354            )),
1355            ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1356                bail!(call_execution_error(
1357                    "Can not estimate: transaction can not be executed".into(),
1358                    format! {"{:?}", e}
1359                ))
1360            }
1361            ExecutionOutcome::NotExecutedDrop(
1362                TxDropError::NotEnoughGasLimit { expected, got },
1363            ) => bail!(call_execution_error(
1364                "Can not estimate: transaction can not be executed".into(),
1365                format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1366            )),
1367            ExecutionOutcome::ExecutionErrorBumpNonce(
1368                ExecutionError::VmError(VmError::Reverted),
1369                executed,
1370            ) => {
1371                let network_type = *self.sync.network.get_network_type();
1372                let (revert_error, innermost_error, errors) =
1373                    decode_error(&executed, |addr| {
1374                        RpcAddress::try_from_h160(addr.clone(), network_type)
1375                            .unwrap()
1376                            .base32_address
1377                    });
1378
1379                bail!(call_execution_error(
1380                    format!("Estimation isn't accurate: transaction is reverted{}{}",
1381                        revert_error, innermost_error),
1382                    errors.join("\n"),
1383                ))
1384            }
1385            ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1386                bail!(call_execution_error(
1387                    format! {"Can not estimate: transaction execution failed, \
1388                    all gas will be charged (execution error: {:?})", e}
1389                    .into(),
1390                    format! {"{:?}", e}
1391                ))
1392            }
1393            ExecutionOutcome::Finished(executed) => executed,
1394        };
1395        let storage_collateralized =
1396            U64::from(estimation.estimated_storage_limit);
1397        let estimated_gas_used = estimation.estimated_gas_limit;
1398        let response = EstimateGasAndCollateralResponse {
1399            gas_limit: estimated_gas_used, /* gas_limit used to be 4/3 of
1400                                            * gas_used due to inaccuracy,
1401                                            * currently it's the same as gas
1402                                            * used as it's more accurate */
1403            gas_used: estimated_gas_used,
1404            storage_collateralized,
1405        };
1406        Ok(response)
1407    }
1408
1409    fn check_balance_against_transaction(
1410        &self, account_addr: RpcAddress, contract_addr: RpcAddress,
1411        gas_limit: U256, gas_price: U256, storage_limit: U256,
1412        epoch: Option<EpochNumber>,
1413    ) -> CoreResult<CheckBalanceAgainstTransactionResponse> {
1414        self.check_address_network(account_addr.network)?;
1415        self.check_address_network(contract_addr.network)?;
1416
1417        let epoch: primitives::EpochNumber =
1418            epoch.unwrap_or(EpochNumber::LatestState).into();
1419
1420        info!(
1421            "RPC Request: cfx_checkBalanceAgainstTransaction account_addr={:?} contract_addr={:?} gas_limit={:?} gas_price={:?} storage_limit={:?} epoch={:?}",
1422            account_addr, contract_addr, gas_limit, gas_price, storage_limit, epoch
1423        );
1424
1425        let account_addr = account_addr.hex_address.with_native_space();
1426        let contract_addr = contract_addr.hex_address.with_native_space();
1427
1428        if storage_limit > U256::from(std::u64::MAX) {
1429            bail!(JsonRpcError::invalid_params(format!("storage_limit has to be within the range of u64 but {} supplied!", storage_limit)));
1430        }
1431
1432        let state_db = self
1433            .consensus
1434            .get_state_db_by_epoch_number(epoch, "epoch")?;
1435
1436        let user_account = state_db.get_account(&account_addr)?;
1437        let contract_account = state_db.get_account(&contract_addr)?;
1438        let state = State::new(state_db)?;
1439        let is_sponsored = state.check_contract_whitelist(
1440            &contract_addr.address,
1441            &account_addr.address,
1442        )?;
1443
1444        Ok(common::check_balance_against_transaction(
1445            user_account,
1446            contract_account,
1447            is_sponsored,
1448            gas_limit,
1449            gas_price,
1450            storage_limit,
1451        ))
1452    }
1453
1454    fn exec_transaction(
1455        &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1456    ) -> CoreResult<(ExecutionOutcome, EstimateExt)> {
1457        let rpc_request_network = invalid_params_check(
1458            "request",
1459            check_two_rpc_address_network_match(
1460                request.from.as_ref(),
1461                request.to.as_ref(),
1462            ),
1463        )?;
1464        invalid_params_check(
1465            "request",
1466            check_rpc_address_network(
1467                rpc_request_network,
1468                self.sync.network.get_network_type(),
1469            ),
1470        )?;
1471
1472        let consensus_graph = self.consensus_graph();
1473        let epoch = epoch.unwrap_or(EpochNumber::LatestState);
1474
1475        let estimate_request = EstimateRequest {
1476            has_sender: request.from.is_some(),
1477            has_gas_limit: request.gas.is_some(),
1478            has_gas_price: request.has_gas_price(),
1479            has_nonce: request.nonce.is_some(),
1480            has_storage_limit: request.storage_limit.is_some(),
1481            collect_access_list: false,
1482        };
1483
1484        let epoch_height = consensus_graph
1485            .get_height_from_epoch_number(epoch.clone().into())?;
1486        let chain_id = consensus_graph.best_chain_id();
1487        let signed_tx = request
1488            .sign_call(
1489                epoch_height,
1490                chain_id.in_native_space(),
1491                self.config.max_estimation_gas_limit,
1492            )
1493            .map_err(error_object_owned_to_jsonrpc_error)?;
1494        trace!("call tx {:?}", signed_tx);
1495
1496        consensus_graph.call_virtual(
1497            &signed_tx,
1498            epoch.into(),
1499            estimate_request,
1500            Default::default(),
1501        )
1502    }
1503
1504    fn current_sync_phase(&self) -> CoreResult<String> {
1505        Ok(self.sync.current_sync_phase().name().into())
1506    }
1507
1508    /// Return the pivot chain block hashes in `height_range` (inclusive) and
1509    /// their subtree weight. If it's none, return all pivot chain from
1510    /// `cur_era_genesis` to chain tip.
1511    ///
1512    /// Note that this should note query blocks before `cur_era_genesis`.
1513    fn get_pivot_chain_and_weight(
1514        &self, height_range: Option<(u64, u64)>,
1515    ) -> CoreResult<Vec<(H256, U256)>> {
1516        let consensus_graph = self.consensus_graph();
1517        Ok(consensus_graph
1518            .inner
1519            .read()
1520            .get_pivot_chain_and_weight(height_range)?)
1521    }
1522
1523    fn get_executed_info(&self, block_hash: H256) -> CoreResult<(H256, H256)> {
1524        let commitment = self
1525            .consensus
1526            .data_manager()
1527            .get_epoch_execution_commitment(&block_hash)
1528            .ok_or(JsonRpcError::invalid_params(
1529                "No receipts root. Possibly never pivot?".to_owned(),
1530            ))?;
1531        Ok((
1532            commitment.receipts_root.clone().into(),
1533            commitment
1534                .state_root_with_aux_info
1535                .state_root
1536                .compute_state_root_hash(),
1537        ))
1538    }
1539
1540    fn expire_block_gc(&self, timeout: u64) -> CoreResult<()> {
1541        self.sync.expire_block_gc(timeout);
1542        Ok(())
1543    }
1544
1545    pub fn consensus_graph_state(&self) -> CoreResult<ConsensusGraphStates> {
1546        let consensus_graph_states =
1547            STATE_EXPOSER.consensus_graph.lock().retrieve();
1548        // Ok(ConsensusGraphStates::new(consensus_graph_states))
1549        let mut block_state_vec = Vec::new();
1550        let mut block_execution_state_vec = Vec::new();
1551
1552        for block_state in &consensus_graph_states.block_state_vec {
1553            block_state_vec.push(ConsensusGraphBlockState {
1554                block_hash: block_state.block_hash.into(),
1555                best_block_hash: block_state.best_block_hash.into(),
1556                block_status: (block_state.block_status as u8).into(),
1557                era_block_hash: block_state.era_block_hash.into(),
1558                adaptive: block_state.adaptive,
1559            })
1560        }
1561        for exec_state in &consensus_graph_states.block_execution_state_vec {
1562            block_execution_state_vec.push(ConsensusGraphBlockExecutionState {
1563                block_hash: exec_state.block_hash.into(),
1564                deferred_state_root: exec_state.deferred_state_root.into(),
1565                deferred_receipt_root: exec_state.deferred_receipt_root.into(),
1566                deferred_logs_bloom_hash: exec_state
1567                    .deferred_logs_bloom_hash
1568                    .into(),
1569                state_valid: exec_state.state_valid,
1570            })
1571        }
1572
1573        Ok(ConsensusGraphStates {
1574            block_state_vec,
1575            block_execution_state_vec,
1576        })
1577    }
1578
1579    pub fn sync_graph_state(&self) -> CoreResult<SyncGraphStates> {
1580        let sync_graph_states = STATE_EXPOSER.sync_graph.lock().retrieve();
1581        let mut ready_block_vec = Vec::new();
1582        for block_state in sync_graph_states.ready_block_vec {
1583            ready_block_vec.push(SyncGraphBlockState {
1584                block_hash: block_state.block_hash.into(),
1585                parent: block_state.parent.into(),
1586                referees: block_state
1587                    .referees
1588                    .iter()
1589                    .map(|x| H256::from(*x))
1590                    .collect(),
1591                nonce: block_state.nonce.into(),
1592                timestamp: U64::from(block_state.timestamp),
1593                adaptive: block_state.adaptive,
1594            })
1595        }
1596        Ok(SyncGraphStates { ready_block_vec })
1597    }
1598
1599    /// Return (block_info.status, state_valid)
1600    /// Return Error if either field is missing
1601    pub fn get_block_status(&self, block_hash: H256) -> CoreResult<(u8, bool)> {
1602        let consensus_graph = self.consensus_graph();
1603        let status = consensus_graph
1604            .data_man
1605            .local_block_info_by_hash(&block_hash)
1606            // FIXME: invalid_params?
1607            .ok_or(invalid_params("block_hash", "No block status"))?
1608            .get_status();
1609        let state_valid = consensus_graph
1610            .inner
1611            .read()
1612            .block_node(&block_hash)
1613            .ok_or(invalid_params("block_hash", "No block in consensus"))?
1614            .data
1615            .state_valid
1616            .ok_or(invalid_params("block_hash", "No state_valid"))?;
1617        Ok((status.to_db_status(), state_valid))
1618    }
1619
1620    pub fn get_supply_info(
1621        &self, epoch: Option<EpochNumber>,
1622    ) -> CoreResult<TokenSupplyInfo> {
1623        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1624        let state = State::new(
1625            self.consensus
1626                .get_state_db_by_epoch_number(epoch, "epoch")?,
1627        )?;
1628        let total_issued = state.total_issued_tokens();
1629        let total_staking = state.total_staking_tokens();
1630        let total_collateral = state.total_storage_tokens();
1631        let two_year_unlock_address = genesis_contract_address_two_year();
1632        let four_year_unlock_address = genesis_contract_address_four_year();
1633        let two_year_locked = state
1634            .balance(&two_year_unlock_address)
1635            .unwrap_or(U256::zero());
1636        let four_year_locked = state
1637            .balance(&four_year_unlock_address)
1638            .unwrap_or(U256::zero());
1639        let total_circulating =
1640            total_issued - two_year_locked - four_year_locked;
1641        let total_espace_tokens = state.total_espace_tokens();
1642        Ok(TokenSupplyInfo {
1643            total_circulating,
1644            total_issued,
1645            total_staking,
1646            total_collateral,
1647            total_espace_tokens,
1648        })
1649    }
1650
1651    pub fn get_collateral_info(
1652        &self, epoch: Option<EpochNumber>,
1653    ) -> CoreResult<StorageCollateralInfo> {
1654        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1655        let state = State::new(
1656            self.consensus
1657                .get_state_db_by_epoch_number(epoch, "epoch")?,
1658        )?;
1659        let total_storage_tokens = state.total_storage_tokens();
1660        let converted_storage_points = state.converted_storage_points()
1661            / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1662        let used_storage_points =
1663            state.used_storage_points() / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1664        Ok(StorageCollateralInfo {
1665            total_storage_tokens,
1666            converted_storage_points,
1667            used_storage_points,
1668        })
1669    }
1670
1671    pub fn get_vote_params(
1672        &self, epoch: Option<EpochNumber>,
1673    ) -> CoreResult<VoteParamsInfo> {
1674        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1675        let state_db = self
1676            .consensus
1677            .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1678        let interest_rate = state_db.get_global_param::<InterestRate>()?
1679            / U256::from(BLOCKS_PER_YEAR);
1680        let pow_base_reward = state_db.get_global_param::<PowBaseReward>()?;
1681
1682        let storage_point_prop =
1683            state_db.get_system_storage(&storage_point_prop())?;
1684
1685        let base_fee_share_prop = state_db.get_global_param::<BaseFeeProp>()?;
1686        Ok(VoteParamsInfo {
1687            pow_base_reward,
1688            interest_rate,
1689            storage_point_prop,
1690            base_fee_share_prop,
1691        })
1692    }
1693
1694    pub fn get_fee_burnt(
1695        &self, epoch: Option<EpochNumber>,
1696    ) -> CoreResult<U256> {
1697        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1698        let state_db = self
1699            .consensus
1700            .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1701
1702        Ok(state_db.get_global_param::<TotalBurnt1559>()?)
1703    }
1704
1705    pub fn set_db_crash(
1706        &self, crash_probability: f64, crash_exit_code: i32,
1707    ) -> CoreResult<()> {
1708        if crash_probability == 0.0 {
1709            *CRASH_EXIT_PROBABILITY.lock() = None;
1710        } else {
1711            *CRASH_EXIT_PROBABILITY.lock() = Some(crash_probability);
1712        }
1713        *CRASH_EXIT_CODE.lock() = crash_exit_code;
1714        Ok(())
1715    }
1716
1717    // estimate response size, return error if it is too large
1718    // note: this is a potentially expensive check
1719    fn check_response_size<T: Serialize>(
1720        &self, response: &T,
1721    ) -> CoreResult<()> {
1722        // account for the enclosing JSON object
1723        // {"jsonrpc":"2.0","id":1,"result": ... }
1724        // note: this is a rough estimation
1725        let max_size = self.config.max_payload_bytes - 50;
1726
1727        let payload_size = serde_json::to_vec(&response)
1728            .map_err(|_e| "Unexpected serialization error")?
1729            .len();
1730
1731        if payload_size > max_size {
1732            // TODO(thegaram): should we define a new error type?
1733            bail!(invalid_params(
1734                "epoch",
1735                format!(
1736                    "Oversized payload: size = {}, max = {}",
1737                    payload_size, max_size
1738                )
1739            ));
1740        }
1741
1742        Ok(())
1743    }
1744
1745    fn get_block_epoch_number(&self, h: &H256) -> Option<u64> {
1746        // try to get from memory
1747        if let Some(e) = self.consensus.get_block_epoch_number(h) {
1748            return Some(e);
1749        }
1750
1751        // try to get from db
1752        self.consensus.data_manager().block_epoch_number(h)
1753    }
1754
1755    fn epoch_receipts(
1756        &self, epoch: BlockHashOrEpochNumber, include_eth_receipt: Option<bool>,
1757    ) -> CoreResult<Option<Vec<Vec<RpcReceipt>>>> {
1758        info!("RPC Request: cfx_getEpochReceipts({:?})", epoch);
1759
1760        let hashes = self
1761            .consensus
1762            .get_block_hashes_by_epoch_or_block_hash(epoch.into())?;
1763
1764        let pivot_hash = *hashes.last().ok_or("Inconsistent state")?;
1765        let mut epoch_receipts = vec![];
1766
1767        for h in hashes {
1768            epoch_receipts.push(
1769                match self.prepare_block_receipts(
1770                    h,
1771                    pivot_hash,
1772                    include_eth_receipt.unwrap_or(false),
1773                )? {
1774                    None => return Ok(None), // not executed
1775                    Some(rs) => rs,
1776                },
1777            );
1778        }
1779
1780        // TODO(thegaram): we should only do this on WS, not on HTTP
1781        // how to treat these differently?
1782        self.check_response_size(&epoch_receipts)?;
1783
1784        Ok(Some(epoch_receipts))
1785    }
1786
1787    fn epoch_receipt_proof_by_transaction(
1788        &self, tx_hash: H256,
1789    ) -> JsonRpcResult<Option<EpochReceiptProof>> {
1790        let (block_hash, tx_index_in_block) =
1791            match self.consensus.get_signed_tx_and_tx_info(&tx_hash) {
1792                None => {
1793                    bail!(invalid_params(
1794                        "transactions hash",
1795                        format!(
1796                            "Unable to get transaction info for hash {:?}",
1797                            tx_hash
1798                        )
1799                    ));
1800                }
1801                Some((_, TransactionInfo { tx_index, .. })) => {
1802                    (tx_index.block_hash, tx_index.real_index)
1803                }
1804            };
1805
1806        let epoch = match self.consensus.get_block_epoch_number(&block_hash) {
1807            Some(epoch) => epoch,
1808            None => {
1809                bail!(invalid_params(
1810                    "block hash",
1811                    format!(
1812                        "Unable to get epoch number for block {:?}",
1813                        block_hash
1814                    )
1815                ));
1816            }
1817        };
1818
1819        let epoch_number = primitives::EpochNumber::Number(epoch);
1820        let epoch_hashes = match self
1821            .consensus
1822            .get_block_hashes_by_epoch(epoch_number.clone())
1823        {
1824            Ok(hs) => hs,
1825            Err(e) => {
1826                bail!(invalid_params(
1827                    "block hash",
1828                    format!("Unable to find epoch hashes for {}: {}", epoch, e)
1829                ));
1830            }
1831        };
1832
1833        let block_index_in_epoch =
1834            match epoch_hashes.iter().position(|h| *h == block_hash) {
1835                Some(id) => id,
1836                None => {
1837                    bail!(invalid_params(
1838                        "block hash",
1839                        format!(
1840                            "Unable to find block {:?} in epoch {}",
1841                            block_hash, epoch
1842                        )
1843                    ));
1844                }
1845            };
1846
1847        let pivot = epoch_hashes
1848            .last()
1849            .expect("epoch hashes should be not empty")
1850            .clone();
1851
1852        let epoch_receipts = epoch_hashes
1853            .into_iter()
1854            .map(|h| {
1855                self.consensus
1856                    .data_manager()
1857                    .block_execution_result_by_hash_with_epoch(
1858                        &h, &pivot, false, /* update_pivot_assumption */
1859                        false, /* update_cache */
1860                    )
1861                    .map(|res| Arc::new((*res.block_receipts).clone()))
1862                    .ok_or_else(|| {
1863                        invalid_params(
1864                            "block hash",
1865                            format!("Unable to find recepits for {}", h),
1866                        )
1867                    })
1868            })
1869            .collect::<Result<Vec<_>, _>>()?;
1870
1871        let epoch_receipt_proof = compute_epoch_receipt_proof(
1872            &epoch_receipts,
1873            block_index_in_epoch,
1874            tx_index_in_block,
1875        );
1876
1877        Ok(Some(epoch_receipt_proof))
1878    }
1879
1880    fn stat_on_gas_load(
1881        &self, last_epoch: EpochNumber, time_window: U64,
1882    ) -> CoreResult<Option<StatOnGasLoad>> {
1883        let mut stat = StatOnGasLoad::default();
1884        stat.time_elapsed = time_window;
1885
1886        let block_not_found_error = || {
1887            internal_error_msg(
1888                "Cannot find the block by a ConsensusGraph provided hash",
1889            )
1890        };
1891
1892        let machine = self.tx_pool.machine();
1893        let consensus = self.consensus_graph();
1894
1895        let mut epoch_number = match last_epoch {
1896            EpochNumber::Earliest => {
1897                bail!(invalid_params_msg("Cannot stat genesis"))
1898            }
1899            EpochNumber::Num(num) if num.is_zero() => {
1900                bail!(invalid_params_msg("Cannot stat genesis"))
1901            }
1902            EpochNumber::LatestMined => bail!(invalid_params_msg(
1903                "Epoch number is earilier than 'latest_state'"
1904            )),
1905            EpochNumber::Num(num) => {
1906                let pivot_hash = consensus.get_hash_from_epoch_number(
1907                    primitives::EpochNumber::LatestState,
1908                )?;
1909                let epoch_number = consensus
1910                    .get_block_epoch_number(&pivot_hash)
1911                    .ok_or_else(block_not_found_error)?;
1912                if epoch_number < num.as_u64() {
1913                    bail!(invalid_params_msg(
1914                        "Epoch number is earilier than 'latest_state'"
1915                    ))
1916                }
1917                num.as_u64()
1918            }
1919            EpochNumber::LatestCheckpoint
1920            | EpochNumber::LatestFinalized
1921            | EpochNumber::LatestConfirmed
1922            | EpochNumber::LatestState => {
1923                let pivot_hash =
1924                    consensus.get_hash_from_epoch_number(last_epoch.into())?;
1925                consensus
1926                    .get_block_epoch_number(&pivot_hash)
1927                    .ok_or_else(block_not_found_error)?
1928            }
1929        };
1930
1931        let mut last_timestamp: Option<u64> = None;
1932
1933        loop {
1934            // Step 1: fetch block data
1935            let block_hashes = consensus.get_block_hashes_by_epoch(
1936                primitives::EpochNumber::Number(epoch_number),
1937            )?;
1938            let blocks = consensus
1939                .data_manager()
1940                .blocks_by_hash_list(&block_hashes, false)
1941                .ok_or_else(block_not_found_error)?;
1942            let pivot_block = blocks
1943                .last()
1944                .ok_or(internal_error_msg("Epoch without block"))?;
1945
1946            // Step 2: update timestamp
1947            let timestamp = pivot_block.block_header.timestamp();
1948            if last_timestamp.is_none() {
1949                last_timestamp = Some(timestamp)
1950            }
1951            // Stop if the epoch does not in the query window.
1952            if last_timestamp.unwrap().saturating_sub(time_window.as_u64())
1953                > timestamp
1954            {
1955                break;
1956            }
1957
1958            // Step 3: Stat blocks
1959            let params = machine.params();
1960            stat.epoch_num += 1.into();
1961            for b in &blocks {
1962                stat.total_block_num += 1.into();
1963                stat.total_gas_limit += *b.block_header.gas_limit();
1964                if params.can_pack_evm_transaction(b.block_header.height()) {
1965                    stat.espace_block_num += 1.into();
1966                    stat.espace_gas_limit += *b.block_header.gas_limit()
1967                        / params.evm_transaction_gas_ratio;
1968                }
1969            }
1970
1971            // Step 4: Stat transactions
1972            for b in &blocks {
1973                // Fetch execution info or return not found.
1974                let exec_info =
1975                    match consensus.get_block_execution_info(&b.hash()) {
1976                        None => bail!(internal_error_msg(
1977                        "Cannot fetch block receipt with checked input params"
1978                    )),
1979                        Some((res, _)) => res.1,
1980                    };
1981
1982                for (receipt, tx) in exec_info
1983                    .block_receipts
1984                    .receipts
1985                    .iter()
1986                    .zip(&b.transactions)
1987                {
1988                    let space = tx.space();
1989                    if receipt.outcome_status == TransactionStatus::Skipped {
1990                        *stat.skipped_tx_count.in_space_mut(space) += 1.into();
1991                        *stat.skipped_tx_gas_limit.in_space_mut(space) +=
1992                            *tx.gas_limit();
1993                    } else {
1994                        *stat.confirmed_tx_count.in_space_mut(space) +=
1995                            1.into();
1996                        *stat.confirmed_tx_gas_limit.in_space_mut(space) +=
1997                            *tx.gas_limit();
1998                        *stat.tx_gas_charged.in_space_mut(space) +=
1999                            receipt.gas_fee / tx.gas_price();
2000                    }
2001                }
2002            }
2003
2004            // Goto Next Epoch
2005            if epoch_number > 0 {
2006                epoch_number -= 1;
2007            } else {
2008                break;
2009            }
2010        }
2011        Ok(Some(stat))
2012    }
2013
2014    fn transactions_by_epoch(
2015        &self, epoch_number: U64,
2016    ) -> JsonRpcResult<Vec<WrapTransaction>> {
2017        debug!("debug_getTransactionsByEpoch {}", epoch_number);
2018
2019        let block_hashs = self
2020            .consensus
2021            .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2022                epoch_number.as_u64(),
2023            ))
2024            .map_err(|e| {
2025                JsonRpcError::invalid_params(format!(
2026                    "Could not get block hashes by epoch {}",
2027                    e
2028                ))
2029            })?;
2030
2031        let blocks = match self
2032            .consensus
2033            .data_manager()
2034            .blocks_by_hash_list(&block_hashs, false)
2035        {
2036            None => {
2037                return Err(JsonRpcError::invalid_params(format!(
2038                    "Could not get blocks for hashs {:?}",
2039                    block_hashs
2040                )))
2041            }
2042            Some(b) => b,
2043        };
2044
2045        let pivot = match blocks.last() {
2046            Some(p) => p,
2047            None => {
2048                return Err(JsonRpcError::invalid_params("blocks is empty"))
2049            }
2050        };
2051
2052        self.get_transactions(&blocks, pivot, epoch_number.as_u64())
2053    }
2054
2055    fn transactions_by_block(
2056        &self, block_hash: H256,
2057    ) -> JsonRpcResult<Vec<WrapTransaction>> {
2058        debug!("debug_getTransactionsByBlock {}", block_hash);
2059
2060        let epoch_number = match self.get_block_epoch_number(&block_hash) {
2061            None => {
2062                return Err(JsonRpcError::invalid_params(format!(
2063                    "Counld not get epoch for block {}",
2064                    block_hash
2065                )))
2066            }
2067            Some(n) => n,
2068        };
2069
2070        let block_hashs = self
2071            .consensus
2072            .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2073                epoch_number,
2074            ))
2075            .map_err(|e| {
2076                JsonRpcError::invalid_params(format!(
2077                    "Could not get block hashes by epoch {}",
2078                    e
2079                ))
2080            })?;
2081
2082        let blocks = match self
2083            .consensus
2084            .data_manager()
2085            .blocks_by_hash_list(&block_hashs, false)
2086        {
2087            None => {
2088                return Err(JsonRpcError::invalid_params(format!(
2089                    "Counld not get blocks for hashs {:?}",
2090                    block_hashs
2091                )))
2092            }
2093            Some(b) => b,
2094        };
2095
2096        let pivot = match blocks.last() {
2097            Some(p) => p,
2098            None => {
2099                return Err(JsonRpcError::invalid_params("blocks is empty"))
2100            }
2101        };
2102
2103        let mut block = vec![];
2104        for b in blocks.iter() {
2105            if b.hash() == block_hash {
2106                block.push((*b).clone());
2107                break;
2108            }
2109        }
2110
2111        self.get_transactions(&block, pivot, epoch_number)
2112    }
2113
2114    fn get_transactions(
2115        &self, blocks: &Vec<Arc<Block>>, pivot: &Arc<Block>, epoch_number: u64,
2116    ) -> JsonRpcResult<Vec<WrapTransaction>> {
2117        let mut transactions = vec![];
2118
2119        for b in blocks.into_iter() {
2120            match self.get_transactions_for_block(b, pivot, epoch_number) {
2121                Ok(mut txs) => {
2122                    transactions.append(&mut txs);
2123                }
2124                Err(e) => bail!(internal_error(e)),
2125            };
2126        }
2127
2128        Ok(transactions)
2129    }
2130
2131    fn get_transactions_for_block(
2132        &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2133    ) -> Result<Vec<WrapTransaction>, String> {
2134        let exec_info = self
2135            .consensus
2136            .data_manager()
2137            .block_execution_result_by_hash_with_epoch(
2138                &b.hash(),
2139                &pivot.hash(),
2140                false,
2141                false,
2142            );
2143        if let Some(execution_result) = exec_info {
2144            self.get_transactions_for_executed_block(
2145                b,
2146                pivot,
2147                epoch_number,
2148                execution_result,
2149            )
2150        } else {
2151            self.get_transactions_for_non_executed_block(b, pivot)
2152        }
2153    }
2154
2155    fn get_transactions_for_non_executed_block(
2156        &self, b: &Arc<Block>, pivot: &Arc<Block>,
2157    ) -> Result<Vec<WrapTransaction>, String> {
2158        let network = *self.sync.network.get_network_type();
2159
2160        let mut eth_transaction_idx = 0;
2161        let mut make_eth_wrap_tx = |tx| {
2162            let block_info = (
2163                Some(pivot.hash()),
2164                Some(pivot.block_header.height().into()),
2165                Some(eth_transaction_idx.into()),
2166            );
2167            eth_transaction_idx += 1;
2168            WrapTransaction::EthTransaction(EthTransaction::from_signed(
2169                tx,
2170                block_info,
2171                (None, None),
2172            ))
2173        };
2174
2175        let make_cfx_wrap_tx = |tx| -> Result<WrapTransaction, String> {
2176            Ok(WrapTransaction::NativeTransaction(
2177                RpcTransaction::from_signed(tx, None, network)?,
2178            ))
2179        };
2180
2181        let mut res = vec![];
2182        for (_, tx) in b.transactions.iter().enumerate() {
2183            res.push(match tx.space() {
2184                Space::Ethereum => make_eth_wrap_tx(tx),
2185                Space::Native => make_cfx_wrap_tx(tx)?,
2186            });
2187        }
2188        Ok(res)
2189    }
2190
2191    fn get_transactions_for_executed_block(
2192        &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2193        execution_result: BlockExecutionResult,
2194    ) -> Result<Vec<WrapTransaction>, String> {
2195        let network = *self.sync.network.get_network_type();
2196        let maybe_state_root = self
2197            .consensus
2198            .data_manager()
2199            .get_executed_state_root(&b.hash());
2200        let block_receipts = &execution_result.block_receipts.receipts;
2201
2202        let mut eth_transaction_idx = 0;
2203        let mut make_eth_wrap_tx = |tx, id: usize| {
2204            let receipt = &block_receipts[id];
2205
2206            let status = receipt.outcome_status.in_space(Space::Ethereum);
2207            let contract_address = match status == EVM_SPACE_SUCCESS {
2208                true => EthTransaction::deployed_contract_address(tx),
2209                false => None,
2210            };
2211            let block_info = (
2212                Some(pivot.hash()),
2213                Some(pivot.block_header.height().into()),
2214                Some(eth_transaction_idx.into()),
2215            );
2216            eth_transaction_idx += 1;
2217
2218            WrapTransaction::EthTransaction(EthTransaction::from_signed(
2219                tx,
2220                block_info,
2221                (Some(status.into()), contract_address),
2222            ))
2223        };
2224
2225        let mut cfx_transaction_index = 0;
2226        let mut make_cfx_wrap_tx = |tx, id: usize| -> Result<_, String> {
2227            let receipt = &block_receipts[id];
2228            let prior_gas_used = if id == 0 {
2229                U256::zero()
2230            } else {
2231                block_receipts[id - 1].accumulated_gas_used
2232            };
2233
2234            if receipt.outcome_status == TransactionStatus::Skipped {
2235                cfx_transaction_index += 1;
2236                return Ok(WrapTransaction::NativeTransaction(
2237                    RpcTransaction::from_signed(tx, None, network)?,
2238                ));
2239            }
2240
2241            let tx_index = TransactionIndex {
2242                block_hash: b.hash(),
2243                real_index: id,
2244                is_phantom: false,
2245                rpc_index: Some(cfx_transaction_index),
2246            };
2247            let tx_exec_error_msg = &execution_result
2248                .block_receipts
2249                .tx_execution_error_messages[id];
2250            let receipt = RpcReceipt::new(
2251                tx.clone(),
2252                receipt.clone(),
2253                tx_index,
2254                prior_gas_used,
2255                Some(epoch_number),
2256                b.block_header.base_price(),
2257                maybe_state_root,
2258                if tx_exec_error_msg.is_empty() {
2259                    None
2260                } else {
2261                    Some(tx_exec_error_msg.clone())
2262                },
2263                network,
2264                false,
2265                false,
2266            )?;
2267            cfx_transaction_index += 1;
2268            let executed = Some(PackedOrExecuted::Executed(receipt));
2269            Ok(WrapTransaction::NativeTransaction(
2270                RpcTransaction::from_signed(tx, executed, network)?,
2271            ))
2272        };
2273
2274        let mut res = vec![];
2275        for (id, tx) in b.transactions.iter().enumerate() {
2276            res.push(match tx.space() {
2277                Space::Ethereum => make_eth_wrap_tx(&**tx, id),
2278                Space::Native => make_cfx_wrap_tx(&**tx, id)?,
2279            })
2280        }
2281
2282        Ok(res)
2283    }
2284}
2285
2286#[allow(dead_code)]
2287pub struct CfxHandler {
2288    common: Arc<CommonImpl>,
2289    rpc_impl: Arc<RpcImpl>,
2290}
2291
2292impl CfxHandler {
2293    pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2294        CfxHandler { common, rpc_impl }
2295    }
2296}
2297
2298impl Cfx for CfxHandler {
2299    delegate! {
2300        to self.common {
2301            fn best_block_hash(&self) -> JsonRpcResult<H256>;
2302            fn block_by_epoch_number(
2303                &self, epoch_num: EpochNumber, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2304            fn block_by_hash_with_pivot_assumption(
2305                &self, block_hash: H256, pivot_hash: H256, epoch_number: U64)
2306                -> BoxFuture<JsonRpcResult<RpcBlock>>;
2307            fn block_by_hash(&self, hash: H256, include_txs: bool)
2308                -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2309            fn block_by_block_number(&self, block_number: U64, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2310            fn confirmation_risk_by_hash(&self, block_hash: H256) -> JsonRpcResult<Option<U256>>;
2311            fn blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2312            fn skipped_blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2313            fn epoch_number(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2314            fn gas_price(&self) -> BoxFuture<JsonRpcResult<U256>>;
2315            fn next_nonce(&self, address: RpcAddress, num: Option<BlockHashOrEpochNumber>)
2316                -> BoxFuture<JsonRpcResult<U256>>;
2317            fn get_status(&self) -> JsonRpcResult<RpcStatus>;
2318            fn get_client_version(&self) -> JsonRpcResult<String>;
2319            fn account_pending_info(&self, addr: RpcAddress) -> BoxFuture<JsonRpcResult<Option<AccountPendingInfo>>>;
2320            fn account_pending_transactions(&self, address: RpcAddress, maybe_start_nonce: Option<U256>, maybe_limit: Option<U64>) -> BoxFuture<JsonRpcResult<AccountPendingTransactions>>;
2321            fn get_pos_reward_by_epoch(&self, epoch: EpochNumber) -> JsonRpcResult<Option<PoSEpochReward>>;
2322            fn fee_history(&self, block_count: HexU64, newest_block: EpochNumber, reward_percentiles: Option<Vec<f64>>) -> BoxFuture<JsonRpcResult<CfxFeeHistory>>;
2323            fn max_priority_fee_per_gas(&self) -> BoxFuture<JsonRpcResult<U256>>;
2324        }
2325
2326        to self.rpc_impl {
2327            fn code(&self, addr: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<Bytes>>;
2328            fn account(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<RpcAccount>>;
2329            fn interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2330            fn accumulate_interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2331            fn pos_economics(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<PoSEconomics>>;
2332            fn admin(&self, address: RpcAddress, num: Option<EpochNumber>)
2333                -> BoxFuture<JsonRpcResult<Option<RpcAddress>>>;
2334            fn sponsor_info(&self, address: RpcAddress, num: Option<EpochNumber>)
2335                -> BoxFuture<JsonRpcResult<SponsorInfo>>;
2336            fn balance(&self, address: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2337            fn staking_balance(&self, address: RpcAddress, num: Option<EpochNumber>)
2338                -> BoxFuture<JsonRpcResult<U256>>;
2339            fn deposit_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<DepositInfo>>>;
2340            fn vote_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<VoteStakeInfo>>>;
2341            fn collateral_for_storage(&self, address: RpcAddress, num: Option<EpochNumber>)
2342                -> BoxFuture<JsonRpcResult<U256>>;
2343            fn call(&self, request: TransactionRequest, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2344                -> JsonRpcResult<Bytes>;
2345            fn estimate_gas_and_collateral(
2346                &self, request: TransactionRequest, epoch_number: Option<EpochNumber>)
2347                -> JsonRpcResult<EstimateGasAndCollateralResponse>;
2348            fn check_balance_against_transaction(
2349                &self, account_addr: RpcAddress, contract_addr: RpcAddress, gas_limit: U256, gas_price: U256, storage_limit: U256, epoch: Option<EpochNumber>,
2350            ) -> BoxFuture<JsonRpcResult<CheckBalanceAgainstTransactionResponse>>;
2351            fn get_logs(&self, filter: CfxRpcLogFilter) -> BoxFuture<JsonRpcResult<Vec<RpcLog>>>;
2352            fn get_block_reward_info(&self, num: EpochNumber) -> JsonRpcResult<Vec<RpcRewardInfo>>;
2353            fn send_raw_transaction(&self, raw: Bytes) -> JsonRpcResult<H256>;
2354            fn storage_at(&self, addr: RpcAddress, pos: U256, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2355                -> BoxFuture<JsonRpcResult<Option<H256>>>;
2356            fn transaction_by_hash(&self, hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcTransaction>>>;
2357            fn transaction_receipt(&self, tx_hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcReceipt>>>;
2358            fn storage_root(&self, address: RpcAddress, epoch_num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Option<StorageRoot>>>;
2359            fn get_supply_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<TokenSupplyInfo>;
2360            fn get_collateral_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<StorageCollateralInfo>;
2361            fn get_vote_params(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<VoteParamsInfo>;
2362            fn get_fee_burnt(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2363        }
2364    }
2365}
2366
2367#[allow(dead_code)]
2368pub struct TestRpcImpl {
2369    common: Arc<CommonImpl>,
2370    rpc_impl: Arc<RpcImpl>,
2371}
2372
2373impl TestRpcImpl {
2374    pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2375        TestRpcImpl { common, rpc_impl }
2376    }
2377}
2378
2379impl TestRpc for TestRpcImpl {
2380    delegate! {
2381        to self.common {
2382            fn add_latency(&self, id: NodeId, latency_ms: f64) -> JsonRpcResult<()>;
2383            fn add_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2384            fn chain(&self) -> JsonRpcResult<Vec<RpcBlock>>;
2385            fn drop_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2386            fn get_block_count(&self) -> JsonRpcResult<u64>;
2387            fn get_goodput(&self) -> JsonRpcResult<String>;
2388            fn get_nodeid(&self, challenge: Vec<u8>) -> JsonRpcResult<Vec<u8>>;
2389            fn get_peer_info(&self) -> JsonRpcResult<Vec<PeerInfo>>;
2390            fn say_hello(&self) -> JsonRpcResult<String>;
2391            fn stop(&self) -> JsonRpcResult<()>;
2392            fn save_node_db(&self) -> JsonRpcResult<()>;
2393            fn pos_register(&self, voting_power: U64, version: Option<u8>) -> JsonRpcResult<(Bytes, AccountAddress)>;
2394            fn pos_update_voting_power(
2395                &self, pos_account: AccountAddress, increased_voting_power: U64,
2396            ) -> JsonRpcResult<()>;
2397            fn pos_stop_election(&self) -> JsonRpcResult<Option<u64>>;
2398            fn pos_start_voting(&self, initialize: bool) -> JsonRpcResult<()>;
2399            fn pos_stop_voting(&self) -> JsonRpcResult<()>;
2400            fn pos_voting_status(&self) -> JsonRpcResult<bool>;
2401            fn pos_start(&self) -> JsonRpcResult<()>;
2402            fn pos_force_vote_proposal(&self, block_id: H256) -> JsonRpcResult<()>;
2403            fn pos_force_propose(&self, round: U64, parent_block_id: H256, payload: Vec<TransactionPayload>) -> JsonRpcResult<()>;
2404            fn pos_trigger_timeout(&self, timeout_type: String) -> JsonRpcResult<()>;
2405            fn pos_force_sign_pivot_decision(&self, block_hash: H256, height: U64) -> JsonRpcResult<()>;
2406            fn pos_get_chosen_proposal(&self) -> JsonRpcResult<Option<PosBlock>>;
2407        }
2408
2409        to self.rpc_impl {
2410            fn expire_block_gc(&self, timeout: u64) -> JsonRpcResult<()>;
2411            fn generate_block_with_blame_info(
2412                &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo) -> JsonRpcResult<H256>;
2413            fn generate_block_with_fake_txs(
2414                &self, raw_txs_without_data: Bytes, adaptive: Option<bool>, tx_data_len: Option<usize>)
2415                -> JsonRpcResult<H256>;
2416            fn generate_custom_block(
2417                &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes, adaptive: Option<bool>, custom: Option<Vec<Bytes>>)
2418                -> JsonRpcResult<H256>;
2419            fn get_pivot_chain_and_weight(&self, height_range: Option<(u64, u64)>) -> JsonRpcResult<Vec<(H256, U256)>>;
2420            fn get_executed_info(&self, block_hash: H256) -> JsonRpcResult<(H256, H256)> ;
2421            fn generate_fixed_block(
2422                &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize, adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>)
2423                -> JsonRpcResult<H256>;
2424            fn generate_one_block_with_direct_txgen(
2425                &self, num_txs: usize, block_size_limit: usize, num_txs_simple: usize, num_txs_erc20: usize)
2426                -> JsonRpcResult<H256>;
2427            fn generate_one_block(&self, num_txs: usize, block_size_limit: usize) -> JsonRpcResult<H256>;
2428            fn generate_block_with_nonce_and_timestamp(
2429                &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256, timestamp: u64, adaptive: bool)
2430                -> JsonRpcResult<H256>;
2431            fn generate_empty_blocks(&self, num_blocks: usize) -> JsonRpcResult<Vec<H256>>;
2432            fn get_block_status(&self, block_hash: H256) -> JsonRpcResult<(u8, bool)>;
2433            fn send_usable_genesis_accounts(& self, account_start_index: usize) -> JsonRpcResult<Bytes>;
2434            fn set_db_crash(&self, crash_probability: f64, crash_exit_code: i32) -> JsonRpcResult<()>;
2435        }
2436    }
2437}
2438
2439pub struct LocalRpcImpl {
2440    common: Arc<CommonImpl>,
2441    rpc_impl: Arc<RpcImpl>,
2442}
2443
2444impl LocalRpcImpl {
2445    pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2446        LocalRpcImpl { common, rpc_impl }
2447    }
2448}
2449
2450impl LocalRpc for LocalRpcImpl {
2451    delegate! {
2452        to self.common {
2453            fn txpool_content(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2454                BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<RpcTransaction>>>>>;
2455            fn txpool_inspect(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2456                BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<String>>>>>;
2457            fn txpool_get_account_transactions(&self, address: RpcAddress) -> JsonRpcResult<Vec<RpcTransaction>>;
2458            fn txpool_clear(&self) -> JsonRpcResult<()>;
2459            fn net_node(&self, id: NodeId) -> JsonRpcResult<Option<(String, Node)>>;
2460            fn net_disconnect_node(&self, id: NodeId, op: Option<UpdateNodeOperation>)
2461                -> JsonRpcResult<bool>;
2462            fn net_sessions(&self, node_id: Option<NodeId>) -> JsonRpcResult<Vec<SessionDetails>>;
2463            fn net_throttling(&self) -> JsonRpcResult<throttling::Service>;
2464            fn accounts(&self) -> JsonRpcResult<Vec<RpcAddress>>;
2465            fn new_account(&self, password: String) -> JsonRpcResult<RpcAddress>;
2466            fn unlock_account(
2467                &self, address: RpcAddress, password: String, duration: Option<U128>)
2468                -> JsonRpcResult<bool>;
2469            fn lock_account(&self, address: RpcAddress) -> JsonRpcResult<bool>;
2470            fn sign(&self, data: Bytes, address: RpcAddress, password: Option<String>)
2471                -> JsonRpcResult<H520>;
2472
2473        }
2474
2475        to self.rpc_impl {
2476            fn current_sync_phase(&self) -> JsonRpcResult<String>;
2477            fn consensus_graph_state(&self) -> JsonRpcResult<ConsensusGraphStates>;
2478            fn epoch_receipts(&self, epoch: BlockHashOrEpochNumber, include_eth_recepits: Option<bool>,) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;
2479            fn epoch_receipt_proof_by_transaction(&self, tx_hash: H256) -> JsonRpcResult<Option<EpochReceiptProof>>;
2480            fn stat_on_gas_load(&self, last_epoch: EpochNumber, time_window: U64) -> JsonRpcResult<Option<StatOnGasLoad>>;
2481            fn sync_graph_state(&self) -> JsonRpcResult<SyncGraphStates>;
2482            fn send_transaction(
2483                &self, tx: TransactionRequest, password: Option<String>) -> BoxFuture<JsonRpcResult<H256>>;
2484            fn sign_transaction(&self, tx: TransactionRequest, password: Option<String>) -> JsonRpcResult<String>;
2485            fn transactions_by_epoch(&self, epoch_number: U64) -> JsonRpcResult<Vec<WrapTransaction>>;
2486            fn transactions_by_block(&self, block_hash: H256) -> JsonRpcResult<Vec<WrapTransaction>>;
2487        }
2488    }
2489}