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