feat(cli): add --rocksdb.* flags for RocksDB table routing (#21191)

This commit is contained in:
YK
2026-01-20 20:29:05 +01:00
committed by GitHub
parent ff8f434dcd
commit bc79cc44c9
6 changed files with 205 additions and 2 deletions

View File

@@ -10,7 +10,8 @@ use reth_node_builder::NodeBuilder;
use reth_node_core::{
args::{
DatabaseArgs, DatadirArgs, DebugArgs, DevArgs, EngineArgs, EraArgs, MetricArgs,
NetworkArgs, PayloadBuilderArgs, PruningArgs, RpcServerArgs, StaticFilesArgs, TxPoolArgs,
NetworkArgs, PayloadBuilderArgs, PruningArgs, RocksDbArgs, RpcServerArgs, StaticFilesArgs,
TxPoolArgs,
},
node_config::NodeConfig,
version,
@@ -102,6 +103,10 @@ pub struct NodeCommand<C: ChainSpecParser, Ext: clap::Args + fmt::Debug = NoArgs
#[command(flatten)]
pub pruning: PruningArgs,
/// All `RocksDB` table routing arguments
#[command(flatten)]
pub rocksdb: RocksDbArgs,
/// Engine cli arguments
#[command(flatten, next_help_heading = "Engine")]
pub engine: EngineArgs,
@@ -166,12 +171,16 @@ where
db,
dev,
pruning,
rocksdb,
engine,
era,
static_files,
ext,
} = self;
// Validate RocksDB arguments
rocksdb.validate()?;
// set up node config
let mut node_config = NodeConfig {
datadir,
@@ -187,6 +196,7 @@ where
db,
dev,
pruning,
rocksdb,
engine,
era,
static_files,

View File

@@ -80,5 +80,9 @@ pub use era::{DefaultEraHost, EraArgs, EraSourceArgs};
mod static_files;
pub use static_files::{StaticFilesArgs, MINIMAL_BLOCKS_PER_FILE};
/// `RocksDbArgs` for configuring RocksDB table routing.
mod rocksdb;
pub use rocksdb::{RocksDbArgs, RocksDbArgsError};
mod error;
pub mod types;

View File

@@ -0,0 +1,122 @@
//! clap [Args](clap::Args) for `RocksDB` table routing configuration
use clap::{ArgAction, Args};
/// Parameters for `RocksDB` table routing configuration.
///
/// These flags control which database tables are stored in `RocksDB` instead of MDBX.
/// All flags are genesis-initialization-only: changing them after genesis requires a re-sync.
#[derive(Debug, Args, PartialEq, Eq, Default, Clone, Copy)]
#[command(next_help_heading = "RocksDB")]
pub struct RocksDbArgs {
/// Route all supported tables to `RocksDB` instead of MDBX.
///
/// This enables `RocksDB` for `tx-hash`, `storages-history`, and `account-history` tables.
/// Cannot be combined with individual flags set to false.
#[arg(long = "rocksdb.all", action = ArgAction::SetTrue)]
pub all: bool,
/// Route tx hash -> number table to `RocksDB` instead of MDBX.
#[arg(long = "rocksdb.tx-hash", action = ArgAction::Set)]
pub tx_hash: Option<bool>,
/// Route storages history tables to `RocksDB` instead of MDBX.
#[arg(long = "rocksdb.storages-history", action = ArgAction::Set)]
pub storages_history: Option<bool>,
/// Route account history tables to `RocksDB` instead of MDBX.
#[arg(long = "rocksdb.account-history", action = ArgAction::Set)]
pub account_history: Option<bool>,
}
impl RocksDbArgs {
/// Validates the `RocksDB` arguments.
///
/// Returns an error if `--rocksdb.all` is used with any individual flag set to `false`.
pub fn validate(&self) -> Result<(), RocksDbArgsError> {
if self.all {
if self.tx_hash == Some(false) {
return Err(RocksDbArgsError::ConflictingFlags("tx-hash"));
}
if self.storages_history == Some(false) {
return Err(RocksDbArgsError::ConflictingFlags("storages-history"));
}
if self.account_history == Some(false) {
return Err(RocksDbArgsError::ConflictingFlags("account-history"));
}
}
Ok(())
}
}
/// Error type for `RocksDB` argument validation.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum RocksDbArgsError {
/// `--rocksdb.all` cannot be combined with an individual flag set to false.
#[error("--rocksdb.all cannot be combined with --rocksdb.{0}=false")]
ConflictingFlags(&'static str),
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
#[derive(Parser)]
struct CommandParser<T: Args> {
#[command(flatten)]
args: T,
}
#[test]
fn test_default_rocksdb_args() {
let args = CommandParser::<RocksDbArgs>::parse_from(["reth"]).args;
assert_eq!(args, RocksDbArgs::default());
}
#[test]
fn test_parse_all_flag() {
let args = CommandParser::<RocksDbArgs>::parse_from(["reth", "--rocksdb.all"]).args;
assert!(args.all);
assert_eq!(args.tx_hash, None);
}
#[test]
fn test_parse_individual_flags() {
let args = CommandParser::<RocksDbArgs>::parse_from([
"reth",
"--rocksdb.tx-hash=true",
"--rocksdb.storages-history=false",
"--rocksdb.account-history=true",
])
.args;
assert!(!args.all);
assert_eq!(args.tx_hash, Some(true));
assert_eq!(args.storages_history, Some(false));
assert_eq!(args.account_history, Some(true));
}
#[test]
fn test_validate_all_alone_ok() {
let args = RocksDbArgs { all: true, ..Default::default() };
assert!(args.validate().is_ok());
}
#[test]
fn test_validate_all_with_true_ok() {
let args = RocksDbArgs { all: true, tx_hash: Some(true), ..Default::default() };
assert!(args.validate().is_ok());
}
#[test]
fn test_validate_all_with_false_errors() {
let args = RocksDbArgs { all: true, tx_hash: Some(false), ..Default::default() };
assert_eq!(args.validate(), Err(RocksDbArgsError::ConflictingFlags("tx-hash")));
let args = RocksDbArgs { all: true, storages_history: Some(false), ..Default::default() };
assert_eq!(args.validate(), Err(RocksDbArgsError::ConflictingFlags("storages-history")));
let args = RocksDbArgs { all: true, account_history: Some(false), ..Default::default() };
assert_eq!(args.validate(), Err(RocksDbArgsError::ConflictingFlags("account-history")));
}
}

View File

@@ -3,7 +3,7 @@
use crate::{
args::{
DatabaseArgs, DatadirArgs, DebugArgs, DevArgs, EngineArgs, NetworkArgs, PayloadBuilderArgs,
PruningArgs, RpcServerArgs, StaticFilesArgs, TxPoolArgs,
PruningArgs, RocksDbArgs, RpcServerArgs, StaticFilesArgs, TxPoolArgs,
},
dirs::{ChainPath, DataDirPath},
utils::get_single_header,
@@ -21,6 +21,7 @@ use reth_primitives_traits::SealedHeader;
use reth_stages_types::StageId;
use reth_storage_api::{
BlockHashReader, DatabaseProviderFactory, HeaderProvider, StageCheckpointReader,
StorageSettings,
};
use reth_storage_errors::provider::ProviderResult;
use reth_transaction_pool::TransactionPool;
@@ -150,6 +151,9 @@ pub struct NodeConfig<ChainSpec> {
/// All static files related arguments
pub static_files: StaticFilesArgs,
/// All `RocksDB` table routing arguments
pub rocksdb: RocksDbArgs,
}
impl NodeConfig<ChainSpec> {
@@ -181,6 +185,7 @@ impl<ChainSpec> NodeConfig<ChainSpec> {
engine: EngineArgs::default(),
era: EraArgs::default(),
static_files: StaticFilesArgs::default(),
rocksdb: RocksDbArgs::default(),
}
}
@@ -255,6 +260,7 @@ impl<ChainSpec> NodeConfig<ChainSpec> {
engine,
era,
static_files,
rocksdb,
..
} = self;
NodeConfig {
@@ -274,6 +280,7 @@ impl<ChainSpec> NodeConfig<ChainSpec> {
engine,
era,
static_files,
rocksdb,
}
}
@@ -350,6 +357,22 @@ impl<ChainSpec> NodeConfig<ChainSpec> {
self.pruning.prune_config(&self.chain)
}
/// Returns the effective storage settings derived from static-file and `RocksDB` CLI args.
pub fn storage_settings(&self) -> StorageSettings {
let tx_hash = self.rocksdb.all || self.rocksdb.tx_hash.unwrap_or(false);
let storages_history = self.rocksdb.all || self.rocksdb.storages_history.unwrap_or(false);
let account_history = self.rocksdb.all || self.rocksdb.account_history.unwrap_or(false);
StorageSettings {
receipts_in_static_files: self.static_files.receipts,
transaction_senders_in_static_files: self.static_files.transaction_senders,
account_changesets_in_static_files: self.static_files.account_changesets,
transaction_hash_numbers_in_rocksdb: tx_hash,
storages_history_in_rocksdb: storages_history,
account_history_in_rocksdb: account_history,
}
}
/// Returns the max block that the node should run to, looking it up from the network if
/// necessary
pub async fn max_block<Provider, Client>(
@@ -544,6 +567,7 @@ impl<ChainSpec> NodeConfig<ChainSpec> {
engine: self.engine,
era: self.era,
static_files: self.static_files,
rocksdb: self.rocksdb,
}
}
@@ -585,6 +609,7 @@ impl<ChainSpec> Clone for NodeConfig<ChainSpec> {
engine: self.engine.clone(),
era: self.era.clone(),
static_files: self.static_files,
rocksdb: self.rocksdb,
}
}
}

View File

@@ -897,6 +897,27 @@ Pruning:
--prune.bodies.before <BLOCK_NUMBER>
Prune storage history before the specified block number. The specified block number is not pruned
RocksDB:
--rocksdb.all
Route all supported tables to `RocksDB` instead of MDBX.
This enables `RocksDB` for `tx-hash`, `storages-history`, and `account-history` tables. Cannot be combined with individual flags set to false.
--rocksdb.tx-hash <TX_HASH>
Route tx hash -> number table to `RocksDB` instead of MDBX
[possible values: true, false]
--rocksdb.storages-history <STORAGES_HISTORY>
Route storages history tables to `RocksDB` instead of MDBX
[possible values: true, false]
--rocksdb.account-history <ACCOUNT_HISTORY>
Route account history tables to `RocksDB` instead of MDBX
[possible values: true, false]
Engine:
--engine.persistence-threshold <PERSISTENCE_THRESHOLD>
Configure persistence threshold for the engine. This determines how many canonical blocks must be in-memory, ahead of the last persisted block, before flushing canonical blocks to disk again.

View File

@@ -897,6 +897,27 @@ Pruning:
--prune.bodies.before <BLOCK_NUMBER>
Prune storage history before the specified block number. The specified block number is not pruned
RocksDB:
--rocksdb.all
Route all supported tables to `RocksDB` instead of MDBX.
This enables `RocksDB` for `tx-hash`, `storages-history`, and `account-history` tables. Cannot be combined with individual flags set to false.
--rocksdb.tx-hash <TX_HASH>
Route tx hash -> number table to `RocksDB` instead of MDBX
[possible values: true, false]
--rocksdb.storages-history <STORAGES_HISTORY>
Route storages history tables to `RocksDB` instead of MDBX
[possible values: true, false]
--rocksdb.account-history <ACCOUNT_HISTORY>
Route account history tables to `RocksDB` instead of MDBX
[possible values: true, false]
Engine:
--engine.persistence-threshold <PERSISTENCE_THRESHOLD>
Configure persistence threshold for the engine. This determines how many canonical blocks must be in-memory, ahead of the last persisted block, before flushing canonical blocks to disk again.