1use crate::system_instruction_processor;
2use gemachain_sdk::{
3 feature_set,
4 instruction::InstructionError,
5 process_instruction::{stable_log, InvokeContext, ProcessInstructionWithContext},
6 pubkey::Pubkey,
7 stake, system_program,
8};
9use std::fmt;
10
11#[cfg(RUSTC_WITH_SPECIALIZATION)]
12use gemachain_frozen_abi::abi_example::AbiExample;
13
14fn process_instruction_with_program_logging(
15 process_instruction: ProcessInstructionWithContext,
16 program_id: &Pubkey,
17 instruction_data: &[u8],
18 invoke_context: &mut dyn InvokeContext,
19) -> Result<(), InstructionError> {
20 let logger = invoke_context.get_logger();
21 stable_log::program_invoke(&logger, program_id, invoke_context.invoke_depth());
22
23 let result = process_instruction(program_id, instruction_data, invoke_context);
24
25 match &result {
26 Ok(()) => stable_log::program_success(&logger, program_id),
27 Err(err) => stable_log::program_failure(&logger, program_id, err),
28 }
29 result
30}
31
32macro_rules! with_program_logging {
33 ($process_instruction:expr) => {
34 |program_id: &Pubkey, instruction_data: &[u8], invoke_context: &mut dyn InvokeContext| {
35 process_instruction_with_program_logging(
36 $process_instruction,
37 program_id,
38 instruction_data,
39 invoke_context,
40 )
41 }
42 };
43}
44
45#[derive(AbiExample, Debug, Clone)]
46pub enum ActivationType {
47 NewProgram,
48 NewVersion,
49}
50
51#[derive(Clone)]
52pub struct Builtin {
53 pub name: String,
54 pub id: Pubkey,
55 pub process_instruction_with_context: ProcessInstructionWithContext,
56}
57
58impl Builtin {
59 pub fn new(
60 name: &str,
61 id: Pubkey,
62 process_instruction_with_context: ProcessInstructionWithContext,
63 ) -> Self {
64 Self {
65 name: name.to_string(),
66 id,
67 process_instruction_with_context,
68 }
69 }
70}
71
72impl fmt::Debug for Builtin {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 write!(f, "Builtin [name={}, id={}]", self.name, self.id)
75 }
76}
77
78#[cfg(RUSTC_WITH_SPECIALIZATION)]
79impl AbiExample for Builtin {
80 fn example() -> Self {
81 Self {
82 name: String::default(),
83 id: Pubkey::default(),
84 process_instruction_with_context: |_, _, _| Ok(()),
85 }
86 }
87}
88
89#[derive(Clone, Debug)]
90pub struct Builtins {
91 pub genesis_builtins: Vec<Builtin>,
93
94 pub feature_builtins: Vec<(Builtin, Pubkey, ActivationType)>,
96}
97
98fn genesis_builtins() -> Vec<Builtin> {
100 vec![
101 Builtin::new(
102 "system_program",
103 system_program::id(),
104 with_program_logging!(system_instruction_processor::process_instruction),
105 ),
106 Builtin::new(
107 "vote_program",
108 gemachain_vote_program::id(),
109 with_program_logging!(gemachain_vote_program::vote_instruction::process_instruction),
110 ),
111 Builtin::new(
112 "stake_program",
113 stake::program::id(),
114 with_program_logging!(gemachain_stake_program::stake_instruction::process_instruction),
115 ),
116 Builtin::new(
117 "config_program",
118 gemachain_config_program::id(),
119 with_program_logging!(gemachain_config_program::config_processor::process_instruction),
120 ),
121 Builtin::new(
122 "secp256k1_program",
123 gemachain_sdk::secp256k1_program::id(),
124 gemachain_secp256k1_program::process_instruction,
125 ),
126 ]
127}
128
129fn feature_builtins() -> Vec<(Builtin, Pubkey, ActivationType)> {
138 vec![
139 (
140 Builtin::new(
141 "compute_budget_program",
142 gemachain_sdk::compute_budget::id(),
143 gemachain_compute_budget_program::process_instruction,
144 ),
145 feature_set::tx_wide_compute_cap::id(),
146 ActivationType::NewProgram,
147 ),
148 (
149 Builtin::new(
150 "ed25519_program",
151 gemachain_sdk::ed25519_program::id(),
152 gemachain_ed25519_program::process_instruction,
153 ),
154 feature_set::ed25519_program_enabled::id(),
155 ActivationType::NewProgram,
156 ),
157 ]
158}
159
160pub(crate) fn get() -> Builtins {
161 Builtins {
162 genesis_builtins: genesis_builtins(),
163 feature_builtins: feature_builtins(),
164 }
165}