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