use crate::{ bank::{Builtin, Entrypoint}, feature_set, system_instruction_processor, }; use solana_sdk::{ clock::{Epoch, GENESIS_EPOCH}, genesis_config::ClusterType, pubkey::Pubkey, system_program, }; use log::*; /// Builtin programs that should be active for the given cluster_type /// /// Old style. Use `get_feature_builtins()` instead pub fn get_cluster_builtins(cluster_type: ClusterType) -> Vec<(Builtin, Epoch)> { trace!("get_cluster_builtins: {:?}", cluster_type); let mut builtins = vec![]; builtins.extend( vec![ Builtin::new( "system_program", system_program::id(), Entrypoint::Program(system_instruction_processor::process_instruction), ), Builtin::new( "config_program", solana_config_program::id(), Entrypoint::Program(solana_config_program::config_processor::process_instruction), ), Builtin::new( "stake_program", solana_stake_program::id(), Entrypoint::Program(solana_stake_program::stake_instruction::process_instruction), ), Builtin::new( "vote_program", solana_vote_program::id(), Entrypoint::Program(solana_vote_program::vote_instruction::process_instruction), ), ] .into_iter() .map(|program| (program, GENESIS_EPOCH)) .collect::>(), ); // repurpose Testnet for test_get_builtins because the Development is overloaded... #[cfg(test)] if cluster_type == ClusterType::Testnet { use solana_sdk::account::KeyedAccount; use solana_sdk::instruction::InstructionError; use std::str::FromStr; fn mock_ix_processor( _pubkey: &Pubkey, _ka: &[KeyedAccount], _data: &[u8], ) -> std::result::Result<(), InstructionError> { Err(InstructionError::Custom(42)) } let program_id = Pubkey::from_str("7saCc6X5a2syoYANA5oUUnPZLcLMfKoSjiDhFU5fbpoK").unwrap(); builtins.push(( Builtin::new("mock", program_id, Entrypoint::Program(mock_ix_processor)), 2, )); } builtins } /// Builtin programs that are activated dynamically by feature pub fn get_feature_builtins() -> Vec<(Builtin, Pubkey)> { vec![( Builtin::new( "secp256k1_program", solana_sdk::secp256k1_program::id(), Entrypoint::Program(solana_secp256k1_program::process_instruction), ), feature_set::secp256k1_program_enabled::id(), )] } #[cfg(test)] mod tests { use super::*; use crate::bank::Bank; use solana_sdk::genesis_config::create_genesis_config; use std::{collections::HashSet, str::FromStr, sync::Arc}; fn do_test_uniqueness(builtins: Vec<(Builtin, Epoch)>) { let mut unique_ids = HashSet::new(); let mut unique_names = HashSet::new(); let mut prev_start_epoch = 0; for (builtin, next_start_epoch) in builtins { assert!(next_start_epoch >= prev_start_epoch); assert!(unique_ids.insert(builtin.name)); assert!(unique_names.insert(builtin.id)); prev_start_epoch = next_start_epoch; } } #[test] fn test_uniqueness() { do_test_uniqueness(get_cluster_builtins(ClusterType::Development)); do_test_uniqueness(get_cluster_builtins(ClusterType::Devnet)); do_test_uniqueness(get_cluster_builtins(ClusterType::Testnet)); do_test_uniqueness(get_cluster_builtins(ClusterType::MainnetBeta)); } #[test] fn test_get_builtins() { let mock_program_id = Pubkey::from_str("7saCc6X5a2syoYANA5oUUnPZLcLMfKoSjiDhFU5fbpoK").unwrap(); let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000); genesis_config.cluster_type = ClusterType::Testnet; let bank0 = Arc::new(Bank::new(&genesis_config)); let restored_slot1 = genesis_config.epoch_schedule.get_first_slot_in_epoch(2); let bank1 = Arc::new(Bank::new_from_parent( &bank0, &Pubkey::default(), restored_slot1, )); let restored_slot2 = genesis_config.epoch_schedule.get_first_slot_in_epoch(3); let bank2 = Arc::new(Bank::new_from_parent( &bank1, &Pubkey::default(), restored_slot2, )); let warped_slot = genesis_config.epoch_schedule.get_first_slot_in_epoch(999); let warped_bank = Arc::new(Bank::warp_from_parent( &bank0, &Pubkey::default(), warped_slot, )); assert_eq!(bank0.slot(), 0); assert_eq!( bank0.builtin_program_ids(), vec![ system_program::id(), solana_config_program::id(), solana_stake_program::id(), solana_vote_program::id(), ] ); assert_eq!(bank1.slot(), restored_slot1); assert_eq!( bank1.builtin_program_ids(), vec![ system_program::id(), solana_config_program::id(), solana_stake_program::id(), solana_vote_program::id(), mock_program_id, ] ); assert_eq!(bank2.slot(), restored_slot2); assert_eq!( bank2.builtin_program_ids(), vec![ system_program::id(), solana_config_program::id(), solana_stake_program::id(), solana_vote_program::id(), mock_program_id, ] ); assert_eq!(warped_bank.slot(), warped_slot); assert_eq!( warped_bank.builtin_program_ids(), vec![ system_program::id(), solana_config_program::id(), solana_stake_program::id(), solana_vote_program::id(), mock_program_id, ] ); } }