mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: introduce ProviderFactoryBuilder (#13989)
This commit is contained in:
@ -22,7 +22,7 @@ use reth_node_builder::{
|
|||||||
BuilderContext, Node, NodeAdapter, NodeComponentsBuilder, PayloadTypes,
|
BuilderContext, Node, NodeAdapter, NodeComponentsBuilder, PayloadTypes,
|
||||||
};
|
};
|
||||||
use reth_primitives::{EthPrimitives, PooledTransaction};
|
use reth_primitives::{EthPrimitives, PooledTransaction};
|
||||||
use reth_provider::{CanonStateSubscriptions, EthStorage};
|
use reth_provider::{providers::ProviderFactoryBuilder, CanonStateSubscriptions, EthStorage};
|
||||||
use reth_rpc::EthApi;
|
use reth_rpc::EthApi;
|
||||||
use reth_tracing::tracing::{debug, info};
|
use reth_tracing::tracing::{debug, info};
|
||||||
use reth_transaction_pool::{
|
use reth_transaction_pool::{
|
||||||
@ -63,6 +63,41 @@ impl EthereumNode {
|
|||||||
.executor(EthereumExecutorBuilder::default())
|
.executor(EthereumExecutorBuilder::default())
|
||||||
.consensus(EthereumConsensusBuilder::default())
|
.consensus(EthereumConsensusBuilder::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Instantiates the [`ProviderFactoryBuilder`] for an ethereum node.
|
||||||
|
///
|
||||||
|
/// # Open a Providerfactory in read-only mode from a datadir
|
||||||
|
///
|
||||||
|
/// See also: [`ProviderFactoryBuilder`] and
|
||||||
|
/// [`ReadOnlyConfig`](reth_provider::providers::ReadOnlyConfig).
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use reth_chainspec::MAINNET;
|
||||||
|
/// use reth_node_ethereum::EthereumNode;
|
||||||
|
///
|
||||||
|
/// let factory = EthereumNode::provider_factory_builder()
|
||||||
|
/// .open_read_only(MAINNET.clone(), "datadir")
|
||||||
|
/// .unwrap();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Open a Providerfactory manually with with all required componets
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use reth_chainspec::ChainSpecBuilder;
|
||||||
|
/// use reth_db::open_db_read_only;
|
||||||
|
/// use reth_node_ethereum::EthereumNode;
|
||||||
|
/// use reth_provider::providers::StaticFileProvider;
|
||||||
|
/// use std::{path::Path, sync::Arc};
|
||||||
|
///
|
||||||
|
/// let factory = EthereumNode::provider_factory_builder()
|
||||||
|
/// .db(Arc::new(open_db_read_only(Path::new("db"), Default::default()).unwrap()))
|
||||||
|
/// .chainspec(ChainSpecBuilder::mainnet().build().into())
|
||||||
|
/// .static_file(StaticFileProvider::read_only("db/static_files", false).unwrap())
|
||||||
|
/// .build_provider_factory();
|
||||||
|
/// ```
|
||||||
|
pub fn provider_factory_builder() -> ProviderFactoryBuilder<Self> {
|
||||||
|
ProviderFactoryBuilder::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeTypes for EthereumNode {
|
impl NodeTypes for EthereumNode {
|
||||||
|
|||||||
@ -58,6 +58,7 @@ notify = { workspace = true, default-features = false, features = ["macos_fseven
|
|||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
dashmap = { workspace = true, features = ["inline"] }
|
dashmap = { workspace = true, features = ["inline"] }
|
||||||
strum.workspace = true
|
strum.workspace = true
|
||||||
|
eyre.workspace = true
|
||||||
|
|
||||||
# test-utils
|
# test-utils
|
||||||
reth-ethereum-engine-primitives = { workspace = true, optional = true }
|
reth-ethereum-engine-primitives = { workspace = true, optional = true }
|
||||||
|
|||||||
280
crates/storage/provider/src/providers/database/builder.rs
Normal file
280
crates/storage/provider/src/providers/database/builder.rs
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
//! Helper builder entrypoint to instantiate a [`ProviderFactory`].
|
||||||
|
//!
|
||||||
|
//! This also includes general purpose staging types that provide builder style functions that lead
|
||||||
|
//! up to the intended build target.
|
||||||
|
|
||||||
|
use crate::{providers::StaticFileProvider, ProviderFactory};
|
||||||
|
use reth_db::{mdbx::DatabaseArguments, open_db_read_only, DatabaseEnv};
|
||||||
|
use reth_db_api::{database_metrics::DatabaseMetrics, Database};
|
||||||
|
use reth_node_types::{NodeTypes, NodeTypesWithDBAdapter};
|
||||||
|
use std::{
|
||||||
|
marker::PhantomData,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Helper type to create a [`ProviderFactory`].
|
||||||
|
///
|
||||||
|
/// This type is the entry point for a stage based builder.
|
||||||
|
///
|
||||||
|
/// The intended staging is:
|
||||||
|
/// 1. Configure the database: [`ProviderFactoryBuilder::db`]
|
||||||
|
/// 2. Configure the chainspec: `chainspec`
|
||||||
|
/// 3. Configure the [`StaticFileProvider`]: `static_file`
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ProviderFactoryBuilder<N> {
|
||||||
|
_types: PhantomData<N>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N> ProviderFactoryBuilder<N> {
|
||||||
|
/// Maps the [`NodeTypes`] of this builder.
|
||||||
|
pub fn types<T>(self) -> ProviderFactoryBuilder<T> {
|
||||||
|
ProviderFactoryBuilder::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the database.
|
||||||
|
pub fn db<DB>(self, db: DB) -> TypesAnd1<N, DB> {
|
||||||
|
TypesAnd1::new(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Opens the database with the given chainspec and [`ReadOnlyConfig`].
|
||||||
|
///
|
||||||
|
/// # Open a monitored instance
|
||||||
|
///
|
||||||
|
/// This is recommended when the new read-only instance is used with an active node.
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use reth_chainspec::MAINNET;
|
||||||
|
/// use reth_node_types::NodeTypes;
|
||||||
|
/// use reth_provider::providers::ProviderFactoryBuilder;
|
||||||
|
///
|
||||||
|
/// fn demo<N: NodeTypes<ChainSpec = reth_chainspec::ChainSpec>>() {
|
||||||
|
/// let provider_factory = ProviderFactoryBuilder::<N>::default()
|
||||||
|
/// .open_read_only(MAINNET.clone(), "datadir")
|
||||||
|
/// .unwrap();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Open an unmonitored instace
|
||||||
|
///
|
||||||
|
/// This is recommended when no changes to the static files are expected (e.g. no active node)
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use reth_chainspec::MAINNET;
|
||||||
|
/// use reth_node_types::NodeTypes;
|
||||||
|
/// ///
|
||||||
|
/// use reth_provider::providers::{ProviderFactoryBuilder, ReadOnlyConfig};
|
||||||
|
///
|
||||||
|
/// fn demo<N: NodeTypes<ChainSpec = reth_chainspec::ChainSpec>>() {
|
||||||
|
/// let provider_factory = ProviderFactoryBuilder::<N>::default()
|
||||||
|
/// .open_read_only(MAINNET.clone(), ReadOnlyConfig::from_datadir("datadir").no_watch())
|
||||||
|
/// .unwrap();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn open_read_only(
|
||||||
|
self,
|
||||||
|
chainspec: Arc<N::ChainSpec>,
|
||||||
|
config: impl Into<ReadOnlyConfig>,
|
||||||
|
) -> eyre::Result<ProviderFactory<NodeTypesWithDBAdapter<N, Arc<DatabaseEnv>>>>
|
||||||
|
where
|
||||||
|
N: NodeTypes,
|
||||||
|
{
|
||||||
|
let ReadOnlyConfig { db_dir, db_args, static_files_dir, watch_static_files } =
|
||||||
|
config.into();
|
||||||
|
Ok(self
|
||||||
|
.db(Arc::new(open_db_read_only(db_dir, db_args)?))
|
||||||
|
.chainspec(chainspec)
|
||||||
|
.static_file(StaticFileProvider::read_only(static_files_dir, watch_static_files)?)
|
||||||
|
.build_provider_factory())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N> Default for ProviderFactoryBuilder<N> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { _types: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Settings for how to open the database and static files.
|
||||||
|
///
|
||||||
|
/// The default derivation from a path assumes the path is the datadir:
|
||||||
|
/// [`ReadOnlyConfig::from_datadir`]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ReadOnlyConfig {
|
||||||
|
/// The path to the database directory.
|
||||||
|
pub db_dir: PathBuf,
|
||||||
|
/// How to open the database
|
||||||
|
pub db_args: DatabaseArguments,
|
||||||
|
/// The path to the static file dir
|
||||||
|
pub static_files_dir: PathBuf,
|
||||||
|
/// Whether the static files should be watched for changes.
|
||||||
|
pub watch_static_files: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadOnlyConfig {
|
||||||
|
/// Derives the [`ReadOnlyConfig`] from the datadir.
|
||||||
|
///
|
||||||
|
/// By default this assumes the following datadir layour:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// -`datadir`
|
||||||
|
/// |__db
|
||||||
|
/// |__static_files
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// By default this watches the static file directory for changes, see also
|
||||||
|
/// [`StaticFileProvider::read_only`]
|
||||||
|
pub fn from_datadir(datadir: impl AsRef<Path>) -> Self {
|
||||||
|
let datadir = datadir.as_ref();
|
||||||
|
let db_path = datadir.join("db");
|
||||||
|
Self::from_db_dir(db_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the [`ReadOnlyConfig`] from the database dir.
|
||||||
|
///
|
||||||
|
/// By default this assumes the following datadir layour:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// - db
|
||||||
|
/// |__static_files
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// By default this watches the static file directory for changes, see also
|
||||||
|
/// [`StaticFileProvider::read_only`]
|
||||||
|
pub fn from_db_dir(db_dir: impl AsRef<Path>) -> Self {
|
||||||
|
let db_dir = db_dir.as_ref();
|
||||||
|
Self {
|
||||||
|
static_files_dir: db_dir.join("static_files"),
|
||||||
|
db_dir: db_dir.into(),
|
||||||
|
db_args: Default::default(),
|
||||||
|
watch_static_files: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the db arguments used when opening the database.
|
||||||
|
pub fn with_db_args(mut self, db_args: impl Into<DatabaseArguments>) -> Self {
|
||||||
|
self.db_args = db_args.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the db directory.
|
||||||
|
pub fn with_db_dir(mut self, db_dir: impl Into<PathBuf>) -> Self {
|
||||||
|
self.db_dir = db_dir.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the static file directory.
|
||||||
|
pub fn with_static_file_dir(mut self, static_file_dir: impl Into<PathBuf>) -> Self {
|
||||||
|
self.static_files_dir = static_file_dir.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the static file directory should be watches for changes, see also
|
||||||
|
/// [`StaticFileProvider::read_only`]
|
||||||
|
pub fn set_watch_static_files(&mut self, watch_static_files: bool) {
|
||||||
|
self.watch_static_files = watch_static_files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Don't watch the static files for changes.
|
||||||
|
///
|
||||||
|
/// This is only recommended if this is used without a running node instance that modifies
|
||||||
|
/// static files.
|
||||||
|
pub fn no_watch(mut self) -> Self {
|
||||||
|
self.set_watch_static_files(false);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for ReadOnlyConfig
|
||||||
|
where
|
||||||
|
T: AsRef<Path>,
|
||||||
|
{
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
Self::from_datadir(value.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is staging type that contains the configured types and _one_ value.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TypesAnd1<N, Val1> {
|
||||||
|
_types: PhantomData<N>,
|
||||||
|
val_1: Val1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, Val1> TypesAnd1<N, Val1> {
|
||||||
|
/// Creates a new instance with the given types and one value.
|
||||||
|
pub fn new(val_1: Val1) -> Self {
|
||||||
|
Self { _types: Default::default(), val_1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the chainspec.
|
||||||
|
pub fn chainspec<C>(self, chainspec: Arc<C>) -> TypesAnd2<N, Val1, Arc<C>> {
|
||||||
|
TypesAnd2::new(self.val_1, chainspec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is staging type that contains the configured types and _two_ values.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TypesAnd2<N, Val1, Val2> {
|
||||||
|
_types: PhantomData<N>,
|
||||||
|
val_1: Val1,
|
||||||
|
val_2: Val2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, Val1, Val2> TypesAnd2<N, Val1, Val2> {
|
||||||
|
/// Creates a new instance with the given types and two values.
|
||||||
|
pub fn new(val_1: Val1, val_2: Val2) -> Self {
|
||||||
|
Self { _types: Default::default(), val_1, val_2 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the first value.
|
||||||
|
pub const fn val_1(&self) -> &Val1 {
|
||||||
|
&self.val_1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the second value.
|
||||||
|
pub const fn val_2(&self) -> &Val2 {
|
||||||
|
&self.val_2
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the [`StaticFileProvider`].
|
||||||
|
pub fn static_file(
|
||||||
|
self,
|
||||||
|
static_file_provider: StaticFileProvider<N::Primitives>,
|
||||||
|
) -> TypesAnd3<N, Val1, Val2, StaticFileProvider<N::Primitives>>
|
||||||
|
where
|
||||||
|
N: NodeTypes,
|
||||||
|
{
|
||||||
|
TypesAnd3::new(self.val_1, self.val_2, static_file_provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add helper fns for opening static file provider
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is staging type that contains the configured types and _three_ values.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TypesAnd3<N, Val1, Val2, Val3> {
|
||||||
|
_types: PhantomData<N>,
|
||||||
|
val_1: Val1,
|
||||||
|
val_2: Val2,
|
||||||
|
val_3: Val3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, Val1, Val2, Val3> TypesAnd3<N, Val1, Val2, Val3> {
|
||||||
|
/// Creates a new instance with the given types and three values.
|
||||||
|
pub fn new(val_1: Val1, val_2: Val2, val_3: Val3) -> Self {
|
||||||
|
Self { _types: Default::default(), val_1, val_2, val_3 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, DB> TypesAnd3<N, DB, Arc<N::ChainSpec>, StaticFileProvider<N::Primitives>>
|
||||||
|
where
|
||||||
|
N: NodeTypes,
|
||||||
|
DB: Database + DatabaseMetrics + Clone + Unpin + 'static,
|
||||||
|
{
|
||||||
|
/// Creates the [`ProviderFactory`].
|
||||||
|
pub fn build_provider_factory(self) -> ProviderFactory<NodeTypesWithDBAdapter<N, DB>> {
|
||||||
|
let Self { _types, val_1, val_2, val_3 } = self;
|
||||||
|
ProviderFactory::new(val_1, val_2, val_3)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,7 +15,9 @@ use reth_chainspec::{ChainInfo, EthereumHardforks};
|
|||||||
use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv};
|
use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv};
|
||||||
use reth_db_api::{database::Database, models::StoredBlockBodyIndices};
|
use reth_db_api::{database::Database, models::StoredBlockBodyIndices};
|
||||||
use reth_errors::{RethError, RethResult};
|
use reth_errors::{RethError, RethResult};
|
||||||
use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
|
use reth_node_types::{
|
||||||
|
BlockTy, HeaderTy, NodeTypes, NodeTypesWithDB, NodeTypesWithDBAdapter, ReceiptTy, TxTy,
|
||||||
|
};
|
||||||
use reth_primitives::{RecoveredBlock, SealedBlock, SealedHeader, StaticFileSegment};
|
use reth_primitives::{RecoveredBlock, SealedBlock, SealedHeader, StaticFileSegment};
|
||||||
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
|
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
|
||||||
use reth_stages_types::{StageCheckpoint, StageId};
|
use reth_stages_types::{StageCheckpoint, StageId};
|
||||||
@ -40,6 +42,9 @@ pub use provider::{DatabaseProvider, DatabaseProviderRO, DatabaseProviderRW};
|
|||||||
|
|
||||||
use super::ProviderNodeTypes;
|
use super::ProviderNodeTypes;
|
||||||
|
|
||||||
|
mod builder;
|
||||||
|
pub use builder::{ProviderFactoryBuilder, ReadOnlyConfig};
|
||||||
|
|
||||||
mod metrics;
|
mod metrics;
|
||||||
|
|
||||||
mod chain;
|
mod chain;
|
||||||
@ -49,7 +54,7 @@ pub use chain::*;
|
|||||||
///
|
///
|
||||||
/// This provider implements most provider or provider factory traits.
|
/// This provider implements most provider or provider factory traits.
|
||||||
pub struct ProviderFactory<N: NodeTypesWithDB> {
|
pub struct ProviderFactory<N: NodeTypesWithDB> {
|
||||||
/// Database
|
/// Database instance
|
||||||
db: N::DB,
|
db: N::DB,
|
||||||
/// Chain spec
|
/// Chain spec
|
||||||
chain_spec: Arc<N::ChainSpec>,
|
chain_spec: Arc<N::ChainSpec>,
|
||||||
@ -61,19 +66,10 @@ pub struct ProviderFactory<N: NodeTypesWithDB> {
|
|||||||
storage: Arc<N::Storage>,
|
storage: Arc<N::Storage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N> fmt::Debug for ProviderFactory<N>
|
impl<N: NodeTypes> ProviderFactory<NodeTypesWithDBAdapter<N, Arc<DatabaseEnv>>> {
|
||||||
where
|
/// Instantiates the builder for this type
|
||||||
N: NodeTypesWithDB<DB: fmt::Debug, ChainSpec: fmt::Debug, Storage: fmt::Debug>,
|
pub fn builder() -> ProviderFactoryBuilder<N> {
|
||||||
{
|
ProviderFactoryBuilder::default()
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let Self { db, chain_spec, static_file_provider, prune_modes, storage } = self;
|
|
||||||
f.debug_struct("ProviderFactory")
|
|
||||||
.field("db", &db)
|
|
||||||
.field("chain_spec", &chain_spec)
|
|
||||||
.field("static_file_provider", &static_file_provider)
|
|
||||||
.field("prune_modes", &prune_modes)
|
|
||||||
.field("storage", &storage)
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,6 +626,22 @@ impl<N: ProviderNodeTypes> HashedPostStateProvider for ProviderFactory<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N> fmt::Debug for ProviderFactory<N>
|
||||||
|
where
|
||||||
|
N: NodeTypesWithDB<DB: fmt::Debug, ChainSpec: fmt::Debug, Storage: fmt::Debug>,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let Self { db, chain_spec, static_file_provider, prune_modes, storage } = self;
|
||||||
|
f.debug_struct("ProviderFactory")
|
||||||
|
.field("db", &db)
|
||||||
|
.field("chain_spec", &chain_spec)
|
||||||
|
.field("static_file_provider", &static_file_provider)
|
||||||
|
.field("prune_modes", &prune_modes)
|
||||||
|
.field("storage", &storage)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: NodeTypesWithDB> Clone for ProviderFactory<N> {
|
impl<N: NodeTypesWithDB> Clone for ProviderFactory<N> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
@ -79,6 +79,13 @@ impl StaticFileAccess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// [`StaticFileProvider`] manages all existing [`StaticFileJarProvider`].
|
/// [`StaticFileProvider`] manages all existing [`StaticFileJarProvider`].
|
||||||
|
///
|
||||||
|
/// "Static files" contain immutable chain history data, such as:
|
||||||
|
/// - transactions
|
||||||
|
/// - headers
|
||||||
|
/// - receipts
|
||||||
|
///
|
||||||
|
/// This provider type is responsible for reading and writing to static files.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StaticFileProvider<N>(pub(crate) Arc<StaticFileProviderInner<N>>);
|
pub struct StaticFileProvider<N>(pub(crate) Arc<StaticFileProviderInner<N>>);
|
||||||
|
|
||||||
@ -89,7 +96,7 @@ impl<N> Clone for StaticFileProvider<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<N: NodePrimitives> StaticFileProvider<N> {
|
impl<N: NodePrimitives> StaticFileProvider<N> {
|
||||||
/// Creates a new [`StaticFileProvider`].
|
/// Creates a new [`StaticFileProvider`] with the given [`StaticFileAccess`].
|
||||||
fn new(path: impl AsRef<Path>, access: StaticFileAccess) -> ProviderResult<Self> {
|
fn new(path: impl AsRef<Path>, access: StaticFileAccess) -> ProviderResult<Self> {
|
||||||
let provider = Self(Arc::new(StaticFileProviderInner::new(path, access)?));
|
let provider = Self(Arc::new(StaticFileProviderInner::new(path, access)?));
|
||||||
provider.initialize_index()?;
|
provider.initialize_index()?;
|
||||||
@ -100,6 +107,11 @@ impl<N: NodePrimitives> StaticFileProvider<N> {
|
|||||||
///
|
///
|
||||||
/// Set `watch_directory` to `true` to track the most recent changes in static files. Otherwise,
|
/// Set `watch_directory` to `true` to track the most recent changes in static files. Otherwise,
|
||||||
/// new data won't be detected or queryable.
|
/// new data won't be detected or queryable.
|
||||||
|
///
|
||||||
|
/// Watching is recommended if the read-only provider is used on a directory that an active node
|
||||||
|
/// instance is modifying.
|
||||||
|
///
|
||||||
|
/// See also [`StaticFileProvider::watch_directory`].
|
||||||
pub fn read_only(path: impl AsRef<Path>, watch_directory: bool) -> ProviderResult<Self> {
|
pub fn read_only(path: impl AsRef<Path>, watch_directory: bool) -> ProviderResult<Self> {
|
||||||
let provider = Self::new(path, StaticFileAccess::RO)?;
|
let provider = Self::new(path, StaticFileAccess::RO)?;
|
||||||
|
|
||||||
|
|||||||
@ -2,16 +2,13 @@ use alloy_consensus::BlockHeader;
|
|||||||
use alloy_primitives::{Address, B256};
|
use alloy_primitives::{Address, B256};
|
||||||
use alloy_rpc_types_eth::{Filter, FilteredParams};
|
use alloy_rpc_types_eth::{Filter, FilteredParams};
|
||||||
use reth_chainspec::ChainSpecBuilder;
|
use reth_chainspec::ChainSpecBuilder;
|
||||||
use reth_db::{open_db_read_only, DatabaseEnv};
|
|
||||||
use reth_node_ethereum::EthereumNode;
|
use reth_node_ethereum::EthereumNode;
|
||||||
use reth_node_types::NodeTypesWithDBAdapter;
|
|
||||||
use reth_primitives::{SealedBlock, SealedHeader, TransactionSigned};
|
use reth_primitives::{SealedBlock, SealedHeader, TransactionSigned};
|
||||||
use reth_primitives_traits::transaction::signed::SignedTransaction;
|
use reth_primitives_traits::transaction::signed::SignedTransaction;
|
||||||
use reth_provider::{
|
use reth_provider::{
|
||||||
providers::StaticFileProvider, AccountReader, BlockReader, BlockSource, HeaderProvider,
|
providers::ReadOnlyConfig, AccountReader, BlockReader, BlockSource, HeaderProvider,
|
||||||
ProviderFactory, ReceiptProvider, StateProvider, TransactionsProvider,
|
ReceiptProvider, StateProvider, TransactionsProvider,
|
||||||
};
|
};
|
||||||
use std::{path::Path, sync::Arc};
|
|
||||||
|
|
||||||
// Providers are zero cost abstractions on top of an opened MDBX Transaction
|
// Providers are zero cost abstractions on top of an opened MDBX Transaction
|
||||||
// exposing a familiar API to query the chain's information without requiring knowledge
|
// exposing a familiar API to query the chain's information without requiring knowledge
|
||||||
@ -22,17 +19,11 @@ use std::{path::Path, sync::Arc};
|
|||||||
fn main() -> eyre::Result<()> {
|
fn main() -> eyre::Result<()> {
|
||||||
// Opens a RO handle to the database file.
|
// Opens a RO handle to the database file.
|
||||||
let db_path = std::env::var("RETH_DB_PATH")?;
|
let db_path = std::env::var("RETH_DB_PATH")?;
|
||||||
let db_path = Path::new(&db_path);
|
|
||||||
let db = open_db_read_only(db_path.join("db").as_path(), Default::default())?;
|
|
||||||
|
|
||||||
// Instantiate a provider factory for Ethereum mainnet using the provided DB.
|
// Instantiate a provider factory for Ethereum mainnet using the provided DB path.
|
||||||
// TODO: Should the DB version include the spec so that you do not need to specify it here?
|
|
||||||
let spec = ChainSpecBuilder::mainnet().build();
|
let spec = ChainSpecBuilder::mainnet().build();
|
||||||
let factory = ProviderFactory::<NodeTypesWithDBAdapter<EthereumNode, Arc<DatabaseEnv>>>::new(
|
let factory = EthereumNode::provider_factory_builder()
|
||||||
db.into(),
|
.open_read_only(spec.into(), ReadOnlyConfig::from_db_dir(db_path))?;
|
||||||
spec.into(),
|
|
||||||
StaticFileProvider::read_only(db_path.join("static_files"), true)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
// This call opens a RO transaction on the database. To write to the DB you'd need to call
|
// This call opens a RO transaction on the database. To write to the DB you'd need to call
|
||||||
// the `provider_rw` function and look for the `Writer` variants of the traits.
|
// the `provider_rw` function and look for the `Writer` variants of the traits.
|
||||||
|
|||||||
Reference in New Issue
Block a user