idl.rs 3.4 KB

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