program.rs 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366
  1. use crate::parser;
  2. use crate::{IxArg, Program, State, StateIx};
  3. use heck::{CamelCase, SnakeCase};
  4. use quote::quote;
  5. // Namespace for calculating state instruction sighash signatures.
  6. const SIGHASH_STATE_NAMESPACE: &str = "state";
  7. // Namespace for calculating instruction sighash signatures for any instruction
  8. // not affecting program state.
  9. const SIGHASH_GLOBAL_NAMESPACE: &str = "global";
  10. pub fn generate(program: Program) -> proc_macro2::TokenStream {
  11. let mod_name = &program.name;
  12. let dispatch = generate_dispatch(&program);
  13. let handlers_non_inlined = generate_non_inlined_handlers(&program);
  14. let methods = generate_methods(&program);
  15. let ixs = generate_ixs(&program);
  16. let cpi = generate_cpi(&program);
  17. let accounts = generate_accounts(&program);
  18. quote! {
  19. // TODO: remove once we allow segmented paths in `Accounts` structs.
  20. use #mod_name::*;
  21. #[cfg(not(feature = "no-entrypoint"))]
  22. anchor_lang::solana_program::entrypoint!(entry);
  23. /// The Anchor codegen exposes a programming model where a user defines
  24. /// a set of methods inside of a `#[program]` module in a way similar
  25. /// to writing RPC request handlers. The macro then generates a bunch of
  26. /// code wrapping these user defined methods into something that can be
  27. /// executed on Solana.
  28. ///
  29. /// These methods fall into one of three categories, each of which
  30. /// can be considered a different "namespace" of the program.
  31. ///
  32. /// 1) Global methods - regular methods inside of the `#[program]`.
  33. /// 2) State methods - associated methods inside a `#[state]` struct.
  34. /// 3) Interface methods - methods inside a strait struct's
  35. /// implementation of an `#[interface]` trait.
  36. ///
  37. /// Care must be taken by the codegen to prevent collisions between
  38. /// methods in these different namespaces. For this reason, Anchor uses
  39. /// a variant of sighash to perform method dispatch, rather than
  40. /// something like a simple enum variant discriminator.
  41. ///
  42. /// The execution flow of the generated code can be roughly outlined:
  43. ///
  44. /// * Start program via the entrypoint.
  45. /// * Strip method identifier off the first 8 bytes of the instruction
  46. /// data and invoke the identified method. The method identifier
  47. /// is a variant of sighash. See docs.rs for `anchor_lang` for details.
  48. /// * If the method identifier is an IDL identifier, execute the IDL
  49. /// instructions, which are a special set of hardcoded instructions
  50. /// baked into every Anchor program. Then exit.
  51. /// * Otherwise, the method identifier is for a user defined
  52. /// instruction, i.e., one of the methods in the user defined
  53. /// `#[program]` module. Perform method dispatch, i.e., execute the
  54. /// big match statement mapping method identifier to method handler
  55. /// wrapper.
  56. /// * Run the method handler wrapper. This wraps the code the user
  57. /// actually wrote, deserializing the accounts, constructing the
  58. /// context, invoking the user's code, and finally running the exit
  59. /// routine, which typically persists account changes.
  60. ///
  61. /// The `entry` function here, defines the standard entry to a Solana
  62. /// program, where execution begins.
  63. #[cfg(not(feature = "no-entrypoint"))]
  64. fn entry(program_id: &Pubkey, accounts: &[AccountInfo], ix_data: &[u8]) -> ProgramResult {
  65. if ix_data.len() < 8 {
  66. return Err(ProgramError::Custom(99));
  67. }
  68. // Split the instruction data into the first 8 byte method
  69. // identifier (sighash) and the serialized instruction data.
  70. let mut ix_data: &[u8] = ix_data;
  71. let sighash: [u8; 8] = {
  72. let mut sighash: [u8; 8] = [0; 8];
  73. sighash.copy_from_slice(&ix_data[..8]);
  74. ix_data = &ix_data[8..];
  75. sighash
  76. };
  77. dispatch(program_id, accounts, sighash, ix_data)
  78. .map_err(|e| {
  79. anchor_lang::solana_program::msg!(&e.to_string());
  80. e
  81. })
  82. }
  83. #dispatch
  84. /// Create a private module to not clutter the program's namespace.
  85. /// Defines an entrypoint for each individual instruction handler
  86. /// wrapper.
  87. mod __private {
  88. use super::*;
  89. #handlers_non_inlined
  90. }
  91. #accounts
  92. #ixs
  93. #methods
  94. #cpi
  95. }
  96. }
  97. pub fn generate_dispatch(program: &Program) -> proc_macro2::TokenStream {
  98. // Dispatch the state constructor.
  99. let ctor_state_dispatch_arm = match &program.state {
  100. None => quote! { /* no-op */ },
  101. Some(state) => match state.ctor_and_anchor.is_some() {
  102. false => quote! {},
  103. true => {
  104. let variant_arm = generate_ctor_variant(state);
  105. let ctor_args = generate_ctor_args(state);
  106. let ix_name: proc_macro2::TokenStream =
  107. generate_ctor_variant_name().parse().unwrap();
  108. let sighash_arr = sighash_ctor();
  109. let sighash_tts: proc_macro2::TokenStream =
  110. format!("{:?}", sighash_arr).parse().unwrap();
  111. quote! {
  112. #sighash_tts => {
  113. let ix = instruction::state::#ix_name::deserialize(&mut ix_data)
  114. .map_err(|_| ProgramError::Custom(1))?; // todo: error code
  115. let instruction::state::#variant_arm = ix;
  116. __private::__state::__ctor(program_id, accounts, #(#ctor_args),*)
  117. }
  118. }
  119. }
  120. },
  121. };
  122. // Dispatch the state impl instructions.
  123. let state_dispatch_arms: Vec<proc_macro2::TokenStream> = match &program.state {
  124. None => vec![],
  125. Some(s) => s
  126. .impl_block_and_methods
  127. .as_ref()
  128. .map(|(_impl_block, methods)| {
  129. methods
  130. .iter()
  131. .map(|ix: &crate::StateIx| {
  132. let ix_arg_names: Vec<&syn::Ident> =
  133. ix.args.iter().map(|arg| &arg.name).collect();
  134. let name = &ix.raw_method.sig.ident.to_string();
  135. let ix_method_name: proc_macro2::TokenStream =
  136. { format!("__{}", name).parse().unwrap() };
  137. let variant_arm =
  138. generate_ix_variant(ix.raw_method.sig.ident.to_string(), &ix.args);
  139. let ix_name = generate_ix_variant_name(ix.raw_method.sig.ident.to_string());
  140. let sighash_arr = sighash(SIGHASH_STATE_NAMESPACE, &name);
  141. let sighash_tts: proc_macro2::TokenStream =
  142. format!("{:?}", sighash_arr).parse().unwrap();
  143. quote! {
  144. #sighash_tts => {
  145. let ix = instruction::state::#ix_name::deserialize(&mut ix_data)
  146. .map_err(|_| ProgramError::Custom(1))?; // todo: error code
  147. let instruction::state::#variant_arm = ix;
  148. __private::__state::#ix_method_name(program_id, accounts, #(#ix_arg_names),*)
  149. }
  150. }
  151. })
  152. .collect()
  153. })
  154. .unwrap_or_default(),
  155. };
  156. // Dispatch all trait interface implementations.
  157. let trait_dispatch_arms: Vec<proc_macro2::TokenStream> = match &program.state {
  158. None => vec![],
  159. Some(s) => s
  160. .interfaces
  161. .as_ref()
  162. .map(|interfaces| {
  163. interfaces
  164. .iter()
  165. .flat_map(|iface: &crate::StateInterface| {
  166. iface
  167. .methods
  168. .iter()
  169. .map(|m: &crate::StateIx| {
  170. let ix_arg_names: Vec<&syn::Ident> =
  171. m.args.iter().map(|arg| &arg.name).collect();
  172. let name = &m.raw_method.sig.ident.to_string();
  173. let ix_name: proc_macro2::TokenStream = format!("__{}_{}", iface.trait_name, name).parse().unwrap();
  174. let raw_args: Vec<&syn::PatType> = m
  175. .args
  176. .iter()
  177. .map(|arg: &crate::IxArg| &arg.raw_arg)
  178. .collect();
  179. let sighash_arr = sighash(&iface.trait_name, &m.ident.to_string());
  180. let sighash_tts: proc_macro2::TokenStream =
  181. format!("{:?}", sighash_arr).parse().unwrap();
  182. let args_struct = {
  183. if m.args.is_empty() {
  184. quote! {
  185. #[derive(anchor_lang::AnchorSerialize, anchor_lang::AnchorDeserialize)]
  186. struct Args;
  187. }
  188. } else {
  189. quote! {
  190. #[derive(anchor_lang::AnchorSerialize, anchor_lang::AnchorDeserialize)]
  191. struct Args {
  192. #(#raw_args),*
  193. }
  194. }
  195. }
  196. };
  197. quote! {
  198. #sighash_tts => {
  199. #args_struct
  200. let ix = Args::deserialize(&mut ix_data)
  201. .map_err(|_| ProgramError::Custom(1))?; // todo: error code
  202. let Args {
  203. #(#ix_arg_names),*
  204. } = ix;
  205. __private::__interface::#ix_name(program_id, accounts, #(#ix_arg_names),*)
  206. }
  207. }
  208. })
  209. .collect::<Vec<proc_macro2::TokenStream>>()
  210. })
  211. .collect()
  212. })
  213. .unwrap_or_default()
  214. };
  215. // Dispatch all global instructions.
  216. let global_dispatch_arms: Vec<proc_macro2::TokenStream> = program
  217. .ixs
  218. .iter()
  219. .map(|ix| {
  220. let ix_arg_names: Vec<&syn::Ident> = ix.args.iter().map(|arg| &arg.name).collect();
  221. let ix_method_name = &ix.raw_method.sig.ident;
  222. let ix_name = generate_ix_variant_name(ix.raw_method.sig.ident.to_string());
  223. let sighash_arr = sighash(SIGHASH_GLOBAL_NAMESPACE, &ix_method_name.to_string());
  224. let sighash_tts: proc_macro2::TokenStream =
  225. format!("{:?}", sighash_arr).parse().unwrap();
  226. let variant_arm = generate_ix_variant(ix.raw_method.sig.ident.to_string(), &ix.args);
  227. quote! {
  228. #sighash_tts => {
  229. let ix = instruction::#ix_name::deserialize(&mut ix_data)
  230. .map_err(|_| ProgramError::Custom(1))?; // todo: error code
  231. let instruction::#variant_arm = ix;
  232. __private::__global::#ix_method_name(program_id, accounts, #(#ix_arg_names),*)
  233. }
  234. }
  235. })
  236. .collect();
  237. quote! {
  238. /// Performs method dispatch.
  239. ///
  240. /// Each method in an anchor program is uniquely defined by a namespace
  241. /// and a rust identifier (i.e., the name given to the method). These
  242. /// two pieces can be combined to creater a method identifier,
  243. /// specifically, Anchor uses
  244. ///
  245. /// Sha256("<namespace>::<rust-identifier>")[..8],
  246. ///
  247. /// where the namespace can be one of three types. 1) "global" for a
  248. /// regular instruction, 2) "state" for a state struct instruction
  249. /// handler and 3) a trait namespace (used in combination with the
  250. /// `#[interface]` attribute), which is defined by the trait name, e..
  251. /// `MyTrait`.
  252. ///
  253. /// With this 8 byte identifier, Anchor performs method dispatch,
  254. /// matching the given 8 byte identifier to the associated method
  255. /// handler, which leads to user defined code being eventually invoked.
  256. fn dispatch(program_id: &Pubkey, accounts: &[AccountInfo], sighash: [u8; 8], mut ix_data: &[u8]) -> ProgramResult {
  257. // If the method identifier is the IDL tag, then execute an IDL
  258. // instruction, injected into all Anchor programs.
  259. if cfg!(not(feature = "no-idl")) {
  260. if sighash == anchor_lang::idl::IDL_IX_TAG.to_le_bytes() {
  261. return __private::__idl::__idl_dispatch(program_id, accounts, &ix_data);
  262. }
  263. }
  264. match sighash {
  265. #ctor_state_dispatch_arm
  266. #(#state_dispatch_arms)*
  267. #(#trait_dispatch_arms)*
  268. #(#global_dispatch_arms)*
  269. _ => {
  270. msg!("Fallback functions are not supported. If you have a use case, please file an issue.");
  271. Err(ProgramError::Custom(99))
  272. }
  273. }
  274. }
  275. }
  276. }
  277. // Generate non-inlined wrappers for each instruction handler, since Solana's
  278. // BPF max stack size can't handle reasonable sized dispatch trees without doing
  279. // so.
  280. pub fn generate_non_inlined_handlers(program: &Program) -> proc_macro2::TokenStream {
  281. let program_name = &program.name;
  282. let non_inlined_idl: proc_macro2::TokenStream = {
  283. quote! {
  284. // Entry for all IDL related instructions. Use the "no-idl" feature
  285. // to eliminate this code, for example, if one wants to make the
  286. // IDL no longer mutable or if one doesn't want to store the IDL
  287. // on chain.
  288. #[inline(never)]
  289. #[cfg(not(feature = "no-idl"))]
  290. pub fn __idl_dispatch(program_id: &Pubkey, accounts: &[AccountInfo], idl_ix_data: &[u8]) -> ProgramResult {
  291. let mut accounts = accounts;
  292. let mut data: &[u8] = idl_ix_data;
  293. let ix = anchor_lang::idl::IdlInstruction::deserialize(&mut data)
  294. .map_err(|_| ProgramError::Custom(2))?; // todo
  295. match ix {
  296. anchor_lang::idl::IdlInstruction::Create { data_len } => {
  297. let mut accounts = anchor_lang::idl::IdlCreateAccounts::try_accounts(program_id, &mut accounts)?;
  298. __idl_create_account(program_id, &mut accounts, data_len)?;
  299. accounts.exit(program_id)?;
  300. },
  301. anchor_lang::idl::IdlInstruction::CreateBuffer => {
  302. let mut accounts = anchor_lang::idl::IdlCreateBuffer::try_accounts(program_id, &mut accounts)?;
  303. __idl_create_buffer(program_id, &mut accounts)?;
  304. accounts.exit(program_id)?;
  305. },
  306. anchor_lang::idl::IdlInstruction::Write { data } => {
  307. let mut accounts = anchor_lang::idl::IdlAccounts::try_accounts(program_id, &mut accounts)?;
  308. __idl_write(program_id, &mut accounts, data)?;
  309. accounts.exit(program_id)?;
  310. },
  311. anchor_lang::idl::IdlInstruction::SetAuthority { new_authority } => {
  312. let mut accounts = anchor_lang::idl::IdlAccounts::try_accounts(program_id, &mut accounts)?;
  313. __idl_set_authority(program_id, &mut accounts, new_authority)?;
  314. accounts.exit(program_id)?;
  315. },
  316. anchor_lang::idl::IdlInstruction::SetBuffer => {
  317. let mut accounts = anchor_lang::idl::IdlSetBuffer::try_accounts(program_id, &mut accounts)?;
  318. __idl_set_buffer(program_id, &mut accounts)?;
  319. accounts.exit(program_id)?;
  320. },
  321. }
  322. Ok(())
  323. }
  324. #[inline(never)]
  325. #[cfg(feature = "no-idl")]
  326. pub fn __idl_dispatch(program_id: &Pubkey, accounts: &[AccountInfo], idl_ix_data: &[u8]) -> ProgramResult {
  327. Err(anchor_lang::solana_program::program_error::ProgramError::Custom(99))
  328. }
  329. // One time IDL account initializer. Will faill on subsequent
  330. // invocations.
  331. #[inline(never)]
  332. pub fn __idl_create_account(
  333. program_id: &Pubkey,
  334. accounts: &mut anchor_lang::idl::IdlCreateAccounts,
  335. data_len: u64,
  336. ) -> ProgramResult {
  337. if program_id != accounts.program.key {
  338. return Err(anchor_lang::solana_program::program_error::ProgramError::Custom(98)); // todo proper error
  339. }
  340. // Create the IDL's account.
  341. let from = accounts.from.key;
  342. let (base, nonce) = Pubkey::find_program_address(&[], program_id);
  343. let seed = anchor_lang::idl::IdlAccount::seed();
  344. let owner = accounts.program.key;
  345. let to = Pubkey::create_with_seed(&base, seed, owner).unwrap();
  346. // Space: account discriminator || authority pubkey || vec len || vec data
  347. let space = 8 + 32 + 4 + data_len as usize;
  348. let lamports = accounts.rent.minimum_balance(space);
  349. let seeds = &[&[nonce][..]];
  350. let ix = anchor_lang::solana_program::system_instruction::create_account_with_seed(
  351. from,
  352. &to,
  353. &base,
  354. seed,
  355. lamports,
  356. space as u64,
  357. owner,
  358. );
  359. anchor_lang::solana_program::program::invoke_signed(
  360. &ix,
  361. &[
  362. accounts.from.clone(),
  363. accounts.to.clone(),
  364. accounts.base.clone(),
  365. accounts.system_program.clone(),
  366. ],
  367. &[seeds],
  368. )?;
  369. // Deserialize the newly created account.
  370. let mut idl_account = {
  371. let mut account_data = accounts.to.try_borrow_data()?;
  372. let mut account_data_slice: &[u8] = &account_data;
  373. anchor_lang::idl::IdlAccount::try_deserialize_unchecked(
  374. &mut account_data_slice,
  375. )?
  376. };
  377. // Set the authority.
  378. idl_account.authority = *accounts.from.key;
  379. // Store the new account data.
  380. let mut data = accounts.to.try_borrow_mut_data()?;
  381. let dst: &mut [u8] = &mut data;
  382. let mut cursor = std::io::Cursor::new(dst);
  383. idl_account.try_serialize(&mut cursor)?;
  384. Ok(())
  385. }
  386. #[inline(never)]
  387. pub fn __idl_create_buffer(
  388. program_id: &Pubkey,
  389. accounts: &mut anchor_lang::idl::IdlCreateBuffer,
  390. ) -> ProgramResult {
  391. let mut buffer = &mut accounts.buffer;
  392. buffer.authority = *accounts.authority.key;
  393. Ok(())
  394. }
  395. #[inline(never)]
  396. pub fn __idl_write(
  397. program_id: &Pubkey,
  398. accounts: &mut anchor_lang::idl::IdlAccounts,
  399. idl_data: Vec<u8>,
  400. ) -> ProgramResult {
  401. let mut idl = &mut accounts.idl;
  402. idl.data.extend(idl_data);
  403. Ok(())
  404. }
  405. #[inline(never)]
  406. pub fn __idl_set_authority(
  407. program_id: &Pubkey,
  408. accounts: &mut anchor_lang::idl::IdlAccounts,
  409. new_authority: Pubkey,
  410. ) -> ProgramResult {
  411. accounts.idl.authority = new_authority;
  412. Ok(())
  413. }
  414. #[inline(never)]
  415. pub fn __idl_set_buffer(
  416. program_id: &Pubkey,
  417. accounts: &mut anchor_lang::idl::IdlSetBuffer,
  418. ) -> ProgramResult {
  419. accounts.idl.data = accounts.buffer.data.clone();
  420. Ok(())
  421. }
  422. }
  423. };
  424. // Constructor handler.
  425. let non_inlined_ctor: proc_macro2::TokenStream = match &program.state {
  426. None => quote! {},
  427. Some(state) => match state.ctor_and_anchor.as_ref() {
  428. None => quote! {},
  429. Some((_ctor, anchor_ident)) => {
  430. let ctor_typed_args = generate_ctor_typed_args(state);
  431. let ctor_untyped_args = generate_ctor_args(state);
  432. let name = &state.strct.ident;
  433. let mod_name = &program.name;
  434. if state.is_zero_copy {
  435. quote! {
  436. // One time state account initializer. Will faill on subsequent
  437. // invocations.
  438. #[inline(never)]
  439. pub fn __ctor(program_id: &Pubkey, accounts: &[AccountInfo], #(#ctor_typed_args),*) -> ProgramResult {
  440. let mut remaining_accounts: &[AccountInfo] = accounts;
  441. // Deserialize accounts.
  442. let ctor_accounts = anchor_lang::__private::Ctor::try_accounts(program_id, &mut remaining_accounts)?;
  443. let mut ctor_user_def_accounts = #anchor_ident::try_accounts(program_id, &mut remaining_accounts)?;
  444. // Create the solana account for the ctor data.
  445. let from = ctor_accounts.from.key;
  446. let (base, nonce) = Pubkey::find_program_address(&[], ctor_accounts.program.key);
  447. let seed = anchor_lang::__private::PROGRAM_STATE_SEED;
  448. let owner = ctor_accounts.program.key;
  449. let to = Pubkey::create_with_seed(&base, seed, owner).unwrap();
  450. let space = 8 + std::mem::size_of::<#name>();
  451. let lamports = ctor_accounts.rent.minimum_balance(std::convert::TryInto::try_into(space).unwrap());
  452. let seeds = &[&[nonce][..]];
  453. let ix = anchor_lang::solana_program::system_instruction::create_account_with_seed(
  454. from,
  455. &to,
  456. &base,
  457. seed,
  458. lamports,
  459. space as u64,
  460. owner,
  461. );
  462. anchor_lang::solana_program::program::invoke_signed(
  463. &ix,
  464. &[
  465. ctor_accounts.from.clone(),
  466. ctor_accounts.to.clone(),
  467. ctor_accounts.base.clone(),
  468. ctor_accounts.system_program.clone(),
  469. ],
  470. &[seeds],
  471. )?;
  472. // Zero copy deserialize.
  473. let loader: anchor_lang::Loader<#mod_name::#name> = anchor_lang::Loader::try_from_init(&ctor_accounts.to)?;
  474. // Invoke the ctor in a new lexical scope so that
  475. // the zero-copy RefMut gets dropped. Required
  476. // so that we can subsequently run the exit routine.
  477. {
  478. let mut instance = loader.load_init()?;
  479. instance.new(
  480. anchor_lang::Context::new(
  481. program_id,
  482. &mut ctor_user_def_accounts,
  483. remaining_accounts,
  484. ),
  485. #(#ctor_untyped_args),*
  486. )?;
  487. }
  488. // Exit routines.
  489. ctor_user_def_accounts.exit(program_id)?;
  490. loader.exit(program_id)?;
  491. Ok(())
  492. }
  493. }
  494. } else {
  495. quote! {
  496. // One time state account initializer. Will faill on subsequent
  497. // invocations.
  498. #[inline(never)]
  499. pub fn __ctor(program_id: &Pubkey, accounts: &[AccountInfo], #(#ctor_typed_args),*) -> ProgramResult {
  500. let mut remaining_accounts: &[AccountInfo] = accounts;
  501. // Deserialize accounts.
  502. let ctor_accounts = anchor_lang::__private::Ctor::try_accounts(program_id, &mut remaining_accounts)?;
  503. let mut ctor_user_def_accounts = #anchor_ident::try_accounts(program_id, &mut remaining_accounts)?;
  504. // Invoke the ctor.
  505. let instance = #mod_name::#name::new(
  506. anchor_lang::Context::new(
  507. program_id,
  508. &mut ctor_user_def_accounts,
  509. remaining_accounts,
  510. ),
  511. #(#ctor_untyped_args),*
  512. )?;
  513. // Create the solana account for the ctor data.
  514. let from = ctor_accounts.from.key;
  515. let (base, nonce) = Pubkey::find_program_address(&[], ctor_accounts.program.key);
  516. let seed = anchor_lang::ProgramState::<#name>::seed();
  517. let owner = ctor_accounts.program.key;
  518. let to = Pubkey::create_with_seed(&base, seed, owner).unwrap();
  519. let space = anchor_lang::__private::AccountSize::size(&instance)?;
  520. let lamports = ctor_accounts.rent.minimum_balance(std::convert::TryInto::try_into(space).unwrap());
  521. let seeds = &[&[nonce][..]];
  522. let ix = anchor_lang::solana_program::system_instruction::create_account_with_seed(
  523. from,
  524. &to,
  525. &base,
  526. seed,
  527. lamports,
  528. space,
  529. owner,
  530. );
  531. anchor_lang::solana_program::program::invoke_signed(
  532. &ix,
  533. &[
  534. ctor_accounts.from.clone(),
  535. ctor_accounts.to.clone(),
  536. ctor_accounts.base.clone(),
  537. ctor_accounts.system_program.clone(),
  538. ],
  539. &[seeds],
  540. )?;
  541. // Serialize the state and save it to storage.
  542. ctor_user_def_accounts.exit(program_id)?;
  543. let mut data = ctor_accounts.to.try_borrow_mut_data()?;
  544. let dst: &mut [u8] = &mut data;
  545. let mut cursor = std::io::Cursor::new(dst);
  546. instance.try_serialize(&mut cursor)?;
  547. Ok(())
  548. }
  549. }
  550. }
  551. }
  552. },
  553. };
  554. // State method handlers.
  555. let non_inlined_state_handlers: Vec<proc_macro2::TokenStream> = match &program.state {
  556. None => vec![],
  557. Some(state) => state
  558. .impl_block_and_methods
  559. .as_ref()
  560. .map(|(_impl_block, methods)| {
  561. methods
  562. .iter()
  563. .map(|ix| {
  564. let ix_params: Vec<_> = ix.args.iter().map(|arg| &arg.raw_arg).collect();
  565. let ix_arg_names: Vec<&syn::Ident> =
  566. ix.args.iter().map(|arg| &arg.name).collect();
  567. let private_ix_name: proc_macro2::TokenStream = {
  568. let n = format!("__{}", &ix.raw_method.sig.ident.to_string());
  569. n.parse().unwrap()
  570. };
  571. let ix_name = &ix.raw_method.sig.ident;
  572. let state_ty: proc_macro2::TokenStream = state.name.parse().unwrap();
  573. let anchor_ident = &ix.anchor_ident;
  574. let name = &state.strct.ident;
  575. let mod_name = &program.name;
  576. if state.is_zero_copy {
  577. quote! {
  578. #[inline(never)]
  579. pub fn #private_ix_name(
  580. program_id: &Pubkey,
  581. accounts: &[AccountInfo],
  582. #(#ix_params),*
  583. ) -> ProgramResult {
  584. let mut remaining_accounts: &[AccountInfo] = accounts;
  585. if remaining_accounts.is_empty() {
  586. return Err(ProgramError::Custom(1)); // todo
  587. }
  588. let state_account = &remaining_accounts[0];
  589. let loader: anchor_lang::Loader<#mod_name::#name> = anchor_lang::Loader::try_from(&state_account)?;
  590. remaining_accounts = &remaining_accounts[1..];
  591. // Deserialize the program's execution context.
  592. let mut accounts = #anchor_ident::try_accounts(
  593. program_id,
  594. &mut remaining_accounts,
  595. )?;
  596. let ctx = Context::new(program_id, &mut accounts, remaining_accounts);
  597. // Execute user defined function.
  598. {
  599. let mut state = loader.load_mut()?;
  600. state.#ix_name(
  601. ctx,
  602. #(#ix_arg_names),*
  603. )?;
  604. }
  605. // Serialize the state and save it to storage.
  606. accounts.exit(program_id)?;
  607. loader.exit(program_id)?;
  608. Ok(())
  609. }
  610. }
  611. } else {
  612. quote! {
  613. #[inline(never)]
  614. pub fn #private_ix_name(
  615. program_id: &Pubkey,
  616. accounts: &[AccountInfo],
  617. #(#ix_params),*
  618. ) -> ProgramResult {
  619. let mut remaining_accounts: &[AccountInfo] = accounts;
  620. if remaining_accounts.is_empty() {
  621. return Err(ProgramError::Custom(1)); // todo
  622. }
  623. // Deserialize the program state account.
  624. let state_account = &remaining_accounts[0];
  625. let mut state: #state_ty = {
  626. let data = state_account.try_borrow_data()?;
  627. let mut sliced: &[u8] = &data;
  628. anchor_lang::AccountDeserialize::try_deserialize(&mut sliced)?
  629. };
  630. remaining_accounts = &remaining_accounts[1..];
  631. // Deserialize the program's execution context.
  632. let mut accounts = #anchor_ident::try_accounts(
  633. program_id,
  634. &mut remaining_accounts,
  635. )?;
  636. let ctx = Context::new(program_id, &mut accounts, remaining_accounts);
  637. // Execute user defined function.
  638. state.#ix_name(
  639. ctx,
  640. #(#ix_arg_names),*
  641. )?;
  642. // Serialize the state and save it to storage.
  643. accounts.exit(program_id)?;
  644. let mut data = state_account.try_borrow_mut_data()?;
  645. let dst: &mut [u8] = &mut data;
  646. let mut cursor = std::io::Cursor::new(dst);
  647. state.try_serialize(&mut cursor)?;
  648. Ok(())
  649. }
  650. }
  651. }
  652. })
  653. .collect()
  654. })
  655. .unwrap_or_default(),
  656. };
  657. // State trait handlers.
  658. let non_inlined_state_trait_handlers: Vec<proc_macro2::TokenStream> = match &program.state {
  659. None => Vec::new(),
  660. Some(state) => state
  661. .interfaces
  662. .as_ref()
  663. .map(|interfaces| {
  664. interfaces
  665. .iter()
  666. .flat_map(|iface: &crate::StateInterface| {
  667. iface
  668. .methods
  669. .iter()
  670. .map(|ix| {
  671. let ix_params: Vec<_> = ix.args.iter().map(|arg| &arg.raw_arg).collect();
  672. let ix_arg_names: Vec<&syn::Ident> =
  673. ix.args.iter().map(|arg| &arg.name).collect();
  674. let private_ix_name: proc_macro2::TokenStream = {
  675. let n = format!("__{}_{}", iface.trait_name, &ix.raw_method.sig.ident.to_string());
  676. n.parse().unwrap()
  677. };
  678. let ix_name = &ix.raw_method.sig.ident;
  679. let state_ty: proc_macro2::TokenStream = state.name.parse().unwrap();
  680. let anchor_ident = &ix.anchor_ident;
  681. if state.is_zero_copy {
  682. // Easy to implement. Just need to write a test.
  683. // Feel free to open a PR.
  684. panic!("Trait implementations not yet implemented for zero copy state structs. Please file an issue.");
  685. }
  686. if ix.has_receiver {
  687. quote! {
  688. #[inline(never)]
  689. pub fn #private_ix_name(
  690. program_id: &Pubkey,
  691. accounts: &[AccountInfo],
  692. #(#ix_params),*
  693. ) -> ProgramResult {
  694. let mut remaining_accounts: &[AccountInfo] = accounts;
  695. if remaining_accounts.is_empty() {
  696. return Err(ProgramError::Custom(1)); // todo
  697. }
  698. // Deserialize the program state account.
  699. let state_account = &remaining_accounts[0];
  700. let mut state: #state_ty = {
  701. let data = state_account.try_borrow_data()?;
  702. let mut sliced: &[u8] = &data;
  703. anchor_lang::AccountDeserialize::try_deserialize(&mut sliced)?
  704. };
  705. remaining_accounts = &remaining_accounts[1..];
  706. // Deserialize the program's execution context.
  707. let mut accounts = #anchor_ident::try_accounts(
  708. program_id,
  709. &mut remaining_accounts,
  710. )?;
  711. let ctx = Context::new(program_id, &mut accounts, remaining_accounts);
  712. // Execute user defined function.
  713. state.#ix_name(
  714. ctx,
  715. #(#ix_arg_names),*
  716. )?;
  717. // Serialize the state and save it to storage.
  718. accounts.exit(program_id)?;
  719. let mut data = state_account.try_borrow_mut_data()?;
  720. let dst: &mut [u8] = &mut data;
  721. let mut cursor = std::io::Cursor::new(dst);
  722. state.try_serialize(&mut cursor)?;
  723. Ok(())
  724. }
  725. }
  726. } else {
  727. let state_name: proc_macro2::TokenStream = state.name.parse().unwrap();
  728. quote! {
  729. #[inline(never)]
  730. pub fn #private_ix_name(
  731. program_id: &Pubkey,
  732. accounts: &[AccountInfo],
  733. #(#ix_params),*
  734. ) -> ProgramResult {
  735. let mut remaining_accounts: &[AccountInfo] = accounts;
  736. let mut accounts = #anchor_ident::try_accounts(
  737. program_id,
  738. &mut remaining_accounts,
  739. )?;
  740. #state_name::#ix_name(
  741. Context::new(program_id, &mut accounts, remaining_accounts),
  742. #(#ix_arg_names),*
  743. )?;
  744. accounts.exit(program_id)
  745. }
  746. }
  747. }
  748. })
  749. .collect::<Vec<proc_macro2::TokenStream>>()
  750. })
  751. .collect()
  752. })
  753. .unwrap_or_default(),
  754. };
  755. let non_inlined_handlers: Vec<proc_macro2::TokenStream> = program
  756. .ixs
  757. .iter()
  758. .map(|ix| {
  759. let ix_params: Vec<_> = ix.args.iter().map(|arg| &arg.raw_arg).collect();
  760. let ix_arg_names: Vec<&syn::Ident> = ix.args.iter().map(|arg| &arg.name).collect();
  761. let ix_name = &ix.raw_method.sig.ident;
  762. let anchor = &ix.anchor_ident;
  763. quote! {
  764. #[inline(never)]
  765. pub fn #ix_name(
  766. program_id: &Pubkey,
  767. accounts: &[AccountInfo],
  768. #(#ix_params),*
  769. ) -> ProgramResult {
  770. let mut remaining_accounts: &[AccountInfo] = accounts;
  771. let mut accounts = #anchor::try_accounts(program_id, &mut remaining_accounts)?;
  772. #program_name::#ix_name(
  773. Context::new(program_id, &mut accounts, remaining_accounts),
  774. #(#ix_arg_names),*
  775. )?;
  776. accounts.exit(program_id)
  777. }
  778. }
  779. })
  780. .collect();
  781. quote! {
  782. /// __idl mod defines handlers for injected Anchor IDL instructions.
  783. pub mod __idl {
  784. use super::*;
  785. #non_inlined_idl
  786. }
  787. /// __state mod defines wrapped handlers for state instructions.
  788. pub mod __state {
  789. use super::*;
  790. #non_inlined_ctor
  791. #(#non_inlined_state_handlers)*
  792. }
  793. /// __interface mod defines wrapped handlers for `#[interface]` trait
  794. /// implementations.
  795. pub mod __interface {
  796. use super::*;
  797. #(#non_inlined_state_trait_handlers)*
  798. }
  799. /// __global mod defines wrapped handlers for global instructions.
  800. pub mod __global {
  801. use super::*;
  802. #(#non_inlined_handlers)*
  803. }
  804. }
  805. }
  806. pub fn generate_ctor_variant(state: &State) -> proc_macro2::TokenStream {
  807. let ctor_args = generate_ctor_args(state);
  808. let ctor_variant_name: proc_macro2::TokenStream = generate_ctor_variant_name().parse().unwrap();
  809. if ctor_args.is_empty() {
  810. quote! {
  811. #ctor_variant_name
  812. }
  813. } else {
  814. quote! {
  815. #ctor_variant_name {
  816. #(#ctor_args),*
  817. }
  818. }
  819. }
  820. }
  821. pub fn generate_ctor_variant_name() -> String {
  822. "Ctor".to_string()
  823. }
  824. fn generate_ctor_typed_args(state: &State) -> Vec<syn::PatType> {
  825. state
  826. .ctor_and_anchor
  827. .as_ref()
  828. .map(|(ctor, _anchor_ident)| {
  829. ctor.sig
  830. .inputs
  831. .iter()
  832. .filter_map(|arg: &syn::FnArg| match arg {
  833. syn::FnArg::Typed(pat_ty) => {
  834. let mut arg_str = parser::tts_to_string(&pat_ty.ty);
  835. arg_str.retain(|c| !c.is_whitespace());
  836. if arg_str.starts_with("Context<") {
  837. return None;
  838. }
  839. Some(pat_ty.clone())
  840. }
  841. _ => {
  842. if !state.is_zero_copy {
  843. panic!("Cannot pass self as parameter")
  844. }
  845. None
  846. }
  847. })
  848. .collect()
  849. })
  850. .unwrap_or_default()
  851. }
  852. fn generate_ctor_args(state: &State) -> Vec<syn::Pat> {
  853. state
  854. .ctor_and_anchor
  855. .as_ref()
  856. .map(|(ctor, _anchor_ident)| {
  857. ctor.sig
  858. .inputs
  859. .iter()
  860. .filter_map(|arg: &syn::FnArg| match arg {
  861. syn::FnArg::Typed(pat_ty) => {
  862. let mut arg_str = parser::tts_to_string(&pat_ty.ty);
  863. arg_str.retain(|c| !c.is_whitespace());
  864. if arg_str.starts_with("Context<") {
  865. return None;
  866. }
  867. Some(*pat_ty.pat.clone())
  868. }
  869. _ => {
  870. if !state.is_zero_copy {
  871. panic!("Cannot pass self as parameter");
  872. }
  873. None
  874. }
  875. })
  876. .collect()
  877. })
  878. .unwrap_or_default()
  879. }
  880. pub fn generate_ix_variant(name: String, args: &[IxArg]) -> proc_macro2::TokenStream {
  881. let ix_arg_names: Vec<&syn::Ident> = args.iter().map(|arg| &arg.name).collect();
  882. let ix_name_camel: proc_macro2::TokenStream = {
  883. let n = name.to_camel_case();
  884. n.parse().unwrap()
  885. };
  886. if args.is_empty() {
  887. quote! {
  888. #ix_name_camel
  889. }
  890. } else {
  891. quote! {
  892. #ix_name_camel {
  893. #(#ix_arg_names),*
  894. }
  895. }
  896. }
  897. }
  898. pub fn generate_ix_variant_name(name: String) -> proc_macro2::TokenStream {
  899. let n = name.to_camel_case();
  900. n.parse().unwrap()
  901. }
  902. pub fn generate_methods(program: &Program) -> proc_macro2::TokenStream {
  903. let program_mod = &program.program_mod;
  904. quote! {
  905. #program_mod
  906. }
  907. }
  908. pub fn generate_ixs(program: &Program) -> proc_macro2::TokenStream {
  909. let ctor_variant = match &program.state {
  910. None => quote! {},
  911. Some(state) => {
  912. let ctor_args: Vec<proc_macro2::TokenStream> = generate_ctor_typed_args(state)
  913. .iter()
  914. .map(|arg| {
  915. format!("pub {}", parser::tts_to_string(&arg))
  916. .parse()
  917. .unwrap()
  918. })
  919. .collect();
  920. let strct = {
  921. if ctor_args.is_empty() {
  922. quote! {
  923. #[derive(AnchorSerialize, AnchorDeserialize)]
  924. pub struct Ctor;
  925. }
  926. } else {
  927. quote! {
  928. #[derive(AnchorSerialize, AnchorDeserialize)]
  929. pub struct Ctor {
  930. #(#ctor_args),*
  931. }
  932. }
  933. }
  934. };
  935. let sighash_arr = sighash_ctor();
  936. let sighash_tts: proc_macro2::TokenStream =
  937. format!("{:?}", sighash_arr).parse().unwrap();
  938. quote! {
  939. /// Instruction arguments to the `#[state]`'s `new`
  940. /// constructor.
  941. #strct
  942. impl anchor_lang::InstructionData for Ctor {
  943. fn data(&self) -> Vec<u8> {
  944. let mut d = #sighash_tts.to_vec();
  945. d.append(&mut self.try_to_vec().expect("Should always serialize"));
  946. d
  947. }
  948. }
  949. }
  950. }
  951. };
  952. let state_method_variants: Vec<proc_macro2::TokenStream> = match &program.state {
  953. None => vec![],
  954. Some(state) => state
  955. .impl_block_and_methods
  956. .as_ref()
  957. .map(|(_impl_block, methods)| {
  958. methods
  959. .iter()
  960. .map(|method| {
  961. let ix_name_camel: proc_macro2::TokenStream = method
  962. .raw_method
  963. .sig
  964. .ident
  965. .to_string()
  966. .to_camel_case()
  967. .parse()
  968. .unwrap();
  969. let raw_args: Vec<proc_macro2::TokenStream> = method
  970. .args
  971. .iter()
  972. .map(|arg| {
  973. format!("pub {}", parser::tts_to_string(&arg.raw_arg))
  974. .parse()
  975. .unwrap()
  976. })
  977. .collect();
  978. let ix_data_trait = {
  979. let name = method.raw_method.sig.ident.to_string();
  980. let sighash_arr = sighash(SIGHASH_STATE_NAMESPACE, &name);
  981. let sighash_tts: proc_macro2::TokenStream =
  982. format!("{:?}", sighash_arr).parse().unwrap();
  983. quote! {
  984. impl anchor_lang::InstructionData for #ix_name_camel {
  985. fn data(&self) -> Vec<u8> {
  986. let mut d = #sighash_tts.to_vec();
  987. d.append(&mut self.try_to_vec().expect("Should always serialize"));
  988. d
  989. }
  990. }
  991. }
  992. };
  993. // If no args, output a "unit" variant instead of a struct variant.
  994. if method.args.is_empty() {
  995. quote! {
  996. /// Anchor generated instruction.
  997. #[derive(AnchorSerialize, AnchorDeserialize)]
  998. pub struct #ix_name_camel;
  999. #ix_data_trait
  1000. }
  1001. } else {
  1002. quote! {
  1003. /// Anchor generated instruction.
  1004. #[derive(AnchorSerialize, AnchorDeserialize)]
  1005. pub struct #ix_name_camel {
  1006. #(#raw_args),*
  1007. }
  1008. #ix_data_trait
  1009. }
  1010. }
  1011. })
  1012. .collect()
  1013. })
  1014. .unwrap_or_default(),
  1015. };
  1016. let variants: Vec<proc_macro2::TokenStream> = program
  1017. .ixs
  1018. .iter()
  1019. .map(|ix| {
  1020. let name = &ix.raw_method.sig.ident.to_string();
  1021. let ix_name_camel =
  1022. proc_macro2::Ident::new(&name.to_camel_case(), ix.raw_method.sig.ident.span());
  1023. let raw_args: Vec<proc_macro2::TokenStream> = ix
  1024. .args
  1025. .iter()
  1026. .map(|arg| {
  1027. format!("pub {}", parser::tts_to_string(&arg.raw_arg))
  1028. .parse()
  1029. .unwrap()
  1030. })
  1031. .collect();
  1032. let ix_data_trait = {
  1033. let sighash_arr = sighash(SIGHASH_GLOBAL_NAMESPACE, &name);
  1034. let sighash_tts: proc_macro2::TokenStream =
  1035. format!("{:?}", sighash_arr).parse().unwrap();
  1036. quote! {
  1037. impl anchor_lang::InstructionData for #ix_name_camel {
  1038. fn data(&self) -> Vec<u8> {
  1039. let mut d = #sighash_tts.to_vec();
  1040. d.append(&mut self.try_to_vec().expect("Should always serialize"));
  1041. d
  1042. }
  1043. }
  1044. }
  1045. };
  1046. // If no args, output a "unit" variant instead of a struct variant.
  1047. if ix.args.is_empty() {
  1048. quote! {
  1049. /// Instruction.
  1050. #[derive(AnchorSerialize, AnchorDeserialize)]
  1051. pub struct #ix_name_camel;
  1052. #ix_data_trait
  1053. }
  1054. } else {
  1055. quote! {
  1056. /// Instruction.
  1057. #[derive(AnchorSerialize, AnchorDeserialize)]
  1058. pub struct #ix_name_camel {
  1059. #(#raw_args),*
  1060. }
  1061. #ix_data_trait
  1062. }
  1063. }
  1064. })
  1065. .collect();
  1066. quote! {
  1067. /// An Anchor generated module containing the program's set of
  1068. /// instructions, where each method handler in the `#[program]` mod is
  1069. /// associated with a struct defining the input arguments to the
  1070. /// method. These should be used directly, when one wants to serialize
  1071. /// Anchor instruction data, for example, when speciying
  1072. /// instructions on a client.
  1073. pub mod instruction {
  1074. use super::*;
  1075. /// Instruction struct definitions for `#[state]` methods.
  1076. pub mod state {
  1077. use super::*;
  1078. #ctor_variant
  1079. #(#state_method_variants)*
  1080. }
  1081. #(#variants)*
  1082. }
  1083. }
  1084. }
  1085. fn generate_accounts(program: &Program) -> proc_macro2::TokenStream {
  1086. let mut accounts = std::collections::HashSet::new();
  1087. // Go through state accounts.
  1088. if let Some(state) = &program.state {
  1089. if let Some((_impl_block, methods)) = &state.impl_block_and_methods {
  1090. for ix in methods {
  1091. let anchor_ident = &ix.anchor_ident;
  1092. // TODO: move to fn and share with accounts.rs.
  1093. let macro_name = format!(
  1094. "__client_accounts_{}",
  1095. anchor_ident.to_string().to_snake_case()
  1096. );
  1097. accounts.insert(macro_name);
  1098. }
  1099. }
  1100. }
  1101. // Go through instruction accounts.
  1102. for ix in &program.ixs {
  1103. let anchor_ident = &ix.anchor_ident;
  1104. // TODO: move to fn and share with accounts.rs.
  1105. let macro_name = format!(
  1106. "__client_accounts_{}",
  1107. anchor_ident.to_string().to_snake_case()
  1108. );
  1109. accounts.insert(macro_name);
  1110. }
  1111. // Build the tokens from all accounts
  1112. let account_structs: Vec<proc_macro2::TokenStream> = accounts
  1113. .iter()
  1114. .map(|macro_name: &String| {
  1115. let macro_name: proc_macro2::TokenStream = macro_name.parse().unwrap();
  1116. quote! {
  1117. pub use crate::#macro_name::*;
  1118. }
  1119. })
  1120. .collect();
  1121. // TODO: calculate the account size and add it as a constant field to
  1122. // each struct here. This is convenient for Rust clients.
  1123. quote! {
  1124. /// An Anchor generated module, providing a set of structs
  1125. /// mirroring the structs deriving `Accounts`, where each field is
  1126. /// a `Pubkey`. This is useful for specifying accounts for a client.
  1127. pub mod accounts {
  1128. #(#account_structs)*
  1129. }
  1130. }
  1131. }
  1132. fn generate_cpi(program: &Program) -> proc_macro2::TokenStream {
  1133. // Generate cpi methods for the state struct.
  1134. // The Ctor is not exposed via CPI, since it is a one time use function.
  1135. let state_cpi_methods: Vec<proc_macro2::TokenStream> = program
  1136. .state
  1137. .as_ref()
  1138. .map(|state| {
  1139. state
  1140. .impl_block_and_methods
  1141. .as_ref()
  1142. .map(|(_, methods)| {
  1143. methods
  1144. .iter()
  1145. .map(|method: &StateIx| {
  1146. let accounts_ident = &method.anchor_ident;
  1147. let ix_variant = generate_ix_variant(
  1148. method.raw_method.sig.ident.to_string(),
  1149. &method.args,
  1150. );
  1151. let method_name = &method.ident;
  1152. let args: Vec<&syn::PatType> =
  1153. method.args.iter().map(|arg| &arg.raw_arg).collect();
  1154. quote! {
  1155. pub fn #method_name<'a, 'b, 'c, 'info>(
  1156. ctx: CpiStateContext<'a, 'b, 'c, 'info, #accounts_ident<'info>>,
  1157. #(#args),*
  1158. ) -> ProgramResult {
  1159. let ix = {
  1160. let ix = instruction::state::#ix_variant;
  1161. let data = anchor_lang::InstructionData::data(&ix);
  1162. let accounts = ctx.to_account_metas(None);
  1163. anchor_lang::solana_program::instruction::Instruction {
  1164. program_id: *ctx.program().key,
  1165. accounts,
  1166. data,
  1167. }
  1168. };
  1169. let mut acc_infos = ctx.to_account_infos();
  1170. anchor_lang::solana_program::program::invoke_signed(
  1171. &ix,
  1172. &acc_infos,
  1173. ctx.signer_seeds(),
  1174. )
  1175. }
  1176. }
  1177. })
  1178. .collect()
  1179. })
  1180. .unwrap_or(vec![])
  1181. })
  1182. .unwrap_or(vec![]);
  1183. // Generate cpi methods for global methods.
  1184. let global_cpi_methods: Vec<proc_macro2::TokenStream> = program
  1185. .ixs
  1186. .iter()
  1187. .map(|ix| {
  1188. let accounts_ident = &ix.anchor_ident;
  1189. let cpi_method = {
  1190. let ix_variant = generate_ix_variant(ix.raw_method.sig.ident.to_string(), &ix.args);
  1191. let method_name = &ix.ident;
  1192. let args: Vec<&syn::PatType> = ix.args.iter().map(|arg| &arg.raw_arg).collect();
  1193. let name = &ix.raw_method.sig.ident.to_string();
  1194. let sighash_arr = sighash(SIGHASH_GLOBAL_NAMESPACE, &name);
  1195. let sighash_tts: proc_macro2::TokenStream =
  1196. format!("{:?}", sighash_arr).parse().unwrap();
  1197. quote! {
  1198. pub fn #method_name<'a, 'b, 'c, 'info>(
  1199. ctx: CpiContext<'a, 'b, 'c, 'info, #accounts_ident<'info>>,
  1200. #(#args),*
  1201. ) -> ProgramResult {
  1202. let ix = {
  1203. let ix = instruction::#ix_variant;
  1204. let mut ix_data = AnchorSerialize::try_to_vec(&ix)
  1205. .map_err(|_| ProgramError::InvalidInstructionData)?;
  1206. let mut data = #sighash_tts.to_vec();
  1207. data.append(&mut ix_data);
  1208. let accounts = ctx.accounts.to_account_metas(None);
  1209. anchor_lang::solana_program::instruction::Instruction {
  1210. program_id: *ctx.program.key,
  1211. accounts,
  1212. data,
  1213. }
  1214. };
  1215. let mut acc_infos = ctx.accounts.to_account_infos();
  1216. acc_infos.push(ctx.program.clone());
  1217. anchor_lang::solana_program::program::invoke_signed(
  1218. &ix,
  1219. &acc_infos,
  1220. ctx.signer_seeds,
  1221. )
  1222. }
  1223. }
  1224. };
  1225. cpi_method
  1226. })
  1227. .collect();
  1228. quote! {
  1229. #[cfg(feature = "cpi")]
  1230. pub mod cpi {
  1231. use super::*;
  1232. pub mod state {
  1233. use super::*;
  1234. #(#state_cpi_methods)*
  1235. }
  1236. #(#global_cpi_methods)*
  1237. }
  1238. }
  1239. }
  1240. // We don't technically use sighash, because the input arguments aren't given.
  1241. // Rust doesn't have method overloading so no need to use the arguments.
  1242. // However, we do namespace methods in the preeimage so that we can use
  1243. // different traits with the same method name.
  1244. pub fn sighash(namespace: &str, name: &str) -> [u8; 8] {
  1245. let preimage = format!("{}::{}", namespace, name);
  1246. let mut sighash = [0u8; 8];
  1247. sighash.copy_from_slice(&crate::hash::hash(preimage.as_bytes()).to_bytes()[..8]);
  1248. sighash
  1249. }
  1250. fn sighash_ctor() -> [u8; 8] {
  1251. let namespace = SIGHASH_STATE_NAMESPACE;
  1252. let preimage = format!("{}::new", namespace);
  1253. let mut sighash = [0u8; 8];
  1254. sighash.copy_from_slice(&crate::hash::hash(preimage.as_bytes()).to_bytes()[..8]);
  1255. sighash
  1256. }