1use cfx_rpc_utils::error::jsonrpc_error_helpers::error_object_owned_to_jsonrpc_error;
6use cfx_types::{
7 AddressSpaceUtil, BigEndianHash, Space, H160, H256, H520, U128, U256, U64,
8};
9use cfx_util_macros::bail;
10use cfxcore::{
11 block_data_manager::BlockDataManager,
12 errors::account_result_to_rpc_result,
13 light_protocol::{self, query_service::TxInfo, Error as LightError},
14 verification::EpochReceiptProof,
15 ConsensusGraph, LightQueryService, PeerInfo, SharedConsensusGraph,
16};
17use cfxcore_accounts::AccountProvider;
18use delegate::delegate;
19use diem_types::transaction::TransactionPayload;
20use futures::future::{self, FutureExt};
21use jsonrpc_core::{BoxFuture, Error as RpcError, Result as JsonRpcResult};
22use log::{debug, info};
23use network::{
24 node_table::{Node, NodeId},
25 throttling, SessionDetails, UpdateNodeOperation,
26};
27use primitives::{
28 Account, DepositInfo, StorageRoot, TransactionWithSignature, VoteStakeInfo,
29};
30use rlp::Encodable;
31use std::{collections::BTreeMap, net::SocketAddr, sync::Arc};
32use crate::{
34 common::delegate_convert,
35 rpc::{
36 errors::{self, invalid_params_check},
37 helpers::{build_block, MAX_FEE_HISTORY_CACHE_BLOCK_COUNT},
38 impls::common::{self, RpcImpl as CommonImpl},
39 traits::{cfx::Cfx, debug::LocalRpc, test::TestRpc},
40 types::{
41 cfx::check_rpc_address_network,
42 pos::{Block as PosBlock, PoSEpochReward},
43 Account as RpcAccount, AccountPendingInfo,
44 AccountPendingTransactions, BlameInfo, Block as RpcBlock,
45 BlockHashOrEpochNumber, Bytes, CfxFeeHistory, CfxRpcLogFilter,
46 CheckBalanceAgainstTransactionResponse, ConsensusGraphStates,
47 EpochNumber, EstimateGasAndCollateralResponse, FeeHistory,
48 Log as RpcLog, PoSEconomics, Receipt as RpcReceipt,
49 RewardInfo as RpcRewardInfo, RpcAddress, SponsorInfo,
50 StatOnGasLoad, Status as RpcStatus, StorageCollateralInfo,
51 SyncGraphStates, TokenSupplyInfo, Transaction as RpcTransaction,
52 TransactionRequest, VoteParamsInfo, WrapTransaction, U64 as HexU64,
53 },
54 CoreBoxFuture, CoreResult,
55 },
56};
57use cfx_addr::Network;
58use cfx_parameters::rpc::GAS_PRICE_DEFAULT_VALUE;
59use cfxcore::{errors::Error::LightProtocol, light_protocol::QueryService};
60use diem_types::account_address::AccountAddress;
61
62macro_rules! not_supported {
64 () => {};
65 ( fn $fn:ident ( &self $(, $name:ident : $type:ty)* ) $( -> BoxFuture<$ret:ty> )? ; $($tail:tt)* ) => {
66 #[allow(unused_variables)]
67 fn $fn ( &self $(, $name : $type)* ) $( -> BoxFuture<$ret> )? {
68 async {
69 Err(errors::unimplemented(Some("Tracking issue: https://github.com/Conflux-Chain/conflux-rust/issues/1461".to_string())))
70 }.boxed()
71 }
72
73 not_supported!($($tail)*);
74 };
75 ( fn $fn:ident ( &self $(, $name:ident : $type:ty)* ) $( -> $ret:ty )? ; $($tail:tt)* ) => {
76 #[allow(unused_variables)]
77 fn $fn ( &self $(, $name : $type)* ) $( -> $ret )? {
78 Err(errors::unimplemented(Some("Tracking issue: https://github.com/Conflux-Chain/conflux-rust/issues/1461".to_string())))
79 }
80
81 not_supported!($($tail)*);
82 };
83}
84
85pub struct RpcImpl {
86 accounts: Arc<AccountProvider>,
88
89 consensus: SharedConsensusGraph,
91
92 data_man: Arc<BlockDataManager>,
94
95 light: Arc<LightQueryService>,
97}
98
99impl RpcImpl {
100 pub fn new(
101 light: Arc<LightQueryService>, accounts: Arc<AccountProvider>,
102 consensus: SharedConsensusGraph, data_man: Arc<BlockDataManager>,
103 ) -> Self {
104 RpcImpl {
105 accounts,
106 consensus,
107 data_man,
108 light,
109 }
110 }
111
112 fn check_address_network(
113 network: Network, light: &QueryService,
114 ) -> CoreResult<()> {
115 invalid_params_check(
116 "address",
117 check_rpc_address_network(Some(network), light.get_network_type()),
118 )
119 .map_err(|e| e.into())
120 }
121
122 fn get_epoch_number_with_pivot_check(
123 consensus_graph: SharedConsensusGraph,
124 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
125 ) -> CoreResult<EpochNumber> {
126 match block_hash_or_epoch_number {
127 Some(BlockHashOrEpochNumber::BlockHashWithOption {
128 hash,
129 require_pivot,
130 }) => {
131 let epoch_number = consensus_graph
132 .get_block_epoch_number_with_pivot_check(
133 &hash,
134 require_pivot.unwrap_or(true),
135 )?;
136 Ok(EpochNumber::Num(U64::from(epoch_number)))
137 }
138 Some(BlockHashOrEpochNumber::EpochNumber(epoch_number)) => {
139 Ok(epoch_number)
140 }
141 None => Ok(EpochNumber::LatestState),
142 }
143 }
144
145 fn account(
146 &self, address: RpcAddress, num: Option<EpochNumber>,
147 ) -> CoreBoxFuture<RpcAccount> {
148 let epoch = num.unwrap_or(EpochNumber::LatestState).into();
149
150 info!(
151 "RPC Request: cfx_getAccount address={:?} epoch={:?}",
152 address, epoch
153 );
154
155 let light = self.light.clone();
157
158 let fut = async move {
159 Self::check_address_network(address.network, &light)?;
160 let network = address.network;
161
162 let account = invalid_params_check(
163 "epoch",
164 light.get_account(epoch, address.hex_address).await,
165 )?;
166
167 let account = account.unwrap_or(account_result_to_rpc_result(
168 "address",
169 Ok(Account::new_empty_with_balance(
170 &address.hex_address.with_native_space(),
171 &U256::zero(), &U256::zero(), )),
174 )?);
175
176 Ok(RpcAccount::try_from(account, network)?)
177 };
178
179 fut.boxed()
180 }
181
182 fn balance(
183 &self, address: RpcAddress,
184 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
185 ) -> CoreBoxFuture<U256> {
186 info!(
187 "RPC Request: cfx_getBalance address={:?} epoch={:?}",
188 address,
189 block_hash_or_epoch_number
190 .as_ref()
191 .ok_or(EpochNumber::LatestState)
192 );
193
194 let light = self.light.clone();
196 let consensus_graph = self.consensus.clone();
197
198 let fut = async move {
199 let epoch = Self::get_epoch_number_with_pivot_check(
200 consensus_graph,
201 block_hash_or_epoch_number,
202 )?
203 .into();
204 Self::check_address_network(address.network, &light)?;
205
206 let account = invalid_params_check(
207 "address",
208 light.get_account(epoch, address.into()).await,
209 )?;
210
211 Ok(account
212 .map(|account| account.balance.into())
213 .unwrap_or_default())
214 };
215
216 fut.boxed()
217 }
218
219 fn admin(
220 &self, address: RpcAddress, num: Option<EpochNumber>,
221 ) -> CoreBoxFuture<Option<RpcAddress>> {
222 let epoch = num.unwrap_or(EpochNumber::LatestState).into();
223 let network = address.network;
224
225 info!(
226 "RPC Request: cfx_getAdmin address={:?} epoch={:?}",
227 address, epoch
228 );
229
230 let light = self.light.clone();
232
233 let fut = async move {
234 Self::check_address_network(address.network, &light)?;
235
236 let account = invalid_params_check(
237 "address",
238 light.get_account(epoch, address.into()).await,
239 )?;
240
241 match account {
242 None => Ok(None),
243 Some(acc) => {
244 Ok(Some(RpcAddress::try_from_h160(acc.admin, network)?))
245 }
246 }
247 };
248
249 fut.boxed()
250 }
251
252 fn sponsor_info(
253 &self, address: RpcAddress, num: Option<EpochNumber>,
254 ) -> CoreBoxFuture<SponsorInfo> {
255 let epoch = num.unwrap_or(EpochNumber::LatestState).into();
256
257 info!(
258 "RPC Request: cfx_getSponsorInfo address={:?} epoch={:?}",
259 address, epoch
260 );
261
262 let light = self.light.clone();
264
265 let fut = async move {
266 Self::check_address_network(address.network, &light)?;
267 let network = address.network;
268
269 let account = invalid_params_check(
270 "address",
271 light.get_account(epoch, address.into()).await,
272 )?;
273
274 match account {
275 None => Ok(SponsorInfo::default(network)?),
276 Some(acc) => {
277 Ok(SponsorInfo::try_from(acc.sponsor_info, network)?)
278 }
279 }
280 };
281
282 fut.boxed()
283 }
284
285 fn staking_balance(
286 &self, address: RpcAddress, num: Option<EpochNumber>,
287 ) -> CoreBoxFuture<U256> {
288 let epoch = num.unwrap_or(EpochNumber::LatestState).into();
289
290 info!(
291 "RPC Request: cfx_getStakingBalance address={:?} epoch={:?}",
292 address, epoch
293 );
294
295 let light = self.light.clone();
297
298 let fut = async move {
299 Self::check_address_network(address.network, &light)?;
300
301 let account = invalid_params_check(
302 "address",
303 light.get_account(epoch, address.into()).await,
304 )?;
305
306 Ok(account
307 .map(|account| account.staking_balance.into())
308 .unwrap_or_default())
309 };
310
311 fut.boxed()
312 }
313
314 fn deposit_list(
315 &self, address: RpcAddress, num: Option<EpochNumber>,
316 ) -> CoreBoxFuture<Vec<DepositInfo>> {
317 let epoch = num.unwrap_or(EpochNumber::LatestState).into();
318
319 info!(
320 "RPC Request: cfx_getDepositList address={:?} epoch_num={:?}",
321 address, epoch
322 );
323
324 let light = self.light.clone();
326
327 let fut = async move {
328 Self::check_address_network(address.network, &light)?;
329
330 let maybe_list = invalid_params_check(
331 "address",
332 light.get_deposit_list(epoch, address.into()).await,
333 )?;
334
335 match maybe_list {
336 None => Ok(vec![]),
337 Some(deposit_list) => Ok(deposit_list.0),
338 }
339 };
340
341 fut.boxed()
342 }
343
344 pub fn account_pending_info(
345 &self, address: RpcAddress,
346 ) -> CoreBoxFuture<Option<AccountPendingInfo>> {
347 info!("RPC Request: cfx_getAccountPendingInfo({:?})", address);
348
349 let fut = async move {
350 Ok(None)
352 };
353 fut.boxed()
354 }
355
356 fn vote_list(
357 &self, address: RpcAddress, num: Option<EpochNumber>,
358 ) -> CoreBoxFuture<Vec<VoteStakeInfo>> {
359 let epoch = num.unwrap_or(EpochNumber::LatestState).into();
360
361 info!(
362 "RPC Request: cfx_getVoteList address={:?} epoch_num={:?}",
363 address, epoch
364 );
365
366 let light = self.light.clone();
368
369 let fut = async move {
370 Self::check_address_network(address.network, &light)?;
371
372 let maybe_list = invalid_params_check(
373 "address",
374 light.get_vote_list(epoch, address.into()).await,
375 )?;
376
377 match maybe_list {
378 None => Ok(vec![]),
379 Some(vote_list) => Ok(vote_list.0),
380 }
381 };
382
383 fut.boxed()
384 }
385
386 fn collateral_for_storage(
387 &self, address: RpcAddress, num: Option<EpochNumber>,
388 ) -> CoreBoxFuture<U256> {
389 let epoch = num.unwrap_or(EpochNumber::LatestState).into();
390
391 info!(
392 "RPC Request: cfx_getCollateralForStorage address={:?} epoch={:?}",
393 address, epoch
394 );
395
396 let light = self.light.clone();
398
399 let fut = async move {
400 Self::check_address_network(address.network, &light)?;
401
402 let account = invalid_params_check(
403 "address",
404 light.get_account(epoch, address.into()).await,
405 )?;
406
407 Ok(account
408 .map(|account| account.collateral_for_storage.into())
409 .unwrap_or_default())
410 };
411
412 fut.boxed()
413 }
414
415 fn code(
416 &self, address: RpcAddress,
417 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
418 ) -> CoreBoxFuture<Bytes> {
419 info!(
420 "RPC Request: cfx_getCode address={:?} epoch={:?}",
421 address,
422 block_hash_or_epoch_number
423 .as_ref()
424 .ok_or(EpochNumber::LatestState)
425 );
426
427 let light = self.light.clone();
429 let consensus_graph = self.consensus.clone();
430
431 let fut = async move {
432 let epoch = Self::get_epoch_number_with_pivot_check(
433 consensus_graph,
434 block_hash_or_epoch_number,
435 )?
436 .into();
437 Self::check_address_network(address.network, &light)?;
438
439 Ok(Bytes::new(
444 invalid_params_check(
445 "address",
446 light.get_code(epoch, address.into()).await,
447 )?
448 .unwrap_or_default(),
449 ))
450 };
451
452 fut.boxed()
453 }
454
455 fn get_logs(&self, filter: CfxRpcLogFilter) -> CoreBoxFuture<Vec<RpcLog>> {
456 info!("RPC Request: cfx_getLogs filter={:?}", filter);
457
458 let light = self.light.clone();
460
461 let fut = async move {
462 if let Some(addresses) = &filter.address {
464 for address in addresses.iter() {
465 invalid_params_check(
466 "filter.address",
467 check_rpc_address_network(
468 Some(address.network),
469 light.get_network_type(),
470 ),
471 )?;
472 }
473 }
474
475 let filter = filter
476 .into_primitive()
477 .map_err(error_object_owned_to_jsonrpc_error)?;
478
479 let logs = light
480 .get_logs(filter)
481 .await
482 .map_err(|e| e.to_string()) .map_err(RpcError::invalid_params)?;
484
485 Ok(logs
486 .into_iter()
487 .map(|l| {
488 RpcLog::try_from_localized(l, *light.get_network_type())
489 })
490 .collect::<Result<_, _>>()?)
491 };
492
493 fut.boxed()
494 }
495
496 fn send_tx_helper(
497 light: Arc<LightQueryService>, raw: Bytes,
498 ) -> CoreResult<H256> {
499 let raw: Vec<u8> = raw.into_vec();
500
501 let tx: TransactionWithSignature =
504 TransactionWithSignature::from_raw(&raw.clone())
505 .map_err(|e| format!("Failed to decode tx: {:?}", e))
506 .map_err(RpcError::invalid_params)?;
507
508 debug!("Deserialized tx: {:?}", tx);
509
510 match light.send_raw_tx(raw) {
515 true => Ok(tx.hash().into()),
516 false => bail!(LightProtocol(light_protocol::Error::InternalError("Unable to relay tx".into()).into())),
517 }
518 }
519
520 fn send_raw_transaction(&self, raw: Bytes) -> CoreResult<H256> {
521 info!("RPC Request: cfx_sendRawTransaction bytes={:?}", raw);
522 Self::send_tx_helper(self.light.clone(), raw)
523 }
524
525 fn send_transaction(
526 &self, mut tx: TransactionRequest, password: Option<String>,
527 ) -> CoreBoxFuture<H256> {
528 info!("RPC Request: cfx_sendTransaction tx={:?}", tx);
529
530 let light = self.light.clone();
532 let accounts = self.accounts.clone();
533
534 let fut = async move {
535 tx.check_rpc_address_network("tx", light.get_network_type())
536 .map_err(error_object_owned_to_jsonrpc_error)?;
537
538 if tx.nonce.is_none() {
539 let address =
543 tx.from.clone().ok_or("from should exist")?.into();
544 let epoch = EpochNumber::LatestState.into_primitive();
545
546 let nonce = light
547 .get_account(epoch, address)
548 .await?
549 .map(|a| a.nonce)
550 .unwrap_or(U256::zero());
551
552 tx.nonce.replace(nonce.into());
553 debug!("after loading nonce in latest state, tx = {:?}", tx);
554 }
555
556 let epoch_height = light.get_latest_verifiable_epoch_number().map_err(|_| {
557 format!("the light client cannot retrieve/verify the latest mined pivot block.")
558 })?;
559 let chain_id = light.get_latest_verifiable_chain_id().map_err(|_| {
560 format!("the light client cannot retrieve/verify the latest chain_id.")
561 })?;
562 let tx = tx.sign_with(
563 epoch_height,
564 chain_id.in_native_space(),
565 password,
566 accounts,
567 )?;
568
569 Self::send_tx_helper(light, Bytes::new(tx.rlp_bytes()))
570 };
571
572 fut.boxed()
573 }
574
575 fn storage_root(
576 &self, address: RpcAddress, epoch_num: Option<EpochNumber>,
577 ) -> CoreBoxFuture<Option<StorageRoot>> {
578 let epoch_num = epoch_num.unwrap_or(EpochNumber::LatestState);
579
580 info!(
581 "RPC Request: cfx_getStorageRoot address={:?} epoch={:?})",
582 address, epoch_num
583 );
584
585 let light = self.light.clone();
587
588 let fut = async move {
589 Self::check_address_network(address.network, &light)?;
590
591 let root = invalid_params_check(
592 "address",
593 light
594 .get_storage_root(epoch_num.into(), address.into())
595 .await,
596 )?;
597
598 Ok(Some(root))
599 };
600
601 fut.boxed()
602 }
603
604 fn storage_at(
605 &self, address: RpcAddress, position: U256,
606 block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>,
607 ) -> CoreBoxFuture<Option<H256>> {
608 let position: H256 = H256::from_uint(&position);
609 info!(
612 "RPC Request: cfx_getStorageAt address={:?} position={:?} epoch={:?})",
613 address,
614 position,
615 block_hash_or_epoch_number
616 .as_ref()
617 .ok_or(EpochNumber::LatestState)
618 );
619
620 let light = self.light.clone();
622 let consensus_graph = self.consensus.clone();
623
624 let fut = async move {
625 let epoch_num = Self::get_epoch_number_with_pivot_check(
626 consensus_graph,
627 block_hash_or_epoch_number,
628 )?;
629 Self::check_address_network(address.network, &light)?;
630
631 let maybe_entry = light
632 .get_storage(epoch_num.into(), address.into(), position)
633 .await
634 .map_err(|e| e.to_string()) .map_err(RpcError::invalid_params)?;
636
637 Ok(maybe_entry.map(Into::into))
638 };
639
640 fut.boxed()
641 }
642
643 fn transaction_by_hash(
644 &self, hash: H256,
645 ) -> CoreBoxFuture<Option<RpcTransaction>> {
646 info!("RPC Request: cfx_getTransactionByHash hash={:?}", hash);
647
648 let light = self.light.clone();
652
653 let fut = async move {
654 let tx = light
655 .get_tx(hash.into())
656 .await
657 .map_err(|e| e.to_string()) .map_err(RpcError::invalid_params)?;
659
660 Ok(Some(RpcTransaction::from_signed(
661 &tx,
662 None,
663 *light.get_network_type(),
664 )?))
665 };
666
667 fut.boxed()
668 }
669
670 fn transaction_receipt(
671 &self, tx_hash: H256,
672 ) -> CoreBoxFuture<Option<RpcReceipt>> {
673 let hash: H256 = tx_hash.into();
674 info!("RPC Request: cfx_getTransactionReceipt hash={:?}", hash);
675
676 let light = self.light.clone();
678 let data_man = self.data_man.clone();
679
680 let fut = async move {
681 let tx_info = match light.get_tx_info(hash).await {
688 Ok(t) => t,
689 Err(LightError::Timeout(_)) => return Ok(None),
690 Err(e) => {
691 bail!(RpcError::invalid_params(e.to_string()))
692 }
693 };
694
695 let TxInfo {
696 tx,
697 maybe_block_number,
698 receipt,
699 tx_index,
700 maybe_epoch,
701 maybe_state_root,
702 prior_gas_used,
703 } = tx_info;
704
705 if maybe_block_number.is_none() || tx_index.is_phantom {
706 return Ok(None);
707 }
708
709 let maybe_base_price = data_man
710 .block_header_by_hash(&tx_index.block_hash)
711 .and_then(|x| x.base_price());
712
713 let receipt = RpcReceipt::new(
714 tx,
715 receipt,
716 tx_index,
717 prior_gas_used,
718 maybe_epoch,
719 maybe_block_number.unwrap(),
720 maybe_base_price,
721 maybe_state_root,
722 None,
724 *light.get_network_type(),
725 false,
726 true,
727 )?;
728
729 Ok(Some(receipt))
730 };
731
732 fut.boxed()
733 }
734
735 pub fn epoch_number(&self, epoch: Option<EpochNumber>) -> CoreResult<U256> {
736 let epoch = epoch.unwrap_or(EpochNumber::LatestMined);
737 info!("RPC Request: cfx_epochNumber epoch={:?}", epoch);
738
739 invalid_params_check(
740 "epoch",
741 self.light
742 .get_height_from_epoch_number(epoch.into())
743 .map(|height| height.into()),
744 )
745 .map_err(|e| e.into())
746 }
747
748 pub fn next_nonce(
749 &self, address: RpcAddress, num: Option<BlockHashOrEpochNumber>,
750 ) -> CoreBoxFuture<U256> {
751 info!(
752 "RPC Request: cfx_getNextNonce address={:?} num={:?}",
753 address, num
754 );
755
756 let consensus_graph = self.consensus.clone();
758 let light = self.light.clone();
759
760 let fut = async move {
761 Self::check_address_network(address.network, &light)?;
762
763 let epoch =
764 Self::get_epoch_number_with_pivot_check(consensus_graph, num)?
765 .into();
766
767 let account = invalid_params_check(
768 "address",
769 light.get_account(epoch, address.into()).await,
770 )?;
771
772 Ok(account
773 .map(|account| account.nonce.into())
774 .unwrap_or_default())
775 };
776
777 fut.boxed()
778 }
779
780 pub fn block_by_hash(
781 &self, hash: H256, include_txs: bool,
782 ) -> CoreBoxFuture<Option<RpcBlock>> {
783 let hash = hash.into();
784
785 info!(
786 "RPC Request: cfx_getBlockByHash hash={:?} include_txs={:?}",
787 hash, include_txs
788 );
789
790 let consensus_graph = self.consensus.clone();
792 let data_man = self.data_man.clone();
793 let light = self.light.clone();
794
795 let fut = async move {
796 let block = match light.retrieve_block(hash).await? {
797 None => return Ok(None),
798 Some(b) => b,
799 };
800
801 let inner = consensus_graph.inner.read();
802
803 Ok(Some(build_block(
804 &block,
805 *light.get_network_type(),
806 &*consensus_graph,
807 &*inner,
808 &data_man,
809 include_txs,
810 Some(Space::Native),
811 )?))
812 };
813
814 fut.boxed()
815 }
816
817 pub fn block_by_hash_with_pivot_assumption(
818 &self, block_hash: H256, pivot_hash: H256, epoch_number: U64,
819 ) -> CoreBoxFuture<RpcBlock> {
820 let block_hash = block_hash.into();
821 let pivot_hash = pivot_hash.into();
822 let epoch_number = epoch_number.as_u64();
823
824 info!(
825 "RPC Request: cfx_getBlockByHashWithPivotAssumption block_hash={:?} pivot_hash={:?} epoch_number={:?}",
826 block_hash, pivot_hash, epoch_number
827 );
828
829 let consensus_graph = self.consensus.clone();
831 let data_man = self.data_man.clone();
832 let light = self.light.clone();
833
834 let fut = async move {
835 consensus_graph
838 .inner
839 .read()
840 .check_block_pivot_assumption(&pivot_hash, epoch_number)
841 .map_err(RpcError::invalid_params)?;
842
843 let block = light
845 .retrieve_block(block_hash)
846 .await?
847 .ok_or_else(|| RpcError::invalid_params("Block not found"))?;
848
849 let inner = consensus_graph.inner.read();
850
851 Ok(build_block(
852 &block,
853 *light.get_network_type(),
854 &*consensus_graph,
855 &*inner,
856 &data_man,
857 true,
858 Some(Space::Native),
859 )?)
860 };
861
862 fut.boxed()
863 }
864
865 pub fn block_by_epoch_number(
866 &self, epoch: EpochNumber, include_txs: bool,
867 ) -> CoreBoxFuture<Option<RpcBlock>> {
868 info!(
869 "RPC Request: cfx_getBlockByEpochNumber epoch={:?} include_txs={:?}",
870 epoch, include_txs
871 );
872
873 let consensus_graph = self.consensus.clone();
875 let data_man = self.data_man.clone();
876 let light = self.light.clone();
877
878 let fut = async move {
879 let epoch: u64 = light
880 .get_height_from_epoch_number(epoch.into())
881 .map_err(|e| e.to_string())
882 .map_err(RpcError::invalid_params)?;
883
884 let hash = consensus_graph
886 .inner
887 .read()
888 .get_pivot_hash_from_epoch_number(epoch)
889 .map_err(RpcError::invalid_params)?;
890
891 let block = match light.retrieve_block(hash).await? {
893 None => return Ok(None),
894 Some(b) => b,
895 };
896
897 let inner = consensus_graph.inner.read();
898
899 Ok(Some(build_block(
900 &block,
901 *light.get_network_type(),
902 &*consensus_graph,
903 &*inner,
904 &data_man,
905 include_txs,
906 Some(Space::Native),
907 )?))
908 };
909
910 fut.boxed()
911 }
912
913 pub fn blocks_by_epoch(&self, epoch: EpochNumber) -> CoreResult<Vec<H256>> {
914 info!("RPC Request: cfx_getBlocksByEpoch epoch_number={:?}", epoch);
915
916 let height = self
917 .light
918 .get_height_from_epoch_number(epoch.into())
919 .map_err(|e| e.to_string())
920 .map_err(RpcError::invalid_params)?;
921
922 let hashes = self
923 .consensus
924 .inner
925 .read()
926 .block_hashes_by_epoch(height)
927 .map_err(|e| e.to_string())
928 .map_err(RpcError::invalid_params)?;
929
930 Ok(hashes)
931 }
932
933 pub fn gas_price(&self) -> CoreBoxFuture<U256> {
934 info!("RPC Request: cfx_gasPrice");
935
936 let light = self.light.clone();
937
938 let fut = async move {
939 Ok(light
940 .gas_price()
941 .await
942 .map_err(|e| e.to_string())
943 .map_err(RpcError::invalid_params)?
944 .unwrap_or(GAS_PRICE_DEFAULT_VALUE.into()))
945 };
946
947 fut.boxed()
948 }
949
950 pub fn interest_rate(
951 &self, epoch: Option<EpochNumber>,
952 ) -> CoreBoxFuture<U256> {
953 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
954 info!("RPC Request: cfx_getInterestRate epoch={:?}", epoch);
955
956 let light = self.light.clone();
958
959 let fut = async move {
960 Ok(light
961 .get_interest_rate(epoch)
962 .await
963 .map_err(|e| e.to_string())
964 .map_err(RpcError::invalid_params)?)
965 };
966
967 fut.boxed()
968 }
969
970 pub fn accumulate_interest_rate(
971 &self, epoch: Option<EpochNumber>,
972 ) -> CoreBoxFuture<U256> {
973 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
974
975 info!(
976 "RPC Request: cfx_getAccumulateInterestRate epoch={:?}",
977 epoch
978 );
979
980 let light = self.light.clone();
982
983 let fut = async move {
984 Ok(light
985 .get_accumulate_interest_rate(epoch)
986 .await
987 .map_err(|e| e.to_string())
988 .map_err(RpcError::invalid_params)?)
989 };
990
991 fut.boxed()
992 }
993
994 pub fn pos_economics(
995 &self, epoch: Option<EpochNumber>,
996 ) -> CoreBoxFuture<PoSEconomics> {
997 let epoch = epoch.unwrap_or(EpochNumber::LatestState).into();
998
999 info!("RPC Request: cfx_getPoSEconomics epoch={:?}", epoch);
1000
1001 let light = self.light.clone();
1003
1004 let fut = async move {
1005 Ok(light
1006 .get_pos_economics(epoch)
1007 .await
1008 .map(|ans| PoSEconomics {
1009 total_pos_staking_tokens: ans[0],
1010 distributable_pos_interest: ans[1],
1011 last_distribute_block: ans[2].as_u64().into(),
1012 })
1013 .map_err(|e| e.to_string())
1014 .map_err(RpcError::invalid_params)?)
1015 };
1016
1017 fut.boxed()
1018 }
1019
1020 fn check_balance_against_transaction(
1021 &self, account_addr: RpcAddress, contract_addr: RpcAddress,
1022 gas_limit: U256, gas_price: U256, storage_limit: U256,
1023 epoch: Option<EpochNumber>,
1024 ) -> CoreBoxFuture<CheckBalanceAgainstTransactionResponse> {
1025 let epoch: primitives::EpochNumber =
1026 epoch.unwrap_or(EpochNumber::LatestState).into();
1027
1028 info!(
1029 "RPC Request: cfx_checkBalanceAgainstTransaction account_addr={:?} contract_addr={:?} gas_limit={:?} gas_price={:?} storage_limit={:?} epoch={:?}",
1030 account_addr, contract_addr, gas_limit, gas_price, storage_limit, epoch
1031 );
1032
1033 let light = self.light.clone();
1035
1036 let fut = async move {
1037 Self::check_address_network(account_addr.network, &light)?;
1038 Self::check_address_network(contract_addr.network, &light)?;
1039
1040 let account_addr: H160 = account_addr.into();
1041 let contract_addr: H160 = contract_addr.into();
1042
1043 if storage_limit > U256::from(std::u64::MAX) {
1044 bail!(RpcError::invalid_params(format!("storage_limit has to be within the range of u64 but {} supplied!", storage_limit)));
1045 }
1046
1047 let (user_account, contract_account, is_sponsored) =
1049 future::try_join3(
1050 light.get_account(epoch.clone(), account_addr),
1051 light.get_account(epoch.clone(), contract_addr),
1052 light.is_user_sponsored(epoch, contract_addr, account_addr),
1053 )
1054 .await?;
1055
1056 Ok(common::check_balance_against_transaction(
1057 user_account,
1058 contract_account,
1059 is_sponsored,
1060 gas_limit,
1061 gas_price,
1062 storage_limit,
1063 ))
1064 };
1065
1066 fut.boxed()
1067 }
1068
1069 fn fee_history(
1070 &self, mut block_count: HexU64, newest_block: EpochNumber,
1071 reward_percentiles: Option<Vec<f64>>,
1072 ) -> CoreBoxFuture<CfxFeeHistory> {
1073 info!(
1074 "RPC Request: cfx_feeHistory: block_count={}, newest_block={:?}, reward_percentiles={:?}",
1075 block_count, newest_block, reward_percentiles
1076 );
1077
1078 if block_count.as_u64() == 0 {
1079 return async { Ok(FeeHistory::new().into()) }.boxed();
1080 }
1081
1082 if block_count.as_u64() > MAX_FEE_HISTORY_CACHE_BLOCK_COUNT {
1083 block_count = HexU64::from(MAX_FEE_HISTORY_CACHE_BLOCK_COUNT);
1084 }
1085
1086 let consensus_graph = self.consensus.clone();
1088 let light = self.light.clone();
1089 let reward_percentiles = reward_percentiles.unwrap_or_default();
1090
1091 let fut = async move {
1092 let start_height: u64 = light
1093 .get_height_from_epoch_number(newest_block.into())
1094 .map_err(|e| e.to_string())
1095 .map_err(RpcError::invalid_params)?;
1096
1097 let mut current_height = start_height;
1098
1099 let mut fee_history = FeeHistory::new();
1100
1101 while current_height
1102 >= start_height.saturating_sub(block_count.as_u64() - 1)
1103 {
1104 let block = fetch_block_for_fee_history(
1105 consensus_graph.clone(),
1106 light.clone(),
1107 current_height,
1108 )
1109 .await?;
1110
1111 let transactions = block
1112 .transactions
1113 .iter()
1114 .filter(|tx| tx.space() == Space::Native)
1115 .map(|x| &**x);
1116 fee_history
1119 .push_front_block(
1120 Space::Native,
1121 &reward_percentiles,
1122 &block.block_header,
1123 transactions,
1124 )
1125 .map_err(|_| RpcError::internal_error())?;
1126
1127 if current_height == 0 {
1128 break;
1129 } else {
1130 current_height -= 1;
1131 }
1132 }
1133
1134 let block = fetch_block_for_fee_history(
1135 consensus_graph.clone(),
1136 light.clone(),
1137 start_height + 1,
1138 )
1139 .await?;
1140 let oldest_block = if current_height == 0 {
1141 0
1142 } else {
1143 current_height + 1
1144 };
1145 fee_history.finish(
1146 oldest_block,
1147 block.block_header.base_price().as_ref(),
1148 Space::Native,
1149 );
1150 Ok(fee_history.into())
1151 };
1152
1153 fut.boxed()
1154 }
1155}
1156
1157async fn fetch_block_for_fee_history(
1158 consensus_graph: Arc<ConsensusGraph>, light: Arc<QueryService>, height: u64,
1159) -> cfxcore::errors::Result<primitives::Block> {
1160 let hash = consensus_graph
1161 .inner
1162 .read()
1163 .get_pivot_hash_from_epoch_number(height)
1164 .map_err(RpcError::invalid_params)?;
1165
1166 match light.retrieve_block(hash).await? {
1167 None => Err(RpcError::internal_error().into()),
1168 Some(b) => Ok(b),
1169 }
1170}
1171
1172pub struct CfxHandler {
1173 common: Arc<CommonImpl>,
1174 rpc_impl: Arc<RpcImpl>,
1175}
1176
1177impl CfxHandler {
1178 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
1179 CfxHandler { common, rpc_impl }
1180 }
1181}
1182
1183impl Cfx for CfxHandler {
1184 delegate! {
1185 to self.common {
1186 fn best_block_hash(&self) -> JsonRpcResult<H256>;
1187 fn confirmation_risk_by_hash(&self, block_hash: H256) -> JsonRpcResult<Option<U256>>;
1188 fn get_client_version(&self) -> JsonRpcResult<String>;
1189 fn get_status(&self) -> JsonRpcResult<RpcStatus>;
1190 fn skipped_blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
1191 fn account_pending_info(&self, addr: RpcAddress) -> BoxFuture<JsonRpcResult<Option<AccountPendingInfo>>>;
1192 }
1193
1194 to self.rpc_impl {
1195 fn account(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<RpcAccount>>;
1196 fn accumulate_interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
1197 fn admin(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Option<RpcAddress>>>;
1198 fn balance(&self, address: RpcAddress, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
1199 fn block_by_epoch_number(&self, epoch_num: EpochNumber, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
1200 fn block_by_hash_with_pivot_assumption(&self, block_hash: H256, pivot_hash: H256, epoch_number: U64) -> BoxFuture<JsonRpcResult<RpcBlock>>;
1201 fn block_by_hash(&self, hash: H256, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
1202 fn blocks_by_epoch(&self, num: EpochNumber) -> JsonRpcResult<Vec<H256>>;
1203 fn check_balance_against_transaction(&self, account_addr: RpcAddress, contract_addr: RpcAddress, gas_limit: U256, gas_price: U256, storage_limit: U256, epoch: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<CheckBalanceAgainstTransactionResponse>>;
1204 fn code(&self, address: RpcAddress, block_hash_or_epoch_num: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<Bytes>>;
1205 fn collateral_for_storage(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
1206 fn deposit_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<DepositInfo>>>;
1207 fn epoch_number(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<U256>;
1208 fn gas_price(&self) -> BoxFuture<JsonRpcResult<U256>>;
1209 fn get_logs(&self, filter: CfxRpcLogFilter) -> BoxFuture<JsonRpcResult<Vec<RpcLog>>>;
1210 fn interest_rate(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
1211 fn next_nonce(&self, address: RpcAddress, num: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
1212 fn pos_economics(&self, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<PoSEconomics>>;
1213 fn send_raw_transaction(&self, raw: Bytes) -> JsonRpcResult<H256>;
1214 fn sponsor_info(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<SponsorInfo>>;
1215 fn staking_balance(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<U256>>;
1216 fn storage_at(&self, addr: RpcAddress, pos: U256, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> BoxFuture<JsonRpcResult<Option<H256>>>;
1217 fn storage_root(&self, address: RpcAddress, epoch_num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Option<StorageRoot>>>;
1218 fn transaction_by_hash(&self, hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcTransaction>>>;
1219 fn transaction_receipt(&self, tx_hash: H256) -> BoxFuture<JsonRpcResult<Option<RpcReceipt>>>;
1220 fn vote_list(&self, address: RpcAddress, num: Option<EpochNumber>) -> BoxFuture<JsonRpcResult<Vec<VoteStakeInfo>>>;
1221 fn fee_history(&self, block_count: HexU64, newest_block: EpochNumber, reward_percentiles: Option<Vec<f64>>) -> BoxFuture<JsonRpcResult<CfxFeeHistory>>;
1222 }
1223 }
1224
1225 not_supported! {
1227 fn account_pending_transactions(&self, address: RpcAddress, maybe_start_nonce: Option<U256>, maybe_limit: Option<U64>) -> BoxFuture<JsonRpcResult<AccountPendingTransactions>>;
1228 fn block_by_block_number(&self, block_number: U64, include_txs: bool) -> BoxFuture<JsonRpcResult<Option<RpcBlock>>>;
1229 fn call(&self, request: TransactionRequest, block_hash_or_epoch_number: Option<BlockHashOrEpochNumber>) -> JsonRpcResult<Bytes>;
1230 fn estimate_gas_and_collateral(&self, request: TransactionRequest, epoch_num: Option<EpochNumber>) -> JsonRpcResult<EstimateGasAndCollateralResponse>;
1231 fn get_block_reward_info(&self, num: EpochNumber) -> JsonRpcResult<Vec<RpcRewardInfo>>;
1232 fn get_supply_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<TokenSupplyInfo>;
1233 fn get_collateral_info(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<StorageCollateralInfo>;
1234 fn get_vote_params(&self, epoch_num: Option<EpochNumber>) -> JsonRpcResult<VoteParamsInfo>;
1235 fn get_pos_reward_by_epoch(&self, epoch: EpochNumber) -> JsonRpcResult<Option<PoSEpochReward>>;
1236 fn get_fee_burnt(&self, epoch: Option<EpochNumber>) -> JsonRpcResult<U256>;
1237 fn max_priority_fee_per_gas(&self) -> BoxFuture<JsonRpcResult<U256>>;
1238 }
1239}
1240
1241pub struct TestRpcImpl {
1242 common: Arc<CommonImpl>,
1243 }
1245
1246impl TestRpcImpl {
1247 pub fn new(common: Arc<CommonImpl>, _rpc_impl: Arc<RpcImpl>) -> Self {
1248 TestRpcImpl {
1249 common, }
1251 }
1252}
1253
1254impl TestRpc for TestRpcImpl {
1255 delegate! {
1256 to self.common {
1257 fn add_latency(&self, id: NodeId, latency_ms: f64) -> JsonRpcResult<()>;
1258 fn add_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
1259 fn chain(&self) -> JsonRpcResult<Vec<RpcBlock>>;
1260 fn drop_peer(&self, node_id: NodeId, address: SocketAddr) -> JsonRpcResult<()>;
1261 fn get_block_count(&self) -> JsonRpcResult<u64>;
1262 fn get_goodput(&self) -> JsonRpcResult<String>;
1263 fn get_nodeid(&self, challenge: Vec<u8>) -> JsonRpcResult<Vec<u8>>;
1264 fn get_peer_info(&self) -> JsonRpcResult<Vec<PeerInfo>>;
1265 fn save_node_db(&self) -> JsonRpcResult<()>;
1266 fn say_hello(&self) -> JsonRpcResult<String>;
1267 fn stop(&self) -> JsonRpcResult<()>;
1268 fn pos_register(&self, voting_power: U64, version: Option<u8>) -> JsonRpcResult<(Bytes, AccountAddress)>;
1269 fn pos_update_voting_power(
1270 &self, pos_account: AccountAddress, increased_voting_power: U64,
1271 ) -> JsonRpcResult<()>;
1272 fn pos_stop_election(&self) -> JsonRpcResult<Option<u64>>;
1273 fn pos_start_voting(&self, initialize: bool) -> JsonRpcResult<()>;
1274 fn pos_stop_voting(&self) -> JsonRpcResult<()>;
1275 fn pos_voting_status(&self) -> JsonRpcResult<bool>;
1276 fn pos_start(&self) -> JsonRpcResult<()>;
1277 fn pos_force_vote_proposal(&self, block_id: H256) -> JsonRpcResult<()>;
1278 fn pos_force_propose(&self, round: U64, parent_block_id: H256, payload: Vec<TransactionPayload>) -> JsonRpcResult<()>;
1279 fn pos_trigger_timeout(&self, timeout_type: String) -> JsonRpcResult<()>;
1280 fn pos_force_sign_pivot_decision(&self, block_hash: H256, height: U64) -> JsonRpcResult<()>;
1281 fn pos_get_chosen_proposal(&self) -> JsonRpcResult<Option<PosBlock>>;
1282 }
1283 }
1284
1285 not_supported! {
1286 fn expire_block_gc(&self, timeout: u64) -> JsonRpcResult<()>;
1287 fn generate_block_with_blame_info(&self, num_txs: usize, block_size_limit: usize, blame_info: BlameInfo) -> JsonRpcResult<H256>;
1288 fn generate_block_with_fake_txs(&self, raw_txs_without_data: Bytes, adaptive: Option<bool>, tx_data_len: Option<usize>) -> JsonRpcResult<H256>;
1289 fn generate_block_with_nonce_and_timestamp(&self, parent: H256, referees: Vec<H256>, raw: Bytes, nonce: U256, timestamp: u64, adaptive: bool) -> JsonRpcResult<H256>;
1290 fn generate_custom_block(&self, parent_hash: H256, referee: Vec<H256>, raw_txs: Bytes, adaptive: Option<bool>, custom: Option<Vec<Bytes>>) -> JsonRpcResult<H256>;
1291 fn generate_empty_blocks(&self, num_blocks: usize) -> JsonRpcResult<Vec<H256>>;
1292 fn generate_fixed_block(&self, parent_hash: H256, referee: Vec<H256>, num_txs: usize, adaptive: bool, difficulty: Option<u64>, pos_reference: Option<H256>) -> JsonRpcResult<H256>;
1293 fn generate_one_block_with_direct_txgen(&self, num_txs: usize, block_size_limit: usize, num_txs_simple: usize, num_txs_erc20: usize) -> JsonRpcResult<H256>;
1294 fn generate_one_block(&self, num_txs: usize, block_size_limit: usize) -> JsonRpcResult<H256>;
1295 fn get_block_status(&self, block_hash: H256) -> JsonRpcResult<(u8, bool)>;
1296 fn get_executed_info(&self, block_hash: H256) -> JsonRpcResult<(H256, H256)> ;
1297 fn get_pivot_chain_and_weight(&self, height_range: Option<(u64, u64)>) -> JsonRpcResult<Vec<(H256, U256)>>;
1298 fn send_usable_genesis_accounts(&self, account_start_index: usize) -> JsonRpcResult<Bytes>;
1299 fn set_db_crash(&self, crash_probability: f64, crash_exit_code: i32) -> JsonRpcResult<()>;
1300 }
1301}
1302
1303pub struct DebugRpcImpl {
1304 common: Arc<CommonImpl>,
1305 rpc_impl: Arc<RpcImpl>,
1306}
1307
1308impl DebugRpcImpl {
1309 pub fn new(common: Arc<CommonImpl>, rpc_impl: Arc<RpcImpl>) -> Self {
1310 DebugRpcImpl { common, rpc_impl }
1311 }
1312}
1313
1314impl LocalRpc for DebugRpcImpl {
1315 delegate! {
1316 to self.common {
1317 fn txpool_content(&self, address: Option<RpcAddress>) -> JsonRpcResult<
1318 BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<RpcTransaction>>>>>;
1319 fn txpool_inspect(&self, address: Option<RpcAddress>) -> JsonRpcResult<
1320 BTreeMap<String, BTreeMap<String, BTreeMap<usize, Vec<String>>>>>;
1321 fn txpool_get_account_transactions(&self, address: RpcAddress) -> JsonRpcResult<Vec<RpcTransaction>>;
1322 fn txpool_clear(&self) -> JsonRpcResult<()>;
1323 fn accounts(&self) -> JsonRpcResult<Vec<RpcAddress>>;
1324 fn lock_account(&self, address: RpcAddress) -> JsonRpcResult<bool>;
1325 fn net_disconnect_node(&self, id: NodeId, op: Option<UpdateNodeOperation>) -> JsonRpcResult<bool>;
1326 fn net_node(&self, id: NodeId) -> JsonRpcResult<Option<(String, Node)>>;
1327 fn net_sessions(&self, node_id: Option<NodeId>) -> JsonRpcResult<Vec<SessionDetails>>;
1328 fn net_throttling(&self) -> JsonRpcResult<throttling::Service>;
1329 fn new_account(&self, password: String) -> JsonRpcResult<RpcAddress>;
1330 fn sign(&self, data: Bytes, address: RpcAddress, password: Option<String>) -> JsonRpcResult<H520>;
1331 fn unlock_account(&self, address: RpcAddress, password: String, duration: Option<U128>) -> JsonRpcResult<bool>;
1332 }
1333
1334 to self.rpc_impl {
1335 fn send_transaction(&self, tx: TransactionRequest, password: Option<String>) -> BoxFuture<JsonRpcResult<H256>>;
1336 }
1337 }
1338
1339 not_supported! {
1340 fn consensus_graph_state(&self) -> JsonRpcResult<ConsensusGraphStates>;
1341 fn current_sync_phase(&self) -> JsonRpcResult<String>;
1342 fn epoch_receipts(&self, epoch: BlockHashOrEpochNumber, include_eth_recepits: Option<bool>) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;
1343 fn epoch_receipt_proof_by_transaction(&self, tx_hash: H256) -> JsonRpcResult<Option<EpochReceiptProof>>;
1344 fn stat_on_gas_load(&self, epoch: EpochNumber, time_window: U64) -> JsonRpcResult<Option<StatOnGasLoad>>;
1345 fn sign_transaction(&self, tx: TransactionRequest, password: Option<String>) -> JsonRpcResult<String>;
1346 fn sync_graph_state(&self) -> JsonRpcResult<SyncGraphStates>;
1347 fn transactions_by_epoch(&self, epoch_number: U64) -> JsonRpcResult<Vec<WrapTransaction>>;
1348 fn transactions_by_block(&self, block_hash: H256) -> JsonRpcResult<Vec<WrapTransaction>>;
1349 }
1350}