coral-xyz / anchor

⚓ Solana Sealevel Framework
https://anchor-lang.com
Apache License 2.0
3.55k stars 1.31k forks source link

lang: Produce compile error if accounts context instruction definition doesn't match instruction #453

Open armaniferrante opened 3 years ago

armaniferrante commented 3 years ago

Currently a runtime error is produced. A compile time error would be better.

fanatid commented 3 years ago

I'm not sure that I understand accounts context instruction definition doesn't match instruction. Can you show an example with accounts context?

armaniferrante commented 3 years ago

The following should produce a compile time error.

#[program]
pub mod myprogram {
   pub fn my_ix(ctx: Context<MyIx>, arg: u8) {...}
}

#[derive(Accounts)]
#[instruction(arg1: u64, arg2: u8)]
pub struct MyIx {
   ...
}
fanatid commented 3 years ago

I checked the code and noticed that accounts instruction and method arguments have the same struct actually. For accounts instruction struct defined inside Accounts::try_accounts method. Do you think it's possible to reuse struct and deserialized output? This should reduce program size and improve performance.

I think the simplest way is to add optionally parsed data, but this does not look the best solution:

struct Empty;

impl borsh::de::BorshDeserialize for Empty {
    fn deserialize(buf: &mut &[u8]) -> Result<Self> {
        Ok(Empty)
    }
}

pub trait Accounts<'info, T: borsh::de::BorshDeserialize = Empty>: ToAccountMetas + ToAccountInfos<'info> + Sized {
    fn try_accounts(
        program_id: &Pubkey, 
        accounts: &mut &[AccountInfo<'info>], 
        ix_data: &[u8],
        parsed_data: Option<T>
    ) -> Result<Self, ProgramError>;
}