1use 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
132impl 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 );
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 )
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 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 );
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 if block_hash == genesis && (pivot_hash != genesis || epoch_number != 0)
338 {
339 bail!(RpcError::invalid_params("pivot chain assumption failed"));
340 }
341
342 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 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 )
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 )
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 );
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 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 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 );
495 if let Some(block) = maybe_block {
496 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 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 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
577impl 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 )
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 )
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 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 )
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 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 + 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 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 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 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 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
977impl 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 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() });
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}