46
46
accounts_update_notifier_interface::AccountsUpdateNotifier,
47
47
ancestors::{Ancestors, AncestorsForSerialization},
48
48
blockhash_queue::BlockhashQueue,
49
- builtins::{self, ActivationType, Builtin , Builtins},
49
+ builtins::{self, BuiltinAction, BuiltinFeatureTransition , Builtins},
50
50
cost_tracker::CostTracker,
51
51
epoch_stakes::{EpochStakes, NodeVoteAccounts},
52
52
inline_spl_associated_token_account, inline_spl_token,
@@ -157,6 +157,7 @@ use {
157
157
};
158
158
159
159
mod address_lookup_table;
160
+ mod builtin_programs;
160
161
mod sysvar_cache;
161
162
mod transaction_account_state_info;
162
163
@@ -1196,9 +1197,9 @@ pub struct Bank {
1196
1197
1197
1198
compute_budget: Option<ComputeBudget>,
1198
1199
1199
- /// Builtin programs activated dynamically by feature
1200
+ /// Dynamic feature transitions for builtin programs
1200
1201
#[allow(clippy::rc_buffer)]
1201
- feature_builtins : Arc<Vec<(Builtin, Pubkey, ActivationType) >>,
1202
+ builtin_feature_transitions : Arc<Vec<BuiltinFeatureTransition >>,
1202
1203
1203
1204
/// Protocol-level rewards that were distributed by this bank
1204
1205
pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
@@ -1367,7 +1368,7 @@ impl Bank {
1367
1368
is_delta: AtomicBool::default(),
1368
1369
builtin_programs: BuiltinPrograms::default(),
1369
1370
compute_budget: Option::<ComputeBudget>::default(),
1370
- feature_builtins : Arc::<Vec<(Builtin, Pubkey, ActivationType) >>::default(),
1371
+ builtin_feature_transitions : Arc::<Vec<BuiltinFeatureTransition >>::default(),
1371
1372
rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
1372
1373
cluster_type: Option::<ClusterType>::default(),
1373
1374
lazy_rent_collection: AtomicBool::default(),
@@ -1703,7 +1704,7 @@ impl Bank {
1703
1704
signature_count: AtomicU64::new(0),
1704
1705
builtin_programs,
1705
1706
compute_budget: parent.compute_budget,
1706
- feature_builtins : parent.feature_builtins .clone(),
1707
+ builtin_feature_transitions : parent.builtin_feature_transitions .clone(),
1707
1708
hard_forks: parent.hard_forks.clone(),
1708
1709
rewards: RwLock::new(vec![]),
1709
1710
cluster_type: parent.cluster_type,
@@ -1989,7 +1990,7 @@ impl Bank {
1989
1990
is_delta: AtomicBool::new(fields.is_delta),
1990
1991
builtin_programs: new(),
1991
1992
compute_budget: None,
1992
- feature_builtins : new(),
1993
+ builtin_feature_transitions : new(),
1993
1994
rewards: new(),
1994
1995
cluster_type: Some(genesis_config.cluster_type),
1995
1996
lazy_rent_collection: new(),
@@ -5514,8 +5515,8 @@ impl Bank {
5514
5515
.genesis_builtins
5515
5516
.extend_from_slice(&additional_builtins.genesis_builtins);
5516
5517
builtins
5517
- .feature_builtins
5518
- .extend_from_slice(&additional_builtins.feature_builtins );
5518
+ .feature_transitions
5519
+ .extend_from_slice(&additional_builtins.feature_transitions );
5519
5520
}
5520
5521
if !debug_do_not_add_builtins {
5521
5522
for builtin in builtins.genesis_builtins {
@@ -5531,7 +5532,7 @@ impl Bank {
5531
5532
}
5532
5533
}
5533
5534
}
5534
- self.feature_builtins = Arc::new(builtins.feature_builtins );
5535
+ self.builtin_feature_transitions = Arc::new(builtins.feature_transitions );
5535
5536
5536
5537
self.apply_feature_activations(true, debug_do_not_add_builtins);
5537
5538
}
@@ -6238,29 +6239,9 @@ impl Bank {
6238
6239
debug!("Added program {} under {:?}", name, program_id);
6239
6240
}
6240
6241
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
-
6261
6242
/// 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);
6243
+ pub fn remove_builtin(&mut self, program_id: &Pubkey) {
6244
+ debug!("Removing program {}" , program_id);
6264
6245
// Don't remove the account since the bank expects the account state to
6265
6246
// be idempotent
6266
6247
if let Some(position) = self
@@ -6271,7 +6252,7 @@ impl Bank {
6271
6252
{
6272
6253
self.builtin_programs.vec.remove(position);
6273
6254
}
6274
- debug!("Removed program {} under {:?}", name , program_id);
6255
+ debug!("Removed program {}" , program_id);
6275
6256
}
6276
6257
6277
6258
pub fn add_precompile(&mut self, program_id: &Pubkey) {
@@ -6451,7 +6432,11 @@ impl Bank {
6451
6432
}
6452
6433
6453
6434
if !debug_do_not_add_builtins {
6454
- self.ensure_feature_builtins(init_finish_or_warp, &new_feature_activations);
6435
+ let apply_transitions_for_new_features = !init_finish_or_warp;
6436
+ self.apply_builtin_program_feature_transitions(
6437
+ apply_transitions_for_new_features,
6438
+ &new_feature_activations,
6439
+ );
6455
6440
self.reconfigure_token2_native_mint();
6456
6441
}
6457
6442
self.ensure_no_storage_rewards_pool();
@@ -6508,33 +6493,34 @@ impl Bank {
6508
6493
newly_activated
6509
6494
}
6510
6495
6511
- fn ensure_feature_builtins (
6496
+ fn apply_builtin_program_feature_transitions (
6512
6497
&mut self,
6513
- init_or_warp : bool,
6498
+ apply_transitions_for_new_features : bool,
6514
6499
new_feature_activations: &HashSet<Pubkey>,
6515
6500
) {
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(
6501
+ let feature_set = self.feature_set.clone();
6502
+ let should_apply_action_for_feature = |feature_id: &Pubkey| -> bool {
6503
+ if apply_transitions_for_new_features {
6504
+ new_feature_activations.contains(feature_id)
6505
+ } else {
6506
+ feature_set.is_active(feature_id)
6507
+ }
6508
+ };
6509
+
6510
+ let builtin_feature_transitions = self.builtin_feature_transitions.clone();
6511
+ for transition in builtin_feature_transitions.iter() {
6512
+ if let Some(builtin_action) = transition.to_action(&should_apply_action_for_feature) {
6513
+ match builtin_action {
6514
+ BuiltinAction::Add(builtin) => self.add_builtin(
6528
6515
&builtin.name,
6529
6516
&builtin.id,
6530
6517
builtin.process_instruction_with_context,
6531
6518
),
6532
- ActivationType::RemoveProgram => {
6533
- self.remove_builtin(&builtin.name, &builtin.id)
6534
- }
6519
+ BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id),
6535
6520
}
6536
6521
}
6537
6522
}
6523
+
6538
6524
for precompile in get_precompiles() {
6539
6525
#[allow(clippy::blocks_in_if_conditions)]
6540
6526
if precompile.feature.map_or(false, |ref feature_id| {
@@ -13350,16 +13336,6 @@ pub(crate) mod tests {
13350
13336
mock_ix_processor,
13351
13337
);
13352
13338
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
- );
13363
13339
}
13364
13340
13365
13341
#[test]
0 commit comments