miraland_program_runtime/
sysvar_cache.rs1#[allow(deprecated)]
2use miraland_sdk::sysvar::{
3 fees::Fees, last_restart_slot::LastRestartSlot, recent_blockhashes::RecentBlockhashes,
4};
5use {
6 crate::invoke_context::InvokeContext,
7 miraland_sdk::{
8 instruction::InstructionError,
9 pubkey::Pubkey,
10 sysvar::{
11 clock::Clock, epoch_rewards::EpochRewards, epoch_schedule::EpochSchedule, rent::Rent,
12 slot_hashes::SlotHashes, stake_history::StakeHistory, Sysvar, SysvarId,
13 },
14 transaction_context::{IndexOfAccount, InstructionContext, TransactionContext},
15 },
16 std::sync::Arc,
17};
18
19#[cfg(RUSTC_WITH_SPECIALIZATION)]
20impl ::miraland_frozen_abi::abi_example::AbiExample for SysvarCache {
21 fn example() -> Self {
22 SysvarCache::default()
24 }
25}
26
27#[derive(Default, Clone, Debug)]
28pub struct SysvarCache {
29 clock: Option<Arc<Clock>>,
30 epoch_schedule: Option<Arc<EpochSchedule>>,
31 epoch_rewards: Option<Arc<EpochRewards>>,
32 #[allow(deprecated)]
33 fees: Option<Arc<Fees>>,
34 rent: Option<Arc<Rent>>,
35 slot_hashes: Option<Arc<SlotHashes>>,
36 #[allow(deprecated)]
37 recent_blockhashes: Option<Arc<RecentBlockhashes>>,
38 stake_history: Option<Arc<StakeHistory>>,
39 last_restart_slot: Option<Arc<LastRestartSlot>>,
40}
41
42impl SysvarCache {
43 pub fn get_clock(&self) -> Result<Arc<Clock>, InstructionError> {
44 self.clock
45 .clone()
46 .ok_or(InstructionError::UnsupportedSysvar)
47 }
48
49 pub fn set_clock(&mut self, clock: Clock) {
50 self.clock = Some(Arc::new(clock));
51 }
52
53 pub fn get_epoch_schedule(&self) -> Result<Arc<EpochSchedule>, InstructionError> {
54 self.epoch_schedule
55 .clone()
56 .ok_or(InstructionError::UnsupportedSysvar)
57 }
58
59 pub fn set_epoch_schedule(&mut self, epoch_schedule: EpochSchedule) {
60 self.epoch_schedule = Some(Arc::new(epoch_schedule));
61 }
62
63 pub fn get_epoch_rewards(&self) -> Result<Arc<EpochRewards>, InstructionError> {
64 self.epoch_rewards
65 .clone()
66 .ok_or(InstructionError::UnsupportedSysvar)
67 }
68
69 pub fn set_epoch_rewards(&mut self, epoch_rewards: EpochRewards) {
70 self.epoch_rewards = Some(Arc::new(epoch_rewards));
71 }
72
73 #[deprecated]
74 #[allow(deprecated)]
75 pub fn get_fees(&self) -> Result<Arc<Fees>, InstructionError> {
76 self.fees.clone().ok_or(InstructionError::UnsupportedSysvar)
77 }
78
79 #[deprecated]
80 #[allow(deprecated)]
81 pub fn set_fees(&mut self, fees: Fees) {
82 self.fees = Some(Arc::new(fees));
83 }
84
85 pub fn get_rent(&self) -> Result<Arc<Rent>, InstructionError> {
86 self.rent.clone().ok_or(InstructionError::UnsupportedSysvar)
87 }
88
89 pub fn set_rent(&mut self, rent: Rent) {
90 self.rent = Some(Arc::new(rent));
91 }
92
93 pub fn get_last_restart_slot(&self) -> Result<Arc<LastRestartSlot>, InstructionError> {
94 self.last_restart_slot
95 .clone()
96 .ok_or(InstructionError::UnsupportedSysvar)
97 }
98
99 pub fn set_last_restart_slot(&mut self, last_restart_slot: LastRestartSlot) {
100 self.last_restart_slot = Some(Arc::new(last_restart_slot));
101 }
102
103 pub fn get_slot_hashes(&self) -> Result<Arc<SlotHashes>, InstructionError> {
104 self.slot_hashes
105 .clone()
106 .ok_or(InstructionError::UnsupportedSysvar)
107 }
108
109 pub fn set_slot_hashes(&mut self, slot_hashes: SlotHashes) {
110 self.slot_hashes = Some(Arc::new(slot_hashes));
111 }
112
113 #[deprecated]
114 #[allow(deprecated)]
115 pub fn get_recent_blockhashes(&self) -> Result<Arc<RecentBlockhashes>, InstructionError> {
116 self.recent_blockhashes
117 .clone()
118 .ok_or(InstructionError::UnsupportedSysvar)
119 }
120
121 #[deprecated]
122 #[allow(deprecated)]
123 pub fn set_recent_blockhashes(&mut self, recent_blockhashes: RecentBlockhashes) {
124 self.recent_blockhashes = Some(Arc::new(recent_blockhashes));
125 }
126
127 pub fn get_stake_history(&self) -> Result<Arc<StakeHistory>, InstructionError> {
128 self.stake_history
129 .clone()
130 .ok_or(InstructionError::UnsupportedSysvar)
131 }
132
133 pub fn set_stake_history(&mut self, stake_history: StakeHistory) {
134 self.stake_history = Some(Arc::new(stake_history));
135 }
136
137 pub fn fill_missing_entries<F: FnMut(&Pubkey, &mut dyn FnMut(&[u8]))>(
138 &mut self,
139 mut get_account_data: F,
140 ) {
141 if self.clock.is_none() {
142 get_account_data(&Clock::id(), &mut |data: &[u8]| {
143 if let Ok(clock) = bincode::deserialize(data) {
144 self.set_clock(clock);
145 }
146 });
147 }
148 if self.epoch_schedule.is_none() {
149 get_account_data(&EpochSchedule::id(), &mut |data: &[u8]| {
150 if let Ok(epoch_schedule) = bincode::deserialize(data) {
151 self.set_epoch_schedule(epoch_schedule);
152 }
153 });
154 }
155
156 if self.epoch_rewards.is_none() {
157 get_account_data(&EpochRewards::id(), &mut |data: &[u8]| {
158 if let Ok(epoch_rewards) = bincode::deserialize(data) {
159 self.set_epoch_rewards(epoch_rewards);
160 }
161 });
162 }
163
164 #[allow(deprecated)]
165 if self.fees.is_none() {
166 get_account_data(&Fees::id(), &mut |data: &[u8]| {
167 if let Ok(fees) = bincode::deserialize(data) {
168 self.set_fees(fees);
169 }
170 });
171 }
172 if self.rent.is_none() {
173 get_account_data(&Rent::id(), &mut |data: &[u8]| {
174 if let Ok(rent) = bincode::deserialize(data) {
175 self.set_rent(rent);
176 }
177 });
178 }
179 if self.slot_hashes.is_none() {
180 get_account_data(&SlotHashes::id(), &mut |data: &[u8]| {
181 if let Ok(slot_hashes) = bincode::deserialize(data) {
182 self.set_slot_hashes(slot_hashes);
183 }
184 });
185 }
186 #[allow(deprecated)]
187 if self.recent_blockhashes.is_none() {
188 get_account_data(&RecentBlockhashes::id(), &mut |data: &[u8]| {
189 if let Ok(recent_blockhashes) = bincode::deserialize(data) {
190 self.set_recent_blockhashes(recent_blockhashes);
191 }
192 });
193 }
194 if self.stake_history.is_none() {
195 get_account_data(&StakeHistory::id(), &mut |data: &[u8]| {
196 if let Ok(stake_history) = bincode::deserialize(data) {
197 self.set_stake_history(stake_history);
198 }
199 });
200 }
201 if self.last_restart_slot.is_none() {
202 get_account_data(&LastRestartSlot::id(), &mut |data: &[u8]| {
203 if let Ok(last_restart_slot) = bincode::deserialize(data) {
204 self.set_last_restart_slot(last_restart_slot);
205 }
206 });
207 }
208 }
209
210 pub fn reset(&mut self) {
211 *self = SysvarCache::default();
212 }
213}
214
215pub mod get_sysvar_with_account_check {
221 use super::*;
222
223 fn check_sysvar_account<S: Sysvar>(
224 transaction_context: &TransactionContext,
225 instruction_context: &InstructionContext,
226 instruction_account_index: IndexOfAccount,
227 ) -> Result<(), InstructionError> {
228 let index_in_transaction = instruction_context
229 .get_index_of_instruction_account_in_transaction(instruction_account_index)?;
230 if !S::check_id(transaction_context.get_key_of_account_at_index(index_in_transaction)?) {
231 return Err(InstructionError::InvalidArgument);
232 }
233 Ok(())
234 }
235
236 pub fn clock(
237 invoke_context: &InvokeContext,
238 instruction_context: &InstructionContext,
239 instruction_account_index: IndexOfAccount,
240 ) -> Result<Arc<Clock>, InstructionError> {
241 check_sysvar_account::<Clock>(
242 invoke_context.transaction_context,
243 instruction_context,
244 instruction_account_index,
245 )?;
246 invoke_context.get_sysvar_cache().get_clock()
247 }
248
249 pub fn rent(
250 invoke_context: &InvokeContext,
251 instruction_context: &InstructionContext,
252 instruction_account_index: IndexOfAccount,
253 ) -> Result<Arc<Rent>, InstructionError> {
254 check_sysvar_account::<Rent>(
255 invoke_context.transaction_context,
256 instruction_context,
257 instruction_account_index,
258 )?;
259 invoke_context.get_sysvar_cache().get_rent()
260 }
261
262 pub fn slot_hashes(
263 invoke_context: &InvokeContext,
264 instruction_context: &InstructionContext,
265 instruction_account_index: IndexOfAccount,
266 ) -> Result<Arc<SlotHashes>, InstructionError> {
267 check_sysvar_account::<SlotHashes>(
268 invoke_context.transaction_context,
269 instruction_context,
270 instruction_account_index,
271 )?;
272 invoke_context.get_sysvar_cache().get_slot_hashes()
273 }
274
275 #[allow(deprecated)]
276 pub fn recent_blockhashes(
277 invoke_context: &InvokeContext,
278 instruction_context: &InstructionContext,
279 instruction_account_index: IndexOfAccount,
280 ) -> Result<Arc<RecentBlockhashes>, InstructionError> {
281 check_sysvar_account::<RecentBlockhashes>(
282 invoke_context.transaction_context,
283 instruction_context,
284 instruction_account_index,
285 )?;
286 invoke_context.get_sysvar_cache().get_recent_blockhashes()
287 }
288
289 pub fn stake_history(
290 invoke_context: &InvokeContext,
291 instruction_context: &InstructionContext,
292 instruction_account_index: IndexOfAccount,
293 ) -> Result<Arc<StakeHistory>, InstructionError> {
294 check_sysvar_account::<StakeHistory>(
295 invoke_context.transaction_context,
296 instruction_context,
297 instruction_account_index,
298 )?;
299 invoke_context.get_sysvar_cache().get_stake_history()
300 }
301
302 pub fn last_restart_slot(
303 invoke_context: &InvokeContext,
304 instruction_context: &InstructionContext,
305 instruction_account_index: IndexOfAccount,
306 ) -> Result<Arc<LastRestartSlot>, InstructionError> {
307 check_sysvar_account::<LastRestartSlot>(
308 invoke_context.transaction_context,
309 instruction_context,
310 instruction_account_index,
311 )?;
312 invoke_context.get_sysvar_cache().get_last_restart_slot()
313 }
314}