Skip to main content

solana_account/
account.rs

1//! The [`Account`] and [`AccountSharedData`] types and their codec-independent APIs.
2
3#[cfg(feature = "dev-context-only-utils")]
4use qualifier_attr::qualifiers;
5use {
6    crate::{Account, AccountSharedData},
7    solana_account_info::{debug_account_data::*, AccountInfo},
8    solana_clock::{Epoch, INITIAL_RENT_EPOCH},
9    solana_instruction_error::LamportsError,
10    solana_pubkey::Pubkey,
11    solana_sdk_ids::{bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, loader_v4},
12    std::{cell::RefCell, fmt, mem::MaybeUninit, ops::Deref, ptr, rc::Rc, sync::Arc},
13};
14
15#[cfg(feature = "bincode")]
16mod bincode;
17#[cfg(feature = "bincode")]
18pub use bincode::*;
19
20// NOTE: the wincode codec surface is not a peer of the bincode module above. Instead of
21// duplicating the inherent `new_data`/`serialize_data`/... methods, wincode is exposed
22// solely through the `state_traits::StateMutWincode` trait (read, write, and construct).
23
24// NOTE: `Account` and `AccountSharedData` are defined in the crate root (`lib.rs`)
25// rather than here. The frozen-abi digest of any downstream struct that holds an
26// `Account`/`AccountSharedData` field hashes that field's fully-qualified
27// `std::any::type_name`, so the definitions must stay at `solana_account::*` to keep
28// `type_name` stable. Moving them into this module would silently change ABI digests
29// across the ecosystem.
30
31/// Compares two ReadableAccounts
32///
33/// Returns true if accounts are essentially equivalent as in all fields are equivalent.
34pub fn accounts_equal<T: ReadableAccount, U: ReadableAccount>(me: &T, other: &U) -> bool {
35    me.lamports() == other.lamports()
36        && me.executable() == other.executable()
37        && me.rent_epoch() == other.rent_epoch()
38        && me.owner() == other.owner()
39        && me.data() == other.data()
40}
41
42impl From<AccountSharedData> for Account {
43    fn from(mut other: AccountSharedData) -> Self {
44        let account_data = Arc::make_mut(&mut other.data);
45        Self {
46            lamports: other.lamports,
47            data: std::mem::take(account_data),
48            owner: other.owner,
49            executable: other.executable,
50            rent_epoch: other.rent_epoch,
51        }
52    }
53}
54
55impl From<Account> for AccountSharedData {
56    fn from(other: Account) -> Self {
57        Self {
58            lamports: other.lamports,
59            data: Arc::new(other.data),
60            owner: other.owner,
61            executable: other.executable,
62            rent_epoch: other.rent_epoch,
63        }
64    }
65}
66
67pub trait WritableAccount: ReadableAccount {
68    fn set_lamports(&mut self, lamports: u64);
69    fn checked_add_lamports(&mut self, lamports: u64) -> Result<(), LamportsError> {
70        self.set_lamports(
71            self.lamports()
72                .checked_add(lamports)
73                .ok_or(LamportsError::ArithmeticOverflow)?,
74        );
75        Ok(())
76    }
77    fn checked_sub_lamports(&mut self, lamports: u64) -> Result<(), LamportsError> {
78        self.set_lamports(
79            self.lamports()
80                .checked_sub(lamports)
81                .ok_or(LamportsError::ArithmeticUnderflow)?,
82        );
83        Ok(())
84    }
85    fn saturating_add_lamports(&mut self, lamports: u64) {
86        self.set_lamports(self.lamports().saturating_add(lamports))
87    }
88    fn saturating_sub_lamports(&mut self, lamports: u64) {
89        self.set_lamports(self.lamports().saturating_sub(lamports))
90    }
91    fn data_as_mut_slice(&mut self) -> &mut [u8];
92    fn set_owner(&mut self, owner: Pubkey);
93    fn copy_into_owner_from_slice(&mut self, source: &[u8]);
94    fn set_executable(&mut self, executable: bool);
95    fn set_rent_epoch(&mut self, epoch: Epoch);
96}
97
98pub trait ReadableAccount: Sized {
99    fn lamports(&self) -> u64;
100    fn data(&self) -> &[u8];
101    fn owner(&self) -> &Pubkey;
102    fn executable(&self) -> bool;
103    fn rent_epoch(&self) -> Epoch;
104}
105
106impl<T> ReadableAccount for T
107where
108    T: Deref,
109    T::Target: ReadableAccount,
110{
111    fn lamports(&self) -> u64 {
112        self.deref().lamports()
113    }
114    fn data(&self) -> &[u8] {
115        self.deref().data()
116    }
117    fn owner(&self) -> &Pubkey {
118        self.deref().owner()
119    }
120    fn executable(&self) -> bool {
121        self.deref().executable()
122    }
123    fn rent_epoch(&self) -> Epoch {
124        self.deref().rent_epoch()
125    }
126}
127
128impl ReadableAccount for Account {
129    fn lamports(&self) -> u64 {
130        self.lamports
131    }
132    fn data(&self) -> &[u8] {
133        &self.data
134    }
135    fn owner(&self) -> &Pubkey {
136        &self.owner
137    }
138    fn executable(&self) -> bool {
139        self.executable
140    }
141    fn rent_epoch(&self) -> Epoch {
142        self.rent_epoch
143    }
144}
145
146impl WritableAccount for Account {
147    fn set_lamports(&mut self, lamports: u64) {
148        self.lamports = lamports;
149    }
150    fn data_as_mut_slice(&mut self) -> &mut [u8] {
151        &mut self.data
152    }
153    fn set_owner(&mut self, owner: Pubkey) {
154        self.owner = owner;
155    }
156    fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
157        self.owner.as_mut().copy_from_slice(source);
158    }
159    fn set_executable(&mut self, executable: bool) {
160        self.executable = executable;
161    }
162    fn set_rent_epoch(&mut self, epoch: Epoch) {
163        self.rent_epoch = epoch;
164    }
165}
166
167impl WritableAccount for AccountSharedData {
168    fn set_lamports(&mut self, lamports: u64) {
169        self.lamports = lamports;
170    }
171    fn data_as_mut_slice(&mut self) -> &mut [u8] {
172        &mut self.data_mut()[..]
173    }
174    fn set_owner(&mut self, owner: Pubkey) {
175        self.owner = owner;
176    }
177    fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
178        self.owner.as_mut().copy_from_slice(source);
179    }
180    fn set_executable(&mut self, executable: bool) {
181        self.executable = executable;
182    }
183    fn set_rent_epoch(&mut self, epoch: Epoch) {
184        self.rent_epoch = epoch;
185    }
186}
187
188impl ReadableAccount for AccountSharedData {
189    fn lamports(&self) -> u64 {
190        self.lamports
191    }
192    fn data(&self) -> &[u8] {
193        &self.data
194    }
195    fn owner(&self) -> &Pubkey {
196        &self.owner
197    }
198    fn executable(&self) -> bool {
199        self.executable
200    }
201    fn rent_epoch(&self) -> Epoch {
202        self.rent_epoch
203    }
204}
205
206fn debug_fmt<T: ReadableAccount>(item: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207    let mut f = f.debug_struct("Account");
208
209    f.field("lamports", &item.lamports())
210        .field("data.len", &item.data().len())
211        .field("owner", &item.owner())
212        .field("executable", &item.executable())
213        .field("rent_epoch", &item.rent_epoch());
214    debug_account_data(item.data(), &mut f);
215
216    f.finish()
217}
218
219impl fmt::Debug for Account {
220    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221        debug_fmt(self, f)
222    }
223}
224
225impl fmt::Debug for AccountSharedData {
226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227        debug_fmt(self, f)
228    }
229}
230
231impl Account {
232    pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
233        Account {
234            lamports,
235            data: vec![0; space],
236            owner: *owner,
237            executable: false,
238            rent_epoch: Epoch::default(),
239        }
240    }
241    /// Construct an `Account` from already-encoded `data`, taking ownership of the
242    /// buffer. Avoids the zero-fill allocation of [`Account::new`] followed by a
243    /// separate write when the caller already has the bytes.
244    pub fn new_with_data(lamports: u64, data: Vec<u8>, owner: &Pubkey) -> Self {
245        Account {
246            lamports,
247            data,
248            owner: *owner,
249            executable: false,
250            rent_epoch: Epoch::default(),
251        }
252    }
253    pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
254        Rc::new(RefCell::new(Account::new(lamports, space, owner)))
255    }
256    pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
257        Account {
258            lamports,
259            data: vec![0; space],
260            owner: *owner,
261            executable: false,
262            rent_epoch,
263        }
264    }
265}
266
267impl AccountSharedData {
268    pub fn is_shared(&self) -> bool {
269        Arc::strong_count(&self.data) > 1
270    }
271
272    pub fn reserve(&mut self, additional: usize) {
273        if let Some(data) = Arc::get_mut(&mut self.data) {
274            data.reserve(additional)
275        } else {
276            let mut data = Vec::with_capacity(self.data.len().saturating_add(additional));
277            data.extend_from_slice(&self.data);
278            self.data = Arc::new(data);
279        }
280    }
281
282    pub fn capacity(&self) -> usize {
283        self.data.capacity()
284    }
285
286    pub fn data_clone(&self) -> Arc<Vec<u8>> {
287        Arc::clone(&self.data)
288    }
289
290    fn data_mut(&mut self) -> &mut Vec<u8> {
291        Arc::make_mut(&mut self.data)
292    }
293
294    pub fn resize(&mut self, new_len: usize, value: u8) {
295        self.data_mut().resize(new_len, value)
296    }
297
298    pub fn extend_from_slice(&mut self, data: &[u8]) {
299        self.data_mut().extend_from_slice(data)
300    }
301
302    pub fn set_data_from_slice(&mut self, new_data: &[u8]) {
303        // If the buffer isn't shared, we're going to memcpy in place.
304        let Some(data) = Arc::get_mut(&mut self.data) else {
305            // If the buffer is shared, the cheapest thing to do is to clone the
306            // incoming slice and replace the buffer.
307            return self.set_data(new_data.to_vec());
308        };
309
310        let new_len = new_data.len();
311
312        // Reserve additional capacity if needed. Here we make the assumption
313        // that growing the current buffer is cheaper than doing a whole new
314        // allocation to make `new_data` owned.
315        //
316        // This assumption holds true during CPI, especially when the account
317        // size doesn't change but the account is only changed in place. And
318        // it's also true when the account is grown by a small margin (the
319        // realloc limit is quite low), in which case the allocator can just
320        // update the allocation metadata without moving.
321        //
322        // Shrinking and copying in place is always faster than making
323        // `new_data` owned, since shrinking boils down to updating the Vec's
324        // length.
325
326        data.reserve(new_len.saturating_sub(data.len()));
327
328        // Safety:
329        // We just reserved enough capacity. We set data::len to 0 to avoid
330        // possible UB on panic (dropping uninitialized elements), do the copy,
331        // finally set the new length once everything is initialized.
332        #[allow(clippy::uninit_vec)]
333        // this is a false positive, the lint doesn't currently special case set_len(0)
334        unsafe {
335            data.set_len(0);
336            ptr::copy_nonoverlapping(new_data.as_ptr(), data.as_mut_ptr(), new_len);
337            data.set_len(new_len);
338        };
339    }
340
341    #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
342    fn set_data(&mut self, data: Vec<u8>) {
343        self.data = Arc::new(data);
344    }
345
346    pub fn spare_data_capacity_mut(&mut self) -> &mut [MaybeUninit<u8>] {
347        self.data_mut().spare_capacity_mut()
348    }
349
350    pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
351        AccountSharedData {
352            lamports,
353            data: Arc::new(vec![0u8; space]),
354            owner: *owner,
355            executable: false,
356            rent_epoch: Epoch::default(),
357        }
358    }
359    /// Construct an `AccountSharedData` from already-encoded `data`, taking ownership of
360    /// the buffer. Avoids the zero-fill allocation of [`AccountSharedData::new`] followed
361    /// by a separate write when the caller already has the bytes.
362    ///
363    /// To reuse an existing `Arc` buffer, or to set `executable`/`rent_epoch`, use
364    /// [`AccountSharedData::create_from_existing_shared_data`].
365    pub fn new_with_data(lamports: u64, data: Vec<u8>, owner: &Pubkey) -> Self {
366        AccountSharedData {
367            lamports,
368            data: Arc::new(data),
369            owner: *owner,
370            executable: false,
371            rent_epoch: Epoch::default(),
372        }
373    }
374    pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
375        Rc::new(RefCell::new(AccountSharedData::new(lamports, space, owner)))
376    }
377    pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
378        AccountSharedData {
379            lamports,
380            data: Arc::new(vec![0; space]),
381            owner: *owner,
382            executable: false,
383            rent_epoch,
384        }
385    }
386    pub fn create_from_existing_shared_data(
387        lamports: u64,
388        data: Arc<Vec<u8>>,
389        owner: Pubkey,
390        executable: bool,
391        rent_epoch: Epoch,
392    ) -> AccountSharedData {
393        AccountSharedData {
394            lamports,
395            data,
396            owner,
397            executable,
398            rent_epoch,
399        }
400    }
401}
402
403pub type InheritableAccountFields = (u64, Epoch);
404pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH);
405
406/// Return the information required to construct an `AccountInfo`.  Used by the
407/// `AccountInfo` conversion implementations.
408impl solana_account_info::Account for Account {
409    fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool) {
410        (
411            &mut self.lamports,
412            &mut self.data,
413            &self.owner,
414            self.executable,
415        )
416    }
417}
418
419/// Create `AccountInfo`s
420pub fn create_is_signer_account_infos<'a>(
421    accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
422) -> Vec<AccountInfo<'a>> {
423    accounts
424        .iter_mut()
425        .map(|(key, is_signer, account)| {
426            AccountInfo::new(
427                key,
428                *is_signer,
429                false,
430                &mut account.lamports,
431                &mut account.data,
432                &account.owner,
433                account.executable,
434            )
435        })
436        .collect()
437}
438
439/// Replacement for the executable flag: An account being owned by one of these contains a program.
440#[deprecated(since = "4.3.0", note = "no longer available as a constant")]
441pub const PROGRAM_OWNERS: &[Pubkey] = &[
442    bpf_loader_upgradeable::id(),
443    bpf_loader::id(),
444    bpf_loader_deprecated::id(),
445    loader_v4::id(),
446];
447
448#[cfg(test)]
449pub mod tests {
450    use super::*;
451
452    fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) {
453        let mut account1 = Account::new(1, 2, key);
454        account1.executable = true;
455        account1.rent_epoch = 4;
456        let mut account2 = AccountSharedData::new(1, 2, key);
457        account2.executable = true;
458        account2.rent_epoch = 4;
459        assert!(accounts_equal(&account1, &account2));
460        (account1, account2)
461    }
462
463    #[test]
464    fn test_account_shared_data_new_with_data() {
465        let key = Pubkey::new_unique();
466
467        let account = AccountSharedData::new_with_data(1, vec![1, 2, 3], &key);
468        assert!(accounts_equal(
469            &account,
470            &Account::new_with_data(1, vec![1, 2, 3], &key)
471        ));
472        assert_eq!(account.lamports(), 1);
473        assert_eq!(account.owner(), &key);
474        assert_eq!(account.data(), &[1, 2, 3]);
475        assert!(!account.executable());
476        assert_eq!(account.rent_epoch(), Epoch::default());
477        assert!(!account.is_shared());
478    }
479
480    #[test]
481    fn test_account_data_copy_as_slice() {
482        let key = Pubkey::new_unique();
483        let key2 = Pubkey::new_unique();
484        let (mut account1, mut account2) = make_two_accounts(&key);
485        account1.copy_into_owner_from_slice(key2.as_ref());
486        account2.copy_into_owner_from_slice(key2.as_ref());
487        assert!(accounts_equal(&account1, &account2));
488        assert_eq!(account1.owner(), &key2);
489    }
490
491    #[test]
492    fn test_account_set_data_from_slice() {
493        let key = Pubkey::new_unique();
494        let (_, mut account) = make_two_accounts(&key);
495        assert_eq!(account.data(), &vec![0, 0]);
496        account.set_data_from_slice(&[1, 2]);
497        assert_eq!(account.data(), &vec![1, 2]);
498        account.set_data_from_slice(&[1, 2, 3]);
499        assert_eq!(account.data(), &vec![1, 2, 3]);
500        account.set_data_from_slice(&[4, 5, 6]);
501        assert_eq!(account.data(), &vec![4, 5, 6]);
502        account.set_data_from_slice(&[4, 5, 6, 0]);
503        assert_eq!(account.data(), &vec![4, 5, 6, 0]);
504        account.set_data_from_slice(&[]);
505        assert_eq!(account.data().len(), 0);
506        account.set_data_from_slice(&[44]);
507        assert_eq!(account.data(), &vec![44]);
508        account.set_data_from_slice(&[44]);
509        assert_eq!(account.data(), &vec![44]);
510    }
511
512    #[test]
513    fn test_account_data_set_data() {
514        let key = Pubkey::new_unique();
515        let (_, mut account) = make_two_accounts(&key);
516        assert_eq!(account.data(), &vec![0, 0]);
517        account.set_data(vec![1, 2]);
518        assert_eq!(account.data(), &vec![1, 2]);
519        account.set_data(vec![]);
520        assert_eq!(account.data().len(), 0);
521    }
522
523    #[test]
524    #[should_panic(
525        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
526    )]
527    fn test_account_deserialize() {
528        let key = Pubkey::new_unique();
529        let (account1, _account2) = make_two_accounts(&key);
530        account1.deserialize_data::<String>().unwrap();
531    }
532
533    #[test]
534    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
535    fn test_account_serialize() {
536        let key = Pubkey::new_unique();
537        let (mut account1, _account2) = make_two_accounts(&key);
538        account1.serialize_data(&"hello world").unwrap();
539    }
540
541    #[test]
542    #[should_panic(
543        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
544    )]
545    fn test_account_shared_data_deserialize() {
546        let key = Pubkey::new_unique();
547        let (_account1, account2) = make_two_accounts(&key);
548        account2.deserialize_data::<String>().unwrap();
549    }
550
551    #[test]
552    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
553    fn test_account_shared_data_serialize() {
554        let key = Pubkey::new_unique();
555        let (_account1, mut account2) = make_two_accounts(&key);
556        account2.serialize_data(&"hello world").unwrap();
557    }
558
559    #[test]
560    fn test_account_shared_data() {
561        let key = Pubkey::new_unique();
562        let (account1, account2) = make_two_accounts(&key);
563        assert!(accounts_equal(&account1, &account2));
564        let account = account1;
565        assert_eq!(account.lamports, 1);
566        assert_eq!(account.lamports(), 1);
567        assert_eq!(account.data.len(), 2);
568        assert_eq!(account.data().len(), 2);
569        assert_eq!(account.owner, key);
570        assert_eq!(account.owner(), &key);
571        assert!(account.executable);
572        assert!(account.executable());
573        assert_eq!(account.rent_epoch, 4);
574        assert_eq!(account.rent_epoch(), 4);
575        let account = account2;
576        assert_eq!(account.lamports, 1);
577        assert_eq!(account.lamports(), 1);
578        assert_eq!(account.data.len(), 2);
579        assert_eq!(account.data().len(), 2);
580        assert_eq!(account.owner, key);
581        assert_eq!(account.owner(), &key);
582        assert!(account.executable);
583        assert!(account.executable());
584        assert_eq!(account.rent_epoch, 4);
585        assert_eq!(account.rent_epoch(), 4);
586    }
587
588    // test clone and from for both types against expected
589    fn test_equal(
590        should_be_equal: bool,
591        account1: &Account,
592        account2: &AccountSharedData,
593        account_expected: &Account,
594    ) {
595        assert_eq!(should_be_equal, accounts_equal(account1, account2));
596        if should_be_equal {
597            assert!(accounts_equal(account_expected, account2));
598        }
599        assert_eq!(
600            accounts_equal(account_expected, account1),
601            accounts_equal(account_expected, &account1.clone())
602        );
603        assert_eq!(
604            accounts_equal(account_expected, account2),
605            accounts_equal(account_expected, &account2.clone())
606        );
607        assert_eq!(
608            accounts_equal(account_expected, account1),
609            accounts_equal(account_expected, &AccountSharedData::from(account1.clone()))
610        );
611        assert_eq!(
612            accounts_equal(account_expected, account2),
613            accounts_equal(account_expected, &Account::from(account2.clone()))
614        );
615    }
616
617    #[test]
618    fn test_account_add_sub_lamports() {
619        let key = Pubkey::new_unique();
620        let (mut account1, mut account2) = make_two_accounts(&key);
621        assert!(accounts_equal(&account1, &account2));
622        account1.checked_add_lamports(1).unwrap();
623        account2.checked_add_lamports(1).unwrap();
624        assert!(accounts_equal(&account1, &account2));
625        assert_eq!(account1.lamports(), 2);
626        account1.checked_sub_lamports(2).unwrap();
627        account2.checked_sub_lamports(2).unwrap();
628        assert!(accounts_equal(&account1, &account2));
629        assert_eq!(account1.lamports(), 0);
630    }
631
632    #[test]
633    #[should_panic(expected = "Overflow")]
634    fn test_account_checked_add_lamports_overflow() {
635        let key = Pubkey::new_unique();
636        let (mut account1, _account2) = make_two_accounts(&key);
637        account1.checked_add_lamports(u64::MAX).unwrap();
638    }
639
640    #[test]
641    #[should_panic(expected = "Underflow")]
642    fn test_account_checked_sub_lamports_underflow() {
643        let key = Pubkey::new_unique();
644        let (mut account1, _account2) = make_two_accounts(&key);
645        account1.checked_sub_lamports(u64::MAX).unwrap();
646    }
647
648    #[test]
649    #[should_panic(expected = "Overflow")]
650    fn test_account_checked_add_lamports_overflow2() {
651        let key = Pubkey::new_unique();
652        let (_account1, mut account2) = make_two_accounts(&key);
653        account2.checked_add_lamports(u64::MAX).unwrap();
654    }
655
656    #[test]
657    #[should_panic(expected = "Underflow")]
658    fn test_account_checked_sub_lamports_underflow2() {
659        let key = Pubkey::new_unique();
660        let (_account1, mut account2) = make_two_accounts(&key);
661        account2.checked_sub_lamports(u64::MAX).unwrap();
662    }
663
664    #[test]
665    fn test_account_saturating_add_lamports() {
666        let key = Pubkey::new_unique();
667        let (mut account, _) = make_two_accounts(&key);
668
669        let remaining = 22;
670        account.set_lamports(u64::MAX - remaining);
671        account.saturating_add_lamports(remaining * 2);
672        assert_eq!(account.lamports(), u64::MAX);
673    }
674
675    #[test]
676    fn test_account_saturating_sub_lamports() {
677        let key = Pubkey::new_unique();
678        let (mut account, _) = make_two_accounts(&key);
679
680        let remaining = 33;
681        account.set_lamports(remaining);
682        account.saturating_sub_lamports(remaining * 2);
683        assert_eq!(account.lamports(), 0);
684    }
685
686    #[test]
687    fn test_account_shared_data_all_fields() {
688        let key = Pubkey::new_unique();
689        let key2 = Pubkey::new_unique();
690        let key3 = Pubkey::new_unique();
691        let (mut account1, mut account2) = make_two_accounts(&key);
692        assert!(accounts_equal(&account1, &account2));
693
694        let mut account_expected = account1.clone();
695        assert!(accounts_equal(&account1, &account_expected));
696        assert!(accounts_equal(&account1, &account2.clone())); // test the clone here
697
698        for field_index in 0..5 {
699            for pass in 0..4 {
700                if field_index == 0 {
701                    if pass == 0 {
702                        account1.checked_add_lamports(1).unwrap();
703                    } else if pass == 1 {
704                        account_expected.checked_add_lamports(1).unwrap();
705                        account2.set_lamports(account2.lamports + 1);
706                    } else if pass == 2 {
707                        account1.set_lamports(account1.lamports + 1);
708                    } else if pass == 3 {
709                        account_expected.checked_add_lamports(1).unwrap();
710                        account2.checked_add_lamports(1).unwrap();
711                    }
712                } else if field_index == 1 {
713                    if pass == 0 {
714                        account1.data[0] += 1;
715                    } else if pass == 1 {
716                        account_expected.data[0] += 1;
717                        account2.data_as_mut_slice()[0] = account2.data[0] + 1;
718                    } else if pass == 2 {
719                        account1.data_as_mut_slice()[0] = account1.data[0] + 1;
720                    } else if pass == 3 {
721                        account_expected.data[0] += 1;
722                        account2.data_as_mut_slice()[0] += 1;
723                    }
724                } else if field_index == 2 {
725                    if pass == 0 {
726                        account1.owner = key2;
727                    } else if pass == 1 {
728                        account_expected.owner = key2;
729                        account2.set_owner(key2);
730                    } else if pass == 2 {
731                        account1.set_owner(key3);
732                    } else if pass == 3 {
733                        account_expected.owner = key3;
734                        account2.owner = key3;
735                    }
736                } else if field_index == 3 {
737                    if pass == 0 {
738                        account1.executable = !account1.executable;
739                    } else if pass == 1 {
740                        account_expected.executable = !account_expected.executable;
741                        account2.set_executable(!account2.executable);
742                    } else if pass == 2 {
743                        account1.set_executable(!account1.executable);
744                    } else if pass == 3 {
745                        account_expected.executable = !account_expected.executable;
746                        account2.executable = !account2.executable;
747                    }
748                } else if field_index == 4 {
749                    if pass == 0 {
750                        account1.rent_epoch += 1;
751                    } else if pass == 1 {
752                        account_expected.rent_epoch += 1;
753                        account2.set_rent_epoch(account2.rent_epoch + 1);
754                    } else if pass == 2 {
755                        account1.set_rent_epoch(account1.rent_epoch + 1);
756                    } else if pass == 3 {
757                        account_expected.rent_epoch += 1;
758                        account2.rent_epoch += 1;
759                    }
760                }
761
762                let should_be_equal = pass == 1 || pass == 3;
763                test_equal(should_be_equal, &account1, &account2, &account_expected);
764
765                // test new_ref
766                if should_be_equal {
767                    assert!(accounts_equal(
768                        &Account::new_ref(
769                            account_expected.lamports(),
770                            account_expected.data().len(),
771                            account_expected.owner()
772                        )
773                        .borrow(),
774                        &AccountSharedData::new_ref(
775                            account_expected.lamports(),
776                            account_expected.data().len(),
777                            account_expected.owner()
778                        )
779                        .borrow()
780                    ));
781
782                    {
783                        // test new_data
784                        let account1_with_data = Account::new_data(
785                            account_expected.lamports(),
786                            &account_expected.data()[0],
787                            account_expected.owner(),
788                        )
789                        .unwrap();
790                        let account2_with_data = AccountSharedData::new_data(
791                            account_expected.lamports(),
792                            &account_expected.data()[0],
793                            account_expected.owner(),
794                        )
795                        .unwrap();
796
797                        assert!(accounts_equal(&account1_with_data, &account2_with_data));
798                        assert_eq!(
799                            account1_with_data.deserialize_data::<u8>().unwrap(),
800                            account2_with_data.deserialize_data::<u8>().unwrap()
801                        );
802                    }
803
804                    // test new_data_with_space
805                    assert!(accounts_equal(
806                        &Account::new_data_with_space(
807                            account_expected.lamports(),
808                            &account_expected.data()[0],
809                            1,
810                            account_expected.owner()
811                        )
812                        .unwrap(),
813                        &AccountSharedData::new_data_with_space(
814                            account_expected.lamports(),
815                            &account_expected.data()[0],
816                            1,
817                            account_expected.owner()
818                        )
819                        .unwrap()
820                    ));
821
822                    // test new_ref_data
823                    assert!(accounts_equal(
824                        &Account::new_ref_data(
825                            account_expected.lamports(),
826                            &account_expected.data()[0],
827                            account_expected.owner()
828                        )
829                        .unwrap()
830                        .borrow(),
831                        &AccountSharedData::new_ref_data(
832                            account_expected.lamports(),
833                            &account_expected.data()[0],
834                            account_expected.owner()
835                        )
836                        .unwrap()
837                        .borrow()
838                    ));
839
840                    //new_ref_data_with_space
841                    assert!(accounts_equal(
842                        &Account::new_ref_data_with_space(
843                            account_expected.lamports(),
844                            &account_expected.data()[0],
845                            1,
846                            account_expected.owner()
847                        )
848                        .unwrap()
849                        .borrow(),
850                        &AccountSharedData::new_ref_data_with_space(
851                            account_expected.lamports(),
852                            &account_expected.data()[0],
853                            1,
854                            account_expected.owner()
855                        )
856                        .unwrap()
857                        .borrow()
858                    ));
859                }
860            }
861        }
862    }
863}