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                        block_number,
753                        maybe_base_price,
754                        maybe_state_root,
755                        tx_exec_error_msg,
756                        *self.sync.network.get_network_type(),
757                        false,
758                        false,
759                    )?)
760                }
761            };
762            let rpc_tx = RpcTransaction::from_signed(
763                &tx,
764                Some(packed_or_executed),
765                *self.sync.network.get_network_type(),
766            )?;
767
768            return Ok(Some(rpc_tx));
769        }
770
771        if let Some(tx) = self.tx_pool.get_transaction(&hash) {
772            if tx.space() == Space::Ethereum {
773                return Ok(None);
774            }
775
776            let rpc_tx = RpcTransaction::from_signed(
777                &tx,
778                None,
779                *self.sync.network.get_network_type(),
780            )?;
781            return Ok(Some(rpc_tx));
782        }
783
784        Ok(None)
785    }
786
787    fn get_block_execution_info(
788        &self, block_hash: &H256,
789    ) -> CoreResult<Option<BlockExecInfo>> {
790        let consensus_graph = self.consensus_graph();
791
792        let (pivot_hash, block_receipts, maybe_state_root) =
793            match consensus_graph.get_block_execution_info(block_hash) {
794                None => return Ok(None),
795                Some((exec_res, maybe_state_root)) => {
796                    (exec_res.0, exec_res.1.block_receipts, maybe_state_root)
797                }
798            };
799
800        let epoch_number = self
801            .consensus
802            .data_manager()
803            .block_header_by_hash(&pivot_hash)
804            // FIXME: server error, client should request another server.
805            .ok_or("Inconsistent state")?
806            .height();
807
808        if epoch_number > consensus_graph.best_executed_state_epoch_number() {
809            // The receipt is only visible to optimistic execution.
810            return Ok(None);
811        }
812
813        let block = self
814            .consensus
815            .data_manager()
816            .block_by_hash(&block_hash, false /* update_cache */)
817            // FIXME: server error, client should request another server.
818            .ok_or("Inconsistent state")?;
819
820        if block_receipts.receipts.len() != block.transactions.len() {
821            bail!("Inconsistent state");
822        }
823
824        let pivot_header = if let Some(x) = self
825            .consensus
826            .data_manager()
827            .block_header_by_hash(&pivot_hash)
828        {
829            x
830        } else {
831            warn!("Cannot find pivot header when get block execution info: pivot hash {:?}", pivot_hash);
832            return Ok(None);
833        };
834
835        Ok(Some(BlockExecInfo {
836            block_receipts,
837            block,
838            epoch_number,
839            maybe_state_root,
840            pivot_header,
841        }))
842    }
843
844    fn construct_rpc_receipt(
845        &self, tx_index: TransactionIndex, exec_info: &BlockExecInfo,
846        include_eth_receipt: bool, include_accumulated_gas_used: bool,
847    ) -> CoreResult<Option<RpcReceipt>> {
848        let id = tx_index.real_index;
849
850        if id >= exec_info.block.transactions.len()
851            || id >= exec_info.block_receipts.receipts.len()
852            || id >= exec_info.block_receipts.tx_execution_error_messages.len()
853        {
854            bail!("Inconsistent state");
855        }
856
857        let tx = &exec_info.block.transactions[id];
858
859        if !include_eth_receipt
860            && (tx.space() == Space::Ethereum || tx_index.is_phantom)
861        {
862            return Ok(None);
863        }
864
865        let prior_gas_used = match id {
866            0 => U256::zero(),
867            id => {
868                exec_info.block_receipts.receipts[id - 1].accumulated_gas_used
869            }
870        };
871
872        let tx_exec_error_msg =
873            match &exec_info.block_receipts.tx_execution_error_messages[id] {
874                msg if msg.is_empty() => None,
875                msg => Some(msg.clone()),
876            };
877
878        let receipt = RpcReceipt::new(
879            (**tx).clone(),
880            exec_info.block_receipts.receipts[id].clone(),
881            tx_index,
882            prior_gas_used,
883            Some(exec_info.epoch_number),
884            exec_info.block_receipts.block_number,
885            exec_info.pivot_header.base_price(),
886            exec_info.maybe_state_root.clone(),
887            tx_exec_error_msg,
888            *self.sync.network.get_network_type(),
889            include_eth_receipt,
890            include_accumulated_gas_used,
891        )?;
892
893        Ok(Some(receipt))
894    }
895
896    fn prepare_receipt(&self, tx_hash: H256) -> CoreResult<Option<RpcReceipt>> {
897        // Note: `transaction_index_by_hash` might return outdated results if
898        // there was a pivot chain reorg but the tx was not re-executed yet. In
899        // this case, `block_execution_results_by_hash` will detect that the
900        // execution results do not match the current pivot view and return
901        // None. If the tx was re-executed in another block on the new pivot
902        // chain, `transaction_index_by_hash` will return the updated result.
903        let tx_index =
904            match self.consensus.data_manager().transaction_index_by_hash(
905                &tx_hash, false, /* update_cache */
906            ) {
907                None => return Ok(None),
908                Some(tx_index) => tx_index,
909            };
910
911        if tx_index.is_phantom {
912            return Ok(None);
913        }
914
915        let exec_info =
916            match self.get_block_execution_info(&tx_index.block_hash)? {
917                None => return Ok(None),
918                Some(res) => res,
919            };
920
921        let receipt =
922            self.construct_rpc_receipt(tx_index, &exec_info, false, true)?;
923        if let Some(r) = &receipt {
924            // A skipped transaction is not available to clients if accessed by
925            // its hash.
926            if r.outcome_status
927                == TransactionStatus::Skipped.in_space(Space::Native).into()
928            {
929                return Ok(None);
930            }
931        }
932        Ok(receipt)
933    }
934
935    fn prepare_block_receipts(
936        &self, block_hash: H256, pivot_assumption: H256,
937        include_eth_receipt: bool,
938    ) -> CoreResult<Option<Vec<RpcReceipt>>> {
939        let exec_info = match self.get_block_execution_info(&block_hash)? {
940            None => return Ok(None), // not executed
941            Some(res) => res,
942        };
943
944        // pivot chain reorg
945        if pivot_assumption != exec_info.pivot_header.hash() {
946            bail!(pivot_assumption_failed(
947                pivot_assumption,
948                exec_info.pivot_header.hash()
949            ));
950        }
951
952        let mut rpc_receipts = vec![];
953
954        let iter = exec_info
955            .block
956            .transactions
957            .iter()
958            .enumerate()
959            .filter(|(_, tx)| {
960                if include_eth_receipt {
961                    true
962                } else {
963                    tx.space() == Space::Native
964                }
965            })
966            .enumerate();
967
968        for (new_index, (original_index, _)) in iter {
969            if let Some(receipt) = self.construct_rpc_receipt(
970                TransactionIndex {
971                    block_hash,
972                    real_index: original_index,
973                    is_phantom: false,
974                    rpc_index: Some(new_index),
975                },
976                &exec_info,
977                include_eth_receipt,
978                true,
979            )? {
980                rpc_receipts.push(receipt);
981            }
982        }
983
984        Ok(Some(rpc_receipts))
985    }
986
987    fn transaction_receipt(
988        &self, tx_hash: H256,
989    ) -> CoreResult<Option<RpcReceipt>> {
990        let hash: H256 = tx_hash.into();
991        info!("RPC Request: cfx_getTransactionReceipt({:?})", hash);
992        self.prepare_receipt(hash)
993    }
994
995    fn generate_empty_blocks(
996        &self, num_blocks: usize,
997    ) -> CoreResult<Vec<H256>> {
998        info!("RPC Request: generate({:?})", num_blocks);
999        let mut hashes = Vec::new();
1000        for _i in 0..num_blocks {
1001            hashes.push(
1002                self.block_gen.generate_block(
1003                    0,
1004                    self.sync
1005                        .get_synchronization_graph()
1006                        .verification_config
1007                        .max_block_size_in_bytes,
1008                    vec![],
1009                ),
1010            );
1011        }
1012        Ok(hashes)
1013    }
1014
1015    fn generate_fixed_block(
1016        &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize,
1017        adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>,
1018    ) -> CoreResult<H256> {
1019        info!(
1020            "RPC Request: generate_fixed_block({:?}, {:?}, {:?}, {:?}, {:?})",
1021            parent_hash, referee, num_txs, difficulty, pos_reference,
1022        );
1023
1024        Ok(self.block_gen.generate_fixed_block(
1025            parent_hash,
1026            referee,
1027            num_txs,
1028            difficulty.unwrap_or(0),
1029            adaptive,
1030            pos_reference,
1031        )?)
1032    }
1033
1034    fn generate_one_block(
1035        &self, num_txs: usize, block_size_limit: usize,
1036    ) -> CoreResult<H256> {
1037        info!("RPC Request: generate_one_block()");
1038        Ok(self
1039            .block_gen
1040            .generate_block(num_txs, block_size_limit, vec![]))
1041    }
1042
1043    fn generate_one_block_with_direct_txgen(
1044        &self, num_txs: usize, mut block_size_limit: usize,
1045        num_txs_simple: usize, num_txs_erc20: usize,
1046    ) -> CoreResult<H256> {
1047        info!("RPC Request: generate_one_block_with_direct_txgen()");
1048
1049        let block_gen = &self.block_gen;
1050        match self.maybe_direct_txgen.as_ref() {
1051            None => {
1052                // FIXME: create helper function.
1053                let mut rpc_error = JsonRpcError::method_not_found();
1054                rpc_error.message = "generate_one_block_with_direct_txgen only allowed in test or dev mode.".into();
1055                bail!(rpc_error)
1056            }
1057            Some(direct_txgen) => {
1058                let generated_transactions =
1059                    direct_txgen.lock().generate_transactions(
1060                        &mut block_size_limit,
1061                        num_txs_simple,
1062                        num_txs_erc20,
1063                        self.consensus.best_chain_id().in_native_space(),
1064                    );
1065
1066                Ok(block_gen.generate_block(
1067                    num_txs,
1068                    block_size_limit,
1069                    generated_transactions,
1070                ))
1071            }
1072        }
1073    }
1074
1075    fn generate_custom_block(
1076        &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes,
1077        adaptive: Option<bool>, custom: Option<Vec<Bytes>>,
1078    ) -> CoreResult<H256> {
1079        info!("RPC Request: generate_custom_block()");
1080
1081        let transactions = self.decode_raw_txs(raw_txs, 0)?;
1082
1083        Ok(self.block_gen.generate_custom_block_with_parent(
1084            parent_hash,
1085            referee,
1086            transactions,
1087            adaptive.unwrap_or(false),
1088            custom.map(|list| list.into_iter().map(|bytes| bytes.0).collect()),
1089        )?)
1090    }
1091
1092    fn generate_block_with_nonce_and_timestamp(
1093        &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256,
1094        timestamp: u64, adaptive: bool,
1095    ) -> CoreResult<H256> {
1096        let transactions = self.decode_raw_txs(raw, 0)?;
1097        self.block_gen
1098            .generate_block_with_nonce_and_timestamp(
1099                parent,
1100                referees,
1101                transactions,
1102                nonce,
1103                timestamp,
1104                adaptive,
1105            )
1106            .map_err(Into::into)
1107    }
1108
1109    fn decode_raw_txs(
1110        &self, raw_txs: Bytes, tx_data_len: usize,
1111    ) -> CoreResult<Vec<Arc<SignedTransaction>>> {
1112        let txs: Vec<TransactionWithSignature> =
1113            Rlp::new(&raw_txs.into_vec()).as_list().map_err(|err| {
1114                invalid_params("raw_txs", format!("Decode error: {:?}", err))
1115            })?;
1116
1117        let mut transactions = Vec::new();
1118
1119        for tx in txs {
1120            let public = match tx.recover_public() {
1121                Ok(public) => public,
1122                Err(e) => {
1123                    bail!(invalid_params(
1124                        &format!("raw_txs, tx {:?}", tx),
1125                        format!("Recover public error: {:?}", e),
1126                    ));
1127                }
1128            };
1129
1130            let mut signed_tx = SignedTransaction::new(public, tx);
1131
1132            // set fake data for latency tests
1133            if tx_data_len > 0 {
1134                *signed_tx.transaction.transaction.unsigned.data_mut() =
1135                    vec![0; tx_data_len];
1136            }
1137
1138            transactions.push(Arc::new(signed_tx));
1139        }
1140
1141        Ok(transactions)
1142    }
1143
1144    fn generate_block_with_fake_txs(
1145        &self, raw_txs_without_data: Bytes, adaptive: Option<bool>,
1146        tx_data_len: Option<usize>,
1147    ) -> CoreResult<H256> {
1148        let transactions = self
1149            .decode_raw_txs(raw_txs_without_data, tx_data_len.unwrap_or(0))?;
1150        Ok(self.block_gen.generate_custom_block(transactions, adaptive))
1151    }
1152
1153    fn generate_block_with_blame_info(
1154        &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo,
1155    ) -> CoreResult<H256> {
1156        Ok(self.block_gen.generate_block_with_blame_info(
1157            num_txs,
1158            block_size_limit,
1159            vec![],
1160            blame_info.blame.map(|x| x.as_u32()),
1161            blame_info.deferred_state_root.map(|x| x.into()),
1162            blame_info.deferred_receipts_root.map(|x| x.into()),
1163            blame_info.deferred_logs_bloom_hash.map(|x| x.into()),
1164        ))
1165    }
1166
1167    fn get_logs(&self, filter: CfxRpcLogFilter) -> CoreResult<Vec<RpcLog>> {
1168        // all addresses specified should be for the correct network
1169        if let Some(addresses) = &filter.address {
1170            for address in addresses.iter() {
1171                invalid_params_check(
1172                    "filter.address",
1173                    check_rpc_address_network(
1174                        Some(address.network),
1175                        self.sync.network.get_network_type(),
1176                    ),
1177                )?;
1178            }
1179        }
1180
1181        let consensus_graph = self.consensus_graph();
1182
1183        info!("RPC Request: cfx_getLogs({:?})", filter);
1184        let filter: LogFilter = filter
1185            .into_primitive()
1186            .map_err(error_object_owned_to_jsonrpc_error)?;
1187
1188        let logs = consensus_graph
1189            .logs(filter)?
1190            .iter()
1191            .cloned()
1192            .map(|l| {
1193                RpcLog::try_from_localized(
1194                    l,
1195                    *self.sync.network.get_network_type(),
1196                )
1197            })
1198            .collect::<Result<Vec<_>, _>>()?;
1199
1200        // If the results does not fit into `max_limit`, report an error
1201        if let Some(max_limit) = self.config.get_logs_filter_max_limit {
1202            if logs.len() > max_limit {
1203                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)));
1204            }
1205        }
1206
1207        Ok(logs)
1208    }
1209
1210    fn get_block_reward_info(
1211        &self, epoch: EpochNumber,
1212    ) -> CoreResult<Vec<RpcRewardInfo>> {
1213        info!(
1214            "RPC Request: cfx_getBlockRewardInfo epoch_number={:?}",
1215            epoch
1216        );
1217        let epoch_height: U64 = self
1218            .consensus_graph()
1219            .get_height_from_epoch_number(epoch.clone().into_primitive())?
1220            .into();
1221        let (epoch_later_number, overflow) =
1222            epoch_height.overflowing_add(REWARD_EPOCH_COUNT.into());
1223        if overflow {
1224            bail!(invalid_params("epoch", "Epoch number overflows!"));
1225        }
1226        let epoch_later = match self.consensus.get_hash_from_epoch_number(
1227            EpochNumber::Num(epoch_later_number).into_primitive(),
1228        ) {
1229            Ok(hash) => hash,
1230            Err(e) => {
1231                debug!("get_block_reward_info: get_hash_from_epoch_number returns error: {}", e);
1232                bail!(invalid_params("epoch", "Reward not calculated yet!"))
1233            }
1234        };
1235
1236        let blocks = self.consensus.get_block_hashes_by_epoch(epoch.into())?;
1237
1238        let mut ret = Vec::new();
1239        for b in blocks {
1240            if let Some(reward_result) = self
1241                .consensus
1242                .data_manager()
1243                .block_reward_result_by_hash_with_epoch(
1244                    &b,
1245                    &epoch_later,
1246                    false, // update_pivot_assumption
1247                    true,  // update_cache
1248                )
1249            {
1250                if let Some(block_header) =
1251                    self.consensus.data_manager().block_header_by_hash(&b)
1252                {
1253                    let author = RpcAddress::try_from_h160(
1254                        *block_header.author(),
1255                        *self.sync.network.get_network_type(),
1256                    )?;
1257
1258                    ret.push(RpcRewardInfo {
1259                        block_hash: b.into(),
1260                        author,
1261                        total_reward: reward_result.total_reward.into(),
1262                        base_reward: reward_result.base_reward.into(),
1263                        tx_fee: reward_result.tx_fee.into(),
1264                    })
1265                }
1266            }
1267        }
1268        Ok(ret)
1269    }
1270
1271    fn call(
1272        &self, request: TransactionRequest,
1273        block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
1274    ) -> CoreResult<Bytes> {
1275        let epoch = Some(
1276            self.get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?,
1277        );
1278        let (execution_outcome, _estimation) =
1279            self.exec_transaction(request, epoch)?;
1280        match execution_outcome {
1281            ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1282                expected,
1283                got,
1284            )) => bail!(call_execution_error(
1285                "Transaction can not be executed".into(),
1286                format! {"nonce is too old expected {:?} got {:?}", expected, got}
1287            )),
1288            ExecutionOutcome::NotExecutedDrop(
1289                TxDropError::InvalidRecipientAddress(recipient),
1290            ) => bail!(call_execution_error(
1291                "Transaction can not be executed".into(),
1292                format! {"invalid recipient address {:?}", recipient}
1293            )),
1294            ExecutionOutcome::NotExecutedDrop(
1295                TxDropError::NotEnoughGasLimit { expected, got },
1296            ) => bail!(call_execution_error(
1297                "Transaction can not be executed".into(),
1298                format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1299            )),
1300            ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1301                address,
1302            )) => bail!(call_execution_error(
1303                "Transaction can not be executed".into(),
1304                format! {"tx sender has contract code: {:?}", address}
1305            )),
1306            ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1307                bail!(call_execution_error(
1308                    "Transaction can not be executed".into(),
1309                    format! {"{:?}", e}
1310                ))
1311            }
1312            ExecutionOutcome::ExecutionErrorBumpNonce(
1313                ExecutionError::VmError(VmError::Reverted),
1314                executed,
1315            ) => bail!(call_execution_error(
1316                "Transaction reverted".into(),
1317                format!("0x{}", executed.output.to_hex::<String>())
1318            )),
1319            ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1320                bail!(call_execution_error(
1321                    "Transaction execution failed".into(),
1322                    format! {"{:?}", e}
1323                ))
1324            }
1325            ExecutionOutcome::Finished(executed) => Ok(executed.output.into()),
1326        }
1327    }
1328
1329    fn estimate_gas_and_collateral(
1330        &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1331    ) -> CoreResult<EstimateGasAndCollateralResponse> {
1332        info!(
1333            "RPC Request: cfx_estimateGasAndCollateral request={:?}, epoch={:?}",request,epoch
1334        );
1335        let (execution_outcome, estimation) =
1336            self.exec_transaction(request, epoch)?;
1337        match execution_outcome {
1338            ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1339                expected,
1340                got,
1341            )) => bail!(call_execution_error(
1342                "Can not estimate: transaction can not be executed".into(),
1343                format! {"nonce is too old expected {:?} got {:?}", expected, got}
1344            )),
1345            ExecutionOutcome::NotExecutedDrop(
1346                TxDropError::InvalidRecipientAddress(recipient),
1347            ) => bail!(call_execution_error(
1348                "Can not estimate: transaction can not be executed".into(),
1349                format! {"invalid recipient address {:?}", recipient}
1350            )),
1351            ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1352                address,
1353            )) => bail!(call_execution_error(
1354                "Can not estimate: transaction sender has code".into(),
1355                format! {"transaction sender has code {:?}", address}
1356            )),
1357            ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1358                bail!(call_execution_error(
1359                    "Can not estimate: transaction can not be executed".into(),
1360                    format! {"{:?}", e}
1361                ))
1362            }
1363            ExecutionOutcome::NotExecutedDrop(
1364                TxDropError::NotEnoughGasLimit { expected, got },
1365            ) => bail!(call_execution_error(
1366                "Can not estimate: transaction can not be executed".into(),
1367                format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1368            )),
1369            ExecutionOutcome::ExecutionErrorBumpNonce(
1370                ExecutionError::VmError(VmError::Reverted),
1371                executed,
1372            ) => {
1373                let network_type = *self.sync.network.get_network_type();
1374                let (revert_error, innermost_error, errors) =
1375                    decode_error(&executed, |addr| {
1376                        RpcAddress::try_from_h160(addr.clone(), network_type)
1377                            .unwrap()
1378                            .base32_address
1379                    });
1380
1381                bail!(call_execution_error(
1382                    format!("Estimation isn't accurate: transaction is reverted{}{}",
1383                        revert_error, innermost_error),
1384                    errors.join("\n"),
1385                ))
1386            }
1387            ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1388                bail!(call_execution_error(
1389                    format! {"Can not estimate: transaction execution failed, \
1390                    all gas will be charged (execution error: {:?})", e}
1391                    .into(),
1392                    format! {"{:?}", e}
1393                ))
1394            }
1395            ExecutionOutcome::Finished(executed) => executed,
1396        };
1397        let storage_collateralized =
1398            U64::from(estimation.estimated_storage_limit);
1399        let estimated_gas_used = estimation.estimated_gas_limit;
1400        let response = EstimateGasAndCollateralResponse {
1401            gas_limit: estimated_gas_used, /* gas_limit used to be 4/3 of
1402                                            * gas_used due to inaccuracy,
1403                                            * currently it's the same as gas
1404                                            * used as it's more accurate */
1405            gas_used: estimated_gas_used,
1406            storage_collateralized,
1407        };
1408        Ok(response)
1409    }
1410
1411    fn check_balance_against_transaction(
1412        &self, account_addr: RpcAddress, contract_addr: RpcAddress,
1413        gas_limit: U256, gas_price: U256, storage_limit: U256,
1414        epoch: Option<EpochNumber>,
1415    ) -> CoreResult<CheckBalanceAgainstTransactionResponse> {
1416        self.check_address_network(account_addr.network)?;
1417        self.check_address_network(contract_addr.network)?;
1418
1419        let epoch: primitives::EpochNumber =
1420            epoch.unwrap_or(EpochNumber::LatestState).into();
1421
1422        info!(
1423            "RPC Request: cfx_checkBalanceAgainstTransaction account_addr={:?} contract_addr={:?} gas_limit={:?} gas_price={:?} storage_limit={:?} epoch={:?}",
1424            account_addr, contract_addr, gas_limit, gas_price, storage_limit, epoch
1425        );
1426
1427        let account_addr = account_addr.hex_address.with_native_space();
1428        let contract_addr = contract_addr.hex_address.with_native_space();
1429
1430        if storage_limit > U256::from(std::u64::MAX) {
1431            bail!(JsonRpcError::invalid_params(format!("storage_limit has to be within the range of u64 but {} supplied!", storage_limit)));
1432        }
1433
1434        let state_db = self
1435            .consensus
1436            .get_state_db_by_epoch_number(epoch, "epoch")?;
1437
1438        let user_account = state_db.get_account(&account_addr)?;
1439        let contract_account = state_db.get_account(&contract_addr)?;
1440        let state = State::new(state_db)?;
1441        let is_sponsored = state.check_contract_whitelist(
1442            &contract_addr.address,
1443            &account_addr.address,
1444        )?;
1445
1446        Ok(common::check_balance_against_transaction(
1447            user_account,
1448            contract_account,
1449            is_sponsored,
1450            gas_limit,
1451            gas_price,
1452            storage_limit,
1453        ))
1454    }
1455
1456    fn exec_transaction(
1457        &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1458    ) -> CoreResult<(ExecutionOutcome, EstimateExt)> {
1459        let rpc_request_network = invalid_params_check(
1460            "request",
1461            check_two_rpc_address_network_match(
1462                request.from.as_ref(),
1463                request.to.as_ref(),
1464            ),
1465        )?;
1466        invalid_params_check(
1467            "request",
1468            check_rpc_address_network(
1469                rpc_request_network,
1470                self.sync.network.get_network_type(),
1471            ),
1472        )?;
1473
1474        let consensus_graph = self.consensus_graph();
1475        let epoch = epoch.unwrap_or(EpochNumber::LatestState);
1476
1477        let estimate_request = EstimateRequest {
1478            has_sender: request.from.is_some(),
1479            has_gas_limit: request.gas.is_some(),
1480            has_gas_price: request.has_gas_price(),
1481            has_nonce: request.nonce.is_some(),
1482            has_storage_limit: request.storage_limit.is_some(),
1483        };
1484
1485        let epoch_height = consensus_graph
1486            .get_height_from_epoch_number(epoch.clone().into())?;
1487        let chain_id = consensus_graph.best_chain_id();
1488        let signed_tx = request
1489            .sign_call(
1490                epoch_height,
1491                chain_id.in_native_space(),
1492                self.config.max_estimation_gas_limit,
1493            )
1494            .map_err(error_object_owned_to_jsonrpc_error)?;
1495        trace!("call tx {:?}", signed_tx);
1496
1497        consensus_graph.call_virtual(
1498            &signed_tx,
1499            epoch.into(),
1500            estimate_request,
1501            Default::default(),
1502        )
1503    }
1504
1505    fn current_sync_phase(&self) -> CoreResult<String> {
1506        Ok(self.sync.current_sync_phase().name().into())
1507    }
1508
1509    /// Return the pivot chain block hashes in `height_range` (inclusive) and
1510    /// their subtree weight. If it's none, return all pivot chain from
1511    /// `cur_era_genesis` to chain tip.
1512    ///
1513    /// Note that this should note query blocks before `cur_era_genesis`.
1514    fn get_pivot_chain_and_weight(
1515        &self, height_range: Option<(u64, u64)>,
1516    ) -> CoreResult<Vec<(H256, U256)>> {
1517        let consensus_graph = self.consensus_graph();
1518        Ok(consensus_graph
1519            .inner
1520            .read()
1521            .get_pivot_chain_and_weight(height_range)?)
1522    }
1523
1524    fn get_executed_info(&self, block_hash: H256) -> CoreResult<(H256, H256)> {
1525        let commitment = self
1526            .consensus
1527            .data_manager()
1528            .get_epoch_execution_commitment(&block_hash)
1529            .ok_or(JsonRpcError::invalid_params(
1530                "No receipts root. Possibly never pivot?".to_owned(),
1531            ))?;
1532        Ok((
1533            commitment.receipts_root.clone().into(),
1534            commitment
1535                .state_root_with_aux_info
1536                .state_root
1537                .compute_state_root_hash(),
1538        ))
1539    }
1540
1541    fn expire_block_gc(&self, timeout: u64) -> CoreResult<()> {
1542        self.sync.expire_block_gc(timeout);
1543        Ok(())
1544    }
1545
1546    pub fn consensus_graph_state(&self) -> CoreResult<ConsensusGraphStates> {
1547        let consensus_graph_states =
1548            STATE_EXPOSER.consensus_graph.lock().retrieve();
1549        // Ok(ConsensusGraphStates::new(consensus_graph_states))
1550        let mut block_state_vec = Vec::new();
1551        let mut block_execution_state_vec = Vec::new();
1552
1553        for block_state in &consensus_graph_states.block_state_vec {
1554            block_state_vec.push(ConsensusGraphBlockState {
1555                block_hash: block_state.block_hash.into(),
1556                best_block_hash: block_state.best_block_hash.into(),
1557                block_status: (block_state.block_status as u8).into(),
1558                era_block_hash: block_state.era_block_hash.into(),
1559                adaptive: block_state.adaptive,
1560            })
1561        }
1562        for exec_state in &consensus_graph_states.block_execution_state_vec {
1563            block_execution_state_vec.push(ConsensusGraphBlockExecutionState {
1564                block_hash: exec_state.block_hash.into(),
1565                deferred_state_root: exec_state.deferred_state_root.into(),
1566                deferred_receipt_root: exec_state.deferred_receipt_root.into(),
1567                deferred_logs_bloom_hash: exec_state
1568                    .deferred_logs_bloom_hash
1569                    .into(),
1570                state_valid: exec_state.state_valid,
1571            })
1572        }
1573
1574        Ok(ConsensusGraphStates {
1575            block_state_vec,
1576            block_execution_state_vec,
1577        })
1578    }
1579
1580    pub fn sync_graph_state(&self) -> CoreResult<SyncGraphStates> {
1581        let sync_graph_states = STATE_EXPOSER.sync_graph.lock().retrieve();
1582        let mut ready_block_vec = Vec::new();
1583        for block_state in sync_graph_states.ready_block_vec {
1584            ready_block_vec.push(SyncGraphBlockState {
1585                block_hash: block_state.block_hash.into(),
1586                parent: block_state.parent.into(),
1587                referees: block_state
1588                    .referees
1589                    .iter()
1590                    .map(|x| H256::from(*x))
1591                    .collect(),
1592                nonce: block_state.nonce.into(),
1593                timestamp: U64::from(block_state.timestamp),
1594                adaptive: block_state.adaptive,
1595            })
1596        }
1597        Ok(SyncGraphStates { ready_block_vec })
1598    }
1599
1600    /// Return (block_info.status, state_valid)
1601    /// Return Error if either field is missing
1602    pub fn get_block_status(&self, block_hash: H256) -> CoreResult<(u8, bool)> {
1603        let consensus_graph = self.consensus_graph();
1604        let status = consensus_graph
1605            .data_man
1606            .local_block_info_by_hash(&block_hash)
1607            // FIXME: invalid_params?
1608            .ok_or(invalid_params("block_hash", "No block status"))?
1609            .get_status();
1610        let state_valid = consensus_graph
1611            .inner
1612            .read()
1613            .block_node(&block_hash)
1614            .ok_or(invalid_params("block_hash", "No block in consensus"))?
1615            .data
1616            .state_valid
1617            .ok_or(invalid_params("block_hash", "No state_valid"))?;
1618        Ok((status.to_db_status(), state_valid))
1619    }
1620
1621    pub fn get_supply_info(
1622        &self, epoch: Option<EpochNumber>,
1623    ) -> CoreResult<TokenSupplyInfo> {
1624        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1625        let state = State::new(
1626            self.consensus
1627                .get_state_db_by_epoch_number(epoch, "epoch")?,
1628        )?;
1629        let total_issued = state.total_issued_tokens();
1630        let total_staking = state.total_staking_tokens();
1631        let total_collateral = state.total_storage_tokens();
1632        let two_year_unlock_address = genesis_contract_address_two_year();
1633        let four_year_unlock_address = genesis_contract_address_four_year();
1634        let two_year_locked = state
1635            .balance(&two_year_unlock_address)
1636            .unwrap_or(U256::zero());
1637        let four_year_locked = state
1638            .balance(&four_year_unlock_address)
1639            .unwrap_or(U256::zero());
1640        let total_circulating =
1641            total_issued - two_year_locked - four_year_locked;
1642        let total_espace_tokens = state.total_espace_tokens();
1643        Ok(TokenSupplyInfo {
1644            total_circulating,
1645            total_issued,
1646            total_staking,
1647            total_collateral,
1648            total_espace_tokens,
1649        })
1650    }
1651
1652    pub fn get_collateral_info(
1653        &self, epoch: Option<EpochNumber>,
1654    ) -> CoreResult<StorageCollateralInfo> {
1655        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1656        let state = State::new(
1657            self.consensus
1658                .get_state_db_by_epoch_number(epoch, "epoch")?,
1659        )?;
1660        let total_storage_tokens = state.total_storage_tokens();
1661        let converted_storage_points = state.converted_storage_points()
1662            / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1663        let used_storage_points =
1664            state.used_storage_points() / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1665        Ok(StorageCollateralInfo {
1666            total_storage_tokens,
1667            converted_storage_points,
1668            used_storage_points,
1669        })
1670    }
1671
1672    pub fn get_vote_params(
1673        &self, epoch: Option<EpochNumber>,
1674    ) -> CoreResult<VoteParamsInfo> {
1675        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1676        let state_db = self
1677            .consensus
1678            .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1679        let interest_rate = state_db.get_global_param::<InterestRate>()?
1680            / U256::from(BLOCKS_PER_YEAR);
1681        let pow_base_reward = state_db.get_global_param::<PowBaseReward>()?;
1682
1683        let storage_point_prop =
1684            state_db.get_system_storage(&storage_point_prop())?;
1685
1686        let base_fee_share_prop = state_db.get_global_param::<BaseFeeProp>()?;
1687        Ok(VoteParamsInfo {
1688            pow_base_reward,
1689            interest_rate,
1690            storage_point_prop,
1691            base_fee_share_prop,
1692        })
1693    }
1694
1695    pub fn get_fee_burnt(
1696        &self, epoch: Option<EpochNumber>,
1697    ) -> CoreResult<U256> {
1698        let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1699        let state_db = self
1700            .consensus
1701            .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1702
1703        Ok(state_db.get_global_param::<TotalBurnt1559>()?)
1704    }
1705
1706    pub fn set_db_crash(
1707        &self, crash_probability: f64, crash_exit_code: i32,
1708    ) -> CoreResult<()> {
1709        if crash_probability == 0.0 {
1710            *CRASH_EXIT_PROBABILITY.lock() = None;
1711        } else {
1712            *CRASH_EXIT_PROBABILITY.lock() = Some(crash_probability);
1713        }
1714        *CRASH_EXIT_CODE.lock() = crash_exit_code;
1715        Ok(())
1716    }
1717
1718    // estimate response size, return error if it is too large
1719    // note: this is a potentially expensive check
1720    fn check_response_size<T: Serialize>(
1721        &self, response: &T,
1722    ) -> CoreResult<()> {
1723        // account for the enclosing JSON object
1724        // {"jsonrpc":"2.0","id":1,"result": ... }
1725        // note: this is a rough estimation
1726        let max_size = self.config.max_payload_bytes - 50;
1727
1728        let payload_size = serde_json::to_vec(&response)
1729            .map_err(|_e| "Unexpected serialization error")?
1730            .len();
1731
1732        if payload_size > max_size {
1733            // TODO(thegaram): should we define a new error type?
1734            bail!(invalid_params(
1735                "epoch",
1736                format!(
1737                    "Oversized payload: size = {}, max = {}",
1738                    payload_size, max_size
1739                )
1740            ));
1741        }
1742
1743        Ok(())
1744    }
1745
1746    fn get_block_epoch_number(&self, h: &H256) -> Option<u64> {
1747        // try to get from memory
1748        if let Some(e) = self.consensus.get_block_epoch_number(h) {
1749            return Some(e);
1750        }
1751
1752        // try to get from db
1753        self.consensus.data_manager().block_epoch_number(h)
1754    }
1755
1756    fn epoch_receipts(
1757        &self, epoch: BlockHashOrEpochNumber, include_eth_receipt: Option<bool>,
1758    ) -> CoreResult<Option<Vec<Vec<RpcReceipt>>>> {
1759        info!("RPC Request: cfx_getEpochReceipts({:?})", epoch);
1760
1761        let hashes = self
1762            .consensus
1763            .get_block_hashes_by_epoch_or_block_hash(epoch.into())?;
1764
1765        let pivot_hash = *hashes.last().ok_or("Inconsistent state")?;
1766        let mut epoch_receipts = vec![];
1767
1768        for h in hashes {
1769            epoch_receipts.push(
1770                match self.prepare_block_receipts(
1771                    h,
1772                    pivot_hash,
1773                    include_eth_receipt.unwrap_or(false),
1774                )? {
1775                    None => return Ok(None), // not executed
1776                    Some(rs) => rs,
1777                },
1778            );
1779        }
1780
1781        // TODO(thegaram): we should only do this on WS, not on HTTP
1782        // how to treat these differently?
1783        self.check_response_size(&epoch_receipts)?;
1784
1785        Ok(Some(epoch_receipts))
1786    }
1787
1788    fn epoch_receipt_proof_by_transaction(
1789        &self, tx_hash: H256,
1790    ) -> JsonRpcResult<Option<EpochReceiptProof>> {
1791        let (block_hash, tx_index_in_block) =
1792            match self.consensus.get_signed_tx_and_tx_info(&tx_hash) {
1793                None => {
1794                    bail!(invalid_params(
1795                        "transactions hash",
1796                        format!(
1797                            "Unable to get transaction info for hash {:?}",
1798                            tx_hash
1799                        )
1800                    ));
1801                }
1802                Some((_, TransactionInfo { tx_index, .. })) => {
1803                    (tx_index.block_hash, tx_index.real_index)
1804                }
1805            };
1806
1807        let epoch = match self.consensus.get_block_epoch_number(&block_hash) {
1808            Some(epoch) => epoch,
1809            None => {
1810                bail!(invalid_params(
1811                    "block hash",
1812                    format!(
1813                        "Unable to get epoch number for block {:?}",
1814                        block_hash
1815                    )
1816                ));
1817            }
1818        };
1819
1820        let epoch_number = primitives::EpochNumber::Number(epoch);
1821        let epoch_hashes = match self
1822            .consensus
1823            .get_block_hashes_by_epoch(epoch_number.clone())
1824        {
1825            Ok(hs) => hs,
1826            Err(e) => {
1827                bail!(invalid_params(
1828                    "block hash",
1829                    format!("Unable to find epoch hashes for {}: {}", epoch, e)
1830                ));
1831            }
1832        };
1833
1834        let block_index_in_epoch =
1835            match epoch_hashes.iter().position(|h| *h == block_hash) {
1836                Some(id) => id,
1837                None => {
1838                    bail!(invalid_params(
1839                        "block hash",
1840                        format!(
1841                            "Unable to find block {:?} in epoch {}",
1842                            block_hash, epoch
1843                        )
1844                    ));
1845                }
1846            };
1847
1848        let pivot = epoch_hashes
1849            .last()
1850            .expect("epoch hashes should be not empty")
1851            .clone();
1852
1853        let epoch_receipts = epoch_hashes
1854            .into_iter()
1855            .map(|h| {
1856                self.consensus
1857                    .data_manager()
1858                    .block_execution_result_by_hash_with_epoch(
1859                        &h, &pivot, false, /* update_pivot_assumption */
1860                        false, /* update_cache */
1861                    )
1862                    .map(|res| Arc::new((*res.block_receipts).clone()))
1863                    .ok_or_else(|| {
1864                        invalid_params(
1865                            "block hash",
1866                            format!("Unable to find recepits for {}", h),
1867                        )
1868                    })
1869            })
1870            .collect::<Result<Vec<_>, _>>()?;
1871
1872        let epoch_receipt_proof = compute_epoch_receipt_proof(
1873            &epoch_receipts,
1874            block_index_in_epoch,
1875            tx_index_in_block,
1876        );
1877
1878        Ok(Some(epoch_receipt_proof))
1879    }
1880
1881    fn stat_on_gas_load(
1882        &self, last_epoch: EpochNumber, time_window: U64,
1883    ) -> CoreResult<Option<StatOnGasLoad>> {
1884        let mut stat = StatOnGasLoad::default();
1885        stat.time_elapsed = time_window;
1886
1887        let block_not_found_error = || {
1888            internal_error_msg(
1889                "Cannot find the block by a ConsensusGraph provided hash",
1890            )
1891        };
1892
1893        let machine = self.tx_pool.machine();
1894        let consensus = self.consensus_graph();
1895
1896        let mut epoch_number = match last_epoch {
1897            EpochNumber::Earliest => {
1898                bail!(invalid_params_msg("Cannot stat genesis"))
1899            }
1900            EpochNumber::Num(num) if num.is_zero() => {
1901                bail!(invalid_params_msg("Cannot stat genesis"))
1902            }
1903            EpochNumber::LatestMined => bail!(invalid_params_msg(
1904                "Epoch number is earilier than 'latest_state'"
1905            )),
1906            EpochNumber::Num(num) => {
1907                let pivot_hash = consensus.get_hash_from_epoch_number(
1908                    primitives::EpochNumber::LatestState,
1909                )?;
1910                let epoch_number = consensus
1911                    .get_block_epoch_number(&pivot_hash)
1912                    .ok_or_else(block_not_found_error)?;
1913                if epoch_number < num.as_u64() {
1914                    bail!(invalid_params_msg(
1915                        "Epoch number is earilier than 'latest_state'"
1916                    ))
1917                }
1918                num.as_u64()
1919            }
1920            EpochNumber::LatestCheckpoint
1921            | EpochNumber::LatestFinalized
1922            | EpochNumber::LatestConfirmed
1923            | EpochNumber::LatestState => {
1924                let pivot_hash =
1925                    consensus.get_hash_from_epoch_number(last_epoch.into())?;
1926                consensus
1927                    .get_block_epoch_number(&pivot_hash)
1928                    .ok_or_else(block_not_found_error)?
1929            }
1930        };
1931
1932        let mut last_timestamp: Option<u64> = None;
1933
1934        loop {
1935            // Step 1: fetch block data
1936            let block_hashes = consensus.get_block_hashes_by_epoch(
1937                primitives::EpochNumber::Number(epoch_number),
1938            )?;
1939            let blocks = consensus
1940                .data_manager()
1941                .blocks_by_hash_list(&block_hashes, false)
1942                .ok_or_else(block_not_found_error)?;
1943            let pivot_block = blocks
1944                .last()
1945                .ok_or(internal_error_msg("Epoch without block"))?;
1946
1947            // Step 2: update timestamp
1948            let timestamp = pivot_block.block_header.timestamp();
1949            if last_timestamp.is_none() {
1950                last_timestamp = Some(timestamp)
1951            }
1952            // Stop if the epoch does not in the query window.
1953            if last_timestamp.unwrap().saturating_sub(time_window.as_u64())
1954                > timestamp
1955            {
1956                break;
1957            }
1958
1959            // Step 3: Stat blocks
1960            let params = machine.params();
1961            stat.epoch_num += 1.into();
1962            for b in &blocks {
1963                stat.total_block_num += 1.into();
1964                stat.total_gas_limit += *b.block_header.gas_limit();
1965                if params.can_pack_evm_transaction(b.block_header.height()) {
1966                    stat.espace_block_num += 1.into();
1967                    stat.espace_gas_limit += *b.block_header.gas_limit()
1968                        / params.evm_transaction_gas_ratio;
1969                }
1970            }
1971
1972            // Step 4: Stat transactions
1973            for b in &blocks {
1974                // Fetch execution info or return not found.
1975                let exec_info =
1976                    match consensus.get_block_execution_info(&b.hash()) {
1977                        None => bail!(internal_error_msg(
1978                        "Cannot fetch block receipt with checked input params"
1979                    )),
1980                        Some((res, _)) => res.1,
1981                    };
1982
1983                for (receipt, tx) in exec_info
1984                    .block_receipts
1985                    .receipts
1986                    .iter()
1987                    .zip(&b.transactions)
1988                {
1989                    let space = tx.space();
1990                    if receipt.outcome_status == TransactionStatus::Skipped {
1991                        *stat.skipped_tx_count.in_space_mut(space) += 1.into();
1992                        *stat.skipped_tx_gas_limit.in_space_mut(space) +=
1993                            *tx.gas_limit();
1994                    } else {
1995                        *stat.confirmed_tx_count.in_space_mut(space) +=
1996                            1.into();
1997                        *stat.confirmed_tx_gas_limit.in_space_mut(space) +=
1998                            *tx.gas_limit();
1999                        *stat.tx_gas_charged.in_space_mut(space) +=
2000                            receipt.gas_fee / tx.gas_price();
2001                    }
2002                }
2003            }
2004
2005            // Goto Next Epoch
2006            if epoch_number > 0 {
2007                epoch_number -= 1;
2008            } else {
2009                break;
2010            }
2011        }
2012        Ok(Some(stat))
2013    }
2014
2015    fn transactions_by_epoch(
2016        &self, epoch_number: U64,
2017    ) -> JsonRpcResult<Vec<WrapTransaction>> {
2018        debug!("debug_getTransactionsByEpoch {}", epoch_number);
2019
2020        let block_hashs = self
2021            .consensus
2022            .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2023                epoch_number.as_u64(),
2024            ))
2025            .map_err(|e| {
2026                JsonRpcError::invalid_params(format!(
2027                    "Could not get block hashes by epoch {}",
2028                    e
2029                ))
2030            })?;
2031
2032        let blocks = match self
2033            .consensus
2034            .data_manager()
2035            .blocks_by_hash_list(&block_hashs, false)
2036        {
2037            None => {
2038                return Err(JsonRpcError::invalid_params(format!(
2039                    "Could not get blocks for hashs {:?}",
2040                    block_hashs
2041                )))
2042            }
2043            Some(b) => b,
2044        };
2045
2046        let pivot = match blocks.last() {
2047            Some(p) => p,
2048            None => {
2049                return Err(JsonRpcError::invalid_params("blocks is empty"))
2050            }
2051        };
2052
2053        self.get_transactions(&blocks, pivot, epoch_number.as_u64())
2054    }
2055
2056    fn transactions_by_block(
2057        &self, block_hash: H256,
2058    ) -> JsonRpcResult<Vec<WrapTransaction>> {
2059        debug!("debug_getTransactionsByBlock {}", block_hash);
2060
2061        let epoch_number = match self.get_block_epoch_number(&block_hash) {
2062            None => {
2063                return Err(JsonRpcError::invalid_params(format!(
2064                    "Counld not get epoch for block {}",
2065                    block_hash
2066                )))
2067            }
2068            Some(n) => n,
2069        };
2070
2071        let block_hashs = self
2072            .consensus
2073            .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2074                epoch_number,
2075            ))
2076            .map_err(|e| {
2077                JsonRpcError::invalid_params(format!(
2078                    "Could not get block hashes by epoch {}",
2079                    e
2080                ))
2081            })?;
2082
2083        let blocks = match self
2084            .consensus
2085            .data_manager()
2086            .blocks_by_hash_list(&block_hashs, false)
2087        {
2088            None => {
2089                return Err(JsonRpcError::invalid_params(format!(
2090                    "Counld not get blocks for hashs {:?}",
2091                    block_hashs
2092                )))
2093            }
2094            Some(b) => b,
2095        };
2096
2097        let pivot = match blocks.last() {
2098            Some(p) => p,
2099            None => {
2100                return Err(JsonRpcError::invalid_params("blocks is empty"))
2101            }
2102        };
2103
2104        let mut block = vec![];
2105        for b in blocks.iter() {
2106            if b.hash() == block_hash {
2107                block.push((*b).clone());
2108                break;
2109            }
2110        }
2111
2112        self.get_transactions(&block, pivot, epoch_number)
2113    }
2114
2115    fn get_transactions(
2116        &self, blocks: &Vec<Arc<Block>>, pivot: &Arc<Block>, epoch_number: u64,
2117    ) -> JsonRpcResult<Vec<WrapTransaction>> {
2118        let mut transactions = vec![];
2119
2120        for b in blocks.into_iter() {
2121            match self.get_transactions_for_block(b, pivot, epoch_number) {
2122                Ok(mut txs) => {
2123                    transactions.append(&mut txs);
2124                }
2125                Err(e) => bail!(internal_error(e)),
2126            };
2127        }
2128
2129        Ok(transactions)
2130    }
2131
2132    fn get_transactions_for_block(
2133        &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2134    ) -> Result<Vec<WrapTransaction>, String> {
2135        let exec_info = self
2136            .consensus
2137            .data_manager()
2138            .block_execution_result_by_hash_with_epoch(
2139                &b.hash(),
2140                &pivot.hash(),
2141                false,
2142                false,
2143            );
2144        if let Some(execution_result) = exec_info {
2145            self.get_transactions_for_executed_block(
2146                b,
2147                pivot,
2148                epoch_number,
2149                execution_result,
2150            )
2151        } else {
2152            self.get_transactions_for_non_executed_block(b, pivot)
2153        }
2154    }
2155
2156    fn get_transactions_for_non_executed_block(
2157        &self, b: &Arc<Block>, pivot: &Arc<Block>,
2158    ) -> Result<Vec<WrapTransaction>, String> {
2159        let network = *self.sync.network.get_network_type();
2160
2161        let mut eth_transaction_idx = 0;
2162        let mut make_eth_wrap_tx = |tx| {
2163            let block_info = (
2164                Some(pivot.hash()),
2165                Some(pivot.block_header.height().into()),
2166                Some(eth_transaction_idx.into()),
2167            );
2168            eth_transaction_idx += 1;
2169            WrapTransaction::EthTransaction(EthTransaction::from_signed(
2170                tx,
2171                block_info,
2172                (None, None),
2173            ))
2174        };
2175
2176        let make_cfx_wrap_tx = |tx| -> Result<WrapTransaction, String> {
2177            Ok(WrapTransaction::NativeTransaction(
2178                RpcTransaction::from_signed(tx, None, network)?,
2179            ))
2180        };
2181
2182        let mut res = vec![];
2183        for (_, tx) in b.transactions.iter().enumerate() {
2184            res.push(match tx.space() {
2185                Space::Ethereum => make_eth_wrap_tx(tx),
2186                Space::Native => make_cfx_wrap_tx(tx)?,
2187            });
2188        }
2189        Ok(res)
2190    }
2191
2192    fn get_transactions_for_executed_block(
2193        &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2194        execution_result: BlockExecutionResult,
2195    ) -> Result<Vec<WrapTransaction>, String> {
2196        let network = *self.sync.network.get_network_type();
2197        let maybe_state_root = self
2198            .consensus
2199            .data_manager()
2200            .get_executed_state_root(&b.hash());
2201        let block_receipts = &execution_result.block_receipts.receipts;
2202
2203        let mut eth_transaction_idx = 0;
2204        let mut make_eth_wrap_tx = |tx, id: usize| {
2205            let receipt = &block_receipts[id];
2206
2207            let status = receipt.outcome_status.in_space(Space::Ethereum);
2208            let contract_address = match status == EVM_SPACE_SUCCESS {
2209                true => EthTransaction::deployed_contract_address(tx),
2210                false => None,
2211            };
2212            let block_info = (
2213                Some(pivot.hash()),
2214                Some(pivot.block_header.height().into()),
2215                Some(eth_transaction_idx.into()),
2216            );
2217            eth_transaction_idx += 1;
2218
2219            WrapTransaction::EthTransaction(EthTransaction::from_signed(
2220                tx,
2221                block_info,
2222                (Some(status.into()), contract_address),
2223            ))
2224        };
2225
2226        let mut cfx_transaction_index = 0;
2227        let mut make_cfx_wrap_tx = |tx, id: usize| -> Result<_, String> {
2228            let receipt = &block_receipts[id];
2229            let prior_gas_used = if id == 0 {
2230                U256::zero()
2231            } else {
2232                block_receipts[id - 1].accumulated_gas_used
2233            };
2234
2235            if receipt.outcome_status == TransactionStatus::Skipped {
2236                cfx_transaction_index += 1;
2237                return Ok(WrapTransaction::NativeTransaction(
2238                    RpcTransaction::from_signed(tx, None, network)?,
2239                ));
2240            }
2241
2242            let tx_index = TransactionIndex {
2243                block_hash: b.hash(),
2244                real_index: id,
2245                is_phantom: false,
2246                rpc_index: Some(cfx_transaction_index),
2247            };
2248            let tx_exec_error_msg = &execution_result
2249                .block_receipts
2250                .tx_execution_error_messages[id];
2251            let receipt = RpcReceipt::new(
2252                tx.clone(),
2253                receipt.clone(),
2254                tx_index,
2255                prior_gas_used,
2256                Some(epoch_number),
2257                execution_result.block_receipts.block_number,
2258                b.block_header.base_price(),
2259                maybe_state_root,
2260                if tx_exec_error_msg.is_empty() {
2261                    None
2262                } else {
2263                    Some(tx_exec_error_msg.clone())
2264                },
2265                network,
2266                false,
2267                false,
2268            )?;
2269            cfx_transaction_index += 1;
2270            let executed = Some(PackedOrExecuted::Executed(receipt));
2271            Ok(WrapTransaction::NativeTransaction(
2272                RpcTransaction::from_signed(tx, executed, network)?,
2273            ))
2274        };
2275
2276        let mut res = vec![];
2277        for (id, tx) in b.transactions.iter().enumerate() {
2278            res.push(match tx.space() {
2279                Space::Ethereum => make_eth_wrap_tx(&**tx, id),
2280                Space::Native => make_cfx_wrap_tx(&**tx, id)?,
2281            })
2282        }
2283
2284        Ok(res)
2285    }
2286}
2287
2288#[allow(dead_code)]
2289pub struct CfxHandler {
2290    common: Arc<CommonImpl>,
2291    rpc_impl: Arc<RpcImpl>,
2292}
2293
2294impl CfxHandler {
2295    pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2296        CfxHandler { common, rpc_impl }
2297    }
2298}
2299
2300impl Cfx for CfxHandler {
2301    delegate! {
2302        to self.common {
2303            fn best_block_hash(&self) -> JsonRpcResult<H256>;
2304            fn block_by_epoch_number(
2305                &self, epoch_num: EpochNumber, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2306            fn block_by_hash_with_pivot_assumption(
2307                &self, block_hash: H256, pivot_hash: H256, epoch_number: U64)
2308                -> BoxFuture<JsonRpcResult<RpcBlock>>;
2309            fn block_by_hash(&self, hash: H256, include_txs: bool)
2310                -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2311            fn block_by_block_number(&self, block_number: U64, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2312            fn confirmation_risk_by_hash(&self, block_hash: H256) -> JsonRpcResult<Option<U256>>;
2313            fn blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2314            fn skipped_blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2315            fn epoch_number(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2316            fn gas_price(&self) -> BoxFuture<JsonRpcResult<U256>>;
2317            fn next_nonce(&self, address: RpcAddress, num: Option<BlockHashOrEpochNumber>)
2318                -> BoxFuture<JsonRpcResult<U256>>;
2319            fn get_status(&self) -> JsonRpcResult<RpcStatus>;
2320            fn get_client_version(&self) -> JsonRpcResult<String>;
2321            fn account_pending_info(&self, addr: RpcAddress) -> BoxFuture<JsonRpcResult<Option<AccountPendingInfo>>>;
2322            fn account_pending_transactions(&self, address: RpcAddress, maybe_start_nonce: Option<U256>, maybe_limit: Option<U64>) -> BoxFuture<JsonRpcResult<AccountPendingTransactions>>;
2323            fn get_pos_reward_by_epoch(&self, epoch: EpochNumber) -> JsonRpcResult<Option<PoSEpochReward>>;
2324            fn fee_history(&self, block_count: HexU64, newest_block: EpochNumber, reward_percentiles: Option<Vec<f64>>) -> BoxFuture<JsonRpcResult<CfxFeeHistory>>;
2325            fn max_priority_fee_per_gas(&self) -> BoxFuture<JsonRpcResult<U256>>;
2326        }
2327
2328        to self.rpc_impl {
2329            fn code(&self, addr: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<Bytes>>;
2330            fn account(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<RpcAccount>>;
2331            fn interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2332            fn accumulate_interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2333            fn pos_economics(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<PoSEconomics>>;
2334            fn admin(&self, address: RpcAddress, num: Option<EpochNumber>)
2335                -> BoxFuture<JsonRpcResult<Option<RpcAddress>>>;
2336            fn sponsor_info(&self, address: RpcAddress, num: Option<EpochNumber>)
2337                -> BoxFuture<JsonRpcResult<SponsorInfo>>;
2338            fn balance(&self, address: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2339            fn staking_balance(&self, address: RpcAddress, num: Option<EpochNumber>)
2340                -> BoxFuture<JsonRpcResult<U256>>;
2341            fn deposit_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<DepositInfo>>>;
2342            fn vote_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<VoteStakeInfo>>>;
2343            fn collateral_for_storage(&self, address: RpcAddress, num: Option<EpochNumber>)
2344                -> BoxFuture<JsonRpcResult<U256>>;
2345            fn call(&self, request: TransactionRequest, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2346                -> JsonRpcResult<Bytes>;
2347            fn estimate_gas_and_collateral(
2348                &self, request: TransactionRequest, epoch_number: Option<EpochNumber>)
2349                -> JsonRpcResult<EstimateGasAndCollateralResponse>;
2350            fn check_balance_against_transaction(
2351                &self, account_addr: RpcAddress, contract_addr: RpcAddress, gas_limit: U256, gas_price: U256, storage_limit: U256, epoch: Option<EpochNumber>,
2352            ) -> BoxFuture<JsonRpcResult<CheckBalanceAgainstTransactionResponse>>;
2353            fn get_logs(&self, filter: CfxRpcLogFilter) -> BoxFuture<JsonRpcResult<Vec<RpcLog>>>;
2354            fn get_block_reward_info(&self, num: EpochNumber) -> JsonRpcResult<Vec<RpcRewardInfo>>;
2355            fn send_raw_transaction(&self, raw: Bytes) -> JsonRpcResult<H256>;
2356            fn storage_at(&self, addr: RpcAddress, pos: U256, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2357                -> BoxFuture<JsonRpcResult<Option<H256>>>;
2358            fn transaction_by_hash(&self, hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcTransaction>>>;
2359            fn transaction_receipt(&self, tx_hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcReceipt>>>;
2360            fn storage_root(&self, address: RpcAddress, epoch_num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Option<StorageRoot>>>;
2361            fn get_supply_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<TokenSupplyInfo>;
2362            fn get_collateral_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<StorageCollateralInfo>;
2363            fn get_vote_params(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<VoteParamsInfo>;
2364            fn get_fee_burnt(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2365        }
2366    }
2367}
2368
2369#[allow(dead_code)]
2370pub struct TestRpcImpl {
2371    common: Arc<CommonImpl>,
2372    rpc_impl: Arc<RpcImpl>,
2373}
2374
2375impl TestRpcImpl {
2376    pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2377        TestRpcImpl { common, rpc_impl }
2378    }
2379}
2380
2381impl TestRpc for TestRpcImpl {
2382    delegate! {
2383        to self.common {
2384            fn add_latency(&self, id: NodeId, latency_ms: f64) -> JsonRpcResult<()>;
2385            fn add_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2386            fn chain(&self) -> JsonRpcResult<Vec<RpcBlock>>;
2387            fn drop_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2388            fn get_block_count(&self) -> JsonRpcResult<u64>;
2389            fn get_goodput(&self) -> JsonRpcResult<String>;
2390            fn get_nodeid(&self, challenge: Vec<u8>) -> JsonRpcResult<Vec<u8>>;
2391            fn get_peer_info(&self) -> JsonRpcResult<Vec<PeerInfo>>;
2392            fn say_hello(&self) -> JsonRpcResult<String>;
2393            fn stop(&self) -> JsonRpcResult<()>;
2394            fn save_node_db(&self) -> JsonRpcResult<()>;
2395            fn pos_register(&self, voting_power: U64, version: Option<u8>) -> JsonRpcResult<(Bytes, AccountAddress)>;
2396            fn pos_update_voting_power(
2397                &self, pos_account: AccountAddress, increased_voting_power: U64,
2398            ) -> JsonRpcResult<()>;
2399            fn pos_stop_election(&self) -> JsonRpcResult<Option<u64>>;
2400            fn pos_start_voting(&self, initialize: bool) -> JsonRpcResult<()>;
2401            fn pos_stop_voting(&self) -> JsonRpcResult<()>;
2402            fn pos_voting_status(&self) -> JsonRpcResult<bool>;
2403            fn pos_start(&self) -> JsonRpcResult<()>;
2404            fn pos_force_vote_proposal(&self, block_id: H256) -> JsonRpcResult<()>;
2405            fn pos_force_propose(&self, round: U64, parent_block_id: H256, payload: Vec<TransactionPayload>) -> JsonRpcResult<()>;
2406            fn pos_trigger_timeout(&self, timeout_type: String) -> JsonRpcResult<()>;
2407            fn pos_force_sign_pivot_decision(&self, block_hash: H256, height: U64) -> JsonRpcResult<()>;
2408            fn pos_get_chosen_proposal(&self) -> JsonRpcResult<Option<PosBlock>>;
2409        }
2410
2411        to self.rpc_impl {
2412            fn expire_block_gc(&self, timeout: u64) -> JsonRpcResult<()>;
2413            fn generate_block_with_blame_info(
2414                &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo) -> JsonRpcResult<H256>;
2415            fn generate_block_with_fake_txs(
2416                &self, raw_txs_without_data: Bytes, adaptive: Option<bool>, tx_data_len: Option<usize>)
2417                -> JsonRpcResult<H256>;
2418            fn generate_custom_block(
2419                &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes, adaptive: Option<bool>, custom: Option<Vec<Bytes>>)
2420                -> JsonRpcResult<H256>;
2421            fn get_pivot_chain_and_weight(&self, height_range: Option<(u64, u64)>) -> JsonRpcResult<Vec<(H256, U256)>>;
2422            fn get_executed_info(&self, block_hash: H256) -> JsonRpcResult<(H256, H256)> ;
2423            fn generate_fixed_block(
2424                &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize, adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>)
2425                -> JsonRpcResult<H256>;
2426            fn generate_one_block_with_direct_txgen(
2427                &self, num_txs: usize, block_size_limit: usize, num_txs_simple: usize, num_txs_erc20: usize)
2428                -> JsonRpcResult<H256>;
2429            fn generate_one_block(&self, num_txs: usize, block_size_limit: usize) -> JsonRpcResult<H256>;
2430            fn generate_block_with_nonce_and_timestamp(
2431                &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256, timestamp: u64, adaptive: bool)
2432                -> JsonRpcResult<H256>;
2433            fn generate_empty_blocks(&self, num_blocks: usize) -> JsonRpcResult<Vec<H256>>;
2434            fn get_block_status(&self, block_hash: H256) -> JsonRpcResult<(u8, bool)>;
2435            fn send_usable_genesis_accounts(& self, account_start_index: usize) -> JsonRpcResult<Bytes>;
2436            fn set_db_crash(&self, crash_probability: f64, crash_exit_code: i32) -> JsonRpcResult<()>;
2437        }
2438    }
2439}
2440
2441pub struct LocalRpcImpl {
2442    common: Arc<CommonImpl>,
2443    rpc_impl: Arc<RpcImpl>,
2444}
2445
2446impl LocalRpcImpl {
2447    pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2448        LocalRpcImpl { common, rpc_impl }
2449    }
2450}
2451
2452impl LocalRpc for LocalRpcImpl {
2453    delegate! {
2454        to self.common {
2455            fn txpool_content(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2456                BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<RpcTransaction>>>>>;
2457            fn txpool_inspect(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2458                BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<String>>>>>;
2459            fn txpool_get_account_transactions(&self, address: RpcAddress) -> JsonRpcResult<Vec<RpcTransaction>>;
2460            fn txpool_clear(&self) -> JsonRpcResult<()>;
2461            fn net_node(&self, id: NodeId) -> JsonRpcResult<Option<(String, Node)>>;
2462            fn net_disconnect_node(&self, id: NodeId, op: Option<UpdateNodeOperation>)
2463                -> JsonRpcResult<bool>;
2464            fn net_sessions(&self, node_id: Option<NodeId>) -> JsonRpcResult<Vec<SessionDetails>>;
2465            fn net_throttling(&self) -> JsonRpcResult<throttling::Service>;
2466            fn accounts(&self) -> JsonRpcResult<Vec<RpcAddress>>;
2467            fn new_account(&self, password: String) -> JsonRpcResult<RpcAddress>;
2468            fn unlock_account(
2469                &self, address: RpcAddress, password: String, duration: Option<U128>)
2470                -> JsonRpcResult<bool>;
2471            fn lock_account(&self, address: RpcAddress) -> JsonRpcResult<bool>;
2472            fn sign(&self, data: Bytes, address: RpcAddress, password: Option<String>)
2473                -> JsonRpcResult<H520>;
2474
2475        }
2476
2477        to self.rpc_impl {
2478            fn current_sync_phase(&self) -> JsonRpcResult<String>;
2479            fn consensus_graph_state(&self) -> JsonRpcResult<ConsensusGraphStates>;
2480            fn epoch_receipts(&self, epoch: BlockHashOrEpochNumber, include_eth_recepits: Option<bool>,) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;
2481            fn epoch_receipt_proof_by_transaction(&self, tx_hash: H256) -> JsonRpcResult<Option<EpochReceiptProof>>;
2482            fn stat_on_gas_load(&self, last_epoch: EpochNumber, time_window: U64) -> JsonRpcResult<Option<StatOnGasLoad>>;
2483            fn sync_graph_state(&self) -> JsonRpcResult<SyncGraphStates>;
2484            fn send_transaction(
2485                &self, tx: TransactionRequest, password: Option<String>) -> BoxFuture<JsonRpcResult<H256>>;
2486            fn sign_transaction(&self, tx: TransactionRequest, password: Option<String>) -> JsonRpcResult<String>;
2487            fn transactions_by_epoch(&self, epoch_number: U64) -> JsonRpcResult<Vec<WrapTransaction>>;
2488            fn transactions_by_block(&self, block_hash: H256) -> JsonRpcResult<Vec<WrapTransaction>>;
2489        }
2490    }
2491}