use crate::evm_tracing_types::{EthApi as EthApiCmd, EvmTracingConfig};
use fc_rpc_core::types::FilterPool;
use fc_storage::StorageOverride;
use fp_rpc::EthereumRuntimeRPCApi;
use moonbeam_rpc_debug::{DebugHandler, DebugRequester};
use moonbeam_rpc_trace::{CacheRequester as TraceFilterCacheRequester, CacheTask};
use sc_client_api::{
Backend, BlockOf, BlockchainEvents, HeaderBackend, StateBackend, StorageProvider,
};
use sc_service::TaskManager;
use sp_api::ProvideRuntimeApi;
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as BlockChainError, HeaderMetadata};
use sp_core::H256;
use sp_runtime::traits::{BlakeTwo256, Block as BlockT, Header as HeaderT};
use std::sync::Arc;
use substrate_prometheus_endpoint::Registry as PrometheusRegistry;
use tokio::sync::Semaphore;
#[derive(Clone)]
pub struct RpcRequesters {
pub debug: Option<DebugRequester>,
pub trace: Option<TraceFilterCacheRequester>,
}
pub struct SpawnTasksParams<'a, B: BlockT, C, BE> {
pub task_manager: &'a TaskManager,
pub client: Arc<C>,
pub substrate_backend: Arc<BE>,
pub frontier_backend: Arc<dyn fc_api::Backend<B> + Send + Sync>,
pub filter_pool: Option<FilterPool>,
pub storage_override: Arc<dyn StorageOverride<B>>,
}
pub fn spawn_tracing_tasks<B, C, BE>(
rpc_config: &EvmTracingConfig,
prometheus: Option<PrometheusRegistry>,
params: SpawnTasksParams<B, C, BE>,
) -> RpcRequesters
where
C: ProvideRuntimeApi<B> + BlockOf,
C: StorageProvider<B, BE>,
C: HeaderBackend<B> + HeaderMetadata<B, Error = BlockChainError> + 'static,
C: BlockchainEvents<B>,
C: Send + Sync + 'static,
C::Api: EthereumRuntimeRPCApi<B> + moonbeam_rpc_primitives_debug::DebugRuntimeApi<B>,
C::Api: BlockBuilder<B>,
B: BlockT<Hash = H256> + Send + Sync + 'static,
B::Header: HeaderT<Number = u32>,
BE: Backend<B> + 'static,
BE::State: StateBackend<BlakeTwo256>,
{
let permit_pool = Arc::new(Semaphore::new(rpc_config.ethapi_max_permits as usize));
let (trace_filter_task, trace_filter_requester) =
if rpc_config.ethapi.contains(&EthApiCmd::Trace) {
let (trace_filter_task, trace_filter_requester) = CacheTask::create(
Arc::clone(¶ms.client),
Arc::clone(¶ms.substrate_backend),
core::time::Duration::from_secs(rpc_config.ethapi_trace_cache_duration),
Arc::clone(&permit_pool),
Arc::clone(¶ms.storage_override),
prometheus,
);
(Some(trace_filter_task), Some(trace_filter_requester))
} else {
(None, None)
};
let (debug_task, debug_requester) = if rpc_config.ethapi.contains(&EthApiCmd::Debug) {
let (debug_task, debug_requester) = DebugHandler::task(
Arc::clone(¶ms.client),
Arc::clone(¶ms.substrate_backend),
Arc::clone(¶ms.frontier_backend),
Arc::clone(&permit_pool),
Arc::clone(¶ms.storage_override),
rpc_config.tracing_raw_max_memory_usage,
);
(Some(debug_task), Some(debug_requester))
} else {
(None, None)
};
if let Some(trace_filter_task) = trace_filter_task {
params.task_manager.spawn_essential_handle().spawn(
"trace-filter-cache",
Some("eth-tracing"),
trace_filter_task,
);
}
if let Some(debug_task) = debug_task {
params.task_manager.spawn_essential_handle().spawn(
"ethapi-debug",
Some("eth-tracing"),
debug_task,
);
}
RpcRequesters {
debug: debug_requester,
trace: trace_filter_requester,
}
}