Add new inflation feature-ids (#13671)
* Add new inflation feature-ids, and full_inflation default values * Compute inflation start from full_inflation activation * Include pico_inflation in inflation start computation * Add full-inflation constructor * Align inflation taper with rewards accrual start and catch overflow edge case
This commit is contained in:
parent
11e92f0c9f
commit
c75d97e3f2
|
@ -1335,6 +1335,32 @@ impl Bank {
|
|||
(examined_count, rewritten_count)
|
||||
}
|
||||
|
||||
// Calculates the starting-slot for inflation from the activation slot.
|
||||
// This method assumes that `pico_inflation` will be enabled before `full_inflation`, giving
|
||||
// precedence to the latter. However, since `pico_inflation` is fixed-rate Inflation, should
|
||||
// `pico_inflation` be enabled 2nd, the incorrect start slot provided here should have no
|
||||
// effect on the inflation calculation.
|
||||
fn get_inflation_start_slot(&self) -> Slot {
|
||||
self.feature_set
|
||||
.activated_slot(&feature_set::full_inflation::id())
|
||||
.unwrap_or_else(|| {
|
||||
self.feature_set
|
||||
.activated_slot(&feature_set::pico_inflation::id())
|
||||
.unwrap_or(0)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_inflation_num_slots(&self) -> u64 {
|
||||
let inflation_activation_slot = self.get_inflation_start_slot();
|
||||
// Normalize inflation_start to align with the start of rewards accrual.
|
||||
let inflation_start_slot = self.epoch_schedule.get_first_slot_in_epoch(
|
||||
self.epoch_schedule
|
||||
.get_epoch(inflation_activation_slot)
|
||||
.saturating_sub(1),
|
||||
);
|
||||
self.epoch_schedule.get_first_slot_in_epoch(self.epoch()) - inflation_start_slot
|
||||
}
|
||||
|
||||
// update rewards based on the previous epoch
|
||||
fn update_rewards(
|
||||
&mut self,
|
||||
|
@ -1346,9 +1372,9 @@ impl Bank {
|
|||
}
|
||||
// if I'm the first Bank in an epoch, count, claim, disburse rewards from Inflation
|
||||
|
||||
// calculated as: prev_slot / (slots / year)
|
||||
let slot_in_year =
|
||||
(self.epoch_schedule.get_last_slot_in_epoch(prev_epoch)) as f64 / self.slots_per_year;
|
||||
// calculated as: num_slots / (slots / year)
|
||||
let num_slots = self.get_inflation_num_slots();
|
||||
let slot_in_year = num_slots as f64 / self.slots_per_year;
|
||||
|
||||
let epoch_duration_in_years = self.epoch_duration_in_years(prev_epoch);
|
||||
|
||||
|
@ -4142,10 +4168,10 @@ impl Bank {
|
|||
self.rent_collector.rent.burn_percent = 50; // 50% rent burn
|
||||
}
|
||||
|
||||
if new_feature_activations.contains(&feature_set::inflation_kill_switch::id()) {
|
||||
*self.inflation.write().unwrap() = Inflation::new_disabled();
|
||||
self.fee_rate_governor.burn_percent = 100; // 100% fee burn
|
||||
self.rent_collector.rent.burn_percent = 100; // 100% rent burn
|
||||
if new_feature_activations.contains(&feature_set::full_inflation::id()) {
|
||||
*self.inflation.write().unwrap() = Inflation::full();
|
||||
self.fee_rate_governor.burn_percent = 50; // 50% fee burn
|
||||
self.rent_collector.rent.burn_percent = 50; // 50% rent burn
|
||||
}
|
||||
|
||||
if new_feature_activations.contains(&feature_set::spl_token_v2_multisig_fix::id()) {
|
||||
|
@ -10702,4 +10728,140 @@ pub(crate) mod tests {
|
|||
|
||||
assert_eq!(bank.rewrite_stakes(), (1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_inflation_start_slot() {
|
||||
let GenesisConfigInfo {
|
||||
mut genesis_config, ..
|
||||
} = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
|
||||
genesis_config
|
||||
.accounts
|
||||
.remove(&feature_set::pico_inflation::id())
|
||||
.unwrap();
|
||||
genesis_config
|
||||
.accounts
|
||||
.remove(&feature_set::full_inflation::id())
|
||||
.unwrap();
|
||||
let bank = Bank::new(&genesis_config);
|
||||
|
||||
// Advance to slot 1
|
||||
let mut bank = new_from_parent(&Arc::new(bank));
|
||||
bank = new_from_parent(&Arc::new(bank));
|
||||
assert_eq!(bank.get_inflation_start_slot(), 0);
|
||||
|
||||
// Request `full_inflation` activation
|
||||
let pico_inflation_activation_slot = 1;
|
||||
bank.store_account(
|
||||
&feature_set::pico_inflation::id(),
|
||||
&feature::create_account(
|
||||
&Feature {
|
||||
activated_at: Some(pico_inflation_activation_slot),
|
||||
},
|
||||
42,
|
||||
),
|
||||
);
|
||||
bank.compute_active_feature_set(true);
|
||||
assert_eq!(
|
||||
bank.get_inflation_start_slot(),
|
||||
pico_inflation_activation_slot
|
||||
);
|
||||
|
||||
// Advance to slot 2
|
||||
bank = new_from_parent(&Arc::new(bank));
|
||||
|
||||
// Request `full_inflation` activation, which takes priority over pico_inflation
|
||||
let full_inflation_activation_slot = 2;
|
||||
bank.store_account(
|
||||
&feature_set::full_inflation::id(),
|
||||
&feature::create_account(
|
||||
&Feature {
|
||||
activated_at: Some(full_inflation_activation_slot),
|
||||
},
|
||||
42,
|
||||
),
|
||||
);
|
||||
bank.compute_active_feature_set(true);
|
||||
assert_eq!(
|
||||
bank.get_inflation_start_slot(),
|
||||
full_inflation_activation_slot
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_inflation_num_slots_with_activations() {
|
||||
let GenesisConfigInfo {
|
||||
mut genesis_config, ..
|
||||
} = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
|
||||
let slots_per_epoch = 32;
|
||||
genesis_config.epoch_schedule = EpochSchedule::new(slots_per_epoch);
|
||||
genesis_config
|
||||
.accounts
|
||||
.remove(&feature_set::pico_inflation::id())
|
||||
.unwrap();
|
||||
genesis_config
|
||||
.accounts
|
||||
.remove(&feature_set::full_inflation::id())
|
||||
.unwrap();
|
||||
let mut bank = Bank::new(&genesis_config);
|
||||
assert_eq!(bank.get_inflation_num_slots(), 0);
|
||||
for _ in 0..2 * slots_per_epoch {
|
||||
bank = new_from_parent(&Arc::new(bank));
|
||||
}
|
||||
assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
|
||||
|
||||
// Activate pico_inflation
|
||||
let pico_inflation_activation_slot = bank.slot();
|
||||
bank.store_account(
|
||||
&feature_set::pico_inflation::id(),
|
||||
&feature::create_account(
|
||||
&Feature {
|
||||
activated_at: Some(pico_inflation_activation_slot),
|
||||
},
|
||||
42,
|
||||
),
|
||||
);
|
||||
bank.compute_active_feature_set(true);
|
||||
assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
|
||||
for _ in 0..slots_per_epoch {
|
||||
bank = new_from_parent(&Arc::new(bank));
|
||||
}
|
||||
assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
|
||||
|
||||
// Activate full_inflation
|
||||
let full_inflation_activation_slot = bank.slot();
|
||||
bank.store_account(
|
||||
&feature_set::full_inflation::id(),
|
||||
&feature::create_account(
|
||||
&Feature {
|
||||
activated_at: Some(full_inflation_activation_slot),
|
||||
},
|
||||
42,
|
||||
),
|
||||
);
|
||||
bank.compute_active_feature_set(true);
|
||||
assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
|
||||
for _ in 0..slots_per_epoch {
|
||||
bank = new_from_parent(&Arc::new(bank));
|
||||
}
|
||||
assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_inflation_num_slots_already_activated() {
|
||||
let GenesisConfigInfo {
|
||||
mut genesis_config, ..
|
||||
} = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
|
||||
let slots_per_epoch = 32;
|
||||
genesis_config.epoch_schedule = EpochSchedule::new(slots_per_epoch);
|
||||
let mut bank = Bank::new(&genesis_config);
|
||||
assert_eq!(bank.get_inflation_num_slots(), 0);
|
||||
for _ in 0..slots_per_epoch {
|
||||
bank = new_from_parent(&Arc::new(bank));
|
||||
}
|
||||
assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
|
||||
for _ in 0..slots_per_epoch {
|
||||
bank = new_from_parent(&Arc::new(bank));
|
||||
}
|
||||
assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ pub mod consistent_recent_blockhashes_sysvar {
|
|||
}
|
||||
|
||||
pub mod pico_inflation {
|
||||
solana_sdk::declare_id!("GaBtBJvmS4Arjj5W1NmFcyvPjsHN38UGYDq2MDwbs9Qu");
|
||||
solana_sdk::declare_id!("4RWNif6C2WCNiKVW7otP4G7dkmkHGyKQWRpuZ1pxKU5m");
|
||||
}
|
||||
|
||||
pub mod inflation_kill_switch {
|
||||
solana_sdk::declare_id!("SECCKV5UVUsr8sTVSVAzULjdm87r7mLPaqH2FGZjevR");
|
||||
pub mod full_inflation {
|
||||
solana_sdk::declare_id!("DT4n6ABDqs6w4bnfwrXT9rsprcPf6cdDga1egctaPkLC");
|
||||
}
|
||||
|
||||
pub mod spl_token_v2_multisig_fix {
|
||||
|
@ -97,7 +97,7 @@ lazy_static! {
|
|||
(secp256k1_program_enabled::id(), "secp256k1 program"),
|
||||
(consistent_recent_blockhashes_sysvar::id(), "consistent recentblockhashes sysvar"),
|
||||
(pico_inflation::id(), "pico-inflation"),
|
||||
(inflation_kill_switch::id(), "inflation kill switch"),
|
||||
(full_inflation::id(), "full-inflation"),
|
||||
(spl_token_v2_multisig_fix::id(), "spl-token multisig fix"),
|
||||
(bpf_loader2_program::id(), "bpf_loader2 program"),
|
||||
(bpf_compute_budget_balancing::id(), "compute budget balancing"),
|
||||
|
|
|
@ -69,6 +69,17 @@ impl Inflation {
|
|||
Self::new_fixed(0.0001) // 0.01% inflation
|
||||
}
|
||||
|
||||
pub fn full() -> Self {
|
||||
Self {
|
||||
initial: DEFAULT_INITIAL,
|
||||
terminal: DEFAULT_TERMINAL,
|
||||
taper: DEFAULT_TAPER,
|
||||
foundation: 0.0,
|
||||
foundation_term: 0.0,
|
||||
__unused: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// inflation rate at year
|
||||
pub fn total(&self, year: f64) -> f64 {
|
||||
assert!(year >= 0.0);
|
||||
|
|
Loading…
Reference in New Issue