1use fc_rpc::{
22 Eth, EthApiServer, EthBlockDataCacheTask, EthFilter, EthFilterApiServer, EthPubSub,
23 EthPubSubApiServer, Net, NetApiServer, TxPool, TxPoolApiServer, Web3, Web3ApiServer,
24};
25use fc_rpc_core::types::{FeeHistoryCache, FilterPool};
26use fc_storage::{StorageOverride, StorageOverrideHandler};
27use jsonrpsee::RpcModule;
28use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
29use std::path::Path;
30
31use cumulus_primitives_core::{ParaId, RelayParentOffsetApi};
32use sc_client_api::{
33 AuxStore, Backend, BlockchainEvents, StateBackend, StorageProvider, UsageProvider,
34};
35use sc_consensus_manual_seal::rpc::ManualSealApiServer;
36use sc_network::service::traits::NetworkService;
37use sc_network_sync::SyncingService;
38use sc_rpc::dev::DevApiServer;
39pub use sc_rpc::SubscriptionTaskExecutor;
40use sc_transaction_pool_api::TransactionPool;
41use sp_api::{CallApiAt, ProvideRuntimeApi};
42use sp_block_builder::BlockBuilder;
43use sp_blockchain::{
44 Backend as BlockchainBackend, Error as BlockChainError, HeaderBackend, HeaderMetadata,
45};
46use sp_consensus_aura::{sr25519::AuthorityId as AuraId, AuraApi};
47use sp_inherents::CreateInherentDataProviders;
48use sp_runtime::traits::{BlakeTwo256, Block as BlockT};
49use std::sync::Arc;
50use substrate_frame_rpc_system::{System, SystemApiServer};
51
52use moonbeam_rpc_debug::{Debug, DebugServer};
53use moonbeam_rpc_trace::{Trace, TraceServer};
54
55use crate::evm_tracing_types::{FrontierBackendConfig, FrontierConfig};
56use astar_primitives::*;
57
58pub mod tracing;
59
60type HashFor<Block> = <Block as BlockT>::Hash;
61
62#[derive(Clone)]
63pub struct EvmTracingConfig {
64 pub tracing_requesters: tracing::RpcRequesters,
65 pub trace_filter_max_count: u32,
66 pub enable_txpool: bool,
67}
68
69#[derive(Debug, Copy, Clone, Default, clap::ValueEnum)]
71pub enum FrontierBackendType {
72 #[default]
74 KeyValue,
75 Sql,
77}
78
79pub fn open_frontier_backend<C, BE>(
82 client: Arc<C>,
83 config: &sc_service::Configuration,
84 rpc_config: &FrontierConfig,
85) -> Result<fc_db::Backend<Block, C>, String>
86where
87 C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,
88 C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,
89 C: Send + Sync + 'static,
90 C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
91 BE: Backend<Block> + 'static,
92 BE::State: StateBackend<BlakeTwo256>,
93{
94 let config_dir = config.base_path.config_dir(config.chain_spec.id());
95 let path = config_dir.join("frontier").join("db");
96
97 let frontier_backend = match rpc_config.frontier_backend_config {
98 FrontierBackendConfig::KeyValue => {
99 fc_db::Backend::KeyValue(Arc::new(fc_db::kv::Backend::<Block, C>::new(
100 client,
101 &fc_db::kv::DatabaseSettings {
102 source: fc_db::DatabaseSource::RocksDb {
103 path,
104 cache_size: 0,
105 },
106 },
107 )?))
108 }
109 FrontierBackendConfig::Sql {
110 pool_size,
111 num_ops_timeout,
112 thread_count,
113 cache_size,
114 } => {
115 let overrides = Arc::new(StorageOverrideHandler::new(client.clone()));
116 std::fs::create_dir_all(&path).expect("failed creating sql db directory");
117 let backend = futures::executor::block_on(fc_db::sql::Backend::new(
118 fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig {
119 path: Path::new("sqlite:///")
120 .join(path)
121 .join("frontier.db3")
122 .to_str()
123 .expect("frontier sql path error"),
124 create_if_missing: true,
125 thread_count: thread_count,
126 cache_size: cache_size,
127 }),
128 pool_size,
129 std::num::NonZeroU32::new(num_ops_timeout),
130 overrides.clone(),
131 ))
132 .unwrap_or_else(|err| panic!("failed creating sql backend: {:?}", err));
133 fc_db::Backend::Sql(Arc::new(backend))
134 }
135 };
136
137 Ok(frontier_backend)
138}
139
140pub struct AstarEthConfig<C, BE>(std::marker::PhantomData<(C, BE)>);
141
142impl<C, BE> fc_rpc::EthConfig<Block, C> for AstarEthConfig<C, BE>
143where
144 C: sc_client_api::StorageProvider<Block, BE> + Sync + Send + 'static,
145 BE: Backend<Block> + 'static,
146{
147 type EstimateGasAdapter = ();
150 type RuntimeStorageOverride =
152 fc_rpc::frontier_backend_client::SystemAccountId32StorageOverride<Block, C, BE>;
153}
154
155pub struct FullDeps<C, P> {
157 pub client: Arc<C>,
159 pub pool: Arc<P>,
161 pub graph: Arc<P>,
163 pub network: Arc<dyn NetworkService>,
165 pub sync: Arc<SyncingService<Block>>,
167 pub is_authority: bool,
169 pub frontier_backend: Arc<dyn fc_api::Backend<Block>>,
171 pub filter_pool: FilterPool,
173 pub fee_history_limit: u64,
175 pub fee_history_cache: FeeHistoryCache,
177 pub storage_override: Arc<dyn StorageOverride<Block>>,
179 pub block_data_cache: Arc<EthBlockDataCacheTask<Block>>,
181 pub enable_evm_rpc: bool,
183 pub command_sink:
185 Option<futures::channel::mpsc::Sender<sc_consensus_manual_seal::EngineCommand<Hash>>>,
186}
187
188pub fn create_full<C, P, BE>(
190 deps: FullDeps<C, P>,
191 subscription_task_executor: SubscriptionTaskExecutor,
192 pubsub_notification_sinks: Arc<
193 fc_mapping_sync::EthereumBlockNotificationSinks<
194 fc_mapping_sync::EthereumBlockNotification<Block>,
195 >,
196 >,
197 tracing_config: EvmTracingConfig,
198) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
199where
200 C: ProvideRuntimeApi<Block>
201 + HeaderBackend<Block>
202 + UsageProvider<Block>
203 + CallApiAt<Block>
204 + AuxStore
205 + StorageProvider<Block, BE>
206 + HeaderMetadata<Block, Error = BlockChainError>
207 + BlockchainEvents<Block>
208 + Send
209 + Sync
210 + 'static,
211 C: sc_client_api::BlockBackend<Block>,
212 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
213 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
214 + fp_rpc::ConvertTransactionRuntimeApi<Block>
215 + fp_rpc::EthereumRuntimeRPCApi<Block>
216 + BlockBuilder<Block>
217 + AuraApi<Block, AuraId>
218 + moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block>
219 + moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block>
220 + RelayParentOffsetApi<Block>,
221 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
222 BE: Backend<Block> + 'static,
223 BE::State: StateBackend<BlakeTwo256>,
224 BE::Blockchain: BlockchainBackend<Block>,
225{
226 let client = Arc::clone(&deps.client);
227 let graph = Arc::clone(&deps.graph);
228
229 let mut io = create_full_rpc(deps, subscription_task_executor, pubsub_notification_sinks)?;
230
231 if tracing_config.enable_txpool {
232 io.merge(TxPool::new(Arc::clone(&client), graph).into_rpc())?;
233 }
234
235 if let Some(trace_filter_requester) = tracing_config.tracing_requesters.trace {
236 io.merge(
237 Trace::new(
238 client,
239 trace_filter_requester,
240 tracing_config.trace_filter_max_count,
241 )
242 .into_rpc(),
243 )?;
244 }
245
246 if let Some(debug_requester) = tracing_config.tracing_requesters.debug {
247 io.merge(Debug::new(debug_requester).into_rpc())?;
248 }
249
250 Ok(io)
251}
252
253pub fn create_full_local_dev<C, P, BE>(
258 deps: FullDeps<C, P>,
259 subscription_task_executor: SubscriptionTaskExecutor,
260 pubsub_notification_sinks: Arc<
261 fc_mapping_sync::EthereumBlockNotificationSinks<
262 fc_mapping_sync::EthereumBlockNotification<Block>,
263 >,
264 >,
265 local_para_id: ParaId,
266 tracing_config: EvmTracingConfig,
267) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
268where
269 C: ProvideRuntimeApi<Block>
270 + HeaderBackend<Block>
271 + UsageProvider<Block>
272 + CallApiAt<Block>
273 + AuxStore
274 + StorageProvider<Block, BE>
275 + HeaderMetadata<Block, Error = BlockChainError>
276 + BlockchainEvents<Block>
277 + Send
278 + Sync
279 + 'static,
280 C: sc_client_api::BlockBackend<Block>,
281 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
282 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
283 + fp_rpc::ConvertTransactionRuntimeApi<Block>
284 + fp_rpc::EthereumRuntimeRPCApi<Block>
285 + BlockBuilder<Block>
286 + AuraApi<Block, AuraId>
287 + moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block>
288 + moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block>
289 + RelayParentOffsetApi<Block>,
290 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
291 BE: Backend<Block> + 'static,
292 BE::State: StateBackend<BlakeTwo256>,
293 BE::Blockchain: BlockchainBackend<Block>,
294{
295 let client = Arc::clone(&deps.client);
296 let graph = Arc::clone(&deps.graph);
297
298 let mut io = create_full_rpc_local_dev(
299 deps,
300 subscription_task_executor,
301 pubsub_notification_sinks,
302 local_para_id,
303 )?;
304
305 if tracing_config.enable_txpool {
306 io.merge(TxPool::new(Arc::clone(&client), graph).into_rpc())?;
307 }
308
309 if let Some(trace_filter_requester) = tracing_config.tracing_requesters.trace {
310 io.merge(
311 Trace::new(
312 client,
313 trace_filter_requester,
314 tracing_config.trace_filter_max_count,
315 )
316 .into_rpc(),
317 )?;
318 }
319
320 if let Some(debug_requester) = tracing_config.tracing_requesters.debug {
321 io.merge(Debug::new(debug_requester).into_rpc())?;
322 }
323
324 Ok(io)
325}
326
327fn create_full_rpc_local_dev<C, P, BE>(
328 deps: FullDeps<C, P>,
329 subscription_task_executor: SubscriptionTaskExecutor,
330 pubsub_notification_sinks: Arc<
331 fc_mapping_sync::EthereumBlockNotificationSinks<
332 fc_mapping_sync::EthereumBlockNotification<Block>,
333 >,
334 >,
335 local_para_id: ParaId,
336) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
337where
338 C: ProvideRuntimeApi<Block>
339 + UsageProvider<Block>
340 + HeaderBackend<Block>
341 + CallApiAt<Block>
342 + AuxStore
343 + StorageProvider<Block, BE>
344 + HeaderMetadata<Block, Error = BlockChainError>
345 + BlockchainEvents<Block>
346 + Send
347 + Sync
348 + 'static,
349 C: sc_client_api::BlockBackend<Block>,
350 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
351 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
352 + fp_rpc::ConvertTransactionRuntimeApi<Block>
353 + fp_rpc::EthereumRuntimeRPCApi<Block>
354 + BlockBuilder<Block>
355 + AuraApi<Block, AuraId>
356 + RelayParentOffsetApi<Block>,
357 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
358 BE: Backend<Block> + 'static,
359 BE::State: StateBackend<BlakeTwo256>,
360 BE::Blockchain: BlockchainBackend<Block>,
361{
362 create_full_rpc_with_pending_provider(
363 deps,
364 subscription_task_executor,
365 pubsub_notification_sinks,
366 |client| crate::local::LocalPendingInherentDataProvider::new(client, local_para_id),
367 )
368}
369
370fn create_full_rpc<C, P, BE>(
371 deps: FullDeps<C, P>,
372 subscription_task_executor: SubscriptionTaskExecutor,
373 pubsub_notification_sinks: Arc<
374 fc_mapping_sync::EthereumBlockNotificationSinks<
375 fc_mapping_sync::EthereumBlockNotification<Block>,
376 >,
377 >,
378) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
379where
380 C: ProvideRuntimeApi<Block>
381 + UsageProvider<Block>
382 + HeaderBackend<Block>
383 + CallApiAt<Block>
384 + AuxStore
385 + StorageProvider<Block, BE>
386 + HeaderMetadata<Block, Error = BlockChainError>
387 + BlockchainEvents<Block>
388 + Send
389 + Sync
390 + 'static,
391 C: sc_client_api::BlockBackend<Block>,
392 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
393 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
394 + fp_rpc::ConvertTransactionRuntimeApi<Block>
395 + fp_rpc::EthereumRuntimeRPCApi<Block>
396 + BlockBuilder<Block>
397 + AuraApi<Block, AuraId>
398 + RelayParentOffsetApi<Block>,
399 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
400 BE: Backend<Block> + 'static,
401 BE::State: StateBackend<BlakeTwo256>,
402 BE::Blockchain: BlockchainBackend<Block>,
403{
404 create_full_rpc_with_pending_provider(
405 deps,
406 subscription_task_executor,
407 pubsub_notification_sinks,
408 crate::parachain::PendingCrateInherentDataProvider::new,
409 )
410}
411
412fn create_full_rpc_with_pending_provider<C, P, BE, CIDP, F>(
413 deps: FullDeps<C, P>,
414 subscription_task_executor: SubscriptionTaskExecutor,
415 pubsub_notification_sinks: Arc<
416 fc_mapping_sync::EthereumBlockNotificationSinks<
417 fc_mapping_sync::EthereumBlockNotification<Block>,
418 >,
419 >,
420 make_pending_inherent_data_provider: F,
421) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
422where
423 C: ProvideRuntimeApi<Block>
424 + UsageProvider<Block>
425 + HeaderBackend<Block>
426 + CallApiAt<Block>
427 + AuxStore
428 + StorageProvider<Block, BE>
429 + HeaderMetadata<Block, Error = BlockChainError>
430 + BlockchainEvents<Block>
431 + Send
432 + Sync
433 + 'static,
434 C: sc_client_api::BlockBackend<Block>,
435 C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
436 + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
437 + fp_rpc::ConvertTransactionRuntimeApi<Block>
438 + fp_rpc::EthereumRuntimeRPCApi<Block>
439 + BlockBuilder<Block>
440 + AuraApi<Block, AuraId>
441 + RelayParentOffsetApi<Block>,
442 P: TransactionPool<Block = Block, Hash = HashFor<Block>> + Sync + Send + 'static,
443 BE: Backend<Block> + 'static,
444 BE::State: StateBackend<BlakeTwo256>,
445 BE::Blockchain: BlockchainBackend<Block>,
446 CIDP: CreateInherentDataProviders<Block, ()> + Send + Sync + 'static,
447 F: FnOnce(Arc<C>) -> CIDP,
448{
449 let mut io = RpcModule::new(());
450 let FullDeps {
451 client,
452 pool,
453 graph,
454 network,
455 sync,
456 is_authority,
457 frontier_backend,
458 filter_pool,
459 fee_history_limit,
460 fee_history_cache,
461 storage_override,
462 block_data_cache,
463 enable_evm_rpc,
464 command_sink,
465 } = deps;
466
467 io.merge(System::new(client.clone(), pool.clone()).into_rpc())?;
468 io.merge(TransactionPayment::new(client.clone()).into_rpc())?;
469 io.merge(sc_rpc::dev::Dev::new(client.clone()).into_rpc())?;
470
471 if let Some(command_sink) = command_sink {
472 io.merge(sc_consensus_manual_seal::rpc::ManualSeal::new(command_sink).into_rpc())?;
473 }
474
475 if !enable_evm_rpc {
476 return Ok(io);
477 }
478
479 let no_tx_converter: Option<fp_rpc::NoTransactionConverter> = None;
480
481 io.merge(
482 Eth::<_, _, _, _, _, _, ()>::new(
483 client.clone(),
484 pool.clone(),
485 graph.clone(),
486 no_tx_converter,
487 sync.clone(),
488 Default::default(),
489 storage_override.clone(),
490 frontier_backend.clone(),
491 is_authority,
492 block_data_cache.clone(),
493 fee_history_cache,
494 fee_history_limit,
495 10,
497 None,
498 make_pending_inherent_data_provider(client.clone()),
499 Some(Box::new(
500 crate::parachain::AuraConsensusDataProviderFallback::new(client.clone()),
501 )),
502 )
503 .replace_config::<AstarEthConfig<C, BE>>()
504 .into_rpc(),
505 )?;
506
507 let max_past_logs: u32 = 10_000;
508 let max_block_range: u32 = 1024;
509 let max_stored_filters: usize = 500;
510 io.merge(
511 EthFilter::new(
512 client.clone(),
513 frontier_backend,
514 graph.clone(),
515 filter_pool,
516 max_stored_filters,
517 max_past_logs,
518 max_block_range,
519 block_data_cache,
520 )
521 .into_rpc(),
522 )?;
523
524 io.merge(Net::new(client.clone(), network.clone(), true).into_rpc())?;
525
526 io.merge(Web3::new(client.clone()).into_rpc())?;
527
528 io.merge(
529 EthPubSub::new(
530 pool,
531 client.clone(),
532 sync,
533 subscription_task_executor,
534 storage_override,
535 pubsub_notification_sinks,
536 )
537 .into_rpc(),
538 )?;
539
540 Ok(io)
541}