diff --git a/core/tests/snapshots.rs b/core/tests/snapshots.rs index 9f9af147ffe16c..44b8b88e4e8079 100644 --- a/core/tests/snapshots.rs +++ b/core/tests/snapshots.rs @@ -103,6 +103,11 @@ mod tests { DEFINE_SNAPSHOT_VERSION_PARAMETERIZED_TEST_FUNCTIONS!(V1_2_0, Testnet, V1_2_0_Testnet); DEFINE_SNAPSHOT_VERSION_PARAMETERIZED_TEST_FUNCTIONS!(V1_2_0, MainnetBeta, V1_2_0_MainnetBeta); + DEFINE_SNAPSHOT_VERSION_PARAMETERIZED_TEST_FUNCTIONS!(V1_3_0, Development, V1_3_0_Development); + DEFINE_SNAPSHOT_VERSION_PARAMETERIZED_TEST_FUNCTIONS!(V1_3_0, Devnet, V1_3_0_Devnet); + DEFINE_SNAPSHOT_VERSION_PARAMETERIZED_TEST_FUNCTIONS!(V1_3_0, Testnet, V1_3_0_Testnet); + DEFINE_SNAPSHOT_VERSION_PARAMETERIZED_TEST_FUNCTIONS!(V1_3_0, MainnetBeta, V1_3_0_MainnetBeta); + struct SnapshotTestConfig { accounts_dir: TempDir, bank_snapshots_dir: TempDir, diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 90176b9a9c33b1..d3d98618155661 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -864,8 +864,6 @@ pub(crate) struct BankFieldsToDeserialize { pub(crate) ns_per_slot: u128, pub(crate) genesis_creation_time: UnixTimestamp, pub(crate) slots_per_year: f64, - #[allow(dead_code)] - pub(crate) unused: u64, pub(crate) slot: Slot, pub(crate) epoch: Epoch, pub(crate) block_height: u64, @@ -880,6 +878,7 @@ pub(crate) struct BankFieldsToDeserialize { pub(crate) stakes: Stakes, pub(crate) epoch_stakes: HashMap, pub(crate) is_delta: bool, + pub(crate) accounts_data_len: Option, // TODO: Remove Option wrapper once "newer" snapshot serde style is the only one supported } // Bank's common fields shared by all supported snapshot versions for serialization. @@ -904,7 +903,6 @@ pub(crate) struct BankFieldsToSerialize<'a> { pub(crate) ns_per_slot: u128, pub(crate) genesis_creation_time: UnixTimestamp, pub(crate) slots_per_year: f64, - pub(crate) unused: u64, pub(crate) slot: Slot, pub(crate) epoch: Epoch, pub(crate) block_height: u64, @@ -919,6 +917,7 @@ pub(crate) struct BankFieldsToSerialize<'a> { pub(crate) stakes: &'a StakesCache, pub(crate) epoch_stakes: &'a HashMap, pub(crate) is_delta: bool, + pub(crate) accounts_data_len: u64, } // Can't derive PartialEq because RwLock doesn't implement PartialEq @@ -943,7 +942,6 @@ impl PartialEq for Bank { && self.ns_per_slot == other.ns_per_slot && self.genesis_creation_time == other.genesis_creation_time && self.slots_per_year == other.slots_per_year - && self.unused == other.unused && self.slot == other.slot && self.epoch == other.epoch && self.block_height == other.block_height @@ -1095,9 +1093,6 @@ pub struct Bank { /// The number of slots per year, used for inflation slots_per_year: f64, - /// Unused - unused: u64, - /// Bank slot (i.e. block) slot: Slot, @@ -1300,7 +1295,6 @@ impl Bank { ns_per_slot: u128::default(), genesis_creation_time: UnixTimestamp::default(), slots_per_year: f64::default(), - unused: u64::default(), slot: Slot::default(), bank_id: BankId::default(), epoch: Epoch::default(), @@ -1531,7 +1525,6 @@ impl Bank { ticks_per_slot: parent.ticks_per_slot, ns_per_slot: parent.ns_per_slot, genesis_creation_time: parent.genesis_creation_time, - unused: parent.unused, slots_per_year: parent.slots_per_year, epoch_schedule, collected_rent: AtomicU64::new(0), @@ -1711,7 +1704,7 @@ impl Bank { debug_keys: Option>>, additional_builtins: Option<&Builtins>, debug_do_not_add_builtins: bool, - accounts_data_len: u64, + computed_accounts_data_len: u64, // TODO: Remove this parameter once "newer" snapshot serde style is the only one supported ) -> Self { fn new() -> T { T::default() @@ -1738,7 +1731,6 @@ impl Bank { ns_per_slot: fields.ns_per_slot, genesis_creation_time: fields.genesis_creation_time, slots_per_year: fields.slots_per_year, - unused: genesis_config.unused, slot: fields.slot, bank_id: 0, epoch: fields.epoch, @@ -1775,8 +1767,13 @@ impl Bank { vote_only_bank: false, cost_tracker: RwLock::new(CostTracker::default()), sysvar_cache: RwLock::new(SysvarCache::default()), - accounts_data_len: AtomicU64::new(accounts_data_len), + accounts_data_len: AtomicU64::new( + fields + .accounts_data_len + .map_or(computed_accounts_data_len, |len| len), + ), }; + bank.finish_init( genesis_config, additional_builtins, @@ -1798,7 +1795,6 @@ impl Bank { * genesis_config.ticks_per_slot as u128 ); assert_eq!(bank.genesis_creation_time, genesis_config.creation_time); - assert_eq!(bank.unused, genesis_config.unused); assert_eq!(bank.max_tick_height, (bank.slot + 1) * bank.ticks_per_slot); assert_eq!( bank.slots_per_year, @@ -1843,7 +1839,6 @@ impl Bank { ns_per_slot: self.ns_per_slot, genesis_creation_time: self.genesis_creation_time, slots_per_year: self.slots_per_year, - unused: self.unused, slot: self.slot, epoch: self.epoch, block_height: self.block_height, @@ -1858,6 +1853,7 @@ impl Bank { stakes: &self.stakes_cache, epoch_stakes: &self.epoch_stakes, is_delta: self.is_delta.load(Relaxed), + accounts_data_len: self.load_accounts_data_len(), } } @@ -1980,11 +1976,6 @@ impl Bank { ) } - /// Unused conversion - pub fn get_unused_from_slot(rooted_slot: Slot, unused: u64) -> u64 { - (rooted_slot + (unused - 1)) / unused - } - pub fn clock(&self) -> sysvar::clock::Clock { from_account(&self.get_account(&sysvar::clock::id()).unwrap_or_default()) .unwrap_or_default() @@ -2910,7 +2901,6 @@ impl Bank { self.ticks_per_slot = genesis_config.ticks_per_slot(); self.ns_per_slot = genesis_config.ns_per_slot(); self.genesis_creation_time = genesis_config.creation_time; - self.unused = genesis_config.unused; self.max_tick_height = (self.slot + 1) * self.ticks_per_slot; self.slots_per_year = genesis_config.slots_per_year(); diff --git a/runtime/src/serde_snapshot.rs b/runtime/src/serde_snapshot.rs index ded689318f9b73..df8a901ef4fc24 100644 --- a/runtime/src/serde_snapshot.rs +++ b/runtime/src/serde_snapshot.rs @@ -44,8 +44,8 @@ use { }, }; -mod common; mod newer; +mod older; mod storage; mod tests; mod utils; @@ -59,6 +59,7 @@ pub(crate) use tests::reconstruct_accounts_db_via_serialization; #[derive(Copy, Clone, Eq, PartialEq)] pub(crate) enum SerdeStyle { Newer, + Older, } const MAX_STREAM_SIZE: u64 = 32 * 1024 * 1024 * 1024; @@ -239,6 +240,7 @@ where } match serde_style { SerdeStyle::Newer => INTO!(newer), + SerdeStyle::Older => INTO!(older), } .map_err(|err| { warn!("bankrc_from_stream error: {:?}", err); @@ -269,6 +271,7 @@ where } match serde_style { SerdeStyle::Newer => INTO!(newer), + SerdeStyle::Older => INTO!(older), } .map_err(|err| { warn!("bankrc_to_stream error: {:?}", err); diff --git a/runtime/src/serde_snapshot/common.rs b/runtime/src/serde_snapshot/common.rs deleted file mode 100644 index e8464ea3def84f..00000000000000 --- a/runtime/src/serde_snapshot/common.rs +++ /dev/null @@ -1,8 +0,0 @@ -use {super::*, std::collections::HashSet}; - -#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize, AbiExample)] -pub(crate) struct UnusedAccounts { - unused1: HashSet, - unused2: HashSet, - unused3: HashMap, -} diff --git a/runtime/src/serde_snapshot/newer.rs b/runtime/src/serde_snapshot/newer.rs index 6f182bc444ddd3..88bc19dbe2e84b 100644 --- a/runtime/src/serde_snapshot/newer.rs +++ b/runtime/src/serde_snapshot/newer.rs @@ -1,6 +1,5 @@ use { super::{ - common::UnusedAccounts, storage::SerializableAccountStorageEntry, utils::{serialize_iter_as_map, serialize_iter_as_seq}, *, @@ -33,7 +32,6 @@ struct DeserializableVersionedBank { ns_per_slot: u128, genesis_creation_time: UnixTimestamp, slots_per_year: f64, - unused: u64, slot: Slot, epoch: Epoch, block_height: u64, @@ -46,10 +44,9 @@ struct DeserializableVersionedBank { epoch_schedule: EpochSchedule, inflation: Inflation, stakes: Stakes, - #[allow(dead_code)] - unused_accounts: UnusedAccounts, epoch_stakes: HashMap, is_delta: bool, + accounts_data_len: u64, } impl From for BankFieldsToDeserialize { @@ -71,7 +68,6 @@ impl From for BankFieldsToDeserialize { ns_per_slot: dvb.ns_per_slot, genesis_creation_time: dvb.genesis_creation_time, slots_per_year: dvb.slots_per_year, - unused: dvb.unused, slot: dvb.slot, epoch: dvb.epoch, block_height: dvb.block_height, @@ -86,6 +82,7 @@ impl From for BankFieldsToDeserialize { stakes: dvb.stakes, epoch_stakes: dvb.epoch_stakes, is_delta: dvb.is_delta, + accounts_data_len: Some(dvb.accounts_data_len), } } } @@ -110,7 +107,6 @@ struct SerializableVersionedBank<'a> { ns_per_slot: u128, genesis_creation_time: UnixTimestamp, slots_per_year: f64, - unused: u64, slot: Slot, epoch: Epoch, block_height: u64, @@ -123,16 +119,13 @@ struct SerializableVersionedBank<'a> { epoch_schedule: EpochSchedule, inflation: Inflation, stakes: &'a StakesCache, - unused_accounts: UnusedAccounts, epoch_stakes: &'a HashMap, is_delta: bool, + accounts_data_len: u64, } impl<'a> From> for SerializableVersionedBank<'a> { fn from(rhs: crate::bank::BankFieldsToSerialize<'a>) -> Self { - fn new() -> T { - T::default() - } Self { blockhash_queue: rhs.blockhash_queue, ancestors: rhs.ancestors, @@ -150,7 +143,6 @@ impl<'a> From> for SerializableVersionedB ns_per_slot: rhs.ns_per_slot, genesis_creation_time: rhs.genesis_creation_time, slots_per_year: rhs.slots_per_year, - unused: rhs.unused, slot: rhs.slot, epoch: rhs.epoch, block_height: rhs.block_height, @@ -163,9 +155,9 @@ impl<'a> From> for SerializableVersionedB epoch_schedule: rhs.epoch_schedule, inflation: rhs.inflation, stakes: rhs.stakes, - unused_accounts: new(), epoch_stakes: rhs.epoch_stakes, is_delta: rhs.is_delta, + accounts_data_len: rhs.accounts_data_len, } } } diff --git a/runtime/src/serde_snapshot/older.rs b/runtime/src/serde_snapshot/older.rs new file mode 100644 index 00000000000000..77c33a054a6777 --- /dev/null +++ b/runtime/src/serde_snapshot/older.rs @@ -0,0 +1,272 @@ +use { + super::{ + storage::SerializableAccountStorageEntry, + utils::{serialize_iter_as_map, serialize_iter_as_seq}, + *, + }, + crate::{ancestors::AncestorsForSerialization, stakes::StakesCache}, + solana_measure::measure::Measure, + std::{cell::RefCell, collections::HashSet, sync::RwLock}, +}; + +type AccountsDbFields = super::AccountsDbFields; + +#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize, AbiExample)] +pub(crate) struct UnusedAccounts { + unused1: HashSet, + unused2: HashSet, + unused3: HashMap, +} + +// Deserializable version of Bank which need not be serializable, +// because it's handled by SerializableVersionedBank. +// So, sync fields with it! +#[derive(Clone, Deserialize)] +struct DeserializableVersionedBank { + blockhash_queue: BlockhashQueue, + ancestors: AncestorsForSerialization, + hash: Hash, + parent_hash: Hash, + parent_slot: Slot, + hard_forks: HardForks, + transaction_count: u64, + tick_height: u64, + signature_count: u64, + capitalization: u64, + max_tick_height: u64, + hashes_per_tick: Option, + ticks_per_slot: u64, + ns_per_slot: u128, + genesis_creation_time: UnixTimestamp, + slots_per_year: f64, + #[allow(dead_code)] + unused: u64, + slot: Slot, + epoch: Epoch, + block_height: u64, + collector_id: Pubkey, + collector_fees: u64, + fee_calculator: FeeCalculator, + fee_rate_governor: FeeRateGovernor, + collected_rent: u64, + rent_collector: RentCollector, + epoch_schedule: EpochSchedule, + inflation: Inflation, + stakes: Stakes, + #[allow(dead_code)] + unused_accounts: UnusedAccounts, + epoch_stakes: HashMap, + is_delta: bool, +} + +impl From for BankFieldsToDeserialize { + fn from(dvb: DeserializableVersionedBank) -> Self { + BankFieldsToDeserialize { + blockhash_queue: dvb.blockhash_queue, + ancestors: dvb.ancestors, + hash: dvb.hash, + parent_hash: dvb.parent_hash, + parent_slot: dvb.parent_slot, + hard_forks: dvb.hard_forks, + transaction_count: dvb.transaction_count, + tick_height: dvb.tick_height, + signature_count: dvb.signature_count, + capitalization: dvb.capitalization, + max_tick_height: dvb.max_tick_height, + hashes_per_tick: dvb.hashes_per_tick, + ticks_per_slot: dvb.ticks_per_slot, + ns_per_slot: dvb.ns_per_slot, + genesis_creation_time: dvb.genesis_creation_time, + slots_per_year: dvb.slots_per_year, + slot: dvb.slot, + epoch: dvb.epoch, + block_height: dvb.block_height, + collector_id: dvb.collector_id, + collector_fees: dvb.collector_fees, + fee_calculator: dvb.fee_calculator, + fee_rate_governor: dvb.fee_rate_governor, + collected_rent: dvb.collected_rent, + rent_collector: dvb.rent_collector, + epoch_schedule: dvb.epoch_schedule, + inflation: dvb.inflation, + stakes: dvb.stakes, + epoch_stakes: dvb.epoch_stakes, + is_delta: dvb.is_delta, + accounts_data_len: None, + } + } +} + +// Serializable version of Bank, not Deserializable to avoid cloning by using refs. +// Sync fields with DeserializableVersionedBank! +#[derive(Serialize)] +pub(crate) struct SerializableVersionedBank<'a> { + pub(crate) blockhash_queue: &'a RwLock, + pub(crate) ancestors: &'a AncestorsForSerialization, + pub(crate) hash: Hash, + pub(crate) parent_hash: Hash, + pub(crate) parent_slot: Slot, + pub(crate) hard_forks: &'a RwLock, + pub(crate) transaction_count: u64, + pub(crate) tick_height: u64, + pub(crate) signature_count: u64, + pub(crate) capitalization: u64, + pub(crate) max_tick_height: u64, + pub(crate) hashes_per_tick: Option, + pub(crate) ticks_per_slot: u64, + pub(crate) ns_per_slot: u128, + pub(crate) genesis_creation_time: UnixTimestamp, + pub(crate) slots_per_year: f64, + pub(crate) unused: u64, + pub(crate) slot: Slot, + pub(crate) epoch: Epoch, + pub(crate) block_height: u64, + pub(crate) collector_id: Pubkey, + pub(crate) collector_fees: u64, + pub(crate) fee_calculator: FeeCalculator, + pub(crate) fee_rate_governor: FeeRateGovernor, + pub(crate) collected_rent: u64, + pub(crate) rent_collector: RentCollector, + pub(crate) epoch_schedule: EpochSchedule, + pub(crate) inflation: Inflation, + pub(crate) stakes: &'a StakesCache, + pub(crate) unused_accounts: UnusedAccounts, + pub(crate) epoch_stakes: &'a HashMap, + pub(crate) is_delta: bool, +} + +impl<'a> From> for SerializableVersionedBank<'a> { + fn from(rhs: crate::bank::BankFieldsToSerialize<'a>) -> Self { + Self { + blockhash_queue: rhs.blockhash_queue, + ancestors: rhs.ancestors, + hash: rhs.hash, + parent_hash: rhs.parent_hash, + parent_slot: rhs.parent_slot, + hard_forks: rhs.hard_forks, + transaction_count: rhs.transaction_count, + tick_height: rhs.tick_height, + signature_count: rhs.signature_count, + capitalization: rhs.capitalization, + max_tick_height: rhs.max_tick_height, + hashes_per_tick: rhs.hashes_per_tick, + ticks_per_slot: rhs.ticks_per_slot, + ns_per_slot: rhs.ns_per_slot, + genesis_creation_time: rhs.genesis_creation_time, + slots_per_year: rhs.slots_per_year, + unused: u64::default(), + slot: rhs.slot, + epoch: rhs.epoch, + block_height: rhs.block_height, + collector_id: rhs.collector_id, + collector_fees: rhs.collector_fees, + fee_calculator: rhs.fee_calculator, + fee_rate_governor: rhs.fee_rate_governor, + collected_rent: rhs.collected_rent, + rent_collector: rhs.rent_collector, + epoch_schedule: rhs.epoch_schedule, + inflation: rhs.inflation, + stakes: rhs.stakes, + unused_accounts: UnusedAccounts::default(), + epoch_stakes: rhs.epoch_stakes, + is_delta: rhs.is_delta, + } + } +} + +#[cfg(RUSTC_WITH_SPECIALIZATION)] +impl<'a> solana_frozen_abi::abi_example::IgnoreAsHelper for SerializableVersionedBank<'a> {} + +pub(super) struct Context {} + +impl<'a> TypeContext<'a> for Context { + type SerializableAccountStorageEntry = SerializableAccountStorageEntry; + + fn serialize_bank_and_storage( + serializer: S, + serializable_bank: &SerializableBankAndStorage<'a, Self>, + ) -> std::result::Result + where + Self: std::marker::Sized, + { + let ancestors = HashMap::from(&serializable_bank.bank.ancestors); + let fields = serializable_bank.bank.get_fields_to_serialize(&ancestors); + ( + SerializableVersionedBank::from(fields), + SerializableAccountsDb::<'a, Self> { + accounts_db: &*serializable_bank.bank.rc.accounts.accounts_db, + slot: serializable_bank.bank.rc.slot, + account_storage_entries: serializable_bank.snapshot_storages, + phantom: std::marker::PhantomData::default(), + }, + ) + .serialize(serializer) + } + + fn serialize_accounts_db_fields( + serializer: S, + serializable_db: &SerializableAccountsDb<'a, Self>, + ) -> std::result::Result + where + Self: std::marker::Sized, + { + // sample write version before serializing storage entries + let version = serializable_db + .accounts_db + .write_version + .load(Ordering::Acquire); + + // (1st of 3 elements) write the list of account storage entry lists out as a map + let entry_count = RefCell::::new(0); + let entries = + serialize_iter_as_map(serializable_db.account_storage_entries.iter().map(|x| { + *entry_count.borrow_mut() += x.len(); + ( + x.first().unwrap().slot(), + serialize_iter_as_seq( + x.iter() + .map(|x| Self::SerializableAccountStorageEntry::from(x.as_ref())), + ), + ) + })); + let slot = serializable_db.slot; + let hash = serializable_db + .accounts_db + .bank_hashes + .read() + .unwrap() + .get(&serializable_db.slot) + .unwrap_or_else(|| panic!("No bank_hashes entry for slot {}", serializable_db.slot)) + .clone(); + + let mut serialize_account_storage_timer = Measure::start("serialize_account_storage_ms"); + let result = (entries, version, slot, hash).serialize(serializer); + serialize_account_storage_timer.stop(); + datapoint_info!( + "serialize_account_storage_ms", + ("duration", serialize_account_storage_timer.as_ms(), i64), + ("num_entries", *entry_count.borrow(), i64), + ); + result + } + + fn deserialize_bank_fields( + mut stream: &mut BufReader, + ) -> Result<(BankFieldsToDeserialize, AccountsDbFields), Error> + where + R: Read, + { + let bank_fields = deserialize_from::<_, DeserializableVersionedBank>(&mut stream)?.into(); + let accounts_db_fields = Self::deserialize_accounts_db_fields(stream)?; + Ok((bank_fields, accounts_db_fields)) + } + + fn deserialize_accounts_db_fields( + stream: &mut BufReader, + ) -> Result + where + R: Read, + { + deserialize_from(stream) + } +} diff --git a/runtime/src/serde_snapshot/tests.rs b/runtime/src/serde_snapshot/tests.rs index 212c830bd75b3c..beba4e494223bb 100644 --- a/runtime/src/serde_snapshot/tests.rs +++ b/runtime/src/serde_snapshot/tests.rs @@ -104,6 +104,11 @@ where account_paths, unpacked_append_vec_map, ), + SerdeStyle::Older => context_accountsdb_from_stream::( + stream, + account_paths, + unpacked_append_vec_map, + ), } } @@ -127,6 +132,15 @@ where phantom: std::marker::PhantomData::default(), }, ), + SerdeStyle::Older => serialize_into( + stream, + &SerializableAccountsDb:: { + accounts_db, + slot, + account_storage_entries, + phantom: std::marker::PhantomData::default(), + }, + ), } } @@ -299,13 +313,23 @@ fn test_bank_serialize_newer() { test_bank_serialize_style(SerdeStyle::Newer) } +#[test] +fn test_accounts_serialize_older() { + test_accounts_serialize_style(SerdeStyle::Older) +} + +#[test] +fn test_bank_serialize_older() { + test_bank_serialize_style(SerdeStyle::Older) +} + #[cfg(RUSTC_WITH_SPECIALIZATION)] mod test_bank_serialize { use super::*; // This some what long test harness is required to freeze the ABI of // Bank's serialization due to versioned nature - #[frozen_abi(digest = "7PcarCw6gpw9Yw8xypdxQP24TFjLiaHyuDkq95cgwtte")] + #[frozen_abi(digest = "EPhJV2aMG2PpDcKiCGNArvYf4bfKt5ketGy8DDK7CdL4")] #[derive(Serialize, AbiExample)] pub struct BankAbiTestWrapperNewer { #[serde(serialize_with = "wrapper_newer")] @@ -332,4 +356,34 @@ mod test_bank_serialize { }) .serialize(s) } + + // This some what long test harness is required to freeze the ABI of + // Bank's serialization due to versioned nature + #[frozen_abi(digest = "5zTpYmVsKjkvpJB8o95LJWyXe2rV7bnxRPmmfKk75brf")] + #[derive(Serialize, AbiExample)] + pub struct BankAbiTestWrapperOlder { + #[serde(serialize_with = "wrapper_older")] + bank: Bank, + } + + pub fn wrapper_older(bank: &Bank, s: S) -> std::result::Result + where + S: serde::Serializer, + { + let snapshot_storages = bank + .rc + .accounts + .accounts_db + .get_snapshot_storages(0, None, None) + .0; + // ensure there is a single snapshot storage example for ABI digesting + assert_eq!(snapshot_storages.len(), 1); + + (SerializableBankAndStorage:: { + bank, + snapshot_storages: &snapshot_storages, + phantom: std::marker::PhantomData::default(), + }) + .serialize(s) + } } diff --git a/runtime/src/snapshot_utils.rs b/runtime/src/snapshot_utils.rs index c071899630ccea..358cfb2ebe189b 100644 --- a/runtime/src/snapshot_utils.rs +++ b/runtime/src/snapshot_utils.rs @@ -49,6 +49,7 @@ pub const DEFAULT_INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS: Slot = 100; const MAX_SNAPSHOT_DATA_FILE_SIZE: u64 = 32 * 1024 * 1024 * 1024; // 32 GiB const MAX_SNAPSHOT_VERSION_FILE_SIZE: u64 = 8; // byte const VERSION_STRING_V1_2_0: &str = "1.2.0"; +const VERSION_STRING_V1_3_0: &str = "1.3.0"; pub(crate) const TMP_BANK_SNAPSHOT_PREFIX: &str = "tmp-bank-snapshot-"; pub const TMP_SNAPSHOT_ARCHIVE_PREFIX: &str = "tmp-snapshot-archive-"; pub const MAX_BANK_SNAPSHOTS_TO_RETAIN: usize = 8; // Save some bank snapshots but not too many @@ -60,6 +61,7 @@ pub const INCREMENTAL_SNAPSHOT_ARCHIVE_FILENAME_REGEX: &str = r"^incremental-sna #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum SnapshotVersion { V1_2_0, + V1_3_0, } impl Default for SnapshotVersion { @@ -78,6 +80,7 @@ impl From for &'static str { fn from(snapshot_version: SnapshotVersion) -> &'static str { match snapshot_version { SnapshotVersion::V1_2_0 => VERSION_STRING_V1_2_0, + SnapshotVersion::V1_3_0 => VERSION_STRING_V1_3_0, } } } @@ -87,6 +90,7 @@ impl FromStr for SnapshotVersion { fn from_str(version_string: &str) -> std::result::Result { // Remove leading 'v' or 'V' from slice + // TODO: Once version 1.3.0 is the only supported version, remove this block that strips leading 'v'. let version_string = if version_string .get(..1) .map_or(false, |s| s.eq_ignore_ascii_case("v")) @@ -97,6 +101,7 @@ impl FromStr for SnapshotVersion { }; match version_string { VERSION_STRING_V1_2_0 => Ok(SnapshotVersion::V1_2_0), + VERSION_STRING_V1_3_0 => Ok(SnapshotVersion::V1_3_0), _ => Err("unsupported snapshot version"), } } @@ -639,7 +644,8 @@ pub fn add_bank_snapshot>( let mut bank_serialize = Measure::start("bank-serialize-ms"); let bank_snapshot_serializer = move |stream: &mut BufWriter| -> Result<()> { let serde_style = match snapshot_version { - SnapshotVersion::V1_2_0 => SerdeStyle::Newer, + SnapshotVersion::V1_2_0 => SerdeStyle::Older, + SnapshotVersion::V1_3_0 => SerdeStyle::Newer, }; bank_to_stream(serde_style, stream.by_ref(), bank, snapshot_storages)?; Ok(()) @@ -1476,6 +1482,22 @@ fn rebuild_bank_from_snapshots( Ok( match incremental_snapshot_version.unwrap_or(full_snapshot_version) { SnapshotVersion::V1_2_0 => bank_from_streams( + SerdeStyle::Older, + snapshot_streams, + account_paths, + unpacked_append_vec_map, + genesis_config, + debug_keys, + additional_builtins, + account_secondary_indexes, + accounts_db_caching_enabled, + limit_load_slot_count_from_snapshot, + shrink_ratio, + verify_index, + accounts_db_config, + accounts_update_notifier, + ), + SnapshotVersion::V1_3_0 => bank_from_streams( SerdeStyle::Newer, snapshot_streams, account_paths,