use { solana_program_runtime::{builtin_program::create_builtin, loaded_programs::LoadedProgram}, solana_sdk::{ bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, feature_set, pubkey::Pubkey, }, std::sync::Arc, }; #[derive(Clone, Debug)] pub struct Builtins { /// Builtin programs that are always available pub genesis_builtins: Vec<(Pubkey, Arc)>, /// Dynamic feature transitions for builtin programs pub feature_transitions: Vec, } /// Actions taken by a bank when managing the list of active builtin programs. #[derive(Debug, Clone)] pub enum BuiltinAction { Add(Pubkey, Arc), Remove(Pubkey), } /// State transition enum used for adding and removing builtin programs through /// feature activations. #[derive(Debug, Clone, AbiExample)] pub enum BuiltinFeatureTransition { /// Add a builtin program if a feature is activated. Add { program_id: Pubkey, builtin: Arc, feature_id: Pubkey, }, /// Remove a builtin program if a feature is activated or /// retain a previously added builtin. RemoveOrRetain { program_id: Pubkey, previously_added_builtin: Arc, addition_feature_id: Pubkey, removal_feature_id: Pubkey, }, } impl BuiltinFeatureTransition { pub fn to_action( &self, should_apply_action_for_feature: &impl Fn(&Pubkey) -> bool, ) -> Option { match self { Self::Add { program_id, builtin, feature_id, } => { if should_apply_action_for_feature(feature_id) { Some(BuiltinAction::Add(*program_id, builtin.clone())) } else { None } } Self::RemoveOrRetain { program_id, previously_added_builtin, addition_feature_id, removal_feature_id, } => { if should_apply_action_for_feature(removal_feature_id) { Some(BuiltinAction::Remove(*program_id)) } else if should_apply_action_for_feature(addition_feature_id) { // Retaining is no different from adding a new builtin. Some(BuiltinAction::Add( *program_id, previously_added_builtin.clone(), )) } else { None } } } } } /// Built-in programs that are always available fn genesis_builtins() -> Vec<(Pubkey, Arc)> { vec![ ( solana_system_program::id(), create_builtin( "system_program".to_string(), solana_system_program::system_processor::process_instruction, ), ), ( solana_vote_program::id(), create_builtin( "vote_program".to_string(), solana_vote_program::vote_processor::process_instruction, ), ), ( solana_stake_program::id(), create_builtin( "stake_program".to_string(), solana_stake_program::stake_instruction::process_instruction, ), ), ( solana_config_program::id(), create_builtin( "config_program".to_string(), solana_config_program::config_processor::process_instruction, ), ), ( bpf_loader_deprecated::id(), create_builtin( "solana_bpf_loader_deprecated_program".to_string(), solana_bpf_loader_program::process_instruction, ), ), ( bpf_loader::id(), create_builtin( "solana_bpf_loader_program".to_string(), solana_bpf_loader_program::process_instruction, ), ), ( bpf_loader_upgradeable::id(), create_builtin( "solana_bpf_loader_upgradeable_program".to_string(), solana_bpf_loader_program::process_instruction, ), ), ] } /// Dynamic feature transitions for builtin programs fn builtin_feature_transitions() -> Vec { vec![ BuiltinFeatureTransition::Add { program_id: solana_sdk::compute_budget::id(), builtin: create_builtin( "compute_budget_program".to_string(), solana_compute_budget_program::process_instruction, ), feature_id: feature_set::add_compute_budget_program::id(), }, BuiltinFeatureTransition::Add { program_id: solana_address_lookup_table_program::id(), builtin: create_builtin( "address_lookup_table_program".to_string(), solana_address_lookup_table_program::processor::process_instruction, ), feature_id: feature_set::versioned_tx_message_enabled::id(), }, BuiltinFeatureTransition::Add { program_id: solana_zk_token_sdk::zk_token_proof_program::id(), builtin: create_builtin( "zk_token_proof_program".to_string(), solana_zk_token_proof_program::process_instruction, ), feature_id: feature_set::zk_token_sdk_enabled::id(), }, ] } pub(crate) fn get() -> Builtins { Builtins { genesis_builtins: genesis_builtins(), feature_transitions: builtin_feature_transitions(), } } /// Returns the addresses of all builtin programs. pub fn get_pubkeys() -> Vec { let builtins = get(); let mut pubkeys = Vec::new(); pubkeys.extend( builtins .genesis_builtins .iter() .map(|(program_id, _builtin)| program_id), ); pubkeys.extend(builtins.feature_transitions.iter().filter_map(|f| match f { BuiltinFeatureTransition::Add { program_id, .. } => Some(program_id), BuiltinFeatureTransition::RemoveOrRetain { .. } => None, })); pubkeys }