Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3198,6 +3198,11 @@ impl Bank {

/// Add a precompiled program account
pub fn add_precompiled_account(&self, program_id: &Pubkey) {
self.add_precompiled_account_with_owner(program_id, native_loader::id())
}

// Used by tests to simulate clusters with precompiles that aren't owned by the native loader
fn add_precompiled_account_with_owner(&self, program_id: &Pubkey, owner: Pubkey) {
if let Some(account) = self.get_account_with_fixed_root(program_id) {
if account.executable() {
// The account is already executable, that's all we need
Expand All @@ -3219,7 +3224,7 @@ impl Bank {
let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
let account = AccountSharedData::from(Account {
lamports,
owner: native_loader::id(),
owner,
data: vec![],
executable: true,
rent_epoch,
Expand Down Expand Up @@ -6494,12 +6499,12 @@ impl Bank {

fn apply_builtin_program_feature_transitions(
&mut self,
apply_transitions_for_new_features: bool,
only_apply_transitions_for_new_features: bool,
new_feature_activations: &HashSet<Pubkey>,
) {
let feature_set = self.feature_set.clone();
let should_apply_action_for_feature = |feature_id: &Pubkey| -> bool {
if apply_transitions_for_new_features {
let should_apply_action_for_feature_transition = |feature_id: &Pubkey| -> bool {
if only_apply_transitions_for_new_features {
new_feature_activations.contains(feature_id)
} else {
feature_set.is_active(feature_id)
Expand All @@ -6508,7 +6513,9 @@ impl Bank {

let builtin_feature_transitions = self.builtin_feature_transitions.clone();
for transition in builtin_feature_transitions.iter() {
if let Some(builtin_action) = transition.to_action(&should_apply_action_for_feature) {
if let Some(builtin_action) =
transition.to_action(&should_apply_action_for_feature_transition)
{
match builtin_action {
BuiltinAction::Add(builtin) => self.add_builtin(
&builtin.name,
Expand Down Expand Up @@ -13000,25 +13007,25 @@ pub(crate) mod tests {
if bank.slot == 0 {
assert_eq!(
bank.hash().to_string(),
"HREoNvUAuqqGdJxYTgnFqjTxsuuBVUFFDNLGR2cdrtMf"
"9tLrxkBoNE7zEUZ2g72ZwE4fTfhUQnhC8A4Xt4EmYhP1"
);
}
if bank.slot == 32 {
assert_eq!(
bank.hash().to_string(),
"J8kjxLMMrpEVQUbX54zDALkXidjdXyFSL5wD2d7xUaWL"
"7qCbZN5WLT928VpsaLwLp6HfRDzZirmoU4JM4XBEyupu"
);
}
if bank.slot == 64 {
assert_eq!(
bank.hash().to_string(),
"yPCTEPtNi2DJb8KyqPKgBK7HCfiEpH2oS3Nn12LPBHm"
"D3ypfQFreDaQhJuuYN8rWG1TVy9ApvTCx5CAiQ5i9d7A"
);
}
if bank.slot == 128 {
assert_eq!(
bank.hash().to_string(),
"2oG1rmA59tmr457oK4oF6C6TcM2gyy2ZAKeJoUhMNb1L"
"67krqDMqjkkixdfypnCCgSyUm2FoqAE8KB1hgRAtCaBp"
);
break;
}
Expand Down Expand Up @@ -13247,7 +13254,7 @@ pub(crate) mod tests {
// No more slots should be shrunk
assert_eq!(bank2.shrink_candidate_slots(), 0);
// alive_counts represents the count of alive accounts in the three slots 0,1,2
assert_eq!(alive_counts, vec![11, 1, 7]);
assert_eq!(alive_counts, vec![9, 1, 7]);
}

#[test]
Expand Down Expand Up @@ -13295,7 +13302,7 @@ pub(crate) mod tests {
.map(|_| bank.process_stale_slot_with_budget(0, force_to_return_alive_account))
.sum();
// consumed_budgets represents the count of alive accounts in the three slots 0,1,2
assert_eq!(consumed_budgets, 12);
assert_eq!(consumed_budgets, 10);
}

#[test]
Expand Down
35 changes: 35 additions & 0 deletions runtime/src/bank/builtin_programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,41 @@ mod tests {
solana_sdk::{feature_set::FeatureSet, genesis_config::create_genesis_config},
};

#[test]
fn test_apply_builtin_program_feature_transitions_for_new_epoch() {
let (genesis_config, _mint_keypair) = create_genesis_config(100_000);

let mut bank = Bank::new_for_tests(&genesis_config);
bank.feature_set = Arc::new(FeatureSet::all_enabled());
bank.finish_init(&genesis_config, None, false);

// Overwrite precompile accounts to simulate a cluster which already added precompiles.
for precompile in get_precompiles() {
bank.store_account(&precompile.program_id, &AccountSharedData::default());
// Simulate cluster which added ed25519 precompile with a system program owner
if precompile.program_id == ed25519_program::id() {
bank.add_precompiled_account_with_owner(
&precompile.program_id,
solana_sdk::system_program::id(),
);
} else {
bank.add_precompiled_account(&precompile.program_id);
}
}

// Normally feature transitions are applied to a bank that hasn't been
// frozen yet. Freeze the bank early to ensure that no account changes
// are made.
bank.freeze();

// Simulate crossing an epoch boundary for a new bank
let only_apply_transitions_for_new_features = true;
bank.apply_builtin_program_feature_transitions(
only_apply_transitions_for_new_features,
&HashSet::new(),
);
}

#[test]
fn test_startup_from_snapshot_after_precompile_transition() {
let (genesis_config, _mint_keypair) = create_genesis_config(100_000);
Expand Down
20 changes: 13 additions & 7 deletions runtime/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ pub enum BuiltinFeatureTransition {
/// Remove a builtin program if a feature is activated or
/// retain a previously added builtin.
RemoveOrRetain {
previous_builtin: Builtin,
previously_added_builtin: Builtin,
addition_feature_id: Pubkey,
removal_feature_id: Pubkey,
},
}
Expand All @@ -139,14 +140,17 @@ impl BuiltinFeatureTransition {
}
}
Self::RemoveOrRetain {
previous_builtin,
previously_added_builtin,
addition_feature_id,
removal_feature_id,
} => {
if should_apply_action_for_feature(removal_feature_id) {
Some(BuiltinAction::Remove(previous_builtin.id))
} else {
Some(BuiltinAction::Remove(previously_added_builtin.id))
} else if should_apply_action_for_feature(addition_feature_id) {
// Retaining is no different from adding a new builtin.
Some(BuiltinAction::Add(previous_builtin.clone()))
Some(BuiltinAction::Add(previously_added_builtin.clone()))
} else {
None
}
}
}
Expand Down Expand Up @@ -200,19 +204,21 @@ fn builtin_feature_transitions() -> Vec<BuiltinFeatureTransition> {
feature_id: feature_set::add_compute_budget_program::id(),
},
BuiltinFeatureTransition::RemoveOrRetain {
previous_builtin: Builtin::new(
previously_added_builtin: Builtin::new(
"secp256k1_program",
solana_sdk::secp256k1_program::id(),
dummy_process_instruction,
),
addition_feature_id: feature_set::secp256k1_program_enabled::id(),
removal_feature_id: feature_set::prevent_calling_precompiles_as_programs::id(),
},
BuiltinFeatureTransition::RemoveOrRetain {
previous_builtin: Builtin::new(
previously_added_builtin: Builtin::new(
"ed25519_program",
solana_sdk::ed25519_program::id(),
dummy_process_instruction,
),
addition_feature_id: feature_set::ed25519_program_enabled::id(),
removal_feature_id: feature_set::prevent_calling_precompiles_as_programs::id(),
},
BuiltinFeatureTransition::Add {
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/genesis_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn bootstrap_validator_stake_lamports() -> u64 {

// Number of lamports automatically used for genesis accounts
pub const fn genesis_sysvar_and_builtin_program_lamports() -> u64 {
const NUM_BUILTIN_PROGRAMS: u64 = 6;
const NUM_BUILTIN_PROGRAMS: u64 = 4;
const FEES_SYSVAR_MIN_BALANCE: u64 = 946_560;
const STAKE_HISTORY_MIN_BALANCE: u64 = 114_979_200;
const CLOCK_SYSVAR_MIN_BALANCE: u64 = 1_169_280;
Expand Down
5 changes: 5 additions & 0 deletions sdk/src/feature_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ pub mod full_inflation {
}
}

pub mod secp256k1_program_enabled {
solana_sdk::declare_id!("E3PHP7w8kB7np3CTQ1qQ2tW3KCtjRSXBQgW9vM2mWv2Y");
}

pub mod spl_token_v2_multisig_fix {
solana_sdk::declare_id!("E5JiFDQCwyC6QfT9REFyMpfK2mHcmv1GUDySU1Ue7TYv");
}
Expand Down Expand Up @@ -314,6 +318,7 @@ pub mod record_instruction_in_transaction_context_push {
lazy_static! {
/// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
(secp256k1_program_enabled::id(), "secp256k1 program"),
(deprecate_rewards_sysvar::id(), "deprecate unused rewards sysvar"),
(pico_inflation::id(), "pico inflation"),
(full_inflation::devnet_and_testnet::id(), "full inflation on devnet and testnet"),
Expand Down