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