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