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