lib.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. //! This example demonstrates the use of zero copy deserialization for accounts.
  2. //! The main noticeable benefit one achieves using zero copy is the ability
  3. //! to create accounts larger than the size of the stack or heap, as is
  4. //! demonstrated by the event queue in this example.
  5. use anchor_lang::prelude::*;
  6. #[program]
  7. pub mod zero_copy {
  8. use super::*;
  9. #[state(zero_copy)]
  10. pub struct Globals {
  11. pub authority: Pubkey,
  12. // The solana runtime currently restricts how much one can resize an
  13. // account on CPI to ~10240 bytes. State accounts are program derived
  14. // addresses, which means its max size is limited by this restriction
  15. // (i.e., this is not an Anchor specific issue).
  16. //
  17. // As a result, we only use 250 events here.
  18. //
  19. // For larger zero-copy data structures, one must use non-state anchor
  20. // accounts, as is demonstrated below.
  21. pub events: [Event; 250],
  22. }
  23. impl Globals {
  24. // Note that the `new` constructor is different from non-zero-copy
  25. // state accounts. Namely, it takes in a `&mut self` parameter.
  26. pub fn new(&mut self, ctx: Context<New>) -> ProgramResult {
  27. self.authority = *ctx.accounts.authority.key;
  28. Ok(())
  29. }
  30. #[access_control(auth(&self, &ctx))]
  31. pub fn set_event(
  32. &mut self,
  33. ctx: Context<SetEvent>,
  34. idx: u32,
  35. event: RpcEvent,
  36. ) -> ProgramResult {
  37. self.events[idx as usize] = event.into();
  38. Ok(())
  39. }
  40. }
  41. pub fn create_foo(ctx: Context<CreateFoo>) -> ProgramResult {
  42. let foo = &mut ctx.accounts.foo.load_init()?;
  43. foo.authority = *ctx.accounts.authority.key;
  44. foo.set_second_authority(ctx.accounts.authority.key);
  45. Ok(())
  46. }
  47. pub fn update_foo(ctx: Context<UpdateFoo>, data: u64) -> ProgramResult {
  48. let mut foo = ctx.accounts.foo.load_mut()?;
  49. foo.data = data;
  50. Ok(())
  51. }
  52. pub fn update_foo_second(ctx: Context<UpdateFooSecond>, second_data: u64) -> ProgramResult {
  53. let mut foo = ctx.accounts.foo.load_mut()?;
  54. foo.second_data = second_data;
  55. Ok(())
  56. }
  57. pub fn create_bar(ctx: Context<CreateBar>) -> ProgramResult {
  58. let bar = &mut ctx.accounts.bar.load_init()?;
  59. bar.authority = *ctx.accounts.authority.key;
  60. Ok(())
  61. }
  62. pub fn update_bar(ctx: Context<UpdateBar>, data: u64) -> ProgramResult {
  63. let bar = &mut ctx.accounts.bar.load_mut()?;
  64. bar.data = data;
  65. Ok(())
  66. }
  67. pub fn create_large_account(_ctx: Context<CreateLargeAccount>) -> ProgramResult {
  68. Ok(())
  69. }
  70. pub fn update_large_account(
  71. ctx: Context<UpdateLargeAccount>,
  72. idx: u32,
  73. data: u64,
  74. ) -> ProgramResult {
  75. let event_q = &mut ctx.accounts.event_q.load_mut()?;
  76. event_q.events[idx as usize] = Event {
  77. data,
  78. from: *ctx.accounts.from.key,
  79. };
  80. Ok(())
  81. }
  82. }
  83. #[derive(Accounts)]
  84. pub struct New<'info> {
  85. #[account(signer)]
  86. authority: AccountInfo<'info>,
  87. }
  88. #[derive(Accounts)]
  89. pub struct SetEvent<'info> {
  90. #[account(signer)]
  91. authority: AccountInfo<'info>,
  92. }
  93. #[derive(Accounts)]
  94. pub struct CreateFoo<'info> {
  95. #[account(init)]
  96. foo: Loader<'info, Foo>,
  97. #[account(signer)]
  98. authority: AccountInfo<'info>,
  99. rent: Sysvar<'info, Rent>,
  100. }
  101. #[derive(Accounts)]
  102. pub struct UpdateFoo<'info> {
  103. #[account(mut, has_one = authority)]
  104. foo: Loader<'info, Foo>,
  105. #[account(signer)]
  106. authority: AccountInfo<'info>,
  107. }
  108. #[derive(Accounts)]
  109. pub struct UpdateFooSecond<'info> {
  110. #[account(mut, "&foo.load()?.get_second_authority() == second_authority.key")]
  111. foo: Loader<'info, Foo>,
  112. #[account(signer)]
  113. second_authority: AccountInfo<'info>,
  114. }
  115. #[derive(Accounts)]
  116. pub struct CreateBar<'info> {
  117. #[account(init, associated = authority, with = foo)]
  118. bar: Loader<'info, Bar>,
  119. #[account(signer)]
  120. authority: AccountInfo<'info>,
  121. foo: Loader<'info, Foo>,
  122. rent: Sysvar<'info, Rent>,
  123. system_program: AccountInfo<'info>,
  124. }
  125. #[derive(Accounts)]
  126. pub struct UpdateBar<'info> {
  127. #[account(mut, associated = authority, with = foo, has_one = authority)]
  128. bar: Loader<'info, Bar>,
  129. #[account(signer)]
  130. authority: AccountInfo<'info>,
  131. foo: Loader<'info, Foo>,
  132. }
  133. #[derive(Accounts)]
  134. pub struct CreateLargeAccount<'info> {
  135. #[account(init)]
  136. event_q: Loader<'info, EventQ>,
  137. rent: Sysvar<'info, Rent>,
  138. }
  139. #[derive(Accounts)]
  140. pub struct UpdateLargeAccount<'info> {
  141. #[account(mut)]
  142. event_q: Loader<'info, EventQ>,
  143. #[account(signer)]
  144. from: AccountInfo<'info>,
  145. }
  146. #[account(zero_copy)]
  147. pub struct Foo {
  148. pub authority: Pubkey,
  149. pub data: u64,
  150. pub second_data: u64,
  151. #[accessor(Pubkey)] // The `accessor` api will likely be removed.
  152. pub second_authority: [u8; 32],
  153. }
  154. #[associated(zero_copy)]
  155. #[derive(Default)]
  156. pub struct Bar {
  157. pub authority: Pubkey,
  158. pub data: u64,
  159. }
  160. #[account(zero_copy)]
  161. pub struct EventQ {
  162. pub events: [Event; 25000],
  163. }
  164. #[zero_copy]
  165. pub struct Event {
  166. pub from: Pubkey,
  167. pub data: u64,
  168. }
  169. // A separate type is used for the RPC interface for two main reasons.
  170. //
  171. // 1. AnchorSerialize and AnchorDeserialize must be derived. Anchor requires
  172. // *all* instructions to implement the AnchorSerialize and AnchorDeserialize
  173. // traits, so any types in method signatures must as well.
  174. // 2. All types for zero copy deserialization are `#[repr(packed)]`. However,
  175. // the implementation of AnchorSerialize (i.e. borsh), uses references
  176. // to the fields it serializes. So if we were to just throw tehse derives
  177. // onto the other `Event` struct, we would have references to
  178. // `#[repr(packed)]` fields, which is unsafe. To avoid the unsafeness, we
  179. // just use a separate type.
  180. #[derive(AnchorSerialize, AnchorDeserialize)]
  181. pub struct RpcEvent {
  182. pub from: Pubkey,
  183. pub data: u64,
  184. }
  185. impl From<RpcEvent> for Event {
  186. fn from(e: RpcEvent) -> Event {
  187. Event {
  188. from: e.from,
  189. data: e.data,
  190. }
  191. }
  192. }
  193. fn auth(globals: &Globals, ctx: &Context<SetEvent>) -> ProgramResult {
  194. if &globals.authority != ctx.accounts.authority.key {
  195. return Err(ProgramError::Custom(1)); // Arbitrary error.
  196. }
  197. Ok(())
  198. }