mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
259 lines
8.7 KiB
Rust
259 lines
8.7 KiB
Rust
// Copyright 2025 DataHaven
|
|
// This file is part of DataHaven.
|
|
|
|
// DataHaven is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// DataHaven is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with DataHaven. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
// Substrate
|
|
use crate::client::{FullBackend, FullClient};
|
|
use datahaven_runtime_common::Block;
|
|
pub use fc_db::Backend as FrontierBackend;
|
|
use fc_rpc::EthConfig;
|
|
use fc_rpc::EthTask;
|
|
pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool};
|
|
pub use fc_storage::{StorageOverride, StorageOverrideHandler};
|
|
use fp_rpc::EthereumRuntimeRPCApi;
|
|
use futures::{future, prelude::*};
|
|
use sc_client_api::{Backend, BlockchainEvents, StorageProvider};
|
|
use sc_executor::HostFunctions;
|
|
use sc_network_sync::SyncingService;
|
|
use sc_service::{error::Error as ServiceError, TaskManager};
|
|
use sp_api::ConstructRuntimeApi;
|
|
use sp_core::H256;
|
|
use sp_runtime::traits::Block as BlockT;
|
|
use std::{
|
|
collections::BTreeMap,
|
|
sync::{Arc, Mutex},
|
|
time::Duration,
|
|
};
|
|
|
|
/// Frontier DB backend type.
|
|
pub struct DefaultEthConfig<C, BE>(std::marker::PhantomData<(C, BE)>);
|
|
|
|
impl<C, BE> EthConfig<Block, C> for DefaultEthConfig<C, BE>
|
|
where
|
|
C: StorageProvider<Block, BE> + Sync + Send + 'static,
|
|
BE: Backend<Block> + 'static,
|
|
{
|
|
type EstimateGasAdapter = ();
|
|
type RuntimeStorageOverride =
|
|
fc_rpc::frontier_backend_client::SystemAccountId20StorageOverride<Block, C, BE>;
|
|
}
|
|
|
|
/// Available frontier backend types.
|
|
#[derive(Debug, Copy, Clone, Default, clap::ValueEnum)]
|
|
pub enum BackendType {
|
|
/// Either RocksDb or ParityDb as per inherited from the global backend settings.
|
|
#[default]
|
|
KeyValue,
|
|
/// Sql database with custom log indexing.
|
|
Sql,
|
|
}
|
|
|
|
/// The ethereum-compatibility configuration used to run a node.
|
|
#[derive(Clone, Debug, clap::Parser)]
|
|
pub struct EthConfiguration {
|
|
/// Maximum number of logs in a query.
|
|
#[arg(long, default_value = "10000")]
|
|
pub max_past_logs: u32,
|
|
|
|
/// Maximum fee history cache size.
|
|
#[arg(long, default_value = "2048")]
|
|
pub fee_history_limit: u64,
|
|
|
|
#[arg(long)]
|
|
pub enable_dev_signer: bool,
|
|
|
|
/// The dynamic-fee pallet target gas price set by block author
|
|
#[arg(long, default_value = "1")]
|
|
pub target_gas_price: u64,
|
|
|
|
/// Maximum allowed gas limit will be `block.gas_limit * execute_gas_limit_multiplier`
|
|
/// when using eth_call/eth_estimateGas.
|
|
#[arg(long, default_value = "10")]
|
|
pub execute_gas_limit_multiplier: u64,
|
|
|
|
/// Size in bytes of the LRU cache for block data.
|
|
#[arg(long, default_value = "50")]
|
|
pub eth_log_block_cache: usize,
|
|
|
|
/// Size in bytes of the LRU cache for transactions statuses data.
|
|
#[arg(long, default_value = "50")]
|
|
pub eth_statuses_cache: usize,
|
|
|
|
/// Sets the frontier backend type (KeyValue or Sql)
|
|
#[arg(long, value_enum, ignore_case = true, default_value_t = BackendType::default())]
|
|
pub frontier_backend_type: BackendType,
|
|
|
|
// Sets the SQL backend's pool size.
|
|
#[arg(long, default_value = "100")]
|
|
pub frontier_sql_backend_pool_size: u32,
|
|
|
|
/// Sets the SQL backend's query timeout in number of VM ops.
|
|
#[arg(long, default_value = "10000000")]
|
|
pub frontier_sql_backend_num_ops_timeout: u32,
|
|
|
|
/// Sets the SQL backend's auxiliary thread limit.
|
|
#[arg(long, default_value = "4")]
|
|
pub frontier_sql_backend_thread_count: u32,
|
|
|
|
/// Sets the SQL backend's query timeout in number of VM ops.
|
|
/// Default value is 200MB.
|
|
#[arg(long, default_value = "209715200")]
|
|
pub frontier_sql_backend_cache_size: u64,
|
|
}
|
|
|
|
pub struct FrontierPartialComponents {
|
|
pub filter_pool: Option<FilterPool>,
|
|
pub fee_history_cache: FeeHistoryCache,
|
|
pub fee_history_cache_limit: FeeHistoryCacheLimit,
|
|
}
|
|
|
|
pub fn new_frontier_partial(
|
|
config: &EthConfiguration,
|
|
) -> Result<FrontierPartialComponents, ServiceError> {
|
|
Ok(FrontierPartialComponents {
|
|
filter_pool: Some(Arc::new(Mutex::new(BTreeMap::new()))),
|
|
fee_history_cache: Arc::new(Mutex::new(BTreeMap::new())),
|
|
fee_history_cache_limit: config.fee_history_limit,
|
|
})
|
|
}
|
|
|
|
/// A set of APIs that ethereum-compatible runtimes must implement.
|
|
pub trait EthCompatRuntimeApiCollection<Block: BlockT>:
|
|
sp_api::ApiExt<Block> + fp_rpc::ConvertTransactionRuntimeApi<Block> + EthereumRuntimeRPCApi<Block>
|
|
{
|
|
}
|
|
|
|
impl<Block, Api> EthCompatRuntimeApiCollection<Block> for Api
|
|
where
|
|
Block: BlockT,
|
|
Api: sp_api::ApiExt<Block>
|
|
+ fp_rpc::ConvertTransactionRuntimeApi<Block>
|
|
+ EthereumRuntimeRPCApi<Block>,
|
|
{
|
|
}
|
|
|
|
pub struct FrontierTasksParams<B, RA, HF>
|
|
where
|
|
B: BlockT<Hash = H256>,
|
|
RA: ConstructRuntimeApi<B, FullClient<B, RA, HF>>,
|
|
RA: Send + Sync + 'static,
|
|
RA::RuntimeApi: EthCompatRuntimeApiCollection<B>,
|
|
HF: HostFunctions + 'static,
|
|
{
|
|
pub client: Arc<FullClient<B, RA, HF>>,
|
|
pub backend: Arc<FullBackend<B>>,
|
|
pub frontier_backend: Arc<FrontierBackend<B, FullClient<B, RA, HF>>>,
|
|
pub frontier_partial_components: FrontierPartialComponents,
|
|
pub storage_override: Arc<dyn StorageOverride<B>>,
|
|
pub sync: Arc<SyncingService<B>>,
|
|
pub pubsub_notification_sinks: Arc<
|
|
fc_mapping_sync::EthereumBlockNotificationSinks<
|
|
fc_mapping_sync::EthereumBlockNotification<B>,
|
|
>,
|
|
>,
|
|
}
|
|
|
|
pub async fn spawn_frontier_tasks<B, RA, HF>(
|
|
task_manager: &TaskManager,
|
|
params: FrontierTasksParams<B, RA, HF>,
|
|
) where
|
|
B: BlockT<Hash = H256>,
|
|
RA: ConstructRuntimeApi<B, FullClient<B, RA, HF>>,
|
|
RA: Send + Sync + 'static,
|
|
RA::RuntimeApi: EthCompatRuntimeApiCollection<B>,
|
|
HF: HostFunctions + 'static,
|
|
{
|
|
let FrontierTasksParams {
|
|
client,
|
|
backend,
|
|
frontier_backend,
|
|
frontier_partial_components,
|
|
storage_override,
|
|
sync,
|
|
pubsub_notification_sinks,
|
|
} = params;
|
|
|
|
let FrontierPartialComponents {
|
|
filter_pool,
|
|
fee_history_cache,
|
|
fee_history_cache_limit,
|
|
} = frontier_partial_components;
|
|
|
|
// Spawn main mapping sync worker background task.
|
|
match &*frontier_backend {
|
|
fc_db::Backend::KeyValue(b) => {
|
|
task_manager.spawn_essential_handle().spawn(
|
|
"frontier-mapping-sync-worker",
|
|
Some("frontier"),
|
|
fc_mapping_sync::kv::MappingSyncWorker::new(
|
|
client.import_notification_stream(),
|
|
Duration::new(6, 0),
|
|
client.clone(),
|
|
backend,
|
|
storage_override.clone(),
|
|
b.clone(),
|
|
3,
|
|
0u32.into(),
|
|
fc_mapping_sync::SyncStrategy::Normal,
|
|
sync,
|
|
pubsub_notification_sinks,
|
|
)
|
|
.for_each(|()| future::ready(())),
|
|
);
|
|
}
|
|
fc_db::Backend::Sql(b) => {
|
|
task_manager.spawn_essential_handle().spawn_blocking(
|
|
"frontier-mapping-sync-worker",
|
|
Some("frontier"),
|
|
fc_mapping_sync::sql::SyncWorker::run(
|
|
client.clone(),
|
|
backend,
|
|
b.clone(),
|
|
client.import_notification_stream(),
|
|
fc_mapping_sync::sql::SyncWorkerConfig {
|
|
read_notification_timeout: Duration::from_secs(30),
|
|
check_indexed_blocks_interval: Duration::from_secs(60),
|
|
},
|
|
fc_mapping_sync::SyncStrategy::Parachain,
|
|
sync,
|
|
pubsub_notification_sinks,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// Spawn Frontier EthFilterApi maintenance task.
|
|
if let Some(filter_pool) = filter_pool {
|
|
// Each filter is allowed to stay in the pool for 100 blocks.
|
|
const FILTER_RETAIN_THRESHOLD: u64 = 100;
|
|
task_manager.spawn_essential_handle().spawn(
|
|
"frontier-filter-pool",
|
|
Some("frontier"),
|
|
EthTask::filter_pool_task(client.clone(), filter_pool, FILTER_RETAIN_THRESHOLD),
|
|
);
|
|
}
|
|
|
|
// Spawn Frontier FeeHistory cache maintenance task.
|
|
task_manager.spawn_essential_handle().spawn(
|
|
"frontier-fee-history",
|
|
Some("frontier"),
|
|
EthTask::fee_history_task(
|
|
client,
|
|
storage_override,
|
|
fee_history_cache,
|
|
fee_history_cache_limit,
|
|
),
|
|
);
|
|
}
|