1use {
2 crate::{AccountSharedData, ReadableAccount, traits::debug_fmt},
3 solana_account_info::AccountInfo,
4 solana_clock::Epoch,
5 solana_pubkey::Pubkey,
6 solana_sdk_ids::{
7 bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, loader_v4, native_loader,
8 },
9 std::{cell::RefCell, fmt, rc::Rc},
10};
11
12#[repr(C)]
14#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "camelCase"))]
15#[cfg_attr(feature = "wincode", derive(wincode::SchemaRead, wincode::SchemaWrite))]
16#[derive(PartialEq, Eq, Clone, Default)]
17pub struct Account {
18 pub lamports: u64,
20 #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
22 pub data: Vec<u8>,
23 pub owner: Pubkey,
25 pub executable: bool,
27 pub rent_epoch: Epoch,
29}
30
31#[cfg(feature = "serde")]
32mod account_serialize {
33 use {
34 crate::ReadableAccount,
35 serde::{Serialize, ser::Serializer},
36 solana_clock::Epoch,
37 solana_pubkey::Pubkey,
38 };
39
40 #[repr(C)]
41 #[derive(serde::Serialize)]
42 #[serde(rename_all = "camelCase")]
43 struct Account<'a> {
45 lamports: u64,
46 #[serde(with = "serde_bytes")]
47 data: &'a [u8],
48 owner: &'a Pubkey,
49 executable: bool,
50 rent_epoch: Epoch,
51 }
52
53 pub(crate) fn serialize_account<S>(
55 account: &impl ReadableAccount,
56 serializer: S,
57 ) -> Result<S::Ok, S::Error>
58 where
59 S: Serializer,
60 {
61 let account = Account {
62 lamports: account.lamports(),
63 data: account.data(),
64 owner: account.owner(),
65 executable: account.executable(),
66 rent_epoch: account.rent_epoch(),
67 };
68 account.serialize(serializer)
69 }
70}
71
72#[cfg(feature = "serde")]
73impl serde::ser::Serialize for Account {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: serde::ser::Serializer,
77 {
78 account_serialize::serialize_account(self, serializer)
79 }
80}
81
82#[cfg(feature = "serde")]
83impl serde::ser::Serialize for AccountSharedData {
84 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85 where
86 S: serde::ser::Serializer,
87 {
88 account_serialize::serialize_account(self, serializer)
89 }
90}
91
92impl From<AccountSharedData> for Account {
93 fn from(other: AccountSharedData) -> Self {
94 Self {
95 lamports: other.lamports(),
96 data: other.data().to_vec(),
97 owner: *other.owner(),
98 executable: other.executable(),
99 rent_epoch: other.rent_epoch(),
100 }
101 }
102}
103
104impl fmt::Debug for Account {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 debug_fmt(self, f, |_| {})
107 }
108}
109
110impl fmt::Debug for AccountSharedData {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 debug_fmt(self, f, |f| {
113 f.field("slot", &self.slot())
114 .field("mode", &self.mode)
115 .field("flags", self.flags())
116 .field("dirty", self.markers());
117 })
118 }
119}
120
121impl Account {
122 fn from_parts(
126 lamports: u64,
127 data: Vec<u8>,
128 owner: Pubkey,
129 executable: bool,
130 rent_epoch: Epoch,
131 ) -> Self {
132 Self {
133 lamports,
134 data,
135 owner,
136 executable,
137 rent_epoch,
138 }
139 }
140
141 pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
143 Self::new_rent_epoch(lamports, space, owner, Epoch::default())
144 }
145
146 pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
148 Rc::new(RefCell::new(Self::new(lamports, space, owner)))
149 }
150
151 #[cfg(feature = "bincode")]
153 pub fn new_data<T: serde::Serialize>(
154 lamports: u64,
155 state: &T,
156 owner: &Pubkey,
157 ) -> Result<Self, bincode::Error> {
158 let data = bincode::serialize(state)?;
159 Ok(Self::from_parts(
160 lamports,
161 data,
162 *owner,
163 false,
164 Epoch::default(),
165 ))
166 }
167
168 #[cfg(feature = "bincode")]
170 pub fn new_ref_data<T: serde::Serialize>(
171 lamports: u64,
172 state: &T,
173 owner: &Pubkey,
174 ) -> Result<RefCell<Self>, bincode::Error> {
175 Self::new_data(lamports, state, owner).map(RefCell::new)
176 }
177
178 #[cfg(feature = "bincode")]
180 pub fn new_data_with_space<T: serde::Serialize>(
181 lamports: u64,
182 state: &T,
183 space: usize,
184 owner: &Pubkey,
185 ) -> Result<Self, bincode::Error> {
186 let mut account = Self::new(lamports, space, owner);
187 crate::codec::serialize_data(&mut account, state)?;
188 Ok(account)
189 }
190
191 #[cfg(feature = "bincode")]
193 pub fn new_ref_data_with_space<T: serde::Serialize>(
194 lamports: u64,
195 state: &T,
196 space: usize,
197 owner: &Pubkey,
198 ) -> Result<RefCell<Self>, bincode::Error> {
199 Self::new_data_with_space(lamports, state, space, owner).map(RefCell::new)
200 }
201
202 pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
204 Self::from_parts(lamports, vec![0; space], *owner, false, rent_epoch)
205 }
206
207 #[cfg(feature = "bincode")]
209 pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
210 crate::codec::deserialize_data(self)
211 }
212
213 #[cfg(feature = "bincode")]
215 pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
216 crate::codec::serialize_data(self, state)
217 }
218}
219
220impl solana_account_info::Account for Account {
221 fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool) {
222 (
223 &mut self.lamports,
224 &mut self.data,
225 &self.owner,
226 self.executable,
227 )
228 }
229}
230
231pub fn create_is_signer_account_infos<'a>(
235 accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
236) -> Vec<AccountInfo<'a>> {
237 accounts
238 .iter_mut()
239 .map(|(key, is_signer, account)| {
240 AccountInfo::new(
241 key,
242 *is_signer,
243 false,
244 &mut account.lamports,
245 &mut account.data,
246 &account.owner,
247 account.executable,
248 )
249 })
250 .collect()
251}
252
253pub const PROGRAM_OWNERS: &[Pubkey] = &[
255 native_loader::id(),
256 bpf_loader_upgradeable::id(),
257 bpf_loader::id(),
258 bpf_loader_deprecated::id(),
259 loader_v4::id(),
260];