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, 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)).
|
* 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)).
|
* 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
|
## Breaking Changes
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,10 @@ pub mod misc {
|
||||||
ctx.accounts.data.idata = idata;
|
ctx.accounts.data.idata = idata;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn test_executable(ctx: Context<TestExecutable>) -> ProgramResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Accounts)]
|
#[derive(Accounts)]
|
||||||
|
@ -39,6 +43,12 @@ pub struct Initialize<'info> {
|
||||||
rent: Sysvar<'info, Rent>,
|
rent: Sysvar<'info, Rent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct TestExecutable<'info> {
|
||||||
|
#[account(executable)]
|
||||||
|
program: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
#[account]
|
#[account]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
udata: u128,
|
udata: u128,
|
||||||
|
|
|
@ -42,4 +42,25 @@ describe("misc", () => {
|
||||||
let accInfo = await anchor.getProvider().connection.getAccountInfo(pid);
|
let accInfo = await anchor.getProvider().connection.getAccountInfo(pid);
|
||||||
assert.ok(accInfo.executable);
|
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::{
|
use crate::{
|
||||||
AccountField, AccountsStruct, CompositeField, Constraint, ConstraintBelongsTo,
|
AccountField, AccountsStruct, CompositeField, Constraint, ConstraintBelongsTo,
|
||||||
ConstraintLiteral, ConstraintOwner, ConstraintRentExempt, ConstraintSeeds, ConstraintSigner,
|
ConstraintExecutable, ConstraintLiteral, ConstraintOwner, ConstraintRentExempt,
|
||||||
Field, Ty,
|
ConstraintSeeds, ConstraintSigner, Field, Ty,
|
||||||
};
|
};
|
||||||
use heck::SnakeCase;
|
use heck::SnakeCase;
|
||||||
use quote::quote;
|
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::Owner(c) => generate_constraint_owner(f, c),
|
||||||
Constraint::RentExempt(c) => generate_constraint_rent_exempt(f, c),
|
Constraint::RentExempt(c) => generate_constraint_rent_exempt(f, c),
|
||||||
Constraint::Seeds(c) => generate_constraint_seeds(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),
|
Owner(ConstraintOwner),
|
||||||
RentExempt(ConstraintRentExempt),
|
RentExempt(ConstraintRentExempt),
|
||||||
Seeds(ConstraintSeeds),
|
Seeds(ConstraintSeeds),
|
||||||
|
Executable(ConstraintExecutable),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -303,6 +304,9 @@ pub struct ConstraintSeeds {
|
||||||
pub seeds: proc_macro2::Group,
|
pub seeds: proc_macro2::Group,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConstraintExecutable {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
AccountField, AccountsStruct, CompositeField, Constraint, ConstraintBelongsTo,
|
AccountField, AccountsStruct, CompositeField, Constraint, ConstraintBelongsTo,
|
||||||
ConstraintLiteral, ConstraintOwner, ConstraintRentExempt, ConstraintSeeds, ConstraintSigner,
|
ConstraintExecutable, ConstraintLiteral, ConstraintOwner, ConstraintRentExempt,
|
||||||
CpiAccountTy, Field, ProgramAccountTy, ProgramStateTy, SysvarTy, Ty,
|
ConstraintSeeds, ConstraintSigner, CpiAccountTy, Field, ProgramAccountTy, ProgramStateTy,
|
||||||
|
SysvarTy, Ty,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse(strct: &syn::ItemStruct) -> AccountsStruct {
|
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");
|
panic!("invalid syntax");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue