1#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#[cfg(feature = "frozen-abi")]
6use clone_solana_frozen_abi_macro::{frozen_abi, AbiExample};
7#[cfg(feature = "bincode")]
8use clone_solana_sysvar::Sysvar;
9#[cfg(feature = "dev-context-only-utils")]
10use qualifier_attr::qualifiers;
11#[cfg(feature = "serde")]
12use serde::ser::{Serialize, Serializer};
13use {
14 clone_solana_account_info::{debug_account_data::*, AccountInfo},
15 clone_solana_clock::{Epoch, INITIAL_RENT_EPOCH},
16 clone_solana_instruction::error::LamportsError,
17 clone_solana_pubkey::Pubkey,
18 clone_solana_sdk_ids::{bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, loader_v4},
19 std::{
20 cell::{Ref, RefCell},
21 fmt,
22 mem::MaybeUninit,
23 ptr,
24 rc::Rc,
25 sync::Arc,
26 },
27};
28#[cfg(feature = "bincode")]
29pub mod state_traits;
30
31#[repr(C)]
33#[cfg_attr(
34 feature = "frozen-abi",
35 derive(AbiExample),
36 frozen_abi(digest = "2SUJNHbXMPWrsSXmDTFc4VHx2XQ85fT5Leabefh5Nwe7")
37)]
38#[cfg_attr(
39 feature = "serde",
40 derive(serde_derive::Deserialize),
41 serde(rename_all = "camelCase")
42)]
43#[derive(PartialEq, Eq, Clone, Default)]
44pub struct Account {
45 pub lamports: u64,
47 #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
49 pub data: Vec<u8>,
50 pub owner: Pubkey,
52 pub executable: bool,
54 pub rent_epoch: Epoch,
56}
57
58#[cfg(feature = "serde")]
60mod account_serialize {
61 #[cfg(feature = "frozen-abi")]
62 use clone_solana_frozen_abi_macro::{frozen_abi, AbiExample};
63 use {
64 crate::ReadableAccount,
65 clone_solana_clock::Epoch,
66 clone_solana_pubkey::Pubkey,
67 serde::{ser::Serializer, Serialize},
68 };
69 #[repr(C)]
70 #[cfg_attr(
71 feature = "frozen-abi",
72 derive(AbiExample),
73 frozen_abi(digest = "2SUJNHbXMPWrsSXmDTFc4VHx2XQ85fT5Leabefh5Nwe7")
74 )]
75 #[derive(serde_derive::Serialize)]
76 #[serde(rename_all = "camelCase")]
77 struct Account<'a> {
78 lamports: u64,
79 #[serde(with = "serde_bytes")]
80 data: &'a [u8],
82 owner: &'a Pubkey,
83 executable: bool,
84 rent_epoch: Epoch,
85 }
86
87 pub fn serialize_account<S>(
89 account: &impl ReadableAccount,
90 serializer: S,
91 ) -> Result<S::Ok, S::Error>
92 where
93 S: Serializer,
94 {
95 let temp = Account {
96 lamports: account.lamports(),
97 data: account.data(),
98 owner: account.owner(),
99 executable: account.executable(),
100 rent_epoch: account.rent_epoch(),
101 };
102 temp.serialize(serializer)
103 }
104}
105
106#[cfg(feature = "serde")]
107impl Serialize for Account {
108 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
109 where
110 S: Serializer,
111 {
112 crate::account_serialize::serialize_account(self, serializer)
113 }
114}
115
116#[cfg(feature = "serde")]
117impl Serialize for AccountSharedData {
118 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
119 where
120 S: Serializer,
121 {
122 crate::account_serialize::serialize_account(self, serializer)
123 }
124}
125
126#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
130#[cfg_attr(
131 feature = "serde",
132 derive(serde_derive::Deserialize),
133 serde(from = "Account")
134)]
135#[derive(PartialEq, Eq, Clone, Default)]
136pub struct AccountSharedData {
137 lamports: u64,
139 data: Arc<Vec<u8>>,
141 owner: Pubkey,
143 executable: bool,
145 rent_epoch: Epoch,
147}
148
149pub fn accounts_equal<T: ReadableAccount, U: ReadableAccount>(me: &T, other: &U) -> bool {
153 me.lamports() == other.lamports()
154 && me.executable() == other.executable()
155 && me.rent_epoch() == other.rent_epoch()
156 && me.owner() == other.owner()
157 && me.data() == other.data()
158}
159
160impl From<AccountSharedData> for Account {
161 fn from(mut other: AccountSharedData) -> Self {
162 let account_data = Arc::make_mut(&mut other.data);
163 Self {
164 lamports: other.lamports,
165 data: std::mem::take(account_data),
166 owner: other.owner,
167 executable: other.executable,
168 rent_epoch: other.rent_epoch,
169 }
170 }
171}
172
173impl From<Account> for AccountSharedData {
174 fn from(other: Account) -> Self {
175 Self {
176 lamports: other.lamports,
177 data: Arc::new(other.data),
178 owner: other.owner,
179 executable: other.executable,
180 rent_epoch: other.rent_epoch,
181 }
182 }
183}
184
185pub trait WritableAccount: ReadableAccount {
186 fn set_lamports(&mut self, lamports: u64);
187 fn checked_add_lamports(&mut self, lamports: u64) -> Result<(), LamportsError> {
188 self.set_lamports(
189 self.lamports()
190 .checked_add(lamports)
191 .ok_or(LamportsError::ArithmeticOverflow)?,
192 );
193 Ok(())
194 }
195 fn checked_sub_lamports(&mut self, lamports: u64) -> Result<(), LamportsError> {
196 self.set_lamports(
197 self.lamports()
198 .checked_sub(lamports)
199 .ok_or(LamportsError::ArithmeticUnderflow)?,
200 );
201 Ok(())
202 }
203 fn saturating_add_lamports(&mut self, lamports: u64) {
204 self.set_lamports(self.lamports().saturating_add(lamports))
205 }
206 fn saturating_sub_lamports(&mut self, lamports: u64) {
207 self.set_lamports(self.lamports().saturating_sub(lamports))
208 }
209 fn data_as_mut_slice(&mut self) -> &mut [u8];
210 fn set_owner(&mut self, owner: Pubkey);
211 fn copy_into_owner_from_slice(&mut self, source: &[u8]);
212 fn set_executable(&mut self, executable: bool);
213 fn set_rent_epoch(&mut self, epoch: Epoch);
214 fn create(
215 lamports: u64,
216 data: Vec<u8>,
217 owner: Pubkey,
218 executable: bool,
219 rent_epoch: Epoch,
220 ) -> Self;
221}
222
223pub trait ReadableAccount: Sized {
224 fn lamports(&self) -> u64;
225 fn data(&self) -> &[u8];
226 fn owner(&self) -> &Pubkey;
227 fn executable(&self) -> bool;
228 fn rent_epoch(&self) -> Epoch;
229 fn to_account_shared_data(&self) -> AccountSharedData {
230 AccountSharedData::create(
231 self.lamports(),
232 self.data().to_vec(),
233 *self.owner(),
234 self.executable(),
235 self.rent_epoch(),
236 )
237 }
238}
239
240impl ReadableAccount for Account {
241 fn lamports(&self) -> u64 {
242 self.lamports
243 }
244 fn data(&self) -> &[u8] {
245 &self.data
246 }
247 fn owner(&self) -> &Pubkey {
248 &self.owner
249 }
250 fn executable(&self) -> bool {
251 self.executable
252 }
253 fn rent_epoch(&self) -> Epoch {
254 self.rent_epoch
255 }
256}
257
258impl WritableAccount for Account {
259 fn set_lamports(&mut self, lamports: u64) {
260 self.lamports = lamports;
261 }
262 fn data_as_mut_slice(&mut self) -> &mut [u8] {
263 &mut self.data
264 }
265 fn set_owner(&mut self, owner: Pubkey) {
266 self.owner = owner;
267 }
268 fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
269 self.owner.as_mut().copy_from_slice(source);
270 }
271 fn set_executable(&mut self, executable: bool) {
272 self.executable = executable;
273 }
274 fn set_rent_epoch(&mut self, epoch: Epoch) {
275 self.rent_epoch = epoch;
276 }
277 fn create(
278 lamports: u64,
279 data: Vec<u8>,
280 owner: Pubkey,
281 executable: bool,
282 rent_epoch: Epoch,
283 ) -> Self {
284 Account {
285 lamports,
286 data,
287 owner,
288 executable,
289 rent_epoch,
290 }
291 }
292}
293
294impl WritableAccount for AccountSharedData {
295 fn set_lamports(&mut self, lamports: u64) {
296 self.lamports = lamports;
297 }
298 fn data_as_mut_slice(&mut self) -> &mut [u8] {
299 &mut self.data_mut()[..]
300 }
301 fn set_owner(&mut self, owner: Pubkey) {
302 self.owner = owner;
303 }
304 fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
305 self.owner.as_mut().copy_from_slice(source);
306 }
307 fn set_executable(&mut self, executable: bool) {
308 self.executable = executable;
309 }
310 fn set_rent_epoch(&mut self, epoch: Epoch) {
311 self.rent_epoch = epoch;
312 }
313 fn create(
314 lamports: u64,
315 data: Vec<u8>,
316 owner: Pubkey,
317 executable: bool,
318 rent_epoch: Epoch,
319 ) -> Self {
320 AccountSharedData {
321 lamports,
322 data: Arc::new(data),
323 owner,
324 executable,
325 rent_epoch,
326 }
327 }
328}
329
330impl ReadableAccount for AccountSharedData {
331 fn lamports(&self) -> u64 {
332 self.lamports
333 }
334 fn data(&self) -> &[u8] {
335 &self.data
336 }
337 fn owner(&self) -> &Pubkey {
338 &self.owner
339 }
340 fn executable(&self) -> bool {
341 self.executable
342 }
343 fn rent_epoch(&self) -> Epoch {
344 self.rent_epoch
345 }
346 fn to_account_shared_data(&self) -> AccountSharedData {
347 self.clone()
349 }
350}
351
352impl ReadableAccount for Ref<'_, AccountSharedData> {
353 fn lamports(&self) -> u64 {
354 self.lamports
355 }
356 fn data(&self) -> &[u8] {
357 &self.data
358 }
359 fn owner(&self) -> &Pubkey {
360 &self.owner
361 }
362 fn executable(&self) -> bool {
363 self.executable
364 }
365 fn rent_epoch(&self) -> Epoch {
366 self.rent_epoch
367 }
368 fn to_account_shared_data(&self) -> AccountSharedData {
369 AccountSharedData {
370 lamports: self.lamports(),
371 data: Arc::clone(&self.data),
373 owner: *self.owner(),
374 executable: self.executable(),
375 rent_epoch: self.rent_epoch(),
376 }
377 }
378}
379
380impl ReadableAccount for Ref<'_, Account> {
381 fn lamports(&self) -> u64 {
382 self.lamports
383 }
384 fn data(&self) -> &[u8] {
385 &self.data
386 }
387 fn owner(&self) -> &Pubkey {
388 &self.owner
389 }
390 fn executable(&self) -> bool {
391 self.executable
392 }
393 fn rent_epoch(&self) -> Epoch {
394 self.rent_epoch
395 }
396}
397
398fn debug_fmt<T: ReadableAccount>(item: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
399 let mut f = f.debug_struct("Account");
400
401 f.field("lamports", &item.lamports())
402 .field("data.len", &item.data().len())
403 .field("owner", &item.owner())
404 .field("executable", &item.executable())
405 .field("rent_epoch", &item.rent_epoch());
406 debug_account_data(item.data(), &mut f);
407
408 f.finish()
409}
410
411impl fmt::Debug for Account {
412 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413 debug_fmt(self, f)
414 }
415}
416
417impl fmt::Debug for AccountSharedData {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 debug_fmt(self, f)
420 }
421}
422
423fn shared_new<T: WritableAccount>(lamports: u64, space: usize, owner: &Pubkey) -> T {
424 T::create(
425 lamports,
426 vec![0u8; space],
427 *owner,
428 bool::default(),
429 Epoch::default(),
430 )
431}
432
433fn shared_new_rent_epoch<T: WritableAccount>(
434 lamports: u64,
435 space: usize,
436 owner: &Pubkey,
437 rent_epoch: Epoch,
438) -> T {
439 T::create(
440 lamports,
441 vec![0u8; space],
442 *owner,
443 bool::default(),
444 rent_epoch,
445 )
446}
447
448fn shared_new_ref<T: WritableAccount>(
449 lamports: u64,
450 space: usize,
451 owner: &Pubkey,
452) -> Rc<RefCell<T>> {
453 Rc::new(RefCell::new(shared_new::<T>(lamports, space, owner)))
454}
455
456#[cfg(feature = "bincode")]
457fn shared_new_data<T: serde::Serialize, U: WritableAccount>(
458 lamports: u64,
459 state: &T,
460 owner: &Pubkey,
461) -> Result<U, bincode::Error> {
462 let data = bincode::serialize(state)?;
463 Ok(U::create(
464 lamports,
465 data,
466 *owner,
467 bool::default(),
468 Epoch::default(),
469 ))
470}
471
472#[cfg(feature = "bincode")]
473fn shared_new_ref_data<T: serde::Serialize, U: WritableAccount>(
474 lamports: u64,
475 state: &T,
476 owner: &Pubkey,
477) -> Result<RefCell<U>, bincode::Error> {
478 Ok(RefCell::new(shared_new_data::<T, U>(
479 lamports, state, owner,
480 )?))
481}
482
483#[cfg(feature = "bincode")]
484fn shared_new_data_with_space<T: serde::Serialize, U: WritableAccount>(
485 lamports: u64,
486 state: &T,
487 space: usize,
488 owner: &Pubkey,
489) -> Result<U, bincode::Error> {
490 let mut account = shared_new::<U>(lamports, space, owner);
491
492 shared_serialize_data(&mut account, state)?;
493
494 Ok(account)
495}
496
497#[cfg(feature = "bincode")]
498fn shared_new_ref_data_with_space<T: serde::Serialize, U: WritableAccount>(
499 lamports: u64,
500 state: &T,
501 space: usize,
502 owner: &Pubkey,
503) -> Result<RefCell<U>, bincode::Error> {
504 Ok(RefCell::new(shared_new_data_with_space::<T, U>(
505 lamports, state, space, owner,
506 )?))
507}
508
509#[cfg(feature = "bincode")]
510fn shared_deserialize_data<T: serde::de::DeserializeOwned, U: ReadableAccount>(
511 account: &U,
512) -> Result<T, bincode::Error> {
513 bincode::deserialize(account.data())
514}
515
516#[cfg(feature = "bincode")]
517fn shared_serialize_data<T: serde::Serialize, U: WritableAccount>(
518 account: &mut U,
519 state: &T,
520) -> Result<(), bincode::Error> {
521 if bincode::serialized_size(state)? > account.data().len() as u64 {
522 return Err(Box::new(bincode::ErrorKind::SizeLimit));
523 }
524 bincode::serialize_into(account.data_as_mut_slice(), state)
525}
526
527impl Account {
528 pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
529 shared_new(lamports, space, owner)
530 }
531 pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
532 shared_new_ref(lamports, space, owner)
533 }
534 #[cfg(feature = "bincode")]
535 pub fn new_data<T: serde::Serialize>(
536 lamports: u64,
537 state: &T,
538 owner: &Pubkey,
539 ) -> Result<Self, bincode::Error> {
540 shared_new_data(lamports, state, owner)
541 }
542 #[cfg(feature = "bincode")]
543 pub fn new_ref_data<T: serde::Serialize>(
544 lamports: u64,
545 state: &T,
546 owner: &Pubkey,
547 ) -> Result<RefCell<Self>, bincode::Error> {
548 shared_new_ref_data(lamports, state, owner)
549 }
550 #[cfg(feature = "bincode")]
551 pub fn new_data_with_space<T: serde::Serialize>(
552 lamports: u64,
553 state: &T,
554 space: usize,
555 owner: &Pubkey,
556 ) -> Result<Self, bincode::Error> {
557 shared_new_data_with_space(lamports, state, space, owner)
558 }
559 #[cfg(feature = "bincode")]
560 pub fn new_ref_data_with_space<T: serde::Serialize>(
561 lamports: u64,
562 state: &T,
563 space: usize,
564 owner: &Pubkey,
565 ) -> Result<RefCell<Self>, bincode::Error> {
566 shared_new_ref_data_with_space(lamports, state, space, owner)
567 }
568 pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
569 shared_new_rent_epoch(lamports, space, owner, rent_epoch)
570 }
571 #[cfg(feature = "bincode")]
572 pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
573 shared_deserialize_data(self)
574 }
575 #[cfg(feature = "bincode")]
576 pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
577 shared_serialize_data(self, state)
578 }
579}
580
581impl AccountSharedData {
582 pub fn is_shared(&self) -> bool {
583 Arc::strong_count(&self.data) > 1
584 }
585
586 pub fn reserve(&mut self, additional: usize) {
587 if let Some(data) = Arc::get_mut(&mut self.data) {
588 data.reserve(additional)
589 } else {
590 let mut data = Vec::with_capacity(self.data.len().saturating_add(additional));
591 data.extend_from_slice(&self.data);
592 self.data = Arc::new(data);
593 }
594 }
595
596 pub fn capacity(&self) -> usize {
597 self.data.capacity()
598 }
599
600 pub fn data_clone(&self) -> Arc<Vec<u8>> {
601 Arc::clone(&self.data)
602 }
603
604 fn data_mut(&mut self) -> &mut Vec<u8> {
605 Arc::make_mut(&mut self.data)
606 }
607
608 pub fn resize(&mut self, new_len: usize, value: u8) {
609 self.data_mut().resize(new_len, value)
610 }
611
612 pub fn extend_from_slice(&mut self, data: &[u8]) {
613 self.data_mut().extend_from_slice(data)
614 }
615
616 pub fn set_data_from_slice(&mut self, new_data: &[u8]) {
617 let Some(data) = Arc::get_mut(&mut self.data) else {
619 return self.set_data(new_data.to_vec());
622 };
623
624 let new_len = new_data.len();
625
626 data.reserve(new_len.saturating_sub(data.len()));
641
642 #[allow(clippy::uninit_vec)]
647 unsafe {
649 data.set_len(0);
650 ptr::copy_nonoverlapping(new_data.as_ptr(), data.as_mut_ptr(), new_len);
651 data.set_len(new_len);
652 };
653 }
654
655 #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
656 fn set_data(&mut self, data: Vec<u8>) {
657 self.data = Arc::new(data);
658 }
659
660 pub fn spare_data_capacity_mut(&mut self) -> &mut [MaybeUninit<u8>] {
661 self.data_mut().spare_capacity_mut()
662 }
663
664 pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
665 shared_new(lamports, space, owner)
666 }
667 pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
668 shared_new_ref(lamports, space, owner)
669 }
670 #[cfg(feature = "bincode")]
671 pub fn new_data<T: serde::Serialize>(
672 lamports: u64,
673 state: &T,
674 owner: &Pubkey,
675 ) -> Result<Self, bincode::Error> {
676 shared_new_data(lamports, state, owner)
677 }
678 #[cfg(feature = "bincode")]
679 pub fn new_ref_data<T: serde::Serialize>(
680 lamports: u64,
681 state: &T,
682 owner: &Pubkey,
683 ) -> Result<RefCell<Self>, bincode::Error> {
684 shared_new_ref_data(lamports, state, owner)
685 }
686 #[cfg(feature = "bincode")]
687 pub fn new_data_with_space<T: serde::Serialize>(
688 lamports: u64,
689 state: &T,
690 space: usize,
691 owner: &Pubkey,
692 ) -> Result<Self, bincode::Error> {
693 shared_new_data_with_space(lamports, state, space, owner)
694 }
695 #[cfg(feature = "bincode")]
696 pub fn new_ref_data_with_space<T: serde::Serialize>(
697 lamports: u64,
698 state: &T,
699 space: usize,
700 owner: &Pubkey,
701 ) -> Result<RefCell<Self>, bincode::Error> {
702 shared_new_ref_data_with_space(lamports, state, space, owner)
703 }
704 pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
705 shared_new_rent_epoch(lamports, space, owner, rent_epoch)
706 }
707 #[cfg(feature = "bincode")]
708 pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
709 shared_deserialize_data(self)
710 }
711 #[cfg(feature = "bincode")]
712 pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
713 shared_serialize_data(self, state)
714 }
715}
716
717pub type InheritableAccountFields = (u64, Epoch);
718pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH);
719
720#[cfg(feature = "bincode")]
721pub fn create_account_with_fields<S: Sysvar>(
722 sysvar: &S,
723 (lamports, rent_epoch): InheritableAccountFields,
724) -> Account {
725 let data_len = S::size_of().max(bincode::serialized_size(sysvar).unwrap() as usize);
726 let mut account = Account::new(lamports, data_len, &clone_solana_sdk_ids::sysvar::id());
727 to_account::<S, Account>(sysvar, &mut account).unwrap();
728 account.rent_epoch = rent_epoch;
729 account
730}
731
732#[cfg(feature = "bincode")]
733pub fn create_account_for_test<S: Sysvar>(sysvar: &S) -> Account {
734 create_account_with_fields(sysvar, DUMMY_INHERITABLE_ACCOUNT_FIELDS)
735}
736
737#[cfg(feature = "bincode")]
738pub fn create_account_shared_data_with_fields<S: Sysvar>(
740 sysvar: &S,
741 fields: InheritableAccountFields,
742) -> AccountSharedData {
743 AccountSharedData::from(create_account_with_fields(sysvar, fields))
744}
745
746#[cfg(feature = "bincode")]
747pub fn create_account_shared_data_for_test<S: Sysvar>(sysvar: &S) -> AccountSharedData {
748 AccountSharedData::from(create_account_with_fields(
749 sysvar,
750 DUMMY_INHERITABLE_ACCOUNT_FIELDS,
751 ))
752}
753
754#[cfg(feature = "bincode")]
755pub fn from_account<S: Sysvar, T: ReadableAccount>(account: &T) -> Option<S> {
757 bincode::deserialize(account.data()).ok()
758}
759
760#[cfg(feature = "bincode")]
761pub fn to_account<S: Sysvar, T: WritableAccount>(sysvar: &S, account: &mut T) -> Option<()> {
763 bincode::serialize_into(account.data_as_mut_slice(), sysvar).ok()
764}
765
766impl clone_solana_account_info::Account for Account {
769 fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool, Epoch) {
770 (
771 &mut self.lamports,
772 &mut self.data,
773 &self.owner,
774 self.executable,
775 self.rent_epoch,
776 )
777 }
778}
779
780pub fn create_is_signer_account_infos<'a>(
782 accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
783) -> Vec<AccountInfo<'a>> {
784 accounts
785 .iter_mut()
786 .map(|(key, is_signer, account)| {
787 AccountInfo::new(
788 key,
789 *is_signer,
790 false,
791 &mut account.lamports,
792 &mut account.data,
793 &account.owner,
794 account.executable,
795 account.rent_epoch,
796 )
797 })
798 .collect()
799}
800
801pub const PROGRAM_OWNERS: &[Pubkey] = &[
803 bpf_loader_upgradeable::id(),
804 bpf_loader::id(),
805 bpf_loader_deprecated::id(),
806 loader_v4::id(),
807];
808
809#[cfg(test)]
810pub mod tests {
811 use super::*;
812
813 fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) {
814 let mut account1 = Account::new(1, 2, key);
815 account1.executable = true;
816 account1.rent_epoch = 4;
817 let mut account2 = AccountSharedData::new(1, 2, key);
818 account2.executable = true;
819 account2.rent_epoch = 4;
820 assert!(accounts_equal(&account1, &account2));
821 (account1, account2)
822 }
823
824 #[test]
825 fn test_account_data_copy_as_slice() {
826 let key = Pubkey::new_unique();
827 let key2 = Pubkey::new_unique();
828 let (mut account1, mut account2) = make_two_accounts(&key);
829 account1.copy_into_owner_from_slice(key2.as_ref());
830 account2.copy_into_owner_from_slice(key2.as_ref());
831 assert!(accounts_equal(&account1, &account2));
832 assert_eq!(account1.owner(), &key2);
833 }
834
835 #[test]
836 fn test_account_set_data_from_slice() {
837 let key = Pubkey::new_unique();
838 let (_, mut account) = make_two_accounts(&key);
839 assert_eq!(account.data(), &vec![0, 0]);
840 account.set_data_from_slice(&[1, 2]);
841 assert_eq!(account.data(), &vec![1, 2]);
842 account.set_data_from_slice(&[1, 2, 3]);
843 assert_eq!(account.data(), &vec![1, 2, 3]);
844 account.set_data_from_slice(&[4, 5, 6]);
845 assert_eq!(account.data(), &vec![4, 5, 6]);
846 account.set_data_from_slice(&[4, 5, 6, 0]);
847 assert_eq!(account.data(), &vec![4, 5, 6, 0]);
848 account.set_data_from_slice(&[]);
849 assert_eq!(account.data().len(), 0);
850 account.set_data_from_slice(&[44]);
851 assert_eq!(account.data(), &vec![44]);
852 account.set_data_from_slice(&[44]);
853 assert_eq!(account.data(), &vec![44]);
854 }
855
856 #[test]
857 fn test_account_data_set_data() {
858 let key = Pubkey::new_unique();
859 let (_, mut account) = make_two_accounts(&key);
860 assert_eq!(account.data(), &vec![0, 0]);
861 account.set_data(vec![1, 2]);
862 assert_eq!(account.data(), &vec![1, 2]);
863 account.set_data(vec![]);
864 assert_eq!(account.data().len(), 0);
865 }
866
867 #[test]
868 #[should_panic(
869 expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
870 )]
871 fn test_account_deserialize() {
872 let key = Pubkey::new_unique();
873 let (account1, _account2) = make_two_accounts(&key);
874 account1.deserialize_data::<String>().unwrap();
875 }
876
877 #[test]
878 #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
879 fn test_account_serialize() {
880 let key = Pubkey::new_unique();
881 let (mut account1, _account2) = make_two_accounts(&key);
882 account1.serialize_data(&"hello world").unwrap();
883 }
884
885 #[test]
886 #[should_panic(
887 expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
888 )]
889 fn test_account_shared_data_deserialize() {
890 let key = Pubkey::new_unique();
891 let (_account1, account2) = make_two_accounts(&key);
892 account2.deserialize_data::<String>().unwrap();
893 }
894
895 #[test]
896 #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
897 fn test_account_shared_data_serialize() {
898 let key = Pubkey::new_unique();
899 let (_account1, mut account2) = make_two_accounts(&key);
900 account2.serialize_data(&"hello world").unwrap();
901 }
902
903 #[test]
904 fn test_to_account_shared_data() {
905 let key = Pubkey::new_unique();
906 let (account1, account2) = make_two_accounts(&key);
907 assert!(accounts_equal(&account1, &account2));
908 let account3 = account1.to_account_shared_data();
909 let account4 = account2.to_account_shared_data();
910 assert!(accounts_equal(&account1, &account3));
911 assert!(accounts_equal(&account1, &account4));
912 }
913
914 #[test]
915 fn test_account_shared_data() {
916 let key = Pubkey::new_unique();
917 let (account1, account2) = make_two_accounts(&key);
918 assert!(accounts_equal(&account1, &account2));
919 let account = account1;
920 assert_eq!(account.lamports, 1);
921 assert_eq!(account.lamports(), 1);
922 assert_eq!(account.data.len(), 2);
923 assert_eq!(account.data().len(), 2);
924 assert_eq!(account.owner, key);
925 assert_eq!(account.owner(), &key);
926 assert!(account.executable);
927 assert!(account.executable());
928 assert_eq!(account.rent_epoch, 4);
929 assert_eq!(account.rent_epoch(), 4);
930 let account = account2;
931 assert_eq!(account.lamports, 1);
932 assert_eq!(account.lamports(), 1);
933 assert_eq!(account.data.len(), 2);
934 assert_eq!(account.data().len(), 2);
935 assert_eq!(account.owner, key);
936 assert_eq!(account.owner(), &key);
937 assert!(account.executable);
938 assert!(account.executable());
939 assert_eq!(account.rent_epoch, 4);
940 assert_eq!(account.rent_epoch(), 4);
941 }
942
943 fn test_equal(
945 should_be_equal: bool,
946 account1: &Account,
947 account2: &AccountSharedData,
948 account_expected: &Account,
949 ) {
950 assert_eq!(should_be_equal, accounts_equal(account1, account2));
951 if should_be_equal {
952 assert!(accounts_equal(account_expected, account2));
953 }
954 assert_eq!(
955 accounts_equal(account_expected, account1),
956 accounts_equal(account_expected, &account1.clone())
957 );
958 assert_eq!(
959 accounts_equal(account_expected, account2),
960 accounts_equal(account_expected, &account2.clone())
961 );
962 assert_eq!(
963 accounts_equal(account_expected, account1),
964 accounts_equal(account_expected, &AccountSharedData::from(account1.clone()))
965 );
966 assert_eq!(
967 accounts_equal(account_expected, account2),
968 accounts_equal(account_expected, &Account::from(account2.clone()))
969 );
970 }
971
972 #[test]
973 fn test_account_add_sub_lamports() {
974 let key = Pubkey::new_unique();
975 let (mut account1, mut account2) = make_two_accounts(&key);
976 assert!(accounts_equal(&account1, &account2));
977 account1.checked_add_lamports(1).unwrap();
978 account2.checked_add_lamports(1).unwrap();
979 assert!(accounts_equal(&account1, &account2));
980 assert_eq!(account1.lamports(), 2);
981 account1.checked_sub_lamports(2).unwrap();
982 account2.checked_sub_lamports(2).unwrap();
983 assert!(accounts_equal(&account1, &account2));
984 assert_eq!(account1.lamports(), 0);
985 }
986
987 #[test]
988 #[should_panic(expected = "Overflow")]
989 fn test_account_checked_add_lamports_overflow() {
990 let key = Pubkey::new_unique();
991 let (mut account1, _account2) = make_two_accounts(&key);
992 account1.checked_add_lamports(u64::MAX).unwrap();
993 }
994
995 #[test]
996 #[should_panic(expected = "Underflow")]
997 fn test_account_checked_sub_lamports_underflow() {
998 let key = Pubkey::new_unique();
999 let (mut account1, _account2) = make_two_accounts(&key);
1000 account1.checked_sub_lamports(u64::MAX).unwrap();
1001 }
1002
1003 #[test]
1004 #[should_panic(expected = "Overflow")]
1005 fn test_account_checked_add_lamports_overflow2() {
1006 let key = Pubkey::new_unique();
1007 let (_account1, mut account2) = make_two_accounts(&key);
1008 account2.checked_add_lamports(u64::MAX).unwrap();
1009 }
1010
1011 #[test]
1012 #[should_panic(expected = "Underflow")]
1013 fn test_account_checked_sub_lamports_underflow2() {
1014 let key = Pubkey::new_unique();
1015 let (_account1, mut account2) = make_two_accounts(&key);
1016 account2.checked_sub_lamports(u64::MAX).unwrap();
1017 }
1018
1019 #[test]
1020 fn test_account_saturating_add_lamports() {
1021 let key = Pubkey::new_unique();
1022 let (mut account, _) = make_two_accounts(&key);
1023
1024 let remaining = 22;
1025 account.set_lamports(u64::MAX - remaining);
1026 account.saturating_add_lamports(remaining * 2);
1027 assert_eq!(account.lamports(), u64::MAX);
1028 }
1029
1030 #[test]
1031 fn test_account_saturating_sub_lamports() {
1032 let key = Pubkey::new_unique();
1033 let (mut account, _) = make_two_accounts(&key);
1034
1035 let remaining = 33;
1036 account.set_lamports(remaining);
1037 account.saturating_sub_lamports(remaining * 2);
1038 assert_eq!(account.lamports(), 0);
1039 }
1040
1041 #[test]
1042 fn test_account_shared_data_all_fields() {
1043 let key = Pubkey::new_unique();
1044 let key2 = Pubkey::new_unique();
1045 let key3 = Pubkey::new_unique();
1046 let (mut account1, mut account2) = make_two_accounts(&key);
1047 assert!(accounts_equal(&account1, &account2));
1048
1049 let mut account_expected = account1.clone();
1050 assert!(accounts_equal(&account1, &account_expected));
1051 assert!(accounts_equal(&account1, &account2.clone())); for field_index in 0..5 {
1054 for pass in 0..4 {
1055 if field_index == 0 {
1056 if pass == 0 {
1057 account1.checked_add_lamports(1).unwrap();
1058 } else if pass == 1 {
1059 account_expected.checked_add_lamports(1).unwrap();
1060 account2.set_lamports(account2.lamports + 1);
1061 } else if pass == 2 {
1062 account1.set_lamports(account1.lamports + 1);
1063 } else if pass == 3 {
1064 account_expected.checked_add_lamports(1).unwrap();
1065 account2.checked_add_lamports(1).unwrap();
1066 }
1067 } else if field_index == 1 {
1068 if pass == 0 {
1069 account1.data[0] += 1;
1070 } else if pass == 1 {
1071 account_expected.data[0] += 1;
1072 account2.data_as_mut_slice()[0] = account2.data[0] + 1;
1073 } else if pass == 2 {
1074 account1.data_as_mut_slice()[0] = account1.data[0] + 1;
1075 } else if pass == 3 {
1076 account_expected.data[0] += 1;
1077 account2.data_as_mut_slice()[0] += 1;
1078 }
1079 } else if field_index == 2 {
1080 if pass == 0 {
1081 account1.owner = key2;
1082 } else if pass == 1 {
1083 account_expected.owner = key2;
1084 account2.set_owner(key2);
1085 } else if pass == 2 {
1086 account1.set_owner(key3);
1087 } else if pass == 3 {
1088 account_expected.owner = key3;
1089 account2.owner = key3;
1090 }
1091 } else if field_index == 3 {
1092 if pass == 0 {
1093 account1.executable = !account1.executable;
1094 } else if pass == 1 {
1095 account_expected.executable = !account_expected.executable;
1096 account2.set_executable(!account2.executable);
1097 } else if pass == 2 {
1098 account1.set_executable(!account1.executable);
1099 } else if pass == 3 {
1100 account_expected.executable = !account_expected.executable;
1101 account2.executable = !account2.executable;
1102 }
1103 } else if field_index == 4 {
1104 if pass == 0 {
1105 account1.rent_epoch += 1;
1106 } else if pass == 1 {
1107 account_expected.rent_epoch += 1;
1108 account2.set_rent_epoch(account2.rent_epoch + 1);
1109 } else if pass == 2 {
1110 account1.set_rent_epoch(account1.rent_epoch + 1);
1111 } else if pass == 3 {
1112 account_expected.rent_epoch += 1;
1113 account2.rent_epoch += 1;
1114 }
1115 }
1116
1117 let should_be_equal = pass == 1 || pass == 3;
1118 test_equal(should_be_equal, &account1, &account2, &account_expected);
1119
1120 if should_be_equal {
1122 assert!(accounts_equal(
1123 &Account::new_ref(
1124 account_expected.lamports(),
1125 account_expected.data().len(),
1126 account_expected.owner()
1127 )
1128 .borrow(),
1129 &AccountSharedData::new_ref(
1130 account_expected.lamports(),
1131 account_expected.data().len(),
1132 account_expected.owner()
1133 )
1134 .borrow()
1135 ));
1136
1137 {
1138 let account1_with_data = Account::new_data(
1140 account_expected.lamports(),
1141 &account_expected.data()[0],
1142 account_expected.owner(),
1143 )
1144 .unwrap();
1145 let account2_with_data = AccountSharedData::new_data(
1146 account_expected.lamports(),
1147 &account_expected.data()[0],
1148 account_expected.owner(),
1149 )
1150 .unwrap();
1151
1152 assert!(accounts_equal(&account1_with_data, &account2_with_data));
1153 assert_eq!(
1154 account1_with_data.deserialize_data::<u8>().unwrap(),
1155 account2_with_data.deserialize_data::<u8>().unwrap()
1156 );
1157 }
1158
1159 assert!(accounts_equal(
1161 &Account::new_data_with_space(
1162 account_expected.lamports(),
1163 &account_expected.data()[0],
1164 1,
1165 account_expected.owner()
1166 )
1167 .unwrap(),
1168 &AccountSharedData::new_data_with_space(
1169 account_expected.lamports(),
1170 &account_expected.data()[0],
1171 1,
1172 account_expected.owner()
1173 )
1174 .unwrap()
1175 ));
1176
1177 assert!(accounts_equal(
1179 &Account::new_ref_data(
1180 account_expected.lamports(),
1181 &account_expected.data()[0],
1182 account_expected.owner()
1183 )
1184 .unwrap()
1185 .borrow(),
1186 &AccountSharedData::new_ref_data(
1187 account_expected.lamports(),
1188 &account_expected.data()[0],
1189 account_expected.owner()
1190 )
1191 .unwrap()
1192 .borrow()
1193 ));
1194
1195 assert!(accounts_equal(
1197 &Account::new_ref_data_with_space(
1198 account_expected.lamports(),
1199 &account_expected.data()[0],
1200 1,
1201 account_expected.owner()
1202 )
1203 .unwrap()
1204 .borrow(),
1205 &AccountSharedData::new_ref_data_with_space(
1206 account_expected.lamports(),
1207 &account_expected.data()[0],
1208 1,
1209 account_expected.owner()
1210 )
1211 .unwrap()
1212 .borrow()
1213 ));
1214 }
1215 }
1216 }
1217 }
1218}