instruction.rs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. //! Instruction types.
  2. use core::{marker::PhantomData, ops::Deref};
  3. use crate::{account_info::AccountInfo, pubkey::Pubkey};
  4. /// Information about a CPI instruction.
  5. #[derive(Debug, Clone)]
  6. pub struct Instruction<'a, 'b, 'c, 'd>
  7. where
  8. 'a: 'b,
  9. {
  10. /// Public key of the program.
  11. pub program_id: &'c Pubkey,
  12. /// Data expected by the program instruction.
  13. pub data: &'d [u8],
  14. /// Metadata describing accounts that should be passed to the program.
  15. pub accounts: &'b [AccountMeta<'a>],
  16. }
  17. /// Use to query and convey information about the sibling instruction components
  18. /// when calling the `sol_get_processed_sibling_instruction` syscall.
  19. #[repr(C)]
  20. #[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
  21. pub struct ProcessedSiblingInstruction {
  22. /// Length of the instruction data
  23. pub data_len: u64,
  24. /// Number of `AccountMeta` structures
  25. pub accounts_len: u64,
  26. }
  27. /// An `Account` for CPI invocations.
  28. ///
  29. /// This struct contains the same information as an [`AccountInfo`], but has
  30. /// the memory layout as expected by `sol_invoke_signed_c` syscall.
  31. #[repr(C)]
  32. #[derive(Clone)]
  33. pub struct Account<'a> {
  34. // Public key of the account.
  35. key: *const Pubkey,
  36. // Number of lamports owned by this account.
  37. lamports: *const u64,
  38. // Length of data in bytes.
  39. data_len: u64,
  40. // On-chain data within this account.
  41. data: *const u8,
  42. // Program that owns this account.
  43. owner: *const Pubkey,
  44. // The epoch at which this account will next owe rent.
  45. rent_epoch: u64,
  46. // Transaction was signed by this account's key?
  47. is_signer: bool,
  48. // Is the account writable?
  49. is_writable: bool,
  50. // This account's data contains a loaded program (and is now read-only).
  51. executable: bool,
  52. /// The pointers to the `AccountInfo` data are only valid for as long as the
  53. /// `&'a AccountInfo` lives. Instead of holding a reference to the actual `AccountInfo`,
  54. /// which would increase the size of the type, we claim to hold a reference without
  55. /// actually holding one using a `PhantomData<&'a AccountInfo>`.
  56. _account_info: PhantomData<&'a AccountInfo>,
  57. }
  58. #[inline(always)]
  59. const fn offset<T, U>(ptr: *const T, offset: usize) -> *const U {
  60. unsafe { (ptr as *const u8).add(offset) as *const U }
  61. }
  62. impl<'a> From<&'a AccountInfo> for Account<'a> {
  63. fn from(account: &'a AccountInfo) -> Self {
  64. Account {
  65. key: offset(account.raw, 8),
  66. lamports: offset(account.raw, 72),
  67. data_len: account.data_len() as u64,
  68. data: offset(account.raw, 88),
  69. owner: offset(account.raw, 40),
  70. // The `rent_epoch` field is not present in the `AccountInfo` struct,
  71. // since the value occurs after the variable data of the account in
  72. // the runtime input data.
  73. rent_epoch: 0,
  74. is_signer: account.is_signer(),
  75. is_writable: account.is_writable(),
  76. executable: account.executable(),
  77. _account_info: PhantomData::<&'a AccountInfo>,
  78. }
  79. }
  80. }
  81. /// Describes a single account read or written by a program during instruction
  82. /// execution.
  83. ///
  84. /// When constructing an [`Instruction`], a list of all accounts that may be
  85. /// read or written during the execution of that instruction must be supplied.
  86. /// Any account that may be mutated by the program during execution, either its
  87. /// data or metadata such as held lamports, must be writable.
  88. ///
  89. /// Note that because the Solana runtime schedules parallel transaction
  90. /// execution around which accounts are writable, care should be taken that only
  91. /// accounts which actually may be mutated are specified as writable.
  92. #[repr(C)]
  93. #[derive(Debug, Clone)]
  94. pub struct AccountMeta<'a> {
  95. /// Public key of the account.
  96. pub pubkey: &'a Pubkey,
  97. /// Indicates whether the account is writable or not.
  98. pub is_writable: bool,
  99. /// Indicates whether the account signed the instruction or not.
  100. pub is_signer: bool,
  101. }
  102. impl<'a> AccountMeta<'a> {
  103. /// Creates a new `AccountMeta`.
  104. #[inline(always)]
  105. pub const fn new(pubkey: &'a Pubkey, is_writable: bool, is_signer: bool) -> Self {
  106. Self {
  107. pubkey,
  108. is_writable,
  109. is_signer,
  110. }
  111. }
  112. /// Creates a new read-only `AccountMeta`.
  113. #[inline(always)]
  114. pub const fn readonly(pubkey: &'a Pubkey) -> Self {
  115. Self::new(pubkey, false, false)
  116. }
  117. /// Creates a new writable `AccountMeta`.
  118. #[inline(always)]
  119. pub const fn writable(pubkey: &'a Pubkey) -> Self {
  120. Self::new(pubkey, true, false)
  121. }
  122. /// Creates a new read-only and signer `AccountMeta`.
  123. #[inline(always)]
  124. pub const fn readonly_signer(pubkey: &'a Pubkey) -> Self {
  125. Self::new(pubkey, false, true)
  126. }
  127. /// Creates a new writable and signer `AccountMeta`.
  128. #[inline(always)]
  129. pub const fn writable_signer(pubkey: &'a Pubkey) -> Self {
  130. Self::new(pubkey, true, true)
  131. }
  132. }
  133. impl<'a> From<&'a AccountInfo> for AccountMeta<'a> {
  134. fn from(account: &'a crate::account_info::AccountInfo) -> Self {
  135. AccountMeta::new(account.key(), account.is_writable(), account.is_signer())
  136. }
  137. }
  138. /// Represents a signer seed.
  139. ///
  140. /// This struct contains the same information as a `[u8]`, but
  141. /// has the memory layout as expected by `sol_invoke_signed_c`
  142. /// syscall.
  143. #[repr(C)]
  144. #[derive(Debug, Clone)]
  145. pub struct Seed<'a> {
  146. /// Seed bytes.
  147. pub(crate) seed: *const u8,
  148. /// Length of the seed bytes.
  149. pub(crate) len: u64,
  150. /// The pointer to the seed bytes is only valid while the `&'a [u8]` lives. Instead
  151. /// of holding a reference to the actual `[u8]`, which would increase the size of the
  152. /// type, we claim to hold a reference without actually holding one using a
  153. /// `PhantomData<&'a [u8]>`.
  154. _bytes: PhantomData<&'a [u8]>,
  155. }
  156. impl<'a> From<&'a [u8]> for Seed<'a> {
  157. fn from(value: &'a [u8]) -> Self {
  158. Self {
  159. seed: value.as_ptr(),
  160. len: value.len() as u64,
  161. _bytes: PhantomData::<&[u8]>,
  162. }
  163. }
  164. }
  165. impl<'a, const SIZE: usize> From<&'a [u8; SIZE]> for Seed<'a> {
  166. fn from(value: &'a [u8; SIZE]) -> Self {
  167. Self {
  168. seed: value.as_ptr(),
  169. len: value.len() as u64,
  170. _bytes: PhantomData::<&[u8]>,
  171. }
  172. }
  173. }
  174. impl Deref for Seed<'_> {
  175. type Target = [u8];
  176. fn deref(&self) -> &Self::Target {
  177. unsafe { core::slice::from_raw_parts(self.seed, self.len as usize) }
  178. }
  179. }
  180. /// Represents a [program derived address][pda] (PDA) signer controlled by the
  181. /// calling program.
  182. ///
  183. /// [pda]: https://solana.com/docs/core/cpi#program-derived-addresses
  184. #[repr(C)]
  185. #[derive(Debug, Clone)]
  186. pub struct Signer<'a, 'b> {
  187. /// Signer seeds.
  188. pub(crate) seeds: *const Seed<'a>,
  189. /// Number of seeds.
  190. pub(crate) len: u64,
  191. /// The pointer to the seeds is only valid while the `&'b [Seed<'a>]` lives. Instead
  192. /// of holding a reference to the actual `[Seed<'a>]`, which would increase the size
  193. /// of the type, we claim to hold a reference without actually holding one using a
  194. /// `PhantomData<&'b [Seed<'a>]>`.
  195. _seeds: PhantomData<&'b [Seed<'a>]>,
  196. }
  197. impl<'a, 'b> From<&'b [Seed<'a>]> for Signer<'a, 'b> {
  198. fn from(value: &'b [Seed<'a>]) -> Self {
  199. Self {
  200. seeds: value.as_ptr(),
  201. len: value.len() as u64,
  202. _seeds: PhantomData::<&'b [Seed<'a>]>,
  203. }
  204. }
  205. }
  206. impl<'a, 'b, const SIZE: usize> From<&'b [Seed<'a>; SIZE]> for Signer<'a, 'b> {
  207. fn from(value: &'b [Seed<'a>; SIZE]) -> Self {
  208. Self {
  209. seeds: value.as_ptr(),
  210. len: value.len() as u64,
  211. _seeds: PhantomData::<&'b [Seed<'a>]>,
  212. }
  213. }
  214. }
  215. /// Convenience macro for constructing a `Signer` from a list of seeds
  216. /// represented as byte slices.
  217. ///
  218. /// # Example
  219. ///
  220. /// Creating a signer for a PDA with a single seed and bump value:
  221. /// ```
  222. /// use pinocchio::signer;
  223. ///
  224. /// let pda_bump = 255;
  225. /// let signer = signer!(b"seed", &[pda_bump]);
  226. /// ```
  227. #[macro_export]
  228. #[deprecated(since = "0.8.0", note = "Use `seeds!` macro instead")]
  229. macro_rules! signer {
  230. ( $($seed:expr),* ) => {
  231. $crate::instruction::Signer::from(&[$(
  232. $seed.into(),
  233. )*])
  234. };
  235. }
  236. /// Convenience macro for constructing a `[Seed; N]` array from a list of seeds.
  237. ///
  238. /// # Example
  239. ///
  240. /// Creating seeds array and signer for a PDA with a single seed and bump value:
  241. /// ```
  242. /// use pinocchio::{seeds, instruction::Signer};
  243. /// use pinocchio::pubkey::Pubkey;
  244. ///
  245. /// let pda_bump = 0xffu8;
  246. /// let pda_ref = &[pda_bump]; // prevent temporary value being freed
  247. /// let example_key = Pubkey::default();
  248. /// let seeds = seeds!(b"seed", &example_key, pda_ref);
  249. /// let signer = Signer::from(&seeds);
  250. /// ```
  251. #[macro_export]
  252. macro_rules! seeds {
  253. ( $($seed:expr),* ) => {
  254. [$(
  255. $crate::instruction::Seed::from($seed),
  256. )*]
  257. };
  258. }