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