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

Commit a525b16

Browse files
committed
Skip adding builtins if they will be removed
1 parent 1351c1b commit a525b16

File tree

3 files changed

+114
-113
lines changed

3 files changed

+114
-113
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: 30 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use {
4646
accounts_update_notifier_interface::AccountsUpdateNotifier,
4747
ancestors::{Ancestors, AncestorsForSerialization},
4848
blockhash_queue::BlockhashQueue,
49-
builtins::{self, ActivationType, Builtin, Builtins},
49+
builtins::{self, BuiltinAction, BuiltinFeatureTransition, Builtins},
5050
cost_tracker::CostTracker,
5151
epoch_stakes::{EpochStakes, NodeVoteAccounts},
5252
inline_spl_associated_token_account, inline_spl_token,
@@ -1196,9 +1196,9 @@ pub struct Bank {
11961196

11971197
compute_budget: Option<ComputeBudget>,
11981198

1199-
/// Builtin programs activated dynamically by feature
1199+
/// Dynamic feature transitions for builtin programs
12001200
#[allow(clippy::rc_buffer)]
1201-
feature_builtins: Arc<Vec<(Builtin, Pubkey, ActivationType)>>,
1201+
builtin_feature_transitions: Arc<Vec<BuiltinFeatureTransition>>,
12021202

12031203
/// Protocol-level rewards that were distributed by this bank
12041204
pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
@@ -1367,7 +1367,7 @@ impl Bank {
13671367
is_delta: AtomicBool::default(),
13681368
builtin_programs: BuiltinPrograms::default(),
13691369
compute_budget: Option::<ComputeBudget>::default(),
1370-
feature_builtins: Arc::<Vec<(Builtin, Pubkey, ActivationType)>>::default(),
1370+
builtin_feature_transitions: Arc::<Vec<BuiltinFeatureTransition>>::default(),
13711371
rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
13721372
cluster_type: Option::<ClusterType>::default(),
13731373
lazy_rent_collection: AtomicBool::default(),
@@ -1703,7 +1703,7 @@ impl Bank {
17031703
signature_count: AtomicU64::new(0),
17041704
builtin_programs,
17051705
compute_budget: parent.compute_budget,
1706-
feature_builtins: parent.feature_builtins.clone(),
1706+
builtin_feature_transitions: parent.builtin_feature_transitions.clone(),
17071707
hard_forks: parent.hard_forks.clone(),
17081708
rewards: RwLock::new(vec![]),
17091709
cluster_type: parent.cluster_type,
@@ -1989,7 +1989,7 @@ impl Bank {
19891989
is_delta: AtomicBool::new(fields.is_delta),
19901990
builtin_programs: new(),
19911991
compute_budget: None,
1992-
feature_builtins: new(),
1992+
builtin_feature_transitions: new(),
19931993
rewards: new(),
19941994
cluster_type: Some(genesis_config.cluster_type),
19951995
lazy_rent_collection: new(),
@@ -5514,8 +5514,8 @@ impl Bank {
55145514
.genesis_builtins
55155515
.extend_from_slice(&additional_builtins.genesis_builtins);
55165516
builtins
5517-
.feature_builtins
5518-
.extend_from_slice(&additional_builtins.feature_builtins);
5517+
.feature_transitions
5518+
.extend_from_slice(&additional_builtins.feature_transitions);
55195519
}
55205520
if !debug_do_not_add_builtins {
55215521
for builtin in builtins.genesis_builtins {
@@ -5531,7 +5531,7 @@ impl Bank {
55315531
}
55325532
}
55335533
}
5534-
self.feature_builtins = Arc::new(builtins.feature_builtins);
5534+
self.builtin_feature_transitions = Arc::new(builtins.feature_transitions);
55355535

55365536
self.apply_feature_activations(true, debug_do_not_add_builtins);
55375537
}
@@ -6238,29 +6238,9 @@ impl Bank {
62386238
debug!("Added program {} under {:?}", name, program_id);
62396239
}
62406240

6241-
/// Replace a builtin instruction processor if it already exists
6242-
pub fn replace_builtin(
6243-
&mut self,
6244-
name: &str,
6245-
program_id: &Pubkey,
6246-
process_instruction: ProcessInstructionWithContext,
6247-
) {
6248-
debug!("Replacing program {} under {:?}", name, program_id);
6249-
self.add_builtin_account(name, program_id, true);
6250-
if let Some(entry) = self
6251-
.builtin_programs
6252-
.vec
6253-
.iter_mut()
6254-
.find(|entry| entry.program_id == *program_id)
6255-
{
6256-
entry.process_instruction = process_instruction;
6257-
}
6258-
debug!("Replaced program {} under {:?}", name, program_id);
6259-
}
6260-
62616241
/// Remove a builtin instruction processor if it already exists
6262-
pub fn remove_builtin(&mut self, name: &str, program_id: &Pubkey) {
6263-
debug!("Removing program {} under {:?}", name, program_id);
6242+
pub fn remove_builtin(&mut self, program_id: &Pubkey) {
6243+
debug!("Removing program {}", program_id);
62646244
// Don't remove the account since the bank expects the account state to
62656245
// be idempotent
62666246
if let Some(position) = self
@@ -6271,7 +6251,7 @@ impl Bank {
62716251
{
62726252
self.builtin_programs.vec.remove(position);
62736253
}
6274-
debug!("Removed program {} under {:?}", name, program_id);
6254+
debug!("Removed program {}", program_id);
62756255
}
62766256

62776257
pub fn add_precompile(&mut self, program_id: &Pubkey) {
@@ -6451,7 +6431,7 @@ impl Bank {
64516431
}
64526432

64536433
if !debug_do_not_add_builtins {
6454-
self.ensure_feature_builtins(init_finish_or_warp, &new_feature_activations);
6434+
self.apply_builtin_feature_transitions(init_finish_or_warp, &new_feature_activations);
64556435
self.reconfigure_token2_native_mint();
64566436
}
64576437
self.ensure_no_storage_rewards_pool();
@@ -6508,33 +6488,34 @@ impl Bank {
65086488
newly_activated
65096489
}
65106490

6511-
fn ensure_feature_builtins(
6491+
fn apply_builtin_feature_transitions(
65126492
&mut self,
65136493
init_or_warp: bool,
65146494
new_feature_activations: &HashSet<Pubkey>,
65156495
) {
6516-
let feature_builtins = self.feature_builtins.clone();
6517-
for (builtin, feature, activation_type) in feature_builtins.iter() {
6518-
let should_populate = init_or_warp && self.feature_set.is_active(feature)
6519-
|| !init_or_warp && new_feature_activations.contains(feature);
6520-
if should_populate {
6521-
match activation_type {
6522-
ActivationType::NewProgram => self.add_builtin(
6523-
&builtin.name,
6524-
&builtin.id,
6525-
builtin.process_instruction_with_context,
6526-
),
6527-
ActivationType::NewVersion => self.replace_builtin(
6496+
let feature_set = self.feature_set.clone();
6497+
let should_apply_action_for_feature = |feature_id: &Pubkey| -> bool {
6498+
if init_or_warp {
6499+
feature_set.is_active(feature_id)
6500+
} else {
6501+
new_feature_activations.contains(feature_id)
6502+
}
6503+
};
6504+
6505+
let builtin_feature_transitions = self.builtin_feature_transitions.clone();
6506+
for transition in builtin_feature_transitions.iter() {
6507+
if let Some(builtin_action) = transition.to_action(&should_apply_action_for_feature) {
6508+
match builtin_action {
6509+
BuiltinAction::Add(builtin) => self.add_builtin(
65286510
&builtin.name,
65296511
&builtin.id,
65306512
builtin.process_instruction_with_context,
65316513
),
6532-
ActivationType::RemoveProgram => {
6533-
self.remove_builtin(&builtin.name, &builtin.id)
6534-
}
6514+
BuiltinAction::Remove { program_id } => self.remove_builtin(&program_id),
65356515
}
65366516
}
65376517
}
6518+
65386519
for precompile in get_precompiles() {
65396520
#[allow(clippy::blocks_in_if_conditions)]
65406521
if precompile.feature.map_or(false, |ref feature_id| {
@@ -13350,16 +13331,6 @@ pub(crate) mod tests {
1335013331
mock_ix_processor,
1335113332
);
1335213333
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
13353-
13354-
Arc::get_mut(&mut bank).unwrap().replace_builtin(
13355-
"mock_program v2",
13356-
&program_id,
13357-
mock_ix_processor,
13358-
);
13359-
assert_eq!(
13360-
bank.get_account_modified_slot(&program_id).unwrap().1,
13361-
bank.slot()
13362-
);
1336313334
}
1336413335

1336513336
#[test]

runtime/src/builtins.rs

Lines changed: 80 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,61 @@ macro_rules! with_program_logging {
5151
};
5252
}
5353

54-
#[derive(AbiExample, Debug, Clone)]
55-
pub enum ActivationType {
56-
NewProgram,
57-
NewVersion,
58-
RemoveProgram,
54+
/// State transition enum used for adding and removing builtin programs through
55+
/// feature activations.
56+
#[derive(Debug, Clone)]
57+
pub enum BuiltinFeatureTransition {
58+
/// Add a builtin program if a feature is activated.
59+
Add {
60+
builtin: Builtin,
61+
feature_id: Pubkey,
62+
},
63+
/// Remove a builtin program if a feature is activated or
64+
/// retain a previously added builtin.
65+
RemoveOrRetain {
66+
previous_builtin: Builtin,
67+
removal_feature_id: Pubkey,
68+
},
69+
}
70+
71+
/// Actions taken by a bank when managing the list of active builtin programs.
72+
#[derive(Debug, Clone)]
73+
pub enum BuiltinAction {
74+
Add(Builtin),
75+
Remove { program_id: Pubkey },
76+
}
77+
78+
impl BuiltinFeatureTransition {
79+
pub fn to_action(
80+
&self,
81+
should_apply_action_for_feature: &impl Fn(&Pubkey) -> bool,
82+
) -> Option<BuiltinAction> {
83+
match self {
84+
Self::Add {
85+
builtin,
86+
feature_id,
87+
} => {
88+
if should_apply_action_for_feature(feature_id) {
89+
Some(BuiltinAction::Add(builtin.clone()))
90+
} else {
91+
None
92+
}
93+
}
94+
Self::RemoveOrRetain {
95+
previous_builtin,
96+
removal_feature_id,
97+
} => {
98+
if should_apply_action_for_feature(removal_feature_id) {
99+
Some(BuiltinAction::Remove {
100+
program_id: previous_builtin.id,
101+
})
102+
} else {
103+
// Retaining is no different from adding a new builtin.
104+
Some(BuiltinAction::Add(previous_builtin.clone()))
105+
}
106+
}
107+
}
108+
}
59109
}
60110

61111
#[derive(Clone)]
@@ -101,8 +151,8 @@ pub struct Builtins {
101151
/// Builtin programs that are always available
102152
pub genesis_builtins: Vec<Builtin>,
103153

104-
/// Builtin programs activated or deactivated dynamically by feature
105-
pub feature_builtins: Vec<(Builtin, Pubkey, ActivationType)>,
154+
/// Dynamic feature transitions for builtin programs
155+
pub feature_transitions: Vec<BuiltinFeatureTransition>,
106156
}
107157

108158
/// Builtin programs that are always available
@@ -133,11 +183,6 @@ fn genesis_builtins() -> Vec<Builtin> {
133183
solana_sdk::secp256k1_program::id(),
134184
dummy_process_instruction,
135185
),
136-
Builtin::new(
137-
"ed25519_program",
138-
solana_sdk::ed25519_program::id(),
139-
dummy_process_instruction,
140-
),
141186
]
142187
}
143188

@@ -150,73 +195,61 @@ fn dummy_process_instruction(
150195
Ok(())
151196
}
152197

153-
/// Builtin programs activated dynamically by feature
154-
///
155-
/// Note: If the feature_builtin is intended to replace another builtin program, it must have a new
156-
/// name.
157-
/// This is to enable the runtime to determine categorically whether the builtin update has
158-
/// occurred, and preserve idempotency in Bank::add_native_program across genesis, snapshot, and
159-
/// normal child Bank creation.
160-
/// https://github.com/solana-labs/solana/blob/84b139cc94b5be7c9e0c18c2ad91743231b85a0d/runtime/src/bank.rs#L1723
161-
fn feature_builtins() -> Vec<(Builtin, Pubkey, ActivationType)> {
198+
/// Dynamic feature transitions for builtin programs
199+
fn builtin_feature_transitions() -> Vec<BuiltinFeatureTransition> {
162200
vec![
163-
(
164-
Builtin::new(
201+
BuiltinFeatureTransition::Add {
202+
builtin: Builtin::new(
165203
"compute_budget_program",
166204
solana_sdk::compute_budget::id(),
167205
solana_compute_budget_program::process_instruction,
168206
),
169-
feature_set::add_compute_budget_program::id(),
170-
ActivationType::NewProgram,
171-
),
207+
feature_id: feature_set::add_compute_budget_program::id(),
208+
},
172209
// TODO when feature `prevent_calling_precompiles_as_programs` is
173210
// cleaned up also remove "secp256k1_program" from the main builtins
174211
// list
175-
(
176-
Builtin::new(
212+
BuiltinFeatureTransition::RemoveOrRetain {
213+
previous_builtin: Builtin::new(
177214
"secp256k1_program",
178215
solana_sdk::secp256k1_program::id(),
179216
dummy_process_instruction,
180217
),
181-
feature_set::prevent_calling_precompiles_as_programs::id(),
182-
ActivationType::RemoveProgram,
183-
),
218+
removal_feature_id: feature_set::prevent_calling_precompiles_as_programs::id(),
219+
},
184220
// TODO when feature `prevent_calling_precompiles_as_programs` is
185221
// cleaned up also remove "ed25519_program" from the main builtins
186222
// list
187-
(
188-
Builtin::new(
223+
BuiltinFeatureTransition::RemoveOrRetain {
224+
previous_builtin: Builtin::new(
189225
"ed25519_program",
190226
solana_sdk::ed25519_program::id(),
191227
dummy_process_instruction,
192228
),
193-
feature_set::prevent_calling_precompiles_as_programs::id(),
194-
ActivationType::RemoveProgram,
195-
),
196-
(
197-
Builtin::new(
229+
removal_feature_id: feature_set::prevent_calling_precompiles_as_programs::id(),
230+
},
231+
BuiltinFeatureTransition::Add {
232+
builtin: Builtin::new(
198233
"address_lookup_table_program",
199234
solana_address_lookup_table_program::id(),
200235
solana_address_lookup_table_program::processor::process_instruction,
201236
),
202-
feature_set::versioned_tx_message_enabled::id(),
203-
ActivationType::NewProgram,
204-
),
205-
(
206-
Builtin::new(
237+
feature_id: feature_set::versioned_tx_message_enabled::id(),
238+
},
239+
BuiltinFeatureTransition::Add {
240+
builtin: Builtin::new(
207241
"zk_token_proof_program",
208242
solana_zk_token_sdk::zk_token_proof_program::id(),
209243
with_program_logging!(solana_zk_token_proof_program::process_instruction),
210244
),
211-
feature_set::zk_token_sdk_enabled::id(),
212-
ActivationType::NewProgram,
213-
),
245+
feature_id: feature_set::zk_token_sdk_enabled::id(),
246+
},
214247
]
215248
}
216249

217250
pub(crate) fn get() -> Builtins {
218251
Builtins {
219252
genesis_builtins: genesis_builtins(),
220-
feature_builtins: feature_builtins(),
253+
feature_transitions: builtin_feature_transitions(),
221254
}
222255
}

0 commit comments

Comments
 (0)