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:
Tyera Eulberg 2020-11-20 09:54:41 -07:00 committed by GitHub
parent 11e92f0c9f
commit c75d97e3f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 184 additions and 11 deletions

View File

@ -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);
}
}

View File

@ -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"),

View File

@ -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);