Skip to content

Commit

Permalink
feat(cli): drop execution stage (paradigmxyz#1854)
Browse files Browse the repository at this point in the history
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
  • Loading branch information
gakonst and mattsse committed Mar 20, 2023
1 parent 8673e95 commit 876df20
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 101 deletions.
6 changes: 5 additions & 1 deletion bin/reth/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::str::FromStr;
use crate::{
chain, db,
dirs::{LogsDir, PlatformPath},
dump_stage, node, p2p,
drop_stage, dump_stage, node, p2p,
runner::CliRunner,
stage, test_eth_chain, test_vectors,
};
Expand All @@ -31,6 +31,7 @@ pub fn run() -> eyre::Result<()> {
Commands::Db(command) => runner.run_until_ctrl_c(command.execute()),
Commands::Stage(command) => runner.run_until_ctrl_c(command.execute()),
Commands::DumpStage(command) => runner.run_until_ctrl_c(command.execute()),
Commands::DropStage(command) => runner.run_until_ctrl_c(command.execute()),
Commands::P2P(command) => runner.run_until_ctrl_c(command.execute()),
Commands::TestVectors(command) => runner.run_until_ctrl_c(command.execute()),
Commands::TestEthChain(command) => runner.run_until_ctrl_c(command.execute()),
Expand Down Expand Up @@ -63,6 +64,9 @@ pub enum Commands {
/// Dumps a stage from a range into a new database.
#[command(name = "dump-stage")]
DumpStage(dump_stage::Command),
/// Drops a stage's tables from the database.
#[command(name = "drop-stage")]
DropStage(drop_stage::Command),
/// P2P Debugging utilities
#[command(name = "p2p")]
P2P(p2p::Command),
Expand Down
72 changes: 7 additions & 65 deletions bin/reth/src/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
//! Database debugging tool
use crate::dirs::{DbPath, PlatformPath};
use crate::{
dirs::{DbPath, PlatformPath},
utils::DbTool,
};
use clap::{Parser, Subcommand};
use comfy_table::{Cell, Row, Table as ComfyTable};
use eyre::{Result, WrapErr};
use eyre::WrapErr;
use human_bytes::human_bytes;
use reth_db::{
cursor::{DbCursorRO, Walker},
database::Database,
table::Table,
tables,
transaction::DbTx,
};
use reth_interfaces::test_utils::generators::random_block_range;
use reth_provider::insert_canonical_block;
use std::collections::BTreeMap;
use tracing::{error, info};
use reth_db::{database::Database, tables};
use tracing::error;

/// DB List TUI
mod tui;
Expand Down Expand Up @@ -189,55 +183,3 @@ impl Command {
Ok(())
}
}

/// Wrapper over DB that implements many useful DB queries.
pub(crate) struct DbTool<'a, DB: Database> {
pub(crate) db: &'a DB,
}

impl<'a, DB: Database> DbTool<'a, DB> {
/// Takes a DB where the tables have already been created.
pub(crate) fn new(db: &'a DB) -> eyre::Result<Self> {
Ok(Self { db })
}

/// Seeds the database with some random data, only used for testing
fn seed(&mut self, len: u64) -> Result<()> {
info!(target: "reth::cli", "Generating random block range from 0 to {len}");
let chain = random_block_range(0..len, Default::default(), 0..64);

self.db.update(|tx| {
chain.into_iter().try_for_each(|block| {
insert_canonical_block(tx, block, None, true)?;
Ok::<_, eyre::Error>(())
})
})??;

info!(target: "reth::cli", "Database seeded with {len} blocks");
Ok(())
}

/// Grabs the contents of the table within a certain index range and places the
/// entries into a [`HashMap`][std::collections::HashMap].
fn list<T: Table>(&mut self, start: usize, len: usize) -> Result<BTreeMap<T::Key, T::Value>> {
let data = self.db.view(|tx| {
let mut cursor = tx.cursor_read::<T>().expect("Was not able to obtain a cursor.");

// TODO: Upstream this in the DB trait.
let start_walker = cursor.current().transpose();
let walker = Walker::new(&mut cursor, start_walker);

walker.skip(start).take(len).collect::<Vec<_>>()
})?;

data.into_iter()
.collect::<Result<BTreeMap<T::Key, T::Value>, _>>()
.map_err(|e| eyre::eyre!(e))
}

fn drop(&mut self, path: &PlatformPath<DbPath>) -> Result<()> {
info!(target: "reth::cli", "Dropping db at {}", path);
std::fs::remove_dir_all(path).wrap_err("Dropping the database failed")?;
Ok(())
}
}
82 changes: 82 additions & 0 deletions bin/reth/src/drop_stage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//! Database debugging tool
use crate::{
dirs::{DbPath, PlatformPath},
utils::DbTool,
StageEnum,
};
use clap::Parser;
use reth_db::{
database::Database,
mdbx::{Env, WriteMap},
tables,
transaction::DbTxMut,
};
use reth_primitives::ChainSpec;
use reth_staged_sync::utils::{chainspec::genesis_value_parser, init::insert_genesis_state};
use reth_stages::stages::EXECUTION;
use std::sync::Arc;
use tracing::info;

/// `reth drop-stage` command
#[derive(Debug, Parser)]
pub struct Command {
/// The path to the database folder.
///
/// Defaults to the OS-specific data directory:
///
/// - Linux: `$XDG_DATA_HOME/reth/db` or `$HOME/.local/share/reth/db`
/// - Windows: `{FOLDERID_RoamingAppData}/reth/db`
/// - macOS: `$HOME/Library/Application Support/reth/db`
#[arg(global = true, long, value_name = "PATH", verbatim_doc_comment, default_value_t)]
db: PlatformPath<DbPath>,

/// The chain this node is running.
///
/// Possible values are either a built-in chain or the path to a chain specification file.
///
/// Built-in chains:
/// - mainnet
/// - goerli
/// - sepolia
#[arg(
long,
value_name = "CHAIN_OR_PATH",
verbatim_doc_comment,
default_value = "mainnet",
value_parser = genesis_value_parser
)]
chain: Arc<ChainSpec>,

stage: StageEnum,
}

impl Command {
/// Execute `db` command
pub async fn execute(&self) -> eyre::Result<()> {
std::fs::create_dir_all(&self.db)?;

let db = Env::<WriteMap>::open(self.db.as_ref(), reth_db::mdbx::EnvKind::RW)?;

let tool = DbTool::new(&db)?;

match &self.stage {
StageEnum::Execution => {
tool.db.update(|tx| {
tx.clear::<tables::PlainAccountState>()?;
tx.clear::<tables::PlainStorageState>()?;
tx.clear::<tables::AccountChangeSet>()?;
tx.clear::<tables::StorageChangeSet>()?;
tx.clear::<tables::Bytecodes>()?;
tx.put::<tables::SyncStage>(EXECUTION.0.to_string(), 0)?;
insert_genesis_state::<Env<WriteMap>>(tx, self.chain.genesis())?;
Ok::<_, eyre::Error>(())
})??;
}
_ => {
info!("Nothing to do for stage {:?}", self.stage);
}
}

Ok(())
}
}
2 changes: 1 addition & 1 deletion bin/reth/src/dump_stage/execution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
db::DbTool,
dirs::{DbPath, PlatformPath},
dump_stage::setup,
utils::DbTool,
};
use eyre::Result;
use reth_db::{
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/dump_stage/hashing_account.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
db::DbTool,
dirs::{DbPath, PlatformPath},
dump_stage::setup,
utils::DbTool,
};
use eyre::Result;
use reth_db::{database::Database, table::TableImporter, tables, transaction::DbTx};
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/dump_stage/hashing_storage.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
db::DbTool,
dirs::{DbPath, PlatformPath},
dump_stage::setup,
utils::DbTool,
};
use eyre::Result;
use reth_db::{database::Database, table::TableImporter, tables};
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/dump_stage/merkle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
db::DbTool,
dirs::{DbPath, PlatformPath},
dump_stage::setup,
utils::DbTool,
};
use eyre::Result;
use reth_db::{database::Database, table::TableImporter, tables, transaction::DbTx};
Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/dump_stage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ mod merkle;
use merkle::dump_merkle_stage;

use crate::{
db::DbTool,
dirs::{DbPath, PlatformPath},
utils::DbTool,
};
use clap::Parser;
use reth_db::{
Expand Down
9 changes: 9 additions & 0 deletions bin/reth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod chain;
pub mod cli;
pub mod db;
pub mod dirs;
pub mod drop_stage;
pub mod dump_stage;
pub mod node;
pub mod p2p;
Expand All @@ -21,3 +22,11 @@ pub mod stage;
pub mod test_eth_chain;
pub mod test_vectors;
pub mod utils;

#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, clap::ValueEnum)]
enum StageEnum {
Headers,
Bodies,
Senders,
Execution,
}
12 changes: 2 additions & 10 deletions bin/reth/src/stage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
use crate::{
args::NetworkArgs,
dirs::{ConfigPath, DbPath, PlatformPath},
prometheus_exporter,
prometheus_exporter, StageEnum,
};
use clap::{Parser, ValueEnum};
use clap::Parser;
use reth_beacon_consensus::BeaconConsensus;
use reth_downloaders::bodies::bodies::BodiesDownloaderBuilder;
use reth_primitives::ChainSpec;
Expand Down Expand Up @@ -86,14 +86,6 @@ pub struct Command {
network: NetworkArgs,
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, ValueEnum)]
enum StageEnum {
Headers,
Bodies,
Senders,
Execution,
}

impl Command {
/// Execute `stage` command
pub async fn execute(&self) -> eyre::Result<()> {
Expand Down
86 changes: 81 additions & 5 deletions bin/reth/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
//! Common CLI utility functions.

use reth_interfaces::p2p::{
download::DownloadClient,
headers::client::{HeadersClient, HeadersRequest},
priority::Priority,
use crate::dirs::{DbPath, PlatformPath};
use eyre::{Result, WrapErr};
use reth_db::{
cursor::{DbCursorRO, Walker},
database::Database,
table::Table,
transaction::{DbTx, DbTxMut},
};
use reth_interfaces::{
p2p::{
download::DownloadClient,
headers::client::{HeadersClient, HeadersRequest},
priority::Priority,
},
test_utils::generators::random_block_range,
};
use reth_network::FetchClient;
use reth_primitives::{BlockHashOrNumber, HeadersDirection, SealedHeader};
use reth_provider::insert_canonical_block;
use std::collections::BTreeMap;
use tracing::info;

/// Get a single header from network
pub async fn get_single_header(
Expand Down Expand Up @@ -41,3 +54,66 @@ pub async fn get_single_header(

Ok(header)
}

/// Wrapper over DB that implements many useful DB queries.
pub struct DbTool<'a, DB: Database> {
pub(crate) db: &'a DB,
}

impl<'a, DB: Database> DbTool<'a, DB> {
/// Takes a DB where the tables have already been created.
pub(crate) fn new(db: &'a DB) -> eyre::Result<Self> {
Ok(Self { db })
}

/// Seeds the database with some random data, only used for testing
pub fn seed(&mut self, len: u64) -> Result<()> {
info!(target: "reth::cli", "Generating random block range from 0 to {len}");
let chain = random_block_range(0..len, Default::default(), 0..64);

self.db.update(|tx| {
chain.into_iter().try_for_each(|block| {
insert_canonical_block(tx, block, None, true)?;
Ok::<_, eyre::Error>(())
})
})??;

info!(target: "reth::cli", "Database seeded with {len} blocks");
Ok(())
}

/// Grabs the contents of the table within a certain index range and places the
/// entries into a [`HashMap`][std::collections::HashMap].
pub fn list<T: Table>(
&mut self,
start: usize,
len: usize,
) -> Result<BTreeMap<T::Key, T::Value>> {
let data = self.db.view(|tx| {
let mut cursor = tx.cursor_read::<T>().expect("Was not able to obtain a cursor.");

// TODO: Upstream this in the DB trait.
let start_walker = cursor.current().transpose();
let walker = Walker::new(&mut cursor, start_walker);

walker.skip(start).take(len).collect::<Vec<_>>()
})?;

data.into_iter()
.collect::<Result<BTreeMap<T::Key, T::Value>, _>>()
.map_err(|e| eyre::eyre!(e))
}

/// Drops the database at the given path.
pub fn drop(&mut self, path: &PlatformPath<DbPath>) -> Result<()> {
info!(target: "reth::cli", "Dropping db at {}", path);
std::fs::remove_dir_all(path).wrap_err("Dropping the database failed")?;
Ok(())
}

/// Drops the provided table from the database.
pub fn drop_table<T: Table>(&mut self) -> Result<()> {
self.db.update(|tx| tx.clear::<T>())??;
Ok(())
}
}
Loading

0 comments on commit 876df20

Please sign in to comment.