Skip to content

Commit 8c9a1b2

Browse files
committed
Implement db schema upgrade and downgrade
1 parent 8c15bab commit 8c9a1b2

File tree

7 files changed

+163
-31
lines changed

7 files changed

+163
-31
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use crate::observed_block_producers::ObservedBlockProducers;
5656
use crate::observed_data_sidecars::ObservedDataSidecars;
5757
use crate::observed_operations::{ObservationOutcome, ObservedOperations};
5858
use crate::observed_slashable::ObservedSlashable;
59-
use crate::persisted_beacon_chain::{PersistedBeaconChain, DUMMY_CANONICAL_HEAD_BLOCK_ROOT};
59+
use crate::persisted_beacon_chain::PersistedBeaconChain;
6060
use crate::persisted_fork_choice::PersistedForkChoice;
6161
use crate::pre_finalization_cache::PreFinalizationBlockCache;
6262
use crate::shuffling_cache::{BlockShufflingIds, ShufflingCache};
@@ -627,11 +627,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
627627

628628
/// Return a `PersistedBeaconChain` without reference to a `BeaconChain`.
629629
pub fn make_persisted_head(genesis_block_root: Hash256) -> PersistedBeaconChain {
630-
PersistedBeaconChain {
631-
_canonical_head_block_root: DUMMY_CANONICAL_HEAD_BLOCK_ROOT,
632-
genesis_block_root,
633-
ssz_head_tracker: <_>::default(),
634-
}
630+
PersistedBeaconChain { genesis_block_root }
635631
}
636632

637633
/// Return a database operation for writing the beacon chain head to disk.

beacon_node/beacon_chain/src/persisted_beacon_chain.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,11 @@
11
use ssz::{Decode, Encode};
22
use ssz_derive::{Decode, Encode};
33
use store::{DBColumn, Error as StoreError, StoreItem};
4-
use types::{Hash256, Slot};
5-
6-
/// Dummy value to use for the canonical head block root, see below.
7-
pub const DUMMY_CANONICAL_HEAD_BLOCK_ROOT: Hash256 = Hash256::repeat_byte(0xff);
4+
use types::Hash256;
85

96
#[derive(Clone, Encode, Decode)]
107
pub struct PersistedBeaconChain {
11-
/// This value is ignored to resolve the issue described here:
12-
///
13-
/// https://github.com/sigp/lighthouse/pull/1639
14-
///
15-
/// Its removal is tracked here:
16-
///
17-
/// https://github.com/sigp/lighthouse/issues/1784
18-
pub _canonical_head_block_root: Hash256,
198
pub genesis_block_root: Hash256,
20-
/// DEPRECATED
21-
pub ssz_head_tracker: SszHeadTracker,
22-
}
23-
24-
/// DEPRECATED
25-
#[derive(Encode, Decode, Clone, Default)]
26-
pub struct SszHeadTracker {
27-
roots: Vec<Hash256>,
28-
slots: Vec<Slot>,
299
}
3010

3111
impl StoreItem for PersistedBeaconChain {

beacon_node/beacon_chain/src/schema_change.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
mod migration_schema_v20;
33
mod migration_schema_v21;
44
mod migration_schema_v22;
5+
mod migration_schema_v23;
56

67
use crate::beacon_chain::BeaconChainTypes;
78
use slog::Logger;
@@ -59,6 +60,14 @@ pub fn migrate_schema<T: BeaconChainTypes>(
5960
// bumped inside the upgrade_to_v22 fn
6061
migration_schema_v22::upgrade_to_v22::<T>(db.clone(), genesis_state_root, log)
6162
}
63+
(SchemaVersion(22), SchemaVersion(23)) => {
64+
let ops = migration_schema_v23::upgrade_to_v23::<T>(db.clone(), log)?;
65+
db.store_schema_version_atomically(to, ops)
66+
}
67+
(SchemaVersion(23), SchemaVersion(22)) => {
68+
let ops = migration_schema_v23::downgrade_from_v23::<T>(db.clone(), log)?;
69+
db.store_schema_version_atomically(to, ops)
70+
}
6271
// Anything else is an error.
6372
(_, _) => Err(HotColdDBError::UnsupportedSchemaVersion {
6473
target_version: to,
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
use crate::beacon_chain::BeaconChainTypes;
2+
use crate::persisted_fork_choice::PersistedForkChoice;
3+
use crate::schema_change::StoreError;
4+
use crate::test_utils::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY, FORK_CHOICE_DB_KEY};
5+
use crate::BeaconForkChoiceStore;
6+
use fork_choice::{ForkChoice, ResetPayloadStatuses};
7+
use slog::Logger;
8+
use ssz::{Decode, Encode};
9+
use ssz_derive::{Decode, Encode};
10+
use std::sync::Arc;
11+
use store::{DBColumn, Error, HotColdDB, KeyValueStoreOp, StoreItem};
12+
use types::{Hash256, Slot};
13+
14+
/// Dummy value to use for the canonical head block root, see below.
15+
pub const DUMMY_CANONICAL_HEAD_BLOCK_ROOT: Hash256 = Hash256::repeat_byte(0xff);
16+
17+
pub fn upgrade_to_v23<T: BeaconChainTypes>(
18+
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
19+
_log: Logger,
20+
) -> Result<Vec<KeyValueStoreOp>, Error> {
21+
// Set the head-tracker to empty
22+
23+
let Some(persisted_beacon_chain_v22) =
24+
db.get_item::<PersistedBeaconChainV22>(&BEACON_CHAIN_DB_KEY)?
25+
else {
26+
// If there is no persisted beacon chain, ignore the upgrade
27+
return Ok(vec![]);
28+
};
29+
30+
let persisted_beacon_chain = PersistedBeaconChain {
31+
genesis_block_root: persisted_beacon_chain_v22.genesis_block_root,
32+
};
33+
34+
db.put_item::<PersistedBeaconChain>(&BEACON_CHAIN_DB_KEY, &persisted_beacon_chain)?;
35+
36+
todo!();
37+
}
38+
39+
pub fn downgrade_from_v23<T: BeaconChainTypes>(
40+
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
41+
log: Logger,
42+
) -> Result<Vec<KeyValueStoreOp>, Error> {
43+
// recreate head-tracker from the fork-choice
44+
45+
let Some(persisted_fork_choice) = db.get_item::<PersistedForkChoice>(&FORK_CHOICE_DB_KEY)?
46+
else {
47+
// Is it possible for the fork-choice to not exist on a downgrade?
48+
return Ok(vec![]);
49+
};
50+
51+
let Some(persisted_beacon_chain) = db.get_item::<PersistedBeaconChain>(&BEACON_CHAIN_DB_KEY)?
52+
else {
53+
// TODO: Is it possible for persisted beacon chain to be missing if the fork choice exists?
54+
return Ok(vec![]);
55+
};
56+
57+
let fc_store =
58+
BeaconForkChoiceStore::from_persisted(persisted_fork_choice.fork_choice_store, db.clone())
59+
.map_err(|e| {
60+
Error::MigrationError(format!(
61+
"Error loading fork choise store from persisted: {e:?}"
62+
))
63+
})?;
64+
65+
// TODO: what value to choose here?
66+
let reset_payload_statuses = ResetPayloadStatuses::OnlyWithInvalidPayload;
67+
let mut fork_choice = ForkChoice::from_persisted(
68+
persisted_fork_choice.fork_choice,
69+
reset_payload_statuses,
70+
fc_store,
71+
&db.spec,
72+
&log,
73+
)
74+
.map_err(|e| {
75+
Error::MigrationError(format!("Error loading fork choice from persisted: {e:?}"))
76+
})?;
77+
78+
// TODO: initialize clock
79+
let current_slot = Slot::new(0);
80+
let head_block_root = fork_choice
81+
.get_head(current_slot, &db.spec)
82+
.map_err(|e| Error::MigrationError(format!("Error computing get_head: {e:?}")))?;
83+
84+
let head_proto_block = fork_choice
85+
.get_block(&head_block_root)
86+
.ok_or(Error::MigrationError(format!(
87+
"HeadBlockMissingFromForkChoice({head_block_root:?})"
88+
)))?;
89+
90+
let heads = fork_choice
91+
.proto_array()
92+
.viable_heads::<T::EthSpec>(head_proto_block.slot);
93+
94+
let head_roots = heads.iter().map(|node| node.root).collect();
95+
let head_slots = heads.iter().map(|node| node.slot).collect();
96+
97+
let persisted_beacon_chain_v22 = PersistedBeaconChainV22 {
98+
_canonical_head_block_root: DUMMY_CANONICAL_HEAD_BLOCK_ROOT,
99+
genesis_block_root: persisted_beacon_chain.genesis_block_root,
100+
ssz_head_tracker: SszHeadTracker {
101+
roots: head_roots,
102+
slots: head_slots,
103+
},
104+
};
105+
106+
db.put_item::<PersistedBeaconChainV22>(&BEACON_CHAIN_DB_KEY, &persisted_beacon_chain_v22)?;
107+
108+
todo!();
109+
}
110+
111+
/// Helper struct that is used to encode/decode the state of the `HeadTracker` as SSZ bytes.
112+
///
113+
/// This is used when persisting the state of the `BeaconChain` to disk.
114+
#[derive(Encode, Decode, Clone)]
115+
pub struct SszHeadTracker {
116+
roots: Vec<Hash256>,
117+
slots: Vec<Slot>,
118+
}
119+
120+
#[derive(Clone, Encode, Decode)]
121+
pub struct PersistedBeaconChainV22 {
122+
/// This value is ignored to resolve the issue described here:
123+
///
124+
/// https://github.com/sigp/lighthouse/pull/1639
125+
///
126+
/// Its removal is tracked here:
127+
///
128+
/// https://github.com/sigp/lighthouse/issues/1784
129+
pub _canonical_head_block_root: Hash256,
130+
pub genesis_block_root: Hash256,
131+
/// DEPRECATED
132+
pub ssz_head_tracker: SszHeadTracker,
133+
}
134+
135+
impl StoreItem for PersistedBeaconChainV22 {
136+
fn db_column() -> DBColumn {
137+
DBColumn::BeaconChain
138+
}
139+
140+
fn as_store_bytes(&self) -> Vec<u8> {
141+
self.as_ssz_bytes()
142+
}
143+
144+
fn from_store_bytes(bytes: &[u8]) -> Result<Self, StoreError> {
145+
Self::from_ssz_bytes(bytes).map_err(Into::into)
146+
}
147+
}

beacon_node/store/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub enum Error {
2525
NoContinuationData,
2626
SplitPointModified(Slot, Slot),
2727
ConfigError(StoreConfigError),
28-
SchemaMigrationError(String),
28+
MigrationError(String),
2929
/// The store's `anchor_info` was mutated concurrently, the latest modification wasn't applied.
3030
AnchorInfoConcurrentMutation,
3131
/// The store's `blob_info` was mutated concurrently, the latest modification wasn't applied.

beacon_node/store/src/hot_cold_store.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use lru::LruCache;
2222
use parking_lot::{Mutex, RwLock};
2323
use safe_arith::SafeArith;
2424
use serde::{Deserialize, Serialize};
25-
use slog::{debug, error, info, trace, warn, Logger};
25+
use slog::{debug, error, info, warn, Logger};
2626
use ssz::{Decode, Encode};
2727
use ssz_derive::{Decode, Encode};
2828
use state_processing::{
@@ -80,7 +80,7 @@ pub struct HotColdDB<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> {
8080
/// HTTP API.
8181
historic_state_cache: Mutex<HistoricStateCache<E>>,
8282
/// Chain spec.
83-
pub(crate) spec: Arc<ChainSpec>,
83+
pub spec: Arc<ChainSpec>,
8484
/// Logger.
8585
pub log: Logger,
8686
/// Mere vessel for E.

beacon_node/store/src/metadata.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use ssz::{Decode, Encode};
44
use ssz_derive::{Decode, Encode};
55
use types::{Checkpoint, Hash256, Slot};
66

7-
pub const CURRENT_SCHEMA_VERSION: SchemaVersion = SchemaVersion(22);
7+
pub const CURRENT_SCHEMA_VERSION: SchemaVersion = SchemaVersion(23);
88

99
// All the keys that get stored under the `BeaconMeta` column.
1010
//

0 commit comments

Comments
 (0)