lang: Add `Owner` & `Discriminator` implementation for ix structures (#2085)

lang: Add into `Discriminator` trait constant `DISCRIMINATOR`

So that during match instructions or other entities there is no explicit instruction call of `discriminator()`

lang: Add `Owner` impl to instructions

Co-authored-by: Mikhail Gorbachev <m.gorbachev@joinsprouttherapy.com>
This commit is contained in:
cyphersnake 2022-11-24 20:19:39 +04:00 committed by GitHub
parent 686c97e45b
commit a73bd728fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 37 deletions

View File

@ -44,6 +44,7 @@ The minor version will be incremented upon a breaking change and the patch versi
- ts: SPL coders have been removed from the main Anchor package. ([#2155](https://github.com/coral-xyz/anchor/pull/2155))
- lang: Remove `rent` from constraints ([#2265](https://github.com/coral-xyz/anchor/pull/2265)).
- spl: Remove `rent` from `associated_token::Create` ([#2265](https://github.com/coral-xyz/anchor/pull/2265)).
- lang: Add `Discriminator` and `Owner` trait implementation for structures representing instructions ([#1997](https://github.com/coral-xyz/anchor/pull/1997))
## [0.25.0] - 2022-07-05

View File

@ -139,9 +139,7 @@ pub fn account(
#[automatically_derived]
impl #impl_gen anchor_lang::Discriminator for #account_name #type_gen #where_clause {
fn discriminator() -> [u8; 8] {
#discriminator
}
const DISCRIMINATOR: [u8; 8] = #discriminator;
}
// This trait is useful for clients deserializing accounts.
@ -211,9 +209,7 @@ pub fn account(
#[automatically_derived]
impl #impl_gen anchor_lang::Discriminator for #account_name #type_gen #where_clause {
fn discriminator() -> [u8; 8] {
#discriminator
}
const DISCRIMINATOR: [u8; 8] = #discriminator;
}
#owner_impl

View File

@ -40,9 +40,7 @@ pub fn event(
}
impl anchor_lang::Discriminator for #event_name {
fn discriminator() -> [u8; 8] {
#discriminator
}
const DISCRIMINATOR: [u8; 8] = #discriminator;
}
})
}

View File

@ -182,8 +182,12 @@ pub trait ZeroCopy: Discriminator + Copy + Clone + Zeroable + Pod {}
/// `Sha256(<namespace>:<method_name>)[..8] || BorshSerialize(args)`.
/// `args` is a borsh serialized struct of named fields for each argument given
/// to an instruction.
pub trait InstructionData: AnchorSerialize {
fn data(&self) -> Vec<u8>;
pub trait InstructionData: Discriminator + AnchorSerialize {
fn data(&self) -> Vec<u8> {
let mut d = Self::discriminator().to_vec();
d.append(&mut self.try_to_vec().expect("Should always serialize"));
d
}
}
/// An event that can be emitted via a Solana log. See [`emit!`](crate::prelude::emit) for an example.
@ -201,7 +205,10 @@ pub trait EventData: AnchorSerialize + Discriminator {
/// 8 byte unique identifier for a type.
pub trait Discriminator {
fn discriminator() -> [u8; 8];
const DISCRIMINATOR: [u8; 8];
fn discriminator() -> [u8; 8] {
Self::DISCRIMINATOR
}
}
/// Bump seed for program derived addresses.

View File

@ -1,5 +1,6 @@
use crate::codegen::program::common::*;
use crate::Program;
use heck::CamelCase;
use quote::quote;
pub fn generate(program: &Program) -> proc_macro2::TokenStream {
@ -35,14 +36,25 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
methods
.iter()
.map(|ix: &crate::StateIx| {
let name = &ix.raw_method.sig.ident.to_string();
let ix_method_name: proc_macro2::TokenStream =
{ format!("__{}", name).parse().unwrap() };
let sighash_arr = sighash(SIGHASH_STATE_NAMESPACE, name);
let sighash_tts: proc_macro2::TokenStream =
format!("{:?}", sighash_arr).parse().unwrap();
format!("__{}", ix.raw_method.sig.ident).parse().expect(
"Failed to parse ix method name with `__` as `TokenStream`",
);
let ix_name_camel: proc_macro2::TokenStream = ix
.raw_method
.sig
.ident
.to_string()
.as_str()
.to_camel_case()
.parse()
.expect(
"Failed to parse state ix method name in camel as `TokenStream`",
);
quote! {
#sighash_tts => {
instruction::state::#ix_name_camel::DISCRIMINATOR => {
__private::__state::#ix_method_name(
program_id,
accounts,
@ -99,11 +111,15 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
.iter()
.map(|ix| {
let ix_method_name = &ix.raw_method.sig.ident;
let sighash_arr = sighash(SIGHASH_GLOBAL_NAMESPACE, &ix_method_name.to_string());
let sighash_tts: proc_macro2::TokenStream =
format!("{:?}", sighash_arr).parse().unwrap();
let ix_name_camel: proc_macro2::TokenStream = ix_method_name
.to_string()
.as_str()
.to_camel_case()
.parse()
.expect("Failed to parse ix method name in camel as `TokenStream`");
quote! {
#sighash_tts => {
instruction::#ix_name_camel::DISCRIMINATOR => {
__private::__global::#ix_method_name(
program_id,
accounts,
@ -162,6 +178,7 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
}
}
use anchor_lang::Discriminator;
match sighash {
#ctor_state_dispatch_arm
#(#state_dispatch_arms)*

View File

@ -39,11 +39,13 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
/// constructor.
#strct
impl anchor_lang::InstructionData for New {
fn data(&self) -> Vec<u8> {
let mut d = #sighash_tts.to_vec();
d.append(&mut self.try_to_vec().expect("Should always serialize"));
d
impl anchor_lang::Discriminator for New {
const DISCRIMINATOR: [u8; 8] = #sighash_tts;
}
impl anchor_lang::InstructionData for New {}
impl anchor_lang::Owner for New {
fn owner() -> Pubkey {
ID
}
}
}
@ -82,11 +84,13 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
let sighash_tts: proc_macro2::TokenStream =
format!("{:?}", sighash_arr).parse().unwrap();
quote! {
impl anchor_lang::InstructionData for #ix_name_camel {
fn data(&self) -> Vec<u8> {
let mut d = #sighash_tts.to_vec();
d.append(&mut self.try_to_vec().expect("Should always serialize"));
d
impl anchor_lang::Discriminator for #ix_name_camel {
const DISCRIMINATOR: [u8; 8] = #sighash_tts;
}
impl anchor_lang::InstructionData for #ix_name_camel {}
impl anchor_lang::Owner for #ix_name_camel {
fn owner() -> Pubkey {
ID
}
}
}
@ -138,11 +142,13 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
let sighash_tts: proc_macro2::TokenStream =
format!("{:?}", sighash_arr).parse().unwrap();
quote! {
impl anchor_lang::InstructionData for #ix_name_camel {
fn data(&self) -> Vec<u8> {
let mut d = #sighash_tts.to_vec();
d.append(&mut self.try_to_vec().expect("Should always serialize"));
d
impl anchor_lang::Discriminator for #ix_name_camel {
const DISCRIMINATOR: [u8; 8] = #sighash_tts;
}
impl anchor_lang::InstructionData for #ix_name_camel {}
impl anchor_lang::Owner for #ix_name_camel {
fn owner() -> Pubkey {
ID
}
}
}