program.rs 61 KB

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