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_sysvar::SysvarSerialize;
13use {
14    solana_account_info::{debug_account_data::*, AccountInfo},
15    solana_clock::{Epoch, INITIAL_RENT_EPOCH},
16    solana_instruction_error::LamportsError,
17    solana_pubkey::Pubkey,
18    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/// An Account with data that is stored on chain
32#[repr(C)]
33#[cfg_attr(
34    feature = "frozen-abi",
35    derive(AbiExample),
36    frozen_abi(digest = "62EqVoynUFvuui7DVfqWCvZP7bxKGJGioeSBnWrdjRME")
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    /// lamports in the account
46    pub lamports: u64,
47    /// data held in this account
48    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
49    pub data: Vec<u8>,
50    /// the program that owns this account. If executable, the program that loads this account.
51    pub owner: Pubkey,
52    /// this account's data contains a loaded program (and is now read-only)
53    pub executable: bool,
54    /// the epoch at which this account will next owe rent
55    pub rent_epoch: Epoch,
56}
57
58// mod because we need 'Account' below to have the name 'Account' to match expected serialization
59#[cfg(feature = "serde")]
60mod account_serialize {
61    #[cfg(feature = "frozen-abi")]
62    use solana_frozen_abi_macro::{frozen_abi, AbiExample};
63    use {
64        crate::ReadableAccount,
65        serde::{ser::Serializer, Serialize},
66        solana_clock::Epoch,
67        solana_pubkey::Pubkey,
68    };
69    #[repr(C)]
70    #[cfg_attr(
71        feature = "frozen-abi",
72        derive(AbiExample),
73        frozen_abi(digest = "62EqVoynUFvuui7DVfqWCvZP7bxKGJGioeSBnWrdjRME")
74    )]
75    #[derive(serde_derive::Serialize)]
76    #[serde(rename_all = "camelCase")]
77    struct Account<'a> {
78        lamports: u64,
79        #[serde(with = "serde_bytes")]
80        // a slice so we don't have to make a copy just to serialize this
81        data: &'a [u8],
82        owner: &'a Pubkey,
83        executable: bool,
84        rent_epoch: Epoch,
85    }
86
87    /// allows us to implement serialize on AccountSharedData that is equivalent to Account::serialize without making a copy of the Vec<u8>
88    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/// An Account with data that is stored on chain
127/// This will be the in-memory representation of the 'Account' struct data.
128/// The existing 'Account' structure cannot easily change due to downstream projects.
129#[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 in the account
138    lamports: u64,
139    /// data held in this account
140    data: Arc<Vec<u8>>,
141    /// the program that owns this account. If executable, the program that loads this account.
142    owner: Pubkey,
143    /// this account's data contains a loaded program (and is now read-only)
144    executable: bool,
145    /// the epoch at which this account will next owe rent
146    rent_epoch: Epoch,
147}
148
149/// Compares two ReadableAccounts
150///
151/// Returns true if accounts are essentially equivalent as in all fields are equivalent.
152pub 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    #[deprecated(since = "3.2.0")]
230    fn to_account_shared_data(&self) -> AccountSharedData {
231        AccountSharedData::create(
232            self.lamports(),
233            self.data().to_vec(),
234            *self.owner(),
235            self.executable(),
236            self.rent_epoch(),
237        )
238    }
239}
240
241impl ReadableAccount for Account {
242    fn lamports(&self) -> u64 {
243        self.lamports
244    }
245    fn data(&self) -> &[u8] {
246        &self.data
247    }
248    fn owner(&self) -> &Pubkey {
249        &self.owner
250    }
251    fn executable(&self) -> bool {
252        self.executable
253    }
254    fn rent_epoch(&self) -> Epoch {
255        self.rent_epoch
256    }
257}
258
259impl WritableAccount for Account {
260    fn set_lamports(&mut self, lamports: u64) {
261        self.lamports = lamports;
262    }
263    fn data_as_mut_slice(&mut self) -> &mut [u8] {
264        &mut self.data
265    }
266    fn set_owner(&mut self, owner: Pubkey) {
267        self.owner = owner;
268    }
269    fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
270        self.owner.as_mut().copy_from_slice(source);
271    }
272    fn set_executable(&mut self, executable: bool) {
273        self.executable = executable;
274    }
275    fn set_rent_epoch(&mut self, epoch: Epoch) {
276        self.rent_epoch = epoch;
277    }
278    fn create(
279        lamports: u64,
280        data: Vec<u8>,
281        owner: Pubkey,
282        executable: bool,
283        rent_epoch: Epoch,
284    ) -> Self {
285        Account {
286            lamports,
287            data,
288            owner,
289            executable,
290            rent_epoch,
291        }
292    }
293}
294
295impl WritableAccount for AccountSharedData {
296    fn set_lamports(&mut self, lamports: u64) {
297        self.lamports = lamports;
298    }
299    fn data_as_mut_slice(&mut self) -> &mut [u8] {
300        &mut self.data_mut()[..]
301    }
302    fn set_owner(&mut self, owner: Pubkey) {
303        self.owner = owner;
304    }
305    fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
306        self.owner.as_mut().copy_from_slice(source);
307    }
308    fn set_executable(&mut self, executable: bool) {
309        self.executable = executable;
310    }
311    fn set_rent_epoch(&mut self, epoch: Epoch) {
312        self.rent_epoch = epoch;
313    }
314    fn create(
315        lamports: u64,
316        data: Vec<u8>,
317        owner: Pubkey,
318        executable: bool,
319        rent_epoch: Epoch,
320    ) -> Self {
321        AccountSharedData {
322            lamports,
323            data: Arc::new(data),
324            owner,
325            executable,
326            rent_epoch,
327        }
328    }
329}
330
331impl ReadableAccount for AccountSharedData {
332    fn lamports(&self) -> u64 {
333        self.lamports
334    }
335    fn data(&self) -> &[u8] {
336        &self.data
337    }
338    fn owner(&self) -> &Pubkey {
339        &self.owner
340    }
341    fn executable(&self) -> bool {
342        self.executable
343    }
344    fn rent_epoch(&self) -> Epoch {
345        self.rent_epoch
346    }
347    fn to_account_shared_data(&self) -> AccountSharedData {
348        // avoid data copy here
349        self.clone()
350    }
351}
352
353impl ReadableAccount for Ref<'_, AccountSharedData> {
354    fn lamports(&self) -> u64 {
355        self.lamports
356    }
357    fn data(&self) -> &[u8] {
358        &self.data
359    }
360    fn owner(&self) -> &Pubkey {
361        &self.owner
362    }
363    fn executable(&self) -> bool {
364        self.executable
365    }
366    fn rent_epoch(&self) -> Epoch {
367        self.rent_epoch
368    }
369    fn to_account_shared_data(&self) -> AccountSharedData {
370        AccountSharedData {
371            lamports: self.lamports(),
372            // avoid data copy here
373            data: Arc::clone(&self.data),
374            owner: *self.owner(),
375            executable: self.executable(),
376            rent_epoch: self.rent_epoch(),
377        }
378    }
379}
380
381impl ReadableAccount for Ref<'_, Account> {
382    fn lamports(&self) -> u64 {
383        self.lamports
384    }
385    fn data(&self) -> &[u8] {
386        &self.data
387    }
388    fn owner(&self) -> &Pubkey {
389        &self.owner
390    }
391    fn executable(&self) -> bool {
392        self.executable
393    }
394    fn rent_epoch(&self) -> Epoch {
395        self.rent_epoch
396    }
397}
398
399fn debug_fmt<T: ReadableAccount>(item: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400    let mut f = f.debug_struct("Account");
401
402    f.field("lamports", &item.lamports())
403        .field("data.len", &item.data().len())
404        .field("owner", &item.owner())
405        .field("executable", &item.executable())
406        .field("rent_epoch", &item.rent_epoch());
407    debug_account_data(item.data(), &mut f);
408
409    f.finish()
410}
411
412impl fmt::Debug for Account {
413    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414        debug_fmt(self, f)
415    }
416}
417
418impl fmt::Debug for AccountSharedData {
419    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420        debug_fmt(self, f)
421    }
422}
423
424fn shared_new<T: WritableAccount>(lamports: u64, space: usize, owner: &Pubkey) -> T {
425    T::create(
426        lamports,
427        vec![0u8; space],
428        *owner,
429        bool::default(),
430        Epoch::default(),
431    )
432}
433
434fn shared_new_rent_epoch<T: WritableAccount>(
435    lamports: u64,
436    space: usize,
437    owner: &Pubkey,
438    rent_epoch: Epoch,
439) -> T {
440    T::create(
441        lamports,
442        vec![0u8; space],
443        *owner,
444        bool::default(),
445        rent_epoch,
446    )
447}
448
449fn shared_new_ref<T: WritableAccount>(
450    lamports: u64,
451    space: usize,
452    owner: &Pubkey,
453) -> Rc<RefCell<T>> {
454    Rc::new(RefCell::new(shared_new::<T>(lamports, space, owner)))
455}
456
457#[cfg(feature = "bincode")]
458fn shared_new_data<T: serde::Serialize, U: WritableAccount>(
459    lamports: u64,
460    state: &T,
461    owner: &Pubkey,
462) -> Result<U, bincode::Error> {
463    let data = bincode::serialize(state)?;
464    Ok(U::create(
465        lamports,
466        data,
467        *owner,
468        bool::default(),
469        Epoch::default(),
470    ))
471}
472
473#[cfg(feature = "bincode")]
474fn shared_new_ref_data<T: serde::Serialize, U: WritableAccount>(
475    lamports: u64,
476    state: &T,
477    owner: &Pubkey,
478) -> Result<RefCell<U>, bincode::Error> {
479    Ok(RefCell::new(shared_new_data::<T, U>(
480        lamports, state, owner,
481    )?))
482}
483
484#[cfg(feature = "bincode")]
485fn shared_new_data_with_space<T: serde::Serialize, U: WritableAccount>(
486    lamports: u64,
487    state: &T,
488    space: usize,
489    owner: &Pubkey,
490) -> Result<U, bincode::Error> {
491    let mut account = shared_new::<U>(lamports, space, owner);
492
493    shared_serialize_data(&mut account, state)?;
494
495    Ok(account)
496}
497
498#[cfg(feature = "bincode")]
499fn shared_new_ref_data_with_space<T: serde::Serialize, U: WritableAccount>(
500    lamports: u64,
501    state: &T,
502    space: usize,
503    owner: &Pubkey,
504) -> Result<RefCell<U>, bincode::Error> {
505    Ok(RefCell::new(shared_new_data_with_space::<T, U>(
506        lamports, state, space, owner,
507    )?))
508}
509
510#[cfg(feature = "bincode")]
511fn shared_deserialize_data<T: serde::de::DeserializeOwned, U: ReadableAccount>(
512    account: &U,
513) -> Result<T, bincode::Error> {
514    bincode::deserialize(account.data())
515}
516
517#[cfg(feature = "bincode")]
518fn shared_serialize_data<T: serde::Serialize, U: WritableAccount>(
519    account: &mut U,
520    state: &T,
521) -> Result<(), bincode::Error> {
522    if bincode::serialized_size(state)? > account.data().len() as u64 {
523        return Err(Box::new(bincode::ErrorKind::SizeLimit));
524    }
525    bincode::serialize_into(account.data_as_mut_slice(), state)
526}
527
528impl Account {
529    pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
530        shared_new(lamports, space, owner)
531    }
532    pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
533        shared_new_ref(lamports, space, owner)
534    }
535    #[cfg(feature = "bincode")]
536    pub fn new_data<T: serde::Serialize>(
537        lamports: u64,
538        state: &T,
539        owner: &Pubkey,
540    ) -> Result<Self, bincode::Error> {
541        shared_new_data(lamports, state, owner)
542    }
543    #[cfg(feature = "bincode")]
544    pub fn new_ref_data<T: serde::Serialize>(
545        lamports: u64,
546        state: &T,
547        owner: &Pubkey,
548    ) -> Result<RefCell<Self>, bincode::Error> {
549        shared_new_ref_data(lamports, state, owner)
550    }
551    #[cfg(feature = "bincode")]
552    pub fn new_data_with_space<T: serde::Serialize>(
553        lamports: u64,
554        state: &T,
555        space: usize,
556        owner: &Pubkey,
557    ) -> Result<Self, bincode::Error> {
558        shared_new_data_with_space(lamports, state, space, owner)
559    }
560    #[cfg(feature = "bincode")]
561    pub fn new_ref_data_with_space<T: serde::Serialize>(
562        lamports: u64,
563        state: &T,
564        space: usize,
565        owner: &Pubkey,
566    ) -> Result<RefCell<Self>, bincode::Error> {
567        shared_new_ref_data_with_space(lamports, state, space, owner)
568    }
569    pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
570        shared_new_rent_epoch(lamports, space, owner, rent_epoch)
571    }
572    #[cfg(feature = "bincode")]
573    pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
574        shared_deserialize_data(self)
575    }
576    #[cfg(feature = "bincode")]
577    pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
578        shared_serialize_data(self, state)
579    }
580}
581
582impl AccountSharedData {
583    pub fn is_shared(&self) -> bool {
584        Arc::strong_count(&self.data) > 1
585    }
586
587    pub fn reserve(&mut self, additional: usize) {
588        if let Some(data) = Arc::get_mut(&mut self.data) {
589            data.reserve(additional)
590        } else {
591            let mut data = Vec::with_capacity(self.data.len().saturating_add(additional));
592            data.extend_from_slice(&self.data);
593            self.data = Arc::new(data);
594        }
595    }
596
597    pub fn capacity(&self) -> usize {
598        self.data.capacity()
599    }
600
601    pub fn data_clone(&self) -> Arc<Vec<u8>> {
602        Arc::clone(&self.data)
603    }
604
605    fn data_mut(&mut self) -> &mut Vec<u8> {
606        Arc::make_mut(&mut self.data)
607    }
608
609    pub fn resize(&mut self, new_len: usize, value: u8) {
610        self.data_mut().resize(new_len, value)
611    }
612
613    pub fn extend_from_slice(&mut self, data: &[u8]) {
614        self.data_mut().extend_from_slice(data)
615    }
616
617    pub fn set_data_from_slice(&mut self, new_data: &[u8]) {
618        // If the buffer isn't shared, we're going to memcpy in place.
619        let Some(data) = Arc::get_mut(&mut self.data) else {
620            // If the buffer is shared, the cheapest thing to do is to clone the
621            // incoming slice and replace the buffer.
622            return self.set_data(new_data.to_vec());
623        };
624
625        let new_len = new_data.len();
626
627        // Reserve additional capacity if needed. Here we make the assumption
628        // that growing the current buffer is cheaper than doing a whole new
629        // allocation to make `new_data` owned.
630        //
631        // This assumption holds true during CPI, especially when the account
632        // size doesn't change but the account is only changed in place. And
633        // it's also true when the account is grown by a small margin (the
634        // realloc limit is quite low), in which case the allocator can just
635        // update the allocation metadata without moving.
636        //
637        // Shrinking and copying in place is always faster than making
638        // `new_data` owned, since shrinking boils down to updating the Vec's
639        // length.
640
641        data.reserve(new_len.saturating_sub(data.len()));
642
643        // Safety:
644        // We just reserved enough capacity. We set data::len to 0 to avoid
645        // possible UB on panic (dropping uninitialized elements), do the copy,
646        // finally set the new length once everything is initialized.
647        #[allow(clippy::uninit_vec)]
648        // this is a false positive, the lint doesn't currently special case set_len(0)
649        unsafe {
650            data.set_len(0);
651            ptr::copy_nonoverlapping(new_data.as_ptr(), data.as_mut_ptr(), new_len);
652            data.set_len(new_len);
653        };
654    }
655
656    #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
657    fn set_data(&mut self, data: Vec<u8>) {
658        self.data = Arc::new(data);
659    }
660
661    pub fn spare_data_capacity_mut(&mut self) -> &mut [MaybeUninit<u8>] {
662        self.data_mut().spare_capacity_mut()
663    }
664
665    pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
666        shared_new(lamports, space, owner)
667    }
668    pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
669        shared_new_ref(lamports, space, owner)
670    }
671    #[cfg(feature = "bincode")]
672    pub fn new_data<T: serde::Serialize>(
673        lamports: u64,
674        state: &T,
675        owner: &Pubkey,
676    ) -> Result<Self, bincode::Error> {
677        shared_new_data(lamports, state, owner)
678    }
679    #[cfg(feature = "bincode")]
680    pub fn new_ref_data<T: serde::Serialize>(
681        lamports: u64,
682        state: &T,
683        owner: &Pubkey,
684    ) -> Result<RefCell<Self>, bincode::Error> {
685        shared_new_ref_data(lamports, state, owner)
686    }
687    #[cfg(feature = "bincode")]
688    pub fn new_data_with_space<T: serde::Serialize>(
689        lamports: u64,
690        state: &T,
691        space: usize,
692        owner: &Pubkey,
693    ) -> Result<Self, bincode::Error> {
694        shared_new_data_with_space(lamports, state, space, owner)
695    }
696    #[cfg(feature = "bincode")]
697    pub fn new_ref_data_with_space<T: serde::Serialize>(
698        lamports: u64,
699        state: &T,
700        space: usize,
701        owner: &Pubkey,
702    ) -> Result<RefCell<Self>, bincode::Error> {
703        shared_new_ref_data_with_space(lamports, state, space, owner)
704    }
705    pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
706        shared_new_rent_epoch(lamports, space, owner, rent_epoch)
707    }
708    #[cfg(feature = "bincode")]
709    pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
710        shared_deserialize_data(self)
711    }
712    #[cfg(feature = "bincode")]
713    pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
714        shared_serialize_data(self, state)
715    }
716
717    pub fn create_from_existing_shared_data(
718        lamports: u64,
719        data: Arc<Vec<u8>>,
720        owner: Pubkey,
721        executable: bool,
722        rent_epoch: Epoch,
723    ) -> AccountSharedData {
724        AccountSharedData {
725            lamports,
726            data,
727            owner,
728            executable,
729            rent_epoch,
730        }
731    }
732}
733
734pub type InheritableAccountFields = (u64, Epoch);
735pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH);
736
737#[cfg(feature = "bincode")]
738pub fn create_account_with_fields<S: SysvarSerialize>(
739    sysvar: &S,
740    (lamports, rent_epoch): InheritableAccountFields,
741) -> Account {
742    let data_len = S::size_of().max(bincode::serialized_size(sysvar).unwrap() as usize);
743    let mut account = Account::new(lamports, data_len, &solana_sdk_ids::sysvar::id());
744    to_account::<S, Account>(sysvar, &mut account).unwrap();
745    account.rent_epoch = rent_epoch;
746    account
747}
748
749#[cfg(feature = "bincode")]
750pub fn create_account_for_test<S: SysvarSerialize>(sysvar: &S) -> Account {
751    create_account_with_fields(sysvar, DUMMY_INHERITABLE_ACCOUNT_FIELDS)
752}
753
754#[cfg(feature = "bincode")]
755/// Create an `Account` from a `Sysvar`.
756pub fn create_account_shared_data_with_fields<S: SysvarSerialize>(
757    sysvar: &S,
758    fields: InheritableAccountFields,
759) -> AccountSharedData {
760    AccountSharedData::from(create_account_with_fields(sysvar, fields))
761}
762
763#[cfg(feature = "bincode")]
764pub fn create_account_shared_data_for_test<S: SysvarSerialize>(sysvar: &S) -> AccountSharedData {
765    AccountSharedData::from(create_account_with_fields(
766        sysvar,
767        DUMMY_INHERITABLE_ACCOUNT_FIELDS,
768    ))
769}
770
771#[cfg(feature = "bincode")]
772/// Create a `Sysvar` from an `Account`'s data.
773pub fn from_account<S: SysvarSerialize, T: ReadableAccount>(account: &T) -> Option<S> {
774    bincode::deserialize(account.data()).ok()
775}
776
777#[cfg(feature = "bincode")]
778/// Serialize a `Sysvar` into an `Account`'s data.
779pub fn to_account<S: SysvarSerialize, T: WritableAccount>(
780    sysvar: &S,
781    account: &mut T,
782) -> Option<()> {
783    bincode::serialize_into(account.data_as_mut_slice(), sysvar).ok()
784}
785
786/// Return the information required to construct an `AccountInfo`.  Used by the
787/// `AccountInfo` conversion implementations.
788impl solana_account_info::Account for Account {
789    fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool) {
790        (
791            &mut self.lamports,
792            &mut self.data,
793            &self.owner,
794            self.executable,
795        )
796    }
797}
798
799/// Create `AccountInfo`s
800pub fn create_is_signer_account_infos<'a>(
801    accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
802) -> Vec<AccountInfo<'a>> {
803    accounts
804        .iter_mut()
805        .map(|(key, is_signer, account)| {
806            AccountInfo::new(
807                key,
808                *is_signer,
809                false,
810                &mut account.lamports,
811                &mut account.data,
812                &account.owner,
813                account.executable,
814            )
815        })
816        .collect()
817}
818
819/// Replacement for the executable flag: An account being owned by one of these contains a program.
820pub const PROGRAM_OWNERS: &[Pubkey] = &[
821    bpf_loader_upgradeable::id(),
822    bpf_loader::id(),
823    bpf_loader_deprecated::id(),
824    loader_v4::id(),
825];
826
827#[cfg(test)]
828pub mod tests {
829    use super::*;
830
831    fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) {
832        let mut account1 = Account::new(1, 2, key);
833        account1.executable = true;
834        account1.rent_epoch = 4;
835        let mut account2 = AccountSharedData::new(1, 2, key);
836        account2.executable = true;
837        account2.rent_epoch = 4;
838        assert!(accounts_equal(&account1, &account2));
839        (account1, account2)
840    }
841
842    #[test]
843    fn test_account_data_copy_as_slice() {
844        let key = Pubkey::new_unique();
845        let key2 = Pubkey::new_unique();
846        let (mut account1, mut account2) = make_two_accounts(&key);
847        account1.copy_into_owner_from_slice(key2.as_ref());
848        account2.copy_into_owner_from_slice(key2.as_ref());
849        assert!(accounts_equal(&account1, &account2));
850        assert_eq!(account1.owner(), &key2);
851    }
852
853    #[test]
854    fn test_account_set_data_from_slice() {
855        let key = Pubkey::new_unique();
856        let (_, mut account) = make_two_accounts(&key);
857        assert_eq!(account.data(), &vec![0, 0]);
858        account.set_data_from_slice(&[1, 2]);
859        assert_eq!(account.data(), &vec![1, 2]);
860        account.set_data_from_slice(&[1, 2, 3]);
861        assert_eq!(account.data(), &vec![1, 2, 3]);
862        account.set_data_from_slice(&[4, 5, 6]);
863        assert_eq!(account.data(), &vec![4, 5, 6]);
864        account.set_data_from_slice(&[4, 5, 6, 0]);
865        assert_eq!(account.data(), &vec![4, 5, 6, 0]);
866        account.set_data_from_slice(&[]);
867        assert_eq!(account.data().len(), 0);
868        account.set_data_from_slice(&[44]);
869        assert_eq!(account.data(), &vec![44]);
870        account.set_data_from_slice(&[44]);
871        assert_eq!(account.data(), &vec![44]);
872    }
873
874    #[test]
875    fn test_account_data_set_data() {
876        let key = Pubkey::new_unique();
877        let (_, mut account) = make_two_accounts(&key);
878        assert_eq!(account.data(), &vec![0, 0]);
879        account.set_data(vec![1, 2]);
880        assert_eq!(account.data(), &vec![1, 2]);
881        account.set_data(vec![]);
882        assert_eq!(account.data().len(), 0);
883    }
884
885    #[test]
886    #[should_panic(
887        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
888    )]
889    fn test_account_deserialize() {
890        let key = Pubkey::new_unique();
891        let (account1, _account2) = make_two_accounts(&key);
892        account1.deserialize_data::<String>().unwrap();
893    }
894
895    #[test]
896    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
897    fn test_account_serialize() {
898        let key = Pubkey::new_unique();
899        let (mut account1, _account2) = make_two_accounts(&key);
900        account1.serialize_data(&"hello world").unwrap();
901    }
902
903    #[test]
904    #[should_panic(
905        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
906    )]
907    fn test_account_shared_data_deserialize() {
908        let key = Pubkey::new_unique();
909        let (_account1, account2) = make_two_accounts(&key);
910        account2.deserialize_data::<String>().unwrap();
911    }
912
913    #[test]
914    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
915    fn test_account_shared_data_serialize() {
916        let key = Pubkey::new_unique();
917        let (_account1, mut account2) = make_two_accounts(&key);
918        account2.serialize_data(&"hello world").unwrap();
919    }
920
921    #[test]
922    #[allow(deprecated)]
923    fn test_to_account_shared_data() {
924        let key = Pubkey::new_unique();
925        let (account1, account2) = make_two_accounts(&key);
926        assert!(accounts_equal(&account1, &account2));
927        let account3 = account1.to_account_shared_data();
928        let account4 = account2.to_account_shared_data();
929        assert!(accounts_equal(&account1, &account3));
930        assert!(accounts_equal(&account1, &account4));
931    }
932
933    #[test]
934    fn test_account_shared_data() {
935        let key = Pubkey::new_unique();
936        let (account1, account2) = make_two_accounts(&key);
937        assert!(accounts_equal(&account1, &account2));
938        let account = account1;
939        assert_eq!(account.lamports, 1);
940        assert_eq!(account.lamports(), 1);
941        assert_eq!(account.data.len(), 2);
942        assert_eq!(account.data().len(), 2);
943        assert_eq!(account.owner, key);
944        assert_eq!(account.owner(), &key);
945        assert!(account.executable);
946        assert!(account.executable());
947        assert_eq!(account.rent_epoch, 4);
948        assert_eq!(account.rent_epoch(), 4);
949        let account = account2;
950        assert_eq!(account.lamports, 1);
951        assert_eq!(account.lamports(), 1);
952        assert_eq!(account.data.len(), 2);
953        assert_eq!(account.data().len(), 2);
954        assert_eq!(account.owner, key);
955        assert_eq!(account.owner(), &key);
956        assert!(account.executable);
957        assert!(account.executable());
958        assert_eq!(account.rent_epoch, 4);
959        assert_eq!(account.rent_epoch(), 4);
960    }
961
962    // test clone and from for both types against expected
963    fn test_equal(
964        should_be_equal: bool,
965        account1: &Account,
966        account2: &AccountSharedData,
967        account_expected: &Account,
968    ) {
969        assert_eq!(should_be_equal, accounts_equal(account1, account2));
970        if should_be_equal {
971            assert!(accounts_equal(account_expected, account2));
972        }
973        assert_eq!(
974            accounts_equal(account_expected, account1),
975            accounts_equal(account_expected, &account1.clone())
976        );
977        assert_eq!(
978            accounts_equal(account_expected, account2),
979            accounts_equal(account_expected, &account2.clone())
980        );
981        assert_eq!(
982            accounts_equal(account_expected, account1),
983            accounts_equal(account_expected, &AccountSharedData::from(account1.clone()))
984        );
985        assert_eq!(
986            accounts_equal(account_expected, account2),
987            accounts_equal(account_expected, &Account::from(account2.clone()))
988        );
989    }
990
991    #[test]
992    fn test_account_add_sub_lamports() {
993        let key = Pubkey::new_unique();
994        let (mut account1, mut account2) = make_two_accounts(&key);
995        assert!(accounts_equal(&account1, &account2));
996        account1.checked_add_lamports(1).unwrap();
997        account2.checked_add_lamports(1).unwrap();
998        assert!(accounts_equal(&account1, &account2));
999        assert_eq!(account1.lamports(), 2);
1000        account1.checked_sub_lamports(2).unwrap();
1001        account2.checked_sub_lamports(2).unwrap();
1002        assert!(accounts_equal(&account1, &account2));
1003        assert_eq!(account1.lamports(), 0);
1004    }
1005
1006    #[test]
1007    #[should_panic(expected = "Overflow")]
1008    fn test_account_checked_add_lamports_overflow() {
1009        let key = Pubkey::new_unique();
1010        let (mut account1, _account2) = make_two_accounts(&key);
1011        account1.checked_add_lamports(u64::MAX).unwrap();
1012    }
1013
1014    #[test]
1015    #[should_panic(expected = "Underflow")]
1016    fn test_account_checked_sub_lamports_underflow() {
1017        let key = Pubkey::new_unique();
1018        let (mut account1, _account2) = make_two_accounts(&key);
1019        account1.checked_sub_lamports(u64::MAX).unwrap();
1020    }
1021
1022    #[test]
1023    #[should_panic(expected = "Overflow")]
1024    fn test_account_checked_add_lamports_overflow2() {
1025        let key = Pubkey::new_unique();
1026        let (_account1, mut account2) = make_two_accounts(&key);
1027        account2.checked_add_lamports(u64::MAX).unwrap();
1028    }
1029
1030    #[test]
1031    #[should_panic(expected = "Underflow")]
1032    fn test_account_checked_sub_lamports_underflow2() {
1033        let key = Pubkey::new_unique();
1034        let (_account1, mut account2) = make_two_accounts(&key);
1035        account2.checked_sub_lamports(u64::MAX).unwrap();
1036    }
1037
1038    #[test]
1039    fn test_account_saturating_add_lamports() {
1040        let key = Pubkey::new_unique();
1041        let (mut account, _) = make_two_accounts(&key);
1042
1043        let remaining = 22;
1044        account.set_lamports(u64::MAX - remaining);
1045        account.saturating_add_lamports(remaining * 2);
1046        assert_eq!(account.lamports(), u64::MAX);
1047    }
1048
1049    #[test]
1050    fn test_account_saturating_sub_lamports() {
1051        let key = Pubkey::new_unique();
1052        let (mut account, _) = make_two_accounts(&key);
1053
1054        let remaining = 33;
1055        account.set_lamports(remaining);
1056        account.saturating_sub_lamports(remaining * 2);
1057        assert_eq!(account.lamports(), 0);
1058    }
1059
1060    #[test]
1061    fn test_account_shared_data_all_fields() {
1062        let key = Pubkey::new_unique();
1063        let key2 = Pubkey::new_unique();
1064        let key3 = Pubkey::new_unique();
1065        let (mut account1, mut account2) = make_two_accounts(&key);
1066        assert!(accounts_equal(&account1, &account2));
1067
1068        let mut account_expected = account1.clone();
1069        assert!(accounts_equal(&account1, &account_expected));
1070        assert!(accounts_equal(&account1, &account2.clone())); // test the clone here
1071
1072        for field_index in 0..5 {
1073            for pass in 0..4 {
1074                if field_index == 0 {
1075                    if pass == 0 {
1076                        account1.checked_add_lamports(1).unwrap();
1077                    } else if pass == 1 {
1078                        account_expected.checked_add_lamports(1).unwrap();
1079                        account2.set_lamports(account2.lamports + 1);
1080                    } else if pass == 2 {
1081                        account1.set_lamports(account1.lamports + 1);
1082                    } else if pass == 3 {
1083                        account_expected.checked_add_lamports(1).unwrap();
1084                        account2.checked_add_lamports(1).unwrap();
1085                    }
1086                } else if field_index == 1 {
1087                    if pass == 0 {
1088                        account1.data[0] += 1;
1089                    } else if pass == 1 {
1090                        account_expected.data[0] += 1;
1091                        account2.data_as_mut_slice()[0] = account2.data[0] + 1;
1092                    } else if pass == 2 {
1093                        account1.data_as_mut_slice()[0] = account1.data[0] + 1;
1094                    } else if pass == 3 {
1095                        account_expected.data[0] += 1;
1096                        account2.data_as_mut_slice()[0] += 1;
1097                    }
1098                } else if field_index == 2 {
1099                    if pass == 0 {
1100                        account1.owner = key2;
1101                    } else if pass == 1 {
1102                        account_expected.owner = key2;
1103                        account2.set_owner(key2);
1104                    } else if pass == 2 {
1105                        account1.set_owner(key3);
1106                    } else if pass == 3 {
1107                        account_expected.owner = key3;
1108                        account2.owner = key3;
1109                    }
1110                } else if field_index == 3 {
1111                    if pass == 0 {
1112                        account1.executable = !account1.executable;
1113                    } else if pass == 1 {
1114                        account_expected.executable = !account_expected.executable;
1115                        account2.set_executable(!account2.executable);
1116                    } else if pass == 2 {
1117                        account1.set_executable(!account1.executable);
1118                    } else if pass == 3 {
1119                        account_expected.executable = !account_expected.executable;
1120                        account2.executable = !account2.executable;
1121                    }
1122                } else if field_index == 4 {
1123                    if pass == 0 {
1124                        account1.rent_epoch += 1;
1125                    } else if pass == 1 {
1126                        account_expected.rent_epoch += 1;
1127                        account2.set_rent_epoch(account2.rent_epoch + 1);
1128                    } else if pass == 2 {
1129                        account1.set_rent_epoch(account1.rent_epoch + 1);
1130                    } else if pass == 3 {
1131                        account_expected.rent_epoch += 1;
1132                        account2.rent_epoch += 1;
1133                    }
1134                }
1135
1136                let should_be_equal = pass == 1 || pass == 3;
1137                test_equal(should_be_equal, &account1, &account2, &account_expected);
1138
1139                // test new_ref
1140                if should_be_equal {
1141                    assert!(accounts_equal(
1142                        &Account::new_ref(
1143                            account_expected.lamports(),
1144                            account_expected.data().len(),
1145                            account_expected.owner()
1146                        )
1147                        .borrow(),
1148                        &AccountSharedData::new_ref(
1149                            account_expected.lamports(),
1150                            account_expected.data().len(),
1151                            account_expected.owner()
1152                        )
1153                        .borrow()
1154                    ));
1155
1156                    {
1157                        // test new_data
1158                        let account1_with_data = Account::new_data(
1159                            account_expected.lamports(),
1160                            &account_expected.data()[0],
1161                            account_expected.owner(),
1162                        )
1163                        .unwrap();
1164                        let account2_with_data = AccountSharedData::new_data(
1165                            account_expected.lamports(),
1166                            &account_expected.data()[0],
1167                            account_expected.owner(),
1168                        )
1169                        .unwrap();
1170
1171                        assert!(accounts_equal(&account1_with_data, &account2_with_data));
1172                        assert_eq!(
1173                            account1_with_data.deserialize_data::<u8>().unwrap(),
1174                            account2_with_data.deserialize_data::<u8>().unwrap()
1175                        );
1176                    }
1177
1178                    // test new_data_with_space
1179                    assert!(accounts_equal(
1180                        &Account::new_data_with_space(
1181                            account_expected.lamports(),
1182                            &account_expected.data()[0],
1183                            1,
1184                            account_expected.owner()
1185                        )
1186                        .unwrap(),
1187                        &AccountSharedData::new_data_with_space(
1188                            account_expected.lamports(),
1189                            &account_expected.data()[0],
1190                            1,
1191                            account_expected.owner()
1192                        )
1193                        .unwrap()
1194                    ));
1195
1196                    // test new_ref_data
1197                    assert!(accounts_equal(
1198                        &Account::new_ref_data(
1199                            account_expected.lamports(),
1200                            &account_expected.data()[0],
1201                            account_expected.owner()
1202                        )
1203                        .unwrap()
1204                        .borrow(),
1205                        &AccountSharedData::new_ref_data(
1206                            account_expected.lamports(),
1207                            &account_expected.data()[0],
1208                            account_expected.owner()
1209                        )
1210                        .unwrap()
1211                        .borrow()
1212                    ));
1213
1214                    //new_ref_data_with_space
1215                    assert!(accounts_equal(
1216                        &Account::new_ref_data_with_space(
1217                            account_expected.lamports(),
1218                            &account_expected.data()[0],
1219                            1,
1220                            account_expected.owner()
1221                        )
1222                        .unwrap()
1223                        .borrow(),
1224                        &AccountSharedData::new_ref_data_with_space(
1225                            account_expected.lamports(),
1226                            &account_expected.data()[0],
1227                            1,
1228                            account_expected.owner()
1229                        )
1230                        .unwrap()
1231                        .borrow()
1232                    ));
1233                }
1234            }
1235        }
1236    }
1237}