solana_account/
lib.rs

1#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3//! The Solana [`Account`] type.
4
5#[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/// An Account with data that is stored on chain
36#[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    /// lamports in the account
50    pub lamports: u64,
51    /// data held in this account
52    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
53    pub data: Vec<u8>,
54    /// the program that owns this account. If executable, the program that loads this account.
55    pub owner: Pubkey,
56    /// this account's data contains a loaded program (and is now read-only)
57    pub executable: bool,
58    /// the epoch at which this account will next owe rent
59    pub rent_epoch: Epoch,
60}
61
62// mod because we need 'Account' below to have the name 'Account' to match expected serialization
63#[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        // a slice so we don't have to make a copy just to serialize this
84        data: &'a [u8],
85        owner: &'a Pubkey,
86        executable: bool,
87        rent_epoch: Epoch,
88    }
89
90    /// allows us to implement serialize on AccountSharedData that is equivalent to Account::serialize without making a copy of the Vec<u8>
91    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/// An Account with data that is stored on chain
130/// This will be the in-memory representation of the 'Account' struct data.
131/// The existing 'Account' structure cannot easily change due to downstream projects.
132#[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 in the account
141    lamports: u64,
142    /// data held in this account
143    data: Arc<Vec<u8>>,
144    /// the program that owns this account. If executable, the program that loads this account.
145    owner: Pubkey,
146    /// this account's data contains a loaded program (and is now read-only)
147    executable: bool,
148    /// the epoch at which this account will next owe rent
149    rent_epoch: Epoch,
150}
151
152/// Compares two ReadableAccounts
153///
154/// Returns true if accounts are essentially equivalent as in all fields are equivalent.
155pub 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        // avoid data copy here
351        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            // avoid data copy here
375            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        // If the buffer isn't shared, we're going to memcpy in place.
617        let Some(data) = Arc::get_mut(&mut self.data) else {
618            // If the buffer is shared, the cheapest thing to do is to clone the
619            // incoming slice and replace the buffer.
620            return self.set_data(new_data.to_vec());
621        };
622
623        let new_len = new_data.len();
624
625        // Reserve additional capacity if needed. Here we make the assumption
626        // that growing the current buffer is cheaper than doing a whole new
627        // allocation to make `new_data` owned.
628        //
629        // This assumption holds true during CPI, especially when the account
630        // size doesn't change but the account is only changed in place. And
631        // it's also true when the account is grown by a small margin (the
632        // realloc limit is quite low), in which case the allocator can just
633        // update the allocation metadata without moving.
634        //
635        // Shrinking and copying in place is always faster than making
636        // `new_data` owned, since shrinking boils down to updating the Vec's
637        // length.
638
639        data.reserve(new_len.saturating_sub(data.len()));
640
641        // Safety:
642        // We just reserved enough capacity. We set data::len to 0 to avoid
643        // possible UB on panic (dropping uninitialized elements), do the copy,
644        // finally set the new length once everything is initialized.
645        #[allow(clippy::uninit_vec)]
646        // this is a false positive, the lint doesn't currently special case set_len(0)
647        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")]
737/// Create an `Account` from a `Sysvar`.
738pub 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")]
754/// Create a `Sysvar` from an `Account`'s data.
755pub fn from_account<S: Sysvar, T: ReadableAccount>(account: &T) -> Option<S> {
756    bincode::deserialize(account.data()).ok()
757}
758
759#[cfg(feature = "bincode")]
760/// Serialize a `Sysvar` into an `Account`'s data.
761pub 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
765/// Return the information required to construct an `AccountInfo`.  Used by the
766/// `AccountInfo` conversion implementations.
767impl 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
779/// Create `AccountInfo`s
780pub 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
800/// Replacement for the executable flag: An account being owned by one of these contains a program.
801pub 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    // test clone and from for both types against expected
943    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())); // test the clone here
1051
1052        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                // test new_ref
1120                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                        // test new_data
1138                        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                    // test new_data_with_space
1159                    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                    // test new_ref_data
1177                    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                    //new_ref_data_with_space
1195                    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}