idl.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. //! Defines the instructions and account state used to store a program's
  2. //! IDL on-chain at a canonical account address, which can be derived as a
  3. //! function of nothing other than the program's ID.
  4. //!
  5. //! It can be upgraded in a way similar to a BPF upgradeable program. That is,
  6. //! one may invoke the `IdlInstruction::CreateBuffer` instruction to create
  7. //! a buffer, `IdlInstruction::Write` to write a new IDL into it, and then
  8. //! `IdlInstruction::SetBuffer` to copy the IDL into the program's canonical
  9. //! IDL account. In order to perform this upgrade, the buffer's `authority`
  10. //! must match the canonical IDL account's authority.
  11. //!
  12. //! Because the IDL can be larger than the max transaction size, the transaction
  13. //! must be broken up into several pieces and stored into the IDL account with
  14. //! multiple transactions via the `Write` instruction to continuously append to
  15. //! the account's IDL data buffer.
  16. //!
  17. //! Note that IDL account instructions are automatically inserted into all
  18. //! Anchor programs. To remove them, one can use the `no-idl` feature.
  19. #[allow(deprecated)]
  20. use crate::accounts::program_account::ProgramAccount;
  21. use crate::prelude::*;
  22. use solana_program::pubkey::Pubkey;
  23. // The first 8 bytes of an instruction to create or modify the IDL account. This
  24. // instruction is defined outside the main program's instruction enum, so that
  25. // the enum variant tags can align with function source order.
  26. //
  27. // Sha256(anchor:idl)[..8];
  28. pub const IDL_IX_TAG: u64 = 0x0a69e9a778bcf440;
  29. #[derive(AnchorSerialize, AnchorDeserialize)]
  30. pub enum IdlInstruction {
  31. // One time initializer for creating the program's idl account.
  32. Create { data_len: u64 },
  33. // Creates a new IDL account buffer. Can be called several times.
  34. CreateBuffer,
  35. // Appends the given data to the end of the idl account buffer.
  36. Write { data: Vec<u8> },
  37. // Sets a new data buffer for the IdlAccount.
  38. SetBuffer,
  39. // Sets a new authority on the IdlAccount.
  40. SetAuthority { new_authority: Pubkey },
  41. }
  42. // Accounts for the Create instruction.
  43. pub type IdlCreateAccounts<'info> = crate::ctor::Ctor<'info>;
  44. // Accounts for Idl instructions.
  45. #[derive(Accounts)]
  46. pub struct IdlAccounts<'info> {
  47. #[account(mut, has_one = authority)]
  48. #[allow(deprecated)]
  49. pub idl: ProgramAccount<'info, IdlAccount>,
  50. #[account(signer, constraint = authority.key != &Pubkey::new_from_array([0u8; 32]))]
  51. pub authority: AccountInfo<'info>,
  52. }
  53. // Accounts for creating an idl buffer.
  54. #[derive(Accounts)]
  55. pub struct IdlCreateBuffer<'info> {
  56. #[account(zero)]
  57. #[allow(deprecated)]
  58. pub buffer: ProgramAccount<'info, IdlAccount>,
  59. #[account(signer, constraint = authority.key != &Pubkey::new_from_array([0u8; 32]))]
  60. pub authority: AccountInfo<'info>,
  61. }
  62. // Accounts for upgrading the canonical IdlAccount with the buffer.
  63. #[derive(Accounts)]
  64. pub struct IdlSetBuffer<'info> {
  65. // The buffer with the new idl data.
  66. #[account(mut, constraint = buffer.authority == idl.authority)]
  67. #[allow(deprecated)]
  68. pub buffer: ProgramAccount<'info, IdlAccount>,
  69. // The idl account to be updated with the buffer's data.
  70. #[account(mut, has_one = authority)]
  71. #[allow(deprecated)]
  72. pub idl: ProgramAccount<'info, IdlAccount>,
  73. #[account(signer, constraint = authority.key != &Pubkey::new_from_array([0u8; 32]))]
  74. pub authority: AccountInfo<'info>,
  75. }
  76. // The account holding a program's IDL. This is stored on chain so that clients
  77. // can fetch it and generate a client with nothing but a program's ID.
  78. //
  79. // Note: we use the same account for the "write buffer", similar to the
  80. // bpf upgradeable loader's mechanism.
  81. #[account("internal")]
  82. #[derive(Debug)]
  83. pub struct IdlAccount {
  84. // Address that can modify the IDL.
  85. pub authority: Pubkey,
  86. // Compressed idl bytes.
  87. pub data: Vec<u8>,
  88. }
  89. impl IdlAccount {
  90. pub fn address(program_id: &Pubkey) -> Pubkey {
  91. let program_signer = Pubkey::find_program_address(&[], program_id).0;
  92. Pubkey::create_with_seed(&program_signer, IdlAccount::seed(), program_id)
  93. .expect("Seed is always valid")
  94. }
  95. pub fn seed() -> &'static str {
  96. "anchor:idl"
  97. }
  98. }