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