entry.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. use crate::program_codegen::dispatch;
  2. use crate::Program;
  3. use quote::quote;
  4. pub fn generate(program: &Program) -> proc_macro2::TokenStream {
  5. let fallback_maybe = dispatch::gen_fallback(program).unwrap_or(quote! {
  6. Err(anchor_lang::__private::ErrorCode::InstructionMissing.into());
  7. });
  8. quote! {
  9. #[cfg(not(feature = "no-entrypoint"))]
  10. anchor_lang::solana_program::entrypoint!(entry);
  11. /// The Anchor codegen exposes a programming model where a user defines
  12. /// a set of methods inside of a `#[program]` module in a way similar
  13. /// to writing RPC request handlers. The macro then generates a bunch of
  14. /// code wrapping these user defined methods into something that can be
  15. /// executed on Solana.
  16. ///
  17. /// These methods fall into one of three categories, each of which
  18. /// can be considered a different "namespace" of the program.
  19. ///
  20. /// 1) Global methods - regular methods inside of the `#[program]`.
  21. /// 2) State methods - associated methods inside a `#[state]` struct.
  22. /// 3) Interface methods - methods inside a strait struct's
  23. /// implementation of an `#[interface]` trait.
  24. ///
  25. /// Care must be taken by the codegen to prevent collisions between
  26. /// methods in these different namespaces. For this reason, Anchor uses
  27. /// a variant of sighash to perform method dispatch, rather than
  28. /// something like a simple enum variant discriminator.
  29. ///
  30. /// The execution flow of the generated code can be roughly outlined:
  31. ///
  32. /// * Start program via the entrypoint.
  33. /// * Strip method identifier off the first 8 bytes of the instruction
  34. /// data and invoke the identified method. The method identifier
  35. /// is a variant of sighash. See docs.rs for `anchor_lang` for details.
  36. /// * If the method identifier is an IDL identifier, execute the IDL
  37. /// instructions, which are a special set of hardcoded instructions
  38. /// baked into every Anchor program. Then exit.
  39. /// * Otherwise, the method identifier is for a user defined
  40. /// instruction, i.e., one of the methods in the user defined
  41. /// `#[program]` module. Perform method dispatch, i.e., execute the
  42. /// big match statement mapping method identifier to method handler
  43. /// wrapper.
  44. /// * Run the method handler wrapper. This wraps the code the user
  45. /// actually wrote, deserializing the accounts, constructing the
  46. /// context, invoking the user's code, and finally running the exit
  47. /// routine, which typically persists account changes.
  48. ///
  49. /// The `entry` function here, defines the standard entry to a Solana
  50. /// program, where execution begins.
  51. #[cfg(not(feature = "no-entrypoint"))]
  52. pub fn entry(program_id: &Pubkey, accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
  53. #[cfg(feature = "anchor-debug")]
  54. {
  55. msg!("anchor-debug is active");
  56. }
  57. if data.len() < 8 {
  58. return #fallback_maybe
  59. }
  60. dispatch(program_id, accounts, data)
  61. .map_err(|e| {
  62. anchor_lang::solana_program::msg!(&e.to_string());
  63. e
  64. })
  65. }
  66. }
  67. }