gemachain_sdk/
account.rs

1use crate::{
2    clock::{Epoch, INITIAL_RENT_EPOCH},
3    carats::CaratsError,
4    pubkey::Pubkey,
5};
6use gemachain_program::{account_info::AccountInfo, sysvar::Sysvar};
7use std::{cell::Ref, cell::RefCell, cmp, fmt, rc::Rc, sync::Arc};
8
9/// An Account with data that is stored on chain
10#[repr(C)]
11#[frozen_abi(digest = "HawRVHh7t4d3H3bitWHFt25WhhoDmbJMCfWdESQQoYEy")]
12#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Default, AbiExample)]
13#[serde(rename_all = "camelCase")]
14pub struct Account {
15    /// carats in the account
16    pub carats: u64,
17    /// data held in this account
18    #[serde(with = "serde_bytes")]
19    pub data: Vec<u8>,
20    /// the program that owns this account. If executable, the program that loads this account.
21    pub owner: Pubkey,
22    /// this account's data contains a loaded program (and is now read-only)
23    pub executable: bool,
24    /// the epoch at which this account will next owe rent
25    pub rent_epoch: Epoch,
26}
27
28/// An Account with data that is stored on chain
29/// This will be the in-memory representation of the 'Account' struct data.
30/// The existing 'Account' structure cannot easily change due to downstream projects.
31#[derive(PartialEq, Eq, Clone, Default, AbiExample)]
32pub struct AccountSharedData {
33    /// carats in the account
34    carats: u64,
35    /// data held in this account
36    data: Arc<Vec<u8>>,
37    /// the program that owns this account. If executable, the program that loads this account.
38    owner: Pubkey,
39    /// this account's data contains a loaded program (and is now read-only)
40    executable: bool,
41    /// the epoch at which this account will next owe rent
42    rent_epoch: Epoch,
43}
44
45/// Compares two ReadableAccounts
46///
47/// Returns true if accounts are essentially equivalent as in all fields are equivalent.
48pub fn accounts_equal<T: ReadableAccount, U: ReadableAccount>(me: &T, other: &U) -> bool {
49    me.carats() == other.carats()
50        && me.data() == other.data()
51        && me.owner() == other.owner()
52        && me.executable() == other.executable()
53        && me.rent_epoch() == other.rent_epoch()
54}
55
56impl From<AccountSharedData> for Account {
57    fn from(mut other: AccountSharedData) -> Self {
58        let account_data = Arc::make_mut(&mut other.data);
59        Self {
60            carats: other.carats,
61            data: std::mem::take(account_data),
62            owner: other.owner,
63            executable: other.executable,
64            rent_epoch: other.rent_epoch,
65        }
66    }
67}
68
69impl From<Account> for AccountSharedData {
70    fn from(other: Account) -> Self {
71        Self {
72            carats: other.carats,
73            data: Arc::new(other.data),
74            owner: other.owner,
75            executable: other.executable,
76            rent_epoch: other.rent_epoch,
77        }
78    }
79}
80
81pub trait WritableAccount: ReadableAccount {
82    fn set_carats(&mut self, carats: u64);
83    fn checked_add_carats(&mut self, carats: u64) -> Result<(), CaratsError> {
84        self.set_carats(
85            self.carats()
86                .checked_add(carats)
87                .ok_or(CaratsError::ArithmeticOverflow)?,
88        );
89        Ok(())
90    }
91    fn checked_sub_carats(&mut self, carats: u64) -> Result<(), CaratsError> {
92        self.set_carats(
93            self.carats()
94                .checked_sub(carats)
95                .ok_or(CaratsError::ArithmeticUnderflow)?,
96        );
97        Ok(())
98    }
99    fn data_as_mut_slice(&mut self) -> &mut [u8];
100    fn set_owner(&mut self, owner: Pubkey);
101    fn copy_into_owner_from_slice(&mut self, source: &[u8]);
102    fn set_executable(&mut self, executable: bool);
103    fn set_rent_epoch(&mut self, epoch: Epoch);
104    fn create(
105        carats: u64,
106        data: Vec<u8>,
107        owner: Pubkey,
108        executable: bool,
109        rent_epoch: Epoch,
110    ) -> Self;
111}
112
113pub trait ReadableAccount: Sized {
114    fn carats(&self) -> u64;
115    fn data(&self) -> &[u8];
116    fn owner(&self) -> &Pubkey;
117    fn executable(&self) -> bool;
118    fn rent_epoch(&self) -> Epoch;
119    fn to_account_shared_data(&self) -> AccountSharedData {
120        AccountSharedData::create(
121            self.carats(),
122            self.data().to_vec(),
123            *self.owner(),
124            self.executable(),
125            self.rent_epoch(),
126        )
127    }
128}
129
130impl ReadableAccount for Account {
131    fn carats(&self) -> u64 {
132        self.carats
133    }
134    fn data(&self) -> &[u8] {
135        &self.data
136    }
137    fn owner(&self) -> &Pubkey {
138        &self.owner
139    }
140    fn executable(&self) -> bool {
141        self.executable
142    }
143    fn rent_epoch(&self) -> Epoch {
144        self.rent_epoch
145    }
146}
147
148impl WritableAccount for Account {
149    fn set_carats(&mut self, carats: u64) {
150        self.carats = carats;
151    }
152    fn data_as_mut_slice(&mut self) -> &mut [u8] {
153        &mut self.data
154    }
155    fn set_owner(&mut self, owner: Pubkey) {
156        self.owner = owner;
157    }
158    fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
159        self.owner.as_mut().copy_from_slice(source);
160    }
161    fn set_executable(&mut self, executable: bool) {
162        self.executable = executable;
163    }
164    fn set_rent_epoch(&mut self, epoch: Epoch) {
165        self.rent_epoch = epoch;
166    }
167    fn create(
168        carats: u64,
169        data: Vec<u8>,
170        owner: Pubkey,
171        executable: bool,
172        rent_epoch: Epoch,
173    ) -> Self {
174        Account {
175            carats,
176            data,
177            owner,
178            executable,
179            rent_epoch,
180        }
181    }
182}
183
184impl WritableAccount for AccountSharedData {
185    fn set_carats(&mut self, carats: u64) {
186        self.carats = carats;
187    }
188    fn data_as_mut_slice(&mut self) -> &mut [u8] {
189        let data = Arc::make_mut(&mut self.data);
190        &mut data[..]
191    }
192    fn set_owner(&mut self, owner: Pubkey) {
193        self.owner = owner;
194    }
195    fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
196        self.owner.as_mut().copy_from_slice(source);
197    }
198    fn set_executable(&mut self, executable: bool) {
199        self.executable = executable;
200    }
201    fn set_rent_epoch(&mut self, epoch: Epoch) {
202        self.rent_epoch = epoch;
203    }
204    fn create(
205        carats: u64,
206        data: Vec<u8>,
207        owner: Pubkey,
208        executable: bool,
209        rent_epoch: Epoch,
210    ) -> Self {
211        AccountSharedData {
212            carats,
213            data: Arc::new(data),
214            owner,
215            executable,
216            rent_epoch,
217        }
218    }
219}
220
221impl ReadableAccount for AccountSharedData {
222    fn carats(&self) -> u64 {
223        self.carats
224    }
225    fn data(&self) -> &[u8] {
226        &self.data
227    }
228    fn owner(&self) -> &Pubkey {
229        &self.owner
230    }
231    fn executable(&self) -> bool {
232        self.executable
233    }
234    fn rent_epoch(&self) -> Epoch {
235        self.rent_epoch
236    }
237}
238
239impl ReadableAccount for Ref<'_, AccountSharedData> {
240    fn carats(&self) -> u64 {
241        self.carats
242    }
243    fn data(&self) -> &[u8] {
244        &self.data
245    }
246    fn owner(&self) -> &Pubkey {
247        &self.owner
248    }
249    fn executable(&self) -> bool {
250        self.executable
251    }
252    fn rent_epoch(&self) -> Epoch {
253        self.rent_epoch
254    }
255}
256
257impl ReadableAccount for Ref<'_, Account> {
258    fn carats(&self) -> u64 {
259        self.carats
260    }
261    fn data(&self) -> &[u8] {
262        &self.data
263    }
264    fn owner(&self) -> &Pubkey {
265        &self.owner
266    }
267    fn executable(&self) -> bool {
268        self.executable
269    }
270    fn rent_epoch(&self) -> Epoch {
271        self.rent_epoch
272    }
273}
274
275fn debug_fmt<T: ReadableAccount>(item: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276    let data_len = cmp::min(64, item.data().len());
277    let data_str = if data_len > 0 {
278        format!(" data: {}", hex::encode(item.data()[..data_len].to_vec()))
279    } else {
280        "".to_string()
281    };
282    write!(
283        f,
284        "Account {{ carats: {} data.len: {} owner: {} executable: {} rent_epoch: {}{} }}",
285        item.carats(),
286        item.data().len(),
287        item.owner(),
288        item.executable(),
289        item.rent_epoch(),
290        data_str,
291    )
292}
293
294impl fmt::Debug for Account {
295    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296        debug_fmt(self, f)
297    }
298}
299
300impl fmt::Debug for AccountSharedData {
301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302        debug_fmt(self, f)
303    }
304}
305
306fn shared_new<T: WritableAccount>(carats: u64, space: usize, owner: &Pubkey) -> T {
307    T::create(
308        carats,
309        vec![0u8; space],
310        *owner,
311        bool::default(),
312        Epoch::default(),
313    )
314}
315
316fn shared_new_ref<T: WritableAccount>(
317    carats: u64,
318    space: usize,
319    owner: &Pubkey,
320) -> Rc<RefCell<T>> {
321    Rc::new(RefCell::new(shared_new::<T>(carats, space, owner)))
322}
323
324fn shared_new_data<T: serde::Serialize, U: WritableAccount>(
325    carats: u64,
326    state: &T,
327    owner: &Pubkey,
328) -> Result<U, bincode::Error> {
329    let data = bincode::serialize(state)?;
330    Ok(U::create(
331        carats,
332        data,
333        *owner,
334        bool::default(),
335        Epoch::default(),
336    ))
337}
338fn shared_new_ref_data<T: serde::Serialize, U: WritableAccount>(
339    carats: u64,
340    state: &T,
341    owner: &Pubkey,
342) -> Result<RefCell<U>, bincode::Error> {
343    Ok(RefCell::new(shared_new_data::<T, U>(
344        carats, state, owner,
345    )?))
346}
347
348fn shared_new_data_with_space<T: serde::Serialize, U: WritableAccount>(
349    carats: u64,
350    state: &T,
351    space: usize,
352    owner: &Pubkey,
353) -> Result<U, bincode::Error> {
354    let mut account = shared_new::<U>(carats, space, owner);
355
356    shared_serialize_data(&mut account, state)?;
357
358    Ok(account)
359}
360fn shared_new_ref_data_with_space<T: serde::Serialize, U: WritableAccount>(
361    carats: u64,
362    state: &T,
363    space: usize,
364    owner: &Pubkey,
365) -> Result<RefCell<U>, bincode::Error> {
366    Ok(RefCell::new(shared_new_data_with_space::<T, U>(
367        carats, state, space, owner,
368    )?))
369}
370
371fn shared_deserialize_data<T: serde::de::DeserializeOwned, U: ReadableAccount>(
372    account: &U,
373) -> Result<T, bincode::Error> {
374    bincode::deserialize(account.data())
375}
376
377fn shared_serialize_data<T: serde::Serialize, U: WritableAccount>(
378    account: &mut U,
379    state: &T,
380) -> Result<(), bincode::Error> {
381    if bincode::serialized_size(state)? > account.data().len() as u64 {
382        return Err(Box::new(bincode::ErrorKind::SizeLimit));
383    }
384    bincode::serialize_into(&mut account.data_as_mut_slice(), state)
385}
386
387impl Account {
388    pub fn new(carats: u64, space: usize, owner: &Pubkey) -> Self {
389        shared_new(carats, space, owner)
390    }
391    pub fn new_ref(carats: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
392        shared_new_ref(carats, space, owner)
393    }
394    pub fn new_data<T: serde::Serialize>(
395        carats: u64,
396        state: &T,
397        owner: &Pubkey,
398    ) -> Result<Self, bincode::Error> {
399        shared_new_data(carats, state, owner)
400    }
401    pub fn new_ref_data<T: serde::Serialize>(
402        carats: u64,
403        state: &T,
404        owner: &Pubkey,
405    ) -> Result<RefCell<Self>, bincode::Error> {
406        shared_new_ref_data(carats, state, owner)
407    }
408    pub fn new_data_with_space<T: serde::Serialize>(
409        carats: u64,
410        state: &T,
411        space: usize,
412        owner: &Pubkey,
413    ) -> Result<Self, bincode::Error> {
414        shared_new_data_with_space(carats, state, space, owner)
415    }
416    pub fn new_ref_data_with_space<T: serde::Serialize>(
417        carats: u64,
418        state: &T,
419        space: usize,
420        owner: &Pubkey,
421    ) -> Result<RefCell<Self>, bincode::Error> {
422        shared_new_ref_data_with_space(carats, state, space, owner)
423    }
424    pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
425        shared_deserialize_data(self)
426    }
427    pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
428        shared_serialize_data(self, state)
429    }
430}
431
432impl AccountSharedData {
433    pub fn set_data_from_slice(&mut self, data: &[u8]) {
434        let len = self.data.len();
435        let len_different = len != data.len();
436        let different = len_different || data != &self.data[..];
437        if different {
438            self.data = Arc::new(data.to_vec());
439        }
440    }
441    pub fn set_data(&mut self, data: Vec<u8>) {
442        self.data = Arc::new(data);
443    }
444    pub fn new(carats: u64, space: usize, owner: &Pubkey) -> Self {
445        shared_new(carats, space, owner)
446    }
447    pub fn new_ref(carats: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
448        shared_new_ref(carats, space, owner)
449    }
450    pub fn new_data<T: serde::Serialize>(
451        carats: u64,
452        state: &T,
453        owner: &Pubkey,
454    ) -> Result<Self, bincode::Error> {
455        shared_new_data(carats, state, owner)
456    }
457    pub fn new_ref_data<T: serde::Serialize>(
458        carats: u64,
459        state: &T,
460        owner: &Pubkey,
461    ) -> Result<RefCell<Self>, bincode::Error> {
462        shared_new_ref_data(carats, state, owner)
463    }
464    pub fn new_data_with_space<T: serde::Serialize>(
465        carats: u64,
466        state: &T,
467        space: usize,
468        owner: &Pubkey,
469    ) -> Result<Self, bincode::Error> {
470        shared_new_data_with_space(carats, state, space, owner)
471    }
472    pub fn new_ref_data_with_space<T: serde::Serialize>(
473        carats: u64,
474        state: &T,
475        space: usize,
476        owner: &Pubkey,
477    ) -> Result<RefCell<Self>, bincode::Error> {
478        shared_new_ref_data_with_space(carats, state, space, owner)
479    }
480    pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
481        shared_deserialize_data(self)
482    }
483    pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
484        shared_serialize_data(self, state)
485    }
486}
487
488pub type InheritableAccountFields = (u64, Epoch);
489pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH);
490
491/// Create an `Account` from a `Sysvar`.
492#[deprecated(
493    since = "1.5.17",
494    note = "Please use `create_account_for_test` instead"
495)]
496pub fn create_account<S: Sysvar>(sysvar: &S, carats: u64) -> Account {
497    create_account_with_fields(sysvar, (carats, INITIAL_RENT_EPOCH))
498}
499
500pub fn create_account_with_fields<S: Sysvar>(
501    sysvar: &S,
502    (carats, rent_epoch): InheritableAccountFields,
503) -> Account {
504    let data_len = S::size_of().max(bincode::serialized_size(sysvar).unwrap() as usize);
505    let mut account = Account::new(carats, data_len, &gemachain_program::sysvar::id());
506    to_account::<S, Account>(sysvar, &mut account).unwrap();
507    account.rent_epoch = rent_epoch;
508    account
509}
510
511pub fn create_account_for_test<S: Sysvar>(sysvar: &S) -> Account {
512    create_account_with_fields(sysvar, DUMMY_INHERITABLE_ACCOUNT_FIELDS)
513}
514
515/// Create an `Account` from a `Sysvar`.
516#[deprecated(
517    since = "1.5.17",
518    note = "Please use `create_account_shared_data_for_test` instead"
519)]
520pub fn create_account_shared_data<S: Sysvar>(sysvar: &S, carats: u64) -> AccountSharedData {
521    AccountSharedData::from(create_account_with_fields(
522        sysvar,
523        (carats, INITIAL_RENT_EPOCH),
524    ))
525}
526
527pub fn create_account_shared_data_with_fields<S: Sysvar>(
528    sysvar: &S,
529    fields: InheritableAccountFields,
530) -> AccountSharedData {
531    AccountSharedData::from(create_account_with_fields(sysvar, fields))
532}
533
534pub fn create_account_shared_data_for_test<S: Sysvar>(sysvar: &S) -> AccountSharedData {
535    AccountSharedData::from(create_account_with_fields(
536        sysvar,
537        DUMMY_INHERITABLE_ACCOUNT_FIELDS,
538    ))
539}
540
541/// Create a `Sysvar` from an `Account`'s data.
542pub fn from_account<S: Sysvar, T: ReadableAccount>(account: &T) -> Option<S> {
543    bincode::deserialize(account.data()).ok()
544}
545
546/// Serialize a `Sysvar` into an `Account`'s data.
547pub fn to_account<S: Sysvar, T: WritableAccount>(sysvar: &S, account: &mut T) -> Option<()> {
548    bincode::serialize_into(account.data_as_mut_slice(), sysvar).ok()
549}
550
551/// Return the information required to construct an `AccountInfo`.  Used by the
552/// `AccountInfo` conversion implementations.
553impl gemachain_program::account_info::Account for Account {
554    fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool, Epoch) {
555        (
556            &mut self.carats,
557            &mut self.data,
558            &self.owner,
559            self.executable,
560            self.rent_epoch,
561        )
562    }
563}
564
565/// Create `AccountInfo`s
566pub fn create_is_signer_account_infos<'a>(
567    accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
568) -> Vec<AccountInfo<'a>> {
569    accounts
570        .iter_mut()
571        .map(|(key, is_signer, account)| {
572            AccountInfo::new(
573                key,
574                *is_signer,
575                false,
576                &mut account.carats,
577                &mut account.data,
578                &account.owner,
579                account.executable,
580                account.rent_epoch,
581            )
582        })
583        .collect()
584}
585
586#[cfg(test)]
587pub mod tests {
588    use super::*;
589
590    fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) {
591        let mut account1 = Account::new(1, 2, key);
592        account1.executable = true;
593        account1.rent_epoch = 4;
594        let mut account2 = AccountSharedData::new(1, 2, key);
595        account2.executable = true;
596        account2.rent_epoch = 4;
597        assert!(accounts_equal(&account1, &account2));
598        (account1, account2)
599    }
600
601    #[test]
602    fn test_account_data_copy_as_slice() {
603        let key = Pubkey::new_unique();
604        let key2 = Pubkey::new_unique();
605        let (mut account1, mut account2) = make_two_accounts(&key);
606        account1.copy_into_owner_from_slice(key2.as_ref());
607        account2.copy_into_owner_from_slice(key2.as_ref());
608        assert!(accounts_equal(&account1, &account2));
609        assert_eq!(account1.owner(), &key2);
610    }
611
612    #[test]
613    fn test_account_set_data_from_slice() {
614        let key = Pubkey::new_unique();
615        let (_, mut account) = make_two_accounts(&key);
616        assert_eq!(account.data(), &vec![0, 0]);
617        account.set_data_from_slice(&[1, 2]);
618        assert_eq!(account.data(), &vec![1, 2]);
619        account.set_data_from_slice(&[1, 2, 3]);
620        assert_eq!(account.data(), &vec![1, 2, 3]);
621        account.set_data_from_slice(&[4, 5, 6]);
622        assert_eq!(account.data(), &vec![4, 5, 6]);
623        account.set_data_from_slice(&[4, 5, 6, 0]);
624        assert_eq!(account.data(), &vec![4, 5, 6, 0]);
625        account.set_data_from_slice(&[]);
626        assert_eq!(account.data().len(), 0);
627        account.set_data_from_slice(&[44]);
628        assert_eq!(account.data(), &vec![44]);
629        account.set_data_from_slice(&[44]);
630        assert_eq!(account.data(), &vec![44]);
631    }
632
633    #[test]
634    fn test_account_data_set_data() {
635        let key = Pubkey::new_unique();
636        let (_, mut account) = make_two_accounts(&key);
637        assert_eq!(account.data(), &vec![0, 0]);
638        account.set_data(vec![1, 2]);
639        assert_eq!(account.data(), &vec![1, 2]);
640        account.set_data(vec![]);
641        assert_eq!(account.data().len(), 0);
642    }
643
644    #[test]
645    #[should_panic(
646        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
647    )]
648    fn test_account_deserialize() {
649        let key = Pubkey::new_unique();
650        let (account1, _account2) = make_two_accounts(&key);
651        account1.deserialize_data::<String>().unwrap();
652    }
653
654    #[test]
655    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
656    fn test_account_serialize() {
657        let key = Pubkey::new_unique();
658        let (mut account1, _account2) = make_two_accounts(&key);
659        account1.serialize_data(&"hello world").unwrap();
660    }
661
662    #[test]
663    #[should_panic(
664        expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
665    )]
666    fn test_account_shared_data_deserialize() {
667        let key = Pubkey::new_unique();
668        let (_account1, account2) = make_two_accounts(&key);
669        account2.deserialize_data::<String>().unwrap();
670    }
671
672    #[test]
673    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
674    fn test_account_shared_data_serialize() {
675        let key = Pubkey::new_unique();
676        let (_account1, mut account2) = make_two_accounts(&key);
677        account2.serialize_data(&"hello world").unwrap();
678    }
679
680    #[test]
681    fn test_to_account_shared_data() {
682        let key = Pubkey::new_unique();
683        let (account1, account2) = make_two_accounts(&key);
684        assert!(accounts_equal(&account1, &account2));
685        let account3 = account1.to_account_shared_data();
686        let account4 = account2.to_account_shared_data();
687        assert!(accounts_equal(&account1, &account3));
688        assert!(accounts_equal(&account1, &account4));
689    }
690
691    #[test]
692    fn test_account_shared_data() {
693        let key = Pubkey::new_unique();
694        let (account1, account2) = make_two_accounts(&key);
695        assert!(accounts_equal(&account1, &account2));
696        let account = account1;
697        assert_eq!(account.carats, 1);
698        assert_eq!(account.carats(), 1);
699        assert_eq!(account.data.len(), 2);
700        assert_eq!(account.data().len(), 2);
701        assert_eq!(account.owner, key);
702        assert_eq!(account.owner(), &key);
703        assert!(account.executable);
704        assert!(account.executable());
705        assert_eq!(account.rent_epoch, 4);
706        assert_eq!(account.rent_epoch(), 4);
707        let account = account2;
708        assert_eq!(account.carats, 1);
709        assert_eq!(account.carats(), 1);
710        assert_eq!(account.data.len(), 2);
711        assert_eq!(account.data().len(), 2);
712        assert_eq!(account.owner, key);
713        assert_eq!(account.owner(), &key);
714        assert!(account.executable);
715        assert!(account.executable());
716        assert_eq!(account.rent_epoch, 4);
717        assert_eq!(account.rent_epoch(), 4);
718    }
719
720    // test clone and from for both types against expected
721    fn test_equal(
722        should_be_equal: bool,
723        account1: &Account,
724        account2: &AccountSharedData,
725        account_expected: &Account,
726    ) {
727        assert_eq!(should_be_equal, accounts_equal(account1, account2));
728        if should_be_equal {
729            assert!(accounts_equal(account_expected, account2));
730        }
731        assert_eq!(
732            accounts_equal(account_expected, account1),
733            accounts_equal(account_expected, &account1.clone())
734        );
735        assert_eq!(
736            accounts_equal(account_expected, account2),
737            accounts_equal(account_expected, &account2.clone())
738        );
739        assert_eq!(
740            accounts_equal(account_expected, account1),
741            accounts_equal(account_expected, &AccountSharedData::from(account1.clone()))
742        );
743        assert_eq!(
744            accounts_equal(account_expected, account2),
745            accounts_equal(account_expected, &Account::from(account2.clone()))
746        );
747    }
748
749    #[test]
750    fn test_account_add_sub_carats() {
751        let key = Pubkey::new_unique();
752        let (mut account1, mut account2) = make_two_accounts(&key);
753        assert!(accounts_equal(&account1, &account2));
754        account1.checked_add_carats(1).unwrap();
755        account2.checked_add_carats(1).unwrap();
756        assert!(accounts_equal(&account1, &account2));
757        assert_eq!(account1.carats(), 2);
758        account1.checked_sub_carats(2).unwrap();
759        account2.checked_sub_carats(2).unwrap();
760        assert!(accounts_equal(&account1, &account2));
761        assert_eq!(account1.carats(), 0);
762    }
763
764    #[test]
765    #[should_panic(expected = "Overflow")]
766    fn test_account_checked_add_carats_overflow() {
767        let key = Pubkey::new_unique();
768        let (mut account1, _account2) = make_two_accounts(&key);
769        account1.checked_add_carats(u64::MAX).unwrap();
770    }
771
772    #[test]
773    #[should_panic(expected = "Underflow")]
774    fn test_account_checked_sub_carats_underflow() {
775        let key = Pubkey::new_unique();
776        let (mut account1, _account2) = make_two_accounts(&key);
777        account1.checked_sub_carats(u64::MAX).unwrap();
778    }
779
780    #[test]
781    #[should_panic(expected = "Overflow")]
782    fn test_account_checked_add_carats_overflow2() {
783        let key = Pubkey::new_unique();
784        let (_account1, mut account2) = make_two_accounts(&key);
785        account2.checked_add_carats(u64::MAX).unwrap();
786    }
787
788    #[test]
789    #[should_panic(expected = "Underflow")]
790    fn test_account_checked_sub_carats_underflow2() {
791        let key = Pubkey::new_unique();
792        let (_account1, mut account2) = make_two_accounts(&key);
793        account2.checked_sub_carats(u64::MAX).unwrap();
794    }
795
796    #[test]
797    #[allow(clippy::redundant_clone)]
798    fn test_account_shared_data_all_fields() {
799        let key = Pubkey::new_unique();
800        let key2 = Pubkey::new_unique();
801        let key3 = Pubkey::new_unique();
802        let (mut account1, mut account2) = make_two_accounts(&key);
803        assert!(accounts_equal(&account1, &account2));
804
805        let mut account_expected = account1.clone();
806        assert!(accounts_equal(&account1, &account_expected));
807        assert!(accounts_equal(&account1, &account2.clone())); // test the clone here
808
809        for field_index in 0..5 {
810            for pass in 0..4 {
811                if field_index == 0 {
812                    if pass == 0 {
813                        account1.checked_add_carats(1).unwrap();
814                    } else if pass == 1 {
815                        account_expected.checked_add_carats(1).unwrap();
816                        account2.set_carats(account2.carats + 1);
817                    } else if pass == 2 {
818                        account1.set_carats(account1.carats + 1);
819                    } else if pass == 3 {
820                        account_expected.checked_add_carats(1).unwrap();
821                        account2.checked_add_carats(1).unwrap();
822                    }
823                } else if field_index == 1 {
824                    if pass == 0 {
825                        account1.data[0] += 1;
826                    } else if pass == 1 {
827                        account_expected.data[0] += 1;
828                        account2.data_as_mut_slice()[0] = account2.data[0] + 1;
829                    } else if pass == 2 {
830                        account1.data_as_mut_slice()[0] = account1.data[0] + 1;
831                    } else if pass == 3 {
832                        account_expected.data[0] += 1;
833                        account2.data_as_mut_slice()[0] += 1;
834                    }
835                } else if field_index == 2 {
836                    if pass == 0 {
837                        account1.owner = key2;
838                    } else if pass == 1 {
839                        account_expected.owner = key2;
840                        account2.set_owner(key2);
841                    } else if pass == 2 {
842                        account1.set_owner(key3);
843                    } else if pass == 3 {
844                        account_expected.owner = key3;
845                        account2.owner = key3;
846                    }
847                } else if field_index == 3 {
848                    if pass == 0 {
849                        account1.executable = !account1.executable;
850                    } else if pass == 1 {
851                        account_expected.executable = !account_expected.executable;
852                        account2.set_executable(!account2.executable);
853                    } else if pass == 2 {
854                        account1.set_executable(!account1.executable);
855                    } else if pass == 3 {
856                        account_expected.executable = !account_expected.executable;
857                        account2.executable = !account2.executable;
858                    }
859                } else if field_index == 4 {
860                    if pass == 0 {
861                        account1.rent_epoch += 1;
862                    } else if pass == 1 {
863                        account_expected.rent_epoch += 1;
864                        account2.set_rent_epoch(account2.rent_epoch + 1);
865                    } else if pass == 2 {
866                        account1.set_rent_epoch(account1.rent_epoch + 1);
867                    } else if pass == 3 {
868                        account_expected.rent_epoch += 1;
869                        account2.rent_epoch += 1;
870                    }
871                }
872
873                let should_be_equal = pass == 1 || pass == 3;
874                test_equal(should_be_equal, &account1, &account2, &account_expected);
875
876                // test new_ref
877                if should_be_equal {
878                    assert!(accounts_equal(
879                        &Account::new_ref(
880                            account_expected.carats(),
881                            account_expected.data().len(),
882                            account_expected.owner()
883                        )
884                        .borrow(),
885                        &AccountSharedData::new_ref(
886                            account_expected.carats(),
887                            account_expected.data().len(),
888                            account_expected.owner()
889                        )
890                        .borrow()
891                    ));
892
893                    {
894                        // test new_data
895                        let account1_with_data = Account::new_data(
896                            account_expected.carats(),
897                            &account_expected.data()[0],
898                            account_expected.owner(),
899                        )
900                        .unwrap();
901                        let account2_with_data = AccountSharedData::new_data(
902                            account_expected.carats(),
903                            &account_expected.data()[0],
904                            account_expected.owner(),
905                        )
906                        .unwrap();
907
908                        assert!(accounts_equal(&account1_with_data, &account2_with_data));
909                        assert_eq!(
910                            account1_with_data.deserialize_data::<u8>().unwrap(),
911                            account2_with_data.deserialize_data::<u8>().unwrap()
912                        );
913                    }
914
915                    // test new_data_with_space
916                    assert!(accounts_equal(
917                        &Account::new_data_with_space(
918                            account_expected.carats(),
919                            &account_expected.data()[0],
920                            1,
921                            account_expected.owner()
922                        )
923                        .unwrap(),
924                        &AccountSharedData::new_data_with_space(
925                            account_expected.carats(),
926                            &account_expected.data()[0],
927                            1,
928                            account_expected.owner()
929                        )
930                        .unwrap()
931                    ));
932
933                    // test new_ref_data
934                    assert!(accounts_equal(
935                        &Account::new_ref_data(
936                            account_expected.carats(),
937                            &account_expected.data()[0],
938                            account_expected.owner()
939                        )
940                        .unwrap()
941                        .borrow(),
942                        &AccountSharedData::new_ref_data(
943                            account_expected.carats(),
944                            &account_expected.data()[0],
945                            account_expected.owner()
946                        )
947                        .unwrap()
948                        .borrow()
949                    ));
950
951                    //new_ref_data_with_space
952                    assert!(accounts_equal(
953                        &Account::new_ref_data_with_space(
954                            account_expected.carats(),
955                            &account_expected.data()[0],
956                            1,
957                            account_expected.owner()
958                        )
959                        .unwrap()
960                        .borrow(),
961                        &AccountSharedData::new_ref_data_with_space(
962                            account_expected.carats(),
963                            &account_expected.data()[0],
964                            1,
965                            account_expected.owner()
966                        )
967                        .unwrap()
968                        .borrow()
969                    ));
970                }
971            }
972        }
973    }
974}