diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index 164ed8a93..fe62f8094 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -914,6 +914,20 @@ where ); } + // Prune blobs sidecars older than the blob data availability boundary in the background. + if beacon_chain.store.get_config().prune_blobs { + let store = beacon_chain.store.clone(); + let log = log.clone(); + beacon_chain.task_executor.spawn_blocking( + move || { + if let Err(e) = store.try_prune_blobs(false) { + error!(log, "Error pruning blobs in background"; "error" => ?e); + } + }, + "prune_blobs_background", + ); + } + Ok(beacon_chain) } } diff --git a/beacon_node/store/src/config.rs b/beacon_node/store/src/config.rs index 53d99f75e..13ac674df 100644 --- a/beacon_node/store/src/config.rs +++ b/beacon_node/store/src/config.rs @@ -26,6 +26,8 @@ pub struct StoreConfig { pub compact_on_prune: bool, /// Whether to prune payloads on initialization and finalization. pub prune_payloads: bool, + /// Whether to prune blobs older than the blob data availability boundary. + pub prune_blobs: bool, } /// Variant of `StoreConfig` that gets written to disk. Contains immutable configuration params. @@ -50,6 +52,7 @@ impl Default for StoreConfig { compact_on_init: false, compact_on_prune: true, prune_payloads: true, + prune_blobs: true, } } } diff --git a/database_manager/src/lib.rs b/database_manager/src/lib.rs index 33accfc05..7222c19f3 100644 --- a/database_manager/src/lib.rs +++ b/database_manager/src/lib.rs @@ -65,6 +65,12 @@ pub fn prune_payloads_app<'a, 'b>() -> App<'a, 'b> { .about("Prune finalized execution payloads") } +pub fn prune_blobs_app<'a, 'b>() -> App<'a, 'b> { + App::new("prune_blobs") + .setting(clap::AppSettings::ColoredHelp) + .about("Prune blobs older than data availability boundary") +} + pub fn cli_app<'a, 'b>() -> App<'a, 'b> { App::new(CMD) .visible_aliases(&["db"]) @@ -92,6 +98,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .subcommand(version_cli_app()) .subcommand(inspect_cli_app()) .subcommand(prune_payloads_app()) + .subcommand(prune_blobs_app()) } fn parse_client_config( @@ -287,6 +294,29 @@ pub fn prune_payloads( db.try_prune_execution_payloads(force) } +pub fn prune_blobs( + client_config: ClientConfig, + runtime_context: &RuntimeContext, + log: Logger, +) -> Result<(), Error> { + let spec = &runtime_context.eth2_config.spec; + let hot_path = client_config.get_db_path(); + let cold_path = client_config.get_freezer_db_path(); + + let db = HotColdDB::, LevelDB>::open( + &hot_path, + &cold_path, + |_, _, _| Ok(()), + client_config.store, + spec.clone(), + log, + )?; + + // If we're trigging a prune manually then ignore the check on the split's parent that bails + // out early by passing true to the force parameter. + db.try_prune_blobs(true) +} + /// Run the database manager, returning an error string if the operation did not succeed. pub fn run(cli_args: &ArgMatches<'_>, env: Environment) -> Result<(), String> { let client_config = parse_client_config(cli_args, &env)?; @@ -304,6 +334,7 @@ pub fn run(cli_args: &ArgMatches<'_>, env: Environment) -> Result inspect_db(inspect_config, client_config, &context, log) } ("prune_payloads", Some(_)) => prune_payloads(client_config, &context, log), + ("prune_blobs", Some(_)) => prune_blobs(client_config, &context, log), _ => { return Err("Unknown subcommand, for help `lighthouse database_manager --help`".into()) }