1use {
4 crate::{
5 clock::{Epoch, INITIAL_RENT_EPOCH},
6 scoobies::ScoobiesError,
7 pubkey::Pubkey,
8 },
9 serde::{
10 ser::{Serialize, Serializer},
11 Deserialize,
12 },
13 cbe_program::{account_info::AccountInfo, debug_account_data::*, sysvar::Sysvar},
14 std::{
15 cell::{Ref, RefCell},
16 fmt, ptr,
17 rc::Rc,
18 sync::Arc,
19 },
20};
21
22#[repr(C)]
24#[frozen_abi(digest = "HawRVHh7t4d3H3bitWHFt25WhhoDmbJMCfWdESQQoYEy")]
25#[derive(Deserialize, PartialEq, Eq, Clone, Default, AbiExample)]
26#[serde(rename_all = "camelCase")]
27pub struct Account {
28 pub scoobies: u64,
30 #[serde(with = "serde_bytes")]
32 pub data: Vec<u8>,
33 pub owner: Pubkey,
35 pub executable: bool,
37 pub rent_epoch: Epoch,
39}
40
41mod account_serialize {
43 use {
44 crate::{account::ReadableAccount, clock::Epoch, pubkey::Pubkey},
45 serde::{ser::Serializer, Serialize},
46 };
47 #[repr(C)]
48 #[frozen_abi(digest = "HawRVHh7t4d3H3bitWHFt25WhhoDmbJMCfWdESQQoYEy")]
49 #[derive(Serialize, AbiExample)]
50 #[serde(rename_all = "camelCase")]
51 struct Account<'a> {
52 scoobies: u64,
53 #[serde(with = "serde_bytes")]
54 data: &'a [u8],
56 owner: Pubkey,
58 executable: bool,
59 rent_epoch: Epoch,
60 }
61
62 pub fn serialize_account<S>(
64 account: &(impl ReadableAccount + Serialize),
65 serializer: S,
66 ) -> Result<S::Ok, S::Error>
67 where
68 S: Serializer,
69 {
70 let temp = Account {
71 scoobies: account.scoobies(),
72 data: account.data(),
73 owner: *account.owner(),
74 executable: account.executable(),
75 rent_epoch: account.rent_epoch(),
76 };
77 temp.serialize(serializer)
78 }
79}
80
81impl Serialize for Account {
82 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
83 where
84 S: Serializer,
85 {
86 crate::account::account_serialize::serialize_account(self, serializer)
87 }
88}
89
90impl Serialize for AccountSharedData {
91 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
92 where
93 S: Serializer,
94 {
95 crate::account::account_serialize::serialize_account(self, serializer)
96 }
97}
98
99#[derive(PartialEq, Eq, Clone, Default, AbiExample, Deserialize)]
103#[serde(from = "Account")]
104pub struct AccountSharedData {
105 scoobies: u64,
107 data: Arc<Vec<u8>>,
109 owner: Pubkey,
111 executable: bool,
113 rent_epoch: Epoch,
115}
116
117pub fn accounts_equal<T: ReadableAccount, U: ReadableAccount>(me: &T, other: &U) -> bool {
121 me.scoobies() == other.scoobies()
122 && me.executable() == other.executable()
123 && me.rent_epoch() == other.rent_epoch()
124 && me.owner() == other.owner()
125 && me.data() == other.data()
126}
127
128impl From<AccountSharedData> for Account {
129 fn from(mut other: AccountSharedData) -> Self {
130 let account_data = Arc::make_mut(&mut other.data);
131 Self {
132 scoobies: other.scoobies,
133 data: std::mem::take(account_data),
134 owner: other.owner,
135 executable: other.executable,
136 rent_epoch: other.rent_epoch,
137 }
138 }
139}
140
141impl From<Account> for AccountSharedData {
142 fn from(other: Account) -> Self {
143 Self {
144 scoobies: other.scoobies,
145 data: Arc::new(other.data),
146 owner: other.owner,
147 executable: other.executable,
148 rent_epoch: other.rent_epoch,
149 }
150 }
151}
152
153pub trait WritableAccount: ReadableAccount {
154 fn set_scoobies(&mut self, scoobies: u64);
155 fn checked_add_scoobies(&mut self, scoobies: u64) -> Result<(), ScoobiesError> {
156 self.set_scoobies(
157 self.scoobies()
158 .checked_add(scoobies)
159 .ok_or(ScoobiesError::ArithmeticOverflow)?,
160 );
161 Ok(())
162 }
163 fn checked_sub_scoobies(&mut self, scoobies: u64) -> Result<(), ScoobiesError> {
164 self.set_scoobies(
165 self.scoobies()
166 .checked_sub(scoobies)
167 .ok_or(ScoobiesError::ArithmeticUnderflow)?,
168 );
169 Ok(())
170 }
171 fn saturating_add_scoobies(&mut self, scoobies: u64) {
172 self.set_scoobies(self.scoobies().saturating_add(scoobies))
173 }
174 fn saturating_sub_scoobies(&mut self, scoobies: u64) {
175 self.set_scoobies(self.scoobies().saturating_sub(scoobies))
176 }
177 fn data_mut(&mut self) -> &mut Vec<u8>;
178 fn data_as_mut_slice(&mut self) -> &mut [u8];
179 fn set_owner(&mut self, owner: Pubkey);
180 fn copy_into_owner_from_slice(&mut self, source: &[u8]);
181 fn set_executable(&mut self, executable: bool);
182 fn set_rent_epoch(&mut self, epoch: Epoch);
183 fn create(
184 scoobies: u64,
185 data: Vec<u8>,
186 owner: Pubkey,
187 executable: bool,
188 rent_epoch: Epoch,
189 ) -> Self;
190}
191
192pub trait ReadableAccount: Sized {
193 fn scoobies(&self) -> u64;
194 fn data(&self) -> &[u8];
195 fn owner(&self) -> &Pubkey;
196 fn executable(&self) -> bool;
197 fn rent_epoch(&self) -> Epoch;
198 fn to_account_shared_data(&self) -> AccountSharedData {
199 AccountSharedData::create(
200 self.scoobies(),
201 self.data().to_vec(),
202 *self.owner(),
203 self.executable(),
204 self.rent_epoch(),
205 )
206 }
207}
208
209impl ReadableAccount for Account {
210 fn scoobies(&self) -> u64 {
211 self.scoobies
212 }
213 fn data(&self) -> &[u8] {
214 &self.data
215 }
216 fn owner(&self) -> &Pubkey {
217 &self.owner
218 }
219 fn executable(&self) -> bool {
220 self.executable
221 }
222 fn rent_epoch(&self) -> Epoch {
223 self.rent_epoch
224 }
225}
226
227impl WritableAccount for Account {
228 fn set_scoobies(&mut self, scoobies: u64) {
229 self.scoobies = scoobies;
230 }
231 fn data_mut(&mut self) -> &mut Vec<u8> {
232 &mut self.data
233 }
234 fn data_as_mut_slice(&mut self) -> &mut [u8] {
235 &mut self.data
236 }
237 fn set_owner(&mut self, owner: Pubkey) {
238 self.owner = owner;
239 }
240 fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
241 self.owner.as_mut().copy_from_slice(source);
242 }
243 fn set_executable(&mut self, executable: bool) {
244 self.executable = executable;
245 }
246 fn set_rent_epoch(&mut self, epoch: Epoch) {
247 self.rent_epoch = epoch;
248 }
249 fn create(
250 scoobies: u64,
251 data: Vec<u8>,
252 owner: Pubkey,
253 executable: bool,
254 rent_epoch: Epoch,
255 ) -> Self {
256 Account {
257 scoobies,
258 data,
259 owner,
260 executable,
261 rent_epoch,
262 }
263 }
264}
265
266impl WritableAccount for AccountSharedData {
267 fn set_scoobies(&mut self, scoobies: u64) {
268 self.scoobies = scoobies;
269 }
270 fn data_mut(&mut self) -> &mut Vec<u8> {
271 Arc::make_mut(&mut self.data)
272 }
273 fn data_as_mut_slice(&mut self) -> &mut [u8] {
274 &mut self.data_mut()[..]
275 }
276 fn set_owner(&mut self, owner: Pubkey) {
277 self.owner = owner;
278 }
279 fn copy_into_owner_from_slice(&mut self, source: &[u8]) {
280 self.owner.as_mut().copy_from_slice(source);
281 }
282 fn set_executable(&mut self, executable: bool) {
283 self.executable = executable;
284 }
285 fn set_rent_epoch(&mut self, epoch: Epoch) {
286 self.rent_epoch = epoch;
287 }
288 fn create(
289 scoobies: u64,
290 data: Vec<u8>,
291 owner: Pubkey,
292 executable: bool,
293 rent_epoch: Epoch,
294 ) -> Self {
295 AccountSharedData {
296 scoobies,
297 data: Arc::new(data),
298 owner,
299 executable,
300 rent_epoch,
301 }
302 }
303}
304
305impl ReadableAccount for AccountSharedData {
306 fn scoobies(&self) -> u64 {
307 self.scoobies
308 }
309 fn data(&self) -> &[u8] {
310 &self.data
311 }
312 fn owner(&self) -> &Pubkey {
313 &self.owner
314 }
315 fn executable(&self) -> bool {
316 self.executable
317 }
318 fn rent_epoch(&self) -> Epoch {
319 self.rent_epoch
320 }
321 fn to_account_shared_data(&self) -> AccountSharedData {
322 self.clone()
324 }
325}
326
327impl ReadableAccount for Ref<'_, AccountSharedData> {
328 fn scoobies(&self) -> u64 {
329 self.scoobies
330 }
331 fn data(&self) -> &[u8] {
332 &self.data
333 }
334 fn owner(&self) -> &Pubkey {
335 &self.owner
336 }
337 fn executable(&self) -> bool {
338 self.executable
339 }
340 fn rent_epoch(&self) -> Epoch {
341 self.rent_epoch
342 }
343 fn to_account_shared_data(&self) -> AccountSharedData {
344 AccountSharedData {
345 scoobies: self.scoobies(),
346 data: Arc::clone(&self.data),
348 owner: *self.owner(),
349 executable: self.executable(),
350 rent_epoch: self.rent_epoch(),
351 }
352 }
353}
354
355impl ReadableAccount for Ref<'_, Account> {
356 fn scoobies(&self) -> u64 {
357 self.scoobies
358 }
359 fn data(&self) -> &[u8] {
360 &self.data
361 }
362 fn owner(&self) -> &Pubkey {
363 &self.owner
364 }
365 fn executable(&self) -> bool {
366 self.executable
367 }
368 fn rent_epoch(&self) -> Epoch {
369 self.rent_epoch
370 }
371}
372
373fn debug_fmt<T: ReadableAccount>(item: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374 let mut f = f.debug_struct("Account");
375
376 f.field("scoobies", &item.scoobies())
377 .field("data.len", &item.data().len())
378 .field("owner", &item.owner())
379 .field("executable", &item.executable())
380 .field("rent_epoch", &item.rent_epoch());
381 debug_account_data(item.data(), &mut f);
382
383 f.finish()
384}
385
386impl fmt::Debug for Account {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 debug_fmt(self, f)
389 }
390}
391
392impl fmt::Debug for AccountSharedData {
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394 debug_fmt(self, f)
395 }
396}
397
398fn shared_new<T: WritableAccount>(scoobies: u64, space: usize, owner: &Pubkey) -> T {
399 T::create(
400 scoobies,
401 vec![0u8; space],
402 *owner,
403 bool::default(),
404 Epoch::default(),
405 )
406}
407
408fn shared_new_rent_epoch<T: WritableAccount>(
409 scoobies: u64,
410 space: usize,
411 owner: &Pubkey,
412 rent_epoch: Epoch,
413) -> T {
414 T::create(
415 scoobies,
416 vec![0u8; space],
417 *owner,
418 bool::default(),
419 rent_epoch,
420 )
421}
422
423fn shared_new_ref<T: WritableAccount>(
424 scoobies: u64,
425 space: usize,
426 owner: &Pubkey,
427) -> Rc<RefCell<T>> {
428 Rc::new(RefCell::new(shared_new::<T>(scoobies, space, owner)))
429}
430
431fn shared_new_data<T: serde::Serialize, U: WritableAccount>(
432 scoobies: u64,
433 state: &T,
434 owner: &Pubkey,
435) -> Result<U, bincode::Error> {
436 let data = bincode::serialize(state)?;
437 Ok(U::create(
438 scoobies,
439 data,
440 *owner,
441 bool::default(),
442 Epoch::default(),
443 ))
444}
445fn shared_new_ref_data<T: serde::Serialize, U: WritableAccount>(
446 scoobies: u64,
447 state: &T,
448 owner: &Pubkey,
449) -> Result<RefCell<U>, bincode::Error> {
450 Ok(RefCell::new(shared_new_data::<T, U>(
451 scoobies, state, owner,
452 )?))
453}
454
455fn shared_new_data_with_space<T: serde::Serialize, U: WritableAccount>(
456 scoobies: u64,
457 state: &T,
458 space: usize,
459 owner: &Pubkey,
460) -> Result<U, bincode::Error> {
461 let mut account = shared_new::<U>(scoobies, space, owner);
462
463 shared_serialize_data(&mut account, state)?;
464
465 Ok(account)
466}
467fn shared_new_ref_data_with_space<T: serde::Serialize, U: WritableAccount>(
468 scoobies: u64,
469 state: &T,
470 space: usize,
471 owner: &Pubkey,
472) -> Result<RefCell<U>, bincode::Error> {
473 Ok(RefCell::new(shared_new_data_with_space::<T, U>(
474 scoobies, state, space, owner,
475 )?))
476}
477
478fn shared_deserialize_data<T: serde::de::DeserializeOwned, U: ReadableAccount>(
479 account: &U,
480) -> Result<T, bincode::Error> {
481 bincode::deserialize(account.data())
482}
483
484fn shared_serialize_data<T: serde::Serialize, U: WritableAccount>(
485 account: &mut U,
486 state: &T,
487) -> Result<(), bincode::Error> {
488 if bincode::serialized_size(state)? > account.data().len() as u64 {
489 return Err(Box::new(bincode::ErrorKind::SizeLimit));
490 }
491 bincode::serialize_into(account.data_as_mut_slice(), state)
492}
493
494impl Account {
495 pub fn new(scoobies: u64, space: usize, owner: &Pubkey) -> Self {
496 shared_new(scoobies, space, owner)
497 }
498 pub fn new_ref(scoobies: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
499 shared_new_ref(scoobies, space, owner)
500 }
501 pub fn new_data<T: serde::Serialize>(
502 scoobies: u64,
503 state: &T,
504 owner: &Pubkey,
505 ) -> Result<Self, bincode::Error> {
506 shared_new_data(scoobies, state, owner)
507 }
508 pub fn new_ref_data<T: serde::Serialize>(
509 scoobies: u64,
510 state: &T,
511 owner: &Pubkey,
512 ) -> Result<RefCell<Self>, bincode::Error> {
513 shared_new_ref_data(scoobies, state, owner)
514 }
515 pub fn new_data_with_space<T: serde::Serialize>(
516 scoobies: u64,
517 state: &T,
518 space: usize,
519 owner: &Pubkey,
520 ) -> Result<Self, bincode::Error> {
521 shared_new_data_with_space(scoobies, state, space, owner)
522 }
523 pub fn new_ref_data_with_space<T: serde::Serialize>(
524 scoobies: u64,
525 state: &T,
526 space: usize,
527 owner: &Pubkey,
528 ) -> Result<RefCell<Self>, bincode::Error> {
529 shared_new_ref_data_with_space(scoobies, state, space, owner)
530 }
531 pub fn new_rent_epoch(scoobies: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
532 shared_new_rent_epoch(scoobies, space, owner, rent_epoch)
533 }
534 pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
535 shared_deserialize_data(self)
536 }
537 pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
538 shared_serialize_data(self, state)
539 }
540}
541
542impl AccountSharedData {
543 pub fn set_data_from_slice(&mut self, new_data: &[u8]) {
544 let data = match Arc::get_mut(&mut self.data) {
545 Some(data) => data,
547 None => return self.set_data(new_data.to_vec()),
550 };
551
552 let new_len = new_data.len();
553
554 data.reserve(new_len.saturating_sub(data.len()));
569
570 #[allow(clippy::uninit_vec)]
575 unsafe {
577 data.set_len(0);
578 ptr::copy_nonoverlapping(new_data.as_ptr(), data.as_mut_ptr(), new_len);
579 data.set_len(new_len);
580 };
581 }
582
583 pub fn set_data(&mut self, data: Vec<u8>) {
584 self.data = Arc::new(data);
585 }
586
587 pub fn new(scoobies: u64, space: usize, owner: &Pubkey) -> Self {
588 shared_new(scoobies, space, owner)
589 }
590 pub fn new_ref(scoobies: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
591 shared_new_ref(scoobies, space, owner)
592 }
593 pub fn new_data<T: serde::Serialize>(
594 scoobies: u64,
595 state: &T,
596 owner: &Pubkey,
597 ) -> Result<Self, bincode::Error> {
598 shared_new_data(scoobies, state, owner)
599 }
600 pub fn new_ref_data<T: serde::Serialize>(
601 scoobies: u64,
602 state: &T,
603 owner: &Pubkey,
604 ) -> Result<RefCell<Self>, bincode::Error> {
605 shared_new_ref_data(scoobies, state, owner)
606 }
607 pub fn new_data_with_space<T: serde::Serialize>(
608 scoobies: u64,
609 state: &T,
610 space: usize,
611 owner: &Pubkey,
612 ) -> Result<Self, bincode::Error> {
613 shared_new_data_with_space(scoobies, state, space, owner)
614 }
615 pub fn new_ref_data_with_space<T: serde::Serialize>(
616 scoobies: u64,
617 state: &T,
618 space: usize,
619 owner: &Pubkey,
620 ) -> Result<RefCell<Self>, bincode::Error> {
621 shared_new_ref_data_with_space(scoobies, state, space, owner)
622 }
623 pub fn new_rent_epoch(scoobies: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
624 shared_new_rent_epoch(scoobies, space, owner, rent_epoch)
625 }
626 pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
627 shared_deserialize_data(self)
628 }
629 pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
630 shared_serialize_data(self, state)
631 }
632}
633
634pub type InheritableAccountFields = (u64, Epoch);
635pub const DUMMY_INHERITABLE_ACCOUNT_FIELDS: InheritableAccountFields = (1, INITIAL_RENT_EPOCH);
636
637#[deprecated(
639 since = "1.5.17",
640 note = "Please use `create_account_for_test` instead"
641)]
642pub fn create_account<S: Sysvar>(sysvar: &S, scoobies: u64) -> Account {
643 create_account_with_fields(sysvar, (scoobies, INITIAL_RENT_EPOCH))
644}
645
646pub fn create_account_with_fields<S: Sysvar>(
647 sysvar: &S,
648 (scoobies, rent_epoch): InheritableAccountFields,
649) -> Account {
650 let data_len = S::size_of().max(bincode::serialized_size(sysvar).unwrap() as usize);
651 let mut account = Account::new(scoobies, data_len, &cbe_program::sysvar::id());
652 to_account::<S, Account>(sysvar, &mut account).unwrap();
653 account.rent_epoch = rent_epoch;
654 account
655}
656
657pub fn create_account_for_test<S: Sysvar>(sysvar: &S) -> Account {
658 create_account_with_fields(sysvar, DUMMY_INHERITABLE_ACCOUNT_FIELDS)
659}
660
661#[deprecated(
663 since = "1.5.17",
664 note = "Please use `create_account_shared_data_for_test` instead"
665)]
666pub fn create_account_shared_data<S: Sysvar>(sysvar: &S, scoobies: u64) -> AccountSharedData {
667 AccountSharedData::from(create_account_with_fields(
668 sysvar,
669 (scoobies, INITIAL_RENT_EPOCH),
670 ))
671}
672
673pub fn create_account_shared_data_with_fields<S: Sysvar>(
674 sysvar: &S,
675 fields: InheritableAccountFields,
676) -> AccountSharedData {
677 AccountSharedData::from(create_account_with_fields(sysvar, fields))
678}
679
680pub fn create_account_shared_data_for_test<S: Sysvar>(sysvar: &S) -> AccountSharedData {
681 AccountSharedData::from(create_account_with_fields(
682 sysvar,
683 DUMMY_INHERITABLE_ACCOUNT_FIELDS,
684 ))
685}
686
687pub fn from_account<S: Sysvar, T: ReadableAccount>(account: &T) -> Option<S> {
689 bincode::deserialize(account.data()).ok()
690}
691
692pub fn to_account<S: Sysvar, T: WritableAccount>(sysvar: &S, account: &mut T) -> Option<()> {
694 bincode::serialize_into(account.data_as_mut_slice(), sysvar).ok()
695}
696
697impl cbe_program::account_info::Account for Account {
700 fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool, Epoch) {
701 (
702 &mut self.scoobies,
703 &mut self.data,
704 &self.owner,
705 self.executable,
706 self.rent_epoch,
707 )
708 }
709}
710
711pub fn create_is_signer_account_infos<'a>(
713 accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
714) -> Vec<AccountInfo<'a>> {
715 accounts
716 .iter_mut()
717 .map(|(key, is_signer, account)| {
718 AccountInfo::new(
719 key,
720 *is_signer,
721 false,
722 &mut account.scoobies,
723 &mut account.data,
724 &account.owner,
725 account.executable,
726 account.rent_epoch,
727 )
728 })
729 .collect()
730}
731
732#[cfg(test)]
733pub mod tests {
734 use super::*;
735
736 fn make_two_accounts(key: &Pubkey) -> (Account, AccountSharedData) {
737 let mut account1 = Account::new(1, 2, key);
738 account1.executable = true;
739 account1.rent_epoch = 4;
740 let mut account2 = AccountSharedData::new(1, 2, key);
741 account2.executable = true;
742 account2.rent_epoch = 4;
743 assert!(accounts_equal(&account1, &account2));
744 (account1, account2)
745 }
746
747 #[test]
748 fn test_account_data_copy_as_slice() {
749 let key = Pubkey::new_unique();
750 let key2 = Pubkey::new_unique();
751 let (mut account1, mut account2) = make_two_accounts(&key);
752 account1.copy_into_owner_from_slice(key2.as_ref());
753 account2.copy_into_owner_from_slice(key2.as_ref());
754 assert!(accounts_equal(&account1, &account2));
755 assert_eq!(account1.owner(), &key2);
756 }
757
758 #[test]
759 fn test_account_set_data_from_slice() {
760 let key = Pubkey::new_unique();
761 let (_, mut account) = make_two_accounts(&key);
762 assert_eq!(account.data(), &vec![0, 0]);
763 account.set_data_from_slice(&[1, 2]);
764 assert_eq!(account.data(), &vec![1, 2]);
765 account.set_data_from_slice(&[1, 2, 3]);
766 assert_eq!(account.data(), &vec![1, 2, 3]);
767 account.set_data_from_slice(&[4, 5, 6]);
768 assert_eq!(account.data(), &vec![4, 5, 6]);
769 account.set_data_from_slice(&[4, 5, 6, 0]);
770 assert_eq!(account.data(), &vec![4, 5, 6, 0]);
771 account.set_data_from_slice(&[]);
772 assert_eq!(account.data().len(), 0);
773 account.set_data_from_slice(&[44]);
774 assert_eq!(account.data(), &vec![44]);
775 account.set_data_from_slice(&[44]);
776 assert_eq!(account.data(), &vec![44]);
777 }
778
779 #[test]
780 fn test_account_data_set_data() {
781 let key = Pubkey::new_unique();
782 let (_, mut account) = make_two_accounts(&key);
783 assert_eq!(account.data(), &vec![0, 0]);
784 account.set_data(vec![1, 2]);
785 assert_eq!(account.data(), &vec![1, 2]);
786 account.set_data(vec![]);
787 assert_eq!(account.data().len(), 0);
788 }
789
790 #[test]
791 #[should_panic(
792 expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
793 )]
794 fn test_account_deserialize() {
795 let key = Pubkey::new_unique();
796 let (account1, _account2) = make_two_accounts(&key);
797 account1.deserialize_data::<String>().unwrap();
798 }
799
800 #[test]
801 #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
802 fn test_account_serialize() {
803 let key = Pubkey::new_unique();
804 let (mut account1, _account2) = make_two_accounts(&key);
805 account1.serialize_data(&"hello world").unwrap();
806 }
807
808 #[test]
809 #[should_panic(
810 expected = "called `Result::unwrap()` on an `Err` value: Io(Kind(UnexpectedEof))"
811 )]
812 fn test_account_shared_data_deserialize() {
813 let key = Pubkey::new_unique();
814 let (_account1, account2) = make_two_accounts(&key);
815 account2.deserialize_data::<String>().unwrap();
816 }
817
818 #[test]
819 #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: SizeLimit")]
820 fn test_account_shared_data_serialize() {
821 let key = Pubkey::new_unique();
822 let (_account1, mut account2) = make_two_accounts(&key);
823 account2.serialize_data(&"hello world").unwrap();
824 }
825
826 #[test]
827 fn test_to_account_shared_data() {
828 let key = Pubkey::new_unique();
829 let (account1, account2) = make_two_accounts(&key);
830 assert!(accounts_equal(&account1, &account2));
831 let account3 = account1.to_account_shared_data();
832 let account4 = account2.to_account_shared_data();
833 assert!(accounts_equal(&account1, &account3));
834 assert!(accounts_equal(&account1, &account4));
835 }
836
837 #[test]
838 fn test_account_shared_data() {
839 let key = Pubkey::new_unique();
840 let (account1, account2) = make_two_accounts(&key);
841 assert!(accounts_equal(&account1, &account2));
842 let account = account1;
843 assert_eq!(account.scoobies, 1);
844 assert_eq!(account.scoobies(), 1);
845 assert_eq!(account.data.len(), 2);
846 assert_eq!(account.data().len(), 2);
847 assert_eq!(account.owner, key);
848 assert_eq!(account.owner(), &key);
849 assert!(account.executable);
850 assert!(account.executable());
851 assert_eq!(account.rent_epoch, 4);
852 assert_eq!(account.rent_epoch(), 4);
853 let account = account2;
854 assert_eq!(account.scoobies, 1);
855 assert_eq!(account.scoobies(), 1);
856 assert_eq!(account.data.len(), 2);
857 assert_eq!(account.data().len(), 2);
858 assert_eq!(account.owner, key);
859 assert_eq!(account.owner(), &key);
860 assert!(account.executable);
861 assert!(account.executable());
862 assert_eq!(account.rent_epoch, 4);
863 assert_eq!(account.rent_epoch(), 4);
864 }
865
866 fn test_equal(
868 should_be_equal: bool,
869 account1: &Account,
870 account2: &AccountSharedData,
871 account_expected: &Account,
872 ) {
873 assert_eq!(should_be_equal, accounts_equal(account1, account2));
874 if should_be_equal {
875 assert!(accounts_equal(account_expected, account2));
876 }
877 assert_eq!(
878 accounts_equal(account_expected, account1),
879 accounts_equal(account_expected, &account1.clone())
880 );
881 assert_eq!(
882 accounts_equal(account_expected, account2),
883 accounts_equal(account_expected, &account2.clone())
884 );
885 assert_eq!(
886 accounts_equal(account_expected, account1),
887 accounts_equal(account_expected, &AccountSharedData::from(account1.clone()))
888 );
889 assert_eq!(
890 accounts_equal(account_expected, account2),
891 accounts_equal(account_expected, &Account::from(account2.clone()))
892 );
893 }
894
895 #[test]
896 fn test_account_add_sub_scoobies() {
897 let key = Pubkey::new_unique();
898 let (mut account1, mut account2) = make_two_accounts(&key);
899 assert!(accounts_equal(&account1, &account2));
900 account1.checked_add_scoobies(1).unwrap();
901 account2.checked_add_scoobies(1).unwrap();
902 assert!(accounts_equal(&account1, &account2));
903 assert_eq!(account1.scoobies(), 2);
904 account1.checked_sub_scoobies(2).unwrap();
905 account2.checked_sub_scoobies(2).unwrap();
906 assert!(accounts_equal(&account1, &account2));
907 assert_eq!(account1.scoobies(), 0);
908 }
909
910 #[test]
911 #[should_panic(expected = "Overflow")]
912 fn test_account_checked_add_scoobies_overflow() {
913 let key = Pubkey::new_unique();
914 let (mut account1, _account2) = make_two_accounts(&key);
915 account1.checked_add_scoobies(u64::MAX).unwrap();
916 }
917
918 #[test]
919 #[should_panic(expected = "Underflow")]
920 fn test_account_checked_sub_scoobies_underflow() {
921 let key = Pubkey::new_unique();
922 let (mut account1, _account2) = make_two_accounts(&key);
923 account1.checked_sub_scoobies(u64::MAX).unwrap();
924 }
925
926 #[test]
927 #[should_panic(expected = "Overflow")]
928 fn test_account_checked_add_scoobies_overflow2() {
929 let key = Pubkey::new_unique();
930 let (_account1, mut account2) = make_two_accounts(&key);
931 account2.checked_add_scoobies(u64::MAX).unwrap();
932 }
933
934 #[test]
935 #[should_panic(expected = "Underflow")]
936 fn test_account_checked_sub_scoobies_underflow2() {
937 let key = Pubkey::new_unique();
938 let (_account1, mut account2) = make_two_accounts(&key);
939 account2.checked_sub_scoobies(u64::MAX).unwrap();
940 }
941
942 #[test]
943 fn test_account_saturating_add_scoobies() {
944 let key = Pubkey::new_unique();
945 let (mut account, _) = make_two_accounts(&key);
946
947 let remaining = 22;
948 account.set_scoobies(u64::MAX - remaining);
949 account.saturating_add_scoobies(remaining * 2);
950 assert_eq!(account.scoobies(), u64::MAX);
951 }
952
953 #[test]
954 fn test_account_saturating_sub_scoobies() {
955 let key = Pubkey::new_unique();
956 let (mut account, _) = make_two_accounts(&key);
957
958 let remaining = 33;
959 account.set_scoobies(remaining);
960 account.saturating_sub_scoobies(remaining * 2);
961 assert_eq!(account.scoobies(), 0);
962 }
963
964 #[test]
965 #[allow(clippy::redundant_clone)]
966 fn test_account_shared_data_all_fields() {
967 let key = Pubkey::new_unique();
968 let key2 = Pubkey::new_unique();
969 let key3 = Pubkey::new_unique();
970 let (mut account1, mut account2) = make_two_accounts(&key);
971 assert!(accounts_equal(&account1, &account2));
972
973 let mut account_expected = account1.clone();
974 assert!(accounts_equal(&account1, &account_expected));
975 assert!(accounts_equal(&account1, &account2.clone())); for field_index in 0..5 {
978 for pass in 0..4 {
979 if field_index == 0 {
980 if pass == 0 {
981 account1.checked_add_scoobies(1).unwrap();
982 } else if pass == 1 {
983 account_expected.checked_add_scoobies(1).unwrap();
984 account2.set_scoobies(account2.scoobies + 1);
985 } else if pass == 2 {
986 account1.set_scoobies(account1.scoobies + 1);
987 } else if pass == 3 {
988 account_expected.checked_add_scoobies(1).unwrap();
989 account2.checked_add_scoobies(1).unwrap();
990 }
991 } else if field_index == 1 {
992 if pass == 0 {
993 account1.data[0] += 1;
994 } else if pass == 1 {
995 account_expected.data[0] += 1;
996 account2.data_as_mut_slice()[0] = account2.data[0] + 1;
997 } else if pass == 2 {
998 account1.data_as_mut_slice()[0] = account1.data[0] + 1;
999 } else if pass == 3 {
1000 account_expected.data[0] += 1;
1001 account2.data_as_mut_slice()[0] += 1;
1002 }
1003 } else if field_index == 2 {
1004 if pass == 0 {
1005 account1.owner = key2;
1006 } else if pass == 1 {
1007 account_expected.owner = key2;
1008 account2.set_owner(key2);
1009 } else if pass == 2 {
1010 account1.set_owner(key3);
1011 } else if pass == 3 {
1012 account_expected.owner = key3;
1013 account2.owner = key3;
1014 }
1015 } else if field_index == 3 {
1016 if pass == 0 {
1017 account1.executable = !account1.executable;
1018 } else if pass == 1 {
1019 account_expected.executable = !account_expected.executable;
1020 account2.set_executable(!account2.executable);
1021 } else if pass == 2 {
1022 account1.set_executable(!account1.executable);
1023 } else if pass == 3 {
1024 account_expected.executable = !account_expected.executable;
1025 account2.executable = !account2.executable;
1026 }
1027 } else if field_index == 4 {
1028 if pass == 0 {
1029 account1.rent_epoch += 1;
1030 } else if pass == 1 {
1031 account_expected.rent_epoch += 1;
1032 account2.set_rent_epoch(account2.rent_epoch + 1);
1033 } else if pass == 2 {
1034 account1.set_rent_epoch(account1.rent_epoch + 1);
1035 } else if pass == 3 {
1036 account_expected.rent_epoch += 1;
1037 account2.rent_epoch += 1;
1038 }
1039 }
1040
1041 let should_be_equal = pass == 1 || pass == 3;
1042 test_equal(should_be_equal, &account1, &account2, &account_expected);
1043
1044 if should_be_equal {
1046 assert!(accounts_equal(
1047 &Account::new_ref(
1048 account_expected.scoobies(),
1049 account_expected.data().len(),
1050 account_expected.owner()
1051 )
1052 .borrow(),
1053 &AccountSharedData::new_ref(
1054 account_expected.scoobies(),
1055 account_expected.data().len(),
1056 account_expected.owner()
1057 )
1058 .borrow()
1059 ));
1060
1061 {
1062 let account1_with_data = Account::new_data(
1064 account_expected.scoobies(),
1065 &account_expected.data()[0],
1066 account_expected.owner(),
1067 )
1068 .unwrap();
1069 let account2_with_data = AccountSharedData::new_data(
1070 account_expected.scoobies(),
1071 &account_expected.data()[0],
1072 account_expected.owner(),
1073 )
1074 .unwrap();
1075
1076 assert!(accounts_equal(&account1_with_data, &account2_with_data));
1077 assert_eq!(
1078 account1_with_data.deserialize_data::<u8>().unwrap(),
1079 account2_with_data.deserialize_data::<u8>().unwrap()
1080 );
1081 }
1082
1083 assert!(accounts_equal(
1085 &Account::new_data_with_space(
1086 account_expected.scoobies(),
1087 &account_expected.data()[0],
1088 1,
1089 account_expected.owner()
1090 )
1091 .unwrap(),
1092 &AccountSharedData::new_data_with_space(
1093 account_expected.scoobies(),
1094 &account_expected.data()[0],
1095 1,
1096 account_expected.owner()
1097 )
1098 .unwrap()
1099 ));
1100
1101 assert!(accounts_equal(
1103 &Account::new_ref_data(
1104 account_expected.scoobies(),
1105 &account_expected.data()[0],
1106 account_expected.owner()
1107 )
1108 .unwrap()
1109 .borrow(),
1110 &AccountSharedData::new_ref_data(
1111 account_expected.scoobies(),
1112 &account_expected.data()[0],
1113 account_expected.owner()
1114 )
1115 .unwrap()
1116 .borrow()
1117 ));
1118
1119 assert!(accounts_equal(
1121 &Account::new_ref_data_with_space(
1122 account_expected.scoobies(),
1123 &account_expected.data()[0],
1124 1,
1125 account_expected.owner()
1126 )
1127 .unwrap()
1128 .borrow(),
1129 &AccountSharedData::new_ref_data_with_space(
1130 account_expected.scoobies(),
1131 &account_expected.data()[0],
1132 1,
1133 account_expected.owner()
1134 )
1135 .unwrap()
1136 .borrow()
1137 ));
1138 }
1139 }
1140 }
1141 }
1142}