idl.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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. use crate::prelude::*;
  20. use solana_program::pubkey::Pubkey;
  21. // The first 8 bytes of an instruction to create or modify the IDL account. This
  22. // instruction is defined outside the main program's instruction enum, so that
  23. // the enum variant tags can align with function source order.
  24. //
  25. // Sha256(anchor:idl)[..8];
  26. pub const IDL_IX_TAG: u64 = 0x0a69e9a778bcf440;
  27. pub const IDL_IX_TAG_LE: [u8; 8] = IDL_IX_TAG.to_le_bytes();
  28. // The Pubkey that is stored as the 'authority' on the IdlAccount when the authority
  29. // is "erased".
  30. pub const ERASED_AUTHORITY: Pubkey = Pubkey::new_from_array([0u8; 32]);
  31. #[derive(AnchorSerialize, AnchorDeserialize)]
  32. pub enum IdlInstruction {
  33. // One time initializer for creating the program's idl account.
  34. Create { data_len: u64 },
  35. // Creates a new IDL account buffer. Can be called several times.
  36. CreateBuffer,
  37. // Appends the given data to the end of the idl account buffer.
  38. Write { data: Vec<u8> },
  39. // Sets a new data buffer for the IdlAccount.
  40. SetBuffer,
  41. // Sets a new authority on the IdlAccount.
  42. SetAuthority { new_authority: Pubkey },
  43. Close,
  44. // Increases account size for accounts that need over 10kb.
  45. Resize { data_len: u64 },
  46. }
  47. // The account holding a program's IDL. This is stored on chain so that clients
  48. // can fetch it and generate a client with nothing but a program's ID.
  49. //
  50. // Note: we use the same account for the "write buffer", similar to the
  51. // bpf upgradeable loader's mechanism.
  52. //
  53. // TODO: IdlAccount exists here only because it's needed by the CLI, the IDL
  54. // itself uses an IdlAccount defined inside the program itself, see program/idl.rs.
  55. // Ideally it would be deleted and a better solution for sharing the type with CLI
  56. // could be found.
  57. #[account("internal")]
  58. #[derive(Debug)]
  59. pub struct IdlAccount {
  60. // Address that can modify the IDL.
  61. pub authority: Pubkey,
  62. // Length of compressed idl bytes.
  63. pub data_len: u32,
  64. // Followed by compressed idl bytes.
  65. }
  66. impl IdlAccount {
  67. pub fn address(program_id: &Pubkey) -> Pubkey {
  68. let program_signer = Pubkey::find_program_address(&[], program_id).0;
  69. Pubkey::create_with_seed(&program_signer, IdlAccount::seed(), program_id)
  70. .expect("Seed is always valid")
  71. }
  72. pub fn seed() -> &'static str {
  73. "anchor:idl"
  74. }
  75. }