2020-05-22 10:54:24 -07:00
use {
crate ::{
2023-02-22 16:10:34 -08:00
account_storage ::meta ::StoredMetaWriteVersion ,
2020-05-22 10:54:24 -07:00
accounts ::Accounts ,
2021-06-09 21:21:32 -07:00
accounts_db ::{
2021-09-07 21:30:38 -07:00
AccountShrinkThreshold , AccountStorageEntry , AccountsDb , AccountsDbConfig , AppendVecId ,
2023-02-03 10:17:50 -08:00
AtomicAppendVecId , BankHashStats , IndexGenerationInfo ,
2021-06-09 21:21:32 -07:00
} ,
2023-02-15 17:24:04 -08:00
accounts_file ::AccountsFile ,
2023-02-24 12:27:12 -08:00
accounts_hash ::AccountsHash ,
2021-09-07 21:30:38 -07:00
accounts_index ::AccountSecondaryIndexes ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier_interface ::AccountsUpdateNotifier ,
2023-02-22 16:10:34 -08:00
append_vec ::AppendVec ,
2022-08-17 13:14:31 -07:00
bank ::{ Bank , BankFieldsToDeserialize , BankIncrementalSnapshotPersistence , BankRc } ,
2020-07-13 07:00:59 -07:00
blockhash_queue ::BlockhashQueue ,
2021-09-02 21:29:11 -07:00
builtins ::Builtins ,
2022-09-07 10:07:00 -07:00
epoch_accounts_hash ::EpochAccountsHash ,
2020-07-13 07:00:59 -07:00
epoch_stakes ::EpochStakes ,
rent_collector ::RentCollector ,
2022-08-05 12:49:00 -07:00
runtime_config ::RuntimeConfig ,
2022-07-06 15:30:30 -07:00
serde_snapshot ::storage ::SerializableAccountStorageEntry ,
2022-08-29 11:17:27 -07:00
snapshot_utils ::{ self , StorageAndNextAppendVecId , BANK_SNAPSHOT_PRE_FILENAME_EXTENSION } ,
2020-07-13 07:00:59 -07:00
stakes ::Stakes ,
2020-05-22 10:54:24 -07:00
} ,
2021-12-03 09:00:31 -08:00
bincode ::{ self , config ::Options , Error } ,
2021-03-10 09:49:10 -08:00
log ::* ,
2020-08-03 16:27:17 -07:00
serde ::{ de ::DeserializeOwned , Deserialize , Serialize } ,
2022-08-29 11:17:27 -07:00
solana_measure ::measure ::Measure ,
2020-07-13 07:00:59 -07:00
solana_sdk ::{
clock ::{ Epoch , Slot , UnixTimestamp } ,
2022-03-24 08:06:24 -07:00
deserialize_utils ::default_on_eof ,
2020-07-13 07:00:59 -07:00
epoch_schedule ::EpochSchedule ,
fee_calculator ::{ FeeCalculator , FeeRateGovernor } ,
genesis_config ::GenesisConfig ,
hard_forks ::HardForks ,
hash ::Hash ,
inflation ::Inflation ,
pubkey ::Pubkey ,
} ,
2020-05-22 10:54:24 -07:00
std ::{
2020-09-23 18:46:42 -07:00
collections ::{ HashMap , HashSet } ,
2021-03-10 09:49:10 -08:00
io ::{ self , BufReader , BufWriter , Read , Write } ,
2021-06-21 08:47:58 -07:00
path ::{ Path , PathBuf } ,
2020-05-22 10:54:24 -07:00
result ::Result ,
2021-09-23 15:34:32 -07:00
sync ::{
2022-09-12 11:51:12 -07:00
atomic ::{ AtomicBool , AtomicUsize , Ordering } ,
2022-08-29 11:17:27 -07:00
Arc ,
2021-09-23 15:34:32 -07:00
} ,
2021-10-24 12:43:33 -07:00
thread ::Builder ,
2020-05-22 10:54:24 -07:00
} ,
2022-08-29 11:17:27 -07:00
storage ::SerializableStorage ,
2020-05-22 10:54:24 -07:00
} ;
2022-01-13 05:12:09 -08:00
mod newer ;
2022-01-13 07:20:20 -08:00
mod storage ;
2020-05-22 10:54:24 -07:00
mod tests ;
2023-02-24 12:27:12 -08:00
mod types ;
2020-05-22 10:54:24 -07:00
mod utils ;
// a number of test cases in accounts_db use this
#[ cfg(test) ]
2022-01-13 07:20:20 -08:00
pub ( crate ) use tests ::reconstruct_accounts_db_via_serialization ;
2023-02-24 12:27:12 -08:00
pub ( crate ) use {
storage ::SerializedAppendVecId ,
2023-02-24 15:15:23 -08:00
types ::{ SerdeAccountsDeltaHash , SerdeAccountsHash , SerdeIncrementalAccountsHash } ,
2023-02-24 12:27:12 -08:00
} ;
2020-05-22 10:54:24 -07:00
#[ derive(Copy, Clone, Eq, PartialEq) ]
2020-07-13 07:00:59 -07:00
pub ( crate ) enum SerdeStyle {
2021-02-18 23:42:09 -08:00
Newer ,
2020-05-22 10:54:24 -07:00
}
2020-07-13 07:00:59 -07:00
const MAX_STREAM_SIZE : u64 = 32 * 1024 * 1024 * 1024 ;
2020-05-22 10:54:24 -07:00
2022-11-28 07:09:47 -08:00
#[ derive(Clone, Debug, Deserialize, Serialize, AbiExample, PartialEq, Eq) ]
2022-07-06 15:30:30 -07:00
pub struct AccountsDbFields < T > (
2021-05-17 16:58:36 -07:00
HashMap < Slot , Vec < T > > ,
StoredMetaWriteVersion ,
Slot ,
BankHashInfo ,
2022-03-24 08:06:24 -07:00
/// all slots that were roots within the last epoch
#[ serde(deserialize_with = " default_on_eof " ) ]
Vec < Slot > ,
/// slots that were roots within the last epoch for which we care about the hash value
#[ serde(deserialize_with = " default_on_eof " ) ]
Vec < ( Slot , Hash ) > ,
2021-05-17 16:58:36 -07:00
) ;
2020-05-22 10:54:24 -07:00
2023-02-03 10:17:50 -08:00
#[ derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, AbiExample) ]
struct BankHashInfo {
2023-02-20 09:25:15 -08:00
accounts_delta_hash : SerdeAccountsDeltaHash ,
accounts_hash : SerdeAccountsHash ,
2023-02-03 10:17:50 -08:00
stats : BankHashStats ,
}
2021-07-22 12:40:37 -07:00
/// Helper type to wrap BufReader streams when deserializing and reconstructing from either just a
/// full snapshot, or both a full and incremental snapshot
pub struct SnapshotStreams < ' a , R > {
pub full_snapshot_stream : & ' a mut BufReader < R > ,
pub incremental_snapshot_stream : Option < & ' a mut BufReader < R > > ,
}
/// Helper type to wrap AccountsDbFields when reconstructing AccountsDb from either just a full
/// snapshot, or both a full and incremental snapshot
#[ derive(Debug) ]
2022-07-06 15:30:30 -07:00
pub struct SnapshotAccountsDbFields < T > {
2021-07-22 12:40:37 -07:00
full_snapshot_accounts_db_fields : AccountsDbFields < T > ,
incremental_snapshot_accounts_db_fields : Option < AccountsDbFields < T > > ,
}
impl < T > SnapshotAccountsDbFields < T > {
/// Collapse the SnapshotAccountsDbFields into a single AccountsDbFields. If there is no
2022-03-24 08:06:24 -07:00
/// incremental snapshot, this returns the AccountsDbFields from the full snapshot.
/// Otherwise, use the AccountsDbFields from the incremental snapshot, and a combination
/// of the storages from both the full and incremental snapshots.
2021-07-22 12:40:37 -07:00
fn collapse_into ( self ) -> Result < AccountsDbFields < T > , Error > {
match self . incremental_snapshot_accounts_db_fields {
None = > Ok ( self . full_snapshot_accounts_db_fields ) ,
Some ( AccountsDbFields (
mut incremental_snapshot_storages ,
incremental_snapshot_version ,
incremental_snapshot_slot ,
incremental_snapshot_bank_hash_info ,
2022-04-02 10:01:43 -07:00
incremental_snapshot_historical_roots ,
incremental_snapshot_historical_roots_with_hash ,
2021-07-22 12:40:37 -07:00
) ) = > {
let full_snapshot_storages = self . full_snapshot_accounts_db_fields . 0 ;
let full_snapshot_slot = self . full_snapshot_accounts_db_fields . 2 ;
// filter out incremental snapshot storages with slot <= full snapshot slot
incremental_snapshot_storages . retain ( | slot , _ | * slot > full_snapshot_slot ) ;
// There must not be any overlap in the slots of storages between the full snapshot and the incremental snapshot
incremental_snapshot_storages
. iter ( )
2022-08-22 18:01:03 -07:00
. all ( | storage_entry | ! full_snapshot_storages . contains_key ( storage_entry . 0 ) ) . then_some ( ( ) ) . ok_or_else ( | | {
2021-07-22 12:40:37 -07:00
io ::Error ::new ( io ::ErrorKind ::InvalidData , " Snapshots are incompatible: There are storages for the same slot in both the full snapshot and the incremental snapshot! " )
} ) ? ;
let mut combined_storages = full_snapshot_storages ;
combined_storages . extend ( incremental_snapshot_storages . into_iter ( ) ) ;
Ok ( AccountsDbFields (
combined_storages ,
incremental_snapshot_version ,
incremental_snapshot_slot ,
incremental_snapshot_bank_hash_info ,
2022-04-02 10:01:43 -07:00
incremental_snapshot_historical_roots ,
incremental_snapshot_historical_roots_with_hash ,
2021-07-22 12:40:37 -07:00
) )
}
}
}
}
2022-04-06 19:55:44 -07:00
trait TypeContext < ' a > : PartialEq {
2020-05-22 10:54:24 -07:00
type SerializableAccountStorageEntry : Serialize
+ DeserializeOwned
+ From < & ' a AccountStorageEntry >
2021-06-16 06:48:24 -07:00
+ SerializableStorage
+ Sync ;
2020-05-22 10:54:24 -07:00
2020-07-13 07:00:59 -07:00
fn serialize_bank_and_storage < S : serde ::ser ::Serializer > (
2020-05-22 10:54:24 -07:00
serializer : S ,
2020-07-13 07:00:59 -07:00
serializable_bank : & SerializableBankAndStorage < ' a , Self > ,
2020-05-22 10:54:24 -07:00
) -> std ::result ::Result < S ::Ok , S ::Error >
where
Self : std ::marker ::Sized ;
2022-06-06 13:07:02 -07:00
#[ cfg(test) ]
fn serialize_bank_and_storage_without_extra_fields < S : serde ::ser ::Serializer > (
serializer : S ,
serializable_bank : & SerializableBankAndStorageNoExtra < ' a , Self > ,
) -> std ::result ::Result < S ::Ok , S ::Error >
where
Self : std ::marker ::Sized ;
2020-05-22 10:54:24 -07:00
fn serialize_accounts_db_fields < S : serde ::ser ::Serializer > (
serializer : S ,
2021-02-18 23:42:09 -08:00
serializable_db : & SerializableAccountsDb < ' a , Self > ,
2020-05-22 10:54:24 -07:00
) -> std ::result ::Result < S ::Ok , S ::Error >
where
Self : std ::marker ::Sized ;
2020-07-13 07:00:59 -07:00
fn deserialize_bank_fields < R > (
stream : & mut BufReader < R > ,
) -> Result <
(
BankFieldsToDeserialize ,
AccountsDbFields < Self ::SerializableAccountStorageEntry > ,
) ,
Error ,
>
where
R : Read ;
2020-05-22 10:54:24 -07:00
fn deserialize_accounts_db_fields < R > (
stream : & mut BufReader < R > ,
2020-07-13 07:00:59 -07:00
) -> Result < AccountsDbFields < Self ::SerializableAccountStorageEntry > , Error >
2020-05-22 10:54:24 -07:00
where
R : Read ;
2022-04-07 12:05:57 -07:00
/// deserialize the bank from 'stream_reader'
/// modify the accounts_hash
/// reserialize the bank to 'stream_writer'
fn reserialize_bank_fields_with_hash < R , W > (
stream_reader : & mut BufReader < R > ,
stream_writer : & mut BufWriter < W > ,
2022-11-28 07:09:47 -08:00
accounts_hash : & AccountsHash ,
2022-08-17 13:14:31 -07:00
incremental_snapshot_persistence : Option < & BankIncrementalSnapshotPersistence > ,
2022-04-07 12:05:57 -07:00
) -> std ::result ::Result < ( ) , Box < bincode ::ErrorKind > >
where
R : Read ,
W : Write ;
2020-07-13 07:00:59 -07:00
}
2020-05-22 10:54:24 -07:00
2020-07-13 07:00:59 -07:00
fn deserialize_from < R , T > ( reader : R ) -> bincode ::Result < T >
where
R : Read ,
T : DeserializeOwned ,
{
bincode ::options ( )
. with_limit ( MAX_STREAM_SIZE )
. with_fixint_encoding ( )
. allow_trailing_bytes ( )
. deserialize_from ::< R , T > ( reader )
2020-05-22 10:54:24 -07:00
}
2022-04-06 19:55:44 -07:00
/// used by tests to compare contents of serialized bank fields
/// serialized format is not deterministic - likely due to randomness in structs like hashmaps
pub ( crate ) fn compare_two_serialized_banks (
path1 : impl AsRef < Path > ,
path2 : impl AsRef < Path > ,
) -> std ::result ::Result < bool , Error > {
use std ::fs ::File ;
let file1 = File ::open ( path1 ) ? ;
let mut stream1 = BufReader ::new ( file1 ) ;
let file2 = File ::open ( path2 ) ? ;
let mut stream2 = BufReader ::new ( file2 ) ;
let fields1 = newer ::Context ::deserialize_bank_fields ( & mut stream1 ) ? ;
let fields2 = newer ::Context ::deserialize_bank_fields ( & mut stream2 ) ? ;
Ok ( fields1 = = fields2 )
}
2022-08-29 11:17:27 -07:00
/// Get snapshot storage lengths from accounts_db_fields
pub ( crate ) fn snapshot_storage_lengths_from_fields (
accounts_db_fields : & AccountsDbFields < SerializableAccountStorageEntry > ,
) -> HashMap < Slot , HashMap < SerializedAppendVecId , usize > > {
let AccountsDbFields ( snapshot_storage , .. ) = & accounts_db_fields ;
snapshot_storage
. iter ( )
. map ( | ( slot , slot_storage ) | {
(
* slot ,
slot_storage
. iter ( )
. map ( | storage_entry | ( storage_entry . id ( ) , storage_entry . current_len ( ) ) )
. collect ( ) ,
)
} )
. collect ( )
}
2022-07-21 10:27:31 -07:00
pub ( crate ) fn fields_from_stream < R : Read > (
serde_style : SerdeStyle ,
snapshot_stream : & mut BufReader < R > ,
) -> std ::result ::Result <
(
BankFieldsToDeserialize ,
AccountsDbFields < SerializableAccountStorageEntry > ,
) ,
Error ,
> {
match serde_style {
SerdeStyle ::Newer = > newer ::Context ::deserialize_bank_fields ( snapshot_stream ) ,
}
}
pub ( crate ) fn fields_from_streams < R : Read > (
2020-05-22 10:54:24 -07:00
serde_style : SerdeStyle ,
2021-07-22 12:40:37 -07:00
snapshot_streams : & mut SnapshotStreams < R > ,
2022-07-06 15:30:30 -07:00
) -> std ::result ::Result <
(
BankFieldsToDeserialize ,
SnapshotAccountsDbFields < SerializableAccountStorageEntry > ,
) ,
Error ,
2022-07-21 10:27:31 -07:00
> {
let ( full_snapshot_bank_fields , full_snapshot_accounts_db_fields ) =
fields_from_stream ( serde_style , snapshot_streams . full_snapshot_stream ) ? ;
let incremental_fields = snapshot_streams
. incremental_snapshot_stream
. as_mut ( )
. map ( | stream | fields_from_stream ( serde_style , stream ) )
. transpose ( ) ? ;
let ( incremental_snapshot_bank_fields , incremental_snapshot_accounts_db_fields ) =
2023-01-24 14:07:29 -08:00
incremental_fields . unzip ( ) ;
2022-07-05 14:37:20 -07:00
let snapshot_accounts_db_fields = SnapshotAccountsDbFields {
full_snapshot_accounts_db_fields ,
incremental_snapshot_accounts_db_fields ,
} ;
2022-07-06 15:30:30 -07:00
Ok ( (
2022-07-05 14:37:20 -07:00
incremental_snapshot_bank_fields . unwrap_or ( full_snapshot_bank_fields ) ,
snapshot_accounts_db_fields ,
2022-07-06 15:30:30 -07:00
) )
}
#[ allow(clippy::too_many_arguments) ]
pub ( crate ) fn bank_from_streams < R > (
serde_style : SerdeStyle ,
snapshot_streams : & mut SnapshotStreams < R > ,
account_paths : & [ PathBuf ] ,
2022-08-29 11:17:27 -07:00
storage_and_next_append_vec_id : StorageAndNextAppendVecId ,
2022-07-06 15:30:30 -07:00
genesis_config : & GenesisConfig ,
2022-08-05 12:49:00 -07:00
runtime_config : & RuntimeConfig ,
2022-07-06 15:30:30 -07:00
debug_keys : Option < Arc < HashSet < Pubkey > > > ,
additional_builtins : Option < & Builtins > ,
account_secondary_indexes : AccountSecondaryIndexes ,
limit_load_slot_count_from_snapshot : Option < usize > ,
shrink_ratio : AccountShrinkThreshold ,
verify_index : bool ,
accounts_db_config : Option < AccountsDbConfig > ,
accounts_update_notifier : Option < AccountsUpdateNotifier > ,
2022-09-12 11:51:12 -07:00
exit : & Arc < AtomicBool > ,
2022-07-06 15:30:30 -07:00
) -> std ::result ::Result < Bank , Error >
where
R : Read ,
{
let ( bank_fields , accounts_db_fields ) = fields_from_streams ( serde_style , snapshot_streams ) ? ;
reconstruct_bank_from_fields (
bank_fields ,
accounts_db_fields ,
2022-07-05 14:37:20 -07:00
genesis_config ,
2022-08-05 12:49:00 -07:00
runtime_config ,
2022-07-05 14:37:20 -07:00
account_paths ,
2022-08-29 11:17:27 -07:00
storage_and_next_append_vec_id ,
2022-07-05 14:37:20 -07:00
debug_keys ,
additional_builtins ,
account_secondary_indexes ,
limit_load_slot_count_from_snapshot ,
shrink_ratio ,
verify_index ,
accounts_db_config ,
accounts_update_notifier ,
2022-09-12 11:51:12 -07:00
exit ,
2022-07-05 14:37:20 -07:00
)
2020-05-22 10:54:24 -07:00
}
2020-07-13 07:00:59 -07:00
pub ( crate ) fn bank_to_stream < W > (
2020-05-22 10:54:24 -07:00
serde_style : SerdeStyle ,
stream : & mut BufWriter < W > ,
2020-07-13 07:00:59 -07:00
bank : & Bank ,
2023-01-18 07:10:56 -08:00
snapshot_storages : & [ Vec < Arc < AccountStorageEntry > > ] ,
2020-06-17 01:56:29 -07:00
) -> Result < ( ) , Error >
2020-05-22 10:54:24 -07:00
where
W : Write ,
{
match serde_style {
2022-07-05 14:37:20 -07:00
SerdeStyle ::Newer = > bincode ::serialize_into (
stream ,
& SerializableBankAndStorage ::< newer ::Context > {
bank ,
snapshot_storages ,
phantom : std ::marker ::PhantomData ::default ( ) ,
} ,
) ,
2020-05-22 10:54:24 -07:00
}
}
2022-06-06 13:07:02 -07:00
#[ cfg(test) ]
pub ( crate ) fn bank_to_stream_no_extra_fields < W > (
serde_style : SerdeStyle ,
stream : & mut BufWriter < W > ,
bank : & Bank ,
2023-01-18 07:10:56 -08:00
snapshot_storages : & [ Vec < Arc < AccountStorageEntry > > ] ,
2022-06-06 13:07:02 -07:00
) -> Result < ( ) , Error >
where
W : Write ,
{
match serde_style {
2022-07-05 14:37:20 -07:00
SerdeStyle ::Newer = > bincode ::serialize_into (
stream ,
& SerializableBankAndStorageNoExtra ::< newer ::Context > {
bank ,
snapshot_storages ,
phantom : std ::marker ::PhantomData ::default ( ) ,
} ,
) ,
2022-06-06 13:07:02 -07:00
}
}
2022-04-07 12:05:57 -07:00
/// deserialize the bank from 'stream_reader'
/// modify the accounts_hash
/// reserialize the bank to 'stream_writer'
fn reserialize_bank_fields_with_new_hash < W , R > (
stream_reader : & mut BufReader < R > ,
stream_writer : & mut BufWriter < W > ,
2022-11-28 07:09:47 -08:00
accounts_hash : & AccountsHash ,
2022-08-17 13:14:31 -07:00
incremental_snapshot_persistence : Option < & BankIncrementalSnapshotPersistence > ,
2022-04-07 12:05:57 -07:00
) -> Result < ( ) , Error >
where
W : Write ,
R : Read ,
{
2022-08-17 13:14:31 -07:00
newer ::Context ::reserialize_bank_fields_with_hash (
stream_reader ,
stream_writer ,
accounts_hash ,
incremental_snapshot_persistence ,
)
2022-04-07 12:05:57 -07:00
}
/// effectively updates the accounts hash in the serialized bank file on disk
/// read serialized bank from pre file
/// update accounts_hash
/// write serialized bank to post file
/// return true if pre file found
pub fn reserialize_bank_with_new_accounts_hash (
bank_snapshots_dir : impl AsRef < Path > ,
slot : Slot ,
2022-11-28 07:09:47 -08:00
accounts_hash : & AccountsHash ,
2022-08-17 13:14:31 -07:00
incremental_snapshot_persistence : Option < & BankIncrementalSnapshotPersistence > ,
2022-04-07 12:05:57 -07:00
) -> bool {
2022-04-06 19:39:26 -07:00
let bank_post = snapshot_utils ::get_bank_snapshots_dir ( bank_snapshots_dir , slot ) ;
let bank_post = bank_post . join ( snapshot_utils ::get_snapshot_file_name ( slot ) ) ;
2023-02-15 09:52:07 -08:00
let bank_pre = bank_post . with_extension ( BANK_SNAPSHOT_PRE_FILENAME_EXTENSION ) ;
2022-04-06 19:39:26 -07:00
2022-04-07 12:05:57 -07:00
let mut found = false ;
{
let file = std ::fs ::File ::open ( & bank_pre ) ;
// some tests don't create the file
if let Ok ( file ) = file {
found = true ;
let file_out = std ::fs ::File ::create ( bank_post ) . unwrap ( ) ;
reserialize_bank_fields_with_new_hash (
& mut BufReader ::new ( file ) ,
& mut BufWriter ::new ( file_out ) ,
accounts_hash ,
2022-08-17 13:14:31 -07:00
incremental_snapshot_persistence ,
2022-04-07 12:05:57 -07:00
)
. unwrap ( ) ;
}
}
if found {
2022-04-06 19:39:26 -07:00
std ::fs ::remove_file ( bank_pre ) . unwrap ( ) ;
}
2022-04-07 12:05:57 -07:00
found
2022-04-06 19:39:26 -07:00
}
2020-07-13 07:00:59 -07:00
struct SerializableBankAndStorage < ' a , C > {
bank : & ' a Bank ,
2023-01-18 07:10:56 -08:00
snapshot_storages : & ' a [ Vec < Arc < AccountStorageEntry > > ] ,
2020-05-22 10:54:24 -07:00
phantom : std ::marker ::PhantomData < C > ,
}
2020-07-13 07:00:59 -07:00
impl < ' a , C : TypeContext < ' a > > Serialize for SerializableBankAndStorage < ' a , C > {
2020-05-22 10:54:24 -07:00
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : serde ::ser ::Serializer ,
{
2020-07-13 07:00:59 -07:00
C ::serialize_bank_and_storage ( serializer , self )
2020-05-22 10:54:24 -07:00
}
}
2022-06-06 13:07:02 -07:00
#[ cfg(test) ]
struct SerializableBankAndStorageNoExtra < ' a , C > {
bank : & ' a Bank ,
2023-01-18 07:10:56 -08:00
snapshot_storages : & ' a [ Vec < Arc < AccountStorageEntry > > ] ,
2022-06-06 13:07:02 -07:00
phantom : std ::marker ::PhantomData < C > ,
}
#[ cfg(test) ]
impl < ' a , C : TypeContext < ' a > > Serialize for SerializableBankAndStorageNoExtra < ' a , C > {
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : serde ::ser ::Serializer ,
{
C ::serialize_bank_and_storage_without_extra_fields ( serializer , self )
}
}
#[ cfg(test) ]
impl < ' a , C > From < SerializableBankAndStorageNoExtra < ' a , C > > for SerializableBankAndStorage < ' a , C > {
fn from ( s : SerializableBankAndStorageNoExtra < ' a , C > ) -> SerializableBankAndStorage < ' a , C > {
let SerializableBankAndStorageNoExtra {
bank ,
snapshot_storages ,
phantom ,
} = s ;
SerializableBankAndStorage {
bank ,
snapshot_storages ,
phantom ,
}
}
}
2021-02-18 23:42:09 -08:00
struct SerializableAccountsDb < ' a , C > {
accounts_db : & ' a AccountsDb ,
2020-05-22 10:54:24 -07:00
slot : Slot ,
2023-01-18 07:10:56 -08:00
account_storage_entries : & ' a [ Vec < Arc < AccountStorageEntry > > ] ,
2020-05-22 10:54:24 -07:00
phantom : std ::marker ::PhantomData < C > ,
}
2021-02-18 23:42:09 -08:00
impl < ' a , C : TypeContext < ' a > > Serialize for SerializableAccountsDb < ' a , C > {
2020-05-22 10:54:24 -07:00
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : serde ::ser ::Serializer ,
{
C ::serialize_accounts_db_fields ( serializer , self )
}
}
2020-07-13 07:00:59 -07:00
#[ cfg(RUSTC_WITH_SPECIALIZATION) ]
2022-01-13 05:12:09 -08:00
impl < ' a , C > solana_frozen_abi ::abi_example ::IgnoreAsHelper for SerializableAccountsDb < ' a , C > { }
2020-07-13 07:00:59 -07:00
2021-01-11 17:00:23 -08:00
#[ allow(clippy::too_many_arguments) ]
2021-03-10 09:49:10 -08:00
fn reconstruct_bank_from_fields < E > (
2020-07-13 07:00:59 -07:00
bank_fields : BankFieldsToDeserialize ,
2021-07-22 12:40:37 -07:00
snapshot_accounts_db_fields : SnapshotAccountsDbFields < E > ,
2020-07-13 07:00:59 -07:00
genesis_config : & GenesisConfig ,
2022-08-05 12:49:00 -07:00
runtime_config : & RuntimeConfig ,
2020-07-13 07:00:59 -07:00
account_paths : & [ PathBuf ] ,
2022-08-29 11:17:27 -07:00
storage_and_next_append_vec_id : StorageAndNextAppendVecId ,
2020-09-23 18:46:42 -07:00
debug_keys : Option < Arc < HashSet < Pubkey > > > ,
2020-09-24 12:23:09 -07:00
additional_builtins : Option < & Builtins > ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes : AccountSecondaryIndexes ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot : Option < usize > ,
2021-06-09 21:21:32 -07:00
shrink_ratio : AccountShrinkThreshold ,
2021-07-13 09:06:18 -07:00
verify_index : bool ,
2021-09-07 21:30:38 -07:00
accounts_db_config : Option < AccountsDbConfig > ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier : Option < AccountsUpdateNotifier > ,
2022-09-12 11:51:12 -07:00
exit : & Arc < AtomicBool > ,
2020-07-13 07:00:59 -07:00
) -> Result < Bank , Error >
where
2021-06-16 06:48:24 -07:00
E : SerializableStorage + std ::marker ::Sync ,
2020-07-13 07:00:59 -07:00
{
2021-12-10 11:27:59 -08:00
let ( accounts_db , reconstructed_accounts_db_info ) = reconstruct_accountsdb_from_fields (
2021-07-22 12:40:37 -07:00
snapshot_accounts_db_fields ,
2020-09-02 00:37:36 -07:00
account_paths ,
2022-08-29 11:17:27 -07:00
storage_and_next_append_vec_id ,
2021-10-11 10:46:27 -07:00
genesis_config ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot ,
2021-06-09 21:21:32 -07:00
shrink_ratio ,
2021-07-13 09:06:18 -07:00
verify_index ,
2021-09-07 21:30:38 -07:00
accounts_db_config ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier ,
2022-09-12 11:51:12 -07:00
exit ,
2022-09-07 10:07:00 -07:00
bank_fields . epoch_accounts_hash ,
2020-09-02 00:37:36 -07:00
) ? ;
2020-07-13 07:00:59 -07:00
let bank_rc = BankRc ::new ( Accounts ::new_empty ( accounts_db ) , bank_fields . slot ) ;
2022-08-05 12:49:00 -07:00
let runtime_config = Arc ::new ( runtime_config . clone ( ) ) ;
2021-06-15 13:39:22 -07:00
// if limit_load_slot_count_from_snapshot is set, then we need to side-step some correctness checks beneath this call
let debug_do_not_add_builtins = limit_load_slot_count_from_snapshot . is_some ( ) ;
2020-09-24 12:23:09 -07:00
let bank = Bank ::new_from_fields (
bank_rc ,
genesis_config ,
2022-08-05 12:49:00 -07:00
runtime_config ,
2020-09-24 12:23:09 -07:00
bank_fields ,
debug_keys ,
additional_builtins ,
2021-06-15 13:39:22 -07:00
debug_do_not_add_builtins ,
2021-12-11 07:34:38 -08:00
reconstructed_accounts_db_info . accounts_data_len ,
2020-09-24 12:23:09 -07:00
) ;
2020-07-13 07:00:59 -07:00
2021-11-04 04:28:41 -07:00
info! ( " rent_collector: {:?} " , bank . rent_collector ( ) ) ;
2020-07-13 07:00:59 -07:00
Ok ( bank )
}
2022-07-25 12:55:30 -07:00
fn reconstruct_single_storage (
2021-06-21 08:47:58 -07:00
slot : & Slot ,
append_vec_path : & Path ,
2022-07-25 12:55:30 -07:00
current_len : usize ,
2021-12-17 07:06:23 -08:00
append_vec_id : AppendVecId ,
2022-07-25 12:55:30 -07:00
) -> io ::Result < Arc < AccountStorageEntry > > {
2023-02-15 17:24:04 -08:00
let ( append_vec , num_accounts ) = AppendVec ::new_from_file ( append_vec_path , current_len ) ? ;
let accounts_file = AccountsFile ::AppendVec ( append_vec ) ;
2022-07-25 12:55:30 -07:00
Ok ( Arc ::new ( AccountStorageEntry ::new_existing (
* slot ,
append_vec_id ,
2023-02-15 17:24:04 -08:00
accounts_file ,
2022-07-25 12:55:30 -07:00
num_accounts ,
) ) )
}
fn remap_append_vec_file (
slot : Slot ,
old_append_vec_id : SerializedAppendVecId ,
append_vec_path : & Path ,
next_append_vec_id : & AtomicAppendVecId ,
num_collisions : & AtomicUsize ,
) -> io ::Result < ( AppendVecId , PathBuf ) > {
// Remap the AppendVec ID to handle any duplicate IDs that may previously existed
// due to full snapshots and incremental snapshots generated from different nodes
let ( remapped_append_vec_id , remapped_append_vec_path ) = loop {
let remapped_append_vec_id = next_append_vec_id . fetch_add ( 1 , Ordering ::AcqRel ) ;
let remapped_file_name = AppendVec ::file_name ( slot , remapped_append_vec_id ) ;
2022-11-09 11:39:38 -08:00
let remapped_append_vec_path = append_vec_path . parent ( ) . unwrap ( ) . join ( remapped_file_name ) ;
2022-07-25 12:55:30 -07:00
// Break out of the loop in the following situations:
// 1. The new ID is the same as the original ID. This means we do not need to
// rename the file, since the ID is the "correct" one already.
// 2. There is not a file already at the new path. This means it is safe to
// rename the file to this new path.
// **DEVELOPER NOTE:** Keep this check last so that it can short-circuit if
// possible.
if old_append_vec_id = = remapped_append_vec_id as SerializedAppendVecId
| | std ::fs ::metadata ( & remapped_append_vec_path ) . is_err ( )
{
break ( remapped_append_vec_id , remapped_append_vec_path ) ;
}
// If we made it this far, a file exists at the new path. Record the collision
// and try again.
num_collisions . fetch_add ( 1 , Ordering ::Relaxed ) ;
} ;
// Only rename the file if the new ID is actually different from the original.
if old_append_vec_id ! = remapped_append_vec_id as SerializedAppendVecId {
std ::fs ::rename ( append_vec_path , & remapped_append_vec_path ) ? ;
}
Ok ( ( remapped_append_vec_id , remapped_append_vec_path ) )
}
2022-08-29 11:17:27 -07:00
pub ( crate ) fn remap_and_reconstruct_single_storage (
2022-07-25 12:55:30 -07:00
slot : Slot ,
old_append_vec_id : SerializedAppendVecId ,
current_len : usize ,
append_vec_path : & Path ,
next_append_vec_id : & AtomicAppendVecId ,
num_collisions : & AtomicUsize ,
) -> io ::Result < Arc < AccountStorageEntry > > {
let ( remapped_append_vec_id , remapped_append_vec_path ) = remap_append_vec_file (
slot ,
old_append_vec_id ,
append_vec_path ,
next_append_vec_id ,
num_collisions ,
) ? ;
let storage = reconstruct_single_storage (
& slot ,
& remapped_append_vec_path ,
current_len ,
remapped_append_vec_id ,
) ? ;
Ok ( storage )
}
2021-12-10 11:27:59 -08:00
/// This struct contains side-info while reconstructing the accounts DB from fields.
#[ derive(Debug, Default, Copy, Clone) ]
struct ReconstructedAccountsDbInfo {
accounts_data_len : u64 ,
}
2021-08-10 03:45:46 -07:00
#[ allow(clippy::too_many_arguments) ]
2021-03-10 09:49:10 -08:00
fn reconstruct_accountsdb_from_fields < E > (
2021-07-22 12:40:37 -07:00
snapshot_accounts_db_fields : SnapshotAccountsDbFields < E > ,
2020-05-22 10:54:24 -07:00
account_paths : & [ PathBuf ] ,
2022-08-29 11:17:27 -07:00
storage_and_next_append_vec_id : StorageAndNextAppendVecId ,
2021-10-11 10:46:27 -07:00
genesis_config : & GenesisConfig ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes : AccountSecondaryIndexes ,
2021-05-26 08:36:12 -07:00
limit_load_slot_count_from_snapshot : Option < usize > ,
2021-06-09 21:21:32 -07:00
shrink_ratio : AccountShrinkThreshold ,
2021-07-13 09:06:18 -07:00
verify_index : bool ,
2021-09-07 21:30:38 -07:00
accounts_db_config : Option < AccountsDbConfig > ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier : Option < AccountsUpdateNotifier > ,
2022-09-12 11:51:12 -07:00
exit : & Arc < AtomicBool > ,
2022-09-07 10:07:00 -07:00
epoch_accounts_hash : Option < Hash > ,
2021-12-10 11:27:59 -08:00
) -> Result < ( AccountsDb , ReconstructedAccountsDbInfo ) , Error >
2020-05-22 10:54:24 -07:00
where
2021-06-16 06:48:24 -07:00
E : SerializableStorage + std ::marker ::Sync ,
2020-05-22 10:54:24 -07:00
{
2021-02-18 23:42:09 -08:00
let mut accounts_db = AccountsDb ::new_with_config (
2021-01-11 17:00:23 -08:00
account_paths . to_vec ( ) ,
2021-10-11 10:46:27 -07:00
& genesis_config . cluster_type ,
2021-07-22 12:40:37 -07:00
account_secondary_indexes ,
2021-06-09 21:21:32 -07:00
shrink_ratio ,
2021-09-07 21:30:38 -07:00
accounts_db_config ,
2021-09-30 14:26:17 -07:00
accounts_update_notifier ,
2022-09-12 11:51:12 -07:00
exit ,
2021-01-11 17:00:23 -08:00
) ;
2022-10-05 14:44:35 -07:00
if let Some ( epoch_accounts_hash ) = epoch_accounts_hash {
accounts_db
. epoch_accounts_hash_manager
. set_valid ( EpochAccountsHash ::new ( epoch_accounts_hash ) , 0 ) ;
}
2021-07-22 12:40:37 -07:00
let AccountsDbFields (
2022-08-29 11:17:27 -07:00
_snapshot_storages ,
2021-07-22 12:40:37 -07:00
snapshot_version ,
snapshot_slot ,
snapshot_bank_hash_info ,
2022-04-04 11:13:11 -07:00
snapshot_historical_roots ,
snapshot_historical_roots_with_hash ,
2021-07-22 12:40:37 -07:00
) = snapshot_accounts_db_fields . collapse_into ( ) ? ;
2021-01-02 17:57:56 -08:00
// Ensure all account paths exist
for path in & accounts_db . paths {
std ::fs ::create_dir_all ( path )
. unwrap_or_else ( | err | panic! ( " Failed to create directory {} : {} " , path . display ( ) , err ) ) ;
}
2022-04-04 11:13:11 -07:00
reconstruct_historical_roots (
& accounts_db ,
snapshot_historical_roots ,
snapshot_historical_roots_with_hash ,
) ;
2022-08-29 11:17:27 -07:00
let StorageAndNextAppendVecId {
storage ,
next_append_vec_id ,
} = storage_and_next_append_vec_id ;
2020-05-22 10:54:24 -07:00
2021-09-23 15:34:32 -07:00
assert! (
! storage . is_empty ( ) ,
" At least one storage entry must exist from deserializing stream "
) ;
2021-11-18 18:34:37 -08:00
let next_append_vec_id = next_append_vec_id . load ( Ordering ::Acquire ) ;
2021-09-23 15:34:32 -07:00
let max_append_vec_id = next_append_vec_id - 1 ;
assert! (
max_append_vec_id < = AppendVecId ::MAX / 2 ,
2022-12-06 06:30:06 -08:00
" Storage id {max_append_vec_id} larger than allowed max "
2021-09-23 15:34:32 -07:00
) ;
2020-05-22 10:54:24 -07:00
2021-09-23 15:34:32 -07:00
// Process deserialized data, set necessary fields in self
2023-02-02 13:50:44 -08:00
let old_accounts_delta_hash = accounts_db . set_accounts_delta_hash_from_snapshot (
snapshot_slot ,
snapshot_bank_hash_info . accounts_delta_hash ,
) ;
assert! (
old_accounts_delta_hash . is_none ( ) ,
" There should not already be an AccountsDeltaHash at slot {snapshot_slot}: {old_accounts_delta_hash:?} " ,
) ;
let old_accounts_hash = accounts_db
. set_accounts_hash_from_snapshot ( snapshot_slot , snapshot_bank_hash_info . accounts_hash ) ;
assert! (
old_accounts_hash . is_none ( ) ,
" There should not already be an AccountsHash at slot {snapshot_slot}: {old_accounts_hash:?} " ,
) ;
let old_stats = accounts_db
. update_bank_hash_stats_from_snapshot ( snapshot_slot , snapshot_bank_hash_info . stats ) ;
assert! (
old_stats . is_none ( ) ,
" There should not already be a BankHashStats at slot {snapshot_slot}: {old_stats:?} " ,
) ;
2023-01-02 14:55:02 -08:00
accounts_db . storage . initialize ( storage ) ;
2021-09-23 15:34:32 -07:00
accounts_db
. next_id
2021-11-18 18:34:37 -08:00
. store ( next_append_vec_id , Ordering ::Release ) ;
2020-05-22 10:54:24 -07:00
accounts_db
. write_version
2021-11-17 05:11:16 -08:00
. fetch_add ( snapshot_version , Ordering ::Release ) ;
2021-10-24 12:43:33 -07:00
let mut measure_notify = Measure ::start ( " accounts_notify " ) ;
let accounts_db = Arc ::new ( accounts_db ) ;
2022-03-08 16:28:00 -08:00
let accounts_db_clone = accounts_db . clone ( ) ;
2021-10-24 12:43:33 -07:00
let handle = Builder ::new ( )
2022-08-17 08:40:23 -07:00
. name ( " solNfyAccRestor " . to_string ( ) )
2021-10-24 12:43:33 -07:00
. spawn ( move | | {
2022-03-08 16:28:00 -08:00
accounts_db_clone . notify_account_restore_from_snapshot ( ) ;
2021-10-24 12:43:33 -07:00
} )
. unwrap ( ) ;
2022-07-12 15:51:33 -07:00
let IndexGenerationInfo {
accounts_data_len ,
rent_paying_accounts_by_partition ,
} = accounts_db . generate_index (
2021-11-03 12:44:52 -07:00
limit_load_slot_count_from_snapshot ,
verify_index ,
genesis_config ,
) ;
2022-07-14 06:52:41 -07:00
accounts_db
2022-07-12 15:51:33 -07:00
. accounts_index
. rent_paying_accounts_by_partition
2022-07-14 06:52:41 -07:00
. set ( rent_paying_accounts_by_partition )
. unwrap ( ) ;
2021-12-10 11:27:59 -08:00
2023-01-06 12:05:32 -08:00
accounts_db . maybe_add_filler_accounts ( & genesis_config . epoch_schedule , snapshot_slot ) ;
2021-09-23 15:34:32 -07:00
2021-10-24 12:43:33 -07:00
handle . join ( ) . unwrap ( ) ;
2021-09-30 14:26:17 -07:00
measure_notify . stop ( ) ;
2021-09-23 15:34:32 -07:00
datapoint_info! (
" reconstruct_accountsdb_from_fields() " ,
2021-09-30 14:26:17 -07:00
( " accountsdb-notify-at-start-us " , measure_notify . as_us ( ) , i64 ) ,
2021-09-23 15:34:32 -07:00
) ;
2021-12-10 11:27:59 -08:00
Ok ( (
Arc ::try_unwrap ( accounts_db ) . unwrap ( ) ,
ReconstructedAccountsDbInfo { accounts_data_len } ,
) )
2020-05-22 10:54:24 -07:00
}
2022-04-04 11:13:11 -07:00
/// populate 'historical_roots' from 'snapshot_historical_roots' and 'snapshot_historical_roots_with_hash'
fn reconstruct_historical_roots (
accounts_db : & AccountsDb ,
mut snapshot_historical_roots : Vec < Slot > ,
snapshot_historical_roots_with_hash : Vec < ( Slot , Hash ) > ,
) {
// inflate 'historical_roots'
// inserting into 'historical_roots' needs to be in order
// combine the slots into 1 vec, then sort
// dups are ok
snapshot_historical_roots . extend (
snapshot_historical_roots_with_hash
. into_iter ( )
. map ( | ( root , _ ) | root ) ,
) ;
snapshot_historical_roots . sort_unstable ( ) ;
let mut roots_tracker = accounts_db . accounts_index . roots_tracker . write ( ) . unwrap ( ) ;
snapshot_historical_roots . into_iter ( ) . for_each ( | root | {
roots_tracker . historical_roots . insert ( root ) ;
} ) ;
}