fc_rpc/eth/
mod.rs

1// This file is part of Frontier.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19mod block;
20mod client;
21mod execute;
22mod fee;
23mod filter;
24pub mod format;
25mod mining;
26pub mod pending;
27mod state;
28mod submit;
29mod transaction;
30
31use std::{collections::BTreeMap, marker::PhantomData, sync::Arc};
32
33use ethereum::{BlockV3 as EthereumBlock, TransactionV3 as EthereumTransaction};
34use ethereum_types::{H160, H256, H64, U256, U64};
35use jsonrpsee::core::{async_trait, RpcResult};
36// Substrate
37use sc_client_api::backend::{Backend, StorageProvider};
38use sc_network_sync::SyncingService;
39use sc_transaction_pool_api::TransactionPool;
40use sp_api::{CallApiAt, ProvideRuntimeApi};
41use sp_block_builder::BlockBuilder as BlockBuilderApi;
42use sp_blockchain::HeaderBackend;
43use sp_core::hashing::keccak_256;
44use sp_inherents::CreateInherentDataProviders;
45use sp_runtime::traits::{Block as BlockT, UniqueSaturatedInto};
46// Frontier
47use fc_rpc_core::{types::*, EthApiServer};
48use fc_storage::StorageOverride;
49use fp_rpc::{
50	ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi,
51	RuntimeStorageOverride, TransactionStatus,
52};
53
54use crate::{
55	cache::EthBlockDataCacheTask, frontier_backend_client, internal_err, public_key,
56	signer::EthSigner,
57};
58
59pub use self::{execute::EstimateGasAdapter, filter::EthFilter};
60
61// Configuration trait for RPC configuration.
62pub trait EthConfig<B: BlockT, C>: Send + Sync + 'static {
63	type EstimateGasAdapter: EstimateGasAdapter + Send + Sync;
64	type RuntimeStorageOverride: RuntimeStorageOverride<B, C>;
65}
66
67impl<B: BlockT, C> EthConfig<B, C> for () {
68	type EstimateGasAdapter = ();
69	type RuntimeStorageOverride = ();
70}
71
72/// Eth API implementation.
73pub struct Eth<B: BlockT, C, P, CT, BE, CIDP, EC> {
74	pool: Arc<P>,
75	graph: Arc<P>,
76	client: Arc<C>,
77	convert_transaction: Option<CT>,
78	sync: Arc<SyncingService<B>>,
79	is_authority: bool,
80	signers: Vec<Box<dyn EthSigner>>,
81	storage_override: Arc<dyn StorageOverride<B>>,
82	backend: Arc<dyn fc_api::Backend<B>>,
83	block_data_cache: Arc<EthBlockDataCacheTask<B>>,
84	fee_history_cache: FeeHistoryCache,
85	fee_history_cache_limit: FeeHistoryCacheLimit,
86	/// When using eth_call/eth_estimateGas, the maximum allowed gas limit will be
87	/// block.gas_limit * execute_gas_limit_multiplier
88	execute_gas_limit_multiplier: u64,
89	forced_parent_hashes: Option<BTreeMap<H256, H256>>,
90	/// Something that can create the inherent data providers for pending state.
91	pending_create_inherent_data_providers: CIDP,
92	pending_consensus_data_provider: Option<Box<dyn pending::ConsensusDataProvider<B>>>,
93	_marker: PhantomData<(BE, EC)>,
94}
95
96impl<B, C, P, CT, BE, CIDP, EC> Eth<B, C, P, CT, BE, CIDP, EC>
97where
98	B: BlockT,
99	C: ProvideRuntimeApi<B>,
100	C::Api: EthereumRuntimeRPCApi<B>,
101	C: HeaderBackend<B> + StorageProvider<B, BE> + 'static,
102	BE: Backend<B> + 'static,
103{
104	pub fn new(
105		client: Arc<C>,
106		pool: Arc<P>,
107		graph: Arc<P>,
108		convert_transaction: Option<CT>,
109		sync: Arc<SyncingService<B>>,
110		signers: Vec<Box<dyn EthSigner>>,
111		storage_override: Arc<dyn StorageOverride<B>>,
112		backend: Arc<dyn fc_api::Backend<B>>,
113		is_authority: bool,
114		block_data_cache: Arc<EthBlockDataCacheTask<B>>,
115		fee_history_cache: FeeHistoryCache,
116		fee_history_cache_limit: FeeHistoryCacheLimit,
117		execute_gas_limit_multiplier: u64,
118		forced_parent_hashes: Option<BTreeMap<H256, H256>>,
119		pending_create_inherent_data_providers: CIDP,
120		pending_consensus_data_provider: Option<Box<dyn pending::ConsensusDataProvider<B>>>,
121	) -> Self {
122		Self {
123			client,
124			pool,
125			graph,
126			convert_transaction,
127			sync,
128			is_authority,
129			signers,
130			storage_override,
131			backend,
132			block_data_cache,
133			fee_history_cache,
134			fee_history_cache_limit,
135			execute_gas_limit_multiplier,
136			forced_parent_hashes,
137			pending_create_inherent_data_providers,
138			pending_consensus_data_provider,
139			_marker: PhantomData,
140		}
141	}
142
143	pub async fn block_info_by_number(
144		&self,
145		number_or_hash: BlockNumberOrHash,
146	) -> RpcResult<BlockInfo<B::Hash>> {
147		let id = match frontier_backend_client::native_block_id::<B, C>(
148			self.client.as_ref(),
149			self.backend.as_ref(),
150			Some(number_or_hash),
151		)
152		.await?
153		{
154			Some(id) => id,
155			None => return Ok(BlockInfo::default()),
156		};
157
158		let substrate_hash = self
159			.client
160			.expect_block_hash_from_id(&id)
161			.map_err(|_| internal_err(format!("Expect block number from id: {id}")))?;
162
163		self.block_info_by_substrate_hash(substrate_hash).await
164	}
165
166	pub async fn block_info_by_eth_block_hash(
167		&self,
168		eth_block_hash: H256,
169	) -> RpcResult<BlockInfo<B::Hash>> {
170		let substrate_hash = match frontier_backend_client::load_hash::<B, C>(
171			self.client.as_ref(),
172			self.backend.as_ref(),
173			eth_block_hash,
174		)
175		.await
176		.map_err(|err| internal_err(format!("{err:?}")))?
177		{
178			Some(hash) => hash,
179			_ => return Ok(BlockInfo::default()),
180		};
181
182		self.block_info_by_substrate_hash(substrate_hash).await
183	}
184
185	pub async fn block_info_by_eth_transaction_hash(
186		&self,
187		ethereum_tx_hash: H256,
188	) -> RpcResult<(BlockInfo<B::Hash>, usize)> {
189		let (eth_block_hash, index) = match frontier_backend_client::load_transactions::<B, C>(
190			self.client.as_ref(),
191			self.backend.as_ref(),
192			ethereum_tx_hash,
193			true,
194		)
195		.await
196		.map_err(|err| internal_err(format!("{err:?}")))?
197		{
198			Some((hash, index)) => (hash, index as usize),
199			None => return Ok((BlockInfo::default(), 0)),
200		};
201
202		let substrate_hash = match frontier_backend_client::load_hash::<B, C>(
203			self.client.as_ref(),
204			self.backend.as_ref(),
205			eth_block_hash,
206		)
207		.await
208		.map_err(|err| internal_err(format!("{err:?}")))?
209		{
210			Some(hash) => hash,
211			_ => return Ok((BlockInfo::default(), 0)),
212		};
213
214		Ok((
215			self.block_info_by_substrate_hash(substrate_hash).await?,
216			index,
217		))
218	}
219
220	pub async fn block_info_by_substrate_hash(
221		&self,
222		substrate_hash: B::Hash,
223	) -> RpcResult<BlockInfo<B::Hash>> {
224		let block = self.block_data_cache.current_block(substrate_hash).await;
225		let statuses = self
226			.block_data_cache
227			.current_transaction_statuses(substrate_hash)
228			.await;
229		let receipts = self.storage_override.current_receipts(substrate_hash);
230		let is_eip1559 = self.storage_override.is_eip1559(substrate_hash);
231		let base_fee = self
232			.client
233			.runtime_api()
234			.gas_price(substrate_hash)
235			.unwrap_or_default();
236
237		Ok(BlockInfo::new(
238			block,
239			receipts,
240			statuses,
241			substrate_hash,
242			is_eip1559,
243			base_fee,
244		))
245	}
246}
247
248impl<B, C, P, CT, BE, CIDP, EC> Eth<B, C, P, CT, BE, CIDP, EC>
249where
250	B: BlockT,
251	EC: EthConfig<B, C>,
252{
253	pub fn replace_config<EC2: EthConfig<B, C>>(self) -> Eth<B, C, P, CT, BE, CIDP, EC2> {
254		let Self {
255			client,
256			pool,
257			graph,
258			convert_transaction,
259			sync,
260			is_authority,
261			signers,
262			storage_override,
263			backend,
264			block_data_cache,
265			fee_history_cache,
266			fee_history_cache_limit,
267			execute_gas_limit_multiplier,
268			forced_parent_hashes,
269			pending_create_inherent_data_providers,
270			pending_consensus_data_provider,
271			_marker: _,
272		} = self;
273
274		Eth {
275			client,
276			pool,
277			graph,
278			convert_transaction,
279			sync,
280			is_authority,
281			signers,
282			storage_override,
283			backend,
284			block_data_cache,
285			fee_history_cache,
286			fee_history_cache_limit,
287			execute_gas_limit_multiplier,
288			forced_parent_hashes,
289			pending_create_inherent_data_providers,
290			pending_consensus_data_provider,
291			_marker: PhantomData,
292		}
293	}
294}
295
296#[async_trait]
297impl<B, C, P, CT, BE, CIDP, EC> EthApiServer for Eth<B, C, P, CT, BE, CIDP, EC>
298where
299	B: BlockT,
300	C: CallApiAt<B> + ProvideRuntimeApi<B>,
301	C::Api: BlockBuilderApi<B> + ConvertTransactionRuntimeApi<B> + EthereumRuntimeRPCApi<B>,
302	C: HeaderBackend<B> + StorageProvider<B, BE> + 'static,
303	BE: Backend<B> + 'static,
304	P: TransactionPool<Block = B, Hash = B::Hash> + 'static,
305	CT: ConvertTransaction<<B as BlockT>::Extrinsic> + Send + Sync + 'static,
306	CIDP: CreateInherentDataProviders<B, ()> + Send + 'static,
307	EC: EthConfig<B, C>,
308{
309	// ########################################################################
310	// Client
311	// ########################################################################
312
313	fn protocol_version(&self) -> RpcResult<u64> {
314		self.protocol_version()
315	}
316
317	async fn syncing(&self) -> RpcResult<SyncStatus> {
318		self.syncing().await
319	}
320
321	fn author(&self) -> RpcResult<H160> {
322		self.author()
323	}
324
325	fn accounts(&self) -> RpcResult<Vec<H160>> {
326		self.accounts()
327	}
328
329	fn block_number(&self) -> RpcResult<U256> {
330		self.block_number()
331	}
332
333	fn chain_id(&self) -> RpcResult<Option<U64>> {
334		self.chain_id()
335	}
336
337	// ########################################################################
338	// Block
339	// ########################################################################
340
341	async fn block_by_hash(&self, hash: H256, full: bool) -> RpcResult<Option<RichBlock>> {
342		self.block_by_hash(hash, full).await
343	}
344
345	async fn block_by_number(
346		&self,
347		number_or_hash: BlockNumberOrHash,
348		full: bool,
349	) -> RpcResult<Option<RichBlock>> {
350		self.block_by_number(number_or_hash, full).await
351	}
352
353	async fn block_transaction_count_by_hash(&self, hash: H256) -> RpcResult<Option<U256>> {
354		self.block_transaction_count_by_hash(hash).await
355	}
356
357	async fn block_transaction_count_by_number(
358		&self,
359		number_or_hash: BlockNumberOrHash,
360	) -> RpcResult<Option<U256>> {
361		self.block_transaction_count_by_number(number_or_hash).await
362	}
363
364	async fn block_transaction_receipts(
365		&self,
366		number_or_hash: BlockNumberOrHash,
367	) -> RpcResult<Option<Vec<Receipt>>> {
368		self.block_transaction_receipts(number_or_hash).await
369	}
370
371	fn block_uncles_count_by_hash(&self, hash: H256) -> RpcResult<U256> {
372		self.block_uncles_count_by_hash(hash)
373	}
374
375	fn block_uncles_count_by_number(&self, number_or_hash: BlockNumberOrHash) -> RpcResult<U256> {
376		self.block_uncles_count_by_number(number_or_hash)
377	}
378
379	fn uncle_by_block_hash_and_index(
380		&self,
381		hash: H256,
382		index: Index,
383	) -> RpcResult<Option<RichBlock>> {
384		self.uncle_by_block_hash_and_index(hash, index)
385	}
386
387	fn uncle_by_block_number_and_index(
388		&self,
389		number_or_hash: BlockNumberOrHash,
390		index: Index,
391	) -> RpcResult<Option<RichBlock>> {
392		self.uncle_by_block_number_and_index(number_or_hash, index)
393	}
394
395	// ########################################################################
396	// Transaction
397	// ########################################################################
398
399	async fn transaction_by_hash(&self, hash: H256) -> RpcResult<Option<Transaction>> {
400		self.transaction_by_hash(hash).await
401	}
402
403	async fn transaction_by_block_hash_and_index(
404		&self,
405		hash: H256,
406		index: Index,
407	) -> RpcResult<Option<Transaction>> {
408		self.transaction_by_block_hash_and_index(hash, index).await
409	}
410
411	async fn transaction_by_block_number_and_index(
412		&self,
413		number_or_hash: BlockNumberOrHash,
414		index: Index,
415	) -> RpcResult<Option<Transaction>> {
416		self.transaction_by_block_number_and_index(number_or_hash, index)
417			.await
418	}
419
420	async fn transaction_receipt(&self, hash: H256) -> RpcResult<Option<Receipt>> {
421		let (block_info, index) = self.block_info_by_eth_transaction_hash(hash).await?;
422		self.transaction_receipt(&block_info, hash, index).await
423	}
424
425	// ########################################################################
426	// State
427	// ########################################################################
428
429	async fn balance(
430		&self,
431		address: H160,
432		number_or_hash: Option<BlockNumberOrHash>,
433	) -> RpcResult<U256> {
434		self.balance(address, number_or_hash).await
435	}
436
437	async fn storage_at(
438		&self,
439		address: H160,
440		index: U256,
441		number_or_hash: Option<BlockNumberOrHash>,
442	) -> RpcResult<H256> {
443		self.storage_at(address, index, number_or_hash).await
444	}
445
446	async fn transaction_count(
447		&self,
448		address: H160,
449		number_or_hash: Option<BlockNumberOrHash>,
450	) -> RpcResult<U256> {
451		self.transaction_count(address, number_or_hash).await
452	}
453
454	async fn pending_transactions(&self) -> RpcResult<Vec<Transaction>> {
455		self.pending_transactions().await
456	}
457
458	async fn code_at(
459		&self,
460		address: H160,
461		number_or_hash: Option<BlockNumberOrHash>,
462	) -> RpcResult<Bytes> {
463		self.code_at(address, number_or_hash).await
464	}
465
466	// ########################################################################
467	// Execute
468	// ########################################################################
469
470	async fn call(
471		&self,
472		request: TransactionRequest,
473		number_or_hash: Option<BlockNumberOrHash>,
474		state_overrides: Option<BTreeMap<H160, CallStateOverride>>,
475	) -> RpcResult<Bytes> {
476		self.call(request, number_or_hash, state_overrides).await
477	}
478
479	async fn estimate_gas(
480		&self,
481		request: TransactionRequest,
482		number_or_hash: Option<BlockNumberOrHash>,
483	) -> RpcResult<U256> {
484		self.estimate_gas(request, number_or_hash).await
485	}
486
487	// ########################################################################
488	// Fee
489	// ########################################################################
490
491	fn gas_price(&self) -> RpcResult<U256> {
492		self.gas_price()
493	}
494
495	async fn fee_history(
496		&self,
497		block_count: BlockCount,
498		newest_block: BlockNumberOrHash,
499		reward_percentiles: Option<Vec<f64>>,
500	) -> RpcResult<FeeHistory> {
501		self.fee_history(block_count.into(), newest_block, reward_percentiles)
502			.await
503	}
504
505	fn max_priority_fee_per_gas(&self) -> RpcResult<U256> {
506		self.max_priority_fee_per_gas()
507	}
508
509	// ########################################################################
510	// Mining
511	// ########################################################################
512
513	fn is_mining(&self) -> RpcResult<bool> {
514		self.is_mining()
515	}
516
517	fn hashrate(&self) -> RpcResult<U256> {
518		self.hashrate()
519	}
520
521	fn work(&self) -> RpcResult<Work> {
522		self.work()
523	}
524
525	fn submit_hashrate(&self, hashrate: U256, id: H256) -> RpcResult<bool> {
526		self.submit_hashrate(hashrate, id)
527	}
528
529	fn submit_work(&self, nonce: H64, pow_hash: H256, mix_digest: H256) -> RpcResult<bool> {
530		self.submit_work(nonce, pow_hash, mix_digest)
531	}
532
533	// ########################################################################
534	// Submit
535	// ########################################################################
536
537	async fn send_transaction(&self, request: TransactionRequest) -> RpcResult<H256> {
538		self.send_transaction(request).await
539	}
540
541	async fn send_raw_transaction(&self, bytes: Bytes) -> RpcResult<H256> {
542		self.send_raw_transaction(bytes).await
543	}
544}
545
546fn rich_block_build(
547	block: EthereumBlock,
548	statuses: Vec<Option<TransactionStatus>>,
549	hash: Option<H256>,
550	full_transactions: bool,
551	base_fee: Option<U256>,
552	is_pending: bool,
553) -> RichBlock {
554	let (hash, miner, nonce, total_difficulty) = if !is_pending {
555		(
556			Some(hash.unwrap_or_else(|| H256::from(keccak_256(&rlp::encode(&block.header))))),
557			Some(block.header.beneficiary),
558			Some(block.header.nonce),
559			Some(U256::zero()),
560		)
561	} else {
562		(None, None, None, None)
563	};
564	Rich {
565		inner: Block {
566			header: Header {
567				hash,
568				parent_hash: block.header.parent_hash,
569				uncles_hash: block.header.ommers_hash,
570				author: block.header.beneficiary,
571				miner,
572				state_root: block.header.state_root,
573				transactions_root: block.header.transactions_root,
574				receipts_root: block.header.receipts_root,
575				number: Some(block.header.number),
576				gas_used: block.header.gas_used,
577				gas_limit: block.header.gas_limit,
578				extra_data: Bytes(block.header.extra_data.clone()),
579				logs_bloom: block.header.logs_bloom,
580				timestamp: U256::from(block.header.timestamp / 1000),
581				difficulty: block.header.difficulty,
582				nonce,
583				size: Some(U256::from(rlp::encode(&block.header).len() as u32)),
584			},
585			total_difficulty,
586			uncles: vec![],
587			transactions: {
588				if full_transactions {
589					BlockTransactions::Full(
590						block
591							.transactions
592							.iter()
593							.enumerate()
594							.map(|(index, transaction)| {
595								transaction_build(
596									transaction,
597									Some(&block),
598									statuses[index].as_ref(),
599									base_fee,
600								)
601							})
602							.collect(),
603					)
604				} else {
605					BlockTransactions::Hashes(
606						block
607							.transactions
608							.iter()
609							.map(|transaction| transaction.hash())
610							.collect(),
611					)
612				}
613			},
614			size: Some(U256::from(rlp::encode(&block).len() as u32)),
615			base_fee_per_gas: base_fee,
616		},
617		extra_info: BTreeMap::new(),
618	}
619}
620
621fn transaction_build(
622	ethereum_transaction: &EthereumTransaction,
623	block: Option<&EthereumBlock>,
624	status: Option<&TransactionStatus>,
625	base_fee: Option<U256>,
626) -> Transaction {
627	let pubkey = public_key(ethereum_transaction).ok();
628	let from = status.map_or(
629		{
630			match pubkey {
631				Some(pk) => H160::from(H256::from(keccak_256(&pk))),
632				_ => H160::default(),
633			}
634		},
635		|status| status.from,
636	);
637
638	let mut transaction: Transaction = Transaction::build_from(from, ethereum_transaction);
639
640	if let EthereumTransaction::EIP1559(_) = ethereum_transaction {
641		if block.is_none() && status.is_none() {
642			// If transaction is not mined yet, gas price is considered just max fee per gas.
643		} else {
644			let base_fee = base_fee.unwrap_or_default();
645			let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas.unwrap_or_default();
646			let max_fee_per_gas = transaction.max_fee_per_gas.unwrap_or_default();
647			// If transaction is already mined, gas price is the effective gas price.
648			transaction.gas_price = Some(
649				base_fee
650					.checked_add(max_priority_fee_per_gas)
651					.unwrap_or_else(U256::max_value)
652					.min(max_fee_per_gas),
653			);
654		}
655	}
656
657	// Block hash.
658	transaction.block_hash = block.map(|block| block.header.hash());
659	// Block number.
660	transaction.block_number = block.map(|block| block.header.number);
661	// Transaction index.
662	transaction.transaction_index = status.map(|status| {
663		U256::from(UniqueSaturatedInto::<u32>::unique_saturated_into(
664			status.transaction_index,
665		))
666	});
667	// Creates.
668	transaction.creates = status.and_then(|status| status.contract_address);
669
670	transaction
671}
672
673/// The most commonly used block information in the rpc interfaces.
674#[derive(Clone, Default)]
675pub struct BlockInfo<H> {
676	block: Option<EthereumBlock>,
677	receipts: Option<Vec<ethereum::ReceiptV4>>,
678	statuses: Option<Vec<TransactionStatus>>,
679	substrate_hash: H,
680	is_eip1559: bool,
681	base_fee: U256,
682}
683
684impl<H> BlockInfo<H> {
685	pub fn new(
686		block: Option<EthereumBlock>,
687		receipts: Option<Vec<ethereum::ReceiptV4>>,
688		statuses: Option<Vec<TransactionStatus>>,
689		substrate_hash: H,
690		is_eip1559: bool,
691		base_fee: U256,
692	) -> Self {
693		Self {
694			block,
695			receipts,
696			statuses,
697			substrate_hash,
698			is_eip1559,
699			base_fee,
700		}
701	}
702}