Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit ab4ee04

Browse files
jstarrymergify-bot
authored andcommitted
Skip adding builtins if they will be removed (#23233)
* Add failing test for precompile transition * Skip adding builtins if they will be removed * cargo clean * nits * fix abi check * remove workaround Co-authored-by: Jack May <[email protected]> (cherry picked from commit 1719d23) # Conflicts: # runtime/src/bank.rs # runtime/src/builtins.rs
1 parent b2b92d7 commit ab4ee04

File tree

4 files changed

+158
-119
lines changed

4 files changed

+158
-119
lines changed

ledger/src/builtins.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use {
2-
solana_runtime::builtins::{ActivationType, Builtin, Builtins},
3-
solana_sdk::pubkey::Pubkey,
4-
};
1+
use solana_runtime::builtins::{Builtin, BuiltinFeatureTransition, Builtins};
52

63
macro_rules! to_builtin {
74
($b:expr) => {
@@ -37,14 +34,14 @@ fn genesis_builtins(bpf_jit: bool) -> Vec<Builtin> {
3734
]
3835
}
3936

40-
/// Builtin programs activated dynamically by feature
41-
fn feature_builtins() -> Vec<(Builtin, Pubkey, ActivationType)> {
37+
/// Dynamic feature transitions for builtin programs
38+
fn builtin_feature_transitions() -> Vec<BuiltinFeatureTransition> {
4239
vec![]
4340
}
4441

4542
pub(crate) fn get(bpf_jit: bool) -> Builtins {
4643
Builtins {
4744
genesis_builtins: genesis_builtins(bpf_jit),
48-
feature_builtins: feature_builtins(),
45+
feature_transitions: builtin_feature_transitions(),
4946
}
5047
}

runtime/src/bank.rs

Lines changed: 40 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use {
4949
accounts_update_notifier_interface::AccountsUpdateNotifier,
5050
ancestors::{Ancestors, AncestorsForSerialization},
5151
blockhash_queue::BlockhashQueue,
52-
builtins::{self, ActivationType, Builtin, Builtins},
52+
builtins::{self, BuiltinAction, BuiltinFeatureTransition, Builtins},
5353
cost_tracker::CostTracker,
5454
epoch_stakes::{EpochStakes, NodeVoteAccounts},
5555
inline_spl_associated_token_account, inline_spl_token,
@@ -162,6 +162,11 @@ use {
162162
},
163163
};
164164

165+
<<<<<<< HEAD
166+
=======
167+
mod address_lookup_table;
168+
mod builtin_programs;
169+
>>>>>>> 1719d2349 (Skip adding builtins if they will be removed (#23233))
165170
mod sysvar_cache;
166171
mod transaction_account_state_info;
167172

@@ -1181,9 +1186,9 @@ pub struct Bank {
11811186

11821187
compute_budget: Option<ComputeBudget>,
11831188

1184-
/// Builtin programs activated dynamically by feature
1189+
/// Dynamic feature transitions for builtin programs
11851190
#[allow(clippy::rc_buffer)]
1186-
feature_builtins: Arc<Vec<(Builtin, Pubkey, ActivationType)>>,
1191+
builtin_feature_transitions: Arc<Vec<BuiltinFeatureTransition>>,
11871192

11881193
/// Protocol-level rewards that were distributed by this bank
11891194
pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
@@ -1352,7 +1357,7 @@ impl Bank {
13521357
is_delta: AtomicBool::default(),
13531358
builtin_programs: BuiltinPrograms::default(),
13541359
compute_budget: Option::<ComputeBudget>::default(),
1355-
feature_builtins: Arc::<Vec<(Builtin, Pubkey, ActivationType)>>::default(),
1360+
builtin_feature_transitions: Arc::<Vec<BuiltinFeatureTransition>>::default(),
13561361
rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
13571362
cluster_type: Option::<ClusterType>::default(),
13581363
lazy_rent_collection: AtomicBool::default(),
@@ -1684,7 +1689,7 @@ impl Bank {
16841689
signature_count: AtomicU64::new(0),
16851690
builtin_programs,
16861691
compute_budget: parent.compute_budget,
1687-
feature_builtins: parent.feature_builtins.clone(),
1692+
builtin_feature_transitions: parent.builtin_feature_transitions.clone(),
16881693
hard_forks: parent.hard_forks.clone(),
16891694
rewards: RwLock::new(vec![]),
16901695
cluster_type: parent.cluster_type,
@@ -1970,7 +1975,7 @@ impl Bank {
19701975
is_delta: AtomicBool::new(fields.is_delta),
19711976
builtin_programs: new(),
19721977
compute_budget: None,
1973-
feature_builtins: new(),
1978+
builtin_feature_transitions: new(),
19741979
rewards: new(),
19751980
cluster_type: Some(genesis_config.cluster_type),
19761981
lazy_rent_collection: new(),
@@ -5472,8 +5477,8 @@ impl Bank {
54725477
.genesis_builtins
54735478
.extend_from_slice(&additional_builtins.genesis_builtins);
54745479
builtins
5475-
.feature_builtins
5476-
.extend_from_slice(&additional_builtins.feature_builtins);
5480+
.feature_transitions
5481+
.extend_from_slice(&additional_builtins.feature_transitions);
54775482
}
54785483
if !debug_do_not_add_builtins {
54795484
for builtin in builtins.genesis_builtins {
@@ -5489,7 +5494,7 @@ impl Bank {
54895494
}
54905495
}
54915496
}
5492-
self.feature_builtins = Arc::new(builtins.feature_builtins);
5497+
self.builtin_feature_transitions = Arc::new(builtins.feature_transitions);
54935498

54945499
self.apply_feature_activations(true, debug_do_not_add_builtins);
54955500
}
@@ -6224,29 +6229,9 @@ impl Bank {
62246229
debug!("Added program {} under {:?}", name, program_id);
62256230
}
62266231

6227-
/// Replace a builtin instruction processor if it already exists
6228-
pub fn replace_builtin(
6229-
&mut self,
6230-
name: &str,
6231-
program_id: &Pubkey,
6232-
process_instruction: ProcessInstructionWithContext,
6233-
) {
6234-
debug!("Replacing program {} under {:?}", name, program_id);
6235-
self.add_builtin_account(name, program_id, true);
6236-
if let Some(entry) = self
6237-
.builtin_programs
6238-
.vec
6239-
.iter_mut()
6240-
.find(|entry| entry.program_id == *program_id)
6241-
{
6242-
entry.process_instruction = process_instruction;
6243-
}
6244-
debug!("Replaced program {} under {:?}", name, program_id);
6245-
}
6246-
62476232
/// Remove a builtin instruction processor if it already exists
6248-
pub fn remove_builtin(&mut self, name: &str, program_id: &Pubkey) {
6249-
debug!("Removing program {} under {:?}", name, program_id);
6233+
pub fn remove_builtin(&mut self, program_id: &Pubkey) {
6234+
debug!("Removing program {}", program_id);
62506235
// Don't remove the account since the bank expects the account state to
62516236
// be idempotent
62526237
if let Some(position) = self
@@ -6257,7 +6242,7 @@ impl Bank {
62576242
{
62586243
self.builtin_programs.vec.remove(position);
62596244
}
6260-
debug!("Removed program {} under {:?}", name, program_id);
6245+
debug!("Removed program {}", program_id);
62616246
}
62626247

62636248
pub fn add_precompile(&mut self, program_id: &Pubkey) {
@@ -6455,7 +6440,11 @@ impl Bank {
64556440
}
64566441

64576442
if !debug_do_not_add_builtins {
6458-
self.ensure_feature_builtins(init_finish_or_warp, &new_feature_activations);
6443+
let apply_transitions_for_new_features = !init_finish_or_warp;
6444+
self.apply_builtin_program_feature_transitions(
6445+
apply_transitions_for_new_features,
6446+
&new_feature_activations,
6447+
);
64596448
self.reconfigure_token2_native_mint();
64606449
}
64616450
self.ensure_no_storage_rewards_pool();
@@ -6542,33 +6531,34 @@ impl Bank {
65426531
newly_activated
65436532
}
65446533

6545-
fn ensure_feature_builtins(
6534+
fn apply_builtin_program_feature_transitions(
65466535
&mut self,
6547-
init_or_warp: bool,
6536+
apply_transitions_for_new_features: bool,
65486537
new_feature_activations: &HashSet<Pubkey>,
65496538
) {
6550-
let feature_builtins = self.feature_builtins.clone();
6551-
for (builtin, feature, activation_type) in feature_builtins.iter() {
6552-
let should_populate = init_or_warp && self.feature_set.is_active(feature)
6553-
|| !init_or_warp && new_feature_activations.contains(feature);
6554-
if should_populate {
6555-
match activation_type {
6556-
ActivationType::NewProgram => self.add_builtin(
6557-
&builtin.name,
6558-
&builtin.id,
6559-
builtin.process_instruction_with_context,
6560-
),
6561-
ActivationType::NewVersion => self.replace_builtin(
6539+
let feature_set = self.feature_set.clone();
6540+
let should_apply_action_for_feature = |feature_id: &Pubkey| -> bool {
6541+
if apply_transitions_for_new_features {
6542+
new_feature_activations.contains(feature_id)
6543+
} else {
6544+
feature_set.is_active(feature_id)
6545+
}
6546+
};
6547+
6548+
let builtin_feature_transitions = self.builtin_feature_transitions.clone();
6549+
for transition in builtin_feature_transitions.iter() {
6550+
if let Some(builtin_action) = transition.to_action(&should_apply_action_for_feature) {
6551+
match builtin_action {
6552+
BuiltinAction::Add(builtin) => self.add_builtin(
65626553
&builtin.name,
65636554
&builtin.id,
65646555
builtin.process_instruction_with_context,
65656556
),
6566-
ActivationType::RemoveProgram => {
6567-
self.remove_builtin(&builtin.name, &builtin.id)
6568-
}
6557+
BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id),
65696558
}
65706559
}
65716560
}
6561+
65726562
for precompile in get_precompiles() {
65736563
#[allow(clippy::blocks_in_if_conditions)]
65746564
if precompile.feature.map_or(false, |ref feature_id| {
@@ -13412,16 +13402,6 @@ pub(crate) mod tests {
1341213402
mock_ix_processor,
1341313403
);
1341413404
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
13415-
13416-
Arc::get_mut(&mut bank).unwrap().replace_builtin(
13417-
"mock_program v2",
13418-
&program_id,
13419-
mock_ix_processor,
13420-
);
13421-
assert_eq!(
13422-
bank.get_account_modified_slot(&program_id).unwrap().1,
13423-
bank.slot()
13424-
);
1342513405
}
1342613406

1342713407
#[test]

runtime/src/bank/builtin_programs.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#[cfg(test)]
2+
mod tests {
3+
use {
4+
crate::bank::*,
5+
solana_sdk::{feature_set::FeatureSet, genesis_config::create_genesis_config},
6+
};
7+
8+
#[test]
9+
fn test_startup_from_snapshot_after_precompile_transition() {
10+
let (genesis_config, _mint_keypair) = create_genesis_config(100_000);
11+
12+
let mut bank = Bank::new_for_tests(&genesis_config);
13+
bank.feature_set = Arc::new(FeatureSet::all_enabled());
14+
bank.finish_init(&genesis_config, None, false);
15+
16+
// Overwrite precompile accounts to simulate a cluster which already added precompiles.
17+
for precompile in get_precompiles() {
18+
bank.store_account(&precompile.program_id, &AccountSharedData::default());
19+
bank.add_precompiled_account(&precompile.program_id);
20+
}
21+
22+
bank.freeze();
23+
24+
// Simulate starting up from snapshot finishing the initialization for a frozen bank
25+
bank.finish_init(&genesis_config, None, false);
26+
}
27+
}

0 commit comments

Comments
 (0)