zebra_state/constants.rs
1//! Constants that impact state behaviour.
2
3use lazy_static::lazy_static;
4use regex::Regex;
5use semver::Version;
6
7// For doc comment links
8#[allow(unused_imports)]
9use crate::{
10 config::{self, Config},
11 constants,
12};
13
14pub use zebra_chain::transparent::MIN_TRANSPARENT_COINBASE_MATURITY;
15
16/// The maximum chain reorganisation height; it bounds the length of the best
17/// non-finalized chain. The value lives in `zebra-chain` so tooling (e.g.
18/// `zebra-checkpoints`) can use it without depending on `zebra-state`.
19pub const MAX_BLOCK_REORG_HEIGHT: u32 = zebra_chain::parameters::constants::MAX_BLOCK_REORG_HEIGHT;
20
21/// The directory name used to distinguish the state database from Zebra's other databases or flat files.
22pub const STATE_DATABASE_KIND: &str = "state";
23
24/// The database format major version, incremented each time the on-disk database format has a
25/// breaking data format change.
26///
27/// Breaking changes include:
28/// - deleting a column family, or
29/// - changing a column family's data format in an incompatible way.
30///
31/// Breaking changes become minor version changes if:
32/// - we previously added compatibility code, and
33/// - it's available in all supported Zebra versions.
34///
35/// Instead of using this constant directly, use [`constants::state_database_format_version_in_code()`]
36/// or [`config::database_format_version_on_disk()`] to get the full semantic format version.
37const DATABASE_FORMAT_VERSION: u64 = 29;
38
39/// The database format minor version, incremented each time the on-disk database format has a
40/// significant data format change.
41///
42/// Significant changes include:
43/// - adding new column families,
44/// - changing the format of a column family in a compatible way, or
45/// - breaking changes with compatibility code in all supported Zebra versions.
46///
47/// Version history:
48/// - 29.0.0: the NU7 Network Sustainability Mechanism pool widens new `ValueBalance` writes from
49/// 48 to 56 bytes and `BlockInfo` writes from 52 to 60 bytes. Legacy records remain readable with
50/// a zero NSM balance. The registered upgrade reuses compatible v28 state by moving its network
51/// directory to `state/v29`, without a resync or record migration. Retain a v28 backup for rollback:
52/// disabling old-database cleanup does not prevent this move, and v28 readers cannot use new records.
53/// - 28.0.0: the NU6.3 Ironwood shielded pool. Adds the `ironwood_*` column families (initially
54/// empty) and widens the chain value pool `ValueBalance` serialization from 40 to 48 bytes for
55/// the `ironwood` pool (read code accepts 32/40/48-byte records). Also widens the history-tree
56/// `zcash_history::Entry` records from 253 to 326 bytes, because NU6.3 adds Ironwood fields to
57/// `zcash_history::NodeData` (read code accepts the legacy 253-byte width and zero-pads it up to
58/// the current width). New CFs are created and the wider records are read in place when the
59/// database is opened, so this is a major bump that is restorable from the previous major
60/// database format version (no resync, no data migration).
61const DATABASE_FORMAT_MINOR_VERSION: u64 = 0;
62
63/// The database format patch version, incremented each time the on-disk database format has a
64/// significant format compatibility fix.
65const DATABASE_FORMAT_PATCH_VERSION: u64 = 0;
66
67/// Returns the full semantic version of the currently running state database format code.
68///
69/// This is the version implemented by the Zebra code that's currently running,
70/// the version on disk can be different.
71pub fn state_database_format_version_in_code() -> Version {
72 Version {
73 major: DATABASE_FORMAT_VERSION,
74 minor: DATABASE_FORMAT_MINOR_VERSION,
75 patch: DATABASE_FORMAT_PATCH_VERSION,
76 pre: semver::Prerelease::EMPTY,
77 #[cfg(feature = "indexer")]
78 build: semver::BuildMetadata::new("indexer").expect("hard-coded value should be valid"),
79 #[cfg(not(feature = "indexer"))]
80 build: semver::BuildMetadata::EMPTY,
81 }
82}
83
84/// The name of the file containing the database version.
85///
86/// Note: This file has historically omitted the major database version.
87///
88/// Use [`Config::version_file_path()`] to get the path to this file.
89pub(crate) const DATABASE_FORMAT_VERSION_FILE_NAME: &str = "version";
90
91/// The maximum number of blocks to check for NU5 transactions,
92/// before we assume we are on a pre-NU5 legacy chain.
93///
94/// Zebra usually only has to check back a few blocks on mainnet, but on testnet it can be a long
95/// time between v5 transactions.
96pub const MAX_LEGACY_CHAIN_BLOCKS: usize = 100_000;
97
98/// The maximum number of non-finalized chain forks Zebra will track.
99/// When this limit is reached, we drop the chain with the lowest work.
100///
101/// When the network is under heavy transaction load, there are around 5 active forks in the last
102/// 100 blocks. (1 fork per 20 blocks.) When block propagation is efficient, there is around
103/// 1 fork per 300 blocks.
104///
105/// This limits non-finalized chain memory, in the worst case, to around:
106/// `10 forks * 1000 blocks * 2 MB per block = 20 GB`
107pub const MAX_NON_FINALIZED_CHAIN_FORKS: usize = 10;
108
109/// The maximum number of block hashes allowed in `getblocks` responses in the Zcash network protocol.
110pub const MAX_FIND_BLOCK_HASHES_RESULTS: u32 = 500;
111
112/// The maximum number of block headers allowed in `getheaders` responses in the Zcash network protocol.
113pub const MAX_FIND_BLOCK_HEADERS_RESULTS: u32 = 160;
114
115/// The maximum number of invalidated block records.
116///
117/// Each record can hold a chain of invalidated descendants up to the rollback
118/// window ([`MAX_BLOCK_REORG_HEIGHT`]) deep, so this limits the memory use, in
119/// the worst case, to around:
120/// `100 entries * up to 1000 blocks * 2 MB per block = 200 GB`
121pub const MAX_INVALIDATED_BLOCKS: usize = 100;
122
123lazy_static! {
124 /// Regex that matches the RocksDB error when its lock file is already open.
125 pub static ref LOCK_FILE_ERROR: Regex = Regex::new("(lock file).*(temporarily unavailable)|(in use)|(being used by another process)|(Database likely already open)").expect("regex is valid");
126}