feat(bin): simple reth node command (#158)

* feat(bin): simple reth node command

* use silent flag

* small chore
This commit is contained in:
rakita
2022-11-07 21:10:09 +01:00
committed by GitHub
parent caad026c70
commit 86ffb4756d
10 changed files with 197 additions and 28 deletions

48
Cargo.lock generated
View File

@ -958,6 +958,26 @@ dependencies = [
"subtle",
]
[[package]]
name = "dirs"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "discv5"
version = "0.1.0"
@ -2969,6 +2989,17 @@ dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom 0.2.8",
"redox_syscall",
"thiserror",
]
[[package]]
name = "regex"
version = "1.6.0"
@ -3010,13 +3041,21 @@ version = "0.1.0"
dependencies = [
"clap 4.0.18",
"eyre",
"reth-consensus",
"reth-db",
"reth-interfaces",
"reth-primitives",
"reth-rpc",
"reth-stages",
"reth-transaction-pool",
"serde",
"serde_json",
"shellexpand",
"thiserror",
"tokio",
"tracing",
"tracing-futures",
"tracing-subscriber",
"walkdir",
]
@ -3902,6 +3941,15 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "shellexpand"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4"
dependencies = [
"dirs",
]
[[package]]
name = "shlex"
version = "1.1.0"

View File

@ -7,13 +7,27 @@ repository = "https://github.com/foundry-rs/reth"
readme = "README.md"
[dependencies]
# reth
reth-primitives = { path = "../../crates/primitives" }
reth-db = {path = "../../crates/db"}
reth-stages = {path = "../../crates/stages"}
reth-interfaces = {path = "../../crates/interfaces"}
reth-transaction-pool = {path = "../../crates/transaction-pool"}
reth-consensus = {path = "../../crates/consensus"}
reth-rpc = {path = "../../crates/net/rpc"}
# tracing
tracing = "0.1"
tracing-futures = "0.2"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# mics
shellexpand = "2.1"
eyre = "0.6.8"
clap = { version = "4.0", features = ["derive"] }
thiserror = "1.0"
tracing = "0.1"
tracing-futures = "0.2"
tokio = { version = "1.21", features = ["sync", "macros", "rt-multi-thread"] }
serde = "1.0"
serde_json = "1.0"
reth-primitives = { path = "../../crates/primitives" }
walkdir = "2.3"

View File

@ -1,12 +1,23 @@
use clap::{ArgAction, Parser, Subcommand};
//! CLI definition and entrypoint to executable
use crate::test_eth_chain;
use clap::{ArgAction, Parser, Subcommand};
use tracing_subscriber::util::SubscriberInitExt;
use crate::{
node, test_eth_chain,
util::reth_tracing::{self, TracingMode},
};
/// main function that parses cli and runs command
pub async fn run() -> eyre::Result<()> {
let opt = Cli::parse();
let tracing = if opt.silent { TracingMode::Silent } else { TracingMode::All };
reth_tracing::build_subscriber(tracing).init();
match opt.command {
Commands::Node(command) => command.execute().await,
Commands::TestEthChain(command) => command.execute().await,
}
}
@ -14,6 +25,9 @@ pub async fn run() -> eyre::Result<()> {
/// Commands to be executed
#[derive(Subcommand)]
pub enum Commands {
/// Main node command
#[command(name = "node")]
Node(node::Command),
/// Runs Ethereum blockchain tests
#[command(name = "test-chain")]
TestEthChain(test_eth_chain::Command),

View File

@ -4,14 +4,9 @@
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
//! Rust Ethereum (reth) binary executable.
/// CLI definition and entrypoint
pub mod cli;
/// Utility functions.
pub mod util;
/// Command for executing Ethereum blockchain tests
pub mod node;
pub mod test_eth_chain;
pub mod util;

48
bin/reth/src/node/mod.rs Normal file
View File

@ -0,0 +1,48 @@
//! Main node command
//!
//! Starts the client
use clap::Parser;
use std::{path::Path, sync::Arc};
use tracing::info;
/// Execute Ethereum blockchain tests by specifying path to json files
#[derive(Debug, Parser)]
pub struct Command {
/// Path to database folder
#[arg(long, default_value = "~/.reth/db")]
db: String,
}
impl Command {
/// Execute `node` command
pub async fn execute(&self) -> eyre::Result<()> {
info!("Rust Ethereum client");
info!("Initialize components:");
let path = shellexpand::full(&self.db)?.into_owned();
let expanded_db_path = Path::new(&path);
std::fs::create_dir_all(expanded_db_path)?;
let db = Arc::new(reth_db::kv::Env::<reth_db::mdbx::WriteMap>::open(
expanded_db_path,
reth_db::kv::EnvKind::RW,
)?);
info!("DB opened");
// let _p2p = ();
// let _consensus = ();
// let _rpc = ();
let mut pipeline = reth_stages::Pipeline::new();
// define all stages here
// run pipeline
info!("Pipeline started:");
pipeline.run(db.clone()).await?;
info!("Finishing");
Ok(())
}
}

View File

@ -1,3 +1,5 @@
//! Command for running Ethereum chain tests.
use crate::util;
use clap::Parser;
use std::path::PathBuf;
@ -21,7 +23,7 @@ impl Command {
.path
.iter()
.map(|item| {
util::find_all_json_tests(item).into_iter().map(|file| {
util::find_all_files_with_postfix(item, ".json").into_iter().map(|file| {
let tfile = file.clone();
let join = tokio::spawn(async move { runner::run_test(tfile.as_path()).await });
(join, file)

View File

@ -1,11 +1,52 @@
//! Utility functions.
use std::path::{Path, PathBuf};
use walkdir::{DirEntry, WalkDir};
pub(crate) fn find_all_json_tests(path: &Path) -> Vec<PathBuf> {
pub(crate) fn find_all_files_with_postfix(path: &Path, postfix: &str) -> Vec<PathBuf> {
WalkDir::new(path)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.file_name().to_string_lossy().ends_with(".json"))
.filter(|e| e.file_name().to_string_lossy().ends_with(postfix))
.map(DirEntry::into_path)
.collect::<Vec<PathBuf>>()
}
/// Tracing utility
pub mod reth_tracing {
use tracing::Subscriber;
use tracing_subscriber::{prelude::*, EnvFilter};
/// Tracing modes
pub enum TracingMode {
/// Enable all info traces.
All,
/// Disable tracing
Silent,
}
impl TracingMode {
fn into_env_filter(self) -> EnvFilter {
match self {
Self::All => EnvFilter::new("reth=info"),
Self::Silent => EnvFilter::new(""),
}
}
}
/// Build subscriber
pub fn build_subscriber(mods: TracingMode) -> impl Subscriber {
let nocolor = std::env::var("RUST_LOG_STYLE").map(|val| val == "never").unwrap_or(false);
// Take env over config
let filter = if std::env::var(EnvFilter::DEFAULT_ENV).unwrap_or_default().is_empty() {
mods.into_env_filter()
} else {
EnvFilter::from_default_env()
};
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer().with_ansi(!nocolor).with_target(false))
.with(filter)
}
}

View File

@ -110,6 +110,7 @@ impl<E: EnvironmentKind> Deref for Env<E> {
#[cfg(any(test, feature = "test-utils"))]
pub mod test_utils {
use super::{Env, EnvKind, EnvironmentKind, Path};
use std::sync::Arc;
/// Error during database creation
pub const ERROR_DB_CREATION: &str = "Not able to create the mdbx file.";
@ -119,8 +120,11 @@ pub mod test_utils {
pub const ERROR_TEMPDIR: &str = "Not able to create a temporary directory.";
/// Create database for testing
pub fn create_test_db<E: EnvironmentKind>(kind: EnvKind) -> Env<E> {
create_test_db_with_path(kind, &tempfile::TempDir::new().expect(ERROR_TEMPDIR).into_path())
pub fn create_test_db<E: EnvironmentKind>(kind: EnvKind) -> Arc<Env<E>> {
Arc::new(create_test_db_with_path(
kind,
&tempfile::TempDir::new().expect(ERROR_TEMPDIR).into_path(),
))
}
/// Create database for testing with specified path
@ -141,7 +145,7 @@ mod tests {
};
use reth_libmdbx::{NoWriteMap, WriteMap};
use reth_primitives::{Account, Address, Header, IntegerList, StorageEntry, H256, U256};
use std::str::FromStr;
use std::{str::FromStr, sync::Arc};
use tempfile::TempDir;
const ERROR_DB_CREATION: &str = "Not able to create the mdbx file.";
@ -282,7 +286,7 @@ mod tests {
#[test]
fn db_sharded_key() {
let db: Env<WriteMap> = test_utils::create_test_db(EnvKind::RW);
let db: Arc<Env<WriteMap>> = test_utils::create_test_db(EnvKind::RW);
let real_key = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047").unwrap();
for i in 1..5 {

View File

@ -4,7 +4,10 @@ use crate::{
};
use reth_interfaces::db::{DBContainer, Database, DbTx};
use reth_primitives::BlockNumber;
use std::fmt::{Debug, Formatter};
use std::{
fmt::{Debug, Formatter},
sync::Arc,
};
use tokio::sync::mpsc::Sender;
use tracing::*;
@ -139,7 +142,7 @@ impl<DB: Database> Pipeline<DB> {
/// Run the pipeline in an infinite loop. Will terminate early if the user has specified
/// a `max_block` in the pipeline.
pub async fn run(&mut self, db: &DB) -> Result<(), PipelineError> {
pub async fn run(&mut self, db: Arc<DB>) -> Result<(), PipelineError> {
loop {
let mut state = PipelineState {
events_sender: self.events_sender.clone(),
@ -148,7 +151,7 @@ impl<DB: Database> Pipeline<DB> {
minimum_progress: None,
reached_tip: true,
};
let next_action = self.run_loop(&mut state, db).await?;
let next_action = self.run_loop(&mut state, db.as_ref()).await?;
// Terminate the loop early if it's reached the maximum user
// configured block.
@ -396,7 +399,7 @@ mod tests {
false,
)
.set_max_block(Some(10))
.run(&db)
.run(db)
.await
});
@ -450,7 +453,7 @@ mod tests {
.set_max_block(Some(10));
// Sync first
pipeline.run(&db).await.expect("Could not run pipeline");
pipeline.run(db.clone()).await.expect("Could not run pipeline");
// Unwind
pipeline.set_channel(tx).unwind(&db, 1, None).await.expect("Could not unwind pipeline");
@ -528,7 +531,7 @@ mod tests {
)
.set_max_block(Some(10))
.set_channel(tx)
.run(&db)
.run(db)
.await
.expect("Could not run pipeline");
});
@ -620,7 +623,7 @@ mod tests {
.set_max_block(Some(10));
// Sync first
pipeline.run(&db).await.expect("Could not run pipeline");
pipeline.run(db.clone()).await.expect("Could not run pipeline");
// Unwind
pipeline.set_channel(tx).unwind(&db, 1, None).await.expect("Could not unwind pipeline");
@ -690,7 +693,7 @@ mod tests {
true,
)
.set_max_block(Some(10))
.run(&db)
.run(db)
.await
});

View File

@ -145,7 +145,7 @@ pub(crate) mod test_utils {
impl Default for StageTestDB {
/// Create a new instance of [StageTestDB]
fn default() -> Self {
Self { db: Arc::new(create_test_db::<WriteMap>(EnvKind::RW)) }
Self { db: create_test_db::<WriteMap>(EnvKind::RW) }
}
}