Skip to content

Commit

Permalink
lang, examples: UncheckedAccount and Cfo updates (#745)
Browse files Browse the repository at this point in the history
  • Loading branch information
armaniferrante authored Sep 16, 2021
1 parent 90df0b1 commit c004b0f
Show file tree
Hide file tree
Showing 11 changed files with 730 additions and 277 deletions.
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,15 @@ mod counter {
pub struct Initialize<'info> {
#[account(init, payer = authority, space = 48)]
pub counter: Account<'info, Counter>,
#[account(signer)]
pub authority: AccountInfo<'info>,
#[account(address = system_program::ID)]
pub system_program: AccountInfo<'info>,
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct Increment<'info> {
#[account(mut, has_one = authority)]
pub counter: Account<'info, Counter>,
#[account(signer)]
pub authority: AccountInfo<'info>,
pub authority: Signer<'info>,
}

#[account]
Expand Down
3 changes: 3 additions & 0 deletions lang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ mod signer;
pub mod state;
mod system_program;
mod sysvar;
mod unchecked_account;
mod vec;

pub use crate::account::Account;
Expand All @@ -74,6 +75,7 @@ pub use crate::signer::Signer;
pub use crate::state::ProgramState;
pub use crate::system_program::System;
pub use crate::sysvar::Sysvar;
pub use crate::unchecked_account::UncheckedAccount;
pub use anchor_attribute_access_control::access_control;
pub use anchor_attribute_account::{account, declare_id, zero_copy};
pub use anchor_attribute_error::error;
Expand Down Expand Up @@ -247,6 +249,7 @@ pub mod prelude {
state, zero_copy, Account, AccountDeserialize, AccountSerialize, Accounts, AccountsExit,
AnchorDeserialize, AnchorSerialize, Context, CpiContext, Key, Loader, Owner, Program,
ProgramAccount, Signer, System, Sysvar, ToAccountInfo, ToAccountInfos, ToAccountMetas,
UncheckedAccount,
};

#[allow(deprecated)]
Expand Down
77 changes: 77 additions & 0 deletions lang/src/unchecked_account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use crate::error::ErrorCode;
use crate::{Accounts, AccountsExit, Key, ToAccountInfo, ToAccountInfos, ToAccountMetas};
use solana_program::account_info::AccountInfo;
use solana_program::entrypoint::ProgramResult;
use solana_program::instruction::AccountMeta;
use solana_program::program_error::ProgramError;
use solana_program::pubkey::Pubkey;
use std::ops::Deref;

/// Explicit wrapper for AccountInfo types.
#[derive(Clone)]
pub struct UncheckedAccount<'info>(AccountInfo<'info>);

impl<'info> UncheckedAccount<'info> {
pub fn try_from(acc_info: AccountInfo<'info>) -> Self {
Self(acc_info)
}
}

impl<'info> Accounts<'info> for UncheckedAccount<'info> {
fn try_accounts(
_program_id: &Pubkey,
accounts: &mut &[AccountInfo<'info>],
_ix_data: &[u8],
) -> Result<Self, ProgramError> {
if accounts.is_empty() {
return Err(ErrorCode::AccountNotEnoughKeys.into());
}
let account = &accounts[0];
*accounts = &accounts[1..];
Ok(UncheckedAccount(account.clone()))
}
}

impl<'info> ToAccountMetas for UncheckedAccount<'info> {
fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
let is_signer = is_signer.unwrap_or(self.is_signer);
let meta = match self.is_writable {
false => AccountMeta::new_readonly(*self.key, is_signer),
true => AccountMeta::new(*self.key, is_signer),
};
vec![meta]
}
}

impl<'info> ToAccountInfos<'info> for UncheckedAccount<'info> {
fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
vec![self.0.clone()]
}
}

impl<'info> ToAccountInfo<'info> for UncheckedAccount<'info> {
fn to_account_info(&self) -> AccountInfo<'info> {
self.0.clone()
}
}

impl<'info> AccountsExit<'info> for UncheckedAccount<'info> {
fn exit(&self, _program_id: &Pubkey) -> ProgramResult {
// no-op
Ok(())
}
}

impl<'info> Key for UncheckedAccount<'info> {
fn key(&self) -> Pubkey {
*self.key
}
}

impl<'info> Deref for UncheckedAccount<'info> {
type Target = AccountInfo<'info>;

fn deref(&self) -> &Self::Target {
&self.0
}
}
10 changes: 5 additions & 5 deletions lang/syn/src/codegen/accounts/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ pub fn generate_constraint_init(f: &Field, c: &ConstraintInitGroup) -> proc_macr
pub fn generate_constraint_zeroed(f: &Field, _c: &ConstraintZeroed) -> proc_macro2::TokenStream {
let field = &f.ident;
let ty_decl = f.ty_decl();
let from_account_info = f.from_account_info(None);
let from_account_info = f.from_account_info_unchecked(None);
quote! {
let #field: #ty_decl = {
let mut __data: &[u8] = &#field.try_borrow_data()?;
Expand Down Expand Up @@ -374,7 +374,7 @@ pub fn generate_init(
) -> proc_macro2::TokenStream {
let field = &f.ident;
let ty_decl = f.ty_decl();
let from_account_info = f.from_account_info(Some(kind));
let from_account_info = f.from_account_info_unchecked(Some(kind));
match kind {
InitKind::Token { owner, mint } => {
let create_account = generate_create_account(
Expand All @@ -401,7 +401,7 @@ pub fn generate_init(
};
let cpi_ctx = CpiContext::new(cpi_program, accounts);
anchor_spl::token::initialize_account(cpi_ctx)?;
let mut pa: #ty_decl = #from_account_info;
let pa: #ty_decl = #from_account_info;
pa
};
}
Expand Down Expand Up @@ -429,7 +429,7 @@ pub fn generate_init(
};
let cpi_ctx = CpiContext::new(cpi_program, accounts);
anchor_spl::token::initialize_mint(cpi_ctx, #decimals, &#owner.to_account_info().key, None)?;
let mut pa: #ty_decl = #from_account_info;
let pa: #ty_decl = #from_account_info;
pa
};
}
Expand Down Expand Up @@ -476,7 +476,7 @@ pub fn generate_init(
#space
#payer
#create_account
let mut pa: #ty_decl = #from_account_info;
let pa: #ty_decl = #from_account_info;
pa
};
}
Expand Down
13 changes: 12 additions & 1 deletion lang/syn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ impl Field {
Ty::AccountInfo => quote! {
AccountInfo
},
Ty::UncheckedAccount => quote! {
UncheckedAccount
},
Ty::Signer => quote! {
Signer
},
Expand Down Expand Up @@ -217,11 +220,14 @@ impl Field {

// TODO: remove the option once `CpiAccount` is completely removed (not
// just deprecated).
pub fn from_account_info(&self, kind: Option<&InitKind>) -> proc_macro2::TokenStream {
pub fn from_account_info_unchecked(&self, kind: Option<&InitKind>) -> proc_macro2::TokenStream {
let field = &self.ident;
let container_ty = self.container_ty();
match &self.ty {
Ty::AccountInfo => quote! { #field.to_account_info() },
Ty::UncheckedAccount => {
quote! { UncheckedAccount::try_from(#field.to_account_info()) }
}
Ty::Account(AccountTy { boxed, .. }) => {
if *boxed {
quote! {
Expand Down Expand Up @@ -276,6 +282,7 @@ impl Field {
Ty::ProgramState(_) => quote! { anchor_lang::ProgramState },
Ty::Program(_) => quote! { anchor_lang::Program },
Ty::AccountInfo => quote! {},
Ty::UncheckedAccount => quote! {},
Ty::Signer => quote! {},
}
}
Expand All @@ -286,6 +293,9 @@ impl Field {
Ty::AccountInfo => quote! {
AccountInfo
},
Ty::UncheckedAccount => quote! {
UncheckedAccount
},
Ty::Signer => quote! {
Signer
},
Expand Down Expand Up @@ -360,6 +370,7 @@ pub struct CompositeField {
#[derive(Debug, PartialEq)]
pub enum Ty {
AccountInfo,
UncheckedAccount,
ProgramState(ProgramStateTy),
CpiState(CpiStateTy),
ProgramAccount(ProgramAccountTy),
Expand Down
1 change: 0 additions & 1 deletion lang/syn/src/parser/accounts/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub fn parse(
}
}
let account_constraints = constraints.build()?;

let mut constraints = ConstraintGroupBuilder::new(f_ty);
for attr in f.attrs.iter().filter(is_instruction) {
if !has_instruction_api {
Expand Down
2 changes: 2 additions & 0 deletions lang/syn/src/parser/accounts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ fn is_field_primitive(f: &syn::Field) -> ParseResult<bool> {
| "CpiAccount"
| "Sysvar"
| "AccountInfo"
| "UncheckedAccount"
| "CpiState"
| "Loader"
| "Account"
Expand All @@ -92,6 +93,7 @@ fn parse_ty(f: &syn::Field) -> ParseResult<Ty> {
"CpiAccount" => Ty::CpiAccount(parse_cpi_account(&path)?),
"Sysvar" => Ty::Sysvar(parse_sysvar(&path)?),
"AccountInfo" => Ty::AccountInfo,
"UncheckedAccount" => Ty::UncheckedAccount,
"Loader" => Ty::Loader(parse_program_account_zero_copy(&path)?),
"Account" => Ty::Account(parse_account_ty(&path)?),
"Program" => Ty::Program(parse_program_ty(&path)?),
Expand Down
3 changes: 2 additions & 1 deletion tests/cfo/programs/cfo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ test = []
[dependencies]
anchor-lang = { path = "../../../../lang" }
anchor-spl = { path = "../../../../spl" }
spl-token = { version ="3.1.1", features = ["no-entrypoint"] }
spl-token = { version = "3.1.1", features = ["no-entrypoint"] }
swap = { path = "../../deps/swap/programs/swap", features = ["cpi"] }
serum_dex = { path = "../../deps/serum-dex/dex", features = ["no-entrypoint"] }
registry = { path = "../../deps/stake/programs/registry", features = ["cpi"] }
lockup = { path = "../../deps/stake/programs/lockup", features = ["cpi"] }
Loading

0 comments on commit c004b0f

Please sign in to comment.