program_account.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #[allow(deprecated)]
  2. use crate::accounts::cpi_account::CpiAccount;
  3. use crate::bpf_writer::BpfWriter;
  4. use crate::error::{Error, ErrorCode};
  5. use crate::{
  6. AccountDeserialize, AccountSerialize, Accounts, AccountsClose, AccountsExit, Key, Result,
  7. ToAccountInfo, ToAccountInfos, ToAccountMetas,
  8. };
  9. use solana_program::account_info::AccountInfo;
  10. use solana_program::instruction::AccountMeta;
  11. use solana_program::pubkey::Pubkey;
  12. use std::collections::{BTreeMap, BTreeSet};
  13. use std::ops::{Deref, DerefMut};
  14. /// Boxed container for a deserialized `account`. Use this to reference any
  15. /// account owned by the currently executing program.
  16. #[derive(Clone)]
  17. #[deprecated(since = "0.15.0", note = "Please use Account instead")]
  18. pub struct ProgramAccount<'info, T: AccountSerialize + AccountDeserialize + Clone> {
  19. inner: Box<Inner<'info, T>>,
  20. }
  21. #[derive(Clone)]
  22. struct Inner<'info, T: AccountSerialize + AccountDeserialize + Clone> {
  23. info: AccountInfo<'info>,
  24. account: T,
  25. }
  26. #[allow(deprecated)]
  27. impl<'a, T: AccountSerialize + AccountDeserialize + Clone> ProgramAccount<'a, T> {
  28. fn new(info: AccountInfo<'a>, account: T) -> ProgramAccount<'a, T> {
  29. Self {
  30. inner: Box::new(Inner { info, account }),
  31. }
  32. }
  33. /// Deserializes the given `info` into a `ProgramAccount`.
  34. #[inline(never)]
  35. pub fn try_from(program_id: &Pubkey, info: &AccountInfo<'a>) -> Result<ProgramAccount<'a, T>> {
  36. if info.owner != program_id {
  37. return Err(Error::from(ErrorCode::AccountOwnedByWrongProgram)
  38. .with_pubkeys((*info.owner, *program_id)));
  39. }
  40. let mut data: &[u8] = &info.try_borrow_data()?;
  41. Ok(ProgramAccount::new(
  42. info.clone(),
  43. T::try_deserialize(&mut data)?,
  44. ))
  45. }
  46. /// Deserializes the given `info` into a `ProgramAccount` without checking
  47. /// the account discriminator. Be careful when using this and avoid it if
  48. /// possible.
  49. #[inline(never)]
  50. pub fn try_from_unchecked(
  51. program_id: &Pubkey,
  52. info: &AccountInfo<'a>,
  53. ) -> Result<ProgramAccount<'a, T>> {
  54. if info.owner != program_id {
  55. return Err(Error::from(ErrorCode::AccountOwnedByWrongProgram)
  56. .with_pubkeys((*info.owner, *program_id)));
  57. }
  58. let mut data: &[u8] = &info.try_borrow_data()?;
  59. Ok(ProgramAccount::new(
  60. info.clone(),
  61. T::try_deserialize_unchecked(&mut data)?,
  62. ))
  63. }
  64. pub fn into_inner(self) -> T {
  65. self.inner.account
  66. }
  67. }
  68. #[allow(deprecated)]
  69. impl<'info, T> Accounts<'info> for ProgramAccount<'info, T>
  70. where
  71. T: AccountSerialize + AccountDeserialize + Clone,
  72. {
  73. #[inline(never)]
  74. fn try_accounts(
  75. program_id: &Pubkey,
  76. accounts: &mut &[AccountInfo<'info>],
  77. _ix_data: &[u8],
  78. _bumps: &mut BTreeMap<String, u8>,
  79. _reallocs: &mut BTreeSet<Pubkey>,
  80. ) -> Result<Self> {
  81. if accounts.is_empty() {
  82. return Err(ErrorCode::AccountNotEnoughKeys.into());
  83. }
  84. let account = &accounts[0];
  85. *accounts = &accounts[1..];
  86. ProgramAccount::try_from(program_id, account)
  87. }
  88. }
  89. #[allow(deprecated)]
  90. impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AccountsExit<'info>
  91. for ProgramAccount<'info, T>
  92. {
  93. fn exit(&self, _program_id: &Pubkey) -> Result<()> {
  94. let info = self.to_account_info();
  95. let mut data = info.try_borrow_mut_data()?;
  96. let dst: &mut [u8] = &mut data;
  97. let mut writer = BpfWriter::new(dst);
  98. self.inner.account.try_serialize(&mut writer)?;
  99. Ok(())
  100. }
  101. }
  102. /// This function is for INTERNAL USE ONLY.
  103. /// Do NOT use this function in a program.
  104. /// Manual closing of `ProgramAccount<'info, T>` types is NOT supported.
  105. ///
  106. /// Details: Using `close` with `ProgramAccount<'info, T>` is not safe because
  107. /// it requires the `mut` constraint but for that type the constraint
  108. /// overwrites the "closed account" discriminator at the end of the instruction.
  109. #[allow(deprecated)]
  110. impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AccountsClose<'info>
  111. for ProgramAccount<'info, T>
  112. {
  113. fn close(&self, sol_destination: AccountInfo<'info>) -> Result<()> {
  114. crate::common::close(self.to_account_info(), sol_destination)
  115. }
  116. }
  117. #[allow(deprecated)]
  118. impl<'info, T: AccountSerialize + AccountDeserialize + Clone> ToAccountMetas
  119. for ProgramAccount<'info, T>
  120. {
  121. fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
  122. let is_signer = is_signer.unwrap_or(self.inner.info.is_signer);
  123. let meta = match self.inner.info.is_writable {
  124. false => AccountMeta::new_readonly(*self.inner.info.key, is_signer),
  125. true => AccountMeta::new(*self.inner.info.key, is_signer),
  126. };
  127. vec![meta]
  128. }
  129. }
  130. #[allow(deprecated)]
  131. impl<'info, T: AccountSerialize + AccountDeserialize + Clone> ToAccountInfos<'info>
  132. for ProgramAccount<'info, T>
  133. {
  134. fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
  135. vec![self.inner.info.clone()]
  136. }
  137. }
  138. #[allow(deprecated)]
  139. impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AsRef<AccountInfo<'info>>
  140. for ProgramAccount<'info, T>
  141. {
  142. fn as_ref(&self) -> &AccountInfo<'info> {
  143. &self.inner.info
  144. }
  145. }
  146. #[allow(deprecated)]
  147. impl<'a, T: AccountSerialize + AccountDeserialize + Clone> Deref for ProgramAccount<'a, T> {
  148. type Target = T;
  149. fn deref(&self) -> &Self::Target {
  150. &(*self.inner).account
  151. }
  152. }
  153. #[allow(deprecated)]
  154. impl<'a, T: AccountSerialize + AccountDeserialize + Clone> DerefMut for ProgramAccount<'a, T> {
  155. fn deref_mut(&mut self) -> &mut Self::Target {
  156. #[cfg(feature = "anchor-debug")]
  157. if !self.inner.info.is_writable {
  158. solana_program::msg!("The given ProgramAccount is not mutable");
  159. panic!();
  160. }
  161. &mut DerefMut::deref_mut(&mut self.inner).account
  162. }
  163. }
  164. #[allow(deprecated)]
  165. impl<'info, T> From<CpiAccount<'info, T>> for ProgramAccount<'info, T>
  166. where
  167. T: AccountSerialize + AccountDeserialize + Clone,
  168. {
  169. fn from(a: CpiAccount<'info, T>) -> Self {
  170. Self::new(a.to_account_info(), Deref::deref(&a).clone())
  171. }
  172. }
  173. #[allow(deprecated)]
  174. impl<'info, T: AccountSerialize + AccountDeserialize + Clone> Key for ProgramAccount<'info, T> {
  175. fn key(&self) -> Pubkey {
  176. *self.inner.info.key
  177. }
  178. }