diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 5768fd85b..97c21097e 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -1074,24 +1074,12 @@ impl BeaconChain { ) -> Result>, Error> { match self.store.get_blobs(block_root)? { Some(blobs) => Ok(Some(blobs)), -<<<<<<< HEAD None => { // Check for the corresponding block to understand whether we *should* have blobs. self.get_blinded_block(block_root)? .map(|block| { // If there are no KZG commitments in the block, we know the sidecar should // be empty. -======= - None => match self.get_blinded_block(block_root)? { - Some(block) => { - let current_slot = self.slot()?; - let current_epoch = current_slot.epoch(T::EthSpec::slots_per_epoch()); - - if block.slot().epoch(T::EthSpec::slots_per_epoch()) - + *MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS - >= current_epoch - { ->>>>>>> 292426505 (Improve syntax) let expected_kzg_commitments = match block.message().body().blob_kzg_commitments() { Ok(kzg_commitments) => kzg_commitments, @@ -3027,21 +3015,34 @@ impl BeaconChain { ops.push(StoreOp::PutBlock(block_root, signed_block.clone())); ops.push(StoreOp::PutState(block.state_root(), &state)); - if let Some(blobs) = blobs { - if blobs.blobs.len() > 0 { - //FIXME(sean) using this for debugging for now - info!(self.log, "Writing blobs to store"; "block_root" => ?block_root); - ops.push(StoreOp::PutBlobs(block_root, blobs)); + let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch()); + + // Only store blobs that haven't passed the data availability boundary. + if Some(block_epoch) >= self.data_availability_boundary() { + if let Some(blobs) = blobs? { + if blobs.blobs.len() > 0 { + //FIXME(sean) using this for debugging for now + info!(self.log, "Writing blobs to store"; "block_root" => ?block_root); + ops.push(StoreOp::PutBlobs(block_root, blobs)); + } } + } + + if Some(current_epoch) + >= self.spec.eip4844_fork_epoch.map(|eip4844_fork_epoch| { + eip4844_fork_epoch + *MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS + }) + { + let current_epoch_start_slot = current_epoch.start_slot(T::EthSpec::slots_per_epoch()); // Update db's metadata for blobs pruning. - if current_slot == current_epoch.start_slot(T::EthSpec::slots_per_epoch()) { + if current_slot == current_epoch_start_slot { if let Some(mut blob_info) = self.store.get_blob_info() { - let next_epoch_to_prune = - blob_info.last_pruned_epoch + *MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS; - - if current_epoch > next_epoch_to_prune { - blob_info.data_availability_breakpoint = Some(block_root); + // Pruning enabled until data availability boundary. + if let Some(data_availability_boundary) = self.data_availability_boundary() { + blob_info.data_availability_boundary = self.state_root_at_slot( + data_availability_boundary.start_slot(T::EthSpec::slots_per_epoch()), + )?; self.store.compare_and_set_blob_info_with_write( self.store.get_blob_info(), Some(blob_info), @@ -3049,7 +3050,8 @@ impl BeaconChain { } } } - }; + } + let txn_lock = self.store.hot_db.begin_rw_transaction(); kv_store_ops.extend(self.store.convert_to_kv_batch(ops)?); diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index c5aef78aa..8932b503f 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -551,6 +551,14 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .takes_value(true) .default_value("true") ) + .arg( + Arg::with_name("prune-blobs") + .long("prune-blobs") + .help("Prune blobs from Lighthouse's database when they are older than the data \ + data availability boundary relative to the current head.") + .takes_value(true) + .default_value("true") + ) /* * Misc. diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index 1ce0f5f77..a435a42fd 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -411,6 +411,10 @@ pub fn get_config( client_config.store.prune_payloads = prune_payloads; } + if let Some(prune_blobs) = clap_utils::parse_optional(cli_args, "prune-blobs")? { + client_config.store.prune_blobs = prune_blobs; + } + /* * Zero-ports * diff --git a/beacon_node/store/src/errors.rs b/beacon_node/store/src/errors.rs index 6a22c888a..ac50cc6aa 100644 --- a/beacon_node/store/src/errors.rs +++ b/beacon_node/store/src/errors.rs @@ -20,7 +20,7 @@ pub enum Error { RlpError(String), BlockNotFound(Hash256), /// The blobs sidecar mapping to this block root is older than the data availability boundary. - BlobsTooOld(Hash256), + BlobsTooOld(Hash256, Slot), NoContinuationData, SplitPointModified(Slot, Slot), ConfigError(StoreConfigError), diff --git a/beacon_node/store/src/hot_cold_store.rs b/beacon_node/store/src/hot_cold_store.rs index 6ed0d129d..83047b053 100644 --- a/beacon_node/store/src/hot_cold_store.rs +++ b/beacon_node/store/src/hot_cold_store.rs @@ -1705,7 +1705,7 @@ impl, Cold: ItemStore> HotColdDB let data_availability_breakpoint: Hash256; - match blob_info.data_availability_breakpoint { + match blob_info.data_availability_boundary { Some(breakpoint) => { if breakpoint == blob_info.oldest_blob_parent { return Ok(()); diff --git a/beacon_node/store/src/metadata.rs b/beacon_node/store/src/metadata.rs index 3757940c2..89cf80976 100644 --- a/beacon_node/store/src/metadata.rs +++ b/beacon_node/store/src/metadata.rs @@ -125,7 +125,7 @@ pub struct BlobInfo { /// The latest epoch that blobs were pruned. pub last_pruned_epoch: Epoch, /// The block root of the next blobs to prune from. - pub data_availability_breakpoint: Option, + pub data_availability_boundary: Option, /// The block root of the next blob that needs to be added to fill in the history. pub oldest_blob_parent: Hash256, /// The slot before which blobs are available. diff --git a/lighthouse/tests/beacon_node.rs b/lighthouse/tests/beacon_node.rs index 7e581ee61..59f03064a 100644 --- a/lighthouse/tests/beacon_node.rs +++ b/lighthouse/tests/beacon_node.rs @@ -1341,6 +1341,19 @@ fn prune_payloads_on_startup_false() { .with_config(|config| assert!(!config.store.prune_payloads)); } #[test] +fn prune_blobs_default() { + CommandLineTest::new() + .run_with_zero_port() + .with_config(|config| assert!(config.store.prune_blobs)); +} +#[test] +fn prune_blobs_on_startup_false() { + CommandLineTest::new() + .flag("prune-blobs", Some("false")) + .run_with_zero_port() + .with_config(|config| assert!(!config.store.prune_blobs)); +} +#[test] fn reconstruct_historic_states_flag() { CommandLineTest::new() .flag("reconstruct-historic-states", None)