Skip to content

Commit 8f90c25

Browse files
kariyclaude
andcommitted
feat: add CLI support for state pruning configuration
This commit adds command-line interface support for configuring state pruning in full nodes, allowing users to control historical state retention directly through CLI arguments. ## Changes ### CLI Options (crates/cli/src/options.rs) - Added `PruningOptions` struct with two configuration parameters: - `--pruning.mode`: Specifies pruning strategy - `full`: Keep all state (default) - `latest`: Keep only latest state - `archive:N`: Keep last N blocks - `--pruning.interval`: Blocks between pruning runs - Added `PruningMode` enum (CLI representation) - Implemented `parse_pruning_mode` parser for flexible mode specification ### Full Node Integration (crates/cli/src/full.rs) - Added `pruning` field to `FullNodeArgs` - Implemented `pruning_config()` to convert CLI options to pipeline config - Maps CLI `PruningMode` to `katana_stage::PruningMode` ### Node Configuration (crates/node/src/full/mod.rs) - Added `pruning` field to full node `Config` - Exported `PruningConfig` from `katana_pipeline` for reuse - Wired pruning config to pipeline during node build ## Usage Examples Keep only last 1000 blocks, prune every 100 blocks: ``` katana node full --pruning.mode archive:1000 --pruning.interval 100 ``` Keep only latest state, prune every 50 blocks: ``` katana node full --pruning.mode latest --pruning.interval 50 ``` No pruning (default): ``` katana node full ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6569b2e commit 8f90c25

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

crates/cli/src/full.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub struct FullNodeArgs {
5454
#[cfg(feature = "explorer")]
5555
#[command(flatten)]
5656
pub explorer: ExplorerOptions,
57+
58+
#[command(flatten)]
59+
pub pruning: PruningOptions,
5760
}
5861

5962
impl FullNodeArgs {
@@ -95,16 +98,30 @@ impl FullNodeArgs {
9598
let db = self.db_config();
9699
let rpc = self.rpc_config()?;
97100
let metrics = self.metrics_config();
101+
let pruning = self.pruning_config();
98102

99103
Ok(full::Config {
100104
db,
101105
rpc,
102106
metrics,
107+
pruning,
103108
network: self.network,
104109
gateway_api_key: self.gateway_api_key.clone(),
105110
})
106111
}
107112

113+
fn pruning_config(&self) -> Option<full::PruningConfig> {
114+
use crate::options::PruningMode as CliPruningMode;
115+
116+
let mode = match self.pruning.mode.as_ref()? {
117+
CliPruningMode::Full => katana_stage::PruningMode::Full,
118+
CliPruningMode::Latest => katana_stage::PruningMode::LatestOnly,
119+
CliPruningMode::Archive(n) => katana_stage::PruningMode::HistoricalBlocks(*n),
120+
};
121+
122+
Some(full::PruningConfig { mode, interval: self.pruning.interval })
123+
}
124+
108125
fn db_config(&self) -> DbConfig {
109126
DbConfig { dir: Some(self.db_dir.clone()) }
110127
}

crates/cli/src/options.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,3 +719,60 @@ impl TracerOptions {
719719
self
720720
}
721721
}
722+
723+
#[derive(Debug, Args, Clone, Serialize, Deserialize, PartialEq)]
724+
#[command(next_help_heading = "Pruning options")]
725+
pub struct PruningOptions {
726+
/// State pruning mode.
727+
///
728+
/// Determines how much historical state to retain:
729+
/// - 'full': Keep all historical state (no pruning, default)
730+
/// - 'archive:N': Keep last N blocks of historical state
731+
/// - 'latest': Keep only the latest state
732+
#[arg(long = "pruning.mode", value_name = "MODE")]
733+
#[arg(value_parser = parse_pruning_mode)]
734+
#[serde(default)]
735+
pub mode: Option<PruningMode>,
736+
737+
/// Number of blocks to process between pruning runs.
738+
///
739+
/// Pruning will be triggered after every N blocks are synced.
740+
/// If not specified, pruning is disabled even if a pruning mode is set.
741+
#[arg(long = "pruning.interval", value_name = "BLOCKS")]
742+
#[serde(default)]
743+
pub interval: Option<u64>,
744+
}
745+
746+
impl Default for PruningOptions {
747+
fn default() -> Self {
748+
Self { mode: None, interval: None }
749+
}
750+
}
751+
752+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
753+
#[serde(rename_all = "lowercase")]
754+
pub enum PruningMode {
755+
Full,
756+
Archive(u64),
757+
Latest,
758+
}
759+
760+
fn parse_pruning_mode(s: &str) -> Result<PruningMode, String> {
761+
match s.to_lowercase().as_str() {
762+
"full" => Ok(PruningMode::Full),
763+
"latest" => Ok(PruningMode::Latest),
764+
s if s.starts_with("archive:") => {
765+
let n = s
766+
.strip_prefix("archive:")
767+
.and_then(|n| n.parse::<u64>().ok())
768+
.ok_or_else(|| {
769+
format!("Invalid archive format. Use 'archive:N' where N is a number")
770+
})?;
771+
Ok(PruningMode::Archive(n))
772+
}
773+
_ => Err(format!(
774+
"Invalid pruning mode '{}'. Valid modes are: 'full', 'latest', 'archive:N'",
775+
s
776+
)),
777+
}
778+
}

crates/node/src/full/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,14 @@ pub enum Network {
5858
Sepolia,
5959
}
6060

61+
pub use katana_pipeline::PruningConfig;
62+
6163
#[derive(Debug)]
6264
pub struct Config {
6365
pub db: DbConfig,
6466
pub rpc: RpcConfig,
6567
pub metrics: Option<MetricsConfig>,
68+
pub pruning: Option<PruningConfig>,
6669
pub gateway_api_key: Option<String>,
6770
pub network: Network,
6871
}
@@ -122,6 +125,12 @@ impl Node {
122125
// --- build pipeline
123126

124127
let (mut pipeline, pipeline_handle) = Pipeline::new(provider.clone(), 50);
128+
129+
// Configure pruning if specified
130+
if let Some(pruning_config) = config.pruning {
131+
pipeline.set_pruning_config(pruning_config);
132+
}
133+
125134
let block_downloader = BatchBlockDownloader::new_gateway(gateway_client.clone(), 8);
126135
pipeline.add_stage(Blocks::new(provider.clone(), block_downloader));
127136
pipeline.add_stage(Classes::new(provider.clone(), gateway_client.clone(), 8));

0 commit comments

Comments
 (0)