client/rpc/impls/cfx/
common.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 cfx_util_macros::bail;
6use std::{
7    collections::{BTreeMap, HashSet},
8    net::SocketAddr,
9    sync::Arc,
10    time::Duration,
11};
12
13use crate::rpc::{
14    errors::invalid_params_check,
15    helpers::{build_block, MAX_FEE_HISTORY_CACHE_BLOCK_COUNT},
16    impls::pos::{convert_to_pos_epoch_reward, hash_value_to_h256},
17    types::{
18        cfx::check_rpc_address_network, pos::PoSEpochReward,
19        AccountPendingInfo, AccountPendingTransactions, Block as RpcBlock,
20        BlockHashOrEpochNumber, Bytes, CfxFeeHistory,
21        CheckBalanceAgainstTransactionResponse, EpochNumber, FeeHistory,
22        RpcAddress, Status as RpcStatus, Transaction as RpcTransaction,
23        TxPoolPendingNonceRange, TxPoolStatus, TxWithPoolInfo, U64 as HexU64,
24    },
25    CoreResult,
26};
27use log::{debug, info, warn};
28
29use bigdecimal::BigDecimal;
30use jsonrpc_core::{
31    Error as RpcError, Result as JsonRpcResult, Value as RpcValue,
32};
33use keccak_hash::keccak;
34use num_bigint::{BigInt, ToBigInt};
35use parking_lot::{Condvar, Mutex};
36
37use crate::rpc::types::pos::{Block as RpcPosBlock, Decision};
38use cfx_addr::Network;
39use cfx_parameters::{
40    rpc::GAS_PRICE_DEFAULT_VALUE, staking::DRIPS_PER_STORAGE_COLLATERAL_UNIT,
41};
42use cfx_rpc_utils::error::jsonrpc_error_helpers::internal_rpc_err;
43use cfx_types::{
44    Address, AddressSpaceUtil, Space, H160, H256, H520, U128, U256, U512, U64,
45};
46use cfxcore::{
47    consensus::pos_handler::PosVerifier, errors::Error as CoreError,
48    genesis_block::register_transaction, BlockDataManager, ConsensusGraph,
49    PeerInfo, SharedConsensusGraph, SharedTransactionPool,
50};
51use cfxcore_accounts::AccountProvider;
52use cfxkey::Password;
53use diem_crypto::hash::HashValue;
54use diem_types::{
55    account_address::{from_consensus_public_key, AccountAddress},
56    block_info::PivotBlockDecision,
57    transaction::TransactionPayload,
58};
59use network::{
60    node_table::{Node, NodeEndpoint, NodeEntry, NodeId},
61    throttling::{self, THROTTLING_SERVICE},
62    NetworkService, SessionDetails, UpdateNodeOperation,
63};
64use primitives::{Account, Action, Block, SignedTransaction, Transaction};
65use storage_interface::DBReaderForPoW;
66
67fn grouped_txs<T, F>(
68    txs: Vec<Arc<SignedTransaction>>, converter: F,
69) -> BTreeMap<String, BTreeMap<usize, Vec<T>>>
70where F: Fn(Arc<SignedTransaction>) -> T {
71    let mut addr_grouped_txs: BTreeMap<String, BTreeMap<usize, Vec<T>>> =
72        BTreeMap::new();
73
74    for tx in txs {
75        let addr = format!("{:?}", tx.sender());
76        let addr_entry: &mut BTreeMap<usize, Vec<T>> =
77            addr_grouped_txs.entry(addr).or_insert(BTreeMap::new());
78
79        let nonce = tx.nonce().as_usize();
80        let nonce_entry: &mut Vec<T> =
81            addr_entry.entry(nonce).or_insert(Vec::new());
82
83        nonce_entry.push(converter(tx));
84    }
85
86    addr_grouped_txs
87}
88
89pub fn check_balance_against_transaction(
90    user_account: Option<Account>, contract_account: Option<Account>,
91    is_sponsored: bool, gas_limit: U256, gas_price: U256, storage_limit: U256,
92) -> CheckBalanceAgainstTransactionResponse {
93    let sponsor_for_gas = contract_account
94        .as_ref()
95        .map(|a| a.sponsor_info.sponsor_for_gas)
96        .unwrap_or_default();
97
98    let gas_bound: U512 = contract_account
99        .as_ref()
100        .map(|a| a.sponsor_info.sponsor_gas_bound)
101        .unwrap_or_default()
102        .into();
103
104    let balance_for_gas: U512 = contract_account
105        .as_ref()
106        .map(|a| a.sponsor_info.sponsor_balance_for_gas)
107        .unwrap_or_default()
108        .into();
109
110    let sponsor_for_collateral = contract_account
111        .as_ref()
112        .map(|a| a.sponsor_info.sponsor_for_collateral)
113        .unwrap_or_default();
114
115    let balance_for_collateral: U512 = contract_account
116        .as_ref()
117        .map(|a| {
118            a.sponsor_info.sponsor_balance_for_collateral
119                + a.sponsor_info.unused_storage_points()
120        })
121        .unwrap_or_default()
122        .into();
123
124    let user_balance: U512 =
125        user_account.map(|a| a.balance).unwrap_or_default().into();
126
127    let gas_cost_in_drip = gas_limit.full_mul(gas_price);
128
129    let will_pay_tx_fee = !is_sponsored
130        || sponsor_for_gas.is_zero()
131        || (gas_cost_in_drip > gas_bound)
132        || (gas_cost_in_drip > balance_for_gas);
133
134    let storage_cost_in_drip =
135        storage_limit.full_mul(*DRIPS_PER_STORAGE_COLLATERAL_UNIT);
136
137    let will_pay_collateral = !is_sponsored
138        || sponsor_for_collateral.is_zero()
139        || (storage_cost_in_drip > balance_for_collateral);
140
141    let minimum_balance = match (will_pay_tx_fee, will_pay_collateral) {
142        (false, false) => 0.into(),
143        (true, false) => gas_cost_in_drip,
144        (false, true) => storage_cost_in_drip,
145        (true, true) => gas_cost_in_drip + storage_cost_in_drip,
146    };
147
148    let is_balance_enough = user_balance >= minimum_balance;
149
150    CheckBalanceAgainstTransactionResponse {
151        will_pay_tx_fee,
152        will_pay_collateral,
153        is_balance_enough,
154    }
155}
156
157pub struct RpcImpl {
158    exit: Arc<(Mutex<bool>, Condvar)>,
159    consensus: SharedConsensusGraph,
160    data_man: Arc<BlockDataManager>,
161    network: Arc<NetworkService>,
162    tx_pool: SharedTransactionPool,
163    accounts: Arc<AccountProvider>,
164    pub pos_handler: Arc<PosVerifier>,
165}
166
167impl RpcImpl {
168    pub fn new(
169        exit: Arc<(Mutex<bool>, Condvar)>, consensus: SharedConsensusGraph,
170        network: Arc<NetworkService>, tx_pool: SharedTransactionPool,
171        accounts: Arc<AccountProvider>, pos_verifier: Arc<PosVerifier>,
172    ) -> Self {
173        let data_man = consensus.data_manager().clone();
174
175        RpcImpl {
176            exit,
177            consensus,
178            data_man,
179            network,
180            tx_pool,
181            accounts,
182            pos_handler: pos_verifier,
183        }
184    }
185
186    fn consensus_graph(&self) -> &ConsensusGraph { &self.consensus }
187
188    fn check_address_network(&self, network: Network) -> CoreResult<()> {
189        invalid_params_check(
190            "address",
191            check_rpc_address_network(
192                Some(network),
193                self.network.get_network_type(),
194            ),
195        )
196        .map_err(|e| e.into())
197    }
198}
199
200// Cfx RPC implementation
201impl RpcImpl {
202    pub fn best_block_hash(&self) -> JsonRpcResult<H256> {
203        info!("RPC Request: cfx_getBestBlockHash()");
204        Ok(self.consensus.best_block_hash().into())
205    }
206
207    pub fn gas_price(&self) -> CoreResult<U256> {
208        let consensus_graph = self.consensus_graph();
209        info!("RPC Request: cfx_gasPrice()");
210        let consensus_gas_price = consensus_graph
211            .gas_price(Space::Native)
212            .unwrap_or(GAS_PRICE_DEFAULT_VALUE.into())
213            .into();
214        Ok(std::cmp::max(
215            consensus_gas_price,
216            self.tx_pool.config.min_native_tx_price.into(),
217        ))
218    }
219
220    pub fn epoch_number(
221        &self, epoch_num: Option<EpochNumber>,
222    ) -> JsonRpcResult<U256> {
223        let consensus_graph = self.consensus_graph();
224        let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestMined);
225        info!("RPC Request: cfx_epochNumber({:?})", epoch_num);
226        match consensus_graph.get_height_from_epoch_number(epoch_num.into()) {
227            Ok(height) => Ok(height.into()),
228            Err(e) => Err(RpcError::invalid_params(e)),
229        }
230    }
231
232    pub fn block_by_epoch_number(
233        &self, epoch_num: EpochNumber, include_txs: bool,
234    ) -> CoreResult<Option<RpcBlock>> {
235        info!("RPC Request: cfx_getBlockByEpochNumber epoch_number={:?} include_txs={:?}", epoch_num, include_txs);
236        let consensus_graph = self.consensus_graph();
237        let inner = &*consensus_graph.inner.read();
238
239        let epoch_height = consensus_graph
240            .get_height_from_epoch_number(epoch_num.into())
241            .map_err(RpcError::invalid_params)?;
242
243        let pivot_hash = inner
244            .get_pivot_hash_from_epoch_number(epoch_height)
245            .map_err(RpcError::invalid_params)?;
246
247        let maybe_block = self
248            .data_man
249            .block_by_hash(&pivot_hash, false /* update_cache */);
250        match maybe_block {
251            None => Ok(None),
252            Some(b) => Ok(Some(build_block(
253                &*b,
254                *self.network.get_network_type(),
255                consensus_graph,
256                inner,
257                &self.data_man,
258                include_txs,
259                Some(Space::Native),
260            )?)),
261        }
262    }
263
264    fn primitive_block_by_epoch_number(
265        &self, epoch_num: EpochNumber,
266    ) -> Option<Arc<Block>> {
267        let consensus_graph = self.consensus_graph();
268        let inner = &*consensus_graph.inner.read();
269        let epoch_height = consensus_graph
270            .get_height_from_epoch_number(epoch_num.into())
271            .ok()?;
272
273        let pivot_hash =
274            inner.get_pivot_hash_from_epoch_number(epoch_height).ok()?;
275
276        self.data_man
277            .block_by_hash(&pivot_hash, false /* update_cache */)
278    }
279
280    pub fn get_pos_reward_by_epoch(
281        &self, epoch: EpochNumber,
282    ) -> JsonRpcResult<Option<PoSEpochReward>> {
283        let maybe_block = self.primitive_block_by_epoch_number(epoch);
284        if maybe_block.is_none() {
285            return Ok(None);
286        }
287        let block = maybe_block.unwrap();
288        if block.block_header.pos_reference().is_none() {
289            return Ok(None);
290        }
291        match self
292            .data_man
293            .block_by_hash(block.block_header.parent_hash(), false)
294        {
295            None => Ok(None),
296            Some(parent_block) => {
297                if parent_block.block_header.pos_reference().is_none() {
298                    return Ok(None);
299                }
300                let block_pos_ref = block.block_header.pos_reference().unwrap();
301                let parent_pos_ref =
302                    parent_block.block_header.pos_reference().unwrap();
303
304                if block_pos_ref == parent_pos_ref {
305                    return Ok(None);
306                }
307
308                let hash = HashValue::from_slice(parent_pos_ref.as_bytes())
309                    .map_err(|_| RpcError::internal_error())?;
310                let pos_block = self
311                    .pos_handler
312                    .pos_ledger_db()
313                    .get_committed_block_by_hash(&hash)
314                    .map_err(|_| RpcError::internal_error())?;
315                let maybe_epoch_rewards =
316                    self.data_man.pos_reward_by_pos_epoch(pos_block.epoch);
317                if maybe_epoch_rewards.is_none() {
318                    return Ok(None);
319                }
320                let epoch_rewards = maybe_epoch_rewards.unwrap();
321                if epoch_rewards.execution_epoch_hash
322                    != block.block_header.hash()
323                {
324                    return Ok(None);
325                }
326                let reward_info: PoSEpochReward = convert_to_pos_epoch_reward(
327                    epoch_rewards,
328                    *self.network.get_network_type(),
329                )
330                .map_err(|_| RpcError::internal_error())?;
331                Ok(Some(reward_info))
332            }
333        }
334    }
335
336    pub fn confirmation_risk_by_hash(
337        &self, block_hash: H256,
338    ) -> JsonRpcResult<Option<U256>> {
339        let consensus_graph = self.consensus_graph();
340        let inner = &*consensus_graph.inner.read();
341        let result = consensus_graph
342            .confirmation_meter
343            .confirmation_risk_by_hash(inner, block_hash.into());
344        if result.is_none() {
345            Ok(None)
346        } else {
347            let risk: BigDecimal = result.unwrap().into();
348            let scale = BigInt::parse_bytes(b"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16).expect("failed to unwrap U256::max into bigInt");
349
350            //TODO: there's a precision problem here, it should be fine under a
351            // (2^256 - 1) scale
352            let scaled_risk: BigInt = (risk * scale)
353                .to_bigint()
354                .expect("failed to convert scaled risk to bigInt");
355            let (sign, big_endian_bytes) = scaled_risk.to_bytes_be();
356            assert_ne!(sign, num_bigint::Sign::Minus);
357            let rpc_result = U256::from(big_endian_bytes.as_slice());
358            Ok(Some(rpc_result.into()))
359        }
360    }
361
362    pub fn block_by_hash(
363        &self, hash: H256, include_txs: bool,
364    ) -> CoreResult<Option<RpcBlock>> {
365        let consensus_graph = self.consensus_graph();
366        let hash: H256 = hash.into();
367        info!(
368            "RPC Request: cfx_getBlockByHash hash={:?} include_txs={:?}",
369            hash, include_txs
370        );
371
372        let inner = &*consensus_graph.inner.read();
373
374        let maybe_block =
375            self.data_man.block_by_hash(&hash, false /* update_cache */);
376
377        match maybe_block {
378            None => Ok(None),
379            Some(b) => Ok(Some(build_block(
380                &*b,
381                *self.network.get_network_type(),
382                consensus_graph,
383                inner,
384                &self.data_man,
385                include_txs,
386                Some(Space::Native),
387            )?)),
388        }
389    }
390
391    pub fn block_by_hash_with_pivot_assumption(
392        &self, block_hash: H256, pivot_hash: H256, epoch_number: U64,
393    ) -> CoreResult<RpcBlock> {
394        let consensus_graph = self.consensus_graph();
395        let inner = &*consensus_graph.inner.read();
396        let block_hash: H256 = block_hash.into();
397        let pivot_hash: H256 = pivot_hash.into();
398        let epoch_number = epoch_number.as_usize() as u64;
399
400        info!(
401            "RPC Request: cfx_getBlockByHashWithPivotAssumption block_hash={:?} pivot_hash={:?} epoch_number={:?}",
402            block_hash, pivot_hash, epoch_number
403        );
404
405        let genesis = self.consensus.data_manager().true_genesis.hash();
406
407        // for genesis, check criteria directly
408        if block_hash == genesis && (pivot_hash != genesis || epoch_number != 0)
409        {
410            bail!(RpcError::invalid_params("pivot chain assumption failed"));
411        }
412
413        // `block_hash` must match `epoch_number`
414        if block_hash != genesis
415            && (consensus_graph.get_block_epoch_number(&block_hash)
416                != epoch_number.into())
417        {
418            bail!(RpcError::invalid_params("pivot chain assumption failed"));
419        }
420
421        // `pivot_hash` must match `epoch_number`
422        inner
423            .check_block_pivot_assumption(&pivot_hash, epoch_number)
424            .map_err(RpcError::invalid_params)?;
425
426        let block = self
427            .data_man
428            .block_by_hash(&block_hash, false /* update_cache */)
429            .ok_or_else(|| RpcError::invalid_params("Block not found"))?;
430
431        debug!("Build RpcBlock {}", block.hash());
432        Ok(build_block(
433            &*block,
434            *self.network.get_network_type(),
435            consensus_graph,
436            inner,
437            &self.data_man,
438            true,
439            Some(Space::Native),
440        )?)
441    }
442
443    pub fn block_by_block_number(
444        &self, block_number: U64, include_txs: bool,
445    ) -> CoreResult<Option<RpcBlock>> {
446        let block_number = block_number.as_u64();
447        let consensus_graph = self.consensus_graph();
448
449        info!(
450            "RPC Request: cfx_getBlockByBlockNumber hash={:?} include_txs={:?}",
451            block_number, include_txs
452        );
453
454        let inner = &*consensus_graph.inner.read();
455
456        let block_hash = match self
457            .data_man
458            .hash_by_block_number(block_number, true /* update cache */)
459        {
460            None => return Ok(None),
461            Some(h) => h,
462        };
463
464        let maybe_block = self
465            .data_man
466            .block_by_hash(&block_hash, false /* update_cache */);
467
468        match maybe_block {
469            None => Ok(None),
470            Some(b) => Ok(Some(build_block(
471                &*b,
472                *self.network.get_network_type(),
473                consensus_graph,
474                inner,
475                &self.data_man,
476                include_txs,
477                Some(Space::Native),
478            )?)),
479        }
480    }
481
482    pub fn blocks_by_epoch(
483        &self, num: EpochNumber,
484    ) -> JsonRpcResult<Vec<H256>> {
485        info!("RPC Request: cfx_getBlocksByEpoch epoch_number={:?}", num);
486
487        self.consensus
488            .get_block_hashes_by_epoch(num.into())
489            .map_err(RpcError::invalid_params)
490            .and_then(|vec| Ok(vec.into_iter().map(|x| x.into()).collect()))
491    }
492
493    pub fn skipped_blocks_by_epoch(
494        &self, num: EpochNumber,
495    ) -> JsonRpcResult<Vec<H256>> {
496        info!(
497            "RPC Request: cfx_getSkippedBlocksByEpoch epoch_number={:?}",
498            num
499        );
500
501        self.consensus
502            .get_skipped_block_hashes_by_epoch(num.into())
503            .map_err(RpcError::invalid_params)
504            .and_then(|vec| Ok(vec.into_iter().map(|x| x.into()).collect()))
505    }
506
507    pub fn next_nonce(
508        &self, address: RpcAddress, num: Option<BlockHashOrEpochNumber>,
509    ) -> CoreResult<U256> {
510        self.check_address_network(address.network)?;
511        let consensus_graph = self.consensus_graph();
512
513        let num = num.unwrap_or(BlockHashOrEpochNumber::EpochNumber(
514            EpochNumber::LatestState,
515        ));
516
517        info!(
518            "RPC Request: cfx_getNextNonce address={:?} epoch_num={:?}",
519            address, num
520        );
521
522        // TODO: check if address is not in reserved address space.
523        // We pass "num" into next_nonce() function for the error reporting
524        // rpc_param_name because the user passed epoch number could be invalid.
525        consensus_graph.next_nonce(
526            address.hex_address.with_native_space(),
527            num.into(),
528            "num",
529        )
530    }
531
532    pub fn fee_history(
533        &self, mut block_count: HexU64, newest_block: EpochNumber,
534        reward_percentiles: Option<Vec<f64>>,
535    ) -> CoreResult<CfxFeeHistory> {
536        if newest_block == EpochNumber::LatestMined {
537            return Err(RpcError::invalid_params(
538                "newestBlock cannot be 'LatestMined'",
539            )
540            .into());
541        }
542
543        info!(
544            "RPC Request: cfx_feeHistory: block_count={}, newest_block={:?}, reward_percentiles={:?}",
545            block_count, newest_block, reward_percentiles
546        );
547
548        if block_count.as_u64() == 0 {
549            return Ok(FeeHistory::new().into());
550        }
551
552        if block_count.as_u64() > MAX_FEE_HISTORY_CACHE_BLOCK_COUNT {
553            block_count = HexU64::from(MAX_FEE_HISTORY_CACHE_BLOCK_COUNT);
554        }
555        // keep read lock to ensure consistent view
556        let inner = self.consensus_graph().inner.read();
557
558        let fetch_block = |height| {
559            let pivot_hash = inner
560                .get_pivot_hash_from_epoch_number(height)
561                .map_err(RpcError::invalid_params)?;
562
563            let maybe_block = self
564                .data_man
565                .block_by_hash(&pivot_hash, false /* update_cache */);
566            if let Some(block) = maybe_block {
567                // Internal error happens only if the fetch header has
568                // inconsistent block height
569                Ok(block)
570            } else {
571                Err(internal_rpc_err("Specified block header does not exist"))
572            }
573        };
574
575        let start_height: u64 = self
576            .consensus_graph()
577            .get_height_from_epoch_number(newest_block.into())
578            .map_err(RpcError::invalid_params)?;
579
580        let reward_percentiles = reward_percentiles.unwrap_or_default();
581        let mut current_height = start_height;
582
583        let mut fee_history = FeeHistory::new();
584        while current_height
585            >= start_height.saturating_sub(block_count.as_u64() - 1)
586        {
587            let block = fetch_block(current_height)?;
588
589            let transactions = block
590                .transactions
591                .iter()
592                .filter(|tx| tx.space() == Space::Native)
593                .map(|x| &**x);
594
595            // Internal error happens only if the fetch header has inconsistent
596            // block height
597            fee_history
598                .push_front_block(
599                    Space::Native,
600                    &reward_percentiles,
601                    &block.block_header,
602                    transactions,
603                )
604                .map_err(|_| RpcError::internal_error())?;
605
606            if current_height == 0 {
607                break;
608            } else {
609                current_height -= 1;
610            }
611        }
612
613        // Fetch the block after the last block in the history
614        let block = fetch_block(start_height + 1)?;
615        let oldest_block = if current_height == 0 {
616            0
617        } else {
618            current_height + 1
619        };
620        fee_history.finish(
621            oldest_block,
622            block.block_header.base_price().as_ref(),
623            Space::Native,
624        );
625
626        Ok(fee_history.into())
627    }
628
629    pub fn max_priority_fee_per_gas(&self) -> CoreResult<U256> {
630        info!("RPC Request: max_priority_fee_per_gas",);
631
632        let fee_history = self.fee_history(
633            HexU64::from(300),
634            EpochNumber::LatestState,
635            Some(vec![50f64]),
636        )?;
637
638        let total_reward: U256 = fee_history
639            .reward()
640            .iter()
641            .map(|x| x.first().unwrap())
642            .fold(U256::zero(), |x, y| x + *y);
643
644        Ok(total_reward / 300)
645    }
646}
647
648// Test RPC implementation
649impl RpcImpl {
650    pub fn add_latency(
651        &self, id: NodeId, latency_ms: f64,
652    ) -> JsonRpcResult<()> {
653        match self.network.add_latency(id, latency_ms) {
654            Ok(_) => Ok(()),
655            Err(_) => Err(RpcError::internal_error()),
656        }
657    }
658
659    pub fn add_peer(
660        &self, node_id: NodeId, address: SocketAddr,
661    ) -> JsonRpcResult<()> {
662        let node = NodeEntry {
663            id: node_id,
664            endpoint: NodeEndpoint {
665                address,
666                udp_port: address.port(),
667            },
668        };
669        info!("RPC Request: add_peer({:?})", node.clone());
670        match self.network.add_peer(node) {
671            Ok(_x) => Ok(()),
672            Err(_) => Err(RpcError::internal_error()),
673        }
674    }
675
676    pub fn chain(&self) -> CoreResult<Vec<RpcBlock>> {
677        info!("RPC Request: test_getChain");
678        let consensus_graph = self.consensus_graph();
679        let inner = &*consensus_graph.inner.read();
680
681        let construct_block = |hash| {
682            let block = self
683                .data_man
684                .block_by_hash(hash, false /* update_cache */)
685                .expect("Error to get block by hash");
686
687            build_block(
688                &*block,
689                *self.network.get_network_type(),
690                consensus_graph,
691                inner,
692                &self.data_man,
693                true,
694                Some(Space::Native),
695            )
696        };
697
698        Ok(inner
699            .all_blocks_with_topo_order()
700            .iter()
701            .map(construct_block)
702            .collect::<Result<_, _>>()?)
703    }
704
705    pub fn drop_peer(
706        &self, node_id: NodeId, address: SocketAddr,
707    ) -> JsonRpcResult<()> {
708        let node = NodeEntry {
709            id: node_id,
710            endpoint: NodeEndpoint {
711                address,
712                udp_port: address.port(),
713            },
714        };
715        info!("RPC Request: drop_peer({:?})", node.clone());
716        match self.network.drop_peer(node) {
717            Ok(_) => Ok(()),
718            Err(_) => Err(RpcError::internal_error()),
719        }
720    }
721
722    pub fn get_block_count(&self) -> JsonRpcResult<u64> {
723        info!("RPC Request: get_block_count()");
724        let count = self.consensus.block_count();
725        info!("RPC Response: get_block_count={}", count);
726        Ok(count)
727    }
728
729    pub fn get_goodput(&self) -> JsonRpcResult<String> {
730        let consensus_graph = self.consensus_graph();
731        info!("RPC Request: get_goodput");
732        let mut all_block_set = HashSet::new();
733        for epoch_number in 1..consensus_graph.best_epoch_number() {
734            for block_hash in consensus_graph
735                .get_block_hashes_by_epoch(epoch_number.into())
736                .map_err(|_| RpcError::internal_error())?
737            {
738                all_block_set.insert(block_hash);
739            }
740        }
741        let mut set = HashSet::new();
742        let mut min = std::u64::MAX;
743        let mut max: u64 = 0;
744        for key in &all_block_set {
745            if let Some(block) =
746                self.data_man.block_by_hash(key, false /* update_cache */)
747            {
748                let timestamp = block.block_header.timestamp();
749                if timestamp < min && timestamp > 0 {
750                    min = timestamp;
751                }
752                if timestamp > max {
753                    max = timestamp;
754                }
755                for transaction in &block.transactions {
756                    set.insert(transaction.hash());
757                }
758            }
759        }
760        if max != min {
761            //get goodput for the range (30%, 80%)
762            let lower_bound = min + ((max - min) as f64 * 0.3) as u64;
763            let upper_bound = min + ((max - min) as f64 * 0.8) as u64;
764            let mut ranged_set = HashSet::new();
765            for key in &all_block_set {
766                if let Some(block) = self
767                    .data_man
768                    .block_by_hash(key, false /* update_cache */)
769                {
770                    let timestamp = block.block_header.timestamp();
771                    if timestamp > lower_bound && timestamp < upper_bound {
772                        for transaction in &block.transactions {
773                            ranged_set.insert(transaction.hash());
774                        }
775                    }
776                }
777            }
778            if upper_bound != lower_bound {
779                Ok(format!(
780                    "full: {}, ranged: {}",
781                    set.len() as isize / (max - min) as isize,
782                    ranged_set.len() as isize
783                        / (upper_bound - lower_bound) as isize
784                ))
785            } else {
786                Ok(format!(
787                    "full: {}",
788                    set.len() as isize / (max - min) as isize
789                ))
790            }
791        } else {
792            Ok("-1".to_string())
793        }
794    }
795
796    pub fn get_nodeid(&self, challenge: Vec<u8>) -> JsonRpcResult<Vec<u8>> {
797        match self.network.sign_challenge(challenge) {
798            Ok(r) => Ok(r),
799            Err(_) => Err(RpcError::internal_error()),
800        }
801    }
802
803    pub fn get_peer_info(&self) -> JsonRpcResult<Vec<PeerInfo>> {
804        info!("RPC Request: get_peer_info");
805        match self.network.get_peer_info() {
806            None => Ok(Vec::new()),
807            Some(peers) => Ok(peers),
808        }
809    }
810
811    pub fn get_status(&self) -> CoreResult<RpcStatus> {
812        let consensus_graph = self.consensus_graph();
813
814        let (best_info, block_number) = {
815            // keep read lock to maintain consistent view
816            let _inner = &*consensus_graph.inner.read();
817
818            let best_info = self.consensus.best_info();
819
820            let block_number = self
821                .consensus
822                .get_block_number(&best_info.best_block_hash)?
823                .ok_or("block_number is missing for best_hash")?
824                // The returned block_number of `best_hash` does not include `best_hash` itself.
825                + 1;
826
827            (best_info, block_number)
828        };
829
830        let tx_count = self.tx_pool.total_unpacked();
831
832        let latest_checkpoint = consensus_graph
833            .get_height_from_epoch_number(EpochNumber::LatestCheckpoint.into())?
834            .into();
835
836        let latest_confirmed = consensus_graph
837            .get_height_from_epoch_number(EpochNumber::LatestConfirmed.into())?
838            .into();
839
840        let latest_state = consensus_graph
841            .get_height_from_epoch_number(EpochNumber::LatestState.into())?
842            .into();
843
844        let latest_finalized = consensus_graph
845            .get_height_from_epoch_number(EpochNumber::LatestFinalized.into())?
846            .into();
847
848        Ok(RpcStatus {
849            best_hash: best_info.best_block_hash.into(),
850            block_number: block_number.into(),
851            chain_id: best_info.chain_id.in_native_space().into(),
852            ethereum_space_chain_id: best_info
853                .chain_id
854                .in_space(Space::Ethereum)
855                .into(),
856            epoch_number: best_info.best_epoch_number.into(),
857            latest_checkpoint,
858            latest_confirmed,
859            latest_finalized,
860            latest_state,
861            network_id: self.network.network_id().into(),
862            pending_tx_number: tx_count.into(),
863        })
864    }
865
866    pub fn say_hello(&self) -> JsonRpcResult<String> {
867        Ok("Hello, world".into())
868    }
869
870    pub fn stop(&self) -> JsonRpcResult<()> {
871        *self.exit.0.lock() = true;
872        self.exit.1.notify_all();
873
874        Ok(())
875    }
876
877    pub fn pos_register(
878        &self, voting_power: U64, version: Option<u8>,
879    ) -> JsonRpcResult<(Bytes, AccountAddress)> {
880        let legacy = version.map_or(false, |x| x == 0);
881        let tx = register_transaction(
882            self.pos_handler.config().bls_key.private_key(),
883            self.pos_handler.config().vrf_key.public_key(),
884            voting_power.as_u64(),
885            0,
886            legacy,
887        );
888        let identifier = from_consensus_public_key(
889            &self.pos_handler.config().bls_key.public_key(),
890            &self.pos_handler.config().vrf_key.public_key(),
891        );
892        Ok((tx.data.into(), identifier))
893    }
894
895    pub fn pos_update_voting_power(
896        &self, _pos_account: AccountAddress, _increased_voting_power: U64,
897    ) -> JsonRpcResult<()> {
898        unimplemented!()
899    }
900
901    pub fn pos_stop_election(&self) -> JsonRpcResult<Option<u64>> {
902        self.pos_handler.stop_election().map_err(|e| {
903            warn!("stop_election: err={:?}", e);
904            RpcError::internal_error().into()
905        })
906    }
907
908    pub fn pos_start_voting(&self, initialize: bool) -> CoreResult<()> {
909        info!("RPC Request: pos_start_voting, initialize={}", initialize);
910        self.pos_handler.start_voting(initialize).map_err(|e| {
911            warn!("start_voting: err={:?}", e);
912            CoreError::Custom(e.to_string())
913        })
914    }
915
916    pub fn pos_stop_voting(&self) -> CoreResult<()> {
917        info!("RPC Request: pos_stop_voting");
918        self.pos_handler.stop_voting().map_err(|e| {
919            warn!("stop_voting: err={:?}", e);
920            CoreError::Custom(e.to_string())
921        })
922    }
923
924    pub fn pos_voting_status(&self) -> CoreResult<bool> {
925        self.pos_handler.voting_status().map_err(|e| {
926            warn!("voting_status: err={:?}", e);
927            CoreError::Custom(e.to_string())
928        })
929    }
930
931    pub fn pos_start(&self) -> CoreResult<()> {
932        self.pos_handler.initialize(self.consensus.clone())?;
933        Ok(())
934    }
935
936    pub fn pos_force_vote_proposal(&self, block_id: H256) -> CoreResult<()> {
937        if !self.network.is_test_mode() {
938            // Reject force vote if test RPCs are enabled in a mainnet node,
939            // because this may cause staked CFXs locked
940            // permanently.
941            bail!(RpcError::internal_error())
942        }
943        self.pos_handler.force_vote_proposal(block_id).map_err(|e| {
944            warn!("force_vote_proposal: err={:?}", e);
945            RpcError::internal_error().into()
946        })
947    }
948
949    pub fn pos_force_propose(
950        &self, round: U64, parent_block_id: H256,
951        payload: Vec<TransactionPayload>,
952    ) -> CoreResult<()> {
953        if !self.network.is_test_mode() {
954            // Reject force vote if test RPCs are enabled in a mainnet node,
955            // because this may cause staked CFXs locked
956            // permanently.
957            bail!(RpcError::internal_error())
958        }
959        self.pos_handler
960            .force_propose(round, parent_block_id, payload)
961            .map_err(|e| {
962                warn!("pos_force_propose: err={:?}", e);
963                RpcError::internal_error().into()
964            })
965    }
966
967    pub fn pos_trigger_timeout(&self, timeout_type: String) -> CoreResult<()> {
968        if !self.network.is_test_mode() {
969            // Reject force vote if test RPCs are enabled in a mainnet node,
970            // because this may cause staked CFXs locked
971            // permanently.
972            bail!(RpcError::internal_error())
973        }
974        debug!("pos_trigger_timeout: type={}", timeout_type);
975        self.pos_handler.trigger_timeout(timeout_type).map_err(|e| {
976            warn!("pos_trigger_timeout: err={:?}", e);
977            RpcError::internal_error().into()
978        })
979    }
980
981    pub fn pos_force_sign_pivot_decision(
982        &self, block_hash: H256, height: U64,
983    ) -> CoreResult<()> {
984        if !self.network.is_test_mode() {
985            // Reject force vote if test RPCs are enabled in a mainnet node,
986            // because this may cause staked CFXs locked
987            // permanently.
988            bail!(RpcError::internal_error())
989        }
990        self.pos_handler
991            .force_sign_pivot_decision(PivotBlockDecision {
992                block_hash,
993                height: height.as_u64(),
994            })
995            .map_err(|e| {
996                warn!("pos_trigger_timeout: err={:?}", e);
997                RpcError::internal_error().into()
998            })
999    }
1000
1001    pub fn pos_get_chosen_proposal(&self) -> CoreResult<Option<RpcPosBlock>> {
1002        let maybe_block = self
1003            .pos_handler
1004            .get_chosen_proposal()
1005            .map_err(|e| {
1006                warn!("pos_get_chosen_proposal: err={:?}", e);
1007                RpcError::internal_error()
1008            })?
1009            .and_then(|b| {
1010                let block_hash = b.id();
1011                self.pos_handler
1012                    .cached_db()
1013                    .get_block(&block_hash)
1014                    .ok()
1015                    .map(|executed_block| {
1016                        let executed_block = executed_block.lock();
1017                        RpcPosBlock {
1018                            hash: hash_value_to_h256(b.id()),
1019                            epoch: U64::from(b.epoch()),
1020                            round: U64::from(b.round()),
1021                            last_tx_number: executed_block
1022                                .output()
1023                                .version()
1024                                .unwrap_or_default()
1025                                .into(),
1026                            miner: b.author().map(|a| H256::from(a.to_u8())),
1027                            parent_hash: hash_value_to_h256(b.parent_id()),
1028                            timestamp: U64::from(b.timestamp_usecs()),
1029                            pivot_decision: executed_block
1030                                .output()
1031                                .pivot_block()
1032                                .as_ref()
1033                                .map(|d| Decision::from(d)),
1034                            height: executed_block
1035                                .output()
1036                                .executed_trees()
1037                                .pos_state()
1038                                .current_view()
1039                                .into(),
1040                            signatures: vec![],
1041                        }
1042                    })
1043            });
1044        Ok(maybe_block)
1045    }
1046}
1047
1048// Debug RPC implementation
1049impl RpcImpl {
1050    pub fn txpool_clear(&self) -> JsonRpcResult<()> {
1051        self.tx_pool.clear_tx_pool();
1052        Ok(())
1053    }
1054
1055    pub fn net_node(
1056        &self, id: NodeId,
1057    ) -> JsonRpcResult<Option<(String, Node)>> {
1058        match self.network.get_node(&id) {
1059            None => Ok(None),
1060            Some((trusted, node)) => {
1061                if trusted {
1062                    Ok(Some(("trusted".into(), node)))
1063                } else {
1064                    Ok(Some(("untrusted".into(), node)))
1065                }
1066            }
1067        }
1068    }
1069
1070    pub fn net_disconnect_node(
1071        &self, id: NodeId, op: Option<UpdateNodeOperation>,
1072    ) -> JsonRpcResult<bool> {
1073        Ok(self.network.disconnect_node(&id, op))
1074    }
1075
1076    pub fn net_sessions(
1077        &self, node_id: Option<NodeId>,
1078    ) -> JsonRpcResult<Vec<SessionDetails>> {
1079        match self.network.get_detailed_sessions(node_id) {
1080            None => Ok(Vec::new()),
1081            Some(sessions) => Ok(sessions),
1082        }
1083    }
1084
1085    pub fn net_throttling(&self) -> JsonRpcResult<throttling::Service> {
1086        Ok(THROTTLING_SERVICE.read().clone())
1087    }
1088
1089    // MARK: Conflux space rpc supports EVM space transaction
1090    pub fn txpool_tx_with_pool_info(
1091        &self, hash: H256,
1092    ) -> JsonRpcResult<TxWithPoolInfo> {
1093        let mut ret = TxWithPoolInfo::default();
1094        let hash: H256 = hash.into();
1095        if let Some(tx) = self.tx_pool.get_transaction(&hash) {
1096            ret.exist = true;
1097            if self.tx_pool.check_tx_packed_in_deferred_pool(&hash) {
1098                ret.packed = true;
1099            }
1100            let (local_nonce, local_balance) =
1101                self.tx_pool.get_local_account_info(&tx.sender());
1102            let (state_nonce, state_balance) = self
1103                .tx_pool
1104                .get_state_account_info(&tx.sender())
1105                .map_err(|e| {
1106                    let mut rpc_error = RpcError::internal_error();
1107                    rpc_error.data = Some(RpcValue::String(format!("{}", e)));
1108                    rpc_error
1109                })?;
1110            let required_storage_collateral =
1111                if let Transaction::Native(ref tx) = tx.unsigned {
1112                    U256::from(*tx.storage_limit())
1113                        * *DRIPS_PER_STORAGE_COLLATERAL_UNIT
1114                } else {
1115                    U256::zero()
1116                };
1117            let required_balance = tx.value()
1118                + tx.gas() * tx.gas_price()
1119                + required_storage_collateral;
1120            ret.local_balance_enough = local_balance > required_balance;
1121            ret.state_balance_enough = state_balance > required_balance;
1122            ret.local_balance = local_balance;
1123            ret.local_nonce = local_nonce;
1124            ret.state_balance = state_balance;
1125            ret.state_nonce = state_nonce;
1126        }
1127        Ok(ret)
1128    }
1129
1130    pub fn txpool_get_account_transactions(
1131        &self, address: RpcAddress,
1132    ) -> CoreResult<Vec<RpcTransaction>> {
1133        self.check_address_network(address.network)?;
1134        let (ready_txs, deferred_txs) = self
1135            .tx_pool
1136            .content(Some(Address::from(address).with_native_space()));
1137        let converter =
1138            |tx: &Arc<SignedTransaction>| -> Result<RpcTransaction, String> {
1139                RpcTransaction::from_signed(
1140                    &tx,
1141                    None,
1142                    *self.network.get_network_type(),
1143                )
1144            };
1145        let result = ready_txs
1146            .iter()
1147            .map(converter)
1148            .chain(deferred_txs.iter().map(converter))
1149            .collect::<Result<_, _>>()?;
1150        return Ok(result);
1151    }
1152
1153    pub fn txpool_transaction_by_address_and_nonce(
1154        &self, address: RpcAddress, nonce: U256,
1155    ) -> CoreResult<Option<RpcTransaction>> {
1156        let tx = self
1157            .tx_pool
1158            .get_transaction_by_address2nonce(
1159                Address::from(address).with_native_space(),
1160                nonce,
1161            )
1162            .map(|tx| {
1163                RpcTransaction::from_signed(
1164                    &tx,
1165                    None,
1166                    *self.network.get_network_type(),
1167                )
1168                .unwrap() // TODO check the unwrap()
1169            });
1170        Ok(tx)
1171    }
1172
1173    pub fn txpool_content(
1174        &self, address: Option<RpcAddress>,
1175    ) -> CoreResult<
1176        BTreeMap<
1177            String,
1178            BTreeMap<String, BTreeMap<usize, Vec<RpcTransaction>>>,
1179        >,
1180    > {
1181        let address: Option<H160> = match address {
1182            None => None,
1183            Some(addr) => {
1184                self.check_address_network(addr.network)?;
1185                Some(addr.into())
1186            }
1187        };
1188
1189        let (ready_txs, deferred_txs) = self
1190            .tx_pool
1191            .content(address.map(AddressSpaceUtil::with_native_space));
1192        let converter = |tx: Arc<SignedTransaction>| -> RpcTransaction {
1193            RpcTransaction::from_signed(&tx, None, *self.network.get_network_type())
1194                .expect("transaction conversion with correct network id should not fail")
1195        };
1196
1197        let mut ret: BTreeMap<
1198            String,
1199            BTreeMap<String, BTreeMap<usize, Vec<RpcTransaction>>>,
1200        > = BTreeMap::new();
1201        ret.insert("ready".into(), grouped_txs(ready_txs, converter));
1202        ret.insert("deferred".into(), grouped_txs(deferred_txs, converter));
1203
1204        Ok(ret)
1205    }
1206
1207    pub fn txpool_inspect(
1208        &self, address: Option<RpcAddress>,
1209    ) -> CoreResult<
1210        BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<String>>>>,
1211    > {
1212        let address: Option<H160> = match address {
1213            None => None,
1214            Some(addr) => {
1215                self.check_address_network(addr.network)?;
1216                Some(addr.into())
1217            }
1218        };
1219
1220        let (ready_txs, deferred_txs) = self
1221            .tx_pool
1222            .content(address.map(AddressSpaceUtil::with_native_space));
1223        let converter = |tx: Arc<SignedTransaction>| -> String {
1224            let to = match tx.action() {
1225                Action::Create => "<Create contract>".into(),
1226                Action::Call(addr) => format!("{:?}", addr),
1227            };
1228
1229            format!(
1230                "{}: {:?} drip + {:?} gas * {:?} drip",
1231                to,
1232                tx.value(),
1233                tx.gas(),
1234                tx.gas_price()
1235            )
1236        };
1237
1238        let mut ret: BTreeMap<
1239            String,
1240            BTreeMap<String, BTreeMap<usize, Vec<String>>>,
1241        > = BTreeMap::new();
1242        ret.insert("ready".into(), grouped_txs(ready_txs, converter));
1243        ret.insert("deferred".into(), grouped_txs(deferred_txs, converter));
1244
1245        Ok(ret)
1246    }
1247
1248    pub fn txpool_status(&self) -> JsonRpcResult<TxPoolStatus> {
1249        let (ready_len, deferred_len, received_len, unexecuted_len) =
1250            self.tx_pool.stats();
1251
1252        Ok(TxPoolStatus {
1253            deferred: U64::from(deferred_len),
1254            ready: U64::from(ready_len),
1255            received: U64::from(received_len),
1256            unexecuted: U64::from(unexecuted_len),
1257        })
1258    }
1259
1260    pub fn accounts(&self) -> CoreResult<Vec<RpcAddress>> {
1261        let accounts: Vec<Address> = self.accounts.accounts().map_err(|e| {
1262            format!("Could not fetch accounts. With error {:?}", e)
1263        })?;
1264
1265        Ok(accounts
1266            .into_iter()
1267            .map(|addr| {
1268                RpcAddress::try_from_h160(
1269                    addr,
1270                    *self.network.get_network_type(),
1271                )
1272            })
1273            .collect::<Result<_, _>>()?)
1274    }
1275
1276    pub fn new_account(&self, password: String) -> CoreResult<RpcAddress> {
1277        let address =
1278            self.accounts.new_account(&password.into()).map_err(|e| {
1279                format!("Could not create account. With error {:?}", e)
1280            })?;
1281
1282        Ok(RpcAddress::try_from_h160(
1283            address,
1284            *self.network.get_network_type(),
1285        )?)
1286    }
1287
1288    pub fn unlock_account(
1289        &self, address: RpcAddress, password: String, duration: Option<U128>,
1290    ) -> CoreResult<bool> {
1291        self.check_address_network(address.network)?;
1292        let account: H160 = address.into();
1293        let store = self.accounts.clone();
1294
1295        let duration = match duration {
1296            None => None,
1297            Some(duration) => {
1298                let duration: U128 = duration.into();
1299                let v = duration.low_u64() as u32;
1300                if duration != v.into() {
1301                    bail!(RpcError::invalid_params("invalid duration number",));
1302                } else {
1303                    Some(v)
1304                }
1305            }
1306        };
1307
1308        let r = match duration {
1309            Some(0) => {
1310                store.unlock_account_permanently(account, password.into())
1311            }
1312            Some(d) => store.unlock_account_timed(
1313                account,
1314                password.into(),
1315                Duration::from_secs(d.into()),
1316            ),
1317            None => store.unlock_account_timed(
1318                account,
1319                password.into(),
1320                Duration::from_secs(300),
1321            ),
1322        };
1323        match r {
1324            Ok(_) => Ok(true),
1325            Err(err) => {
1326                warn!("Unable to unlock the account. With error {:?}", err);
1327                bail!(RpcError::internal_error())
1328            }
1329        }
1330    }
1331
1332    pub fn lock_account(&self, address: RpcAddress) -> CoreResult<bool> {
1333        self.check_address_network(address.network)?;
1334        match self.accounts.lock_account(address.into()) {
1335            Ok(_) => Ok(true),
1336            Err(err) => {
1337                warn!("Unable to lock the account. With error {:?}", err);
1338                bail!(RpcError::internal_error())
1339            }
1340        }
1341    }
1342
1343    pub fn sign(
1344        &self, data: Bytes, address: RpcAddress, password: Option<String>,
1345    ) -> CoreResult<H520> {
1346        self.check_address_network(address.network)?;
1347
1348        let message = eth_data_hash(data.0);
1349        let password = password.map(Password::from);
1350        let signature =
1351            match self.accounts.sign(address.into(), password, message) {
1352                Ok(signature) => signature,
1353                Err(err) => {
1354                    warn!("Unable to sign the message. With error {:?}", err);
1355                    bail!(RpcError::internal_error());
1356                }
1357            };
1358        Ok(H520(signature.into()))
1359    }
1360
1361    pub fn save_node_db(&self) -> JsonRpcResult<()> {
1362        self.network.save_node_db();
1363        Ok(())
1364    }
1365
1366    pub fn get_client_version(&self) -> JsonRpcResult<String> {
1367        Ok(parity_version::conflux_client_version!())
1368    }
1369
1370    pub fn txpool_pending_nonce_range(
1371        &self, address: RpcAddress,
1372    ) -> CoreResult<TxPoolPendingNonceRange> {
1373        self.check_address_network(address.network)?;
1374
1375        let mut ret = TxPoolPendingNonceRange::default();
1376        let (pending_txs, _, _) =
1377            self.tx_pool.get_account_pending_transactions(
1378                &address.hex_address.with_native_space(),
1379                None,
1380                None,
1381                self.consensus.best_epoch_number(),
1382            )?;
1383        let mut max_nonce: U256 = U256::from(0);
1384        let mut min_nonce: U256 = U256::max_value();
1385        for tx in pending_txs.iter() {
1386            if *tx.nonce() > max_nonce {
1387                max_nonce = *tx.nonce();
1388            }
1389            if *tx.nonce() < min_nonce {
1390                min_nonce = *tx.nonce();
1391            }
1392        }
1393        ret.min_nonce = min_nonce;
1394        ret.max_nonce = max_nonce;
1395        Ok(ret)
1396    }
1397
1398    pub fn txpool_next_nonce(&self, address: RpcAddress) -> CoreResult<U256> {
1399        Ok(self
1400            .tx_pool
1401            .get_next_nonce(&address.hex_address.with_native_space()))
1402    }
1403
1404    pub fn account_pending_info(
1405        &self, address: RpcAddress,
1406    ) -> CoreResult<Option<AccountPendingInfo>> {
1407        info!("RPC Request: cfx_getAccountPendingInfo({:?})", address);
1408        self.check_address_network(address.network)?;
1409
1410        match self.tx_pool.get_account_pending_info(
1411            &Address::from(address).with_native_space(),
1412        ) {
1413            None => Ok(None),
1414            Some((
1415                local_nonce,
1416                pending_count,
1417                pending_nonce,
1418                next_pending_tx,
1419            )) => Ok(Some(AccountPendingInfo {
1420                local_nonce: local_nonce.into(),
1421                pending_count: pending_count.into(),
1422                pending_nonce: pending_nonce.into(),
1423                next_pending_tx: next_pending_tx.into(),
1424            })),
1425        }
1426    }
1427
1428    pub fn account_pending_transactions(
1429        &self, address: RpcAddress, maybe_start_nonce: Option<U256>,
1430        maybe_limit: Option<U64>,
1431    ) -> CoreResult<AccountPendingTransactions> {
1432        info!("RPC Request: cfx_getAccountPendingTransactions(addr={:?}, start_nonce={:?}, limit={:?})",
1433              address, maybe_start_nonce, maybe_limit);
1434        self.check_address_network(address.network)?;
1435
1436        let (pending_txs, tx_status, pending_count) =
1437            self.tx_pool.get_account_pending_transactions(
1438                &Address::from(address).with_native_space(),
1439                maybe_start_nonce,
1440                maybe_limit.map(|limit| limit.as_usize()),
1441                self.consensus.best_epoch_number(),
1442            )?;
1443        Ok(AccountPendingTransactions {
1444            pending_transactions: pending_txs
1445                .into_iter()
1446                .map(|tx| {
1447                    RpcTransaction::from_signed(
1448                        &tx,
1449                        None,
1450                        *self.network.get_network_type(),
1451                    )
1452                })
1453                .collect::<Result<Vec<RpcTransaction>, String>>()?,
1454            first_tx_status: tx_status,
1455            pending_count: pending_count.into(),
1456        })
1457    }
1458}
1459
1460/// Returns a eth_sign-compatible hash of data to sign.
1461/// The data is prepended with special message to prevent
1462/// malicious DApps from using the function to sign forged transactions.
1463fn eth_data_hash(mut data: Vec<u8>) -> H256 {
1464    let mut message_data =
1465        format!("\x19Ethereum Signed Message:\n{}", data.len()).into_bytes();
1466    message_data.append(&mut data);
1467    keccak(message_data)
1468}