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 block_number,
753 maybe_base_price,
754 maybe_state_root,
755 tx_exec_error_msg,
756 *self.sync.network.get_network_type(),
757 false,
758 false,
759 )?)
760 }
761 };
762 let rpc_tx = RpcTransaction::from_signed(
763 &tx,
764 Some(packed_or_executed),
765 *self.sync.network.get_network_type(),
766 )?;
767
768 return Ok(Some(rpc_tx));
769 }
770
771 if let Some(tx) = self.tx_pool.get_transaction(&hash) {
772 if tx.space() == Space::Ethereum {
773 return Ok(None);
774 }
775
776 let rpc_tx = RpcTransaction::from_signed(
777 &tx,
778 None,
779 *self.sync.network.get_network_type(),
780 )?;
781 return Ok(Some(rpc_tx));
782 }
783
784 Ok(None)
785 }
786
787 fn get_block_execution_info(
788 &self, block_hash: &H256,
789 ) -> CoreResult<Option<BlockExecInfo>> {
790 let consensus_graph = self.consensus_graph();
791
792 let (pivot_hash, block_receipts, maybe_state_root) =
793 match consensus_graph.get_block_execution_info(block_hash) {
794 None => return Ok(None),
795 Some((exec_res, maybe_state_root)) => {
796 (exec_res.0, exec_res.1.block_receipts, maybe_state_root)
797 }
798 };
799
800 let epoch_number = self
801 .consensus
802 .data_manager()
803 .block_header_by_hash(&pivot_hash)
804 .ok_or("Inconsistent state")?
806 .height();
807
808 if epoch_number > consensus_graph.best_executed_state_epoch_number() {
809 return Ok(None);
811 }
812
813 let block = self
814 .consensus
815 .data_manager()
816 .block_by_hash(&block_hash, false )
817 .ok_or("Inconsistent state")?;
819
820 if block_receipts.receipts.len() != block.transactions.len() {
821 bail!("Inconsistent state");
822 }
823
824 let pivot_header = if let Some(x) = self
825 .consensus
826 .data_manager()
827 .block_header_by_hash(&pivot_hash)
828 {
829 x
830 } else {
831 warn!("Cannot find pivot header when get block execution info: pivot hash {:?}", pivot_hash);
832 return Ok(None);
833 };
834
835 Ok(Some(BlockExecInfo {
836 block_receipts,
837 block,
838 epoch_number,
839 maybe_state_root,
840 pivot_header,
841 }))
842 }
843
844 fn construct_rpc_receipt(
845 &self, tx_index: TransactionIndex, exec_info: &BlockExecInfo,
846 include_eth_receipt: bool, include_accumulated_gas_used: bool,
847 ) -> CoreResult<Option<RpcReceipt>> {
848 let id = tx_index.real_index;
849
850 if id >= exec_info.block.transactions.len()
851 || id >= exec_info.block_receipts.receipts.len()
852 || id >= exec_info.block_receipts.tx_execution_error_messages.len()
853 {
854 bail!("Inconsistent state");
855 }
856
857 let tx = &exec_info.block.transactions[id];
858
859 if !include_eth_receipt
860 && (tx.space() == Space::Ethereum || tx_index.is_phantom)
861 {
862 return Ok(None);
863 }
864
865 let prior_gas_used = match id {
866 0 => U256::zero(),
867 id => {
868 exec_info.block_receipts.receipts[id - 1].accumulated_gas_used
869 }
870 };
871
872 let tx_exec_error_msg =
873 match &exec_info.block_receipts.tx_execution_error_messages[id] {
874 msg if msg.is_empty() => None,
875 msg => Some(msg.clone()),
876 };
877
878 let receipt = RpcReceipt::new(
879 (**tx).clone(),
880 exec_info.block_receipts.receipts[id].clone(),
881 tx_index,
882 prior_gas_used,
883 Some(exec_info.epoch_number),
884 exec_info.block_receipts.block_number,
885 exec_info.pivot_header.base_price(),
886 exec_info.maybe_state_root.clone(),
887 tx_exec_error_msg,
888 *self.sync.network.get_network_type(),
889 include_eth_receipt,
890 include_accumulated_gas_used,
891 )?;
892
893 Ok(Some(receipt))
894 }
895
896 fn prepare_receipt(&self, tx_hash: H256) -> CoreResult<Option<RpcReceipt>> {
897 let tx_index =
904 match self.consensus.data_manager().transaction_index_by_hash(
905 &tx_hash, false, ) {
907 None => return Ok(None),
908 Some(tx_index) => tx_index,
909 };
910
911 if tx_index.is_phantom {
912 return Ok(None);
913 }
914
915 let exec_info =
916 match self.get_block_execution_info(&tx_index.block_hash)? {
917 None => return Ok(None),
918 Some(res) => res,
919 };
920
921 let receipt =
922 self.construct_rpc_receipt(tx_index, &exec_info, false, true)?;
923 if let Some(r) = &receipt {
924 if r.outcome_status
927 == TransactionStatus::Skipped.in_space(Space::Native).into()
928 {
929 return Ok(None);
930 }
931 }
932 Ok(receipt)
933 }
934
935 fn prepare_block_receipts(
936 &self, block_hash: H256, pivot_assumption: H256,
937 include_eth_receipt: bool,
938 ) -> CoreResult<Option<Vec<RpcReceipt>>> {
939 let exec_info = match self.get_block_execution_info(&block_hash)? {
940 None => return Ok(None), Some(res) => res,
942 };
943
944 if pivot_assumption != exec_info.pivot_header.hash() {
946 bail!(pivot_assumption_failed(
947 pivot_assumption,
948 exec_info.pivot_header.hash()
949 ));
950 }
951
952 let mut rpc_receipts = vec![];
953
954 let iter = exec_info
955 .block
956 .transactions
957 .iter()
958 .enumerate()
959 .filter(|(_, tx)| {
960 if include_eth_receipt {
961 true
962 } else {
963 tx.space() == Space::Native
964 }
965 })
966 .enumerate();
967
968 for (new_index, (original_index, _)) in iter {
969 if let Some(receipt) = self.construct_rpc_receipt(
970 TransactionIndex {
971 block_hash,
972 real_index: original_index,
973 is_phantom: false,
974 rpc_index: Some(new_index),
975 },
976 &exec_info,
977 include_eth_receipt,
978 true,
979 )? {
980 rpc_receipts.push(receipt);
981 }
982 }
983
984 Ok(Some(rpc_receipts))
985 }
986
987 fn transaction_receipt(
988 &self, tx_hash: H256,
989 ) -> CoreResult<Option<RpcReceipt>> {
990 let hash: H256 = tx_hash.into();
991 info!("RPC Request: cfx_getTransactionReceipt({:?})", hash);
992 self.prepare_receipt(hash)
993 }
994
995 fn generate_empty_blocks(
996 &self, num_blocks: usize,
997 ) -> CoreResult<Vec<H256>> {
998 info!("RPC Request: generate({:?})", num_blocks);
999 let mut hashes = Vec::new();
1000 for _i in 0..num_blocks {
1001 hashes.push(
1002 self.block_gen.generate_block(
1003 0,
1004 self.sync
1005 .get_synchronization_graph()
1006 .verification_config
1007 .max_block_size_in_bytes,
1008 vec![],
1009 ),
1010 );
1011 }
1012 Ok(hashes)
1013 }
1014
1015 fn generate_fixed_block(
1016 &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize,
1017 adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>,
1018 ) -> CoreResult<H256> {
1019 info!(
1020 "RPC Request: generate_fixed_block({:?}, {:?}, {:?}, {:?}, {:?})",
1021 parent_hash, referee, num_txs, difficulty, pos_reference,
1022 );
1023
1024 Ok(self.block_gen.generate_fixed_block(
1025 parent_hash,
1026 referee,
1027 num_txs,
1028 difficulty.unwrap_or(0),
1029 adaptive,
1030 pos_reference,
1031 )?)
1032 }
1033
1034 fn generate_one_block(
1035 &self, num_txs: usize, block_size_limit: usize,
1036 ) -> CoreResult<H256> {
1037 info!("RPC Request: generate_one_block()");
1038 Ok(self
1039 .block_gen
1040 .generate_block(num_txs, block_size_limit, vec![]))
1041 }
1042
1043 fn generate_one_block_with_direct_txgen(
1044 &self, num_txs: usize, mut block_size_limit: usize,
1045 num_txs_simple: usize, num_txs_erc20: usize,
1046 ) -> CoreResult<H256> {
1047 info!("RPC Request: generate_one_block_with_direct_txgen()");
1048
1049 let block_gen = &self.block_gen;
1050 match self.maybe_direct_txgen.as_ref() {
1051 None => {
1052 let mut rpc_error = JsonRpcError::method_not_found();
1054 rpc_error.message = "generate_one_block_with_direct_txgen only allowed in test or dev mode.".into();
1055 bail!(rpc_error)
1056 }
1057 Some(direct_txgen) => {
1058 let generated_transactions =
1059 direct_txgen.lock().generate_transactions(
1060 &mut block_size_limit,
1061 num_txs_simple,
1062 num_txs_erc20,
1063 self.consensus.best_chain_id().in_native_space(),
1064 );
1065
1066 Ok(block_gen.generate_block(
1067 num_txs,
1068 block_size_limit,
1069 generated_transactions,
1070 ))
1071 }
1072 }
1073 }
1074
1075 fn generate_custom_block(
1076 &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes,
1077 adaptive: Option<bool>, custom: Option<Vec<Bytes>>,
1078 ) -> CoreResult<H256> {
1079 info!("RPC Request: generate_custom_block()");
1080
1081 let transactions = self.decode_raw_txs(raw_txs, 0)?;
1082
1083 Ok(self.block_gen.generate_custom_block_with_parent(
1084 parent_hash,
1085 referee,
1086 transactions,
1087 adaptive.unwrap_or(false),
1088 custom.map(|list| list.into_iter().map(|bytes| bytes.0).collect()),
1089 )?)
1090 }
1091
1092 fn generate_block_with_nonce_and_timestamp(
1093 &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256,
1094 timestamp: u64, adaptive: bool,
1095 ) -> CoreResult<H256> {
1096 let transactions = self.decode_raw_txs(raw, 0)?;
1097 self.block_gen
1098 .generate_block_with_nonce_and_timestamp(
1099 parent,
1100 referees,
1101 transactions,
1102 nonce,
1103 timestamp,
1104 adaptive,
1105 )
1106 .map_err(Into::into)
1107 }
1108
1109 fn decode_raw_txs(
1110 &self, raw_txs: Bytes, tx_data_len: usize,
1111 ) -> CoreResult<Vec<Arc<SignedTransaction>>> {
1112 let txs: Vec<TransactionWithSignature> =
1113 Rlp::new(&raw_txs.into_vec()).as_list().map_err(|err| {
1114 invalid_params("raw_txs", format!("Decode error: {:?}", err))
1115 })?;
1116
1117 let mut transactions = Vec::new();
1118
1119 for tx in txs {
1120 let public = match tx.recover_public() {
1121 Ok(public) => public,
1122 Err(e) => {
1123 bail!(invalid_params(
1124 &format!("raw_txs, tx {:?}", tx),
1125 format!("Recover public error: {:?}", e),
1126 ));
1127 }
1128 };
1129
1130 let mut signed_tx = SignedTransaction::new(public, tx);
1131
1132 if tx_data_len > 0 {
1134 *signed_tx.transaction.transaction.unsigned.data_mut() =
1135 vec![0; tx_data_len];
1136 }
1137
1138 transactions.push(Arc::new(signed_tx));
1139 }
1140
1141 Ok(transactions)
1142 }
1143
1144 fn generate_block_with_fake_txs(
1145 &self, raw_txs_without_data: Bytes, adaptive: Option<bool>,
1146 tx_data_len: Option<usize>,
1147 ) -> CoreResult<H256> {
1148 let transactions = self
1149 .decode_raw_txs(raw_txs_without_data, tx_data_len.unwrap_or(0))?;
1150 Ok(self.block_gen.generate_custom_block(transactions, adaptive))
1151 }
1152
1153 fn generate_block_with_blame_info(
1154 &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo,
1155 ) -> CoreResult<H256> {
1156 Ok(self.block_gen.generate_block_with_blame_info(
1157 num_txs,
1158 block_size_limit,
1159 vec![],
1160 blame_info.blame.map(|x| x.as_u32()),
1161 blame_info.deferred_state_root.map(|x| x.into()),
1162 blame_info.deferred_receipts_root.map(|x| x.into()),
1163 blame_info.deferred_logs_bloom_hash.map(|x| x.into()),
1164 ))
1165 }
1166
1167 fn get_logs(&self, filter: CfxRpcLogFilter) -> CoreResult<Vec<RpcLog>> {
1168 if let Some(addresses) = &filter.address {
1170 for address in addresses.iter() {
1171 invalid_params_check(
1172 "filter.address",
1173 check_rpc_address_network(
1174 Some(address.network),
1175 self.sync.network.get_network_type(),
1176 ),
1177 )?;
1178 }
1179 }
1180
1181 let consensus_graph = self.consensus_graph();
1182
1183 info!("RPC Request: cfx_getLogs({:?})", filter);
1184 let filter: LogFilter = filter
1185 .into_primitive()
1186 .map_err(error_object_owned_to_jsonrpc_error)?;
1187
1188 let logs = consensus_graph
1189 .logs(filter)?
1190 .iter()
1191 .cloned()
1192 .map(|l| {
1193 RpcLog::try_from_localized(
1194 l,
1195 *self.sync.network.get_network_type(),
1196 )
1197 })
1198 .collect::<Result<Vec<_>, _>>()?;
1199
1200 if let Some(max_limit) = self.config.get_logs_filter_max_limit {
1202 if logs.len() > max_limit {
1203 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)));
1204 }
1205 }
1206
1207 Ok(logs)
1208 }
1209
1210 fn get_block_reward_info(
1211 &self, epoch: EpochNumber,
1212 ) -> CoreResult<Vec<RpcRewardInfo>> {
1213 info!(
1214 "RPC Request: cfx_getBlockRewardInfo epoch_number={:?}",
1215 epoch
1216 );
1217 let epoch_height: U64 = self
1218 .consensus_graph()
1219 .get_height_from_epoch_number(epoch.clone().into_primitive())?
1220 .into();
1221 let (epoch_later_number, overflow) =
1222 epoch_height.overflowing_add(REWARD_EPOCH_COUNT.into());
1223 if overflow {
1224 bail!(invalid_params("epoch", "Epoch number overflows!"));
1225 }
1226 let epoch_later = match self.consensus.get_hash_from_epoch_number(
1227 EpochNumber::Num(epoch_later_number).into_primitive(),
1228 ) {
1229 Ok(hash) => hash,
1230 Err(e) => {
1231 debug!("get_block_reward_info: get_hash_from_epoch_number returns error: {}", e);
1232 bail!(invalid_params("epoch", "Reward not calculated yet!"))
1233 }
1234 };
1235
1236 let blocks = self.consensus.get_block_hashes_by_epoch(epoch.into())?;
1237
1238 let mut ret = Vec::new();
1239 for b in blocks {
1240 if let Some(reward_result) = self
1241 .consensus
1242 .data_manager()
1243 .block_reward_result_by_hash_with_epoch(
1244 &b,
1245 &epoch_later,
1246 false, true, )
1249 {
1250 if let Some(block_header) =
1251 self.consensus.data_manager().block_header_by_hash(&b)
1252 {
1253 let author = RpcAddress::try_from_h160(
1254 *block_header.author(),
1255 *self.sync.network.get_network_type(),
1256 )?;
1257
1258 ret.push(RpcRewardInfo {
1259 block_hash: b.into(),
1260 author,
1261 total_reward: reward_result.total_reward.into(),
1262 base_reward: reward_result.base_reward.into(),
1263 tx_fee: reward_result.tx_fee.into(),
1264 })
1265 }
1266 }
1267 }
1268 Ok(ret)
1269 }
1270
1271 fn call(
1272 &self, request: TransactionRequest,
1273 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
1274 ) -> CoreResult<Bytes> {
1275 let epoch = Some(
1276 self.get_epoch_number_with_pivot_check(block_hash_or_epoch_number)?,
1277 );
1278 let (execution_outcome, _estimation) =
1279 self.exec_transaction(request, epoch)?;
1280 match execution_outcome {
1281 ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1282 expected,
1283 got,
1284 )) => bail!(call_execution_error(
1285 "Transaction can not be executed".into(),
1286 format! {"nonce is too old expected {:?} got {:?}", expected, got}
1287 )),
1288 ExecutionOutcome::NotExecutedDrop(
1289 TxDropError::InvalidRecipientAddress(recipient),
1290 ) => bail!(call_execution_error(
1291 "Transaction can not be executed".into(),
1292 format! {"invalid recipient address {:?}", recipient}
1293 )),
1294 ExecutionOutcome::NotExecutedDrop(
1295 TxDropError::NotEnoughGasLimit { expected, got },
1296 ) => bail!(call_execution_error(
1297 "Transaction can not be executed".into(),
1298 format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1299 )),
1300 ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1301 address,
1302 )) => bail!(call_execution_error(
1303 "Transaction can not be executed".into(),
1304 format! {"tx sender has contract code: {:?}", address}
1305 )),
1306 ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1307 bail!(call_execution_error(
1308 "Transaction can not be executed".into(),
1309 format! {"{:?}", e}
1310 ))
1311 }
1312 ExecutionOutcome::ExecutionErrorBumpNonce(
1313 ExecutionError::VmError(VmError::Reverted),
1314 executed,
1315 ) => bail!(call_execution_error(
1316 "Transaction reverted".into(),
1317 format!("0x{}", executed.output.to_hex::<String>())
1318 )),
1319 ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1320 bail!(call_execution_error(
1321 "Transaction execution failed".into(),
1322 format! {"{:?}", e}
1323 ))
1324 }
1325 ExecutionOutcome::Finished(executed) => Ok(executed.output.into()),
1326 }
1327 }
1328
1329 fn estimate_gas_and_collateral(
1330 &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1331 ) -> CoreResult<EstimateGasAndCollateralResponse> {
1332 info!(
1333 "RPC Request: cfx_estimateGasAndCollateral request={:?}, epoch={:?}",request,epoch
1334 );
1335 let (execution_outcome, estimation) =
1336 self.exec_transaction(request, epoch)?;
1337 match execution_outcome {
1338 ExecutionOutcome::NotExecutedDrop(TxDropError::OldNonce(
1339 expected,
1340 got,
1341 )) => bail!(call_execution_error(
1342 "Can not estimate: transaction can not be executed".into(),
1343 format! {"nonce is too old expected {:?} got {:?}", expected, got}
1344 )),
1345 ExecutionOutcome::NotExecutedDrop(
1346 TxDropError::InvalidRecipientAddress(recipient),
1347 ) => bail!(call_execution_error(
1348 "Can not estimate: transaction can not be executed".into(),
1349 format! {"invalid recipient address {:?}", recipient}
1350 )),
1351 ExecutionOutcome::NotExecutedDrop(TxDropError::SenderWithCode(
1352 address,
1353 )) => bail!(call_execution_error(
1354 "Can not estimate: transaction sender has code".into(),
1355 format! {"transaction sender has code {:?}", address}
1356 )),
1357 ExecutionOutcome::NotExecutedToReconsiderPacking(e) => {
1358 bail!(call_execution_error(
1359 "Can not estimate: transaction can not be executed".into(),
1360 format! {"{:?}", e}
1361 ))
1362 }
1363 ExecutionOutcome::NotExecutedDrop(
1364 TxDropError::NotEnoughGasLimit { expected, got },
1365 ) => bail!(call_execution_error(
1366 "Can not estimate: transaction can not be executed".into(),
1367 format! {"not enough gas limit with respected to tx size: expected {:?} got {:?}", expected, got}
1368 )),
1369 ExecutionOutcome::ExecutionErrorBumpNonce(
1370 ExecutionError::VmError(VmError::Reverted),
1371 executed,
1372 ) => {
1373 let network_type = *self.sync.network.get_network_type();
1374 let (revert_error, innermost_error, errors) =
1375 decode_error(&executed, |addr| {
1376 RpcAddress::try_from_h160(addr.clone(), network_type)
1377 .unwrap()
1378 .base32_address
1379 });
1380
1381 bail!(call_execution_error(
1382 format!("Estimation isn't accurate: transaction is reverted{}{}",
1383 revert_error, innermost_error),
1384 errors.join("\n"),
1385 ))
1386 }
1387 ExecutionOutcome::ExecutionErrorBumpNonce(e, _) => {
1388 bail!(call_execution_error(
1389 format! {"Can not estimate: transaction execution failed, \
1390 all gas will be charged (execution error: {:?})", e}
1391 .into(),
1392 format! {"{:?}", e}
1393 ))
1394 }
1395 ExecutionOutcome::Finished(executed) => executed,
1396 };
1397 let storage_collateralized =
1398 U64::from(estimation.estimated_storage_limit);
1399 let estimated_gas_used = estimation.estimated_gas_limit;
1400 let response = EstimateGasAndCollateralResponse {
1401 gas_limit: estimated_gas_used, gas_used: estimated_gas_used,
1406 storage_collateralized,
1407 };
1408 Ok(response)
1409 }
1410
1411 fn check_balance_against_transaction(
1412 &self, account_addr: RpcAddress, contract_addr: RpcAddress,
1413 gas_limit: U256, gas_price: U256, storage_limit: U256,
1414 epoch: Option<EpochNumber>,
1415 ) -> CoreResult<CheckBalanceAgainstTransactionResponse> {
1416 self.check_address_network(account_addr.network)?;
1417 self.check_address_network(contract_addr.network)?;
1418
1419 let epoch: primitives::EpochNumber =
1420 epoch.unwrap_or(EpochNumber::LatestState).into();
1421
1422 info!(
1423 "RPC Request: cfx_checkBalanceAgainstTransaction account_addr={:?} contract_addr={:?} gas_limit={:?} gas_price={:?} storage_limit={:?} epoch={:?}",
1424 account_addr, contract_addr, gas_limit, gas_price, storage_limit, epoch
1425 );
1426
1427 let account_addr = account_addr.hex_address.with_native_space();
1428 let contract_addr = contract_addr.hex_address.with_native_space();
1429
1430 if storage_limit > U256::from(std::u64::MAX) {
1431 bail!(JsonRpcError::invalid_params(format!("storage_limit has to be within the range of u64 but {} supplied!", storage_limit)));
1432 }
1433
1434 let state_db = self
1435 .consensus
1436 .get_state_db_by_epoch_number(epoch, "epoch")?;
1437
1438 let user_account = state_db.get_account(&account_addr)?;
1439 let contract_account = state_db.get_account(&contract_addr)?;
1440 let state = State::new(state_db)?;
1441 let is_sponsored = state.check_contract_whitelist(
1442 &contract_addr.address,
1443 &account_addr.address,
1444 )?;
1445
1446 Ok(common::check_balance_against_transaction(
1447 user_account,
1448 contract_account,
1449 is_sponsored,
1450 gas_limit,
1451 gas_price,
1452 storage_limit,
1453 ))
1454 }
1455
1456 fn exec_transaction(
1457 &self, request: TransactionRequest, epoch: Option<EpochNumber>,
1458 ) -> CoreResult<(ExecutionOutcome, EstimateExt)> {
1459 let rpc_request_network = invalid_params_check(
1460 "request",
1461 check_two_rpc_address_network_match(
1462 request.from.as_ref(),
1463 request.to.as_ref(),
1464 ),
1465 )?;
1466 invalid_params_check(
1467 "request",
1468 check_rpc_address_network(
1469 rpc_request_network,
1470 self.sync.network.get_network_type(),
1471 ),
1472 )?;
1473
1474 let consensus_graph = self.consensus_graph();
1475 let epoch = epoch.unwrap_or(EpochNumber::LatestState);
1476
1477 let estimate_request = EstimateRequest {
1478 has_sender: request.from.is_some(),
1479 has_gas_limit: request.gas.is_some(),
1480 has_gas_price: request.has_gas_price(),
1481 has_nonce: request.nonce.is_some(),
1482 has_storage_limit: request.storage_limit.is_some(),
1483 };
1484
1485 let epoch_height = consensus_graph
1486 .get_height_from_epoch_number(epoch.clone().into())?;
1487 let chain_id = consensus_graph.best_chain_id();
1488 let signed_tx = request
1489 .sign_call(
1490 epoch_height,
1491 chain_id.in_native_space(),
1492 self.config.max_estimation_gas_limit,
1493 )
1494 .map_err(error_object_owned_to_jsonrpc_error)?;
1495 trace!("call tx {:?}", signed_tx);
1496
1497 consensus_graph.call_virtual(
1498 &signed_tx,
1499 epoch.into(),
1500 estimate_request,
1501 Default::default(),
1502 )
1503 }
1504
1505 fn current_sync_phase(&self) -> CoreResult<String> {
1506 Ok(self.sync.current_sync_phase().name().into())
1507 }
1508
1509 fn get_pivot_chain_and_weight(
1515 &self, height_range: Option<(u64, u64)>,
1516 ) -> CoreResult<Vec<(H256, U256)>> {
1517 let consensus_graph = self.consensus_graph();
1518 Ok(consensus_graph
1519 .inner
1520 .read()
1521 .get_pivot_chain_and_weight(height_range)?)
1522 }
1523
1524 fn get_executed_info(&self, block_hash: H256) -> CoreResult<(H256, H256)> {
1525 let commitment = self
1526 .consensus
1527 .data_manager()
1528 .get_epoch_execution_commitment(&block_hash)
1529 .ok_or(JsonRpcError::invalid_params(
1530 "No receipts root. Possibly never pivot?".to_owned(),
1531 ))?;
1532 Ok((
1533 commitment.receipts_root.clone().into(),
1534 commitment
1535 .state_root_with_aux_info
1536 .state_root
1537 .compute_state_root_hash(),
1538 ))
1539 }
1540
1541 fn expire_block_gc(&self, timeout: u64) -> CoreResult<()> {
1542 self.sync.expire_block_gc(timeout);
1543 Ok(())
1544 }
1545
1546 pub fn consensus_graph_state(&self) -> CoreResult<ConsensusGraphStates> {
1547 let consensus_graph_states =
1548 STATE_EXPOSER.consensus_graph.lock().retrieve();
1549 let mut block_state_vec = Vec::new();
1551 let mut block_execution_state_vec = Vec::new();
1552
1553 for block_state in &consensus_graph_states.block_state_vec {
1554 block_state_vec.push(ConsensusGraphBlockState {
1555 block_hash: block_state.block_hash.into(),
1556 best_block_hash: block_state.best_block_hash.into(),
1557 block_status: (block_state.block_status as u8).into(),
1558 era_block_hash: block_state.era_block_hash.into(),
1559 adaptive: block_state.adaptive,
1560 })
1561 }
1562 for exec_state in &consensus_graph_states.block_execution_state_vec {
1563 block_execution_state_vec.push(ConsensusGraphBlockExecutionState {
1564 block_hash: exec_state.block_hash.into(),
1565 deferred_state_root: exec_state.deferred_state_root.into(),
1566 deferred_receipt_root: exec_state.deferred_receipt_root.into(),
1567 deferred_logs_bloom_hash: exec_state
1568 .deferred_logs_bloom_hash
1569 .into(),
1570 state_valid: exec_state.state_valid,
1571 })
1572 }
1573
1574 Ok(ConsensusGraphStates {
1575 block_state_vec,
1576 block_execution_state_vec,
1577 })
1578 }
1579
1580 pub fn sync_graph_state(&self) -> CoreResult<SyncGraphStates> {
1581 let sync_graph_states = STATE_EXPOSER.sync_graph.lock().retrieve();
1582 let mut ready_block_vec = Vec::new();
1583 for block_state in sync_graph_states.ready_block_vec {
1584 ready_block_vec.push(SyncGraphBlockState {
1585 block_hash: block_state.block_hash.into(),
1586 parent: block_state.parent.into(),
1587 referees: block_state
1588 .referees
1589 .iter()
1590 .map(|x| H256::from(*x))
1591 .collect(),
1592 nonce: block_state.nonce.into(),
1593 timestamp: U64::from(block_state.timestamp),
1594 adaptive: block_state.adaptive,
1595 })
1596 }
1597 Ok(SyncGraphStates { ready_block_vec })
1598 }
1599
1600 pub fn get_block_status(&self, block_hash: H256) -> CoreResult<(u8, bool)> {
1603 let consensus_graph = self.consensus_graph();
1604 let status = consensus_graph
1605 .data_man
1606 .local_block_info_by_hash(&block_hash)
1607 .ok_or(invalid_params("block_hash", "No block status"))?
1609 .get_status();
1610 let state_valid = consensus_graph
1611 .inner
1612 .read()
1613 .block_node(&block_hash)
1614 .ok_or(invalid_params("block_hash", "No block in consensus"))?
1615 .data
1616 .state_valid
1617 .ok_or(invalid_params("block_hash", "No state_valid"))?;
1618 Ok((status.to_db_status(), state_valid))
1619 }
1620
1621 pub fn get_supply_info(
1622 &self, epoch: Option<EpochNumber>,
1623 ) -> CoreResult<TokenSupplyInfo> {
1624 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1625 let state = State::new(
1626 self.consensus
1627 .get_state_db_by_epoch_number(epoch, "epoch")?,
1628 )?;
1629 let total_issued = state.total_issued_tokens();
1630 let total_staking = state.total_staking_tokens();
1631 let total_collateral = state.total_storage_tokens();
1632 let two_year_unlock_address = genesis_contract_address_two_year();
1633 let four_year_unlock_address = genesis_contract_address_four_year();
1634 let two_year_locked = state
1635 .balance(&two_year_unlock_address)
1636 .unwrap_or(U256::zero());
1637 let four_year_locked = state
1638 .balance(&four_year_unlock_address)
1639 .unwrap_or(U256::zero());
1640 let total_circulating =
1641 total_issued - two_year_locked - four_year_locked;
1642 let total_espace_tokens = state.total_espace_tokens();
1643 Ok(TokenSupplyInfo {
1644 total_circulating,
1645 total_issued,
1646 total_staking,
1647 total_collateral,
1648 total_espace_tokens,
1649 })
1650 }
1651
1652 pub fn get_collateral_info(
1653 &self, epoch: Option<EpochNumber>,
1654 ) -> CoreResult<StorageCollateralInfo> {
1655 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1656 let state = State::new(
1657 self.consensus
1658 .get_state_db_by_epoch_number(epoch, "epoch")?,
1659 )?;
1660 let total_storage_tokens = state.total_storage_tokens();
1661 let converted_storage_points = state.converted_storage_points()
1662 / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1663 let used_storage_points =
1664 state.used_storage_points() / *DRIPS_PER_STORAGE_COLLATERAL_UNIT;
1665 Ok(StorageCollateralInfo {
1666 total_storage_tokens,
1667 converted_storage_points,
1668 used_storage_points,
1669 })
1670 }
1671
1672 pub fn get_vote_params(
1673 &self, epoch: Option<EpochNumber>,
1674 ) -> CoreResult<VoteParamsInfo> {
1675 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1676 let state_db = self
1677 .consensus
1678 .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1679 let interest_rate = state_db.get_global_param::<InterestRate>()?
1680 / U256::from(BLOCKS_PER_YEAR);
1681 let pow_base_reward = state_db.get_global_param::<PowBaseReward>()?;
1682
1683 let storage_point_prop =
1684 state_db.get_system_storage(&storage_point_prop())?;
1685
1686 let base_fee_share_prop = state_db.get_global_param::<BaseFeeProp>()?;
1687 Ok(VoteParamsInfo {
1688 pow_base_reward,
1689 interest_rate,
1690 storage_point_prop,
1691 base_fee_share_prop,
1692 })
1693 }
1694
1695 pub fn get_fee_burnt(
1696 &self, epoch: Option<EpochNumber>,
1697 ) -> CoreResult<U256> {
1698 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
1699 let state_db = self
1700 .consensus
1701 .get_state_db_by_epoch_number(epoch, "epoch_num")?;
1702
1703 Ok(state_db.get_global_param::<TotalBurnt1559>()?)
1704 }
1705
1706 pub fn set_db_crash(
1707 &self, crash_probability: f64, crash_exit_code: i32,
1708 ) -> CoreResult<()> {
1709 if crash_probability == 0.0 {
1710 *CRASH_EXIT_PROBABILITY.lock() = None;
1711 } else {
1712 *CRASH_EXIT_PROBABILITY.lock() = Some(crash_probability);
1713 }
1714 *CRASH_EXIT_CODE.lock() = crash_exit_code;
1715 Ok(())
1716 }
1717
1718 fn check_response_size<T: Serialize>(
1721 &self, response: &T,
1722 ) -> CoreResult<()> {
1723 let max_size = self.config.max_payload_bytes - 50;
1727
1728 let payload_size = serde_json::to_vec(&response)
1729 .map_err(|_e| "Unexpected serialization error")?
1730 .len();
1731
1732 if payload_size > max_size {
1733 bail!(invalid_params(
1735 "epoch",
1736 format!(
1737 "Oversized payload: size = {}, max = {}",
1738 payload_size, max_size
1739 )
1740 ));
1741 }
1742
1743 Ok(())
1744 }
1745
1746 fn get_block_epoch_number(&self, h: &H256) -> Option<u64> {
1747 if let Some(e) = self.consensus.get_block_epoch_number(h) {
1749 return Some(e);
1750 }
1751
1752 self.consensus.data_manager().block_epoch_number(h)
1754 }
1755
1756 fn epoch_receipts(
1757 &self, epoch: BlockHashOrEpochNumber, include_eth_receipt: Option<bool>,
1758 ) -> CoreResult<Option<Vec<Vec<RpcReceipt>>>> {
1759 info!("RPC Request: cfx_getEpochReceipts({:?})", epoch);
1760
1761 let hashes = self
1762 .consensus
1763 .get_block_hashes_by_epoch_or_block_hash(epoch.into())?;
1764
1765 let pivot_hash = *hashes.last().ok_or("Inconsistent state")?;
1766 let mut epoch_receipts = vec![];
1767
1768 for h in hashes {
1769 epoch_receipts.push(
1770 match self.prepare_block_receipts(
1771 h,
1772 pivot_hash,
1773 include_eth_receipt.unwrap_or(false),
1774 )? {
1775 None => return Ok(None), Some(rs) => rs,
1777 },
1778 );
1779 }
1780
1781 self.check_response_size(&epoch_receipts)?;
1784
1785 Ok(Some(epoch_receipts))
1786 }
1787
1788 fn epoch_receipt_proof_by_transaction(
1789 &self, tx_hash: H256,
1790 ) -> JsonRpcResult<Option<EpochReceiptProof>> {
1791 let (block_hash, tx_index_in_block) =
1792 match self.consensus.get_signed_tx_and_tx_info(&tx_hash) {
1793 None => {
1794 bail!(invalid_params(
1795 "transactions hash",
1796 format!(
1797 "Unable to get transaction info for hash {:?}",
1798 tx_hash
1799 )
1800 ));
1801 }
1802 Some((_, TransactionInfo { tx_index, .. })) => {
1803 (tx_index.block_hash, tx_index.real_index)
1804 }
1805 };
1806
1807 let epoch = match self.consensus.get_block_epoch_number(&block_hash) {
1808 Some(epoch) => epoch,
1809 None => {
1810 bail!(invalid_params(
1811 "block hash",
1812 format!(
1813 "Unable to get epoch number for block {:?}",
1814 block_hash
1815 )
1816 ));
1817 }
1818 };
1819
1820 let epoch_number = primitives::EpochNumber::Number(epoch);
1821 let epoch_hashes = match self
1822 .consensus
1823 .get_block_hashes_by_epoch(epoch_number.clone())
1824 {
1825 Ok(hs) => hs,
1826 Err(e) => {
1827 bail!(invalid_params(
1828 "block hash",
1829 format!("Unable to find epoch hashes for {}: {}", epoch, e)
1830 ));
1831 }
1832 };
1833
1834 let block_index_in_epoch =
1835 match epoch_hashes.iter().position(|h| *h == block_hash) {
1836 Some(id) => id,
1837 None => {
1838 bail!(invalid_params(
1839 "block hash",
1840 format!(
1841 "Unable to find block {:?} in epoch {}",
1842 block_hash, epoch
1843 )
1844 ));
1845 }
1846 };
1847
1848 let pivot = epoch_hashes
1849 .last()
1850 .expect("epoch hashes should be not empty")
1851 .clone();
1852
1853 let epoch_receipts = epoch_hashes
1854 .into_iter()
1855 .map(|h| {
1856 self.consensus
1857 .data_manager()
1858 .block_execution_result_by_hash_with_epoch(
1859 &h, &pivot, false, false, )
1862 .map(|res| Arc::new((*res.block_receipts).clone()))
1863 .ok_or_else(|| {
1864 invalid_params(
1865 "block hash",
1866 format!("Unable to find recepits for {}", h),
1867 )
1868 })
1869 })
1870 .collect::<Result<Vec<_>, _>>()?;
1871
1872 let epoch_receipt_proof = compute_epoch_receipt_proof(
1873 &epoch_receipts,
1874 block_index_in_epoch,
1875 tx_index_in_block,
1876 );
1877
1878 Ok(Some(epoch_receipt_proof))
1879 }
1880
1881 fn stat_on_gas_load(
1882 &self, last_epoch: EpochNumber, time_window: U64,
1883 ) -> CoreResult<Option<StatOnGasLoad>> {
1884 let mut stat = StatOnGasLoad::default();
1885 stat.time_elapsed = time_window;
1886
1887 let block_not_found_error = || {
1888 internal_error_msg(
1889 "Cannot find the block by a ConsensusGraph provided hash",
1890 )
1891 };
1892
1893 let machine = self.tx_pool.machine();
1894 let consensus = self.consensus_graph();
1895
1896 let mut epoch_number = match last_epoch {
1897 EpochNumber::Earliest => {
1898 bail!(invalid_params_msg("Cannot stat genesis"))
1899 }
1900 EpochNumber::Num(num) if num.is_zero() => {
1901 bail!(invalid_params_msg("Cannot stat genesis"))
1902 }
1903 EpochNumber::LatestMined => bail!(invalid_params_msg(
1904 "Epoch number is earilier than 'latest_state'"
1905 )),
1906 EpochNumber::Num(num) => {
1907 let pivot_hash = consensus.get_hash_from_epoch_number(
1908 primitives::EpochNumber::LatestState,
1909 )?;
1910 let epoch_number = consensus
1911 .get_block_epoch_number(&pivot_hash)
1912 .ok_or_else(block_not_found_error)?;
1913 if epoch_number < num.as_u64() {
1914 bail!(invalid_params_msg(
1915 "Epoch number is earilier than 'latest_state'"
1916 ))
1917 }
1918 num.as_u64()
1919 }
1920 EpochNumber::LatestCheckpoint
1921 | EpochNumber::LatestFinalized
1922 | EpochNumber::LatestConfirmed
1923 | EpochNumber::LatestState => {
1924 let pivot_hash =
1925 consensus.get_hash_from_epoch_number(last_epoch.into())?;
1926 consensus
1927 .get_block_epoch_number(&pivot_hash)
1928 .ok_or_else(block_not_found_error)?
1929 }
1930 };
1931
1932 let mut last_timestamp: Option<u64> = None;
1933
1934 loop {
1935 let block_hashes = consensus.get_block_hashes_by_epoch(
1937 primitives::EpochNumber::Number(epoch_number),
1938 )?;
1939 let blocks = consensus
1940 .data_manager()
1941 .blocks_by_hash_list(&block_hashes, false)
1942 .ok_or_else(block_not_found_error)?;
1943 let pivot_block = blocks
1944 .last()
1945 .ok_or(internal_error_msg("Epoch without block"))?;
1946
1947 let timestamp = pivot_block.block_header.timestamp();
1949 if last_timestamp.is_none() {
1950 last_timestamp = Some(timestamp)
1951 }
1952 if last_timestamp.unwrap().saturating_sub(time_window.as_u64())
1954 > timestamp
1955 {
1956 break;
1957 }
1958
1959 let params = machine.params();
1961 stat.epoch_num += 1.into();
1962 for b in &blocks {
1963 stat.total_block_num += 1.into();
1964 stat.total_gas_limit += *b.block_header.gas_limit();
1965 if params.can_pack_evm_transaction(b.block_header.height()) {
1966 stat.espace_block_num += 1.into();
1967 stat.espace_gas_limit += *b.block_header.gas_limit()
1968 / params.evm_transaction_gas_ratio;
1969 }
1970 }
1971
1972 for b in &blocks {
1974 let exec_info =
1976 match consensus.get_block_execution_info(&b.hash()) {
1977 None => bail!(internal_error_msg(
1978 "Cannot fetch block receipt with checked input params"
1979 )),
1980 Some((res, _)) => res.1,
1981 };
1982
1983 for (receipt, tx) in exec_info
1984 .block_receipts
1985 .receipts
1986 .iter()
1987 .zip(&b.transactions)
1988 {
1989 let space = tx.space();
1990 if receipt.outcome_status == TransactionStatus::Skipped {
1991 *stat.skipped_tx_count.in_space_mut(space) += 1.into();
1992 *stat.skipped_tx_gas_limit.in_space_mut(space) +=
1993 *tx.gas_limit();
1994 } else {
1995 *stat.confirmed_tx_count.in_space_mut(space) +=
1996 1.into();
1997 *stat.confirmed_tx_gas_limit.in_space_mut(space) +=
1998 *tx.gas_limit();
1999 *stat.tx_gas_charged.in_space_mut(space) +=
2000 receipt.gas_fee / tx.gas_price();
2001 }
2002 }
2003 }
2004
2005 if epoch_number > 0 {
2007 epoch_number -= 1;
2008 } else {
2009 break;
2010 }
2011 }
2012 Ok(Some(stat))
2013 }
2014
2015 fn transactions_by_epoch(
2016 &self, epoch_number: U64,
2017 ) -> JsonRpcResult<Vec<WrapTransaction>> {
2018 debug!("debug_getTransactionsByEpoch {}", epoch_number);
2019
2020 let block_hashs = self
2021 .consensus
2022 .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2023 epoch_number.as_u64(),
2024 ))
2025 .map_err(|e| {
2026 JsonRpcError::invalid_params(format!(
2027 "Could not get block hashes by epoch {}",
2028 e
2029 ))
2030 })?;
2031
2032 let blocks = match self
2033 .consensus
2034 .data_manager()
2035 .blocks_by_hash_list(&block_hashs, false)
2036 {
2037 None => {
2038 return Err(JsonRpcError::invalid_params(format!(
2039 "Could not get blocks for hashs {:?}",
2040 block_hashs
2041 )))
2042 }
2043 Some(b) => b,
2044 };
2045
2046 let pivot = match blocks.last() {
2047 Some(p) => p,
2048 None => {
2049 return Err(JsonRpcError::invalid_params("blocks is empty"))
2050 }
2051 };
2052
2053 self.get_transactions(&blocks, pivot, epoch_number.as_u64())
2054 }
2055
2056 fn transactions_by_block(
2057 &self, block_hash: H256,
2058 ) -> JsonRpcResult<Vec<WrapTransaction>> {
2059 debug!("debug_getTransactionsByBlock {}", block_hash);
2060
2061 let epoch_number = match self.get_block_epoch_number(&block_hash) {
2062 None => {
2063 return Err(JsonRpcError::invalid_params(format!(
2064 "Counld not get epoch for block {}",
2065 block_hash
2066 )))
2067 }
2068 Some(n) => n,
2069 };
2070
2071 let block_hashs = self
2072 .consensus
2073 .get_block_hashes_by_epoch(primitives::EpochNumber::Number(
2074 epoch_number,
2075 ))
2076 .map_err(|e| {
2077 JsonRpcError::invalid_params(format!(
2078 "Could not get block hashes by epoch {}",
2079 e
2080 ))
2081 })?;
2082
2083 let blocks = match self
2084 .consensus
2085 .data_manager()
2086 .blocks_by_hash_list(&block_hashs, false)
2087 {
2088 None => {
2089 return Err(JsonRpcError::invalid_params(format!(
2090 "Counld not get blocks for hashs {:?}",
2091 block_hashs
2092 )))
2093 }
2094 Some(b) => b,
2095 };
2096
2097 let pivot = match blocks.last() {
2098 Some(p) => p,
2099 None => {
2100 return Err(JsonRpcError::invalid_params("blocks is empty"))
2101 }
2102 };
2103
2104 let mut block = vec![];
2105 for b in blocks.iter() {
2106 if b.hash() == block_hash {
2107 block.push((*b).clone());
2108 break;
2109 }
2110 }
2111
2112 self.get_transactions(&block, pivot, epoch_number)
2113 }
2114
2115 fn get_transactions(
2116 &self, blocks: &Vec<Arc<Block>>, pivot: &Arc<Block>, epoch_number: u64,
2117 ) -> JsonRpcResult<Vec<WrapTransaction>> {
2118 let mut transactions = vec![];
2119
2120 for b in blocks.into_iter() {
2121 match self.get_transactions_for_block(b, pivot, epoch_number) {
2122 Ok(mut txs) => {
2123 transactions.append(&mut txs);
2124 }
2125 Err(e) => bail!(internal_error(e)),
2126 };
2127 }
2128
2129 Ok(transactions)
2130 }
2131
2132 fn get_transactions_for_block(
2133 &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2134 ) -> Result<Vec<WrapTransaction>, String> {
2135 let exec_info = self
2136 .consensus
2137 .data_manager()
2138 .block_execution_result_by_hash_with_epoch(
2139 &b.hash(),
2140 &pivot.hash(),
2141 false,
2142 false,
2143 );
2144 if let Some(execution_result) = exec_info {
2145 self.get_transactions_for_executed_block(
2146 b,
2147 pivot,
2148 epoch_number,
2149 execution_result,
2150 )
2151 } else {
2152 self.get_transactions_for_non_executed_block(b, pivot)
2153 }
2154 }
2155
2156 fn get_transactions_for_non_executed_block(
2157 &self, b: &Arc<Block>, pivot: &Arc<Block>,
2158 ) -> Result<Vec<WrapTransaction>, String> {
2159 let network = *self.sync.network.get_network_type();
2160
2161 let mut eth_transaction_idx = 0;
2162 let mut make_eth_wrap_tx = |tx| {
2163 let block_info = (
2164 Some(pivot.hash()),
2165 Some(pivot.block_header.height().into()),
2166 Some(eth_transaction_idx.into()),
2167 );
2168 eth_transaction_idx += 1;
2169 WrapTransaction::EthTransaction(EthTransaction::from_signed(
2170 tx,
2171 block_info,
2172 (None, None),
2173 ))
2174 };
2175
2176 let make_cfx_wrap_tx = |tx| -> Result<WrapTransaction, String> {
2177 Ok(WrapTransaction::NativeTransaction(
2178 RpcTransaction::from_signed(tx, None, network)?,
2179 ))
2180 };
2181
2182 let mut res = vec![];
2183 for (_, tx) in b.transactions.iter().enumerate() {
2184 res.push(match tx.space() {
2185 Space::Ethereum => make_eth_wrap_tx(tx),
2186 Space::Native => make_cfx_wrap_tx(tx)?,
2187 });
2188 }
2189 Ok(res)
2190 }
2191
2192 fn get_transactions_for_executed_block(
2193 &self, b: &Arc<Block>, pivot: &Arc<Block>, epoch_number: u64,
2194 execution_result: BlockExecutionResult,
2195 ) -> Result<Vec<WrapTransaction>, String> {
2196 let network = *self.sync.network.get_network_type();
2197 let maybe_state_root = self
2198 .consensus
2199 .data_manager()
2200 .get_executed_state_root(&b.hash());
2201 let block_receipts = &execution_result.block_receipts.receipts;
2202
2203 let mut eth_transaction_idx = 0;
2204 let mut make_eth_wrap_tx = |tx, id: usize| {
2205 let receipt = &block_receipts[id];
2206
2207 let status = receipt.outcome_status.in_space(Space::Ethereum);
2208 let contract_address = match status == EVM_SPACE_SUCCESS {
2209 true => EthTransaction::deployed_contract_address(tx),
2210 false => None,
2211 };
2212 let block_info = (
2213 Some(pivot.hash()),
2214 Some(pivot.block_header.height().into()),
2215 Some(eth_transaction_idx.into()),
2216 );
2217 eth_transaction_idx += 1;
2218
2219 WrapTransaction::EthTransaction(EthTransaction::from_signed(
2220 tx,
2221 block_info,
2222 (Some(status.into()), contract_address),
2223 ))
2224 };
2225
2226 let mut cfx_transaction_index = 0;
2227 let mut make_cfx_wrap_tx = |tx, id: usize| -> Result<_, String> {
2228 let receipt = &block_receipts[id];
2229 let prior_gas_used = if id == 0 {
2230 U256::zero()
2231 } else {
2232 block_receipts[id - 1].accumulated_gas_used
2233 };
2234
2235 if receipt.outcome_status == TransactionStatus::Skipped {
2236 cfx_transaction_index += 1;
2237 return Ok(WrapTransaction::NativeTransaction(
2238 RpcTransaction::from_signed(tx, None, network)?,
2239 ));
2240 }
2241
2242 let tx_index = TransactionIndex {
2243 block_hash: b.hash(),
2244 real_index: id,
2245 is_phantom: false,
2246 rpc_index: Some(cfx_transaction_index),
2247 };
2248 let tx_exec_error_msg = &execution_result
2249 .block_receipts
2250 .tx_execution_error_messages[id];
2251 let receipt = RpcReceipt::new(
2252 tx.clone(),
2253 receipt.clone(),
2254 tx_index,
2255 prior_gas_used,
2256 Some(epoch_number),
2257 execution_result.block_receipts.block_number,
2258 b.block_header.base_price(),
2259 maybe_state_root,
2260 if tx_exec_error_msg.is_empty() {
2261 None
2262 } else {
2263 Some(tx_exec_error_msg.clone())
2264 },
2265 network,
2266 false,
2267 false,
2268 )?;
2269 cfx_transaction_index += 1;
2270 let executed = Some(PackedOrExecuted::Executed(receipt));
2271 Ok(WrapTransaction::NativeTransaction(
2272 RpcTransaction::from_signed(tx, executed, network)?,
2273 ))
2274 };
2275
2276 let mut res = vec![];
2277 for (id, tx) in b.transactions.iter().enumerate() {
2278 res.push(match tx.space() {
2279 Space::Ethereum => make_eth_wrap_tx(&**tx, id),
2280 Space::Native => make_cfx_wrap_tx(&**tx, id)?,
2281 })
2282 }
2283
2284 Ok(res)
2285 }
2286}
2287
2288#[allow(dead_code)]
2289pub struct CfxHandler {
2290 common: Arc<CommonImpl>,
2291 rpc_impl: Arc<RpcImpl>,
2292}
2293
2294impl CfxHandler {
2295 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2296 CfxHandler { common, rpc_impl }
2297 }
2298}
2299
2300impl Cfx for CfxHandler {
2301 delegate! {
2302 to self.common {
2303 fn best_block_hash(&self) -> JsonRpcResult<H256>;
2304 fn block_by_epoch_number(
2305 &self, epoch_num: EpochNumber, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2306 fn block_by_hash_with_pivot_assumption(
2307 &self, block_hash: H256, pivot_hash: H256, epoch_number: U64)
2308 -> BoxFuture<JsonRpcResult<RpcBlock>>;
2309 fn block_by_hash(&self, hash: H256, include_txs: bool)
2310 -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2311 fn block_by_block_number(&self, block_number: U64, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
2312 fn confirmation_risk_by_hash(&self, block_hash: H256) -> JsonRpcResult<Option<U256>>;
2313 fn blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2314 fn skipped_blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
2315 fn epoch_number(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2316 fn gas_price(&self) -> BoxFuture<JsonRpcResult<U256>>;
2317 fn next_nonce(&self, address: RpcAddress, num: Option<BlockHashOrEpochNumber>)
2318 -> BoxFuture<JsonRpcResult<U256>>;
2319 fn get_status(&self) -> JsonRpcResult<RpcStatus>;
2320 fn get_client_version(&self) -> JsonRpcResult<String>;
2321 fn account_pending_info(&self, addr: RpcAddress) -> BoxFuture<JsonRpcResult<Option<AccountPendingInfo>>>;
2322 fn account_pending_transactions(&self, address: RpcAddress, maybe_start_nonce: Option<U256>, maybe_limit: Option<U64>) -> BoxFuture<JsonRpcResult<AccountPendingTransactions>>;
2323 fn get_pos_reward_by_epoch(&self, epoch: EpochNumber) -> JsonRpcResult<Option<PoSEpochReward>>;
2324 fn fee_history(&self, block_count: HexU64, newest_block: EpochNumber, reward_percentiles: Option<Vec<f64>>) -> BoxFuture<JsonRpcResult<CfxFeeHistory>>;
2325 fn max_priority_fee_per_gas(&self) -> BoxFuture<JsonRpcResult<U256>>;
2326 }
2327
2328 to self.rpc_impl {
2329 fn code(&self, addr: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<Bytes>>;
2330 fn account(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<RpcAccount>>;
2331 fn interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2332 fn accumulate_interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2333 fn pos_economics(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<PoSEconomics>>;
2334 fn admin(&self, address: RpcAddress, num: Option<EpochNumber>)
2335 -> BoxFuture<JsonRpcResult<Option<RpcAddress>>>;
2336 fn sponsor_info(&self, address: RpcAddress, num: Option<EpochNumber>)
2337 -> BoxFuture<JsonRpcResult<SponsorInfo>>;
2338 fn balance(&self, address: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
2339 fn staking_balance(&self, address: RpcAddress, num: Option<EpochNumber>)
2340 -> BoxFuture<JsonRpcResult<U256>>;
2341 fn deposit_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<DepositInfo>>>;
2342 fn vote_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<VoteStakeInfo>>>;
2343 fn collateral_for_storage(&self, address: RpcAddress, num: Option<EpochNumber>)
2344 -> BoxFuture<JsonRpcResult<U256>>;
2345 fn call(&self, request: TransactionRequest, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2346 -> JsonRpcResult<Bytes>;
2347 fn estimate_gas_and_collateral(
2348 &self, request: TransactionRequest, epoch_number: Option<EpochNumber>)
2349 -> JsonRpcResult<EstimateGasAndCollateralResponse>;
2350 fn check_balance_against_transaction(
2351 &self, account_addr: RpcAddress, contract_addr: RpcAddress, gas_limit: U256, gas_price: U256, storage_limit: U256, epoch: Option<EpochNumber>,
2352 ) -> BoxFuture<JsonRpcResult<CheckBalanceAgainstTransactionResponse>>;
2353 fn get_logs(&self, filter: CfxRpcLogFilter) -> BoxFuture<JsonRpcResult<Vec<RpcLog>>>;
2354 fn get_block_reward_info(&self, num: EpochNumber) -> JsonRpcResult<Vec<RpcRewardInfo>>;
2355 fn send_raw_transaction(&self, raw: Bytes) -> JsonRpcResult<H256>;
2356 fn storage_at(&self, addr: RpcAddress, pos: U256, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>)
2357 -> BoxFuture<JsonRpcResult<Option<H256>>>;
2358 fn transaction_by_hash(&self, hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcTransaction>>>;
2359 fn transaction_receipt(&self, tx_hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcReceipt>>>;
2360 fn storage_root(&self, address: RpcAddress, epoch_num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Option<StorageRoot>>>;
2361 fn get_supply_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<TokenSupplyInfo>;
2362 fn get_collateral_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<StorageCollateralInfo>;
2363 fn get_vote_params(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<VoteParamsInfo>;
2364 fn get_fee_burnt(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
2365 }
2366 }
2367}
2368
2369#[allow(dead_code)]
2370pub struct TestRpcImpl {
2371 common: Arc<CommonImpl>,
2372 rpc_impl: Arc<RpcImpl>,
2373}
2374
2375impl TestRpcImpl {
2376 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2377 TestRpcImpl { common, rpc_impl }
2378 }
2379}
2380
2381impl TestRpc for TestRpcImpl {
2382 delegate! {
2383 to self.common {
2384 fn add_latency(&self, id: NodeId, latency_ms: f64) -> JsonRpcResult<()>;
2385 fn add_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2386 fn chain(&self) -> JsonRpcResult<Vec<RpcBlock>>;
2387 fn drop_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
2388 fn get_block_count(&self) -> JsonRpcResult<u64>;
2389 fn get_goodput(&self) -> JsonRpcResult<String>;
2390 fn get_nodeid(&self, challenge: Vec<u8>) -> JsonRpcResult<Vec<u8>>;
2391 fn get_peer_info(&self) -> JsonRpcResult<Vec<PeerInfo>>;
2392 fn say_hello(&self) -> JsonRpcResult<String>;
2393 fn stop(&self) -> JsonRpcResult<()>;
2394 fn save_node_db(&self) -> JsonRpcResult<()>;
2395 fn pos_register(&self, voting_power: U64, version: Option<u8>) -> JsonRpcResult<(Bytes, AccountAddress)>;
2396 fn pos_update_voting_power(
2397 &self, pos_account: AccountAddress, increased_voting_power: U64,
2398 ) -> JsonRpcResult<()>;
2399 fn pos_stop_election(&self) -> JsonRpcResult<Option<u64>>;
2400 fn pos_start_voting(&self, initialize: bool) -> JsonRpcResult<()>;
2401 fn pos_stop_voting(&self) -> JsonRpcResult<()>;
2402 fn pos_voting_status(&self) -> JsonRpcResult<bool>;
2403 fn pos_start(&self) -> JsonRpcResult<()>;
2404 fn pos_force_vote_proposal(&self, block_id: H256) -> JsonRpcResult<()>;
2405 fn pos_force_propose(&self, round: U64, parent_block_id: H256, payload: Vec<TransactionPayload>) -> JsonRpcResult<()>;
2406 fn pos_trigger_timeout(&self, timeout_type: String) -> JsonRpcResult<()>;
2407 fn pos_force_sign_pivot_decision(&self, block_hash: H256, height: U64) -> JsonRpcResult<()>;
2408 fn pos_get_chosen_proposal(&self) -> JsonRpcResult<Option<PosBlock>>;
2409 }
2410
2411 to self.rpc_impl {
2412 fn expire_block_gc(&self, timeout: u64) -> JsonRpcResult<()>;
2413 fn generate_block_with_blame_info(
2414 &self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo) -> JsonRpcResult<H256>;
2415 fn generate_block_with_fake_txs(
2416 &self, raw_txs_without_data: Bytes, adaptive: Option<bool>, tx_data_len: Option<usize>)
2417 -> JsonRpcResult<H256>;
2418 fn generate_custom_block(
2419 &self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes, adaptive: Option<bool>, custom: Option<Vec<Bytes>>)
2420 -> JsonRpcResult<H256>;
2421 fn get_pivot_chain_and_weight(&self, height_range: Option<(u64, u64)>) -> JsonRpcResult<Vec<(H256, U256)>>;
2422 fn get_executed_info(&self, block_hash: H256) -> JsonRpcResult<(H256, H256)> ;
2423 fn generate_fixed_block(
2424 &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize, adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>)
2425 -> JsonRpcResult<H256>;
2426 fn generate_one_block_with_direct_txgen(
2427 &self, num_txs: usize, block_size_limit: usize, num_txs_simple: usize, num_txs_erc20: usize)
2428 -> JsonRpcResult<H256>;
2429 fn generate_one_block(&self, num_txs: usize, block_size_limit: usize) -> JsonRpcResult<H256>;
2430 fn generate_block_with_nonce_and_timestamp(
2431 &self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256, timestamp: u64, adaptive: bool)
2432 -> JsonRpcResult<H256>;
2433 fn generate_empty_blocks(&self, num_blocks: usize) -> JsonRpcResult<Vec<H256>>;
2434 fn get_block_status(&self, block_hash: H256) -> JsonRpcResult<(u8, bool)>;
2435 fn send_usable_genesis_accounts(& self, account_start_index: usize) -> JsonRpcResult<Bytes>;
2436 fn set_db_crash(&self, crash_probability: f64, crash_exit_code: i32) -> JsonRpcResult<()>;
2437 }
2438 }
2439}
2440
2441pub struct LocalRpcImpl {
2442 common: Arc<CommonImpl>,
2443 rpc_impl: Arc<RpcImpl>,
2444}
2445
2446impl LocalRpcImpl {
2447 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
2448 LocalRpcImpl { common, rpc_impl }
2449 }
2450}
2451
2452impl LocalRpc for LocalRpcImpl {
2453 delegate! {
2454 to self.common {
2455 fn txpool_content(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2456 BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<RpcTransaction>>>>>;
2457 fn txpool_inspect(&self, address: Option<RpcAddress>) -> JsonRpcResult<
2458 BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<String>>>>>;
2459 fn txpool_get_account_transactions(&self, address: RpcAddress) -> JsonRpcResult<Vec<RpcTransaction>>;
2460 fn txpool_clear(&self) -> JsonRpcResult<()>;
2461 fn net_node(&self, id: NodeId) -> JsonRpcResult<Option<(String, Node)>>;
2462 fn net_disconnect_node(&self, id: NodeId, op: Option<UpdateNodeOperation>)
2463 -> JsonRpcResult<bool>;
2464 fn net_sessions(&self, node_id: Option<NodeId>) -> JsonRpcResult<Vec<SessionDetails>>;
2465 fn net_throttling(&self) -> JsonRpcResult<throttling::Service>;
2466 fn accounts(&self) -> JsonRpcResult<Vec<RpcAddress>>;
2467 fn new_account(&self, password: String) -> JsonRpcResult<RpcAddress>;
2468 fn unlock_account(
2469 &self, address: RpcAddress, password: String, duration: Option<U128>)
2470 -> JsonRpcResult<bool>;
2471 fn lock_account(&self, address: RpcAddress) -> JsonRpcResult<bool>;
2472 fn sign(&self, data: Bytes, address: RpcAddress, password: Option<String>)
2473 -> JsonRpcResult<H520>;
2474
2475 }
2476
2477 to self.rpc_impl {
2478 fn current_sync_phase(&self) -> JsonRpcResult<String>;
2479 fn consensus_graph_state(&self) -> JsonRpcResult<ConsensusGraphStates>;
2480 fn epoch_receipts(&self, epoch: BlockHashOrEpochNumber, include_eth_recepits: Option<bool>,) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;
2481 fn epoch_receipt_proof_by_transaction(&self, tx_hash: H256) -> JsonRpcResult<Option<EpochReceiptProof>>;
2482 fn stat_on_gas_load(&self, last_epoch: EpochNumber, time_window: U64) -> JsonRpcResult<Option<StatOnGasLoad>>;
2483 fn sync_graph_state(&self) -> JsonRpcResult<SyncGraphStates>;
2484 fn send_transaction(
2485 &self, tx: TransactionRequest, password: Option<String>) -> BoxFuture<JsonRpcResult<H256>>;
2486 fn sign_transaction(&self, tx: TransactionRequest, password: Option<String>) -> JsonRpcResult<String>;
2487 fn transactions_by_epoch(&self, epoch_number: U64) -> JsonRpcResult<Vec<WrapTransaction>>;
2488 fn transactions_by_block(&self, block_hash: H256) -> JsonRpcResult<Vec<WrapTransaction>>;
2489 }
2490 }
2491}