diff --git a/beacon_node/beacon_chain/src/schema_change.rs b/beacon_node/beacon_chain/src/schema_change.rs index ddc59783394..aa4925deb30 100644 --- a/beacon_node/beacon_chain/src/schema_change.rs +++ b/beacon_node/beacon_chain/src/schema_change.rs @@ -5,6 +5,7 @@ mod migration_schema_v25; mod migration_schema_v26; mod migration_schema_v27; mod migration_schema_v28; +mod migration_schema_v29; use crate::beacon_chain::BeaconChainTypes; use std::sync::Arc; @@ -88,6 +89,14 @@ pub fn migrate_schema( let ops = migration_schema_v28::downgrade_from_v28::(db.clone())?; db.store_schema_version_atomically(to, ops) } + (SchemaVersion(28), SchemaVersion(29)) => { + let ops = migration_schema_v29::upgrade_to_v29::(db.clone())?; + db.store_schema_version_atomically(to, ops) + } + (SchemaVersion(29), SchemaVersion(28)) => { + let ops = migration_schema_v29::downgrade_from_v29::(db.clone())?; + db.store_schema_version_atomically(to, ops) + } // Anything else is an error. (_, _) => Err(HotColdDBError::UnsupportedSchemaVersion { target_version: to, diff --git a/beacon_node/beacon_chain/src/schema_change/migration_schema_v29.rs b/beacon_node/beacon_chain/src/schema_change/migration_schema_v29.rs new file mode 100644 index 00000000000..6a8c6d78b53 --- /dev/null +++ b/beacon_node/beacon_chain/src/schema_change/migration_schema_v29.rs @@ -0,0 +1,21 @@ +use crate::BeaconChainTypes; +use std::sync::Arc; +use store::{Error, HotColdDB, KeyValueStoreOp}; + +pub fn upgrade_to_v29( + db: Arc>, +) -> Result, Error> { + db.upgrade()?; + Ok(vec![]) +} + +pub fn downgrade_from_v29( + db: Arc>, +) -> Result, Error> { + if db.is_redb() { + return Err(Error::MigrationError( + "Downgrade from v29 not supported for Redb".into(), + )); + } + Ok(vec![]) +} diff --git a/beacon_node/store/Cargo.toml b/beacon_node/store/Cargo.toml index 50028fe73ff..8eb80c48fad 100644 --- a/beacon_node/store/Cargo.toml +++ b/beacon_node/store/Cargo.toml @@ -23,7 +23,7 @@ lru = { workspace = true } metrics = { workspace = true } milhouse = { workspace = true } parking_lot = { workspace = true } -redb = { version = "2.1.3", optional = true } +redb = { version = "2.6.3", optional = true } safe_arith = { workspace = true } serde = { workspace = true } smallvec = { workspace = true } diff --git a/beacon_node/store/src/database/interface.rs b/beacon_node/store/src/database/interface.rs index 5646f1179c8..1cc940b4076 100644 --- a/beacon_node/store/src/database/interface.rs +++ b/beacon_node/store/src/database/interface.rs @@ -6,6 +6,7 @@ use crate::{ColumnIter, ColumnKeyIter, DBColumn, Error, ItemStore, Key, KeyValue use crate::{KeyValueStoreOp, StoreConfig, config::DatabaseBackend}; use std::collections::HashSet; use std::path::Path; +use tracing::info; use types::EthSpec; pub enum BeaconNodeBackend { @@ -169,6 +170,31 @@ impl KeyValueStore for BeaconNodeBackend { } } + fn upgrade(&self) -> Result<(), Error> { + match self { + #[cfg(feature = "leveldb")] + BeaconNodeBackend::LevelDb(_) => { + info!("LevelDB, no upgrade required"); + Ok(()) + } + #[cfg(feature = "redb")] + BeaconNodeBackend::Redb(redb) => { + info!("Updating Redb file format to v3"); + redb.upgrade()?; + Ok(()) + } + } + } + + fn is_redb(&self) -> bool { + match self { + #[cfg(feature = "leveldb")] + BeaconNodeBackend::LevelDb(_level_db) => false, + #[cfg(feature = "redb")] + BeaconNodeBackend::Redb(_redb) => true, + } + } + fn delete_if( &self, column: DBColumn, diff --git a/beacon_node/store/src/database/redb_impl.rs b/beacon_node/store/src/database/redb_impl.rs index 4077326ecaf..4403c54d8f9 100644 --- a/beacon_node/store/src/database/redb_impl.rs +++ b/beacon_node/store/src/database/redb_impl.rs @@ -41,6 +41,11 @@ impl Redb { }) } + pub fn upgrade(&self) -> Result<(), Error> { + self.db.write().upgrade()?; + Ok(()) + } + fn create_table(db: &redb::Database, table_name: &str) -> Result<(), Error> { let table_definition: TableDefinition<'_, &[u8], &[u8]> = TableDefinition::new(table_name); let tx = db.begin_write()?; diff --git a/beacon_node/store/src/errors.rs b/beacon_node/store/src/errors.rs index a07cc838863..a6b7110c05c 100644 --- a/beacon_node/store/src/errors.rs +++ b/beacon_node/store/src/errors.rs @@ -63,6 +63,8 @@ pub enum Error { LevelDbError(LevelDBError), #[cfg(feature = "redb")] RedbError(Box), + #[cfg(feature = "redb")] + RedbUpgrade(redb::UpgradeError), CacheBuildError(EpochCacheError), RandaoMixOutOfBounds, MilhouseError(milhouse::Error), @@ -233,6 +235,13 @@ impl From for Error { } } +#[cfg(feature = "redb")] +impl From for Error { + fn from(e: redb::UpgradeError) -> Self { + Error::RedbUpgrade(e) + } +} + impl From for Error { fn from(e: EpochCacheError) -> Error { Error::CacheBuildError(e) diff --git a/beacon_node/store/src/hot_cold_store.rs b/beacon_node/store/src/hot_cold_store.rs index 6e165702a27..3816f509259 100644 --- a/beacon_node/store/src/hot_cold_store.rs +++ b/beacon_node/store/src/hot_cold_store.rs @@ -473,6 +473,16 @@ impl, Cold: ItemStore> HotColdDB } } + pub fn upgrade(&self) -> Result<(), Error> { + self.hot_db.upgrade()?; + self.cold_db.upgrade()?; + Ok(()) + } + + pub fn is_redb(&self) -> bool { + self.hot_db.is_redb() + } + pub fn update_finalized_state( &self, state_root: Hash256, diff --git a/beacon_node/store/src/lib.rs b/beacon_node/store/src/lib.rs index ee9cfce0ecc..ba6d1db8a7f 100644 --- a/beacon_node/store/src/lib.rs +++ b/beacon_node/store/src/lib.rs @@ -103,6 +103,10 @@ pub trait KeyValueStore: Sync + Send + Sized + 'static { fn delete_batch(&self, column: DBColumn, ops: HashSet<&[u8]>) -> Result<(), Error>; + // TODO(migration-v29) can delete these functions once db migration v29 is deprecated + fn upgrade(&self) -> Result<(), Error>; + fn is_redb(&self) -> bool; + fn delete_if( &self, column: DBColumn, diff --git a/beacon_node/store/src/memory_store.rs b/beacon_node/store/src/memory_store.rs index 6baef61c9d8..98ce2892a1f 100644 --- a/beacon_node/store/src/memory_store.rs +++ b/beacon_node/store/src/memory_store.rs @@ -146,6 +146,14 @@ impl KeyValueStore for MemoryStore { }); Ok(()) } + + fn upgrade(&self) -> Result<(), Error> { + Ok(()) + } + + fn is_redb(&self) -> bool { + false + } } impl ItemStore for MemoryStore {} diff --git a/beacon_node/store/src/metadata.rs b/beacon_node/store/src/metadata.rs index cf494684515..215cdb2b64d 100644 --- a/beacon_node/store/src/metadata.rs +++ b/beacon_node/store/src/metadata.rs @@ -4,7 +4,7 @@ use ssz::{Decode, Encode}; use ssz_derive::{Decode, Encode}; use types::{Hash256, Slot}; -pub const CURRENT_SCHEMA_VERSION: SchemaVersion = SchemaVersion(28); +pub const CURRENT_SCHEMA_VERSION: SchemaVersion = SchemaVersion(29); // All the keys that get stored under the `BeaconMeta` column. //