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,
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
200impl 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 );
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 )
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 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 );
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 if block_hash == genesis && (pivot_hash != genesis || epoch_number != 0)
409 {
410 bail!(RpcError::invalid_params("pivot chain assumption failed"));
411 }
412
413 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 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 )
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 )
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 );
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 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 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 );
566 if let Some(block) = maybe_block {
567 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 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 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
648impl 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 )
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 )
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 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 )
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 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 + 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 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 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 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 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
1048impl 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 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() });
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
1460fn 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}