signer.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. //! Type validating that the account signed the transaction
  2. use crate::error::ErrorCode;
  3. use crate::{Accounts, AccountsExit, Key, Result, ToAccountInfos, ToAccountMetas};
  4. use solana_program::account_info::AccountInfo;
  5. use solana_program::instruction::AccountMeta;
  6. use solana_program::pubkey::Pubkey;
  7. use std::collections::BTreeSet;
  8. use std::ops::Deref;
  9. /// Type validating that the account signed the transaction. No other ownership
  10. /// or type checks are done. If this is used, one should not try to access the
  11. /// underlying account data.
  12. ///
  13. /// Checks:
  14. ///
  15. /// - `Signer.info.is_signer == true`
  16. ///
  17. /// # Example
  18. /// ```ignore
  19. /// #[account]
  20. /// #[derive(Default)]
  21. /// pub struct MyData {
  22. /// pub data: u64
  23. /// }
  24. ///
  25. /// #[derive(Accounts)]
  26. /// pub struct Example<'info> {
  27. /// #[account(init, payer = payer)]
  28. /// pub my_acc: Account<'info, MyData>,
  29. /// #[account(mut)]
  30. /// pub payer: Signer<'info>,
  31. /// pub system_program: Program<'info, System>
  32. /// }
  33. /// ```
  34. ///
  35. /// When creating an account with `init`, the `payer` needs to sign the transaction.
  36. #[derive(Debug, Clone)]
  37. pub struct Signer<'info> {
  38. info: &'info AccountInfo<'info>,
  39. }
  40. impl<'info> Signer<'info> {
  41. fn new(info: &'info AccountInfo<'info>) -> Signer<'info> {
  42. Self { info }
  43. }
  44. /// Deserializes the given `info` into a `Signer`.
  45. #[inline(never)]
  46. pub fn try_from(info: &'info AccountInfo<'info>) -> Result<Signer<'info>> {
  47. if !info.is_signer {
  48. return Err(ErrorCode::AccountNotSigner.into());
  49. }
  50. Ok(Signer::new(info))
  51. }
  52. }
  53. impl<'info, B> Accounts<'info, B> for Signer<'info> {
  54. #[inline(never)]
  55. fn try_accounts(
  56. _program_id: &Pubkey,
  57. accounts: &mut &'info [AccountInfo<'info>],
  58. _ix_data: &[u8],
  59. _bumps: &mut B,
  60. _reallocs: &mut BTreeSet<Pubkey>,
  61. ) -> Result<Self> {
  62. if accounts.is_empty() {
  63. return Err(ErrorCode::AccountNotEnoughKeys.into());
  64. }
  65. let account = &accounts[0];
  66. *accounts = &accounts[1..];
  67. Signer::try_from(account)
  68. }
  69. }
  70. impl<'info> AccountsExit<'info> for Signer<'info> {}
  71. impl ToAccountMetas for Signer<'_> {
  72. fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
  73. let is_signer = is_signer.unwrap_or(self.info.is_signer);
  74. let meta = match self.info.is_writable {
  75. false => AccountMeta::new_readonly(*self.info.key, is_signer),
  76. true => AccountMeta::new(*self.info.key, is_signer),
  77. };
  78. vec![meta]
  79. }
  80. }
  81. impl<'info> ToAccountInfos<'info> for Signer<'info> {
  82. fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
  83. vec![self.info.clone()]
  84. }
  85. }
  86. impl<'info> AsRef<AccountInfo<'info>> for Signer<'info> {
  87. fn as_ref(&self) -> &AccountInfo<'info> {
  88. self.info
  89. }
  90. }
  91. impl<'info> Deref for Signer<'info> {
  92. type Target = AccountInfo<'info>;
  93. fn deref(&self) -> &Self::Target {
  94. self.info
  95. }
  96. }
  97. impl Key for Signer<'_> {
  98. fn key(&self) -> Pubkey {
  99. *self.info.key
  100. }
  101. }