Files
solana/runtime/src/builtins.rs
mergify[bot] bc3aa53e02 Runtime feature activation framework (bp #12376) (#12497)
* Runtime feature activation framework

(cherry picked from commit 93259f0bae)

# Conflicts:
#	runtime/src/bank.rs

* Add feature set identifier to gossiped version information

(cherry picked from commit 35f5f9fc7b)

# Conflicts:
#	Cargo.lock
#	version/Cargo.toml

* Port instructions sysvar and secp256k1 program activation to FeatureSet

(cherry picked from commit c10da16d7b)

# Conflicts:
#	runtime/src/bank.rs
#	runtime/src/message_processor.rs

* Add feature management commands

(cherry picked from commit 93ed0ab2bb)

# Conflicts:
#	Cargo.lock
#	cli/Cargo.toml

* Make test_process_rest_api less fragile

(cherry picked from commit 7526bb96f3)

* Remove id field

(cherry picked from commit cc6ba1e131)

* FeatureSet test

(cherry picked from commit 92406cf9a0)

* cargo fmt

(cherry picked from commit 199940d683)

* cli review feedback

(cherry picked from commit 3a2b8c5e5b)

* Rename active() to is_active()

(cherry picked from commit e39fac9f01)

* Resolve merge conflicts

* Remove continues from compute_active_feature_set()

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-09-26 17:49:53 +00:00

189 lines
6.0 KiB
Rust

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::<Vec<_>>(),
);
// 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,
]
);
}
}