forked from sigp/lighthouse
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
340 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
beacon_node/beacon_chain/src/schema_change/migration_schema_v23.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
use crate::beacon_chain::BeaconChainTypes; | ||
use crate::validator_pubkey_cache::DatabasePubkey; | ||
use slog::{info, Logger}; | ||
use ssz::{Decode, Encode}; | ||
use std::{ | ||
sync::Arc, | ||
time::{Duration, Instant}, | ||
}; | ||
use store::{ | ||
get_key_for_col, hdiff::StorageStrategy, hot_cold_store::StorageStrategyHot, DBColumn, Error, | ||
HotColdDB, HotStateSummary, KeyValueStore, KeyValueStoreOp, StoreItem, | ||
}; | ||
use types::{Hash256, PublicKey, Slot}; | ||
|
||
const LOG_EVERY: usize = 200_000; | ||
|
||
#[derive(Debug, Clone, Copy, Encode, Decode)] | ||
pub struct HotStateSummaryV22 { | ||
slot: Slot, | ||
latest_block_root: Hash256, | ||
epoch_boundary_state_root: Hash256, | ||
} | ||
|
||
pub fn upgrade_to_v23<T: BeaconChainTypes>( | ||
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>, | ||
log: Logger, | ||
) -> Result<Vec<KeyValueStoreOp>, Error> { | ||
info!(log, "Upgrading from v22 to v23"); | ||
|
||
// Upgrade all hot DB state summaries to the new type: | ||
// - Set all summaries of boundary states as `Snapshot` type | ||
// - Set all others are `Replay` pointing to `epoch_boundary_state_root` | ||
|
||
let mut other_ops = vec![]; | ||
let mut store_diff_ops = vec![]; | ||
let mut diffs_written = 0; | ||
let mut last_log_time = Instant::now(); | ||
|
||
// Iterate through all pubkeys and decompress them. | ||
for (i, res) in db | ||
.hot_db | ||
.iter_column::<Hash256>(DBColumn::BeaconStateSummary) | ||
.enumerate() | ||
{ | ||
let (key, value) = res?; | ||
let state_root: Hash256 = key.into(); | ||
let summary = HotStateSummaryV22::from_ssz_bytes(&value)?; | ||
let storage_strategy = if summary.slot % T::EthSpec::slots_per_epoch() == 0 { | ||
// boundary state | ||
// - Read state from DB | ||
// - Compute diff | ||
// - Commit immediately in separate diff column | ||
// - Schedule state deletion as part of atomic ops | ||
let state = get_full_state(&self.hot_db, &state_root, &self.spec)? | ||
.ok_or(HotColdDBError::MissingEpochBoundaryState(state_root))?; | ||
|
||
let storage_strategy = match self.hierarchy_hot.storage_strategy(slot)? { | ||
StorageStrategy::ReplayFrom(from) => { | ||
let from_root = *state | ||
.get_state_root(from_slot) | ||
.map_err(HotColdDBError::HotStateSummaryError)?; | ||
StorageStrategyHot::ReplayFrom(from_root) | ||
} | ||
StorageStrategy::Snapshot => StorageStrategyHot::Snapshot(0), | ||
StorageStrategy::DiffFrom(from) => { | ||
// Compute and store diff, and delete the state | ||
|
||
// TOOD: Find a cleaner way to de-duplicate the code to compute diffs on | ||
// migration | ||
// TODO: Ensure that the other of diffs is optimal, i.e. follow topological | ||
// order to not re-compute intermediary values | ||
db.store_hot_state_separate_ops( | ||
&state_root, | ||
state, | ||
&mut vec![], | ||
&mut store_diff_ops, | ||
)?; | ||
|
||
let from_root = *state | ||
.get_state_root(from_slot) | ||
.map_err(HotColdDBError::HotStateSummaryError)?; | ||
StorageStrategyHot::DiffFrom(from_root) | ||
} | ||
}; | ||
|
||
let should_delete_state = match storage_strategy { | ||
StorageStrategyHot::ReplayFrom(_) => true, // State no longer needed, we will replay | ||
StorageStrategyHot::Snapshot(_) => false, // Keep state, need for snapshot | ||
StorageStrategyHot::DiffFrom(_) => true, // State no longer needed, we will diff | ||
}; | ||
|
||
if should_delete_state { | ||
// Note: Do not delete the BeaconStateSummary as this will be over-written below | ||
// TODO: Should also delete the temporary flag? | ||
let state_key = | ||
get_key_for_col(DBColumn::BeaconState.into(), state_root.as_slice()); | ||
other_ops.push(KeyValueStoreOp::DeleteKey(state_key)); | ||
} | ||
|
||
storage_strategy | ||
} else { | ||
// TODO: Clip to anchor / finalized, if not aligned | ||
StorageStrategyHot::ReplayFrom(summary.epoch_boundary_state_root) | ||
}; | ||
|
||
let new_summary = HotStateSummary { | ||
slot: summary.slot, | ||
latest_block_root: summary.latest_block_root, | ||
storage_strategy, | ||
}; | ||
ops.push(new_summary.as_kv_store_op(key)); | ||
|
||
if last_log_time.elapsed() > Duration::from_secs(5) { | ||
last_log_time = Instant::now(); | ||
|
||
diffs_written += store_diff_ops.len(); | ||
// Commit diff ops once in a while to not blow up memory | ||
// Commit diff ops before deleting states to not lose data. | ||
db.hot_db.do_atomically(store_diff_ops)?; | ||
store_diff_ops = vec![]; | ||
|
||
// TODO: Display the slot distance between head and finalized, and head-tracker count | ||
info!( | ||
log, | ||
"Hot state migration in progress"; | ||
"summaries_migrated" => i, | ||
"diff_written" => diffs_written | ||
); | ||
} | ||
} | ||
|
||
// TODO: Should run hot DB compaction after deleting potentially a lot of states. Or should wait | ||
// for the next finality event? | ||
info!(log, "Hot state migration complete"); | ||
|
||
Ok(ops) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.