lang: Add executable account constraint (#140)
This commit is contained in:
parent
7f2ef239ac
commit
d6d41eee59
|
@ -18,6 +18,7 @@ incremented for features.
|
|||
* lang, client, ts: Add event emission and subscriptions ([#89](https://github.com/project-serum/anchor/pull/89)).
|
||||
* lang/account: Allow namespacing account discriminators ([#128](https://github.com/project-serum/anchor/pull/128)).
|
||||
* cli: TypeScript migrations ([#132](https://github.com/project-serum/anchor/pull/132)).
|
||||
* lang: Add `#[account(executable)]` attribute ([#140](https://github.com/project-serum/anchor/pull/140)).
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@ pub mod misc {
|
|||
ctx.accounts.data.idata = idata;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_executable(ctx: Context<TestExecutable>) -> ProgramResult {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
@ -39,6 +43,12 @@ pub struct Initialize<'info> {
|
|||
rent: Sysvar<'info, Rent>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestExecutable<'info> {
|
||||
#[account(executable)]
|
||||
program: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct Data {
|
||||
udata: u128,
|
||||
|
|
|
@ -42,4 +42,25 @@ describe("misc", () => {
|
|||
let accInfo = await anchor.getProvider().connection.getAccountInfo(pid);
|
||||
assert.ok(accInfo.executable);
|
||||
});
|
||||
|
||||
it("Can use the executable attribtue", async () => {
|
||||
await program.rpc.testExecutable({
|
||||
accounts: {
|
||||
program: program.programId,
|
||||
},
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
async () => {
|
||||
await program.rpc.testExecutable({
|
||||
accounts: {
|
||||
program: program.provider.wallet.publicKey,
|
||||
},
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
AccountField, AccountsStruct, CompositeField, Constraint, ConstraintBelongsTo,
|
||||
ConstraintLiteral, ConstraintOwner, ConstraintRentExempt, ConstraintSeeds, ConstraintSigner,
|
||||
Field, Ty,
|
||||
ConstraintExecutable, ConstraintLiteral, ConstraintOwner, ConstraintRentExempt,
|
||||
ConstraintSeeds, ConstraintSigner, Field, Ty,
|
||||
};
|
||||
use heck::SnakeCase;
|
||||
use quote::quote;
|
||||
|
@ -305,6 +305,7 @@ pub fn generate_field_constraint(f: &Field, c: &Constraint) -> proc_macro2::Toke
|
|||
Constraint::Owner(c) => generate_constraint_owner(f, c),
|
||||
Constraint::RentExempt(c) => generate_constraint_rent_exempt(f, c),
|
||||
Constraint::Seeds(c) => generate_constraint_seeds(f, c),
|
||||
Constraint::Executable(c) => generate_constraint_executable(f, c),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,3 +412,15 @@ pub fn generate_constraint_seeds(f: &Field, c: &ConstraintSeeds) -> proc_macro2:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_constraint_executable(
|
||||
f: &Field,
|
||||
_c: &ConstraintExecutable,
|
||||
) -> proc_macro2::TokenStream {
|
||||
let name = &f.ident;
|
||||
quote! {
|
||||
if !#name.to_account_info().executable {
|
||||
return Err(anchor_lang::solana_program::program_error::ProgramError::Custom(5)) // todo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,6 +271,7 @@ pub enum Constraint {
|
|||
Owner(ConstraintOwner),
|
||||
RentExempt(ConstraintRentExempt),
|
||||
Seeds(ConstraintSeeds),
|
||||
Executable(ConstraintExecutable),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -303,6 +304,9 @@ pub struct ConstraintSeeds {
|
|||
pub seeds: proc_macro2::Group,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConstraintExecutable {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
pub name: String,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
AccountField, AccountsStruct, CompositeField, Constraint, ConstraintBelongsTo,
|
||||
ConstraintLiteral, ConstraintOwner, ConstraintRentExempt, ConstraintSeeds, ConstraintSigner,
|
||||
CpiAccountTy, Field, ProgramAccountTy, ProgramStateTy, SysvarTy, Ty,
|
||||
ConstraintExecutable, ConstraintLiteral, ConstraintOwner, ConstraintRentExempt,
|
||||
ConstraintSeeds, ConstraintSigner, CpiAccountTy, Field, ProgramAccountTy, ProgramStateTy,
|
||||
SysvarTy, Ty,
|
||||
};
|
||||
|
||||
pub fn parse(strct: &syn::ItemStruct) -> AccountsStruct {
|
||||
|
@ -270,6 +271,9 @@ fn parse_constraints(anchor: &syn::Attribute) -> (Vec<Constraint>, bool, bool, b
|
|||
}
|
||||
};
|
||||
}
|
||||
"executable" => {
|
||||
constraints.push(Constraint::Executable(ConstraintExecutable {}));
|
||||
}
|
||||
_ => {
|
||||
panic!("invalid syntax");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue