idl.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. // The Pubkey that is stored as the 'authority' on the IdlAccount when the authority
  30. // is "erased".
  31. pub const ERASED_AUTHORITY: Pubkey = Pubkey::new_from_array([0u8; 32]);
  32. #[derive(AnchorSerialize, AnchorDeserialize)]
  33. pub enum IdlInstruction {
  34. // One time initializer for creating the program's idl account.
  35. Create { data_len: u64 },
  36. // Creates a new IDL account buffer. Can be called several times.
  37. CreateBuffer,
  38. // Appends the given data to the end of the idl account buffer.
  39. Write { data: Vec<u8> },
  40. // Sets a new data buffer for the IdlAccount.
  41. SetBuffer,
  42. // Sets a new authority on the IdlAccount.
  43. SetAuthority { new_authority: Pubkey },
  44. }
  45. // Accounts for the Create instruction.
  46. pub type IdlCreateAccounts<'info> = crate::ctor::Ctor<'info>;
  47. // Accounts for Idl instructions.
  48. #[derive(Accounts)]
  49. pub struct IdlAccounts<'info> {
  50. #[account(mut, has_one = authority)]
  51. #[allow(deprecated)]
  52. pub idl: ProgramAccount<'info, IdlAccount>,
  53. #[account(constraint = authority.key != &ERASED_AUTHORITY)]
  54. pub authority: Signer<'info>,
  55. }
  56. // Accounts for creating an idl buffer.
  57. #[derive(Accounts)]
  58. pub struct IdlCreateBuffer<'info> {
  59. #[account(zero)]
  60. #[allow(deprecated)]
  61. pub buffer: ProgramAccount<'info, IdlAccount>,
  62. #[account(constraint = authority.key != &ERASED_AUTHORITY)]
  63. pub authority: Signer<'info>,
  64. }
  65. // Accounts for upgrading the canonical IdlAccount with the buffer.
  66. #[derive(Accounts)]
  67. pub struct IdlSetBuffer<'info> {
  68. // The buffer with the new idl data.
  69. #[account(mut, constraint = buffer.authority == idl.authority)]
  70. #[allow(deprecated)]
  71. pub buffer: ProgramAccount<'info, IdlAccount>,
  72. // The idl account to be updated with the buffer's data.
  73. #[account(mut, has_one = authority)]
  74. #[allow(deprecated)]
  75. pub idl: ProgramAccount<'info, IdlAccount>,
  76. #[account(constraint = authority.key != &ERASED_AUTHORITY)]
  77. pub authority: Signer<'info>,
  78. }
  79. // The account holding a program's IDL. This is stored on chain so that clients
  80. // can fetch it and generate a client with nothing but a program's ID.
  81. //
  82. // Note: we use the same account for the "write buffer", similar to the
  83. // bpf upgradeable loader's mechanism.
  84. #[account("internal")]
  85. #[derive(Debug)]
  86. pub struct IdlAccount {
  87. // Address that can modify the IDL.
  88. pub authority: Pubkey,
  89. // Compressed idl bytes.
  90. pub data: Vec<u8>,
  91. }
  92. impl IdlAccount {
  93. pub fn address(program_id: &Pubkey) -> Pubkey {
  94. let program_signer = Pubkey::find_program_address(&[], program_id).0;
  95. Pubkey::create_with_seed(&program_signer, IdlAccount::seed(), program_id)
  96. .expect("Seed is always valid")
  97. }
  98. pub fn seed() -> &'static str {
  99. "anchor:idl"
  100. }
  101. }