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    pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
360        Rc::new(RefCell::new(AccountSharedData::new(lamports, space, owner)))
361    }
362    pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
363        AccountSharedData {
364            lamports,
365            data: Arc::new(vec![0; space]),
366            owner: *owner,
367            executable: false,
368            rent_epoch,
369        }
370    }
371    pub fn create_from_existing_shared_data(
372        lamports: u64,
373        data: Arc<Vec<u8>>,
374        owner: Pubkey,
375        executable: bool,
376        rent_epoch: Epoch,
377    ) -> AccountSharedData {
378        AccountSharedData {
379            lamports,
380            data,
381            owner,
382            executable,
383            rent_epoch,
384        }
385    }
386}
387
388pub type InheritableAccountFields = (u64, Epoch);
389pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH);
390
391/// Return the information required to construct an `AccountInfo`.  Used by the
392/// `AccountInfo` conversion implementations.
393impl solana_account_info::Account for Account {
394    fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool) {
395        (
396            &mut self.lamports,
397            &mut self.data,
398            &self.owner,
399            self.executable,
400        )
401    }
402}
403
404/// Create `AccountInfo`s
405pub fn create_is_signer_account_infos<'a>(
406    accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
407) -> Vec<AccountInfo<'a>> {
408    accounts
409        .iter_mut()
410        .map(|(key, is_signer, account)| {
411            AccountInfo::new(
412                key,
413                *is_signer,
414                false,
415                &mut account.lamports,
416                &mut account.data,
417                &account.owner,
418                account.executable,
419            )
420        })
421        .collect()
422}
423
424/// Replacement for the executable flag: An account being owned by one of these contains a program.
425#[deprecated(since = "4.3.0", note = "no longer available as a constant")]
426pub const PROGRAM_OWNERS: &[Pubkey] = &[
427    bpf_loader_upgradeable::id(),
428    bpf_loader::id(),
429    bpf_loader_deprecated::id(),
430    loader_v4::id(),
431];
432
433#[cfg(test)]
434pub mod tests {
435    use super::*;
436
437    fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) {
438        let mut account1 = Account::new(1, 2, key);
439        account1.executable = true;
440        account1.rent_epoch = 4;
441        let mut account2 = AccountSharedData::new(1, 2, key);
442        account2.executable = true;
443        account2.rent_epoch = 4;
444        assert!(accounts_equal(&account1, &account2));
445        (account1, account2)
446    }
447
448    #[test]
449    fn test_account_data_copy_as_slice() {
450        let key = Pubkey::new_unique();
451        let key2 = Pubkey::new_unique();
452        let (mut account1, mut account2) = make_two_accounts(&key);
453        account1.copy_into_owner_from_slice(key2.as_ref());
454        account2.copy_into_owner_from_slice(key2.as_ref());
455        assert!(accounts_equal(&account1, &account2));
456        assert_eq!(account1.owner(), &key2);
457    }
458
459    #[test]
460    fn test_account_set_data_from_slice() {
461        let key = Pubkey::new_unique();
462        let (_, mut account) = make_two_accounts(&key);
463        assert_eq!(account.data(), &vec![0, 0]);
464        account.set_data_from_slice(&[1, 2]);
465        assert_eq!(account.data(), &vec![1, 2]);
466        account.set_data_from_slice(&[1, 2, 3]);
467        assert_eq!(account.data(), &vec![1, 2, 3]);
468        account.set_data_from_slice(&[4, 5, 6]);
469        assert_eq!(account.data(), &vec![4, 5, 6]);
470        account.set_data_from_slice(&[4, 5, 6, 0]);
471        assert_eq!(account.data(), &vec![4, 5, 6, 0]);
472        account.set_data_from_slice(&[]);
473        assert_eq!(account.data().len(), 0);
474        account.set_data_from_slice(&[44]);
475        assert_eq!(account.data(), &vec![44]);
476        account.set_data_from_slice(&[44]);
477        assert_eq!(account.data(), &vec![44]);
478    }
479
480    #[test]
481    fn test_account_data_set_data() {
482        let key = Pubkey::new_unique();
483        let (_, mut account) = make_two_accounts(&key);
484        assert_eq!(account.data(), &vec![0, 0]);
485        account.set_data(vec![1, 2]);
486        assert_eq!(account.data(), &vec![1, 2]);
487        account.set_data(vec![]);
488        assert_eq!(account.data().len(), 0);
489    }
490
491    #[test]
492    #[should_panic(
493        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
494    )]
495    fn test_account_deserialize() {
496        let key = Pubkey::new_unique();
497        let (account1, _account2) = make_two_accounts(&key);
498        account1.deserialize_data::<String>().unwrap();
499    }
500
501    #[test]
502    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
503    fn test_account_serialize() {
504        let key = Pubkey::new_unique();
505        let (mut account1, _account2) = make_two_accounts(&key);
506        account1.serialize_data(&"hello world").unwrap();
507    }
508
509    #[test]
510    #[should_panic(
511        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
512    )]
513    fn test_account_shared_data_deserialize() {
514        let key = Pubkey::new_unique();
515        let (_account1, account2) = make_two_accounts(&key);
516        account2.deserialize_data::<String>().unwrap();
517    }
518
519    #[test]
520    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
521    fn test_account_shared_data_serialize() {
522        let key = Pubkey::new_unique();
523        let (_account1, mut account2) = make_two_accounts(&key);
524        account2.serialize_data(&"hello world").unwrap();
525    }
526
527    #[test]
528    fn test_account_shared_data() {
529        let key = Pubkey::new_unique();
530        let (account1, account2) = make_two_accounts(&key);
531        assert!(accounts_equal(&account1, &account2));
532        let account = account1;
533        assert_eq!(account.lamports, 1);
534        assert_eq!(account.lamports(), 1);
535        assert_eq!(account.data.len(), 2);
536        assert_eq!(account.data().len(), 2);
537        assert_eq!(account.owner, key);
538        assert_eq!(account.owner(), &key);
539        assert!(account.executable);
540        assert!(account.executable());
541        assert_eq!(account.rent_epoch, 4);
542        assert_eq!(account.rent_epoch(), 4);
543        let account = account2;
544        assert_eq!(account.lamports, 1);
545        assert_eq!(account.lamports(), 1);
546        assert_eq!(account.data.len(), 2);
547        assert_eq!(account.data().len(), 2);
548        assert_eq!(account.owner, key);
549        assert_eq!(account.owner(), &key);
550        assert!(account.executable);
551        assert!(account.executable());
552        assert_eq!(account.rent_epoch, 4);
553        assert_eq!(account.rent_epoch(), 4);
554    }
555
556    // test clone and from for both types against expected
557    fn test_equal(
558        should_be_equal: bool,
559        account1: &Account,
560        account2: &AccountSharedData,
561        account_expected: &Account,
562    ) {
563        assert_eq!(should_be_equal, accounts_equal(account1, account2));
564        if should_be_equal {
565            assert!(accounts_equal(account_expected, account2));
566        }
567        assert_eq!(
568            accounts_equal(account_expected, account1),
569            accounts_equal(account_expected, &account1.clone())
570        );
571        assert_eq!(
572            accounts_equal(account_expected, account2),
573            accounts_equal(account_expected, &account2.clone())
574        );
575        assert_eq!(
576            accounts_equal(account_expected, account1),
577            accounts_equal(account_expected, &AccountSharedData::from(account1.clone()))
578        );
579        assert_eq!(
580            accounts_equal(account_expected, account2),
581            accounts_equal(account_expected, &Account::from(account2.clone()))
582        );
583    }
584
585    #[test]
586    fn test_account_add_sub_lamports() {
587        let key = Pubkey::new_unique();
588        let (mut account1, mut account2) = make_two_accounts(&key);
589        assert!(accounts_equal(&account1, &account2));
590        account1.checked_add_lamports(1).unwrap();
591        account2.checked_add_lamports(1).unwrap();
592        assert!(accounts_equal(&account1, &account2));
593        assert_eq!(account1.lamports(), 2);
594        account1.checked_sub_lamports(2).unwrap();
595        account2.checked_sub_lamports(2).unwrap();
596        assert!(accounts_equal(&account1, &account2));
597        assert_eq!(account1.lamports(), 0);
598    }
599
600    #[test]
601    #[should_panic(expected = "Overflow")]
602    fn test_account_checked_add_lamports_overflow() {
603        let key = Pubkey::new_unique();
604        let (mut account1, _account2) = make_two_accounts(&key);
605        account1.checked_add_lamports(u64::MAX).unwrap();
606    }
607
608    #[test]
609    #[should_panic(expected = "Underflow")]
610    fn test_account_checked_sub_lamports_underflow() {
611        let key = Pubkey::new_unique();
612        let (mut account1, _account2) = make_two_accounts(&key);
613        account1.checked_sub_lamports(u64::MAX).unwrap();
614    }
615
616    #[test]
617    #[should_panic(expected = "Overflow")]
618    fn test_account_checked_add_lamports_overflow2() {
619        let key = Pubkey::new_unique();
620        let (_account1, mut account2) = make_two_accounts(&key);
621        account2.checked_add_lamports(u64::MAX).unwrap();
622    }
623
624    #[test]
625    #[should_panic(expected = "Underflow")]
626    fn test_account_checked_sub_lamports_underflow2() {
627        let key = Pubkey::new_unique();
628        let (_account1, mut account2) = make_two_accounts(&key);
629        account2.checked_sub_lamports(u64::MAX).unwrap();
630    }
631
632    #[test]
633    fn test_account_saturating_add_lamports() {
634        let key = Pubkey::new_unique();
635        let (mut account, _) = make_two_accounts(&key);
636
637        let remaining = 22;
638        account.set_lamports(u64::MAX - remaining);
639        account.saturating_add_lamports(remaining * 2);
640        assert_eq!(account.lamports(), u64::MAX);
641    }
642
643    #[test]
644    fn test_account_saturating_sub_lamports() {
645        let key = Pubkey::new_unique();
646        let (mut account, _) = make_two_accounts(&key);
647
648        let remaining = 33;
649        account.set_lamports(remaining);
650        account.saturating_sub_lamports(remaining * 2);
651        assert_eq!(account.lamports(), 0);
652    }
653
654    #[test]
655    fn test_account_shared_data_all_fields() {
656        let key = Pubkey::new_unique();
657        let key2 = Pubkey::new_unique();
658        let key3 = Pubkey::new_unique();
659        let (mut account1, mut account2) = make_two_accounts(&key);
660        assert!(accounts_equal(&account1, &account2));
661
662        let mut account_expected = account1.clone();
663        assert!(accounts_equal(&account1, &account_expected));
664        assert!(accounts_equal(&account1, &account2.clone())); // test the clone here
665
666        for field_index in 0..5 {
667            for pass in 0..4 {
668                if field_index == 0 {
669                    if pass == 0 {
670                        account1.checked_add_lamports(1).unwrap();
671                    } else if pass == 1 {
672                        account_expected.checked_add_lamports(1).unwrap();
673                        account2.set_lamports(account2.lamports + 1);
674                    } else if pass == 2 {
675                        account1.set_lamports(account1.lamports + 1);
676                    } else if pass == 3 {
677                        account_expected.checked_add_lamports(1).unwrap();
678                        account2.checked_add_lamports(1).unwrap();
679                    }
680                } else if field_index == 1 {
681                    if pass == 0 {
682                        account1.data[0] += 1;
683                    } else if pass == 1 {
684                        account_expected.data[0] += 1;
685                        account2.data_as_mut_slice()[0] = account2.data[0] + 1;
686                    } else if pass == 2 {
687                        account1.data_as_mut_slice()[0] = account1.data[0] + 1;
688                    } else if pass == 3 {
689                        account_expected.data[0] += 1;
690                        account2.data_as_mut_slice()[0] += 1;
691                    }
692                } else if field_index == 2 {
693                    if pass == 0 {
694                        account1.owner = key2;
695                    } else if pass == 1 {
696                        account_expected.owner = key2;
697                        account2.set_owner(key2);
698                    } else if pass == 2 {
699                        account1.set_owner(key3);
700                    } else if pass == 3 {
701                        account_expected.owner = key3;
702                        account2.owner = key3;
703                    }
704                } else if field_index == 3 {
705                    if pass == 0 {
706                        account1.executable = !account1.executable;
707                    } else if pass == 1 {
708                        account_expected.executable = !account_expected.executable;
709                        account2.set_executable(!account2.executable);
710                    } else if pass == 2 {
711                        account1.set_executable(!account1.executable);
712                    } else if pass == 3 {
713                        account_expected.executable = !account_expected.executable;
714                        account2.executable = !account2.executable;
715                    }
716                } else if field_index == 4 {
717                    if pass == 0 {
718                        account1.rent_epoch += 1;
719                    } else if pass == 1 {
720                        account_expected.rent_epoch += 1;
721                        account2.set_rent_epoch(account2.rent_epoch + 1);
722                    } else if pass == 2 {
723                        account1.set_rent_epoch(account1.rent_epoch + 1);
724                    } else if pass == 3 {
725                        account_expected.rent_epoch += 1;
726                        account2.rent_epoch += 1;
727                    }
728                }
729
730                let should_be_equal = pass == 1 || pass == 3;
731                test_equal(should_be_equal, &account1, &account2, &account_expected);
732
733                // test new_ref
734                if should_be_equal {
735                    assert!(accounts_equal(
736                        &Account::new_ref(
737                            account_expected.lamports(),
738                            account_expected.data().len(),
739                            account_expected.owner()
740                        )
741                        .borrow(),
742                        &AccountSharedData::new_ref(
743                            account_expected.lamports(),
744                            account_expected.data().len(),
745                            account_expected.owner()
746                        )
747                        .borrow()
748                    ));
749
750                    {
751                        // test new_data
752                        let account1_with_data = Account::new_data(
753                            account_expected.lamports(),
754                            &account_expected.data()[0],
755                            account_expected.owner(),
756                        )
757                        .unwrap();
758                        let account2_with_data = AccountSharedData::new_data(
759                            account_expected.lamports(),
760                            &account_expected.data()[0],
761                            account_expected.owner(),
762                        )
763                        .unwrap();
764
765                        assert!(accounts_equal(&account1_with_data, &account2_with_data));
766                        assert_eq!(
767                            account1_with_data.deserialize_data::<u8>().unwrap(),
768                            account2_with_data.deserialize_data::<u8>().unwrap()
769                        );
770                    }
771
772                    // test new_data_with_space
773                    assert!(accounts_equal(
774                        &Account::new_data_with_space(
775                            account_expected.lamports(),
776                            &account_expected.data()[0],
777                            1,
778                            account_expected.owner()
779                        )
780                        .unwrap(),
781                        &AccountSharedData::new_data_with_space(
782                            account_expected.lamports(),
783                            &account_expected.data()[0],
784                            1,
785                            account_expected.owner()
786                        )
787                        .unwrap()
788                    ));
789
790                    // test new_ref_data
791                    assert!(accounts_equal(
792                        &Account::new_ref_data(
793                            account_expected.lamports(),
794                            &account_expected.data()[0],
795                            account_expected.owner()
796                        )
797                        .unwrap()
798                        .borrow(),
799                        &AccountSharedData::new_ref_data(
800                            account_expected.lamports(),
801                            &account_expected.data()[0],
802                            account_expected.owner()
803                        )
804                        .unwrap()
805                        .borrow()
806                    ));
807
808                    //new_ref_data_with_space
809                    assert!(accounts_equal(
810                        &Account::new_ref_data_with_space(
811                            account_expected.lamports(),
812                            &account_expected.data()[0],
813                            1,
814                            account_expected.owner()
815                        )
816                        .unwrap()
817                        .borrow(),
818                        &AccountSharedData::new_ref_data_with_space(
819                            account_expected.lamports(),
820                            &account_expected.data()[0],
821                            1,
822                            account_expected.owner()
823                        )
824                        .unwrap()
825                        .borrow()
826                    ));
827                }
828            }
829        }
830    }
831}