domain_eth_service/
service.rs1use fc_mapping_sync::kv::MappingSyncWorker;
2use fc_mapping_sync::SyncStrategy;
3use fc_rpc::EthTask;
4pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool};
5use fc_storage::StorageOverride;
6use futures::{future, StreamExt};
7use sc_client_api::{BlockchainEvents, StorageProvider};
8use sc_network_sync::SyncingService;
9use sc_service::error::Error as ServiceError;
10use sp_api::ProvideRuntimeApi;
11use sp_blockchain::HeaderBackend;
12use sp_core::traits::SpawnEssentialNamed;
13use sp_runtime::traits::{Block as BlockT, NumberFor, Zero};
14use std::collections::BTreeMap;
15use std::sync::{Arc, Mutex};
16use std::time::Duration;
17
18#[derive(Clone, Debug, clap::Parser)]
20pub struct EthConfiguration {
21 #[arg(long, default_value = "10000")]
23 pub max_past_logs: u32,
24
25 #[arg(long, default_value = "2048")]
27 pub fee_history_limit: u64,
28
29 #[arg(long)]
30 pub enable_dev_signer: bool,
31
32 #[arg(long, default_value = "1")]
34 pub target_gas_price: u64,
35
36 #[arg(long, default_value = "10")]
39 pub execute_gas_limit_multiplier: u64,
40
41 #[arg(long, default_value = "50")]
43 pub eth_log_block_cache: usize,
44
45 #[arg(long, default_value = "50")]
47 pub eth_statuses_cache: usize,
48}
49
50pub(crate) struct FrontierPartialComponents {
51 pub(crate) filter_pool: Option<FilterPool>,
52 pub(crate) fee_history_cache: FeeHistoryCache,
53 pub(crate) fee_history_cache_limit: FeeHistoryCacheLimit,
54}
55
56#[expect(clippy::result_large_err, reason = "Comes from Substrate")]
57pub(crate) fn new_frontier_partial(
58 fee_history_cache_limit: u64,
59) -> Result<FrontierPartialComponents, ServiceError> {
60 Ok(FrontierPartialComponents {
61 filter_pool: Some(Arc::new(Mutex::new(BTreeMap::new()))),
62 fee_history_cache: Arc::new(Mutex::new(BTreeMap::new())),
63 fee_history_cache_limit,
64 })
65}
66
67#[allow(clippy::too_many_arguments)]
68pub(crate) fn spawn_frontier_tasks<Block, Client, Backend, SE>(
69 essential_task_spawner: SE,
70 client: Arc<Client>,
71 backend: Arc<Backend>,
72 frontier_backend: Arc<fc_db::kv::Backend<Block, Client>>,
73 storage_override: Arc<dyn StorageOverride<Block>>,
74 frontier_partial_components: FrontierPartialComponents,
75 sync: Arc<SyncingService<Block>>,
76 pubsub_notification_sinks: Arc<
77 fc_mapping_sync::EthereumBlockNotificationSinks<
78 fc_mapping_sync::EthereumBlockNotification<Block>,
79 >,
80 >,
81) where
82 Block: BlockT,
83 Backend: sc_client_api::Backend<Block> + 'static,
84 Client: ProvideRuntimeApi<Block>
85 + BlockchainEvents<Block>
86 + HeaderBackend<Block>
87 + StorageProvider<Block, Backend>
88 + Send
89 + Sync
90 + 'static,
91 Client::Api: sp_api::ApiExt<Block>
92 + fp_rpc::EthereumRuntimeRPCApi<Block>
93 + fp_rpc::ConvertTransactionRuntimeApi<Block>,
94 SE: SpawnEssentialNamed,
95{
96 essential_task_spawner.spawn_essential(
97 "frontier-mapping-sync-worker",
98 Some("frontier"),
99 Box::pin(
100 MappingSyncWorker::new(
101 client.import_notification_stream(),
102 Duration::new(6, 0),
103 client.clone(),
104 backend,
105 storage_override.clone(),
106 frontier_backend,
107 3,
108 NumberFor::<Block>::zero(),
109 SyncStrategy::Normal,
110 sync,
111 pubsub_notification_sinks,
112 )
113 .for_each(|()| future::ready(())),
114 ),
115 );
116
117 let FrontierPartialComponents {
118 filter_pool,
119 fee_history_cache,
120 fee_history_cache_limit,
121 } = frontier_partial_components;
122
123 if let Some(filter_pool) = filter_pool {
125 const FILTER_RETAIN_THRESHOLD: u64 = 100;
127 essential_task_spawner.spawn_essential(
128 "frontier-filter-pool",
129 Some("frontier"),
130 Box::pin(EthTask::filter_pool_task(
131 client.clone(),
132 filter_pool,
133 FILTER_RETAIN_THRESHOLD,
134 )),
135 );
136 }
137
138 essential_task_spawner.spawn_essential(
140 "frontier-fee-history",
141 Some("frontier"),
142 Box::pin(EthTask::fee_history_task(
143 client,
144 storage_override,
145 fee_history_cache,
146 fee_history_cache_limit,
147 )),
148 );
149}