use std::sync::Arc;
use clap::Parser;
#[derive(PartialEq, Clone, Debug)]
pub enum EthApi {
Debug,
Trace,
TxPool,
}
impl std::str::FromStr for EthApi {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"debug" => Ok(EthApi::Debug),
"trace" => Ok(EthApi::Trace),
"txpool" => Ok(EthApi::TxPool),
_ => Err(format!("Invalid EthApi: {}", s))
}
}
}
#[derive(PartialEq, Clone, Debug, Copy, clap::ValueEnum, Default)]
pub enum FrontierBackendType {
#[default]
KeyValue,
Sql
}
#[derive(Clone)]
pub struct EvmTracingConfig {
pub ethapi: Vec<EthApi>,
pub ethapi_max_permits: u32,
pub ethapi_trace_max_count: u32,
pub ethapi_trace_cache_duration: u64,
pub eth_log_block_cache: usize,
pub eth_statuses_cache: usize,
pub max_past_logs: u32,
pub tracing_raw_max_memory_usage: usize,
pub fee_history_limit: u64,
pub frontier_backend_type: FrontierBackendType,
pub frontier_sql_backend_pool_size: u32,
pub frontier_sql_backend_num_ops_timeout: u32,
pub frontier_sql_backend_thread_count: u32,
pub frontier_sql_backend_cache_size: u64,
}
impl EthApiOptions {
pub fn build_evm_tracing_config(&self) -> EvmTracingConfig {
EvmTracingConfig {
ethapi: self.ethapi.clone(),
ethapi_max_permits: self.ethapi_max_permits,
ethapi_trace_max_count: self.ethapi_trace_max_count,
ethapi_trace_cache_duration: self.ethapi_trace_cache_duration,
eth_log_block_cache: self.eth_log_block_cache,
eth_statuses_cache: self.eth_statuses_cache,
max_past_logs: self.max_past_logs,
fee_history_limit: self.fee_history_limit,
tracing_raw_max_memory_usage: self.tracing_raw_max_memory_usage,
frontier_backend_type: self.frontier_backend_type,
frontier_sql_backend_pool_size: self.frontier_sql_backend_pool_size,
frontier_sql_backend_num_ops_timeout: self.frontier_sql_backend_num_ops_timeout,
frontier_sql_backend_thread_count: self.frontier_sql_backend_thread_count,
frontier_sql_backend_cache_size: self.frontier_sql_backend_cache_size,
}
}
}
#[derive(Debug, Parser)]
pub struct EthApiOptions {
#[clap(
long,
conflicts_with = "validator",
value_delimiter = ','
)]
pub ethapi: Vec<EthApi>,
#[clap(long, default_value = "10")]
pub ethapi_max_permits: u32,
#[clap(long, default_value = "500")]
pub ethapi_trace_max_count: u32,
#[clap(long, default_value = "300")]
pub ethapi_trace_cache_duration: u64,
#[clap(long, value_enum, ignore_case = true, default_value_t = FrontierBackendType::default())]
pub frontier_backend_type: FrontierBackendType,
#[clap(long, default_value = "300000000")]
pub eth_log_block_cache: usize,
#[clap(long, default_value = "300000000")]
pub eth_statuses_cache: usize,
#[clap(long, default_value = "20000000")]
pub tracing_raw_max_memory_usage: usize,
#[clap(long, default_value = "10000")]
pub max_past_logs: u32,
#[arg(long, default_value = "2048")]
pub fee_history_limit: u64,
#[arg(long, default_value = "100")]
pub frontier_sql_backend_pool_size: u32,
#[arg(long, default_value = "10000000")]
pub frontier_sql_backend_num_ops_timeout: u32,
#[arg(long, default_value = "4")]
pub frontier_sql_backend_thread_count: u32,
#[arg(long, default_value = "209715200")]
pub frontier_sql_backend_cache_size: u64,
}
pub(crate) fn db_config_dir(config: &sc_service::Configuration) -> std::path::PathBuf {
config.base_path.config_dir(config.chain_spec.id())
}
pub(crate) fn frontier_backend<B, C, BE>(
config: &sc_service::Configuration,
client: Arc<C>,
eth_api_options: EvmTracingConfig,
) -> Result<fc_db::Backend<B>, String>
where
B: sp_runtime::traits::Block<Hash=sp_core::H256> + 'static,
BE: sc_client_api::Backend<B> + 'static,
C: sc_client_api::StorageProvider<B, BE> + Sync + Send + 'static
+ sp_api::ProvideRuntimeApi<B>
+ sc_client_api::HeaderBackend<B>,
C::Api: fp_rpc::EthereumRuntimeRPCApi<B>,
{
let db_config_dir = db_config_dir(config);
let overrides_handle = fc_storage::overrides_handle(client.clone());
match eth_api_options.frontier_backend_type {
FrontierBackendType::KeyValue => {
let db = fc_db::kv::Backend::open(
client, &config.database, &db_config_dir)?;
Ok(fc_db::Backend::<B>::KeyValue(db))
},
FrontierBackendType::Sql => {
let db_path = db_config_dir.join("sql");
std::fs::create_dir_all(&db_path).expect("failed creating sql db directory");
let backend = futures::executor::block_on(fc_db::sql::Backend::new(
fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig {
path: std::path::Path::new("sqlite:///")
.join(db_path)
.join("frontier.db3")
.to_str()
.unwrap(),
create_if_missing: true,
thread_count: eth_api_options.frontier_sql_backend_thread_count,
cache_size: eth_api_options.frontier_sql_backend_cache_size,
}),
eth_api_options.frontier_sql_backend_pool_size,
std::num::NonZeroU32::new(eth_api_options.frontier_sql_backend_num_ops_timeout),
overrides_handle,
))
.unwrap_or_else(|err| panic!("failed creating sql backend: {:?}", err));
Ok(fc_db::Backend::<B>::Sql(backend))
}
}
}