diff --git a/bin/citrea/src/rollup/mod.rs b/bin/citrea/src/rollup/mod.rs index ce328412f0..044dd8ea4d 100644 --- a/bin/citrea/src/rollup/mod.rs +++ b/bin/citrea/src/rollup/mod.rs @@ -14,6 +14,10 @@ use sov_db::ledger_db::migrations::LedgerDBMigrator; use sov_db::ledger_db::{LedgerDB, SharedLedgerOps}; use sov_db::mmr_db::MmrDB; use sov_db::rocks_db_config::RocksdbConfig; +use sov_db::schema::tables::{ + BATCH_PROVER_LEDGER_TABLES, FULL_NODE_LEDGER_TABLES, LIGHT_CLIENT_PROVER_LEDGER_TABLES, + SEQUENCER_LEDGER_TABLES, +}; use sov_db::schema::types::SoftConfirmationNumber; use sov_modules_api::Spec; use sov_modules_rollup_blueprint::RollupBlueprint; @@ -66,12 +70,21 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { rollup_config.storage.path.as_path(), citrea_sequencer::db_migrations::migrations(), ); - migrator.migrate(rollup_config.storage.db_max_open_files)?; + + let sequencer_tables = SEQUENCER_LEDGER_TABLES + .iter() + .map(|table| table.to_string()) + .collect::>(); + + migrator.migrate( + rollup_config.storage.db_max_open_files, + sequencer_tables.clone(), + )?; let rocksdb_config = RocksdbConfig::new( rollup_config.storage.path.as_path(), rollup_config.storage.db_max_open_files, - None, + Some(sequencer_tables), ); let ledger_db = self.create_ledger_db(&rocksdb_config); let genesis_config = self.create_genesis_config(runtime_genesis_paths, &rollup_config)?; @@ -188,12 +201,20 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { citrea_fullnode::db_migrations::migrations(), ); - migrator.migrate(rollup_config.storage.db_max_open_files)?; + let full_node_tables = FULL_NODE_LEDGER_TABLES + .iter() + .map(|table| table.to_string()) + .collect::>(); + + migrator.migrate( + rollup_config.storage.db_max_open_files, + full_node_tables.clone(), + )?; let rocksdb_config = RocksdbConfig::new( rollup_config.storage.path.as_path(), rollup_config.storage.db_max_open_files, - None, + Some(full_node_tables), ); let ledger_db = self.create_ledger_db(&rocksdb_config); @@ -315,12 +336,21 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { rollup_config.storage.path.as_path(), citrea_batch_prover::db_migrations::migrations(), ); - migrator.migrate(rollup_config.storage.db_max_open_files)?; + + let batch_prover_tables = BATCH_PROVER_LEDGER_TABLES + .iter() + .map(|table| table.to_string()) + .collect::>(); + + migrator.migrate( + rollup_config.storage.db_max_open_files, + batch_prover_tables.clone(), + )?; let rocksdb_config = RocksdbConfig::new( rollup_config.storage.path.as_path(), rollup_config.storage.db_max_open_files, - None, + Some(batch_prover_tables), ); let ledger_db = self.create_ledger_db(&rocksdb_config); @@ -437,7 +467,16 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { rollup_config.storage.path.as_path(), citrea_light_client_prover::db_migrations::migrations(), ); - migrator.migrate(rollup_config.storage.db_max_open_files)?; + + let light_client_prover_tables = LIGHT_CLIENT_PROVER_LEDGER_TABLES + .iter() + .map(|table| table.to_string()) + .collect::>(); + + migrator.migrate( + rollup_config.storage.db_max_open_files, + light_client_prover_tables.clone(), + )?; let mut task_manager = TaskManager::default(); let da_service = self @@ -447,7 +486,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { let rocksdb_config = RocksdbConfig::new( rollup_config.storage.path.as_path(), rollup_config.storage.db_max_open_files, - None, + Some(light_client_prover_tables), ); let ledger_db = self.create_ledger_db(&rocksdb_config); let mmr_db = MmrDB::new(&rocksdb_config)?; diff --git a/bin/citrea/tests/e2e/sequencer_replacement.rs b/bin/citrea/tests/e2e/sequencer_replacement.rs index 70cbc4aca4..1ea0c1d741 100644 --- a/bin/citrea/tests/e2e/sequencer_replacement.rs +++ b/bin/citrea/tests/e2e/sequencer_replacement.rs @@ -13,6 +13,7 @@ use reth_primitives::BlockNumberOrTag; use sov_db::ledger_db::migrations::copy_db_dir_recursive; use sov_db::ledger_db::{LedgerDB, SequencerLedgerOps}; use sov_db::rocks_db_config::RocksdbConfig; +use sov_db::schema::tables::SEQUENCER_LEDGER_TABLES; use sov_mock_da::{MockAddress, MockDaService}; use tokio::time::sleep; @@ -246,9 +247,18 @@ async fn test_sequencer_crash_restore_mempool() -> Result<(), anyhow::Error> { &sequencer_db_dir, &storage_dir.path().join("sequencer_unlocked"), ); + + let sequencer_tables = SEQUENCER_LEDGER_TABLES + .iter() + .map(|x| x.to_string()) + .collect::>(); let sequencer_db_dir = storage_dir.path().join("sequencer_unlocked").to_path_buf(); - let ledger_db = - LedgerDB::with_config(&RocksdbConfig::new(sequencer_db_dir.as_path(), None, None)).unwrap(); + let ledger_db = LedgerDB::with_config(&RocksdbConfig::new( + sequencer_db_dir.as_path(), + None, + Some(sequencer_tables.clone()), + )) + .unwrap(); let txs = ledger_db.get_mempool_txs().unwrap(); assert_eq!(txs.len(), 2); assert_eq!(txs[1].0, tx_hash.to_vec()); @@ -333,8 +343,12 @@ async fn test_sequencer_crash_restore_mempool() -> Result<(), anyhow::Error> { &storage_dir.path().join("sequencer_unlocked"), ); let sequencer_db_dir = storage_dir.path().join("sequencer_unlocked").to_path_buf(); - let ledger_db = - LedgerDB::with_config(&RocksdbConfig::new(sequencer_db_dir.as_path(), None, None)).unwrap(); + let ledger_db = LedgerDB::with_config(&RocksdbConfig::new( + sequencer_db_dir.as_path(), + None, + Some(sequencer_tables), + )) + .unwrap(); let txs = ledger_db.get_mempool_txs().unwrap(); // should be removed from db assert_eq!(txs.len(), 0); diff --git a/crates/batch-prover/src/db_migrations/mod.rs b/crates/batch-prover/src/db_migrations/mod.rs index 3e87e7180c..6521b44db0 100644 --- a/crates/batch-prover/src/db_migrations/mod.rs +++ b/crates/batch-prover/src/db_migrations/mod.rs @@ -3,9 +3,11 @@ use std::sync::OnceLock; use sov_db::ledger_db::migrations::LedgerMigration; use crate::db_migrations::batch_and_slot_by_number::MigrateBatchAndSlotByNumber; +use crate::db_migrations::remove_unused_common_tables::RemoveUnusedTables; use crate::db_migrations::verified_proofs::MigrateVerifiedProofsBySlotNumber; mod batch_and_slot_by_number; +mod remove_unused_common_tables; mod verified_proofs; pub fn migrations() -> &'static Vec> { @@ -15,6 +17,7 @@ pub fn migrations() -> &'static Vec (MigrationName, MigrationVersion) { + ("RemoveUnusedTables".to_owned(), 3) + } + + fn execute( + &self, + ledger_db: Arc, + tables_to_drop: &mut Vec, + ) -> anyhow::Result<()> { + // Get difference of LEDGER_TABLES and SEQUENCER_LEDGER_TABLES and drop them + let mut diff = LEDGER_TABLES.to_vec(); + diff.retain(|x| !BATCH_PROVER_LEDGER_TABLES.contains(x)); + let diff_tables = diff.iter().map(|x| x.to_string()).collect::>(); + for table in diff_tables { + // Check if table exists in the database + if ledger_db.get_cf_handle(&table).is_ok() { + tables_to_drop.push(table); + } + } + Ok(()) + } +} diff --git a/crates/fullnode/src/db_migrations/mod.rs b/crates/fullnode/src/db_migrations/mod.rs index 3e87e7180c..6521b44db0 100644 --- a/crates/fullnode/src/db_migrations/mod.rs +++ b/crates/fullnode/src/db_migrations/mod.rs @@ -3,9 +3,11 @@ use std::sync::OnceLock; use sov_db::ledger_db::migrations::LedgerMigration; use crate::db_migrations::batch_and_slot_by_number::MigrateBatchAndSlotByNumber; +use crate::db_migrations::remove_unused_common_tables::RemoveUnusedTables; use crate::db_migrations::verified_proofs::MigrateVerifiedProofsBySlotNumber; mod batch_and_slot_by_number; +mod remove_unused_common_tables; mod verified_proofs; pub fn migrations() -> &'static Vec> { @@ -15,6 +17,7 @@ pub fn migrations() -> &'static Vec (MigrationName, MigrationVersion) { + ("RemoveUnusedTables".to_owned(), 3) + } + + fn execute( + &self, + ledger_db: Arc, + tables_to_drop: &mut Vec, + ) -> anyhow::Result<()> { + // Get difference of LEDGER_TABLES and SEQUENCER_LEDGER_TABLES and drop them + let mut diff = LEDGER_TABLES.to_vec(); + diff.retain(|x| !FULL_NODE_LEDGER_TABLES.contains(x)); + let diff_tables = diff.iter().map(|x| x.to_string()).collect::>(); + for table in diff_tables { + // Check if table exists in the database + if ledger_db.get_cf_handle(&table).is_ok() { + tables_to_drop.push(table); + } + } + Ok(()) + } +} diff --git a/crates/light-client-prover/src/db_migrations/mod.rs b/crates/light-client-prover/src/db_migrations/mod.rs index 847f6306f6..59138069ad 100644 --- a/crates/light-client-prover/src/db_migrations/mod.rs +++ b/crates/light-client-prover/src/db_migrations/mod.rs @@ -2,8 +2,12 @@ use std::sync::OnceLock; use sov_db::ledger_db::migrations::LedgerMigration; +mod remove_unused_common_tables; + +use remove_unused_common_tables::RemoveUnusedTables; + pub fn migrations() -> &'static Vec> { static MIGRATIONS: OnceLock>> = OnceLock::new(); - MIGRATIONS.get_or_init(Vec::new) + MIGRATIONS.get_or_init(|| vec![Box::new(RemoveUnusedTables {})]) } diff --git a/crates/light-client-prover/src/db_migrations/remove_unused_common_tables.rs b/crates/light-client-prover/src/db_migrations/remove_unused_common_tables.rs new file mode 100644 index 0000000000..9143a7a2f5 --- /dev/null +++ b/crates/light-client-prover/src/db_migrations/remove_unused_common_tables.rs @@ -0,0 +1,33 @@ +use std::sync::Arc; + +use sov_db::ledger_db::migrations::{LedgerMigration, MigrationName, MigrationVersion}; +use sov_db::ledger_db::LedgerDB; +use sov_db::schema::tables::{LEDGER_TABLES, LIGHT_CLIENT_PROVER_LEDGER_TABLES}; + +/// Table removal migration +/// tables BatchByNumber and SlotByNumber are removed +pub(crate) struct RemoveUnusedTables {} + +impl LedgerMigration for RemoveUnusedTables { + fn identifier(&self) -> (MigrationName, MigrationVersion) { + ("RemoveUnusedTables".to_owned(), 3) + } + + fn execute( + &self, + ledger_db: Arc, + tables_to_drop: &mut Vec, + ) -> anyhow::Result<()> { + // Get difference of LEDGER_TABLES and SEQUENCER_LEDGER_TABLES and drop them + let mut diff = LEDGER_TABLES.to_vec(); + diff.retain(|x| !LIGHT_CLIENT_PROVER_LEDGER_TABLES.contains(x)); + let diff_tables = diff.iter().map(|x| x.to_string()).collect::>(); + for table in diff_tables { + // Check if table exists in the database + if ledger_db.get_cf_handle(&table).is_ok() { + tables_to_drop.push(table); + } + } + Ok(()) + } +} diff --git a/crates/sequencer/src/db_migrations/mod.rs b/crates/sequencer/src/db_migrations/mod.rs index 3e87e7180c..6521b44db0 100644 --- a/crates/sequencer/src/db_migrations/mod.rs +++ b/crates/sequencer/src/db_migrations/mod.rs @@ -3,9 +3,11 @@ use std::sync::OnceLock; use sov_db::ledger_db::migrations::LedgerMigration; use crate::db_migrations::batch_and_slot_by_number::MigrateBatchAndSlotByNumber; +use crate::db_migrations::remove_unused_common_tables::RemoveUnusedTables; use crate::db_migrations::verified_proofs::MigrateVerifiedProofsBySlotNumber; mod batch_and_slot_by_number; +mod remove_unused_common_tables; mod verified_proofs; pub fn migrations() -> &'static Vec> { @@ -15,6 +17,7 @@ pub fn migrations() -> &'static Vec (MigrationName, MigrationVersion) { + ("RemoveUnusedTables".to_owned(), 3) + } + + fn execute( + &self, + ledger_db: Arc, + tables_to_drop: &mut Vec, + ) -> anyhow::Result<()> { + // Get difference of LEDGER_TABLES and SEQUENCER_LEDGER_TABLES and drop them + let mut diff = LEDGER_TABLES.to_vec(); + diff.retain(|x| !SEQUENCER_LEDGER_TABLES.contains(x)); + let diff_tables = diff.iter().map(|x| x.to_string()).collect::>(); + for table in diff_tables { + // Check if table exists in the database + if ledger_db.get_cf_handle(&table).is_ok() { + tables_to_drop.push(table); + } + } + Ok(()) + } +} diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/migrations/mod.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/migrations/mod.rs index dfa6e32409..ef1773819b 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/migrations/mod.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/migrations/mod.rs @@ -10,7 +10,6 @@ use super::migrations::utils::{drop_column_families, list_column_families}; use super::LedgerDB; use crate::ledger_db::{SharedLedgerOps, LEDGER_DB_PATH_SUFFIX}; use crate::rocks_db_config::RocksdbConfig; -use crate::schema::tables::LEDGER_TABLES; /// Utilities for ledger db migrations pub mod utils; @@ -56,7 +55,11 @@ impl<'a> LedgerDBMigrator<'a> { } /// Run migrations - pub fn migrate(&self, max_open_files: Option) -> anyhow::Result<()> { + pub fn migrate( + &self, + max_open_files: Option, + node_column_families: Vec, + ) -> anyhow::Result<()> { if self.migrations.is_empty() { return Ok(()); } @@ -66,8 +69,11 @@ impl<'a> LedgerDBMigrator<'a> { if !dbs_path.join(LEDGER_DB_PATH_SUFFIX).exists() { // If this is the first time the ledger db is being created, then we don't need to run migrations // all migrations up to this point are considered successful - let ledger_db = - LedgerDB::with_config(&RocksdbConfig::new(self.ledger_path, max_open_files, None))?; + let ledger_db = LedgerDB::with_config(&RocksdbConfig::new( + self.ledger_path, + max_open_files, + Some(node_column_families), + ))?; for migration in self.migrations.iter() { ledger_db @@ -86,7 +92,8 @@ impl<'a> LedgerDBMigrator<'a> { let column_families_in_db = list_column_families(self.ledger_path); - let all_column_families = merge_column_families(column_families_in_db); + let all_column_families = + merge_column_families(column_families_in_db, node_column_families); let ledger_db = LedgerDB::with_config(&RocksdbConfig::new( self.ledger_path, @@ -221,10 +228,13 @@ pub fn copy_db_dir_recursive(src: &Path, dst: &Path) -> std::io::Result<()> { Ok(()) } -fn merge_column_families(column_families_in_db: Vec) -> Vec { - let column_families: HashSet = LEDGER_TABLES +fn merge_column_families( + column_families_in_db: Vec, + node_column_families: Vec, +) -> Vec { + let column_families: HashSet = node_column_families .iter() - .map(|&table_name| table_name.to_string()) + .map(|table_name| table_name.to_string()) .chain(column_families_in_db) .collect(); column_families.into_iter().collect() diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/tests.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/tests.rs index ed7e40a6a3..82f6fef0d3 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/tests.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/tests.rs @@ -7,7 +7,7 @@ use super::migrations::{LedgerDBMigrator, LedgerMigration, MigrationName, Migrat use super::LedgerDB; use crate::ledger_db::{SharedLedgerOps, TestLedgerOps}; use crate::rocks_db_config::RocksdbConfig; -use crate::schema::tables::TestTableOld; +use crate::schema::tables::{TestTableOld, LEDGER_TABLES}; pub fn successful_migrations() -> &'static Vec> { static MIGRATIONS: OnceLock>> = @@ -77,7 +77,12 @@ fn test_successful_migrations() { // Run migrations let ledger_db_migrator = LedgerDBMigrator::new(ledger_db_path.path(), successful_migrations()); - assert!(matches!(ledger_db_migrator.migrate(None), Ok(()))); + let ledger_tables = LEDGER_TABLES.iter().map(|x| x.to_string()).collect(); + + assert!(matches!( + ledger_db_migrator.migrate(None, ledger_tables), + Ok(()) + )); // This instance is post-migrations DB. let ledger_db = @@ -121,7 +126,8 @@ fn test_failed_migrations() { // Run migrations let ledger_db_migrator = LedgerDBMigrator::new(ledger_db_path.path(), failed_migrations()); - assert!(ledger_db_migrator.migrate(None).is_err()); + let ledger_tables = LEDGER_TABLES.iter().map(|x| x.to_string()).collect(); + assert!(ledger_db_migrator.migrate(None, ledger_tables).is_err()); let ledger_db = LedgerDB::with_config(&RocksdbConfig::new(ledger_db_path.path(), None, None)).unwrap(); diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs index 244ee4c37a..17a8aacde7 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs @@ -40,6 +40,89 @@ pub const STATE_TABLES: &[&str] = &[ JmtNodes::table_name(), ]; +/// A list of all tables used by Sequencer LedgerDB +pub const SEQUENCER_LEDGER_TABLES: &[&str] = &[ + ExecutedMigrations::table_name(), + SlotByHash::table_name(), + SoftConfirmationByNumber::table_name(), + SoftConfirmationByHash::table_name(), + L2RangeByL1Height::table_name(), + L2GenesisStateRoot::table_name(), + LastStateDiff::table_name(), + PendingSequencerCommitmentL2Range::table_name(), + LastSequencerCommitmentSent::table_name(), + SoftConfirmationStatus::table_name(), + CommitmentsByNumber::table_name(), + VerifiedBatchProofsBySlotNumber::table_name(), + ProverLastScannedSlot::table_name(), + MempoolTxs::table_name(), + LastPrunedBlock::table_name(), + #[cfg(test)] + TestTableOld::table_name(), + #[cfg(test)] + TestTableNew::table_name(), +]; + +/// A list of all tables used by FullNode LedgerDB +/// Also includes tables of Sequencer LedgerDB so that it can be used as a sequencer if needed +pub const FULL_NODE_LEDGER_TABLES: &[&str] = &[ + ExecutedMigrations::table_name(), + SlotByHash::table_name(), + SoftConfirmationByNumber::table_name(), + SoftConfirmationByHash::table_name(), + L2RangeByL1Height::table_name(), + L2GenesisStateRoot::table_name(), + LastStateDiff::table_name(), + PendingSequencerCommitmentL2Range::table_name(), + LastSequencerCommitmentSent::table_name(), + SoftConfirmationStatus::table_name(), + ProverLastScannedSlot::table_name(), + CommitmentsByNumber::table_name(), + MempoolTxs::table_name(), + LastPrunedBlock::table_name(), + VerifiedBatchProofsBySlotNumber::table_name(), + #[cfg(test)] + TestTableOld::table_name(), + #[cfg(test)] + TestTableNew::table_name(), +]; + +/// A list of all tables used by BatchProver LedgerDB +pub const BATCH_PROVER_LEDGER_TABLES: &[&str] = &[ + ExecutedMigrations::table_name(), + SlotByHash::table_name(), + SoftConfirmationByNumber::table_name(), + SoftConfirmationByHash::table_name(), + L2RangeByL1Height::table_name(), + L2Witness::table_name(), + L2GenesisStateRoot::table_name(), + ProverLastScannedSlot::table_name(), + SoftConfirmationStatus::table_name(), + CommitmentsByNumber::table_name(), + ProofsBySlotNumber::table_name(), + ProofsBySlotNumberV2::table_name(), + PendingProvingSessions::table_name(), + ProverStateDiffs::table_name(), + LastPrunedBlock::table_name(), + #[cfg(test)] + TestTableOld::table_name(), + #[cfg(test)] + TestTableNew::table_name(), +]; + +/// A list of all tables used by LightClientProver LedgerDB +pub const LIGHT_CLIENT_PROVER_LEDGER_TABLES: &[&str] = &[ + ExecutedMigrations::table_name(), + SlotByHash::table_name(), + LightClientProofBySlotNumber::table_name(), + ProverLastScannedSlot::table_name(), + SoftConfirmationByNumber::table_name(), + #[cfg(test)] + TestTableOld::table_name(), + #[cfg(test)] + TestTableNew::table_name(), +]; + /// A list of all tables used by the LedgerDB. These tables store rollup "history" - meaning /// transaction, events, receipts, etc. pub const LEDGER_TABLES: &[&str] = &[ diff --git a/resources/configs/mock/light_client_prover_config.toml b/resources/configs/mock/light_client_prover_config.toml index 3428aac35d..183ceba2e6 100644 --- a/resources/configs/mock/light_client_prover_config.toml +++ b/resources/configs/mock/light_client_prover_config.toml @@ -1,3 +1,4 @@ +initial_da_height = 1 proving_mode = "execute" proof_sampling_number = 500 enable_recovery = true