magicblock_account/
traits.rs1use {
2 crate::{
3 Account, AccountSharedData,
4 cow::{DirtyMarkers, StateFlags},
5 },
6 solana_account_info::debug_account_data::debug_account_data,
7 solana_clock::Epoch,
8 solana_instruction_error::LamportsError,
9 solana_pubkey::Pubkey,
10 std::{fmt, ops::Deref},
11};
12
13pub trait ReadableAccount: Sized {
15 fn lamports(&self) -> u64;
17
18 fn data(&self) -> &[u8];
20
21 fn owner(&self) -> &Pubkey;
23
24 fn executable(&self) -> bool;
26
27 fn rent_epoch(&self) -> Epoch;
29}
30
31pub trait WritableAccount: ReadableAccount {
33 fn set_lamports(&mut self, lamports: u64);
35
36 fn checked_add_lamports(&mut self, lamports: u64) -> Result<(), LamportsError> {
38 self.set_lamports(
39 self.lamports().checked_add(lamports).ok_or(LamportsError::ArithmeticOverflow)?,
40 );
41 Ok(())
42 }
43
44 fn checked_sub_lamports(&mut self, lamports: u64) -> Result<(), LamportsError> {
46 self.set_lamports(
47 self.lamports()
48 .checked_sub(lamports)
49 .ok_or(LamportsError::ArithmeticUnderflow)?,
50 );
51 Ok(())
52 }
53
54 fn saturating_add_lamports(&mut self, lamports: u64) {
56 self.set_lamports(self.lamports().saturating_add(lamports))
57 }
58
59 fn saturating_sub_lamports(&mut self, lamports: u64) {
61 self.set_lamports(self.lamports().saturating_sub(lamports))
62 }
63
64 fn data_as_mut_slice(&mut self) -> &mut [u8];
66
67 fn set_owner(&mut self, owner: Pubkey);
69
70 fn copy_into_owner_from_slice(&mut self, source: &[u8]);
72
73 fn set_executable(&mut self, executable: bool);
75
76 fn set_rent_epoch(&mut self, epoch: Epoch);
80}
81
82pub fn accounts_equal<T: ReadableAccount, U: ReadableAccount>(me: &T, other: &U) -> bool {
86 me.lamports() == other.lamports()
87 && me.executable() == other.executable()
88 && me.rent_epoch() == other.rent_epoch()
89 && me.owner() == other.owner()
90 && me.data() == other.data()
91}
92
93pub(crate) fn debug_fmt<T: ReadableAccount>(
95 item: &T,
96 f: &mut fmt::Formatter<'_>,
97 add: impl FnOnce(&mut fmt::DebugStruct<'_, '_>),
98) -> fmt::Result {
99 let mut f = f.debug_struct("Account");
100
101 f.field("lamports", &item.lamports())
102 .field("data.len", &item.data().len())
103 .field("owner", &item.owner())
104 .field("executable", &item.executable())
105 .field("rent_epoch", &item.rent_epoch());
106 add(&mut f);
107 debug_account_data(item.data(), &mut f);
108
109 f.finish()
110}
111
112impl<T> ReadableAccount for T
113where
114 T: Deref,
115 T::Target: ReadableAccount,
116{
117 fn lamports(&self) -> u64 {
118 self.deref().lamports()
119 }
120
121 fn data(&self) -> &[u8] {
122 self.deref().data()
123 }
124
125 fn owner(&self) -> &Pubkey {
126 self.deref().owner()
127 }
128
129 fn executable(&self) -> bool {
130 self.deref().executable()
131 }
132
133 fn rent_epoch(&self) -> Epoch {
134 self.deref().rent_epoch()
135 }
136}
137
138impl ReadableAccount for Account {
139 fn lamports(&self) -> u64 {
140 self.lamports
141 }
142
143 fn data(&self) -> &[u8] {
144 &self.data
145 }
146
147 fn owner(&self) -> &Pubkey {
148 &self.owner
149 }
150
151 fn executable(&self) -> bool {
152 self.executable
153 }
154
155 fn rent_epoch(&self) -> Epoch {
156 self.rent_epoch
157 }
158}
159
160impl WritableAccount for Account {
161 fn set_lamports(&mut self, lamports: u64) {
162 self.lamports = lamports;
163 }
164
165 fn data_as_mut_slice(&mut self) -> &mut [u8] {
166 &mut self.data
167 }
168
169 fn set_owner(&mut self, owner: Pubkey) {
170 self.owner = owner;
171 }
172
173 fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
174 self.owner.as_mut().copy_from_slice(source);
175 }
176
177 fn set_executable(&mut self, executable: bool) {
178 self.executable = executable;
179 }
180
181 fn set_rent_epoch(&mut self, epoch: Epoch) {
182 self.rent_epoch = epoch;
183 }
184}
185
186impl ReadableAccount for AccountSharedData {
187 fn lamports(&self) -> u64 {
188 self.lamports
189 }
190
191 fn data(&self) -> &[u8] {
192 self.cow.data()
193 }
194
195 fn owner(&self) -> &Pubkey {
196 &self.owner
197 }
198
199 fn executable(&self) -> bool {
200 self.flags.contains(StateFlags::EXECUTABLE)
201 }
202
203 fn rent_epoch(&self) -> Epoch {
204 Epoch::MAX
205 }
206}
207
208impl WritableAccount for AccountSharedData {
209 fn set_lamports(&mut self, lamports: u64) {
210 if self.lamports == lamports {
211 return;
212 }
213 self.translate();
214 self.dirty.insert(DirtyMarkers::LAMPORTS);
215 self.lamports = lamports;
216 }
217
218 fn data_as_mut_slice(&mut self) -> &mut [u8] {
219 self.translate();
220 self.mark_data_dirty();
221 self.cow.data_mut()
222 }
223
224 fn set_owner(&mut self, owner: Pubkey) {
225 if self.owner == owner {
226 return;
227 }
228 self.translate();
229 self.dirty.insert(DirtyMarkers::OWNER);
230 self.owner = owner;
231 }
232
233 fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
234 self.translate();
235 self.dirty.insert(DirtyMarkers::OWNER);
236 self.owner.as_mut().copy_from_slice(source);
237 }
238
239 fn set_executable(&mut self, executable: bool) {
240 let mut flags = self.flags;
241 flags.set(StateFlags::EXECUTABLE, executable);
242 self.set_flags(flags);
243 }
244
245 fn set_rent_epoch(&mut self, _: Epoch) {}
246}