Fix - `Bank::compute_active_feature_set()` and `Bank::apply_feature_activations()` (#34124)
* Moves modification of feature accounts from Bank::compute_active_feature_set() into Bank::apply_feature_activations(). * Renames allow_new_activations and newly_activated to include_pending and pending. * Fix test_compute_active_feature_set.
This commit is contained in:
parent
5658d6ee5b
commit
6b8545061f
|
@ -7968,6 +7968,19 @@ impl Bank {
|
||||||
self.compute_active_feature_set(allow_new_activations);
|
self.compute_active_feature_set(allow_new_activations);
|
||||||
self.feature_set = Arc::new(feature_set);
|
self.feature_set = Arc::new(feature_set);
|
||||||
|
|
||||||
|
// Update activation slot of features in `new_feature_activations`
|
||||||
|
for feature_id in new_feature_activations.iter() {
|
||||||
|
if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
|
||||||
|
if let Some(mut feature) = feature::from_account(&account) {
|
||||||
|
feature.activated_at = Some(self.slot());
|
||||||
|
if feature::to_account(&feature, &mut account).is_some() {
|
||||||
|
self.store_account(feature_id, &account);
|
||||||
|
}
|
||||||
|
info!("Feature {} activated at slot {}", feature_id, self.slot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
|
if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
|
||||||
*self.inflation.write().unwrap() = Inflation::pico();
|
*self.inflation.write().unwrap() = Inflation::pico();
|
||||||
self.fee_rate_governor.burn_percent = 50; // 50% fee burn
|
self.fee_rate_governor.burn_percent = 50; // 50% fee burn
|
||||||
|
@ -8036,38 +8049,27 @@ impl Bank {
|
||||||
|
|
||||||
/// Compute the active feature set based on the current bank state,
|
/// Compute the active feature set based on the current bank state,
|
||||||
/// and return it together with the set of newly activated features.
|
/// and return it together with the set of newly activated features.
|
||||||
fn compute_active_feature_set(
|
fn compute_active_feature_set(&self, include_pending: bool) -> (FeatureSet, HashSet<Pubkey>) {
|
||||||
&mut self,
|
|
||||||
allow_new_activations: bool,
|
|
||||||
) -> (FeatureSet, HashSet<Pubkey>) {
|
|
||||||
let mut active = self.feature_set.active.clone();
|
let mut active = self.feature_set.active.clone();
|
||||||
let mut inactive = HashSet::new();
|
let mut inactive = HashSet::new();
|
||||||
let mut newly_activated = HashSet::new();
|
let mut pending = HashSet::new();
|
||||||
let slot = self.slot();
|
let slot = self.slot();
|
||||||
|
|
||||||
for feature_id in &self.feature_set.inactive {
|
for feature_id in &self.feature_set.inactive {
|
||||||
let mut activated = None;
|
let mut activated = None;
|
||||||
if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
|
if let Some(account) = self.get_account_with_fixed_root(feature_id) {
|
||||||
if let Some(mut feature) = feature::from_account(&account) {
|
if let Some(feature) = feature::from_account(&account) {
|
||||||
match feature.activated_at {
|
match feature.activated_at {
|
||||||
None => {
|
None if include_pending => {
|
||||||
if allow_new_activations {
|
// Feature activation is pending
|
||||||
// Feature has been requested, activate it now
|
pending.insert(*feature_id);
|
||||||
feature.activated_at = Some(slot);
|
|
||||||
if feature::to_account(&feature, &mut account).is_some() {
|
|
||||||
self.store_account(feature_id, &account);
|
|
||||||
}
|
|
||||||
newly_activated.insert(*feature_id);
|
|
||||||
activated = Some(slot);
|
activated = Some(slot);
|
||||||
info!("Feature {} activated at slot {}", feature_id, slot);
|
|
||||||
}
|
}
|
||||||
}
|
Some(activation_slot) if slot >= activation_slot => {
|
||||||
Some(activation_slot) => {
|
// Feature has been activated already
|
||||||
if slot >= activation_slot {
|
|
||||||
// Feature is already active
|
|
||||||
activated = Some(activation_slot);
|
activated = Some(activation_slot);
|
||||||
}
|
}
|
||||||
}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8078,7 +8080,7 @@ impl Bank {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(FeatureSet { active, inactive }, newly_activated)
|
(FeatureSet { active, inactive }, pending)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_builtin_program_feature_transitions(
|
fn apply_builtin_program_feature_transitions(
|
||||||
|
|
|
@ -7749,25 +7749,26 @@ fn test_compute_active_feature_set() {
|
||||||
let feature = Feature::default();
|
let feature = Feature::default();
|
||||||
assert_eq!(feature.activated_at, None);
|
assert_eq!(feature.activated_at, None);
|
||||||
bank.store_account(&test_feature, &feature::create_account(&feature, 42));
|
bank.store_account(&test_feature, &feature::create_account(&feature, 42));
|
||||||
|
|
||||||
// Run `compute_active_feature_set` disallowing new activations
|
|
||||||
let (feature_set, new_activations) = bank.compute_active_feature_set(false);
|
|
||||||
assert!(new_activations.is_empty());
|
|
||||||
assert!(!feature_set.is_active(&test_feature));
|
|
||||||
let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
|
let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
|
||||||
.expect("from_account");
|
.expect("from_account");
|
||||||
assert_eq!(feature.activated_at, None);
|
assert_eq!(feature.activated_at, None);
|
||||||
|
|
||||||
// Run `compute_active_feature_set` allowing new activations
|
// Run `compute_active_feature_set` excluding pending activation
|
||||||
let (feature_set, new_activations) = bank.compute_active_feature_set(true);
|
let (feature_set, new_activations) = bank.compute_active_feature_set(false);
|
||||||
|
assert!(new_activations.is_empty());
|
||||||
|
assert!(!feature_set.is_active(&test_feature));
|
||||||
|
|
||||||
|
// Run `compute_active_feature_set` including pending activation
|
||||||
|
let (_feature_set, new_activations) = bank.compute_active_feature_set(true);
|
||||||
assert_eq!(new_activations.len(), 1);
|
assert_eq!(new_activations.len(), 1);
|
||||||
assert!(feature_set.is_active(&test_feature));
|
assert!(new_activations.contains(&test_feature));
|
||||||
|
|
||||||
|
// Actually activate the pending activation
|
||||||
|
bank.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, true);
|
||||||
let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
|
let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
|
||||||
.expect("from_account");
|
.expect("from_account");
|
||||||
assert_eq!(feature.activated_at, Some(1));
|
assert_eq!(feature.activated_at, Some(1));
|
||||||
|
|
||||||
// Running `compute_active_feature_set` will not cause new activations, but
|
|
||||||
// `test_feature` is now be active
|
|
||||||
let (feature_set, new_activations) = bank.compute_active_feature_set(true);
|
let (feature_set, new_activations) = bank.compute_active_feature_set(true);
|
||||||
assert!(new_activations.is_empty());
|
assert!(new_activations.is_empty());
|
||||||
assert!(feature_set.is_active(&test_feature));
|
assert!(feature_set.is_active(&test_feature));
|
||||||
|
|
Loading…
Reference in New Issue