solana_accounts_db/account_storage/
meta.rs

1use {
2    crate::{
3        account_info::AccountInfo,
4        accounts_hash::AccountHash,
5        append_vec::AppendVecStoredAccountMeta,
6        tiered_storage::hot::{HotAccount, HotAccountMeta},
7    },
8    solana_sdk::{account::ReadableAccount, hash::Hash, pubkey::Pubkey, stake_history::Epoch},
9};
10
11pub type StoredMetaWriteVersion = u64;
12
13lazy_static! {
14    static ref DEFAULT_ACCOUNT_HASH: AccountHash = AccountHash(Hash::default());
15}
16
17/// References to account data stored elsewhere. Getting an `Account` requires cloning
18/// (see `StoredAccountMeta::clone_account()`).
19#[derive(PartialEq, Eq, Debug)]
20pub enum StoredAccountMeta<'storage> {
21    AppendVec(AppendVecStoredAccountMeta<'storage>),
22    Hot(HotAccount<'storage, HotAccountMeta>),
23}
24
25impl<'storage> StoredAccountMeta<'storage> {
26    pub fn pubkey(&self) -> &'storage Pubkey {
27        match self {
28            Self::AppendVec(av) => av.pubkey(),
29            Self::Hot(hot) => hot.address(),
30        }
31    }
32
33    pub fn hash(&self) -> &'storage AccountHash {
34        match self {
35            Self::AppendVec(av) => av.hash(),
36            // tiered-storage has deprecated the use of AccountHash
37            Self::Hot(_) => &DEFAULT_ACCOUNT_HASH,
38        }
39    }
40
41    pub fn stored_size(&self) -> usize {
42        match self {
43            Self::AppendVec(av) => av.stored_size(),
44            Self::Hot(hot) => hot.stored_size(),
45        }
46    }
47
48    pub fn offset(&self) -> usize {
49        match self {
50            Self::AppendVec(av) => av.offset(),
51            Self::Hot(hot) => AccountInfo::reduced_offset_to_offset(hot.index().0),
52        }
53    }
54
55    pub fn data(&self) -> &'storage [u8] {
56        match self {
57            Self::AppendVec(av) => av.data(),
58            Self::Hot(hot) => hot.data(),
59        }
60    }
61
62    pub fn data_len(&self) -> usize {
63        match self {
64            Self::AppendVec(av) => av.data_len() as usize,
65            Self::Hot(hot) => hot.data().len(),
66        }
67    }
68
69    pub fn meta(&self) -> &StoredMeta {
70        match self {
71            Self::AppendVec(av) => av.meta(),
72            // Hot account does not support this API as it does not
73            // use the same in-memory layout as StoredMeta.
74            Self::Hot(_) => unreachable!(),
75        }
76    }
77
78    pub(crate) fn sanitize(&self) -> bool {
79        match self {
80            Self::AppendVec(av) => av.sanitize(),
81            // Hot account currently doesn't have the concept of sanitization.
82            Self::Hot(_) => unimplemented!(),
83        }
84    }
85}
86
87impl<'storage> ReadableAccount for StoredAccountMeta<'storage> {
88    fn lamports(&self) -> u64 {
89        match self {
90            Self::AppendVec(av) => av.lamports(),
91            Self::Hot(hot) => hot.lamports(),
92        }
93    }
94    fn data(&self) -> &[u8] {
95        match self {
96            Self::AppendVec(av) => av.data(),
97            Self::Hot(hot) => hot.data(),
98        }
99    }
100    fn owner(&self) -> &Pubkey {
101        match self {
102            Self::AppendVec(av) => av.owner(),
103            Self::Hot(hot) => hot.owner(),
104        }
105    }
106    fn executable(&self) -> bool {
107        match self {
108            Self::AppendVec(av) => av.executable(),
109            Self::Hot(hot) => hot.executable(),
110        }
111    }
112    fn rent_epoch(&self) -> Epoch {
113        match self {
114            Self::AppendVec(av) => av.rent_epoch(),
115            Self::Hot(hot) => hot.rent_epoch(),
116        }
117    }
118}
119
120/// Meta contains enough context to recover the index from storage itself
121/// This struct will be backed by mmaped and snapshotted data files.
122/// So the data layout must be stable and consistent across the entire cluster!
123#[derive(Clone, PartialEq, Eq, Debug)]
124#[repr(C)]
125pub struct StoredMeta {
126    /// global write version
127    /// This will be made completely obsolete such that we stop storing it.
128    /// We will not support multiple append vecs per slot anymore, so this concept is no longer necessary.
129    /// Order of stores of an account to an append vec will determine 'latest' account data per pubkey.
130    pub write_version_obsolete: StoredMetaWriteVersion,
131    pub data_len: u64,
132    /// key for the account
133    pub pubkey: Pubkey,
134}
135
136/// This struct will be backed by mmaped and snapshotted data files.
137/// So the data layout must be stable and consistent across the entire cluster!
138#[derive(Serialize, Deserialize, Clone, Debug, Default, Eq, PartialEq)]
139#[repr(C)]
140pub struct AccountMeta {
141    /// lamports in the account
142    pub lamports: u64,
143    /// the epoch at which this account will next owe rent
144    pub rent_epoch: Epoch,
145    /// the program that owns this account. If executable, the program that loads this account.
146    pub owner: Pubkey,
147    /// this account's data contains a loaded program (and is now read-only)
148    pub executable: bool,
149}
150
151impl<'a, T: ReadableAccount> From<&'a T> for AccountMeta {
152    fn from(account: &'a T) -> Self {
153        Self {
154            lamports: account.lamports(),
155            owner: *account.owner(),
156            executable: account.executable(),
157            rent_epoch: account.rent_epoch(),
158        }
159    }
160}
161
162impl<'a, T: ReadableAccount> From<Option<&'a T>> for AccountMeta {
163    fn from(account: Option<&'a T>) -> Self {
164        match account {
165            Some(account) => AccountMeta::from(account),
166            None => AccountMeta::default(),
167        }
168    }
169}