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#[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 pub carats: u64,
17 #[serde(with = "serde_bytes")]
19 pub data: Vec<u8>,
20 pub owner: Pubkey,
22 pub executable: bool,
24 pub rent_epoch: Epoch,
26}
27
28#[derive(PartialEq, Eq, Clone, Default, AbiExample)]
32pub struct AccountSharedData {
33 carats: u64,
35 data: Arc<Vec<u8>>,
37 owner: Pubkey,
39 executable: bool,
41 rent_epoch: Epoch,
43}
44
45pub 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#[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#[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
541pub fn from_account<S: Sysvar, T: ReadableAccount>(account: &T) -> Option<S> {
543 bincode::deserialize(account.data()).ok()
544}
545
546pub 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
551impl 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
565pub 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 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())); 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 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 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 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 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 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}