Skip to content

Commit 199059a

Browse files
committed
refactors fix tree keys, cache genesis roots, and value balance upgrades to use new trait
1 parent ac1eb1b commit 199059a

File tree

3 files changed

+121
-40
lines changed

3 files changed

+121
-40
lines changed

zebra-state/src/service/finalized_state/disk_format/upgrade.rs

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ use crate::service::finalized_state::ZebraDb;
2525
pub(crate) mod add_subtrees;
2626
pub(crate) mod cache_genesis_roots;
2727
pub(crate) mod fix_tree_key_type;
28+
pub(crate) mod no_migration;
2829
pub(crate) mod prune_trees;
30+
pub(crate) mod tree_keys_and_caches_upgrade;
2931

3032
#[cfg(not(feature = "indexer"))]
3133
pub(crate) mod drop_tx_locs_by_spends;
@@ -72,15 +74,21 @@ pub trait DiskFormatUpgrade {
7274
) -> Result<(), CancelFormatChange> {
7375
Ok(())
7476
}
77+
78+
/// Returns true if the [`DiskFormatUpgrade`] needs to run a migration on existing data in the db.
79+
fn needs_migration(&self) -> bool {
80+
true
81+
}
7582
}
7683

7784
fn format_upgrades() -> Vec<Box<dyn DiskFormatUpgrade>> {
85+
// Note: Disk format upgrades must be run in order.
7886
vec![
7987
Box::new(prune_trees::PruneTrees),
8088
Box::new(add_subtrees::AddSubtrees),
81-
// TODO:
82-
// Box::new(cache_genesis_roots::CacheGenesisRoots),
83-
// Box::new(fix_tree_key_type::FixTreeKeyType),
89+
Box::new(tree_keys_and_caches_upgrade::FixTreeKeyTypeAndCacheGenesisRoots),
90+
// Value balance upgrade
91+
Box::new(no_migration::NoMigration::new(26, 0, 0)),
8492
]
8593
}
8694

@@ -532,6 +540,11 @@ impl DbFormatChange {
532540
continue;
533541
}
534542

543+
if !upgrade.needs_migration() {
544+
Self::mark_as_upgraded_to(db, &upgrade.version());
545+
continue;
546+
}
547+
535548
let timer = CodeTimer::start();
536549

537550
upgrade.prepare(initial_tip_height, db, cancel_receiver, older_disk_version)?;
@@ -553,32 +566,6 @@ impl DbFormatChange {
553566
timer.finish(module_path!(), line!(), upgrade.description());
554567
}
555568

556-
// Sprout & history tree key formats, and cached genesis tree roots database upgrades.
557-
558-
let version_for_tree_keys_and_caches =
559-
Version::parse("25.3.0").expect("Hardcoded version string should be valid.");
560-
561-
// Check if we need to do the upgrade.
562-
if older_disk_version < &version_for_tree_keys_and_caches {
563-
let timer = CodeTimer::start();
564-
565-
// It shouldn't matter what order these are run in.
566-
cache_genesis_roots::run(initial_tip_height, db, cancel_receiver)?;
567-
fix_tree_key_type::run(initial_tip_height, db, cancel_receiver)?;
568-
569-
// Before marking the state as upgraded, check that the upgrade completed successfully.
570-
cache_genesis_roots::detailed_check(db, cancel_receiver)?
571-
.expect("database format is valid after upgrade");
572-
fix_tree_key_type::detailed_check(db, cancel_receiver)?
573-
.expect("database format is valid after upgrade");
574-
575-
// Mark the database as upgraded. Zebra won't repeat the upgrade anymore once the
576-
// database is marked, so the upgrade MUST be complete at this point.
577-
Self::mark_as_upgraded_to(db, &version_for_tree_keys_and_caches);
578-
579-
timer.finish(module_path!(), line!(), "tree keys and caches upgrade");
580-
}
581-
582569
let version_for_upgrading_value_balance_format =
583570
Version::parse("26.0.0").expect("hard-coded version string should be valid");
584571

@@ -587,14 +574,6 @@ impl DbFormatChange {
587574
Self::mark_as_upgraded_to(db, &version_for_upgrading_value_balance_format)
588575
}
589576

590-
// # New Upgrades Usually Go Here
591-
//
592-
// New code goes above this comment!
593-
//
594-
// Run the latest format upgrade code after the other upgrades are complete,
595-
// then mark the format as upgraded. The code should check `cancel_receiver`
596-
// every time it runs its inner update loop.
597-
598577
info!(
599578
%newer_running_version,
600579
"Zebra automatically upgraded the database format to:"
@@ -650,9 +629,6 @@ impl DbFormatChange {
650629
results.push(upgrade.validate(db, cancel_receiver)?);
651630
}
652631

653-
results.push(cache_genesis_roots::detailed_check(db, cancel_receiver)?);
654-
results.push(fix_tree_key_type::detailed_check(db, cancel_receiver)?);
655-
656632
// The work is done in the functions we just called.
657633
timer.finish(module_path!(), line!(), "format_validity_checks_detailed()");
658634

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! An implementation of [`DiskFormatUpgrade`] for marking the database as upgraded to a new format version.
2+
3+
use crossbeam_channel::Receiver;
4+
5+
use semver::Version;
6+
use zebra_chain::block::Height;
7+
8+
use crate::service::finalized_state::ZebraDb;
9+
10+
use super::{CancelFormatChange, DiskFormatUpgrade};
11+
12+
/// Implements [`DiskFormatUpgrade`] for pruning duplicate Sapling and Orchard note commitment trees from database
13+
pub struct NoMigration {
14+
version: Version,
15+
}
16+
17+
impl NoMigration {
18+
/// Creates a new instance of the [`NoMigration`] upgrade.
19+
pub fn new(major: u64, minor: u64, patch: u64) -> Self {
20+
Self {
21+
version: Version::new(major, minor, patch),
22+
}
23+
}
24+
}
25+
26+
impl DiskFormatUpgrade for NoMigration {
27+
fn version(&self) -> Version {
28+
self.version.clone()
29+
}
30+
31+
fn description(&self) -> &'static str {
32+
"no migration"
33+
}
34+
35+
#[allow(clippy::unwrap_in_result)]
36+
fn run(
37+
&self,
38+
_initial_tip_height: Height,
39+
_db: &ZebraDb,
40+
_cancel_receiver: &Receiver<CancelFormatChange>,
41+
) -> Result<(), CancelFormatChange> {
42+
Ok(())
43+
}
44+
45+
fn needs_migration(&self) -> bool {
46+
false
47+
}
48+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! Applies the [`fix_tree_key_type`] and [`cache_genesis_roots`] upgrades to the database.
2+
3+
use crossbeam_channel::Receiver;
4+
5+
use semver::Version;
6+
use zebra_chain::block::Height;
7+
8+
use crate::service::finalized_state::ZebraDb;
9+
10+
use super::{cache_genesis_roots, fix_tree_key_type, CancelFormatChange, DiskFormatUpgrade};
11+
12+
/// Implements [`DiskFormatUpgrade`] for updating the sprout and history tree key type from
13+
/// `Height` to the empty key `()` and the genesis note commitment trees to cache their roots
14+
pub struct FixTreeKeyTypeAndCacheGenesisRoots;
15+
16+
impl DiskFormatUpgrade for FixTreeKeyTypeAndCacheGenesisRoots {
17+
fn version(&self) -> Version {
18+
Version::new(25, 3, 0)
19+
}
20+
21+
fn description(&self) -> &'static str {
22+
"tree keys and caches upgrade"
23+
}
24+
25+
#[allow(clippy::unwrap_in_result)]
26+
fn run(
27+
&self,
28+
initial_tip_height: Height,
29+
db: &ZebraDb,
30+
cancel_receiver: &Receiver<CancelFormatChange>,
31+
) -> Result<(), CancelFormatChange> {
32+
// It shouldn't matter what order these are run in.
33+
cache_genesis_roots::run(initial_tip_height, db, cancel_receiver)?;
34+
fix_tree_key_type::run(initial_tip_height, db, cancel_receiver)?;
35+
Ok(())
36+
}
37+
38+
#[allow(clippy::unwrap_in_result)]
39+
fn validate(
40+
&self,
41+
db: &ZebraDb,
42+
cancel_receiver: &Receiver<CancelFormatChange>,
43+
) -> Result<Result<(), String>, CancelFormatChange> {
44+
let results = [
45+
cache_genesis_roots::detailed_check(db, cancel_receiver)?,
46+
fix_tree_key_type::detailed_check(db, cancel_receiver)?,
47+
];
48+
49+
let result = if results.iter().any(Result::is_err) {
50+
Err(format!("{results:?}"))
51+
} else {
52+
Ok(())
53+
};
54+
55+
Ok(result)
56+
}
57+
}

0 commit comments

Comments
 (0)