1use crate::rpc::{
6 errors::{
7 internal_error_msg, invalid_params_check, invalid_params_detail,
8 invalid_params_msg,
9 },
10 types::{
11 cfx::{
12 check_rpc_address_network, check_two_rpc_address_network_match,
13 CfxFeeHistory,
14 },
15 pos::PoSEpochReward,
16 PoSEconomics, RpcAddress, SponsorInfo, StatOnGasLoad, TokenSupplyInfo,
17 VoteParamsInfo, WrapTransaction, U64 as HexU64,
18 },
19};
20use blockgen::BlockGeneratorTestApi;
21use cfx_execute_helper::estimation::{decode_error, EstimateExt};
22use cfx_executor::{
23 executive::{ExecutionError, ExecutionOutcome, TxDropError},
24 internal_contract::storage_point_prop,
25};
26use cfx_rpc_eth_types::Transaction as EthTransaction;
27use cfx_rpc_utils::error::jsonrpc_error_helpers::error_object_owned_to_jsonrpc_error;
28use cfx_statedb::{
29 global_params::{
30 AccumulateInterestRate, BaseFeeProp, DistributablePoSInterest,
31 InterestRate, LastDistributeBlock, PowBaseReward, TotalBurnt1559,
32 TotalPosStaking,
33 },
34 StateDbExt,
35};
36use cfx_types::{
37 Address, AddressSpaceUtil, BigEndianHash, Space, H256, H520, U128, U256,
38 U64,
39};
40use cfx_util_macros::bail;
41use cfx_vm_types::Error as VmError;
42use cfxcore::{
43 block_data_manager::BlockExecutionResult,
44 errors::account_result_to_rpc_result,
45 state_exposer::STATE_EXPOSER,
46 transaction_pool::TransactionPoolError,
47 verification::{compute_epoch_receipt_proof, EpochReceiptProof},
48 ConsensusGraph, PeerInfo, SharedConsensusGraph,
49 SharedSynchronizationService, SharedTransactionPool,
50};
51use cfxcore_accounts::AccountProvider;
52use delegate::delegate;
53use diem_types::transaction::TransactionPayload;
54use jsonrpc_core::{BoxFuture, Error as JsonRpcError, Result as JsonRpcResult};
55use log::{debug, error, info, trace, warn};
56use network::{
57 node_table::{Node, NodeId},
58 throttling, SessionDetails, UpdateNodeOperation,
59};
60use parking_lot::Mutex;
61use primitives::{
62 filter::LogFilter, receipt::EVM_SPACE_SUCCESS, Account, Block, BlockHeader,
63 BlockReceipts, DepositInfo, SignedTransaction, StorageKey, StorageRoot,
64 StorageValue, TransactionIndex, TransactionStatus,
65 TransactionWithSignature, VoteStakeInfo,
66};
67use random_crash::*;
68use rlp::Rlp;
69use rustc_hex::ToHex;
70use std::{
71 collections::BTreeMap, net::SocketAddr, sync::Arc, thread, time::Duration,
72};
73use txgen::{DirectTransactionGenerator, TransactionGenerator};
74use crate::{
76 common::delegate_convert,
77 rpc::{
78 errors::{
79 call_execution_error, internal_error, invalid_params,
80 pivot_assumption_failed, request_rejected_in_catch_up_mode,
81 },
82 impls::{
83 common::{self, RpcImpl as CommonImpl},
84 RpcImplConfiguration,
85 },
86 traits::{cfx::Cfx, debug::LocalRpc, test::TestRpc},
87 types::{
88 pos::Block as PosBlock, Account as RpcAccount, AccountPendingInfo,
89 AccountPendingTransactions, BlameInfo, Block as RpcBlock,
90 BlockHashOrEpochNumber, Bytes, CfxRpcLogFilter,
91 CheckBalanceAgainstTransactionResponse,
92 ConsensusGraphBlockExecutionState, ConsensusGraphBlockState,
93 ConsensusGraphStates, EpochNumber,
94 EstimateGasAndCollateralResponse, Log as RpcLog, PackedOrExecuted,
95 Receipt as RpcReceipt, RewardInfo as RpcRewardInfo,
96 Status as RpcStatus, StorageCollateralInfo, SyncGraphBlockState,
97 SyncGraphStates, Transaction as RpcTransaction, TransactionRequest,
98 },
99 CoreResult,
100 },
101};
102use cfx_addr::Network;
103use cfx_execute_helper::estimation::EstimateRequest;
104use cfx_executor::state::State;
105use cfx_parameters::{
106 consensus_internal::REWARD_EPOCH_COUNT,
107 genesis::{
108 genesis_contract_address_four_year, genesis_contract_address_two_year,
109 },
110 staking::{BLOCKS_PER_YEAR, DRIPS_PER_STORAGE_COLLATERAL_UNIT},
111};
112use cfx_storage::state::StateDbGetOriginalMethods;
113use cfxcore::{
114 consensus::{MaybeExecutedTxExtraInfo, TransactionInfo},
115 consensus_parameters::DEFERRED_STATE_EPOCH_COUNT,
116};
117use diem_types::account_address::AccountAddress;
118use serde::Serialize;
119
120#[derive(Debug)]
121pub(crate) struct BlockExecInfo {
122 pub(crate) block_receipts: Arc<BlockReceipts>,
123 pub(crate) block: Arc<Block>,
124 pub(crate) epoch_number: u64,
125 pub(crate) maybe_state_root: Option<H256>,
126 pub(crate) pivot_header: Arc<BlockHeader>,
127}
128
129pub struct RpcImpl {
130 pub config: RpcImplConfiguration,
131 pub consensus: SharedConsensusGraph,
132 pub sync: SharedSynchronizationService,
133 block_gen: BlockGeneratorTestApi,
134 pub tx_pool: SharedTransactionPool,
135 maybe_txgen: Option<Arc<TransactionGenerator>>,
136 maybe_direct_txgen: Option<Arc<Mutex<DirectTransactionGenerator>>>,
137 accounts: Arc<AccountProvider>,
138}
139
140impl RpcImpl {
141 pub fn new(
142 consensus: SharedConsensusGraph, sync: SharedSynchronizationService,
143 block_gen: BlockGeneratorTestApi, tx_pool: SharedTransactionPool,
144 maybe_txgen: Option<Arc<TransactionGenerator>>,
145 maybe_direct_txgen: Option<Arc<Mutex<DirectTransactionGenerator>>>,
146 config: RpcImplConfiguration, accounts: Arc<AccountProvider>,
147 ) -> Self {
148 RpcImpl {
149 consensus,
150 sync,
151 block_gen,
152 tx_pool,
153 maybe_txgen,
154 maybe_direct_txgen,
155 config,
156 accounts,
157 }
158 }
159
160 fn consensus_graph(&self) -> &ConsensusGraph { &self.consensus }
161
162 fn check_address_network(&self, network: Network) -> CoreResult<()> {
163 invalid_params_check(
164 "address",
165 check_rpc_address_network(
166 Some(network),
167 self.sync.network.get_network_type(),
168 ),
169 )
170 .map_err(|e| e.into())
171 }
172
173 fn get_epoch_number_with_pivot_check(
178 &self, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
179 ) -> CoreResult<EpochNumber> {
180 match block_hash_or_epoch_number {
181 Some(BlockHashOrEpochNumber::BlockHashWithOption {
182 hash,
183 require_pivot,
184 }) => {
185 let epoch_number = self
187 .consensus_graph()
188 .get_block_epoch_number_with_pivot_check(
189 &hash,
190 require_pivot.unwrap_or(true),
191 )?;
192 Ok(EpochNumber::Num(U64::from(epoch_number)))
193 }
194 Some(BlockHashOrEpochNumber::EpochNumber(epoch_number)) => {
195 Ok(epoch_number)
196 }
197 None => Ok(EpochNumber::LatestState),
198 }
199 }
200
201 fn code(
202 &self, address: RpcAddress,
203 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
204 ) -> CoreResult<Bytes> {
205 self.check_address_network(address.network)?;
206 let epoch_num = self
207 .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
208 .into();
209
210 info!(
211 "RPC Request: cfx_getCode address={:?} epoch_num={:?}",
212 address, epoch_num
213 );
214
215 let state_db = self
216 .consensus
217 .get_state_db_by_epoch_number(epoch_num, "num")?;
218
219 let address = address.hex_address.with_native_space();
220
221 let code = match state_db.get_account(&address)? {
222 Some(acc) => match state_db.get_code(&address, &acc.code_hash)? {
223 Some(code) => (*code.code).clone(),
224 _ => vec![],
225 },
226 None => vec![],
227 };
228
229 Ok(Bytes::new(code))
230 }
231
232 fn balance(
233 &self, address: RpcAddress,
234 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
235 ) -> CoreResult<U256> {
236 self.check_address_network(address.network)?;
237 let epoch_num = self
238 .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
239 .into();
240 info!(
243 "RPC Request: cfx_getBalance address={:?} epoch_num={:?}",
244 address, epoch_num
245 );
246
247 let state_db = self
248 .consensus
249 .get_state_db_by_epoch_number(epoch_num, "num")?;
250 let acc =
251 state_db.get_account(&address.hex_address.with_native_space())?;
252
253 Ok(acc.map_or(U256::zero(), |acc| acc.balance).into())
254 }
255
256 fn admin(
257 &self, address: RpcAddress, num: Option<EpochNumber>,
258 ) -> CoreResult<Option<RpcAddress>> {
259 self.check_address_network(address.network)?;
260 let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
261 let network = address.network;
262
263 info!(
264 "RPC Request: cfx_getAdmin address={:?} epoch_num={:?}",
265 address, epoch_num
266 );
267
268 let state_db = self
269 .consensus
270 .get_state_db_by_epoch_number(epoch_num, "num")?;
271
272 match state_db.get_account(&address.hex_address.with_native_space())? {
273 None => Ok(None),
274 Some(acc) => {
275 Ok(Some(RpcAddress::try_from_h160(acc.admin, network)?))
276 }
277 }
278 }
279
280 fn sponsor_info(
281 &self, address: RpcAddress, num: Option<EpochNumber>,
282 ) -> CoreResult<SponsorInfo> {
283 self.check_address_network(address.network)?;
284 let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
285 let network = address.network;
286
287 info!(
288 "RPC Request: cfx_getSponsorInfo address={:?} epoch_num={:?}",
289 address, epoch_num
290 );
291
292 let state_db = self
293 .consensus
294 .get_state_db_by_epoch_number(epoch_num, "num")?;
295
296 match state_db.get_account(&address.hex_address.with_native_space())? {
297 None => Ok(SponsorInfo::default(network)?),
298 Some(acc) => Ok(SponsorInfo::try_from(acc.sponsor_info, network)?),
299 }
300 }
301
302 fn staking_balance(
303 &self, address: RpcAddress, num: Option<EpochNumber>,
304 ) -> CoreResult<U256> {
305 self.check_address_network(address.network)?;
306 let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
307
308 info!(
309 "RPC Request: cfx_getStakingBalance address={:?} epoch_num={:?}",
310 address, epoch_num
311 );
312
313 let state_db = self
314 .consensus
315 .get_state_db_by_epoch_number(epoch_num, "num")?;
316 let acc =
317 state_db.get_account(&address.hex_address.with_native_space())?;
318
319 Ok(acc.map_or(U256::zero(), |acc| acc.staking_balance).into())
320 }
321
322 fn deposit_list(
323 &self, address: RpcAddress, num: Option<EpochNumber>,
324 ) -> CoreResult<Vec<DepositInfo>> {
325 self.check_address_network(address.network)?;
326 let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
327
328 info!(
329 "RPC Request: cfx_getDepositList address={:?} epoch_num={:?}",
330 address, epoch_num
331 );
332
333 let state_db = self
334 .consensus
335 .get_state_db_by_epoch_number(epoch_num, "num")?;
336
337 match state_db
338 .get_deposit_list(&address.hex_address.with_native_space())?
339 {
340 None => Ok(vec![]),
341 Some(deposit_list) => Ok(deposit_list.0),
342 }
343 }
344
345 fn vote_list(
346 &self, address: RpcAddress, num: Option<EpochNumber>,
347 ) -> CoreResult<Vec<VoteStakeInfo>> {
348 self.check_address_network(address.network)?;
349 let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
350
351 info!(
352 "RPC Request: cfx_getVoteList address={:?} epoch_num={:?}",
353 address, epoch_num
354 );
355
356 let state_db = self
357 .consensus
358 .get_state_db_by_epoch_number(epoch_num, "num")?;
359
360 match state_db
361 .get_vote_list(&address.hex_address.with_native_space())?
362 {
363 None => Ok(vec![]),
364 Some(vote_list) => Ok(vote_list.0),
365 }
366 }
367
368 fn collateral_for_storage(
369 &self, address: RpcAddress, num: Option<EpochNumber>,
370 ) -> CoreResult<U256> {
371 self.check_address_network(address.network)?;
372 let epoch_num = num.unwrap_or(EpochNumber::LatestState).into();
373
374 info!(
375 "RPC Request: cfx_getCollateralForStorage address={:?} epoch_num={:?}",
376 address, epoch_num
377 );
378
379 let state_db = self
380 .consensus
381 .get_state_db_by_epoch_number(epoch_num, "num")?;
382 let acc =
383 state_db.get_account(&address.hex_address.with_native_space())?;
384
385 Ok(acc
386 .map_or(U256::zero(), |acc| acc.collateral_for_storage)
387 .into())
388 }
389
390 fn account(
392 &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
393 ) -> CoreResult<RpcAccount> {
394 self.check_address_network(address.network)?;
395 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
396 let network = address.network;
397
398 info!(
399 "RPC Request: cfx_getAccount address={:?} epoch_num={:?}",
400 address, epoch_num
401 );
402
403 let address = &address.hex_address;
404
405 let state_db = self
406 .consensus
407 .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
408
409 let account =
410 match state_db.get_account(&address.with_native_space())? {
411 Some(t) => t,
412 None => account_result_to_rpc_result(
413 "address",
414 Ok(Account::new_empty_with_balance(
415 &address.with_native_space(),
416 &U256::zero(), &U256::zero(), )),
419 )?,
420 };
421
422 Ok(RpcAccount::try_from(account, network)?)
423 }
424
425 fn interest_rate(
427 &self, epoch_num: Option<EpochNumber>,
428 ) -> CoreResult<U256> {
429 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
430 let state_db = self
431 .consensus
432 .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
433
434 Ok(state_db.get_global_param::<InterestRate>()?.into())
435 }
436
437 fn accumulate_interest_rate(
439 &self, epoch_num: Option<EpochNumber>,
440 ) -> CoreResult<U256> {
441 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
442 let state_db = self
443 .consensus
444 .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
445
446 Ok(state_db
447 .get_global_param::<AccumulateInterestRate>()?
448 .into())
449 }
450
451 fn pos_economics(
453 &self, epoch_num: Option<EpochNumber>,
454 ) -> CoreResult<PoSEconomics> {
455 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
456 let state_db = self
457 .consensus
458 .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
459
460 Ok(PoSEconomics {
461 total_pos_staking_tokens: state_db
462 .get_global_param::<TotalPosStaking>()?,
463 distributable_pos_interest: state_db
464 .get_global_param::<DistributablePoSInterest>()?,
465 last_distribute_block: U64::from(
466 state_db.get_global_param::<LastDistributeBlock>()?.as_u64(),
467 ),
468 })
469 }
470
471 fn send_raw_transaction(&self, raw: Bytes) -> CoreResult<H256> {
472 info!("RPC Request: cfx_sendRawTransaction len={:?}", raw.0.len());
473 debug!("RawTransaction bytes={:?}", raw);
474
475 let tx: TransactionWithSignature = invalid_params_check(
476 "raw",
477 TransactionWithSignature::from_raw(&raw.into_vec()),
478 )?;
479
480 if tx.recover_public().is_err() {
481 bail!(invalid_params_detail(
482 "tx",
483 "Can not recover pubkey for Ethereum like tx"
484 ));
485 }
486
487 let r = self.send_transaction_with_signature(tx);
488 if r.is_ok() && self.config.dev_pack_tx_immediately {
489 for _ in 0..DEFERRED_STATE_EPOCH_COUNT {
491 let generated = self.generate_one_block(
492 1, self.sync
494 .get_synchronization_graph()
495 .verification_config
496 .max_block_size_in_bytes,
497 )?;
498 loop {
499 if self.consensus.best_block_hash() == generated {
503 break;
504 } else {
505 thread::sleep(Duration::from_millis(10));
506 }
507 }
508 }
509 }
510 r
511 }
512
513 fn storage_at(
514 &self, address: RpcAddress, position: U256,
515 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
516 ) -> CoreResult<Option<H256>> {
517 self.check_address_network(address.network)?;
518 let epoch_num = self
519 .get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?
520 .into();
521
522 info!(
523 "RPC Request: cfx_getStorageAt address={:?}, position={:?}, epoch_num={:?})",
524 address, position, epoch_num
525 );
526
527 let state_db = self
528 .consensus
529 .get_state_db_by_epoch_number(epoch_num, "epoch_num")?;
530
531 let position: H256 = H256::from_uint(&position);
532
533 let key = StorageKey::new_storage_key(
534 &address.hex_address,
535 position.as_ref(),
536 )
537 .with_native_space();
538
539 Ok(match state_db.get::<StorageValue>(key)? {
540 Some(entry) => Some(H256::from_uint(&entry.value).into()),
541 None => None,
542 })
543 }
544
545 fn send_transaction_with_signature(
546 &self, tx: TransactionWithSignature,
547 ) -> CoreResult<H256> {
548 if self.sync.catch_up_mode() {
549 warn!("Ignore send_transaction request {}. Cannot send transaction when the node is still in catch-up mode.", tx.hash());
550 bail!(request_rejected_in_catch_up_mode(None));
551 }
552 let (signed_trans, failed_trans) =
553 self.tx_pool.insert_new_transactions(vec![tx]);
554
555 match (signed_trans.len(), failed_trans.len()) {
556 (0, 0) => {
557 debug!("insert_new_transactions ignores inserted transactions");
558 bail!(invalid_params_detail("tx", "tx already exist"))
559 }
560 (0, 1) => {
561 let tx_err = failed_trans.values().next().unwrap();
562 if let TransactionPoolError::StateDbError(err) = tx_err {
563 bail!(internal_error(err))
564 } else {
565 bail!(invalid_params_detail("tx", tx_err.to_string()))
566 }
567 }
568 (1, 0) => {
569 let tx_hash = signed_trans[0].hash();
570 self.sync.append_received_transactions(signed_trans);
571 Ok(tx_hash)
572 }
573 _ => {
574 error!("insert_new_transactions failed, invalid length of returned result vector {}", signed_trans.len() + failed_trans.len());
576 bail!(internal_error(format!(
577 "unexpected insert result, {} returned items",
578 signed_trans.len() + failed_trans.len()
579 )))
580 }
581 }
582 }
583
584 fn prepare_transaction(
585 &self, mut tx: TransactionRequest, password: Option<String>,
586 ) -> CoreResult<TransactionWithSignature> {
587 let consensus_graph = self.consensus_graph();
588 tx.check_rpc_address_network(
589 "tx",
590 self.sync.network.get_network_type(),
591 )
592 .map_err(error_object_owned_to_jsonrpc_error)?;
593
594 if tx.nonce.is_none() {
595 let nonce = consensus_graph.next_nonce(
596 Address::from(tx.from.clone().ok_or("from should have")?)
597 .with_native_space(),
598 BlockHashOrEpochNumber::EpochNumber(EpochNumber::LatestState)
599 .into_primitive(),
600 "internal EpochNumber::LatestState",
604 )?;
605 tx.nonce.replace(nonce.into());
606 debug!("after loading nonce in latest state, tx = {:?}", tx);
607 }
608
609 let epoch_height = consensus_graph.best_epoch_number();
610 let chain_id = consensus_graph.best_chain_id();
611
612 if tx.gas.is_none() || tx.storage_limit.is_none() {
613 let estimate =
614 self.estimate_gas_and_collateral(tx.clone(), None)?;
615
616 if tx.gas.is_none() {
617 tx.gas.replace(estimate.gas_used);
618 }
619
620 if tx.storage_limit.is_none() {
621 tx.storage_limit.replace(estimate.storage_collateralized);
622 }
623 }
624
625 if tx.transaction_type.is_none() && tx.gas_price.is_none() {
627 let gas_price = consensus_graph.gas_price(Space::Native);
628 if gas_price.is_some() {
629 tx.gas_price.replace(gas_price.unwrap());
630 }
631 }
632
633 tx.sign_with(
634 epoch_height,
635 chain_id.in_native_space(),
636 password,
637 self.accounts.clone(),
638 )
639 .map_err(Into::into)
640 }
641
642 fn send_transaction(
643 &self, tx: TransactionRequest, password: Option<String>,
644 ) -> CoreResult<H256> {
645 info!("RPC Request: cfx_sendTransaction, tx = {:?}", tx);
646
647 self.prepare_transaction(tx, password)
648 .and_then(|tx| self.send_transaction_with_signature(tx))
649 }
650
651 pub fn sign_transaction(
652 &self, tx: TransactionRequest, password: Option<String>,
653 ) -> CoreResult<String> {
654 let tx = self.prepare_transaction(tx, password).map_err(|e| {
655 invalid_params("tx", format!("failed to sign transaction: {:?}", e))
656 })?;
657 let raw_tx = rlp::encode(&tx);
658 Ok(format!("0x{}", raw_tx.to_hex::<String>()))
659 }
660
661 fn storage_root(
662 &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
663 ) -> CoreResult<Option<StorageRoot>> {
664 self.check_address_network(address.network)?;
665 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState).into();
666
667 info!(
668 "RPC Request: cfx_getStorageRoot address={:?} epoch={:?}",
669 address, epoch_num
670 );
671
672 let root = self
673 .consensus
674 .get_storage_state_by_epoch_number(epoch_num, "epoch_num")?
675 .get_original_storage_root(
676 &address.hex_address.with_native_space(),
677 )?;
678
679 Ok(Some(root))
680 }
681
682 fn send_usable_genesis_accounts(
683 &self, account_start_index: usize,
684 ) -> CoreResult<Bytes> {
685 info!(
686 "RPC Request: send_usable_genesis_accounts start from {:?}",
687 account_start_index
688 );
689 match self.maybe_txgen.as_ref() {
690 None => {
691 let mut rpc_error = JsonRpcError::method_not_found();
693 rpc_error.message = "send_usable_genesis_accounts only allowed in test or dev mode with txgen set.".into();
694 bail!(rpc_error)
695 }
696 Some(txgen) => {
697 txgen.set_genesis_accounts_start_index(account_start_index);
698 Ok(Bytes::new("1".into()))
699 }
700 }
701 }
702
703 pub fn transaction_by_hash(
704 &self, hash: H256,
705 ) -> CoreResult<Option<RpcTransaction>> {
706 let hash: H256 = hash.into();
707 info!("RPC Request: cfx_getTransactionByHash({:?})", hash);
708
709 if let Some((
710 tx,
711 TransactionInfo {
712 tx_index,
713 maybe_executed_extra_info,
714 },
715 )) = self.consensus.get_signed_tx_and_tx_info(&hash)
716 {
717 if tx.space() == Space::Ethereum || tx_index.is_phantom {
718 return Ok(None);
719 }
720
721 let packed_or_executed = match maybe_executed_extra_info {
722 None => PackedOrExecuted::Packed(tx_index),
723 Some(MaybeExecutedTxExtraInfo {
724 receipt,
725 block_number: _,
726 prior_gas_used,
727 tx_exec_error_msg,
728 }) => {
729 let epoch_number = self
730 .consensus
731 .get_block_epoch_number(&tx_index.block_hash);
732
733 let maybe_state_root = self
734 .consensus
735 .data_manager()
736 .get_executed_state_root(&tx_index.block_hash);
737
738 let maybe_base_price = self
741 .consensus
742 .data_manager()
743 .block_header_by_hash(&tx_index.block_hash)
744 .and_then(|x| x.base_price());
745
746 PackedOrExecuted::Executed(RpcReceipt::new(
747 tx.clone(),
748 receipt,
749 tx_index,
750 prior_gas_used,
751 epoch_number,
752 maybe_base_price,
753 maybe_state_root,
754 tx_exec_error_msg,
755 *self.sync.network.get_network_type(),
756 false,
757 false,
758 )?)
759 }
760 };
761 let rpc_tx = RpcTransaction::from_signed(
762 &tx,
763 Some(packed_or_executed),
764 *self.sync.network.get_network_type(),
765 )?;
766
767 return Ok(Some(rpc_tx));
768 }
769
770 if let Some(tx) = self.tx_pool.get_transaction(&hash) {
771 if tx.space() == Space::Ethereum {
772 return Ok(None);
773 }
774
775 let rpc_tx = RpcTransaction::from_signed(
776 &tx,
777 None,
778 *self.sync.network.get_network_type(),
779 )?;
780 return Ok(Some(rpc_tx));
781 }
782
783 Ok(None)
784 }
785
786 fn get_block_execution_info(
787 &self, block_hash: &H256,
788 ) -> CoreResult<Option<BlockExecInfo>> {
789 let consensus_graph = self.consensus_graph();
790
791 let (pivot_hash, block_receipts, maybe_state_root) =
792 match consensus_graph.get_block_execution_info(block_hash) {
793 None => return Ok(None),
794 Some((exec_res, maybe_state_root)) => {
795 (exec_res.0, exec_res.1.block_receipts, maybe_state_root)
796 }
797 };
798
799 let epoch_number = self
800 .consensus
801 .data_manager()
802 .block_header_by_hash(&pivot_hash)
803 .ok_or("Inconsistent state")?
805 .height();
806
807 if epoch_number > consensus_graph.best_executed_state_epoch_number() {
808 return Ok(None);
810 }
811
812 let block = self
813 .consensus
814 .data_manager()
815 .block_by_hash(&block_hash, false )
816 .ok_or("Inconsistent state")?;
818
819 if block_receipts.receipts.len() != block.transactions.len() {
820 bail!("Inconsistent state");
821 }
822
823 let pivot_header = if let Some(x) = self
824 .consensus
825 .data_manager()
826 .block_header_by_hash(&pivot_hash)
827 {
828 x
829 } else {
830 warn!("Cannot find pivot header when get block execution info: pivot hash {:?}", pivot_hash);
831 return Ok(None);
832 };
833
834 Ok(Some(BlockExecInfo {
835 block_receipts,
836 block,
837 epoch_number,
838 maybe_state_root,
839 pivot_header,
840 }))
841 }
842
843 fn construct_rpc_receipt(
844 &self, tx_index: TransactionIndex, exec_info: &BlockExecInfo,
845 include_eth_receipt: bool, include_accumulated_gas_used: bool,
846 ) -> CoreResult<Option<RpcReceipt>> {
847 let id = tx_index.real_index;
848
849 if id >= exec_info.block.transactions.len()
850 || id >= exec_info.block_receipts.receipts.len()
851 || id >= exec_info.block_receipts.tx_execution_error_messages.len()
852 {
853 bail!("Inconsistent state");
854 }
855
856 let tx = &exec_info.block.transactions[id];
857
858 if !include_eth_receipt
859 && (tx.space() == Space::Ethereum || tx_index.is_phantom)
860 {
861 return Ok(None);
862 }
863
864 let prior_gas_used = match id {
865 0 => U256::zero(),
866 id => {
867 exec_info.block_receipts.receipts[id - 1].accumulated_gas_used
868 }
869 };
870
871 let tx_exec_error_msg =
872 match &exec_info.block_receipts.tx_execution_error_messages[id] {
873 msg if msg.is_empty() => None,
874 msg => Some(msg.clone()),
875 };
876
877 let receipt = RpcReceipt::new(
878 (**tx).clone(),
879 exec_info.block_receipts.receipts[id].clone(),
880 tx_index,
881 prior_gas_used,
882 Some(exec_info.epoch_number),
883 exec_info.pivot_header.base_price(),
884 exec_info.maybe_state_root.clone(),
885 tx_exec_error_msg,
886 *self.sync.network.get_network_type(),
887 include_eth_receipt,
888 include_accumulated_gas_used,
889 )?;
890
891 Ok(Some(receipt))
892 }
893
894 fn prepare_receipt(&self, tx_hash: H256) -> CoreResult<Option<RpcReceipt>> {
895 let tx_index =
902 match self.consensus.data_manager().transaction_index_by_hash(
903 &tx_hash, false, ) {
905 None => return Ok(None),
906 Some(tx_index) => tx_index,
907 };
908
909 if tx_index.is_phantom {
910 return Ok(None);
911 }
912
913 let exec_info =
914 match self.get_block_execution_info(&tx_index.block_hash)? {
915 None => return Ok(None),
916 Some(res) => res,
917 };
918
919 let receipt =
920 self.construct_rpc_receipt(tx_index, &exec_info, false, true)?;
921 if let Some(r) = &receipt {
922 if r.outcome_status
925 == TransactionStatus::Skipped.in_space(Space::Native).into()
926 {
927 return Ok(None);
928 }
929 }
930 Ok(receipt)
931 }
932
933 fn prepare_block_receipts(
934 &self, block_hash: H256, pivot_assumption: H256,
935 include_eth_receipt: bool,
936 ) -> CoreResult<Option<Vec<RpcReceipt>>> {
937 let exec_info = match self.get_block_execution_info(&block_hash)? {
938 None => return Ok(None), Some(res) => res,
940 };
941
942 if pivot_assumption != exec_info.pivot_header.hash() {
944 bail!(pivot_assumption_failed(
945 pivot_assumption,
946 exec_info.pivot_header.hash()
947 ));
948 }
949
950 let mut rpc_receipts = vec![];
951
952 let iter = exec_info
953 .block
954 .transactions
955 .iter()
956 .enumerate()
957 .filter(|(_, tx)| {
958 if include_eth_receipt {
959 true
960 } else {
961 tx.space() == Space::Native
962 }
963 })
964 .enumerate();
965
966 for (new_index, (original_index, _)) in iter {
967 if let Some(receipt) = self.construct_rpc_receipt(
968 TransactionIndex {
969 block_hash,
970 real_index: original_index,
971 is_phantom: false,
972 rpc_index: Some(new_index),
973 },
974 &exec_info,
975 include_eth_receipt,
976 true,
977 )? {
978 rpc_receipts.push(receipt);
979 }
980 }
981
982 Ok(Some(rpc_receipts))
983 }
984
985 fn transaction_receipt(
986 &self, tx_hash: H256,
987 ) -> CoreResult<Option<RpcReceipt>> {
988 let hash: H256 = tx_hash.into();
989 info!("RPC Request: cfx_getTransactionReceipt({:?})", hash);
990 self.prepare_receipt(hash)
991 }
992
993 fn generate_empty_blocks(
994 &self, num_blocks: usize,
995 ) -> CoreResult<Vec<H256>> {
996 info!("RPC Request: generate({:?})", num_blocks);
997 let mut hashes = Vec::new();
998 for _i in 0..num_blocks {
999 hashes.push(
1000 self.block_gen.generate_block(
1001 0,
1002 self.sync
1003 .get_synchronization_graph()
1004 .verification_config
1005 .max_block_size_in_bytes,
1006 vec![],
1007 ),
1008 );
1009 }
1010 Ok(hashes)
1011 }
1012
1013 fn generate_fixed_block(
1014 &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize,
1015 adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>,
1016 ) -> CoreResult<H256> {
1017 info!(
1018 "RPC Request: generate_fixed_block({:?}, {:?}, {:?}, {:?}, {:?})",
1019 parent_hash, referee, num_txs, difficulty, pos_reference,
1020 );
1021
1022 Ok(self.block_gen.generate_fixed_block(
1023 parent_hash,
1024 referee,
1025 num_txs,
1026 difficulty.unwrap_or(0),
1027 adaptive,
1028 pos_reference,
1029 )?)
1030 }
1031
1032 fn generate_one_block(
1033 &self, num_txs: usize, block_size_limit: usize,
1034 ) -> CoreResult<H256> {
1035 info!("RPC Request: generate_one_block()");
1036 Ok(self
1037 .block_gen
1038 .generate_block(num_txs, block_size_limit, vec![]))
1039 }
1040
1041 fn generate_one_block_with_direct_txgen(
1042 &self, num_txs: usize, mut block_size_limit: usize,
1043 num_txs_simple: usize, num_txs_erc20: usize,
1044 ) -> CoreResult<H256> {
1045 info!("RPC Request: generate_one_block_with_direct_txgen()");
1046
1047 let block_gen = &self.block_gen;
1048 match self.maybe_direct_txgen.as_ref() {
1049 None => {
1050 let mut rpc_error = JsonRpcError::method_not_found();
1052 rpc_error.message = "generate_one_block_with_direct_txgen only allowed in test or dev mode.".into();
1053 bail!(rpc_error)
1054 }
1055 Some(direct_txgen) => {
1056 let generated_transactions =
1057 direct_txgen.lock().generate_transactions(
1058 &mut block_size_limit,
1059 num_txs_simple,
1060 num_txs_erc20,
1061 self.consensus.best_chain_id().in_native_space(),
1062 );
1063
1064 Ok(block_gen.generate_block(
1065 num_txs,
1066 block_size_limit,
1067 generated_transactions,
1068 ))
1069 }
1070 }
1071 }
1072
1073 fn generate_custom_block(
1074 &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes,
1075 adaptive: Option<bool>, custom: Option<Vec<Bytes>>,
1076 ) -> CoreResult<H256> {
1077 info!("RPC Request: generate_custom_block()");
1078
1079 let transactions = self.decode_raw_txs(raw_txs, 0)?;
1080
1081 Ok(self.block_gen.generate_custom_block_with_parent(
1082 parent_hash,
1083 referee,
1084 transactions,
1085 adaptive.unwrap_or(false),
1086 custom.map(|list| list.into_iter().map(|bytes| bytes.0).collect()),
1087 )?)
1088 }
1089
1090 fn generate_block_with_nonce_and_timestamp(
1091 &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256,
1092 timestamp: u64, adaptive: bool,
1093 ) -> CoreResult<H256> {
1094 let transactions = self.decode_raw_txs(raw, 0)?;
1095 self.block_gen
1096 .generate_block_with_nonce_and_timestamp(
1097 parent,
1098 referees,
1099 transactions,
1100 nonce,
1101 timestamp,
1102 adaptive,
1103 )
1104 .map_err(Into::into)
1105 }
1106
1107 fn decode_raw_txs(
1108 &self, raw_txs: Bytes, tx_data_len: usize,
1109 ) -> CoreResult<Vec<Arc<SignedTransaction>>> {
1110 let txs: Vec<TransactionWithSignature> =
1111 Rlp::new(&raw_txs.into_vec()).as_list().map_err(|err| {
1112 invalid_params("raw_txs", format!("Decode error: {:?}", err))
1113 })?;
1114
1115 let mut transactions = Vec::new();
1116
1117 for tx in txs {
1118 let public = match tx.recover_public() {
1119 Ok(public) => public,
1120 Err(e) => {
1121 bail!(invalid_params(
1122 &format!("raw_txs, tx {:?}", tx),
1123 format!("Recover public error: {:?}", e),
1124 ));
1125 }
1126 };
1127
1128 let mut signed_tx = SignedTransaction::new(public, tx);
1129
1130 if tx_data_len > 0 {
1132 *signed_tx.transaction.transaction.unsigned.data_mut() =
1133 vec![0; tx_data_len];
1134 }
1135
1136 transactions.push(Arc::new(signed_tx));
1137 }
1138
1139 Ok(transactions)
1140 }
1141
1142 fn generate_block_with_fake_txs(
1143 &self, raw_txs_without_data: Bytes, adaptive: Option<bool>,
1144 tx_data_len: Option<usize>,
1145 ) -> CoreResult<H256> {
1146 let transactions = self
1147 .decode_raw_txs(raw_txs_without_data, tx_data_len.unwrap_or(0))?;
1148 Ok(self.block_gen.generate_custom_block(transactions, adaptive))
1149 }
1150
1151 fn generate_block_with_blame_info(
1152 &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo,
1153 ) -> CoreResult<H256> {
1154 Ok(self.block_gen.generate_block_with_blame_info(
1155 num_txs,
1156 block_size_limit,
1157 vec![],
1158 blame_info.blame.map(|x| x.as_u32()),
1159 blame_info.deferred_state_root.map(|x| x.into()),
1160 blame_info.deferred_receipts_root.map(|x| x.into()),
1161 blame_info.deferred_logs_bloom_hash.map(|x| x.into()),
1162 ))
1163 }
1164
1165 fn get_logs(&self, filter: CfxRpcLogFilter) -> CoreResult<Vec<RpcLog>> {
1166 if let Some(addresses) = &filter.address {
1168 for address in addresses.iter() {
1169 invalid_params_check(
1170 "filter.address",
1171 check_rpc_address_network(
1172 Some(address.network),
1173 self.sync.network.get_network_type(),
1174 ),
1175 )?;
1176 }
1177 }
1178
1179 let consensus_graph = self.consensus_graph();
1180
1181 info!("RPC Request: cfx_getLogs({:?})", filter);
1182 let filter: LogFilter = filter
1183 .into_primitive()
1184 .map_err(error_object_owned_to_jsonrpc_error)?;
1185
1186 let logs = consensus_graph
1187 .logs(filter)?
1188 .iter()
1189 .cloned()
1190 .map(|l| {
1191 RpcLog::try_from_localized(
1192 l,
1193 *self.sync.network.get_network_type(),
1194 )
1195 })
1196 .collect::<Result<Vec<_>, _>>()?;
1197
1198 if let Some(max_limit) = self.config.get_logs_filter_max_limit {
1200 if logs.len() > max_limit {
1201 bail!(invalid_params("filter", format!("This query results in too many logs, max limitation is {}, please filter results by a smaller epoch/block range", max_limit)));
1202 }
1203 }
1204
1205 Ok(logs)
1206 }
1207
1208 fn get_block_reward_info(
1209 &self, epoch: EpochNumber,
1210 ) -> CoreResult<Vec<RpcRewardInfo>> {
1211 info!(
1212 "RPC Request: cfx_getBlockRewardInfo epoch_number={:?}",
1213 epoch
1214 );
1215 let epoch_height: U64 = self
1216 .consensus_graph()
1217 .get_height_from_epoch_number(epoch.clone().into_primitive())?
1218 .into();
1219 let (epoch_later_number, overflow) =
1220 epoch_height.overflowing_add(REWARD_EPOCH_COUNT.into());
1221 if overflow {
1222 bail!(invalid_params("epoch", "Epoch number overflows!"));
1223 }
1224 let epoch_later = match self.consensus.get_hash_from_epoch_number(
1225 EpochNumber::Num(epoch_later_number).into_primitive(),
1226 ) {
1227 Ok(hash) => hash,
1228 Err(e) => {
1229 debug!("get_block_reward_info: get_hash_from_epoch_number returns error: {}", e);
1230 bail!(invalid_params("epoch", "Reward not calculated yet!"))
1231 }
1232 };
1233
1234 let blocks = self.consensus.get_block_hashes_by_epoch(epoch.into())?;
1235
1236 let mut ret = Vec::new();
1237 for b in blocks {
1238 if let Some(reward_result) = self
1239 .consensus
1240 .data_manager()
1241 .block_reward_result_by_hash_with_epoch(
1242 &b,
1243 &epoch_later,
1244 false, true, )
1247 {
1248 if let Some(block_header) =
1249 self.consensus.data_manager().block_header_by_hash(&b)
1250 {
1251 let author = RpcAddress::try_from_h160(
1252 *block_header.author(),
1253 *self.sync.network.get_network_type(),
1254 )?;
1255
1256 ret.push(RpcRewardInfo {
1257 block_hash: b.into(),
1258 author,
1259 total_reward: reward_result.total_reward.into(),
1260 base_reward: reward_result.base_reward.into(),
1261 tx_fee: reward_result.tx_fee.into(),
1262 })
1263 }
1264 }
1265 }
1266 Ok(ret)
1267 }
1268
1269 fn call(
1270 &self, request: TransactionRequest,
1271 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
1272 ) -> CoreResult<Bytes> {
1273 let epoch = Some(
1274 self.get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?,
1275 );
1276 let (execution_outcome, _estimation) =
1277 self.exec_transaction(request, epoch)?;
1278 match execution_outcome {
1279 ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1280 expected,
1281 got,
1282 )) => bail!(call_execution_error(
1283 "Transaction can not be executed".into(),
1284 format! {"nonce is too old expected {:?} got {:?}", expected, got}
1285 )),
1286 ExecutionOutcome::NotExecutedDrop(
1287 TxDropError::InvalidRecipientAddress(recipient),
1288 ) => bail!(call_execution_error(
1289 "Transaction can not be executed".into(),
1290 format! {"invalid recipient address {:?}", recipient}
1291 )),
1292 ExecutionOutcome::NotExecutedDrop(
1293 TxDropError::NotEnoughGasLimit { expected, got },
1294 ) => bail!(call_execution_error(
1295 "Transaction can not be executed".into(),
1296 format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1297 )),
1298 ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1299 address,
1300 )) => bail!(call_execution_error(
1301 "Transaction can not be executed".into(),
1302 format! {"tx sender has contract code: {:?}", address}
1303 )),
1304 ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1305 bail!(call_execution_error(
1306 "Transaction can not be executed".into(),
1307 format! {"{:?}", e}
1308 ))
1309 }
1310 ExecutionOutcome::ExecutionErrorBumpNonce(
1311 ExecutionError::VmError(VmError::Reverted),
1312 executed,
1313 ) => bail!(call_execution_error(
1314 "Transaction reverted".into(),
1315 format!("0x{}", executed.output.to_hex::<String>())
1316 )),
1317 ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1318 bail!(call_execution_error(
1319 "Transaction execution failed".into(),
1320 format! {"{:?}", e}
1321 ))
1322 }
1323 ExecutionOutcome::Finished(executed) => Ok(executed.output.into()),
1324 }
1325 }
1326
1327 fn estimate_gas_and_collateral(
1328 &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1329 ) -> CoreResult<EstimateGasAndCollateralResponse> {
1330 info!(
1331 "RPC Request: cfx_estimateGasAndCollateral request={:?}, epoch={:?}",request,epoch
1332 );
1333 let (execution_outcome, estimation) =
1334 self.exec_transaction(request, epoch)?;
1335 match execution_outcome {
1336 ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1337 expected,
1338 got,
1339 )) => bail!(call_execution_error(
1340 "Can not estimate: transaction can not be executed".into(),
1341 format! {"nonce is too old expected {:?} got {:?}", expected, got}
1342 )),
1343 ExecutionOutcome::NotExecutedDrop(
1344 TxDropError::InvalidRecipientAddress(recipient),
1345 ) => bail!(call_execution_error(
1346 "Can not estimate: transaction can not be executed".into(),
1347 format! {"invalid recipient address {:?}", recipient}
1348 )),
1349 ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1350 address,
1351 )) => bail!(call_execution_error(
1352 "Can not estimate: transaction sender has code".into(),
1353 format! {"transaction sender has code {:?}", address}
1354 )),
1355 ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1356 bail!(call_execution_error(
1357 "Can not estimate: transaction can not be executed".into(),
1358 format! {"{:?}", e}
1359 ))
1360 }
1361 ExecutionOutcome::NotExecutedDrop(
1362 TxDropError::NotEnoughGasLimit { expected, got },
1363 ) => bail!(call_execution_error(
1364 "Can not estimate: transaction can not be executed".into(),
1365 format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1366 )),
1367 ExecutionOutcome::ExecutionErrorBumpNonce(
1368 ExecutionError::VmError(VmError::Reverted),
1369 executed,
1370 ) => {
1371 let network_type = *self.sync.network.get_network_type();
1372 let (revert_error, innermost_error, errors) =
1373 decode_error(&executed, |addr| {
1374 RpcAddress::try_from_h160(addr.clone(), network_type)
1375 .unwrap()
1376 .base32_address
1377 });
1378
1379 bail!(call_execution_error(
1380 format!("Estimation isn't accurate: transaction is reverted{}{}",
1381 revert_error, innermost_error),
1382 errors.join("\n"),
1383 ))
1384 }
1385 ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1386 bail!(call_execution_error(
1387 format! {"Can not estimate: transaction execution failed, \
1388 all gas will be charged (execution error: {:?})", e}
1389 .into(),
1390 format! {"{:?}", e}
1391 ))
1392 }
1393 ExecutionOutcome::Finished(executed) => executed,
1394 };
1395 let storage_collateralized =
1396 U64::from(estimation.estimated_storage_limit);
1397 let estimated_gas_used = estimation.estimated_gas_limit;
1398 let response = EstimateGasAndCollateralResponse {
1399 gas_limit: estimated_gas_used, gas_used: estimated_gas_used,
1404 storage_collateralized,
1405 };
1406 Ok(response)
1407 }
1408
1409 fn check_balance_against_transaction(
1410 &self, account_addr: RpcAddress, contract_addr: RpcAddress,
1411 gas_limit: U256, gas_price: U256, storage_limit: U256,
1412 epoch: Option<EpochNumber>,
1413 ) -> CoreResult<CheckBalanceAgainstTransactionResponse> {
1414 self.check_address_network(account_addr.network)?;
1415 self.check_address_network(contract_addr.network)?;
1416
1417 let epoch: primitives::EpochNumber =
1418 epoch.unwrap_or(EpochNumber::LatestState).into();
1419
1420 info!(
1421 "RPC Request: cfx_checkBalanceAgainstTransaction account_addr={:?} contract_addr={:?} gas_limit={:?} gas_price={:?} storage_limit={:?} epoch={:?}",
1422 account_addr, contract_addr, gas_limit, gas_price, storage_limit, epoch
1423 );
1424
1425 let account_addr = account_addr.hex_address.with_native_space();
1426 let contract_addr = contract_addr.hex_address.with_native_space();
1427
1428 if storage_limit > U256::from(std::u64::MAX) {
1429 bail!(JsonRpcError::invalid_params(format!("storage_limit has to be within the range of u64 but {} supplied!", storage_limit)));
1430 }
1431
1432 let state_db = self
1433 .consensus
1434 .get_state_db_by_epoch_number(epoch, "epoch")?;
1435
1436 let user_account = state_db.get_account(&account_addr)?;
1437 let contract_account = state_db.get_account(&contract_addr)?;
1438 let state = State::new(state_db)?;
1439 let is_sponsored = state.check_contract_whitelist(
1440 &contract_addr.address,
1441 &account_addr.address,
1442 )?;
1443
1444 Ok(common::check_balance_against_transaction(
1445 user_account,
1446 contract_account,
1447 is_sponsored,
1448 gas_limit,
1449 gas_price,
1450 storage_limit,
1451 ))
1452 }
1453
1454 fn exec_transaction(
1455 &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1456 ) -> CoreResult<(ExecutionOutcome, EstimateExt)> {
1457 let rpc_request_network = invalid_params_check(
1458 "request",
1459 check_two_rpc_address_network_match(
1460 request.from.as_ref(),
1461 request.to.as_ref(),
1462 ),
1463 )?;
1464 invalid_params_check(
1465 "request",
1466 check_rpc_address_network(
1467 rpc_request_network,
1468 self.sync.network.get_network_type(),
1469 ),
1470 )?;
1471
1472 let consensus_graph = self.consensus_graph();
1473 let epoch = epoch.unwrap_or(EpochNumber::LatestState);
1474
1475 let estimate_request = EstimateRequest {
1476 has_sender: request.from.is_some(),
1477 has_gas_limit: request.gas.is_some(),
1478 has_gas_price: request.has_gas_price(),
1479 has_nonce: request.nonce.is_some(),
1480 has_storage_limit: request.storage_limit.is_some(),
1481 collect_access_list: false,
1482 };
1483
1484 let epoch_height = consensus_graph
1485 .get_height_from_epoch_number(epoch.clone().into())?;
1486 let chain_id = consensus_graph.best_chain_id();
1487 let signed_tx = request
1488 .sign_call(
1489 epoch_height,
1490 chain_id.in_native_space(),
1491 self.config.max_estimation_gas_limit,
1492 )
1493 .map_err(error_object_owned_to_jsonrpc_error)?;
1494 trace!("call tx {:?}", signed_tx);
1495
1496 consensus_graph.call_virtual(
1497 &signed_tx,
1498 epoch.into(),
1499 estimate_request,
1500 Default::default(),
1501 )
1502 }
1503
1504 fn current_sync_phase(&self) -> CoreResult<String> {
1505 Ok(self.sync.current_sync_phase().name().into())
1506 }
1507
1508 fn get_pivot_chain_and_weight(
1514 &self, height_range: Option<(u64, u64)>,
1515 ) -> CoreResult<Vec<(H256, U256)>> {
1516 let consensus_graph = self.consensus_graph();
1517 Ok(consensus_graph
1518 .inner
1519 .read()
1520 .get_pivot_chain_and_weight(height_range)?)
1521 }
1522
1523 fn get_executed_info(&self, block_hash: H256) -> CoreResult<(H256, H256)> {
1524 let commitment = self
1525 .consensus
1526 .data_manager()
1527 .get_epoch_execution_commitment(&block_hash)
1528 .ok_or(JsonRpcError::invalid_params(
1529 "No receipts root. Possibly never pivot?".to_owned(),
1530 ))?;
1531 Ok((
1532 commitment.receipts_root.clone().into(),
1533 commitment
1534 .state_root_with_aux_info
1535 .state_root
1536 .compute_state_root_hash(),
1537 ))
1538 }
1539
1540 fn expire_block_gc(&self, timeout: u64) -> CoreResult<()> {
1541 self.sync.expire_block_gc(timeout);
1542 Ok(())
1543 }
1544
1545 pub fn consensus_graph_state(&self) -> CoreResult<ConsensusGraphStates> {
1546 let consensus_graph_states =
1547 STATE_EXPOSER.consensus_graph.lock().retrieve();
1548 let mut block_state_vec = Vec::new();
1550 let mut block_execution_state_vec = Vec::new();
1551
1552 for block_state in &consensus_graph_states.block_state_vec {
1553 block_state_vec.push(ConsensusGraphBlockState {
1554 block_hash: block_state.block_hash.into(),
1555 best_block_hash: block_state.best_block_hash.into(),
1556 block_status: (block_state.block_status as u8).into(),
1557 era_block_hash: block_state.era_block_hash.into(),
1558 adaptive: block_state.adaptive,
1559 })
1560 }
1561 for exec_state in &consensus_graph_states.block_execution_state_vec {
1562 block_execution_state_vec.push(ConsensusGraphBlockExecutionState {
1563 block_hash: exec_state.block_hash.into(),
1564 deferred_state_root: exec_state.deferred_state_root.into(),
1565 deferred_receipt_root: exec_state.deferred_receipt_root.into(),
1566 deferred_logs_bloom_hash: exec_state
1567 .deferred_logs_bloom_hash
1568 .into(),
1569 state_valid: exec_state.state_valid,
1570 })
1571 }
1572
1573 Ok(ConsensusGraphStates {
1574 block_state_vec,
1575 block_execution_state_vec,
1576 })
1577 }
1578
1579 pub fn sync_graph_state(&self) -> CoreResult<SyncGraphStates> {
1580 let sync_graph_states = STATE_EXPOSER.sync_graph.lock().retrieve();
1581 let mut ready_block_vec = Vec::new();
1582 for block_state in sync_graph_states.ready_block_vec {
1583 ready_block_vec.push(SyncGraphBlockState {
1584 block_hash: block_state.block_hash.into(),
1585 parent: block_state.parent.into(),
1586 referees: block_state
1587 .referees
1588 .iter()
1589 .map(|x| H256::from(*x))
1590 .collect(),
1591 nonce: block_state.nonce.into(),
1592 timestamp: U64::from(block_state.timestamp),
1593 adaptive: block_state.adaptive,
1594 })
1595 }
1596 Ok(SyncGraphStates { ready_block_vec })
1597 }
1598
1599 pub fn get_block_status(&self, block_hash: H256) -> CoreResult<(u8, bool)> {
1602 let consensus_graph = self.consensus_graph();
1603 let status = consensus_graph
1604 .data_man
1605 .local_block_info_by_hash(&block_hash)
1606 .ok_or(invalid_params("block_hash", "No block status"))?
1608 .get_status();
1609 let state_valid = consensus_graph
1610 .inner
1611 .read()
1612 .block_node(&block_hash)
1613 .ok_or(invalid_params("block_hash", "No block in consensus"))?
1614 .data
1615 .state_valid
1616 .ok_or(invalid_params("block_hash", "No state_valid"))?;
1617 Ok((status.to_db_status(), state_valid))
1618 }
1619
1620 pub fn get_supply_info(
1621 &self, epoch: Option<EpochNumber>,
1622 ) -> CoreResult<TokenSupplyInfo> {
1623 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1624 let state = State::new(
1625 self.consensus
1626 .get_state_db_by_epoch_number(epoch, "epoch")?,
1627 )?;
1628 let total_issued = state.total_issued_tokens();
1629 let total_staking = state.total_staking_tokens();
1630 let total_collateral = state.total_storage_tokens();
1631 let two_year_unlock_address = genesis_contract_address_two_year();
1632 let four_year_unlock_address = genesis_contract_address_four_year();
1633 let two_year_locked = state
1634 .balance(&two_year_unlock_address)
1635 .unwrap_or(U256::zero());
1636 let four_year_locked = state
1637 .balance(&four_year_unlock_address)
1638 .unwrap_or(U256::zero());
1639 let total_circulating =
1640 total_issued - two_year_locked - four_year_locked;
1641 let total_espace_tokens = state.total_espace_tokens();
1642 Ok(TokenSupplyInfo {
1643 total_circulating,
1644 total_issued,
1645 total_staking,
1646 total_collateral,
1647 total_espace_tokens,
1648 })
1649 }
1650
1651 pub fn get_collateral_info(
1652 &self, epoch: Option<EpochNumber>,
1653 ) -> CoreResult<StorageCollateralInfo> {
1654 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1655 let state = State::new(
1656 self.consensus
1657 .get_state_db_by_epoch_number(epoch, "epoch")?,
1658 )?;
1659 let total_storage_tokens = state.total_storage_tokens();
1660 let converted_storage_points = state.converted_storage_points()
1661 / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1662 let used_storage_points =
1663 state.used_storage_points() / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1664 Ok(StorageCollateralInfo {
1665 total_storage_tokens,
1666 converted_storage_points,
1667 used_storage_points,
1668 })
1669 }
1670
1671 pub fn get_vote_params(
1672 &self, epoch: Option<EpochNumber>,
1673 ) -> CoreResult<VoteParamsInfo> {
1674 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1675 let state_db = self
1676 .consensus
1677 .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1678 let interest_rate = state_db.get_global_param::<InterestRate>()?
1679 / U256::from(BLOCKS_PER_YEAR);
1680 let pow_base_reward = state_db.get_global_param::<PowBaseReward>()?;
1681
1682 let storage_point_prop =
1683 state_db.get_system_storage(&storage_point_prop())?;
1684
1685 let base_fee_share_prop = state_db.get_global_param::<BaseFeeProp>()?;
1686 Ok(VoteParamsInfo {
1687 pow_base_reward,
1688 interest_rate,
1689 storage_point_prop,
1690 base_fee_share_prop,
1691 })
1692 }
1693
1694 pub fn get_fee_burnt(
1695 &self, epoch: Option<EpochNumber>,
1696 ) -> CoreResult<U256> {
1697 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1698 let state_db = self
1699 .consensus
1700 .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1701
1702 Ok(state_db.get_global_param::<TotalBurnt1559>()?)
1703 }
1704
1705 pub fn set_db_crash(
1706 &self, crash_probability: f64, crash_exit_code: i32,
1707 ) -> CoreResult<()> {
1708 if crash_probability == 0.0 {
1709 *CRASH_EXIT_PROBABILITY.lock() = None;
1710 } else {
1711 *CRASH_EXIT_PROBABILITY.lock() = Some(crash_probability);
1712 }
1713 *CRASH_EXIT_CODE.lock() = crash_exit_code;
1714 Ok(())
1715 }
1716
1717 fn check_response_size<T: Serialize>(
1720 &self, response: &T,
1721 ) -> CoreResult<()> {
1722 let max_size = self.config.max_payload_bytes - 50;
1726
1727 let payload_size = serde_json::to_vec(&response)
1728 .map_err(|_e| "Unexpected serialization error")?
1729 .len();
1730
1731 if payload_size > max_size {
1732 bail!(invalid_params(
1734 "epoch",
1735 format!(
1736 "Oversized payload: size = {}, max = {}",
1737 payload_size, max_size
1738 )
1739 ));
1740 }
1741
1742 Ok(())
1743 }
1744
1745 fn get_block_epoch_number(&self, h: &H256) -> Option<u64> {
1746 if let Some(e) = self.consensus.get_block_epoch_number(h) {
1748 return Some(e);
1749 }
1750
1751 self.consensus.data_manager().block_epoch_number(h)
1753 }
1754
1755 fn epoch_receipts(
1756 &self, epoch: BlockHashOrEpochNumber, include_eth_receipt: Option<bool>,
1757 ) -> CoreResult<Option<Vec<Vec<RpcReceipt>>>> {
1758 info!("RPC Request: cfx_getEpochReceipts({:?})", epoch);
1759
1760 let hashes = self
1761 .consensus
1762 .get_block_hashes_by_epoch_or_block_hash(epoch.into())?;
1763
1764 let pivot_hash = *hashes.last().ok_or("Inconsistent state")?;
1765 let mut epoch_receipts = vec![];
1766
1767 for h in hashes {
1768 epoch_receipts.push(
1769 match self.prepare_block_receipts(
1770 h,
1771 pivot_hash,
1772 include_eth_receipt.unwrap_or(false),
1773 )? {
1774 None => return Ok(None), Some(rs) => rs,
1776 },
1777 );
1778 }
1779
1780 self.check_response_size(&epoch_receipts)?;
1783
1784 Ok(Some(epoch_receipts))
1785 }
1786
1787 fn epoch_receipt_proof_by_transaction(
1788 &self, tx_hash: H256,
1789 ) -> JsonRpcResult<Option<EpochReceiptProof>> {
1790 let (block_hash, tx_index_in_block) =
1791 match self.consensus.get_signed_tx_and_tx_info(&tx_hash) {
1792 None => {
1793 bail!(invalid_params(
1794 "transactions hash",
1795 format!(
1796 "Unable to get transaction info for hash {:?}",
1797 tx_hash
1798 )
1799 ));
1800 }
1801 Some((_, TransactionInfo { tx_index, .. })) => {
1802 (tx_index.block_hash, tx_index.real_index)
1803 }
1804 };
1805
1806 let epoch = match self.consensus.get_block_epoch_number(&block_hash) {
1807 Some(epoch) => epoch,
1808 None => {
1809 bail!(invalid_params(
1810 "block hash",
1811 format!(
1812 "Unable to get epoch number for block {:?}",
1813 block_hash
1814 )
1815 ));
1816 }
1817 };
1818
1819 let epoch_number = primitives::EpochNumber::Number(epoch);
1820 let epoch_hashes = match self
1821 .consensus
1822 .get_block_hashes_by_epoch(epoch_number.clone())
1823 {
1824 Ok(hs) => hs,
1825 Err(e) => {
1826 bail!(invalid_params(
1827 "block hash",
1828 format!("Unable to find epoch hashes for {}: {}", epoch, e)
1829 ));
1830 }
1831 };
1832
1833 let block_index_in_epoch =
1834 match epoch_hashes.iter().position(|h| *h == block_hash) {
1835 Some(id) => id,
1836 None => {
1837 bail!(invalid_params(
1838 "block hash",
1839 format!(
1840 "Unable to find block {:?} in epoch {}",
1841 block_hash, epoch
1842 )
1843 ));
1844 }
1845 };
1846
1847 let pivot = epoch_hashes
1848 .last()
1849 .expect("epoch hashes should be not empty")
1850 .clone();
1851
1852 let epoch_receipts = epoch_hashes
1853 .into_iter()
1854 .map(|h| {
1855 self.consensus
1856 .data_manager()
1857 .block_execution_result_by_hash_with_epoch(
1858 &h, &pivot, false, false, )
1861 .map(|res| Arc::new((*res.block_receipts).clone()))
1862 .ok_or_else(|| {
1863 invalid_params(
1864 "block hash",
1865 format!("Unable to find recepits for {}", h),
1866 )
1867 })
1868 })
1869 .collect::<Result<Vec<_>, _>>()?;
1870
1871 let epoch_receipt_proof = compute_epoch_receipt_proof(
1872 &epoch_receipts,
1873 block_index_in_epoch,
1874 tx_index_in_block,
1875 );
1876
1877 Ok(Some(epoch_receipt_proof))
1878 }
1879
1880 fn stat_on_gas_load(
1881 &self, last_epoch: EpochNumber, time_window: U64,
1882 ) -> CoreResult<Option<StatOnGasLoad>> {
1883 let mut stat = StatOnGasLoad::default();
1884 stat.time_elapsed = time_window;
1885
1886 let block_not_found_error = || {
1887 internal_error_msg(
1888 "Cannot find the block by a ConsensusGraph provided hash",
1889 )
1890 };
1891
1892 let machine = self.tx_pool.machine();
1893 let consensus = self.consensus_graph();
1894
1895 let mut epoch_number = match last_epoch {
1896 EpochNumber::Earliest => {
1897 bail!(invalid_params_msg("Cannot stat genesis"))
1898 }
1899 EpochNumber::Num(num) if num.is_zero() => {
1900 bail!(invalid_params_msg("Cannot stat genesis"))
1901 }
1902 EpochNumber::LatestMined => bail!(invalid_params_msg(
1903 "Epoch number is earilier than 'latest_state'"
1904 )),
1905 EpochNumber::Num(num) => {
1906 let pivot_hash = consensus.get_hash_from_epoch_number(
1907 primitives::EpochNumber::LatestState,
1908 )?;
1909 let epoch_number = consensus
1910 .get_block_epoch_number(&pivot_hash)
1911 .ok_or_else(block_not_found_error)?;
1912 if epoch_number < num.as_u64() {
1913 bail!(invalid_params_msg(
1914 "Epoch number is earilier than 'latest_state'"
1915 ))
1916 }
1917 num.as_u64()
1918 }
1919 EpochNumber::LatestCheckpoint
1920 | EpochNumber::LatestFinalized
1921 | EpochNumber::LatestConfirmed
1922 | EpochNumber::LatestState => {
1923 let pivot_hash =
1924 consensus.get_hash_from_epoch_number(last_epoch.into())?;
1925 consensus
1926 .get_block_epoch_number(&pivot_hash)
1927 .ok_or_else(block_not_found_error)?
1928 }
1929 };
1930
1931 let mut last_timestamp: Option<u64> = None;
1932
1933 loop {
1934 let block_hashes = consensus.get_block_hashes_by_epoch(
1936 primitives::EpochNumber::Number(epoch_number),
1937 )?;
1938 let blocks = consensus
1939 .data_manager()
1940 .blocks_by_hash_list(&block_hashes, false)
1941 .ok_or_else(block_not_found_error)?;
1942 let pivot_block = blocks
1943 .last()
1944 .ok_or(internal_error_msg("Epoch without block"))?;
1945
1946 let timestamp = pivot_block.block_header.timestamp();
1948 if last_timestamp.is_none() {
1949 last_timestamp = Some(timestamp)
1950 }
1951 if last_timestamp.unwrap().saturating_sub(time_window.as_u64())
1953 > timestamp
1954 {
1955 break;
1956 }
1957
1958 let params = machine.params();
1960 stat.epoch_num += 1.into();
1961 for b in &blocks {
1962 stat.total_block_num += 1.into();
1963 stat.total_gas_limit += *b.block_header.gas_limit();
1964 if params.can_pack_evm_transaction(b.block_header.height()) {
1965 stat.espace_block_num += 1.into();
1966 stat.espace_gas_limit += *b.block_header.gas_limit()
1967 / params.evm_transaction_gas_ratio;
1968 }
1969 }
1970
1971 for b in &blocks {
1973 let exec_info =
1975 match consensus.get_block_execution_info(&b.hash()) {
1976 None => bail!(internal_error_msg(
1977 "Cannot fetch block receipt with checked input params"
1978 )),
1979 Some((res, _)) => res.1,
1980 };
1981
1982 for (receipt, tx) in exec_info
1983 .block_receipts
1984 .receipts
1985 .iter()
1986 .zip(&b.transactions)
1987 {
1988 let space = tx.space();
1989 if receipt.outcome_status == TransactionStatus::Skipped {
1990 *stat.skipped_tx_count.in_space_mut(space) += 1.into();
1991 *stat.skipped_tx_gas_limit.in_space_mut(space) +=
1992 *tx.gas_limit();
1993 } else {
1994 *stat.confirmed_tx_count.in_space_mut(space) +=
1995 1.into();
1996 *stat.confirmed_tx_gas_limit.in_space_mut(space) +=
1997 *tx.gas_limit();
1998 *stat.tx_gas_charged.in_space_mut(space) +=
1999 receipt.gas_fee / tx.gas_price();
2000 }
2001 }
2002 }
2003
2004 if epoch_number > 0 {
2006 epoch_number -= 1;
2007 } else {
2008 break;
2009 }
2010 }
2011 Ok(Some(stat))
2012 }
2013
2014 fn transactions_by_epoch(
2015 &self, epoch_number: U64,
2016 ) -> JsonRpcResult<Vec<WrapTransaction>> {
2017 debug!("debug_getTransactionsByEpoch {}", epoch_number);
2018
2019 let block_hashs = self
2020 .consensus
2021 .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2022 epoch_number.as_u64(),
2023 ))
2024 .map_err(|e| {
2025 JsonRpcError::invalid_params(format!(
2026 "Could not get block hashes by epoch {}",
2027 e
2028 ))
2029 })?;
2030
2031 let blocks = match self
2032 .consensus
2033 .data_manager()
2034 .blocks_by_hash_list(&block_hashs, false)
2035 {
2036 None => {
2037 return Err(JsonRpcError::invalid_params(format!(
2038 "Could not get blocks for hashs {:?}",
2039 block_hashs
2040 )))
2041 }
2042 Some(b) => b,
2043 };
2044
2045 let pivot = match blocks.last() {
2046 Some(p) => p,
2047 None => {
2048 return Err(JsonRpcError::invalid_params("blocks is empty"))
2049 }
2050 };
2051
2052 self.get_transactions(&blocks, pivot, epoch_number.as_u64())
2053 }
2054
2055 fn transactions_by_block(
2056 &self, block_hash: H256,
2057 ) -> JsonRpcResult<Vec<WrapTransaction>> {
2058 debug!("debug_getTransactionsByBlock {}", block_hash);
2059
2060 let epoch_number = match self.get_block_epoch_number(&block_hash) {
2061 None => {
2062 return Err(JsonRpcError::invalid_params(format!(
2063 "Counld not get epoch for block {}",
2064 block_hash
2065 )))
2066 }
2067 Some(n) => n,
2068 };
2069
2070 let block_hashs = self
2071 .consensus
2072 .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2073 epoch_number,
2074 ))
2075 .map_err(|e| {
2076 JsonRpcError::invalid_params(format!(
2077 "Could not get block hashes by epoch {}",
2078 e
2079 ))
2080 })?;
2081
2082 let blocks = match self
2083 .consensus
2084 .data_manager()
2085 .blocks_by_hash_list(&block_hashs, false)
2086 {
2087 None => {
2088 return Err(JsonRpcError::invalid_params(format!(
2089 "Counld not get blocks for hashs {:?}",
2090 block_hashs
2091 )))
2092 }
2093 Some(b) => b,
2094 };
2095
2096 let pivot = match blocks.last() {
2097 Some(p) => p,
2098 None => {
2099 return Err(JsonRpcError::invalid_params("blocks is empty"))
2100 }
2101 };
2102
2103 let mut block = vec![];
2104 for b in blocks.iter() {
2105 if b.hash() == block_hash {
2106 block.push((*b).clone());
2107 break;
2108 }
2109 }
2110
2111 self.get_transactions(&block, pivot, epoch_number)
2112 }
2113
2114 fn get_transactions(
2115 &self, blocks: &Vec<Arc<Block>>, pivot: &Arc<Block>, epoch_number: u64,
2116 ) -> JsonRpcResult<Vec<WrapTransaction>> {
2117 let mut transactions = vec![];
2118
2119 for b in blocks.into_iter() {
2120 match self.get_transactions_for_block(b, pivot, epoch_number) {
2121 Ok(mut txs) => {
2122 transactions.append(&mut txs);
2123 }
2124 Err(e) => bail!(internal_error(e)),
2125 };
2126 }
2127
2128 Ok(transactions)
2129 }
2130
2131 fn get_transactions_for_block(
2132 &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2133 ) -> Result<Vec<WrapTransaction>, String> {
2134 let exec_info = self
2135 .consensus
2136 .data_manager()
2137 .block_execution_result_by_hash_with_epoch(
2138 &b.hash(),
2139 &pivot.hash(),
2140 false,
2141 false,
2142 );
2143 if let Some(execution_result) = exec_info {
2144 self.get_transactions_for_executed_block(
2145 b,
2146 pivot,
2147 epoch_number,
2148 execution_result,
2149 )
2150 } else {
2151 self.get_transactions_for_non_executed_block(b, pivot)
2152 }
2153 }
2154
2155 fn get_transactions_for_non_executed_block(
2156 &self, b: &Arc<Block>, pivot: &Arc<Block>,
2157 ) -> Result<Vec<WrapTransaction>, String> {
2158 let network = *self.sync.network.get_network_type();
2159
2160 let mut eth_transaction_idx = 0;
2161 let mut make_eth_wrap_tx = |tx| {
2162 let block_info = (
2163 Some(pivot.hash()),
2164 Some(pivot.block_header.height().into()),
2165 Some(eth_transaction_idx.into()),
2166 );
2167 eth_transaction_idx += 1;
2168 WrapTransaction::EthTransaction(EthTransaction::from_signed(
2169 tx,
2170 block_info,
2171 (None, None),
2172 ))
2173 };
2174
2175 let make_cfx_wrap_tx = |tx| -> Result<WrapTransaction, String> {
2176 Ok(WrapTransaction::NativeTransaction(
2177 RpcTransaction::from_signed(tx, None, network)?,
2178 ))
2179 };
2180
2181 let mut res = vec![];
2182 for (_, tx) in b.transactions.iter().enumerate() {
2183 res.push(match tx.space() {
2184 Space::Ethereum => make_eth_wrap_tx(tx),
2185 Space::Native => make_cfx_wrap_tx(tx)?,
2186 });
2187 }
2188 Ok(res)
2189 }
2190
2191 fn get_transactions_for_executed_block(
2192 &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2193 execution_result: BlockExecutionResult,
2194 ) -> Result<Vec<WrapTransaction>, String> {
2195 let network = *self.sync.network.get_network_type();
2196 let maybe_state_root = self
2197 .consensus
2198 .data_manager()
2199 .get_executed_state_root(&b.hash());
2200 let block_receipts = &execution_result.block_receipts.receipts;
2201
2202 let mut eth_transaction_idx = 0;
2203 let mut make_eth_wrap_tx = |tx, id: usize| {
2204 let receipt = &block_receipts[id];
2205
2206 let status = receipt.outcome_status.in_space(Space::Ethereum);
2207 let contract_address = match status == EVM_SPACE_SUCCESS {
2208 true => EthTransaction::deployed_contract_address(tx),
2209 false => None,
2210 };
2211 let block_info = (
2212 Some(pivot.hash()),
2213 Some(pivot.block_header.height().into()),
2214 Some(eth_transaction_idx.into()),
2215 );
2216 eth_transaction_idx += 1;
2217
2218 WrapTransaction::EthTransaction(EthTransaction::from_signed(
2219 tx,
2220 block_info,
2221 (Some(status.into()), contract_address),
2222 ))
2223 };
2224
2225 let mut cfx_transaction_index = 0;
2226 let mut make_cfx_wrap_tx = |tx, id: usize| -> Result<_, String> {
2227 let receipt = &block_receipts[id];
2228 let prior_gas_used = if id == 0 {
2229 U256::zero()
2230 } else {
2231 block_receipts[id - 1].accumulated_gas_used
2232 };
2233
2234 if receipt.outcome_status == TransactionStatus::Skipped {
2235 cfx_transaction_index += 1;
2236 return Ok(WrapTransaction::NativeTransaction(
2237 RpcTransaction::from_signed(tx, None, network)?,
2238 ));
2239 }
2240
2241 let tx_index = TransactionIndex {
2242 block_hash: b.hash(),
2243 real_index: id,
2244 is_phantom: false,
2245 rpc_index: Some(cfx_transaction_index),
2246 };
2247 let tx_exec_error_msg = &execution_result
2248 .block_receipts
2249 .tx_execution_error_messages[id];
2250 let receipt = RpcReceipt::new(
2251 tx.clone(),
2252 receipt.clone(),
2253 tx_index,
2254 prior_gas_used,
2255 Some(epoch_number),
2256 b.block_header.base_price(),
2257 maybe_state_root,
2258 if tx_exec_error_msg.is_empty() {
2259 None
2260 } else {
2261 Some(tx_exec_error_msg.clone())
2262 },
2263 network,
2264 false,
2265 false,
2266 )?;
2267 cfx_transaction_index += 1;
2268 let executed = Some(PackedOrExecuted::Executed(receipt));
2269 Ok(WrapTransaction::NativeTransaction(
2270 RpcTransaction::from_signed(tx, executed, network)?,
2271 ))
2272 };
2273
2274 let mut res = vec![];
2275 for (id, tx) in b.transactions.iter().enumerate() {
2276 res.push(match tx.space() {
2277 Space::Ethereum => make_eth_wrap_tx(&**tx, id),
2278 Space::Native => make_cfx_wrap_tx(&**tx, id)?,
2279 })
2280 }
2281
2282 Ok(res)
2283 }
2284}
2285
2286#[allow(dead_code)]
2287pub struct CfxHandler {
2288 common: Arc<CommonImpl>,
2289 rpc_impl: Arc<RpcImpl>,
2290}
2291
2292impl CfxHandler {
2293 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2294 CfxHandler { common, rpc_impl }
2295 }
2296}
2297
2298impl Cfx for CfxHandler {
2299 delegate! {
2300 to self.common {
2301 fn best_block_hash(&self) -> JsonRpcResult<H256>;
2302 fn block_by_epoch_number(
2303 &self, epoch_num: EpochNumber, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2304 fn block_by_hash_with_pivot_assumption(
2305 &self, block_hash: H256, pivot_hash: H256, epoch_number: U64)
2306 -> BoxFuture<JsonRpcResult<RpcBlock>>;
2307 fn block_by_hash(&self, hash: H256, include_txs: bool)
2308 -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2309 fn block_by_block_number(&self, block_number: U64, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2310 fn confirmation_risk_by_hash(&self, block_hash: H256) -> JsonRpcResult<Option<U256>>;
2311 fn blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2312 fn skipped_blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2313 fn epoch_number(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2314 fn gas_price(&self) -> BoxFuture<JsonRpcResult<U256>>;
2315 fn next_nonce(&self, address: RpcAddress, num: Option<BlockHashOrEpochNumber>)
2316 -> BoxFuture<JsonRpcResult<U256>>;
2317 fn get_status(&self) -> JsonRpcResult<RpcStatus>;
2318 fn get_client_version(&self) -> JsonRpcResult<String>;
2319 fn account_pending_info(&self, addr: RpcAddress) -> BoxFuture<JsonRpcResult<Option<AccountPendingInfo>>>;
2320 fn account_pending_transactions(&self, address: RpcAddress, maybe_start_nonce: Option<U256>, maybe_limit: Option<U64>) -> BoxFuture<JsonRpcResult<AccountPendingTransactions>>;
2321 fn get_pos_reward_by_epoch(&self, epoch: EpochNumber) -> JsonRpcResult<Option<PoSEpochReward>>;
2322 fn fee_history(&self, block_count: HexU64, newest_block: EpochNumber, reward_percentiles: Option<Vec<f64>>) -> BoxFuture<JsonRpcResult<CfxFeeHistory>>;
2323 fn max_priority_fee_per_gas(&self) -> BoxFuture<JsonRpcResult<U256>>;
2324 }
2325
2326 to self.rpc_impl {
2327 fn code(&self, addr: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<Bytes>>;
2328 fn account(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<RpcAccount>>;
2329 fn interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2330 fn accumulate_interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2331 fn pos_economics(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<PoSEconomics>>;
2332 fn admin(&self, address: RpcAddress, num: Option<EpochNumber>)
2333 -> BoxFuture<JsonRpcResult<Option<RpcAddress>>>;
2334 fn sponsor_info(&self, address: RpcAddress, num: Option<EpochNumber>)
2335 -> BoxFuture<JsonRpcResult<SponsorInfo>>;
2336 fn balance(&self, address: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2337 fn staking_balance(&self, address: RpcAddress, num: Option<EpochNumber>)
2338 -> BoxFuture<JsonRpcResult<U256>>;
2339 fn deposit_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<DepositInfo>>>;
2340 fn vote_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<VoteStakeInfo>>>;
2341 fn collateral_for_storage(&self, address: RpcAddress, num: Option<EpochNumber>)
2342 -> BoxFuture<JsonRpcResult<U256>>;
2343 fn call(&self, request: TransactionRequest, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2344 -> JsonRpcResult<Bytes>;
2345 fn estimate_gas_and_collateral(
2346 &self, request: TransactionRequest, epoch_number: Option<EpochNumber>)
2347 -> JsonRpcResult<EstimateGasAndCollateralResponse>;
2348 fn check_balance_against_transaction(
2349 &self, account_addr: RpcAddress, contract_addr: RpcAddress, gas_limit: U256, gas_price: U256, storage_limit: U256, epoch: Option<EpochNumber>,
2350 ) -> BoxFuture<JsonRpcResult<CheckBalanceAgainstTransactionResponse>>;
2351 fn get_logs(&self, filter: CfxRpcLogFilter) -> BoxFuture<JsonRpcResult<Vec<RpcLog>>>;
2352 fn get_block_reward_info(&self, num: EpochNumber) -> JsonRpcResult<Vec<RpcRewardInfo>>;
2353 fn send_raw_transaction(&self, raw: Bytes) -> JsonRpcResult<H256>;
2354 fn storage_at(&self, addr: RpcAddress, pos: U256, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2355 -> BoxFuture<JsonRpcResult<Option<H256>>>;
2356 fn transaction_by_hash(&self, hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcTransaction>>>;
2357 fn transaction_receipt(&self, tx_hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcReceipt>>>;
2358 fn storage_root(&self, address: RpcAddress, epoch_num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Option<StorageRoot>>>;
2359 fn get_supply_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<TokenSupplyInfo>;
2360 fn get_collateral_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<StorageCollateralInfo>;
2361 fn get_vote_params(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<VoteParamsInfo>;
2362 fn get_fee_burnt(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2363 }
2364 }
2365}
2366
2367#[allow(dead_code)]
2368pub struct TestRpcImpl {
2369 common: Arc<CommonImpl>,
2370 rpc_impl: Arc<RpcImpl>,
2371}
2372
2373impl TestRpcImpl {
2374 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2375 TestRpcImpl { common, rpc_impl }
2376 }
2377}
2378
2379impl TestRpc for TestRpcImpl {
2380 delegate! {
2381 to self.common {
2382 fn add_latency(&self, id: NodeId, latency_ms: f64) -> JsonRpcResult<()>;
2383 fn add_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2384 fn chain(&self) -> JsonRpcResult<Vec<RpcBlock>>;
2385 fn drop_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2386 fn get_block_count(&self) -> JsonRpcResult<u64>;
2387 fn get_goodput(&self) -> JsonRpcResult<String>;
2388 fn get_nodeid(&self, challenge: Vec<u8>) -> JsonRpcResult<Vec<u8>>;
2389 fn get_peer_info(&self) -> JsonRpcResult<Vec<PeerInfo>>;
2390 fn say_hello(&self) -> JsonRpcResult<String>;
2391 fn stop(&self) -> JsonRpcResult<()>;
2392 fn save_node_db(&self) -> JsonRpcResult<()>;
2393 fn pos_register(&self, voting_power: U64, version: Option<u8>) -> JsonRpcResult<(Bytes, AccountAddress)>;
2394 fn pos_update_voting_power(
2395 &self, pos_account: AccountAddress, increased_voting_power: U64,
2396 ) -> JsonRpcResult<()>;
2397 fn pos_stop_election(&self) -> JsonRpcResult<Option<u64>>;
2398 fn pos_start_voting(&self, initialize: bool) -> JsonRpcResult<()>;
2399 fn pos_stop_voting(&self) -> JsonRpcResult<()>;
2400 fn pos_voting_status(&self) -> JsonRpcResult<bool>;
2401 fn pos_start(&self) -> JsonRpcResult<()>;
2402 fn pos_force_vote_proposal(&self, block_id: H256) -> JsonRpcResult<()>;
2403 fn pos_force_propose(&self, round: U64, parent_block_id: H256, payload: Vec<TransactionPayload>) -> JsonRpcResult<()>;
2404 fn pos_trigger_timeout(&self, timeout_type: String) -> JsonRpcResult<()>;
2405 fn pos_force_sign_pivot_decision(&self, block_hash: H256, height: U64) -> JsonRpcResult<()>;
2406 fn pos_get_chosen_proposal(&self) -> JsonRpcResult<Option<PosBlock>>;
2407 }
2408
2409 to self.rpc_impl {
2410 fn expire_block_gc(&self, timeout: u64) -> JsonRpcResult<()>;
2411 fn generate_block_with_blame_info(
2412 &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo) -> JsonRpcResult<H256>;
2413 fn generate_block_with_fake_txs(
2414 &self, raw_txs_without_data: Bytes, adaptive: Option<bool>, tx_data_len: Option<usize>)
2415 -> JsonRpcResult<H256>;
2416 fn generate_custom_block(
2417 &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes, adaptive: Option<bool>, custom: Option<Vec<Bytes>>)
2418 -> JsonRpcResult<H256>;
2419 fn get_pivot_chain_and_weight(&self, height_range: Option<(u64, u64)>) -> JsonRpcResult<Vec<(H256, U256)>>;
2420 fn get_executed_info(&self, block_hash: H256) -> JsonRpcResult<(H256, H256)> ;
2421 fn generate_fixed_block(
2422 &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize, adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>)
2423 -> JsonRpcResult<H256>;
2424 fn generate_one_block_with_direct_txgen(
2425 &self, num_txs: usize, block_size_limit: usize, num_txs_simple: usize, num_txs_erc20: usize)
2426 -> JsonRpcResult<H256>;
2427 fn generate_one_block(&self, num_txs: usize, block_size_limit: usize) -> JsonRpcResult<H256>;
2428 fn generate_block_with_nonce_and_timestamp(
2429 &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256, timestamp: u64, adaptive: bool)
2430 -> JsonRpcResult<H256>;
2431 fn generate_empty_blocks(&self, num_blocks: usize) -> JsonRpcResult<Vec<H256>>;
2432 fn get_block_status(&self, block_hash: H256) -> JsonRpcResult<(u8, bool)>;
2433 fn send_usable_genesis_accounts(& self, account_start_index: usize) -> JsonRpcResult<Bytes>;
2434 fn set_db_crash(&self, crash_probability: f64, crash_exit_code: i32) -> JsonRpcResult<()>;
2435 }
2436 }
2437}
2438
2439pub struct LocalRpcImpl {
2440 common: Arc<CommonImpl>,
2441 rpc_impl: Arc<RpcImpl>,
2442}
2443
2444impl LocalRpcImpl {
2445 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2446 LocalRpcImpl { common, rpc_impl }
2447 }
2448}
2449
2450impl LocalRpc for LocalRpcImpl {
2451 delegate! {
2452 to self.common {
2453 fn txpool_content(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2454 BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<RpcTransaction>>>>>;
2455 fn txpool_inspect(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2456 BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<String>>>>>;
2457 fn txpool_get_account_transactions(&self, address: RpcAddress) -> JsonRpcResult<Vec<RpcTransaction>>;
2458 fn txpool_clear(&self) -> JsonRpcResult<()>;
2459 fn net_node(&self, id: NodeId) -> JsonRpcResult<Option<(String, Node)>>;
2460 fn net_disconnect_node(&self, id: NodeId, op: Option<UpdateNodeOperation>)
2461 -> JsonRpcResult<bool>;
2462 fn net_sessions(&self, node_id: Option<NodeId>) -> JsonRpcResult<Vec<SessionDetails>>;
2463 fn net_throttling(&self) -> JsonRpcResult<throttling::Service>;
2464 fn accounts(&self) -> JsonRpcResult<Vec<RpcAddress>>;
2465 fn new_account(&self, password: String) -> JsonRpcResult<RpcAddress>;
2466 fn unlock_account(
2467 &self, address: RpcAddress, password: String, duration: Option<U128>)
2468 -> JsonRpcResult<bool>;
2469 fn lock_account(&self, address: RpcAddress) -> JsonRpcResult<bool>;
2470 fn sign(&self, data: Bytes, address: RpcAddress, password: Option<String>)
2471 -> JsonRpcResult<H520>;
2472
2473 }
2474
2475 to self.rpc_impl {
2476 fn current_sync_phase(&self) -> JsonRpcResult<String>;
2477 fn consensus_graph_state(&self) -> JsonRpcResult<ConsensusGraphStates>;
2478 fn epoch_receipts(&self, epoch: BlockHashOrEpochNumber, include_eth_recepits: Option<bool>,) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;
2479 fn epoch_receipt_proof_by_transaction(&self, tx_hash: H256) -> JsonRpcResult<Option<EpochReceiptProof>>;
2480 fn stat_on_gas_load(&self, last_epoch: EpochNumber, time_window: U64) -> JsonRpcResult<Option<StatOnGasLoad>>;
2481 fn sync_graph_state(&self) -> JsonRpcResult<SyncGraphStates>;
2482 fn send_transaction(
2483 &self, tx: TransactionRequest, password: Option<String>) -> BoxFuture<JsonRpcResult<H256>>;
2484 fn sign_transaction(&self, tx: TransactionRequest, password: Option<String>) -> JsonRpcResult<String>;
2485 fn transactions_by_epoch(&self, epoch_number: U64) -> JsonRpcResult<Vec<WrapTransaction>>;
2486 fn transactions_by_block(&self, block_hash: H256) -> JsonRpcResult<Vec<WrapTransaction>>;
2487 }
2488 }
2489}