Skip to content

Commit

Permalink
change(state): Allow opening the database in a read-only mode (#8079)
Browse files Browse the repository at this point in the history
* Allow opening the database read-only mode

* Update zebra-scan/src/storage/db.rs

Co-authored-by: teor <teor@riseup.net>

* Refactor skipping database upgrades

* Fix errors caused by the merge

* Add new argument in new_test_storage()

* Simplify test storage code

* Fix importing the `new_test_storate` fn

---------

Co-authored-by: teor <teor@riseup.net>
  • Loading branch information
upbqdn and teor2345 authored Dec 13, 2023
1 parent 92758a0 commit 22852bc
Show file tree
Hide file tree
Showing 11 changed files with 33 additions and 14 deletions.
2 changes: 1 addition & 1 deletion zebra-scan/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub async fn init(
state: scan::State,
chain_tip_change: ChainTipChange,
) -> Result<(), Report> {
let storage = tokio::task::spawn_blocking(move || Storage::new(&config, network))
let storage = tokio::task::spawn_blocking(move || Storage::new(&config, network, false))
.wait_for_panics()
.await;

Expand Down
4 changes: 2 additions & 2 deletions zebra-scan/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ impl Storage {
///
/// This method can block while creating or reading database files, so it must be inside
/// spawn_blocking() in async code.
pub fn new(config: &Config, network: Network) -> Self {
let mut storage = Self::new_db(config, network);
pub fn new(config: &Config, network: Network, read_only: bool) -> Self {
let mut storage = Self::new_db(config, network, read_only);

for (sapling_key, birthday) in config.sapling_keys_to_scan.iter() {
storage.add_sapling_key(sapling_key, Some(zebra_chain::block::Height(*birthday)));
Expand Down
8 changes: 5 additions & 3 deletions zebra-scan/src/storage/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ impl Storage {
/// If there is no existing database, creates a new database on disk.
///
/// New keys in `config` are not inserted into the database.
pub(crate) fn new_db(config: &Config, network: Network) -> Self {
pub(crate) fn new_db(config: &Config, network: Network, read_only: bool) -> Self {
Self::new_with_debug(
config, network,
// TODO: make format upgrades work with any database, then change this to `false`
true,
// TODO: make format upgrades work with any database, then change debug_skip_format_upgrades to `false`
true, read_only,
)
}

Expand All @@ -67,6 +67,7 @@ impl Storage {
config: &Config,
network: Network,
debug_skip_format_upgrades: bool,
read_only: bool,
) -> Self {
let db = ScannerDb::new(
config.db_config(),
Expand All @@ -77,6 +78,7 @@ impl Storage {
SCANNER_COLUMN_FAMILIES_IN_CODE
.iter()
.map(ToString::to_string),
read_only,
);

let new_storage = Self { db };
Expand Down
2 changes: 1 addition & 1 deletion zebra-scan/src/storage/db/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod snapshot;

/// Returns an empty `Storage` suitable for testing.
pub fn new_test_storage(network: Network) -> Storage {
Storage::new(&Config::ephemeral(), network)
Storage::new(&Config::ephemeral(), network, false)
}

/// Add fake keys to `storage` for testing purposes.
Expand Down
4 changes: 2 additions & 2 deletions zebra-scan/src/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use zebra_chain::{
use zebra_state::{SaplingScannedResult, TransactionIndex};

use crate::{
config::Config,
scan::{block_to_compact, scan_block},
storage::db::tests::new_test_storage,
tests::{fake_block, ZECPAGES_SAPLING_VIEWING_KEY},
};

Expand Down Expand Up @@ -157,7 +157,7 @@ fn scanning_fake_blocks_store_key_and_results() -> Result<()> {
zcash_client_backend::encoding::encode_extended_full_viewing_key("zxviews", &extfvk);

// Create a database
let mut s = crate::storage::Storage::new(&Config::ephemeral(), Network::Mainnet);
let mut s = new_test_storage(Network::Mainnet);

// Insert the generated key to the database
s.add_sapling_key(&key_to_be_stored, None);
Expand Down
3 changes: 3 additions & 0 deletions zebra-state/src/service/finalized_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ impl FinalizedState {
false,
#[cfg(feature = "elasticsearch")]
elastic_db,
false,
)
}

Expand All @@ -158,6 +159,7 @@ impl FinalizedState {
network: Network,
debug_skip_format_upgrades: bool,
#[cfg(feature = "elasticsearch")] elastic_db: Option<elasticsearch::Elasticsearch>,
read_only: bool,
) -> Self {
let db = ZebraDb::new(
config,
Expand All @@ -168,6 +170,7 @@ impl FinalizedState {
STATE_COLUMN_FAMILIES_IN_CODE
.iter()
.map(ToString::to_string),
read_only,
);

#[cfg(feature = "elasticsearch")]
Expand Down
7 changes: 6 additions & 1 deletion zebra-state/src/service/finalized_state/disk_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ impl DiskDb {
format_version_in_code: &Version,
network: Network,
column_families_in_code: impl IntoIterator<Item = String>,
read_only: bool,
) -> DiskDb {
let db_kind = db_kind.as_ref();
let path = config.db_path(db_kind, format_version_in_code.major, network);
Expand All @@ -680,7 +681,11 @@ impl DiskDb {
.unique()
.map(|cf_name| rocksdb::ColumnFamilyDescriptor::new(cf_name, db_options.clone()));

let db_result = DB::open_cf_descriptors(&db_options, &path, column_families);
let db_result = if read_only {
DB::open_cf_descriptors_read_only(&db_options, &path, column_families, false)
} else {
DB::open_cf_descriptors(&db_options, &path, column_families)
};

match db_result {
Ok(db) => {
Expand Down
14 changes: 10 additions & 4 deletions zebra-state/src/service/finalized_state/zebra_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ impl ZebraDb {
network: Network,
debug_skip_format_upgrades: bool,
column_families_in_code: impl IntoIterator<Item = String>,
read_only: bool,
) -> ZebraDb {
let disk_version = database_format_version_on_disk(
config,
Expand All @@ -108,16 +109,20 @@ impl ZebraDb {
// Log any format changes before opening the database, in case opening fails.
let format_change = DbFormatChange::open_database(format_version_in_code, disk_version);

// Always do format upgrades in production, but allow them to be skipped by the scanner
// (because it doesn't support them yet).
// Format upgrades try to write to the database, so we always skip them if `read_only` is
// `true`.
//
// We allow skipping the upgrades by the scanner because it doesn't support them yet and we
// also allow skipping them when we are running tests.
//
// TODO: Make scanner support format upgrades, then remove `shielded-scan` here.
let can_skip_format_upgrades = cfg!(test) || cfg!(feature = "shielded-scan");
let debug_skip_format_upgrades = read_only
|| ((cfg!(test) || cfg!(feature = "shielded-scan")) && debug_skip_format_upgrades);

// Open the database and do initial checks.
let mut db = ZebraDb {
config: Arc::new(config.clone()),
debug_skip_format_upgrades: can_skip_format_upgrades && debug_skip_format_upgrades,
debug_skip_format_upgrades,
format_change_handle: None,
// After the database directory is created, a newly created database temporarily
// changes to the default database version. Then we set the correct version in the
Expand All @@ -129,6 +134,7 @@ impl ZebraDb {
format_version_in_code,
network,
column_families_in_code,
read_only,
),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ fn test_block_db_round_trip_with(
STATE_COLUMN_FAMILIES_IN_CODE
.iter()
.map(ToString::to_string),
false,
);

// Check that each block round-trips to the database
Expand Down
1 change: 1 addition & 0 deletions zebra-state/src/service/read/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,5 +377,6 @@ fn new_ephemeral_db() -> ZebraDb {
STATE_COLUMN_FAMILIES_IN_CODE
.iter()
.map(ToString::to_string),
false,
)
}
1 change: 1 addition & 0 deletions zebra-state/src/tests/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub(crate) fn new_state_with_mainnet_genesis(
true,
#[cfg(feature = "elasticsearch")]
None,
false,
);
let non_finalized_state = NonFinalizedState::new(network);

Expand Down

0 comments on commit 22852bc

Please sign in to comment.