1mod 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};
36use 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};
46use 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
61pub 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
72pub 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 execute_gas_limit_multiplier: u64,
89 forced_parent_hashes: Option<BTreeMap<H256, H256>>,
90 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 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 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 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 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 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 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 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 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 } 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 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 transaction.block_hash = block.map(|block| block.header.hash());
659 transaction.block_number = block.map(|block| block.header.number);
661 transaction.transaction_index = status.map(|status| {
663 U256::from(UniqueSaturatedInto::<u32>::unique_saturated_into(
664 status.transaction_index,
665 ))
666 });
667 transaction.creates = status.and_then(|status| status.contract_address);
669
670 transaction
671}
672
673#[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}