1use std::{sync::Arc, thread, time::Duration};
6
7use async_trait::async_trait;
8use bigdecimal::BigDecimal;
9use blockgen::BlockGeneratorTestApi;
10use cfx_addr::Network;
11use cfx_execute_helper::estimation::{
12 decode_error, EstimateExt, EstimateRequest,
13};
14use cfx_executor::{
15 executive::{ExecutionError, ExecutionOutcome, TxDropError},
16 internal_contract::storage_point_prop,
17 state::State,
18};
19use cfx_parameters::{
20 consensus_internal::REWARD_EPOCH_COUNT,
21 genesis::{
22 genesis_contract_address_four_year, genesis_contract_address_two_year,
23 },
24 rpc::GAS_PRICE_DEFAULT_VALUE,
25 staking::{BLOCKS_PER_YEAR, DRIPS_PER_STORAGE_COLLATERAL_UNIT},
26};
27use cfx_rpc_cfx_api::{CfxDebugRpcServer, CfxRpcServer};
28use cfx_rpc_cfx_types::{
29 address::{check_rpc_address_network, check_two_rpc_address_network_match},
30 pos::PoSEpochReward,
31 receipt::Receipt as RpcReceipt,
32 transaction::PackedOrExecuted,
33 Account as RpcAccount, AccountPendingInfo, AccountPendingTransactions,
34 Block as RpcBlock, BlockHashOrEpochNumber, Bytes, CfxFeeHistory,
35 CfxRpcLogFilter, CheckBalanceAgainstTransactionResponse, EpochNumber,
36 EstimateGasAndCollateralResponse, Log as RpcLog, PoSEconomics,
37 RewardInfo as RpcRewardInfo, RpcAddress, RpcImplConfiguration, SponsorInfo,
38 Status as RpcStatus, StorageCollateralInfo, TokenSupplyInfo,
39 Transaction as RpcTransaction, TransactionRequest, VoteParamsInfo,
40};
41use cfx_rpc_eth_types::FeeHistory;
42use cfx_rpc_primitives::U64 as HexU64;
43use cfx_rpc_utils::error::jsonrpsee_error_helpers::{
44 call_execution_error, internal_error, internal_error_with_data,
45 invalid_params, invalid_params_check, invalid_params_detail,
46 invalid_params_msg, invalid_params_rpc_err, pivot_assumption_failed,
47 request_rejected_in_catch_up_mode,
48};
49use cfx_statedb::{
50 global_params::{
51 AccumulateInterestRate, BaseFeeProp, DistributablePoSInterest,
52 InterestRate, LastDistributeBlock, PowBaseReward, TotalBurnt1559,
53 TotalPosStaking,
54 },
55 StateDbExt,
56};
57use cfx_storage::state::StateDbGetOriginalMethods;
58use cfx_types::{
59 Address, AddressSpaceUtil, BigEndianHash, Space, H160, H256, H520, U128,
60 U256, U64,
61};
62use cfx_util_macros::bail;
63use cfx_vm_types::Error as VmError;
64use cfxcore::{
65 block_data_manager::BlockDataManager,
66 consensus::{
67 pos_handler::PosVerifier, MaybeExecutedTxExtraInfo, TransactionInfo,
68 },
69 consensus_parameters::DEFERRED_STATE_EPOCH_COUNT,
70 errors::{
71 account_result_to_rpc_result, Error as CoreError, Result as CoreResult,
72 },
73 ConsensusGraph, SharedConsensusGraph, SharedSynchronizationService,
74 SharedTransactionPool,
75};
76use cfxcore_accounts::AccountProvider;
77use cfxkey::Password;
78use diem_crypto::hash::HashValue;
79use jsonrpsee::{core::RpcResult, types::ErrorObjectOwned};
80use log::{debug, info, trace, warn};
81use num_bigint::{BigInt, ToBigInt};
82use primitives::{
83 filter::LogFilter, Account, Block, BlockHeader, BlockReceipts, DepositInfo,
84 EpochNumber as PrimitiveEpochNumber, StorageKey, StorageRoot, StorageValue,
85 TransactionIndex, TransactionStatus, TransactionWithSignature,
86 VoteStakeInfo,
87};
88use rustc_hex::ToHex;
89use storage_interface::DBReaderForPoW;
90
91use crate::{
92 eth_data_hash, helpers::build_block,
93 pos_handler::convert_to_pos_epoch_reward,
94};
95
96fn into_rpc_err<E>(e: E) -> ErrorObjectOwned
97where CoreError: From<E> {
98 ErrorObjectOwned::from(CoreError::from(e))
99}
100
101#[derive(Debug)]
103struct BlockExecInfo {
104 block_receipts: Arc<BlockReceipts>,
105 block: Arc<Block>,
106 epoch_number: u64,
107 maybe_state_root: Option<H256>,
108 pivot_header: Arc<BlockHeader>,
109}
110
111pub struct CfxHandler {
112 pub config: RpcImplConfiguration,
113 pub consensus: SharedConsensusGraph,
114 pub sync: SharedSynchronizationService,
115 pub tx_pool: SharedTransactionPool,
116 pub accounts: Arc<AccountProvider>,
117 pub data_man: Arc<BlockDataManager>,
118 pub network_type: Network,
119 pub pos_handler: Arc<PosVerifier>,
120 block_gen: BlockGeneratorTestApi,
121}
122
123impl CfxHandler {
124 pub fn new(
125 config: RpcImplConfiguration, consensus: SharedConsensusGraph,
126 sync: SharedSynchronizationService, tx_pool: SharedTransactionPool,
127 accounts: Arc<AccountProvider>, pos_handler: Arc<PosVerifier>,
128 block_gen: BlockGeneratorTestApi,
129 ) -> Self {
130 let data_man = consensus.data_manager().clone();
131 let network_type = *sync.network.get_network_type();
132 CfxHandler {
133 config,
134 consensus,
135 sync,
136 tx_pool,
137 accounts,
138 data_man,
139 network_type,
140 pos_handler,
141 block_gen,
142 }
143 }
144
145 fn consensus_graph(&self) -> &ConsensusGraph { &self.consensus }
146
147 fn check_address_network(&self, network: Network) -> RpcResult<()> {
148 invalid_params_check(
149 "address",
150 check_rpc_address_network(Some(network), &self.network_type),
151 )
152 }
153
154 fn get_epoch_number_with_pivot_check(
155 &self, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
156 ) -> CoreResult<EpochNumber> {
157 match block_hash_or_epoch_number {
158 Some(BlockHashOrEpochNumber::BlockHashWithOption {
159 hash,
160 require_pivot,
161 }) => {
162 let epoch_number = self
163 .consensus_graph()
164 .get_block_epoch_number_with_pivot_check(
165 &hash,
166 require_pivot.unwrap_or(true),
167 )?;
168 Ok(EpochNumber::Num(U64::from(epoch_number)))
169 }
170 Some(BlockHashOrEpochNumber::EpochNumber(epoch_number)) => {
171 Ok(epoch_number)
172 }
173 None => Ok(EpochNumber::LatestState),
174 }
175 }
176
177 fn get_block_execution_info(
178 &self, block_hash: &H256,
179 ) -> CoreResult<Option<BlockExecInfo>> {
180 let consensus_graph = self.consensus_graph();
181 let (pivot_hash, block_receipts, maybe_state_root) =
182 match consensus_graph.get_block_execution_info(block_hash) {
183 None => return Ok(None),
184 Some((exec_res, maybe_state_root)) => {
185 (exec_res.0, exec_res.1.block_receipts, maybe_state_root)
186 }
187 };
188
189 let epoch_number = self
190 .consensus
191 .data_manager()
192 .block_header_by_hash(&pivot_hash)
193 .ok_or("Inconsistent state")?
194 .height();
195
196 if epoch_number > consensus_graph.best_executed_state_epoch_number() {
197 return Ok(None);
198 }
199
200 let block = self
201 .consensus
202 .data_manager()
203 .block_by_hash(&block_hash, false)
204 .ok_or("Inconsistent state")?;
205
206 if block_receipts.receipts.len() != block.transactions.len() {
207 bail!("Inconsistent state");
208 }
209
210 let pivot_header = match self
211 .consensus
212 .data_manager()
213 .block_header_by_hash(&pivot_hash)
214 {
215 Some(x) => x,
216 None => {
217 warn!("Cannot find pivot header when get block execution info: pivot hash {:?}", pivot_hash);
218 return Ok(None);
219 }
220 };
221
222 Ok(Some(BlockExecInfo {
223 block_receipts,
224 block,
225 epoch_number,
226 maybe_state_root,
227 pivot_header,
228 }))
229 }
230
231 fn construct_rpc_receipt(
232 &self, tx_index: TransactionIndex, exec_info: &BlockExecInfo,
233 include_eth_receipt: bool, include_accumulated_gas_used: bool,
234 ) -> CoreResult<Option<RpcReceipt>> {
235 let id = tx_index.real_index;
236
237 if id >= exec_info.block.transactions.len()
238 || id >= exec_info.block_receipts.receipts.len()
239 || id >= exec_info.block_receipts.tx_execution_error_messages.len()
240 {
241 bail!("Inconsistent state");
242 }
243
244 let tx = &exec_info.block.transactions[id];
245
246 if !include_eth_receipt
247 && (tx.space() == Space::Ethereum || tx_index.is_phantom)
248 {
249 return Ok(None);
250 }
251
252 let prior_gas_used = match id {
253 0 => U256::zero(),
254 id => {
255 exec_info.block_receipts.receipts[id - 1].accumulated_gas_used
256 }
257 };
258
259 let tx_exec_error_msg =
260 match &exec_info.block_receipts.tx_execution_error_messages[id] {
261 msg if msg.is_empty() => None,
262 msg => Some(msg.clone()),
263 };
264
265 let receipt = RpcReceipt::new(
266 (**tx).clone(),
267 exec_info.block_receipts.receipts[id].clone(),
268 tx_index,
269 prior_gas_used,
270 Some(exec_info.epoch_number),
271 exec_info.pivot_header.base_price(),
272 exec_info.maybe_state_root.clone(),
273 tx_exec_error_msg,
274 self.network_type,
275 include_eth_receipt,
276 include_accumulated_gas_used,
277 )?;
278
279 Ok(Some(receipt))
280 }
281
282 fn prepare_receipt(&self, tx_hash: H256) -> CoreResult<Option<RpcReceipt>> {
283 let tx_index = match self
284 .consensus
285 .data_manager()
286 .transaction_index_by_hash(&tx_hash, false)
287 {
288 None => return Ok(None),
289 Some(tx_index) => tx_index,
290 };
291
292 if tx_index.is_phantom {
293 return Ok(None);
294 }
295
296 let exec_info =
297 match self.get_block_execution_info(&tx_index.block_hash)? {
298 None => return Ok(None),
299 Some(res) => res,
300 };
301
302 let receipt =
303 self.construct_rpc_receipt(tx_index, &exec_info, false, true)?;
304 if let Some(r) = &receipt {
305 if r.outcome_status
306 == TransactionStatus::Skipped.in_space(Space::Native).into()
307 {
308 return Ok(None);
309 }
310 }
311 Ok(receipt)
312 }
313
314 fn prepare_block_receipts(
315 &self, block_hash: H256, pivot_assumption: H256,
316 include_eth_receipt: bool,
317 ) -> CoreResult<Option<Vec<RpcReceipt>>> {
318 let exec_info = match self.get_block_execution_info(&block_hash)? {
319 None => return Ok(None),
320 Some(res) => res,
321 };
322
323 if pivot_assumption != exec_info.pivot_header.hash() {
324 bail!(pivot_assumption_failed(
325 pivot_assumption,
326 exec_info.pivot_header.hash()
327 ));
328 }
329
330 let mut rpc_receipts = vec![];
331
332 let iter = exec_info
333 .block
334 .transactions
335 .iter()
336 .enumerate()
337 .filter(|(_, tx)| {
338 if include_eth_receipt {
339 true
340 } else {
341 tx.space() == Space::Native
342 }
343 })
344 .enumerate();
345
346 for (new_index, (original_index, _)) in iter {
347 if let Some(receipt) = self.construct_rpc_receipt(
348 TransactionIndex {
349 block_hash,
350 real_index: original_index,
351 is_phantom: false,
352 rpc_index: Some(new_index),
353 },
354 &exec_info,
355 include_eth_receipt,
356 true,
357 )? {
358 rpc_receipts.push(receipt);
359 }
360 }
361
362 Ok(Some(rpc_receipts))
363 }
364
365 fn exec_transaction(
366 &self, request: TransactionRequest, epoch: Option<EpochNumber>,
367 ) -> CoreResult<(ExecutionOutcome, EstimateExt)> {
368 let rpc_request_network = invalid_params_check(
369 "request",
370 check_two_rpc_address_network_match(
371 request.from.as_ref(),
372 request.to.as_ref(),
373 ),
374 )?;
375
376 invalid_params_check(
377 "request",
378 check_rpc_address_network(rpc_request_network, &self.network_type),
379 )?;
380
381 let consensus_graph = self.consensus_graph();
382 let epoch = epoch.unwrap_or(EpochNumber::LatestState);
383
384 let estimate_request = EstimateRequest {
385 has_sender: request.from.is_some(),
386 has_gas_limit: request.gas.is_some(),
387 has_gas_price: request.has_gas_price(),
388 has_nonce: request.nonce.is_some(),
389 has_storage_limit: request.storage_limit.is_some(),
390 collect_access_list: false,
391 };
392
393 let epoch_height = consensus_graph
394 .get_height_from_epoch_number(epoch.clone().into())?;
395 let chain_id = consensus_graph.best_chain_id();
396 let signed_tx = request.sign_call(
397 epoch_height,
398 chain_id.in_native_space(),
399 self.config.max_estimation_gas_limit,
400 )?;
401 trace!("call tx {:?}", signed_tx);
402
403 consensus_graph.call_virtual(
404 &signed_tx,
405 epoch.into(),
406 estimate_request,
407 Default::default(),
408 )
409 }
410
411 fn send_transaction_with_signature(
412 &self, tx: TransactionWithSignature,
413 ) -> CoreResult<H256> {
414 if self.sync.catch_up_mode() {
415 warn!("Ignore send_transaction request {}. Cannot send transaction when the node is still in catch-up mode.", tx.hash());
416 bail!(request_rejected_in_catch_up_mode(None));
417 }
418 let (signed_trans, failed_trans) =
419 self.tx_pool.insert_new_transactions(vec![tx]);
420
421 match (signed_trans.len(), failed_trans.len()) {
422 (0, 0) => {
423 debug!("insert_new_transactions ignores inserted transactions");
424 bail!(invalid_params_detail("tx", "tx already exist"))
425 }
426 (0, 1) => {
427 let tx_err = failed_trans.values().next().unwrap();
428 bail!(invalid_params_detail("tx", tx_err.to_string()))
429 }
430 (1, 0) => {
431 let tx_hash = signed_trans[0].hash();
432 self.sync.append_received_transactions(signed_trans);
433 Ok(tx_hash)
434 }
435 _ => {
436 bail!(internal_error_with_data(format!(
437 "unexpected insert result, {} returned items",
438 signed_trans.len() + failed_trans.len()
439 )))
440 }
441 }
442 }
443
444 fn prepare_transaction(
445 &self, mut tx: TransactionRequest, password: Option<String>,
446 ) -> CoreResult<TransactionWithSignature> {
447 let consensus_graph = self.consensus_graph();
448 tx.check_rpc_address_network("tx", &self.network_type)?;
449
450 if tx.nonce.is_none() {
451 let nonce = consensus_graph.next_nonce(
452 Address::from(tx.from.clone().ok_or("from should have")?)
453 .with_native_space(),
454 BlockHashOrEpochNumber::EpochNumber(EpochNumber::LatestState)
455 .into(),
456 "internal EpochNumber::LatestState",
457 )?;
458 tx.nonce.replace(nonce.into());
459 debug!("after loading nonce in latest state, tx = {:?}", tx);
460 }
461
462 let epoch_height = consensus_graph.best_epoch_number();
463 let chain_id = consensus_graph.best_chain_id();
464
465 if tx.gas.is_none() || tx.storage_limit.is_none() {
466 let estimate =
467 self.estimate_gas_and_collateral_impl(tx.clone(), None)?;
468
469 if tx.gas.is_none() {
470 tx.gas.replace(estimate.gas_used);
471 }
472
473 if tx.storage_limit.is_none() {
474 tx.storage_limit.replace(estimate.storage_collateralized);
475 }
476 }
477
478 if tx.transaction_type.is_none() && tx.gas_price.is_none() {
479 let gas_price = consensus_graph.gas_price(Space::Native);
480 if gas_price.is_some() {
481 tx.gas_price.replace(gas_price.unwrap());
482 }
483 }
484
485 tx.sign_with(
486 epoch_height,
487 chain_id.in_native_space(),
488 password,
489 self.accounts.clone(),
490 )
491 .map_err(Into::into)
492 }
493
494 fn estimate_gas_and_collateral_impl(
495 &self, request: TransactionRequest, epoch: Option<EpochNumber>,
496 ) -> CoreResult<EstimateGasAndCollateralResponse> {
497 let (execution_outcome, estimation) =
498 self.exec_transaction(request, epoch)?;
499 match execution_outcome {
500 ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
501 expected,
502 got,
503 )) => bail!(call_execution_error(
504 "Can not estimate: transaction can not be executed".into(),
505 format! {"nonce is too old expected {:?} got {:?}", expected, got}
506 )),
507 ExecutionOutcome::NotExecutedDrop(
508 TxDropError::InvalidRecipientAddress(recipient),
509 ) => bail!(call_execution_error(
510 "Can not estimate: transaction can not be executed".into(),
511 format! {"invalid recipient address {:?}", recipient}
512 )),
513 ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
514 address,
515 )) => bail!(call_execution_error(
516 "Can not estimate: transaction sender has code".into(),
517 format! {"transaction sender has code {:?}", address}
518 )),
519 ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
520 bail!(call_execution_error(
521 "Can not estimate: transaction can not be executed".into(),
522 format! {"{:?}", e}
523 ))
524 }
525 ExecutionOutcome::NotExecutedDrop(
526 TxDropError::NotEnoughGasLimit { expected, got },
527 ) => bail!(call_execution_error(
528 "Can not estimate: transaction can not be executed".into(),
529 format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
530 )),
531 ExecutionOutcome::ExecutionErrorBumpNonce(
532 ExecutionError::VmError(VmError::Reverted),
533 executed,
534 ) => {
535 let (revert_error, innermost_error, errors) =
536 decode_error(&executed, |addr| {
537 RpcAddress::try_from_h160(
538 addr.clone(),
539 self.network_type,
540 )
541 .unwrap()
542 .base32_address
543 });
544 bail!(call_execution_error(
545 format!("Estimation isn't accurate: transaction is reverted{}{}",
546 revert_error, innermost_error),
547 errors.join("\n"),
548 ))
549 }
550 ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
551 bail!(call_execution_error(
552 format! {"Can not estimate: transaction execution failed, \
553 all gas will be charged (execution error: {:?})", e}
554 .into(),
555 format! {"{:?}", e}
556 ))
557 }
558 ExecutionOutcome::Finished(_) => {}
559 };
560 let storage_collateralized =
561 U64::from(estimation.estimated_storage_limit);
562 let estimated_gas_used = estimation.estimated_gas_limit;
563 Ok(EstimateGasAndCollateralResponse {
564 gas_limit: estimated_gas_used,
565 gas_used: estimated_gas_used,
566 storage_collateralized,
567 })
568 }
569
570 fn check_response_size<T: serde::Serialize>(
571 &self, response: &T,
572 ) -> CoreResult<()> {
573 let max_size = self.config.max_payload_bytes.saturating_sub(50);
574 let payload_size = serde_json::to_vec(&response)
575 .map_err(|_| "Unexpected serialization error")?
576 .len();
577
578 if payload_size > max_size {
579 bail!(invalid_params(
580 "epoch",
581 Some(format!(
582 "Oversized payload: size = {}, max = {}",
583 payload_size, max_size
584 ))
585 ));
586 }
587 Ok(())
588 }
589
590 fn generate_one_block(
591 &self, num_txs: usize, block_size_limit: usize,
592 ) -> CoreResult<H256> {
593 info!("RPC Request: generate_one_block()");
594 Ok(self
595 .block_gen
596 .generate_block(num_txs, block_size_limit, vec![]))
597 }
598}
599
600#[async_trait]
601impl CfxRpcServer for CfxHandler {
602 async fn gas_price(&self) -> RpcResult<U256> {
603 let consensus_graph = self.consensus_graph();
604 info!("RPC Request: cfx_gasPrice()");
605 let consensus_gas_price = consensus_graph
606 .gas_price(Space::Native)
607 .unwrap_or(GAS_PRICE_DEFAULT_VALUE.into())
608 .into();
609 Ok(std::cmp::max(
610 consensus_gas_price,
611 self.tx_pool.config.min_native_tx_price.into(),
612 ))
613 }
614
615 async fn max_priority_fee_per_gas(&self) -> RpcResult<U256> {
616 info!("RPC Request: max_priority_fee_per_gas");
617 let fee_history = self
618 .fee_history(
619 HexU64::from(300),
620 EpochNumber::LatestState,
621 Some(vec![50f64]),
622 )
623 .await?;
624 let total_reward: U256 = fee_history
625 .reward()
626 .iter()
627 .map(|x| x.first().unwrap())
628 .fold(U256::zero(), |x, y| x + *y);
629 Ok(total_reward / 300)
630 }
631
632 async fn epoch_number(
633 &self, epoch_num: Option<EpochNumber>,
634 ) -> RpcResult<U256> {
635 let consensus_graph = self.consensus_graph();
636 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestMined);
637 info!("RPC Request: cfx_epochNumber({:?})", epoch_num);
638 consensus_graph
639 .get_height_from_epoch_number(epoch_num.into())
640 .map(|h| h.into())
641 .map_err(|e| invalid_params_rpc_err(e, None::<()>))
642 }
643
644 async fn balance(
645 &self, addr: RpcAddress,
646 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
647 ) -> RpcResult<U256> {
648 self.check_address_network(addr.network)?;
649 let epoch_num = self
650 .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
651 .into();
652 info!(
653 "RPC Request: cfx_getBalance address={:?} epoch_num={:?}",
654 addr, epoch_num
655 );
656 let state_db = self
657 .consensus
658 .get_state_db_by_epoch_number(epoch_num, "num")?;
659 let acc = state_db
660 .get_account(&addr.hex_address.with_native_space())
661 .map_err(into_rpc_err)?;
662 Ok(acc.map_or(U256::zero(), |acc| acc.balance).into())
663 }
664
665 async fn admin(
666 &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
667 ) -> RpcResult<Option<RpcAddress>> {
668 self.check_address_network(addr.network)?;
669 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
670 let network = addr.network;
671 info!(
672 "RPC Request: cfx_getAdmin address={:?} epoch_num={:?}",
673 addr, epoch_num
674 );
675 let state_db = self
676 .consensus
677 .get_state_db_by_epoch_number(epoch_num, "num")?;
678 match state_db
679 .get_account(&addr.hex_address.with_native_space())
680 .map_err(into_rpc_err)?
681 {
682 None => Ok(None),
683 Some(acc) => Ok(Some(
684 RpcAddress::try_from_h160(acc.admin, network)
685 .map_err(into_rpc_err)?,
686 )),
687 }
688 }
689
690 async fn sponsor_info(
691 &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
692 ) -> RpcResult<SponsorInfo> {
693 self.check_address_network(addr.network)?;
694 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
695 let network = addr.network;
696 info!(
697 "RPC Request: cfx_getSponsorInfo address={:?} epoch_num={:?}",
698 addr, epoch_num
699 );
700 let state_db = self
701 .consensus
702 .get_state_db_by_epoch_number(epoch_num, "num")?;
703 match state_db
704 .get_account(&addr.hex_address.with_native_space())
705 .map_err(into_rpc_err)?
706 {
707 None => SponsorInfo::default(network).map_err(into_rpc_err),
708 Some(acc) => SponsorInfo::try_from(acc.sponsor_info, network)
709 .map_err(into_rpc_err),
710 }
711 }
712
713 async fn staking_balance(
714 &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
715 ) -> RpcResult<U256> {
716 self.check_address_network(addr.network)?;
717 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
718 info!(
719 "RPC Request: cfx_getStakingBalance address={:?} epoch_num={:?}",
720 addr, epoch_num
721 );
722 let state_db = self
723 .consensus
724 .get_state_db_by_epoch_number(epoch_num, "num")?;
725 let acc = state_db
726 .get_account(&addr.hex_address.with_native_space())
727 .map_err(into_rpc_err)?;
728 Ok(acc.map_or(U256::zero(), |acc| acc.staking_balance).into())
729 }
730
731 async fn deposit_list(
732 &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
733 ) -> RpcResult<Vec<DepositInfo>> {
734 self.check_address_network(addr.network)?;
735 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
736 info!(
737 "RPC Request: cfx_getDepositList address={:?} epoch_num={:?}",
738 addr, epoch_num
739 );
740 let state_db = self
741 .consensus
742 .get_state_db_by_epoch_number(epoch_num, "num")?;
743 match state_db
744 .get_deposit_list(&addr.hex_address.with_native_space())
745 .map_err(into_rpc_err)?
746 {
747 None => Ok(vec![]),
748 Some(deposit_list) => Ok(deposit_list.0),
749 }
750 }
751
752 async fn vote_list(
753 &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
754 ) -> RpcResult<Vec<VoteStakeInfo>> {
755 self.check_address_network(addr.network)?;
756 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
757 info!(
758 "RPC Request: cfx_getVoteList address={:?} epoch_num={:?}",
759 addr, epoch_num
760 );
761 let state_db = self
762 .consensus
763 .get_state_db_by_epoch_number(epoch_num, "num")?;
764 match state_db
765 .get_vote_list(&addr.hex_address.with_native_space())
766 .map_err(into_rpc_err)?
767 {
768 None => Ok(vec![]),
769 Some(vote_list) => Ok(vote_list.0),
770 }
771 }
772
773 async fn collateral_for_storage(
774 &self, addr: RpcAddress, epoch_number: Option<EpochNumber>,
775 ) -> RpcResult<U256> {
776 self.check_address_network(addr.network)?;
777 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
778 info!(
779 "RPC Request: cfx_getCollateralForStorage address={:?} epoch_num={:?}",
780 addr, epoch_num
781 );
782 let state_db = self
783 .consensus
784 .get_state_db_by_epoch_number(epoch_num, "num")?;
785 let acc = state_db
786 .get_account(&addr.hex_address.with_native_space())
787 .map_err(into_rpc_err)?;
788 Ok(acc
789 .map_or(U256::zero(), |acc| acc.collateral_for_storage)
790 .into())
791 }
792
793 async fn code(
794 &self, addr: RpcAddress,
795 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
796 ) -> RpcResult<Bytes> {
797 self.check_address_network(addr.network)?;
798 let epoch_num = self
799 .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)
800 .map_err(into_rpc_err)?
801 .into();
802 info!(
803 "RPC Request: cfx_getCode address={:?} epoch_num={:?}",
804 addr, epoch_num
805 );
806 let state_db = self
807 .consensus
808 .get_state_db_by_epoch_number(epoch_num, "num")?;
809 let address = addr.hex_address.with_native_space();
810 let code = match state_db.get_account(&address).map_err(into_rpc_err)? {
811 Some(acc) => match state_db
812 .get_code(&address, &acc.code_hash)
813 .map_err(into_rpc_err)?
814 {
815 Some(code) => (*code.code).clone(),
816 _ => vec![],
817 },
818 None => vec![],
819 };
820 Ok(Bytes::new(code))
821 }
822
823 async fn storage_at(
824 &self, addr: RpcAddress, pos: U256,
825 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
826 ) -> RpcResult<Option<H256>> {
827 self.check_address_network(addr.network)?;
828 let epoch_num = self
829 .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)
830 .map_err(into_rpc_err)?
831 .into();
832 info!(
833 "RPC Request: cfx_getStorageAt address={:?}, position={:?}, epoch_num={:?})",
834 addr, pos, epoch_num
835 );
836 let state_db = self
837 .consensus
838 .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
839 let position: H256 = H256::from_uint(&pos);
840 let key =
841 StorageKey::new_storage_key(&addr.hex_address, position.as_ref())
842 .with_native_space();
843 Ok(
844 match state_db.get::<StorageValue>(key).map_err(into_rpc_err)? {
845 Some(entry) => {
846 let h: H256 = H256::from_uint(&entry.value);
847 Some(h.into())
848 }
849 None => None,
850 },
851 )
852 }
853
854 async fn storage_root(
855 &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
856 ) -> RpcResult<Option<StorageRoot>> {
857 self.check_address_network(address.network)?;
858 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
859 info!(
860 "RPC Request: cfx_getStorageRoot address={:?} epoch={:?}",
861 address, epoch_num
862 );
863 let root = self
864 .consensus
865 .get_storage_state_by_epoch_number(epoch_num, "epoch_num")?
866 .get_original_storage_root(&address.hex_address.with_native_space())
867 .map_err(into_rpc_err)?;
868 Ok(Some(root))
869 }
870
871 async fn block_by_hash(
872 &self, block_hash: H256, include_txs: bool,
873 ) -> RpcResult<Option<RpcBlock>> {
874 let consensus_graph = self.consensus_graph();
875 info!(
876 "RPC Request: cfx_getBlockByHash hash={:?} include_txs={:?}",
877 block_hash, include_txs
878 );
879 let inner = &*consensus_graph.inner.read();
880 let maybe_block = self.data_man.block_by_hash(&block_hash, false);
881 match maybe_block {
882 None => Ok(None),
883 Some(b) => Ok(Some(
884 build_block(
885 &*b,
886 self.network_type,
887 consensus_graph,
888 inner,
889 &self.data_man,
890 include_txs,
891 Some(Space::Native),
892 )
893 .map_err(into_rpc_err)?,
894 )),
895 }
896 }
897
898 async fn block_by_hash_with_pivot_assumption(
899 &self, block_hash: H256, pivot_hash: H256, epoch_number: U64,
900 ) -> RpcResult<RpcBlock> {
901 let consensus_graph = self.consensus_graph();
902 let inner = &*consensus_graph.inner.read();
903 let epoch_number = epoch_number.as_usize() as u64;
904 info!(
905 "RPC Request: cfx_getBlockByHashWithPivotAssumption block_hash={:?} pivot_hash={:?} epoch_number={:?}",
906 block_hash, pivot_hash, epoch_number
907 );
908
909 let genesis = self.consensus.data_manager().true_genesis.hash();
910
911 if block_hash == genesis && (pivot_hash != genesis || epoch_number != 0)
912 {
913 return Err(invalid_params_msg("pivot chain assumption failed"));
914 }
915
916 if block_hash != genesis
917 && (consensus_graph.get_block_epoch_number(&block_hash)
918 != epoch_number.into())
919 {
920 return Err(invalid_params_msg("pivot chain assumption failed"));
921 }
922
923 inner
924 .check_block_pivot_assumption(&pivot_hash, epoch_number)
925 .map_err(|e| invalid_params_msg(&e.to_string()))?;
926
927 let block = self
928 .data_man
929 .block_by_hash(&block_hash, false)
930 .ok_or(invalid_params_msg("Block not found"))?;
931
932 debug!("Build RpcBlock {}", block.hash());
933 build_block(
934 &*block,
935 self.network_type,
936 consensus_graph,
937 inner,
938 &self.data_man,
939 true,
940 Some(Space::Native),
941 )
942 .map_err(into_rpc_err)
943 }
944
945 async fn block_by_epoch_number(
946 &self, epoch_number: EpochNumber, include_txs: bool,
947 ) -> RpcResult<Option<RpcBlock>> {
948 info!("RPC Request: cfx_getBlockByEpochNumber epoch_number={:?} include_txs={:?}", epoch_number, include_txs);
949 let consensus_graph = self.consensus_graph();
950 let inner = &*consensus_graph.inner.read();
951
952 let epoch_height = consensus_graph
953 .get_height_from_epoch_number(epoch_number.into())
954 .map_err(|e| invalid_params_msg(&e.to_string()))?;
955
956 let pivot_hash = inner
957 .get_pivot_hash_from_epoch_number(epoch_height)
958 .map_err(|e| invalid_params_msg(&e.to_string()))?;
959
960 let maybe_block = self.data_man.block_by_hash(&pivot_hash, false);
961 match maybe_block {
962 None => Ok(None),
963 Some(b) => Ok(Some(
964 build_block(
965 &*b,
966 self.network_type,
967 consensus_graph,
968 inner,
969 &self.data_man,
970 include_txs,
971 Some(Space::Native),
972 )
973 .map_err(into_rpc_err)?,
974 )),
975 }
976 }
977
978 async fn block_by_block_number(
979 &self, block_number: U64, include_txs: bool,
980 ) -> RpcResult<Option<RpcBlock>> {
981 let block_number = block_number.as_u64();
982 let consensus_graph = self.consensus_graph();
983 info!(
984 "RPC Request: cfx_getBlockByBlockNumber block_number={:?} include_txs={:?}",
985 block_number, include_txs
986 );
987 let inner = &*consensus_graph.inner.read();
988 let block_hash =
989 match self.data_man.hash_by_block_number(block_number, true) {
990 None => return Ok(None),
991 Some(h) => h,
992 };
993 let maybe_block = self.data_man.block_by_hash(&block_hash, false);
994 match maybe_block {
995 None => Ok(None),
996 Some(b) => Ok(Some(
997 build_block(
998 &*b,
999 self.network_type,
1000 consensus_graph,
1001 inner,
1002 &self.data_man,
1003 include_txs,
1004 Some(Space::Native),
1005 )
1006 .map_err(into_rpc_err)?,
1007 )),
1008 }
1009 }
1010
1011 async fn best_block_hash(&self) -> RpcResult<H256> {
1012 info!("RPC Request: cfx_getBestBlockHash()");
1013 Ok(self.consensus.best_block_hash().into())
1014 }
1015
1016 async fn next_nonce(
1017 &self, addr: RpcAddress, num: Option<BlockHashOrEpochNumber>,
1018 ) -> RpcResult<U256> {
1019 self.check_address_network(addr.network)?;
1020 let consensus_graph = self.consensus_graph();
1021 let num = num.unwrap_or(BlockHashOrEpochNumber::EpochNumber(
1022 EpochNumber::LatestState,
1023 ));
1024 info!(
1025 "RPC Request: cfx_getNextNonce address={:?} epoch_num={:?}",
1026 addr, num
1027 );
1028 consensus_graph
1029 .next_nonce(addr.hex_address.with_native_space(), num.into(), "num")
1030 .map_err(into_rpc_err)
1031 }
1032
1033 async fn send_raw_transaction(&self, raw_tx: Bytes) -> RpcResult<H256> {
1034 info!(
1035 "RPC Request: cfx_sendRawTransaction len={:?}",
1036 raw_tx.0.len()
1037 );
1038 debug!("RawTransaction bytes={:?}", raw_tx);
1039
1040 let tx: TransactionWithSignature = invalid_params_check(
1041 "raw",
1042 TransactionWithSignature::from_raw(&raw_tx.into_vec()),
1043 )?;
1044
1045 if tx.recover_public().is_err() {
1046 return Err(invalid_params_detail(
1047 "tx",
1048 "Can not recover pubkey for Ethereum like tx",
1049 ));
1050 }
1051
1052 let r = self
1053 .send_transaction_with_signature(tx)
1054 .map_err(into_rpc_err);
1055
1056 if r.is_ok() && self.config.dev_pack_tx_immediately {
1057 for _ in 0..DEFERRED_STATE_EPOCH_COUNT {
1059 let generated = self.generate_one_block(
1060 1, self.sync
1062 .get_synchronization_graph()
1063 .verification_config
1064 .max_block_size_in_bytes,
1065 )?;
1066 loop {
1067 if self.consensus.best_block_hash() == generated {
1071 break;
1072 } else {
1073 thread::sleep(Duration::from_millis(10));
1074 }
1075 }
1076 }
1077 }
1078
1079 r
1080 }
1081
1082 async fn call(
1083 &self, tx: TransactionRequest,
1084 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
1085 ) -> RpcResult<Bytes> {
1086 let epoch = Some(
1087 self.get_epoch_number_with_pivot_check(block_hash_or_epoch_number)
1088 .map_err(into_rpc_err)?,
1089 );
1090 let (execution_outcome, _estimation) =
1091 self.exec_transaction(tx, epoch).map_err(into_rpc_err)?;
1092 match execution_outcome {
1093 ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1094 expected,
1095 got,
1096 )) => Err(call_execution_error(
1097 "Transaction can not be executed".into(),
1098 format! {"nonce is too old expected {:?} got {:?}", expected, got},
1099 )),
1100 ExecutionOutcome::NotExecutedDrop(
1101 TxDropError::InvalidRecipientAddress(recipient),
1102 ) => Err(call_execution_error(
1103 "Transaction can not be executed".into(),
1104 format! {"invalid recipient address {:?}", recipient},
1105 )),
1106 ExecutionOutcome::NotExecutedDrop(
1107 TxDropError::NotEnoughGasLimit { expected, got },
1108 ) => Err(call_execution_error(
1109 "Transaction can not be executed".into(),
1110 format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got},
1111 )),
1112 ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1113 address,
1114 )) => Err(call_execution_error(
1115 "Transaction can not be executed".into(),
1116 format! {"tx sender has contract code: {:?}", address},
1117 )),
1118 ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1119 Err(call_execution_error(
1120 "Transaction can not be executed".into(),
1121 format! {"{:?}", e},
1122 ))
1123 }
1124 ExecutionOutcome::ExecutionErrorBumpNonce(
1125 ExecutionError::VmError(VmError::Reverted),
1126 executed,
1127 ) => Err(call_execution_error(
1128 "Transaction reverted".into(),
1129 format!("0x{}", executed.output.to_hex::<String>()),
1130 )),
1131 ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1132 Err(call_execution_error(
1133 "Transaction execution failed".into(),
1134 format! {"{:?}", e},
1135 ))
1136 }
1137 ExecutionOutcome::Finished(executed) => Ok(executed.output.into()),
1138 }
1139 }
1140
1141 async fn get_logs(
1142 &self, filter: CfxRpcLogFilter,
1143 ) -> RpcResult<Vec<RpcLog>> {
1144 if let Some(addresses) = &filter.address {
1145 for address in addresses.iter() {
1146 invalid_params_check(
1147 "filter.address",
1148 check_rpc_address_network(
1149 Some(address.network),
1150 &self.network_type,
1151 ),
1152 )?;
1153 }
1154 }
1155
1156 let consensus_graph = self.consensus_graph();
1157 info!("RPC Request: cfx_getLogs({:?})", filter);
1158
1159 let filter: LogFilter = filter.into_primitive()?;
1160
1161 let logs = consensus_graph
1162 .logs(filter)
1163 .map_err(into_rpc_err)?
1164 .iter()
1165 .cloned()
1166 .map(|l| RpcLog::try_from_localized(l, self.network_type))
1167 .collect::<Result<Vec<_>, _>>()
1168 .map_err(into_rpc_err)?;
1169
1170 if let Some(max_limit) = self.config.get_logs_filter_max_limit {
1171 if logs.len() > max_limit {
1172 return Err(invalid_params_rpc_err(
1173 "filter",
1174 Some(format!(
1175 "This query results in too many logs, max limitation is {}, please filter results by a smaller epoch/block range",
1176 max_limit
1177 )),
1178 ));
1179 }
1180 }
1181
1182 Ok(logs)
1183 }
1184
1185 async fn transaction_by_hash(
1186 &self, tx_hash: H256,
1187 ) -> RpcResult<Option<RpcTransaction>> {
1188 info!("RPC Request: cfx_getTransactionByHash({:?})", tx_hash);
1189
1190 if let Some((
1191 tx,
1192 TransactionInfo {
1193 tx_index,
1194 maybe_executed_extra_info,
1195 },
1196 )) = self.consensus.get_signed_tx_and_tx_info(&tx_hash)
1197 {
1198 if tx.space() == Space::Ethereum || tx_index.is_phantom {
1199 return Ok(None);
1200 }
1201
1202 let packed_or_executed = match maybe_executed_extra_info {
1203 None => PackedOrExecuted::Packed(tx_index),
1204 Some(MaybeExecutedTxExtraInfo {
1205 receipt,
1206 block_number: _,
1207 prior_gas_used,
1208 tx_exec_error_msg,
1209 }) => {
1210 let epoch_number = self
1211 .consensus
1212 .get_block_epoch_number(&tx_index.block_hash);
1213
1214 let maybe_state_root = self
1215 .consensus
1216 .data_manager()
1217 .get_executed_state_root(&tx_index.block_hash);
1218
1219 let maybe_base_price = self
1220 .consensus
1221 .data_manager()
1222 .block_header_by_hash(&tx_index.block_hash)
1223 .and_then(|x| x.base_price());
1224
1225 PackedOrExecuted::Executed(
1226 RpcReceipt::new(
1227 tx.clone(),
1228 receipt,
1229 tx_index,
1230 prior_gas_used,
1231 epoch_number,
1232 maybe_base_price,
1233 maybe_state_root,
1234 tx_exec_error_msg,
1235 self.network_type,
1236 false,
1237 false,
1238 )
1239 .map_err(into_rpc_err)?,
1240 )
1241 }
1242 };
1243
1244 let rpc_tx = RpcTransaction::from_signed(
1245 &tx,
1246 Some(packed_or_executed),
1247 self.network_type,
1248 )
1249 .map_err(into_rpc_err)?;
1250
1251 return Ok(Some(rpc_tx));
1252 }
1253
1254 if let Some(tx) = self.tx_pool.get_transaction(&tx_hash) {
1255 if tx.space() == Space::Ethereum {
1256 return Ok(None);
1257 }
1258 let rpc_tx =
1259 RpcTransaction::from_signed(&tx, None, self.network_type)
1260 .map_err(into_rpc_err)?;
1261 return Ok(Some(rpc_tx));
1262 }
1263
1264 Ok(None)
1265 }
1266
1267 async fn estimate_gas_and_collateral(
1268 &self, request: TransactionRequest, epoch_number: Option<EpochNumber>,
1269 ) -> RpcResult<EstimateGasAndCollateralResponse> {
1270 info!(
1271 "RPC Request: cfx_estimateGasAndCollateral request={:?}, epoch={:?}",
1272 request, epoch_number
1273 );
1274 self.estimate_gas_and_collateral_impl(request, epoch_number)
1275 .map_err(into_rpc_err)
1276 }
1277
1278 async fn fee_history(
1279 &self, block_count: HexU64, newest_block: EpochNumber,
1280 reward_percentiles: Option<Vec<f64>>,
1281 ) -> RpcResult<CfxFeeHistory> {
1282 use crate::helpers::MAX_FEE_HISTORY_CACHE_BLOCK_COUNT;
1283
1284 if newest_block == EpochNumber::LatestMined {
1285 return Err(invalid_params_rpc_err(
1286 "newestBlock cannot be 'LatestMined'",
1287 None::<bool>,
1288 ));
1289 }
1290
1291 info!(
1292 "RPC Request: cfx_feeHistory: block_count={}, newest_block={:?}, reward_percentiles={:?}",
1293 block_count, newest_block, reward_percentiles
1294 );
1295
1296 let mut block_count = block_count;
1297
1298 if block_count.as_u64() == 0 {
1299 return Ok(FeeHistory::new().into());
1300 }
1301
1302 if block_count.as_u64() > MAX_FEE_HISTORY_CACHE_BLOCK_COUNT {
1303 block_count = HexU64::from(MAX_FEE_HISTORY_CACHE_BLOCK_COUNT);
1304 }
1305
1306 let inner = self.consensus_graph().inner.read();
1307
1308 let fetch_block = |height| {
1309 let pivot_hash = inner
1310 .get_pivot_hash_from_epoch_number(height)
1311 .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?;
1312 let maybe_block = self.data_man.block_by_hash(&pivot_hash, false);
1313 if let Some(block) = maybe_block {
1314 Ok(block)
1315 } else {
1316 Err(internal_error())
1317 }
1318 };
1319
1320 let start_height: u64 = self
1321 .consensus_graph()
1322 .get_height_from_epoch_number(newest_block.into())
1323 .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?;
1324
1325 let reward_percentiles = reward_percentiles.unwrap_or_default();
1326 let mut current_height = start_height;
1327
1328 let mut fee_history = FeeHistory::new();
1329 while current_height
1330 >= start_height.saturating_sub(block_count.as_u64() - 1)
1331 {
1332 let block = fetch_block(current_height)?;
1333 let transactions = block
1334 .transactions
1335 .iter()
1336 .filter(|tx| tx.space() == Space::Native)
1337 .map(|x| &**x);
1338 fee_history
1339 .push_front_block(
1340 Space::Native,
1341 &reward_percentiles,
1342 &block.block_header,
1343 transactions,
1344 )
1345 .map_err(|_| internal_error())?;
1346
1347 if current_height == 0 {
1348 break;
1349 } else {
1350 current_height -= 1;
1351 }
1352 }
1353
1354 let block = fetch_block(start_height + 1)?;
1355 let oldest_block = if current_height == 0 {
1356 0
1357 } else {
1358 current_height + 1
1359 };
1360 fee_history.finish(
1361 oldest_block,
1362 block.block_header.base_price().as_ref(),
1363 Space::Native,
1364 );
1365
1366 Ok(fee_history.into())
1367 }
1368
1369 async fn check_balance_against_transaction(
1370 &self, account_addr: RpcAddress, contract_addr: RpcAddress,
1371 gas_limit: U256, gas_price: U256, storage_limit: U256,
1372 epoch: Option<EpochNumber>,
1373 ) -> RpcResult<CheckBalanceAgainstTransactionResponse> {
1374 self.check_address_network(account_addr.network)?;
1375 self.check_address_network(contract_addr.network)?;
1376
1377 let epoch: PrimitiveEpochNumber =
1378 epoch.unwrap_or(EpochNumber::LatestState).into();
1379
1380 info!(
1381 "RPC Request: cfx_checkBalanceAgainstTransaction account_addr={:?} contract_addr={:?} gas_limit={:?} gas_price={:?} storage_limit={:?} epoch={:?}",
1382 account_addr, contract_addr, gas_limit, gas_price, storage_limit, epoch
1383 );
1384
1385 let account_addr_spaced = account_addr.hex_address.with_native_space();
1386 let contract_addr_spaced =
1387 contract_addr.hex_address.with_native_space();
1388
1389 if storage_limit > U256::from(std::u64::MAX) {
1390 return Err(invalid_params_rpc_err(
1391 format!(
1392 "storage_limit has to be within the range of u64 but {} supplied!",
1393 storage_limit
1394 ),
1395 None::<bool>,
1396 ));
1397 }
1398
1399 let state_db = self
1400 .consensus
1401 .get_state_db_by_epoch_number(epoch, "epoch")
1402 .map_err(into_rpc_err)?;
1403
1404 let user_account = state_db
1405 .get_account(&account_addr_spaced)
1406 .map_err(into_rpc_err)?;
1407 let contract_account = state_db
1408 .get_account(&contract_addr_spaced)
1409 .map_err(into_rpc_err)?;
1410 let state = State::new(state_db).map_err(into_rpc_err)?;
1411 let is_sponsored = state
1412 .check_contract_whitelist(
1413 &contract_addr_spaced.address,
1414 &account_addr_spaced.address,
1415 )
1416 .map_err(into_rpc_err)?;
1417
1418 Ok(check_balance_against_transaction(
1419 user_account,
1420 contract_account,
1421 is_sponsored,
1422 gas_limit,
1423 gas_price,
1424 storage_limit,
1425 ))
1426 }
1427
1428 async fn blocks_by_epoch(
1429 &self, epoch_number: EpochNumber,
1430 ) -> RpcResult<Vec<H256>> {
1431 info!(
1432 "RPC Request: cfx_getBlocksByEpoch epoch_number={:?}",
1433 epoch_number
1434 );
1435 self.consensus
1436 .get_block_hashes_by_epoch(epoch_number.into())
1437 .map_err(|e| invalid_params_rpc_err(e, None::<bool>))
1438 .and_then(|vec| Ok(vec.into_iter().map(|x| x.into()).collect()))
1439 }
1440
1441 async fn skipped_blocks_by_epoch(
1442 &self, epoch_number: EpochNumber,
1443 ) -> RpcResult<Vec<H256>> {
1444 info!(
1445 "RPC Request: cfx_getSkippedBlocksByEpoch epoch_number={:?}",
1446 epoch_number
1447 );
1448 self.consensus
1449 .get_skipped_block_hashes_by_epoch(epoch_number.into())
1450 .map_err(|e| invalid_params_rpc_err(e, None::<bool>))
1451 .and_then(|vec| Ok(vec.into_iter().map(|x| x.into()).collect()))
1452 }
1453
1454 async fn transaction_receipt(
1455 &self, tx_hash: H256,
1456 ) -> RpcResult<Option<RpcReceipt>> {
1457 info!("RPC Request: cfx_getTransactionReceipt({:?})", tx_hash);
1458 self.prepare_receipt(tx_hash).map_err(into_rpc_err)
1459 }
1460
1461 async fn account(
1462 &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
1463 ) -> RpcResult<RpcAccount> {
1464 self.check_address_network(address.network)?;
1465 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
1466 let network = address.network;
1467 info!(
1468 "RPC Request: cfx_getAccount address={:?} epoch_num={:?}",
1469 address, epoch_num
1470 );
1471 let addr = &address.hex_address;
1472 let state_db = self
1473 .consensus
1474 .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1475 .map_err(into_rpc_err)?;
1476 let account = match state_db
1477 .get_account(&addr.with_native_space())
1478 .map_err(into_rpc_err)?
1479 {
1480 Some(t) => t,
1481 None => account_result_to_rpc_result(
1482 "address",
1483 Ok(Account::new_empty_with_balance(
1484 &addr.with_native_space(),
1485 &U256::zero(),
1486 &U256::zero(),
1487 )),
1488 )
1489 .map_err(into_rpc_err)?,
1490 };
1491 RpcAccount::try_from(account, network)
1492 .map_err(|e| invalid_params_rpc_err(e, None::<bool>))
1493 }
1494
1495 async fn interest_rate(
1496 &self, epoch_number: Option<EpochNumber>,
1497 ) -> RpcResult<U256> {
1498 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1499 let state_db = self
1500 .consensus
1501 .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1502 .map_err(into_rpc_err)?;
1503 Ok(state_db
1504 .get_global_param::<InterestRate>()
1505 .map_err(into_rpc_err)?
1506 .into())
1507 }
1508
1509 async fn accumulate_interest_rate(
1510 &self, epoch_number: Option<EpochNumber>,
1511 ) -> RpcResult<U256> {
1512 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1513 let state_db = self
1514 .consensus
1515 .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1516 .map_err(into_rpc_err)?;
1517 Ok(state_db
1518 .get_global_param::<AccumulateInterestRate>()
1519 .map_err(into_rpc_err)?
1520 .into())
1521 }
1522
1523 async fn pos_economics(
1524 &self, epoch_number: Option<EpochNumber>,
1525 ) -> RpcResult<PoSEconomics> {
1526 let epoch_num = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1527 let state_db = self
1528 .consensus
1529 .get_state_db_by_epoch_number(epoch_num, "epoch_num")
1530 .map_err(into_rpc_err)?;
1531 Ok(PoSEconomics {
1532 total_pos_staking_tokens: state_db
1533 .get_global_param::<TotalPosStaking>()
1534 .map_err(into_rpc_err)?,
1535 distributable_pos_interest: state_db
1536 .get_global_param::<DistributablePoSInterest>()
1537 .map_err(into_rpc_err)?,
1538 last_distribute_block: U64::from(
1539 state_db
1540 .get_global_param::<LastDistributeBlock>()
1541 .map_err(into_rpc_err)?
1542 .as_u64(),
1543 ),
1544 })
1545 }
1546
1547 async fn confirmation_risk_by_hash(
1548 &self, block_hash: H256,
1549 ) -> RpcResult<Option<U256>> {
1550 let consensus_graph = self.consensus_graph();
1551 let inner = &*consensus_graph.inner.read();
1552 let result = consensus_graph
1553 .confirmation_meter
1554 .confirmation_risk_by_hash(inner, block_hash.into());
1555 if result.is_none() {
1556 return Ok(None);
1557 }
1558 let risk: BigDecimal = result.unwrap().into();
1559 let scale = BigInt::parse_bytes(
1560 b"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
1561 16,
1562 )
1563 .expect("failed to unwrap U256::max into bigInt");
1564 let scaled_risk: BigInt = (risk * scale)
1565 .to_bigint()
1566 .expect("failed to convert scaled risk to bigInt");
1567 let (sign, big_endian_bytes) = scaled_risk.to_bytes_be();
1568 assert_ne!(sign, num_bigint::Sign::Minus);
1569 let rpc_result = U256::from(big_endian_bytes.as_slice());
1570 Ok(Some(rpc_result.into()))
1571 }
1572
1573 async fn get_status(&self) -> RpcResult<RpcStatus> {
1574 let consensus_graph = self.consensus_graph();
1575 let (best_info, block_number) = {
1576 let _inner = &*consensus_graph.inner.read();
1577 let best_info = self.consensus.best_info();
1578 let block_number = self
1579 .consensus
1580 .get_block_number(&best_info.best_block_hash)
1581 .map_err(into_rpc_err)?
1582 .ok_or_else(|| internal_error())?
1583 + 1;
1584 (best_info, block_number)
1585 };
1586
1587 let tx_count = self.tx_pool.total_unpacked();
1588
1589 let latest_checkpoint = consensus_graph
1590 .get_height_from_epoch_number(EpochNumber::LatestCheckpoint.into())
1591 .map_err(into_rpc_err)?
1592 .into();
1593
1594 let latest_confirmed = consensus_graph
1595 .get_height_from_epoch_number(EpochNumber::LatestConfirmed.into())
1596 .map_err(into_rpc_err)?
1597 .into();
1598
1599 let latest_state = consensus_graph
1600 .get_height_from_epoch_number(EpochNumber::LatestState.into())
1601 .map_err(into_rpc_err)?
1602 .into();
1603
1604 let latest_finalized = consensus_graph
1605 .get_height_from_epoch_number(EpochNumber::LatestFinalized.into())
1606 .map_err(into_rpc_err)?
1607 .into();
1608
1609 Ok(RpcStatus {
1610 best_hash: best_info.best_block_hash.into(),
1611 block_number: block_number.into(),
1612 chain_id: best_info.chain_id.in_native_space().into(),
1613 ethereum_space_chain_id: best_info
1614 .chain_id
1615 .in_space(Space::Ethereum)
1616 .into(),
1617 epoch_number: best_info.best_epoch_number.into(),
1618 latest_checkpoint,
1619 latest_confirmed,
1620 latest_finalized,
1621 latest_state,
1622 network_id: self.sync.network.network_id().into(),
1623 pending_tx_number: tx_count.into(),
1624 })
1625 }
1626
1627 async fn get_block_reward_info(
1628 &self, num: EpochNumber,
1629 ) -> RpcResult<Vec<RpcRewardInfo>> {
1630 info!("RPC Request: cfx_getBlockRewardInfo epoch_number={:?}", num);
1631 let epoch_height: U64 = self
1632 .consensus_graph()
1633 .get_height_from_epoch_number(num.clone().into_primitive())
1634 .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?
1635 .into();
1636 let (epoch_later_number, overflow) =
1637 epoch_height.overflowing_add(REWARD_EPOCH_COUNT.into());
1638 if overflow {
1639 return Err(invalid_params(
1640 "epoch",
1641 Some("Epoch number overflows!"),
1642 ));
1643 }
1644 let epoch_later = match self.consensus.get_hash_from_epoch_number(
1645 EpochNumber::Num(epoch_later_number).into_primitive(),
1646 ) {
1647 Ok(hash) => hash,
1648 Err(e) => {
1649 debug!(
1650 "get_block_reward_info: get_hash_from_epoch_number returns error: {}",
1651 e
1652 );
1653 return Err(invalid_params(
1654 "epoch",
1655 Some("Reward not calculated yet!"),
1656 ));
1657 }
1658 };
1659
1660 let blocks = self
1661 .consensus
1662 .get_block_hashes_by_epoch(num.into())
1663 .map_err(into_rpc_err)?;
1664
1665 let mut ret = Vec::new();
1666 for b in blocks {
1667 if let Some(reward_result) = self
1668 .consensus
1669 .data_manager()
1670 .block_reward_result_by_hash_with_epoch(
1671 &b,
1672 &epoch_later,
1673 false,
1674 true,
1675 )
1676 {
1677 if let Some(block_header) =
1678 self.consensus.data_manager().block_header_by_hash(&b)
1679 {
1680 let author = RpcAddress::try_from_h160(
1681 *block_header.author(),
1682 self.network_type,
1683 )
1684 .map_err(|e| invalid_params_rpc_err(e, None::<bool>))?;
1685
1686 ret.push(RpcRewardInfo {
1687 block_hash: b.into(),
1688 author,
1689 total_reward: reward_result.total_reward.into(),
1690 base_reward: reward_result.base_reward.into(),
1691 tx_fee: reward_result.tx_fee.into(),
1692 })
1693 }
1694 }
1695 }
1696 Ok(ret)
1697 }
1698
1699 async fn get_client_version(&self) -> RpcResult<String> {
1700 Ok(parity_version::conflux_client_version!())
1701 }
1702
1703 async fn get_supply_info(
1704 &self, epoch_number: Option<EpochNumber>,
1705 ) -> RpcResult<TokenSupplyInfo> {
1706 let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1707 let state = State::new(
1708 self.consensus
1709 .get_state_db_by_epoch_number(epoch, "epoch")
1710 .map_err(into_rpc_err)?,
1711 )
1712 .map_err(into_rpc_err)?;
1713 let total_issued = state.total_issued_tokens();
1714 let total_staking = state.total_staking_tokens();
1715 let total_collateral = state.total_storage_tokens();
1716 let two_year_unlock_address = genesis_contract_address_two_year();
1717 let four_year_unlock_address = genesis_contract_address_four_year();
1718 let two_year_locked = state
1719 .balance(&two_year_unlock_address)
1720 .unwrap_or(U256::zero());
1721 let four_year_locked = state
1722 .balance(&four_year_unlock_address)
1723 .unwrap_or(U256::zero());
1724 let total_circulating =
1725 total_issued - two_year_locked - four_year_locked;
1726 let total_espace_tokens = state.total_espace_tokens();
1727 Ok(TokenSupplyInfo {
1728 total_circulating,
1729 total_issued,
1730 total_staking,
1731 total_collateral,
1732 total_espace_tokens,
1733 })
1734 }
1735
1736 async fn get_collateral_info(
1737 &self, epoch_number: Option<EpochNumber>,
1738 ) -> RpcResult<StorageCollateralInfo> {
1739 let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1740 let state = State::new(
1741 self.consensus
1742 .get_state_db_by_epoch_number(epoch, "epoch")
1743 .map_err(into_rpc_err)?,
1744 )
1745 .map_err(into_rpc_err)?;
1746 let total_storage_tokens = state.total_storage_tokens();
1747 let converted_storage_points = state.converted_storage_points()
1748 / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1749 let used_storage_points =
1750 state.used_storage_points() / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1751 Ok(StorageCollateralInfo {
1752 total_storage_tokens,
1753 converted_storage_points,
1754 used_storage_points,
1755 })
1756 }
1757
1758 async fn get_fee_burnt(
1759 &self, epoch_number: Option<EpochNumber>,
1760 ) -> RpcResult<U256> {
1761 let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1762 let state_db = self
1763 .consensus
1764 .get_state_db_by_epoch_number(epoch, "epoch_num")
1765 .map_err(into_rpc_err)?;
1766 Ok(state_db
1767 .get_global_param::<TotalBurnt1559>()
1768 .map_err(into_rpc_err)?)
1769 }
1770
1771 async fn get_pos_reward_by_epoch(
1772 &self, epoch: EpochNumber,
1773 ) -> RpcResult<Option<PoSEpochReward>> {
1774 let maybe_block = {
1775 let consensus_graph = self.consensus_graph();
1776 let inner = &*consensus_graph.inner.read();
1777 let epoch_height = match consensus_graph
1778 .get_height_from_epoch_number(epoch.into())
1779 .ok()
1780 {
1781 None => return Ok(None),
1782 Some(v) => v,
1783 };
1784 let pivot_hash =
1785 match inner.get_pivot_hash_from_epoch_number(epoch_height).ok()
1786 {
1787 None => return Ok(None),
1788 Some(v) => v,
1789 };
1790 self.data_man.block_by_hash(&pivot_hash, false)
1791 };
1792
1793 if maybe_block.is_none() {
1794 return Ok(None);
1795 }
1796 let block = maybe_block.unwrap();
1797 if block.block_header.pos_reference().is_none() {
1798 return Ok(None);
1799 }
1800 match self
1801 .data_man
1802 .block_by_hash(block.block_header.parent_hash(), false)
1803 {
1804 None => Ok(None),
1805 Some(parent_block) => {
1806 if parent_block.block_header.pos_reference().is_none() {
1807 return Ok(None);
1808 }
1809 let block_pos_ref = block.block_header.pos_reference().unwrap();
1810 let parent_pos_ref =
1811 parent_block.block_header.pos_reference().unwrap();
1812
1813 if block_pos_ref == parent_pos_ref {
1814 return Ok(None);
1815 }
1816
1817 let hash = HashValue::from_slice(parent_pos_ref.as_bytes())
1818 .map_err(|_| internal_error())?;
1819 let pos_block = self
1820 .pos_handler
1821 .pos_ledger_db()
1822 .get_committed_block_by_hash(&hash)
1823 .map_err(|_| internal_error())?;
1824 let maybe_epoch_rewards =
1825 self.data_man.pos_reward_by_pos_epoch(pos_block.epoch);
1826 if maybe_epoch_rewards.is_none() {
1827 return Ok(None);
1828 }
1829 let epoch_rewards = maybe_epoch_rewards.unwrap();
1830 if epoch_rewards.execution_epoch_hash
1831 != block.block_header.hash()
1832 {
1833 return Ok(None);
1834 }
1835 let reward_info: PoSEpochReward = convert_to_pos_epoch_reward(
1836 epoch_rewards,
1837 self.network_type,
1838 )
1839 .map_err(|_| internal_error())?;
1840 Ok(Some(reward_info))
1841 }
1842 }
1843 }
1844
1845 async fn get_vote_params(
1846 &self, epoch_number: Option<EpochNumber>,
1847 ) -> RpcResult<VoteParamsInfo> {
1848 let epoch = epoch_number.unwrap_or(EpochNumber::LatestState).into();
1849 let state_db = self
1850 .consensus
1851 .get_state_db_by_epoch_number(epoch, "epoch_num")
1852 .map_err(into_rpc_err)?;
1853 let interest_rate = state_db
1854 .get_global_param::<InterestRate>()
1855 .map_err(into_rpc_err)?
1856 / U256::from(BLOCKS_PER_YEAR);
1857 let pow_base_reward = state_db
1858 .get_global_param::<PowBaseReward>()
1859 .map_err(into_rpc_err)?;
1860 let storage_point_prop = state_db
1861 .get_system_storage(&storage_point_prop())
1862 .map_err(into_rpc_err)?;
1863 let base_fee_share_prop = state_db
1864 .get_global_param::<BaseFeeProp>()
1865 .map_err(into_rpc_err)?;
1866 Ok(VoteParamsInfo {
1867 pow_base_reward,
1868 interest_rate,
1869 storage_point_prop,
1870 base_fee_share_prop,
1871 })
1872 }
1873}
1874
1875pub fn check_balance_against_transaction(
1877 user_account: Option<Account>, contract_account: Option<Account>,
1878 is_sponsored: bool, gas_limit: U256, gas_price: U256, storage_limit: U256,
1879) -> CheckBalanceAgainstTransactionResponse {
1880 let sponsor_for_gas = contract_account
1881 .as_ref()
1882 .map(|a| a.sponsor_info.sponsor_for_gas)
1883 .unwrap_or_default();
1884
1885 let gas_bound: cfx_types::U512 = contract_account
1886 .as_ref()
1887 .map(|a| a.sponsor_info.sponsor_gas_bound)
1888 .unwrap_or_default()
1889 .into();
1890
1891 let balance_for_gas: cfx_types::U512 = contract_account
1892 .as_ref()
1893 .map(|a| a.sponsor_info.sponsor_balance_for_gas)
1894 .unwrap_or_default()
1895 .into();
1896
1897 let sponsor_for_collateral = contract_account
1898 .as_ref()
1899 .map(|a| a.sponsor_info.sponsor_for_collateral)
1900 .unwrap_or_default();
1901
1902 let balance_for_collateral: cfx_types::U512 = contract_account
1903 .as_ref()
1904 .map(|a| {
1905 a.sponsor_info.sponsor_balance_for_collateral
1906 + a.sponsor_info.unused_storage_points()
1907 })
1908 .unwrap_or_default()
1909 .into();
1910
1911 let user_balance: cfx_types::U512 =
1912 user_account.map(|a| a.balance).unwrap_or_default().into();
1913
1914 let gas_cost_in_drip = gas_limit.full_mul(gas_price);
1915 let storage_cost_in_drip =
1916 storage_limit.full_mul(*DRIPS_PER_STORAGE_COLLATERAL_UNIT);
1917
1918 let will_pay_tx_fee = !is_sponsored
1919 || sponsor_for_gas.is_zero()
1920 || (gas_cost_in_drip > gas_bound)
1921 || (gas_cost_in_drip > balance_for_gas);
1922
1923 let will_pay_collateral = !is_sponsored
1924 || sponsor_for_collateral.is_zero()
1925 || (storage_cost_in_drip > balance_for_collateral);
1926
1927 let minimum_balance = match (will_pay_tx_fee, will_pay_collateral) {
1928 (false, false) => 0.into(),
1929 (true, false) => gas_cost_in_drip,
1930 (false, true) => storage_cost_in_drip,
1931 (true, true) => gas_cost_in_drip + storage_cost_in_drip,
1932 };
1933
1934 let is_balance_enough = user_balance >= minimum_balance;
1935
1936 CheckBalanceAgainstTransactionResponse {
1937 will_pay_tx_fee,
1938 will_pay_collateral,
1939 is_balance_enough,
1940 }
1941}
1942
1943#[async_trait]
1944impl CfxDebugRpcServer for CfxHandler {
1945 async fn send_transaction(
1946 &self, tx: TransactionRequest, password: Option<String>,
1947 ) -> RpcResult<H256> {
1948 info!("RPC Request: cfx_sendTransaction, tx = {:?}", tx);
1949 let signed = self
1950 .prepare_transaction(tx, password)
1951 .map_err(into_rpc_err)?;
1952 self.send_transaction_with_signature(signed)
1953 .map_err(into_rpc_err)
1954 }
1955
1956 async fn accounts(&self) -> RpcResult<Vec<RpcAddress>> {
1957 let accounts: Vec<Address> = self.accounts.accounts().map_err(|e| {
1958 into_rpc_err(format!(
1959 "Could not fetch accounts. With error {:?}",
1960 e
1961 ))
1962 })?;
1963 Ok(accounts
1964 .into_iter()
1965 .map(|addr| RpcAddress::try_from_h160(addr, self.network_type))
1966 .collect::<Result<_, _>>()
1967 .map_err(|e| into_rpc_err(e))?)
1968 }
1969
1970 async fn new_account(&self, password: String) -> RpcResult<RpcAddress> {
1971 let address =
1972 self.accounts.new_account(&password.into()).map_err(|e| {
1973 into_rpc_err(format!(
1974 "Could not create account. With error {:?}",
1975 e
1976 ))
1977 })?;
1978 RpcAddress::try_from_h160(address, self.network_type)
1979 .map_err(into_rpc_err)
1980 }
1981
1982 async fn unlock_account(
1983 &self, address: RpcAddress, password: String, duration: Option<U128>,
1984 ) -> RpcResult<bool> {
1985 self.check_address_network(address.network)?;
1986 let account: H160 = address.into();
1987 let store = self.accounts.clone();
1988
1989 let duration = match duration {
1990 None => None,
1991 Some(duration) => {
1992 let duration: U128 = duration.into();
1993 let v = duration.low_u64() as u32;
1994 if duration != v.into() {
1995 return Err(invalid_params_msg("invalid duration number"));
1996 } else {
1997 Some(v)
1998 }
1999 }
2000 };
2001
2002 let r = match duration {
2003 Some(0) => {
2004 store.unlock_account_permanently(account, password.into())
2005 }
2006 Some(d) => store.unlock_account_timed(
2007 account,
2008 password.into(),
2009 Duration::from_secs(d.into()),
2010 ),
2011 None => store.unlock_account_timed(
2012 account,
2013 password.into(),
2014 Duration::from_secs(300),
2015 ),
2016 };
2017 match r {
2018 Ok(_) => Ok(true),
2019 Err(err) => {
2020 warn!("Unable to unlock the account. With error {:?}", err);
2021 Err(internal_error())
2022 }
2023 }
2024 }
2025
2026 async fn lock_account(&self, address: RpcAddress) -> RpcResult<bool> {
2027 self.check_address_network(address.network)?;
2028 match self.accounts.lock_account(address.into()) {
2029 Ok(_) => Ok(true),
2030 Err(err) => {
2031 warn!("Unable to lock the account. With error {:?}", err);
2032 Err(internal_error())
2033 }
2034 }
2035 }
2036
2037 fn sign(
2038 &self, data: Bytes, address: RpcAddress, password: Option<String>,
2039 ) -> RpcResult<H520> {
2040 self.check_address_network(address.network)?;
2041 let message = eth_data_hash(data.0);
2042 let password = password.map(Password::from);
2043 let signature =
2044 match self.accounts.sign(address.into(), password, message) {
2045 Ok(signature) => signature,
2046 Err(err) => {
2047 warn!("Unable to sign the message. With error {:?}", err);
2048 return Err(internal_error());
2049 }
2050 };
2051 Ok(H520(signature.into()))
2052 }
2053
2054 fn sign_transaction(
2055 &self, tx: TransactionRequest, password: Option<String>,
2056 ) -> RpcResult<String> {
2057 let tx = self.prepare_transaction(tx, password).map_err(|e| {
2058 invalid_params(
2059 "tx",
2060 Some(format!("failed to sign transaction: {:?}", e)),
2061 )
2062 })?;
2063 let raw_tx = rlp::encode(&tx);
2064 Ok(format!("0x{}", raw_tx.to_hex::<String>()))
2065 }
2066
2067 async fn epoch_receipts(
2068 &self, epoch: BlockHashOrEpochNumber,
2069 include_eth_receipts: Option<bool>,
2070 ) -> RpcResult<Option<Vec<Vec<RpcReceipt>>>> {
2071 info!("RPC Request: cfx_getEpochReceipts({:?})", epoch);
2072
2073 let hashes = self
2074 .consensus
2075 .get_block_hashes_by_epoch_or_block_hash(epoch.into())
2076 .map_err(into_rpc_err)?;
2077
2078 let pivot_hash =
2079 *hashes.last().ok_or(into_rpc_err("Inconsistent state"))?;
2080 let mut epoch_receipts = vec![];
2081
2082 for h in hashes {
2083 epoch_receipts.push(
2084 match self
2085 .prepare_block_receipts(
2086 h,
2087 pivot_hash,
2088 include_eth_receipts.unwrap_or(false),
2089 )
2090 .map_err(into_rpc_err)?
2091 {
2092 None => return Ok(None),
2093 Some(rs) => rs,
2094 },
2095 );
2096 }
2097
2098 self.check_response_size(&epoch_receipts)
2099 .map_err(into_rpc_err)?;
2100
2101 Ok(Some(epoch_receipts))
2102 }
2103
2104 async fn account_pending_info(
2105 &self, address: RpcAddress,
2106 ) -> RpcResult<Option<AccountPendingInfo>> {
2107 info!("RPC Request: cfx_getAccountPendingInfo({:?})", address);
2108 self.check_address_network(address.network)?;
2109
2110 match self.tx_pool.get_account_pending_info(
2111 &Address::from(address).with_native_space(),
2112 ) {
2113 None => Ok(None),
2114 Some((
2115 local_nonce,
2116 pending_count,
2117 pending_nonce,
2118 next_pending_tx,
2119 )) => Ok(Some(AccountPendingInfo {
2120 local_nonce: local_nonce.into(),
2121 pending_count: pending_count.into(),
2122 pending_nonce: pending_nonce.into(),
2123 next_pending_tx: next_pending_tx.into(),
2124 })),
2125 }
2126 }
2127
2128 async fn account_pending_transactions(
2129 &self, address: RpcAddress, maybe_start_nonce: Option<U256>,
2130 maybe_limit: Option<U64>,
2131 ) -> RpcResult<AccountPendingTransactions> {
2132 info!(
2133 "RPC Request: cfx_getAccountPendingTransactions(addr={:?}, start_nonce={:?}, limit={:?})",
2134 address, maybe_start_nonce, maybe_limit
2135 );
2136 self.check_address_network(address.network)?;
2137
2138 let (pending_txs, tx_status, pending_count) = self
2139 .tx_pool
2140 .get_account_pending_transactions(
2141 &Address::from(address).with_native_space(),
2142 maybe_start_nonce,
2143 maybe_limit.map(|limit| limit.as_usize()),
2144 self.consensus.best_epoch_number(),
2145 )
2146 .map_err(into_rpc_err)?;
2147
2148 Ok(AccountPendingTransactions {
2149 pending_transactions: pending_txs
2150 .into_iter()
2151 .map(|tx| {
2152 RpcTransaction::from_signed(&tx, None, self.network_type)
2153 })
2154 .collect::<Result<Vec<RpcTransaction>, String>>()
2155 .map_err(|e| into_rpc_err(e))?,
2156 first_tx_status: tx_status,
2157 pending_count: pending_count.into(),
2158 })
2159 }
2160}