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