solana_account/
lib.rs

1#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
2#![cfg_attr(docsrs, feature(doc_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    #[deprecated(since = "3.3.0")]
215    fn create(
216        lamports: u64,
217        data: Vec<u8>,
218        owner: Pubkey,
219        executable: bool,
220        rent_epoch: Epoch,
221    ) -> Self;
222}
223
224pub trait ReadableAccount: Sized {
225    fn lamports(&self) -> u64;
226    fn data(&self) -> &[u8];
227    fn owner(&self) -> &Pubkey;
228    fn executable(&self) -> bool;
229    fn rent_epoch(&self) -> Epoch;
230    #[deprecated(since = "3.2.0")]
231    fn to_account_shared_data(&self) -> AccountSharedData {
232        #[allow(deprecated)]
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
426#[cfg(feature = "bincode")]
427fn shared_deserialize_data<T: serde::de::DeserializeOwned, U: ReadableAccount>(
428    account: &U,
429) -> Result<T, bincode::Error> {
430    bincode::deserialize(account.data())
431}
432
433#[cfg(feature = "bincode")]
434fn shared_serialize_data<T: serde::Serialize, U: WritableAccount>(
435    account: &mut U,
436    state: &T,
437) -> Result<(), bincode::Error> {
438    if bincode::serialized_size(state)? > account.data().len() as u64 {
439        return Err(Box::new(bincode::ErrorKind::SizeLimit));
440    }
441    bincode::serialize_into(account.data_as_mut_slice(), state)
442}
443
444impl Account {
445    pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
446        Account {
447            lamports,
448            data: vec![0; space],
449            owner: *owner,
450            executable: false,
451            rent_epoch: Epoch::default(),
452        }
453    }
454    pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
455        Rc::new(RefCell::new(Account::new(lamports, space, owner)))
456    }
457    #[cfg(feature = "bincode")]
458    pub fn new_data<T: serde::Serialize>(
459        lamports: u64,
460        state: &T,
461        owner: &Pubkey,
462    ) -> Result<Self, bincode::Error> {
463        let data = bincode::serialize(state)?;
464        Ok(Account {
465            lamports,
466            data,
467            owner: *owner,
468            executable: false,
469            rent_epoch: Epoch::default(),
470        })
471    }
472    #[cfg(feature = "bincode")]
473    pub fn new_ref_data<T: serde::Serialize>(
474        lamports: u64,
475        state: &T,
476        owner: &Pubkey,
477    ) -> Result<RefCell<Self>, bincode::Error> {
478        Account::new_data(lamports, state, owner).map(RefCell::new)
479    }
480    #[cfg(feature = "bincode")]
481    pub fn new_data_with_space<T: serde::Serialize>(
482        lamports: u64,
483        state: &T,
484        space: usize,
485        owner: &Pubkey,
486    ) -> Result<Self, bincode::Error> {
487        let mut account = Account::new(lamports, space, owner);
488        shared_serialize_data(&mut account, state)?;
489        Ok(account)
490    }
491    #[cfg(feature = "bincode")]
492    pub fn new_ref_data_with_space<T: serde::Serialize>(
493        lamports: u64,
494        state: &T,
495        space: usize,
496        owner: &Pubkey,
497    ) -> Result<RefCell<Self>, bincode::Error> {
498        Account::new_data_with_space(lamports, state, space, owner).map(RefCell::new)
499    }
500    pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
501        Account {
502            lamports,
503            data: vec![0; space],
504            owner: *owner,
505            executable: false,
506            rent_epoch,
507        }
508    }
509    #[cfg(feature = "bincode")]
510    pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
511        shared_deserialize_data(self)
512    }
513    #[cfg(feature = "bincode")]
514    pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
515        shared_serialize_data(self, state)
516    }
517}
518
519impl AccountSharedData {
520    pub fn is_shared(&self) -> bool {
521        Arc::strong_count(&self.data) > 1
522    }
523
524    pub fn reserve(&mut self, additional: usize) {
525        if let Some(data) = Arc::get_mut(&mut self.data) {
526            data.reserve(additional)
527        } else {
528            let mut data = Vec::with_capacity(self.data.len().saturating_add(additional));
529            data.extend_from_slice(&self.data);
530            self.data = Arc::new(data);
531        }
532    }
533
534    pub fn capacity(&self) -> usize {
535        self.data.capacity()
536    }
537
538    pub fn data_clone(&self) -> Arc<Vec<u8>> {
539        Arc::clone(&self.data)
540    }
541
542    fn data_mut(&mut self) -> &mut Vec<u8> {
543        Arc::make_mut(&mut self.data)
544    }
545
546    pub fn resize(&mut self, new_len: usize, value: u8) {
547        self.data_mut().resize(new_len, value)
548    }
549
550    pub fn extend_from_slice(&mut self, data: &[u8]) {
551        self.data_mut().extend_from_slice(data)
552    }
553
554    pub fn set_data_from_slice(&mut self, new_data: &[u8]) {
555        // If the buffer isn't shared, we're going to memcpy in place.
556        let Some(data) = Arc::get_mut(&mut self.data) else {
557            // If the buffer is shared, the cheapest thing to do is to clone the
558            // incoming slice and replace the buffer.
559            return self.set_data(new_data.to_vec());
560        };
561
562        let new_len = new_data.len();
563
564        // Reserve additional capacity if needed. Here we make the assumption
565        // that growing the current buffer is cheaper than doing a whole new
566        // allocation to make `new_data` owned.
567        //
568        // This assumption holds true during CPI, especially when the account
569        // size doesn't change but the account is only changed in place. And
570        // it's also true when the account is grown by a small margin (the
571        // realloc limit is quite low), in which case the allocator can just
572        // update the allocation metadata without moving.
573        //
574        // Shrinking and copying in place is always faster than making
575        // `new_data` owned, since shrinking boils down to updating the Vec's
576        // length.
577
578        data.reserve(new_len.saturating_sub(data.len()));
579
580        // Safety:
581        // We just reserved enough capacity. We set data::len to 0 to avoid
582        // possible UB on panic (dropping uninitialized elements), do the copy,
583        // finally set the new length once everything is initialized.
584        #[allow(clippy::uninit_vec)]
585        // this is a false positive, the lint doesn't currently special case set_len(0)
586        unsafe {
587            data.set_len(0);
588            ptr::copy_nonoverlapping(new_data.as_ptr(), data.as_mut_ptr(), new_len);
589            data.set_len(new_len);
590        };
591    }
592
593    #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
594    fn set_data(&mut self, data: Vec<u8>) {
595        self.data = Arc::new(data);
596    }
597
598    pub fn spare_data_capacity_mut(&mut self) -> &mut [MaybeUninit<u8>] {
599        self.data_mut().spare_capacity_mut()
600    }
601
602    pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
603        AccountSharedData {
604            lamports,
605            data: Arc::new(vec![0u8; space]),
606            owner: *owner,
607            executable: false,
608            rent_epoch: Epoch::default(),
609        }
610    }
611    pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
612        Rc::new(RefCell::new(AccountSharedData::new(lamports, space, owner)))
613    }
614    #[cfg(feature = "bincode")]
615    pub fn new_data<T: serde::Serialize>(
616        lamports: u64,
617        state: &T,
618        owner: &Pubkey,
619    ) -> Result<Self, bincode::Error> {
620        let data = bincode::serialize(state)?;
621        Ok(Self::create_from_existing_shared_data(
622            lamports,
623            Arc::new(data),
624            *owner,
625            false,
626            Epoch::default(),
627        ))
628    }
629    #[cfg(feature = "bincode")]
630    pub fn new_ref_data<T: serde::Serialize>(
631        lamports: u64,
632        state: &T,
633        owner: &Pubkey,
634    ) -> Result<RefCell<Self>, bincode::Error> {
635        AccountSharedData::new_data(lamports, state, owner).map(RefCell::new)
636    }
637    #[cfg(feature = "bincode")]
638    pub fn new_data_with_space<T: serde::Serialize>(
639        lamports: u64,
640        state: &T,
641        space: usize,
642        owner: &Pubkey,
643    ) -> Result<Self, bincode::Error> {
644        let mut account = AccountSharedData::new(lamports, space, owner);
645        shared_serialize_data(&mut account, state)?;
646        Ok(account)
647    }
648    #[cfg(feature = "bincode")]
649    pub fn new_ref_data_with_space<T: serde::Serialize>(
650        lamports: u64,
651        state: &T,
652        space: usize,
653        owner: &Pubkey,
654    ) -> Result<RefCell<Self>, bincode::Error> {
655        AccountSharedData::new_data_with_space(lamports, state, space, owner).map(RefCell::new)
656    }
657    pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
658        AccountSharedData {
659            lamports,
660            data: Arc::new(vec![0; space]),
661            owner: *owner,
662            executable: false,
663            rent_epoch,
664        }
665    }
666    #[cfg(feature = "bincode")]
667    pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
668        shared_deserialize_data(self)
669    }
670    #[cfg(feature = "bincode")]
671    pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
672        shared_serialize_data(self, state)
673    }
674
675    pub fn create_from_existing_shared_data(
676        lamports: u64,
677        data: Arc<Vec<u8>>,
678        owner: Pubkey,
679        executable: bool,
680        rent_epoch: Epoch,
681    ) -> AccountSharedData {
682        AccountSharedData {
683            lamports,
684            data,
685            owner,
686            executable,
687            rent_epoch,
688        }
689    }
690}
691
692pub type InheritableAccountFields = (u64, Epoch);
693pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH);
694
695#[cfg(feature = "bincode")]
696pub fn create_account_with_fields<S: SysvarSerialize>(
697    sysvar: &S,
698    (lamports, rent_epoch): InheritableAccountFields,
699) -> Account {
700    let data_len = S::size_of().max(bincode::serialized_size(sysvar).unwrap() as usize);
701    let mut account = Account::new(lamports, data_len, &solana_sdk_ids::sysvar::id());
702    to_account::<S, Account>(sysvar, &mut account).unwrap();
703    account.rent_epoch = rent_epoch;
704    account
705}
706
707#[cfg(feature = "bincode")]
708pub fn create_account_for_test<S: SysvarSerialize>(sysvar: &S) -> Account {
709    create_account_with_fields(sysvar, DUMMY_INHERITABLE_ACCOUNT_FIELDS)
710}
711
712#[cfg(feature = "bincode")]
713/// Create an `Account` from a `Sysvar`.
714pub fn create_account_shared_data_with_fields<S: SysvarSerialize>(
715    sysvar: &S,
716    fields: InheritableAccountFields,
717) -> AccountSharedData {
718    AccountSharedData::from(create_account_with_fields(sysvar, fields))
719}
720
721#[cfg(feature = "bincode")]
722pub fn create_account_shared_data_for_test<S: SysvarSerialize>(sysvar: &S) -> AccountSharedData {
723    AccountSharedData::from(create_account_with_fields(
724        sysvar,
725        DUMMY_INHERITABLE_ACCOUNT_FIELDS,
726    ))
727}
728
729#[cfg(feature = "bincode")]
730/// Create a `Sysvar` from an `Account`'s data.
731pub fn from_account<S: SysvarSerialize, T: ReadableAccount>(account: &T) -> Option<S> {
732    bincode::deserialize(account.data()).ok()
733}
734
735#[cfg(feature = "bincode")]
736/// Serialize a `Sysvar` into an `Account`'s data.
737pub fn to_account<S: SysvarSerialize, T: WritableAccount>(
738    sysvar: &S,
739    account: &mut T,
740) -> Option<()> {
741    bincode::serialize_into(account.data_as_mut_slice(), sysvar).ok()
742}
743
744/// Return the information required to construct an `AccountInfo`.  Used by the
745/// `AccountInfo` conversion implementations.
746impl solana_account_info::Account for Account {
747    fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool) {
748        (
749            &mut self.lamports,
750            &mut self.data,
751            &self.owner,
752            self.executable,
753        )
754    }
755}
756
757/// Create `AccountInfo`s
758pub fn create_is_signer_account_infos<'a>(
759    accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
760) -> Vec<AccountInfo<'a>> {
761    accounts
762        .iter_mut()
763        .map(|(key, is_signer, account)| {
764            AccountInfo::new(
765                key,
766                *is_signer,
767                false,
768                &mut account.lamports,
769                &mut account.data,
770                &account.owner,
771                account.executable,
772            )
773        })
774        .collect()
775}
776
777/// Replacement for the executable flag: An account being owned by one of these contains a program.
778pub const PROGRAM_OWNERS: &[Pubkey] = &[
779    bpf_loader_upgradeable::id(),
780    bpf_loader::id(),
781    bpf_loader_deprecated::id(),
782    loader_v4::id(),
783];
784
785#[cfg(test)]
786pub mod tests {
787    use super::*;
788
789    fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) {
790        let mut account1 = Account::new(1, 2, key);
791        account1.executable = true;
792        account1.rent_epoch = 4;
793        let mut account2 = AccountSharedData::new(1, 2, key);
794        account2.executable = true;
795        account2.rent_epoch = 4;
796        assert!(accounts_equal(&account1, &account2));
797        (account1, account2)
798    }
799
800    #[test]
801    fn test_account_data_copy_as_slice() {
802        let key = Pubkey::new_unique();
803        let key2 = Pubkey::new_unique();
804        let (mut account1, mut account2) = make_two_accounts(&key);
805        account1.copy_into_owner_from_slice(key2.as_ref());
806        account2.copy_into_owner_from_slice(key2.as_ref());
807        assert!(accounts_equal(&account1, &account2));
808        assert_eq!(account1.owner(), &key2);
809    }
810
811    #[test]
812    fn test_account_set_data_from_slice() {
813        let key = Pubkey::new_unique();
814        let (_, mut account) = make_two_accounts(&key);
815        assert_eq!(account.data(), &vec![0, 0]);
816        account.set_data_from_slice(&[1, 2]);
817        assert_eq!(account.data(), &vec![1, 2]);
818        account.set_data_from_slice(&[1, 2, 3]);
819        assert_eq!(account.data(), &vec![1, 2, 3]);
820        account.set_data_from_slice(&[4, 5, 6]);
821        assert_eq!(account.data(), &vec![4, 5, 6]);
822        account.set_data_from_slice(&[4, 5, 6, 0]);
823        assert_eq!(account.data(), &vec![4, 5, 6, 0]);
824        account.set_data_from_slice(&[]);
825        assert_eq!(account.data().len(), 0);
826        account.set_data_from_slice(&[44]);
827        assert_eq!(account.data(), &vec![44]);
828        account.set_data_from_slice(&[44]);
829        assert_eq!(account.data(), &vec![44]);
830    }
831
832    #[test]
833    fn test_account_data_set_data() {
834        let key = Pubkey::new_unique();
835        let (_, mut account) = make_two_accounts(&key);
836        assert_eq!(account.data(), &vec![0, 0]);
837        account.set_data(vec![1, 2]);
838        assert_eq!(account.data(), &vec![1, 2]);
839        account.set_data(vec![]);
840        assert_eq!(account.data().len(), 0);
841    }
842
843    #[test]
844    #[should_panic(
845        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
846    )]
847    fn test_account_deserialize() {
848        let key = Pubkey::new_unique();
849        let (account1, _account2) = make_two_accounts(&key);
850        account1.deserialize_data::<String>().unwrap();
851    }
852
853    #[test]
854    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
855    fn test_account_serialize() {
856        let key = Pubkey::new_unique();
857        let (mut account1, _account2) = make_two_accounts(&key);
858        account1.serialize_data(&"hello world").unwrap();
859    }
860
861    #[test]
862    #[should_panic(
863        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
864    )]
865    fn test_account_shared_data_deserialize() {
866        let key = Pubkey::new_unique();
867        let (_account1, account2) = make_two_accounts(&key);
868        account2.deserialize_data::<String>().unwrap();
869    }
870
871    #[test]
872    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
873    fn test_account_shared_data_serialize() {
874        let key = Pubkey::new_unique();
875        let (_account1, mut account2) = make_two_accounts(&key);
876        account2.serialize_data(&"hello world").unwrap();
877    }
878
879    #[test]
880    #[allow(deprecated)]
881    fn test_to_account_shared_data() {
882        let key = Pubkey::new_unique();
883        let (account1, account2) = make_two_accounts(&key);
884        assert!(accounts_equal(&account1, &account2));
885        let account3 = account1.to_account_shared_data();
886        let account4 = account2.to_account_shared_data();
887        assert!(accounts_equal(&account1, &account3));
888        assert!(accounts_equal(&account1, &account4));
889    }
890
891    #[test]
892    fn test_account_shared_data() {
893        let key = Pubkey::new_unique();
894        let (account1, account2) = make_two_accounts(&key);
895        assert!(accounts_equal(&account1, &account2));
896        let account = account1;
897        assert_eq!(account.lamports, 1);
898        assert_eq!(account.lamports(), 1);
899        assert_eq!(account.data.len(), 2);
900        assert_eq!(account.data().len(), 2);
901        assert_eq!(account.owner, key);
902        assert_eq!(account.owner(), &key);
903        assert!(account.executable);
904        assert!(account.executable());
905        assert_eq!(account.rent_epoch, 4);
906        assert_eq!(account.rent_epoch(), 4);
907        let account = account2;
908        assert_eq!(account.lamports, 1);
909        assert_eq!(account.lamports(), 1);
910        assert_eq!(account.data.len(), 2);
911        assert_eq!(account.data().len(), 2);
912        assert_eq!(account.owner, key);
913        assert_eq!(account.owner(), &key);
914        assert!(account.executable);
915        assert!(account.executable());
916        assert_eq!(account.rent_epoch, 4);
917        assert_eq!(account.rent_epoch(), 4);
918    }
919
920    // test clone and from for both types against expected
921    fn test_equal(
922        should_be_equal: bool,
923        account1: &Account,
924        account2: &AccountSharedData,
925        account_expected: &Account,
926    ) {
927        assert_eq!(should_be_equal, accounts_equal(account1, account2));
928        if should_be_equal {
929            assert!(accounts_equal(account_expected, account2));
930        }
931        assert_eq!(
932            accounts_equal(account_expected, account1),
933            accounts_equal(account_expected, &account1.clone())
934        );
935        assert_eq!(
936            accounts_equal(account_expected, account2),
937            accounts_equal(account_expected, &account2.clone())
938        );
939        assert_eq!(
940            accounts_equal(account_expected, account1),
941            accounts_equal(account_expected, &AccountSharedData::from(account1.clone()))
942        );
943        assert_eq!(
944            accounts_equal(account_expected, account2),
945            accounts_equal(account_expected, &Account::from(account2.clone()))
946        );
947    }
948
949    #[test]
950    fn test_account_add_sub_lamports() {
951        let key = Pubkey::new_unique();
952        let (mut account1, mut account2) = make_two_accounts(&key);
953        assert!(accounts_equal(&account1, &account2));
954        account1.checked_add_lamports(1).unwrap();
955        account2.checked_add_lamports(1).unwrap();
956        assert!(accounts_equal(&account1, &account2));
957        assert_eq!(account1.lamports(), 2);
958        account1.checked_sub_lamports(2).unwrap();
959        account2.checked_sub_lamports(2).unwrap();
960        assert!(accounts_equal(&account1, &account2));
961        assert_eq!(account1.lamports(), 0);
962    }
963
964    #[test]
965    #[should_panic(expected = "Overflow")]
966    fn test_account_checked_add_lamports_overflow() {
967        let key = Pubkey::new_unique();
968        let (mut account1, _account2) = make_two_accounts(&key);
969        account1.checked_add_lamports(u64::MAX).unwrap();
970    }
971
972    #[test]
973    #[should_panic(expected = "Underflow")]
974    fn test_account_checked_sub_lamports_underflow() {
975        let key = Pubkey::new_unique();
976        let (mut account1, _account2) = make_two_accounts(&key);
977        account1.checked_sub_lamports(u64::MAX).unwrap();
978    }
979
980    #[test]
981    #[should_panic(expected = "Overflow")]
982    fn test_account_checked_add_lamports_overflow2() {
983        let key = Pubkey::new_unique();
984        let (_account1, mut account2) = make_two_accounts(&key);
985        account2.checked_add_lamports(u64::MAX).unwrap();
986    }
987
988    #[test]
989    #[should_panic(expected = "Underflow")]
990    fn test_account_checked_sub_lamports_underflow2() {
991        let key = Pubkey::new_unique();
992        let (_account1, mut account2) = make_two_accounts(&key);
993        account2.checked_sub_lamports(u64::MAX).unwrap();
994    }
995
996    #[test]
997    fn test_account_saturating_add_lamports() {
998        let key = Pubkey::new_unique();
999        let (mut account, _) = make_two_accounts(&key);
1000
1001        let remaining = 22;
1002        account.set_lamports(u64::MAX - remaining);
1003        account.saturating_add_lamports(remaining * 2);
1004        assert_eq!(account.lamports(), u64::MAX);
1005    }
1006
1007    #[test]
1008    fn test_account_saturating_sub_lamports() {
1009        let key = Pubkey::new_unique();
1010        let (mut account, _) = make_two_accounts(&key);
1011
1012        let remaining = 33;
1013        account.set_lamports(remaining);
1014        account.saturating_sub_lamports(remaining * 2);
1015        assert_eq!(account.lamports(), 0);
1016    }
1017
1018    #[test]
1019    fn test_account_shared_data_all_fields() {
1020        let key = Pubkey::new_unique();
1021        let key2 = Pubkey::new_unique();
1022        let key3 = Pubkey::new_unique();
1023        let (mut account1, mut account2) = make_two_accounts(&key);
1024        assert!(accounts_equal(&account1, &account2));
1025
1026        let mut account_expected = account1.clone();
1027        assert!(accounts_equal(&account1, &account_expected));
1028        assert!(accounts_equal(&account1, &account2.clone())); // test the clone here
1029
1030        for field_index in 0..5 {
1031            for pass in 0..4 {
1032                if field_index == 0 {
1033                    if pass == 0 {
1034                        account1.checked_add_lamports(1).unwrap();
1035                    } else if pass == 1 {
1036                        account_expected.checked_add_lamports(1).unwrap();
1037                        account2.set_lamports(account2.lamports + 1);
1038                    } else if pass == 2 {
1039                        account1.set_lamports(account1.lamports + 1);
1040                    } else if pass == 3 {
1041                        account_expected.checked_add_lamports(1).unwrap();
1042                        account2.checked_add_lamports(1).unwrap();
1043                    }
1044                } else if field_index == 1 {
1045                    if pass == 0 {
1046                        account1.data[0] += 1;
1047                    } else if pass == 1 {
1048                        account_expected.data[0] += 1;
1049                        account2.data_as_mut_slice()[0] = account2.data[0] + 1;
1050                    } else if pass == 2 {
1051                        account1.data_as_mut_slice()[0] = account1.data[0] + 1;
1052                    } else if pass == 3 {
1053                        account_expected.data[0] += 1;
1054                        account2.data_as_mut_slice()[0] += 1;
1055                    }
1056                } else if field_index == 2 {
1057                    if pass == 0 {
1058                        account1.owner = key2;
1059                    } else if pass == 1 {
1060                        account_expected.owner = key2;
1061                        account2.set_owner(key2);
1062                    } else if pass == 2 {
1063                        account1.set_owner(key3);
1064                    } else if pass == 3 {
1065                        account_expected.owner = key3;
1066                        account2.owner = key3;
1067                    }
1068                } else if field_index == 3 {
1069                    if pass == 0 {
1070                        account1.executable = !account1.executable;
1071                    } else if pass == 1 {
1072                        account_expected.executable = !account_expected.executable;
1073                        account2.set_executable(!account2.executable);
1074                    } else if pass == 2 {
1075                        account1.set_executable(!account1.executable);
1076                    } else if pass == 3 {
1077                        account_expected.executable = !account_expected.executable;
1078                        account2.executable = !account2.executable;
1079                    }
1080                } else if field_index == 4 {
1081                    if pass == 0 {
1082                        account1.rent_epoch += 1;
1083                    } else if pass == 1 {
1084                        account_expected.rent_epoch += 1;
1085                        account2.set_rent_epoch(account2.rent_epoch + 1);
1086                    } else if pass == 2 {
1087                        account1.set_rent_epoch(account1.rent_epoch + 1);
1088                    } else if pass == 3 {
1089                        account_expected.rent_epoch += 1;
1090                        account2.rent_epoch += 1;
1091                    }
1092                }
1093
1094                let should_be_equal = pass == 1 || pass == 3;
1095                test_equal(should_be_equal, &account1, &account2, &account_expected);
1096
1097                // test new_ref
1098                if should_be_equal {
1099                    assert!(accounts_equal(
1100                        &Account::new_ref(
1101                            account_expected.lamports(),
1102                            account_expected.data().len(),
1103                            account_expected.owner()
1104                        )
1105                        .borrow(),
1106                        &AccountSharedData::new_ref(
1107                            account_expected.lamports(),
1108                            account_expected.data().len(),
1109                            account_expected.owner()
1110                        )
1111                        .borrow()
1112                    ));
1113
1114                    {
1115                        // test new_data
1116                        let account1_with_data = Account::new_data(
1117                            account_expected.lamports(),
1118                            &account_expected.data()[0],
1119                            account_expected.owner(),
1120                        )
1121                        .unwrap();
1122                        let account2_with_data = AccountSharedData::new_data(
1123                            account_expected.lamports(),
1124                            &account_expected.data()[0],
1125                            account_expected.owner(),
1126                        )
1127                        .unwrap();
1128
1129                        assert!(accounts_equal(&account1_with_data, &account2_with_data));
1130                        assert_eq!(
1131                            account1_with_data.deserialize_data::<u8>().unwrap(),
1132                            account2_with_data.deserialize_data::<u8>().unwrap()
1133                        );
1134                    }
1135
1136                    // test new_data_with_space
1137                    assert!(accounts_equal(
1138                        &Account::new_data_with_space(
1139                            account_expected.lamports(),
1140                            &account_expected.data()[0],
1141                            1,
1142                            account_expected.owner()
1143                        )
1144                        .unwrap(),
1145                        &AccountSharedData::new_data_with_space(
1146                            account_expected.lamports(),
1147                            &account_expected.data()[0],
1148                            1,
1149                            account_expected.owner()
1150                        )
1151                        .unwrap()
1152                    ));
1153
1154                    // test new_ref_data
1155                    assert!(accounts_equal(
1156                        &Account::new_ref_data(
1157                            account_expected.lamports(),
1158                            &account_expected.data()[0],
1159                            account_expected.owner()
1160                        )
1161                        .unwrap()
1162                        .borrow(),
1163                        &AccountSharedData::new_ref_data(
1164                            account_expected.lamports(),
1165                            &account_expected.data()[0],
1166                            account_expected.owner()
1167                        )
1168                        .unwrap()
1169                        .borrow()
1170                    ));
1171
1172                    //new_ref_data_with_space
1173                    assert!(accounts_equal(
1174                        &Account::new_ref_data_with_space(
1175                            account_expected.lamports(),
1176                            &account_expected.data()[0],
1177                            1,
1178                            account_expected.owner()
1179                        )
1180                        .unwrap()
1181                        .borrow(),
1182                        &AccountSharedData::new_ref_data_with_space(
1183                            account_expected.lamports(),
1184                            &account_expected.data()[0],
1185                            1,
1186                            account_expected.owner()
1187                        )
1188                        .unwrap()
1189                        .borrow()
1190                    ));
1191                }
1192            }
1193        }
1194    }
1195}