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