Add inflation to epoch phases (#6787)

This commit is contained in:
Jack May 2019-11-07 10:53:04 -08:00 committed by GitHub
parent 180bc1784e
commit a9c4cd6cbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 127 additions and 25 deletions

View File

@ -382,12 +382,15 @@ fn main() -> Result<(), Box<dyn error::Error>> {
} else {
OperatingMode::SoftLaunch
};
let native_instruction_processors = solana_genesis_programs::get(operating_mode, 0).unwrap();
let native_instruction_processors =
solana_genesis_programs::get_programs(operating_mode, 0).unwrap();
let inflation = solana_genesis_programs::get_inflation(operating_mode, 0).unwrap();
let mut genesis_block = GenesisBlock {
accounts,
native_instruction_processors,
ticks_per_slot,
epoch_schedule,
inflation,
fee_calculator,
rent,
poh_config,

View File

@ -1,6 +1,6 @@
use solana_sdk::{
clock::Epoch, genesis_block::OperatingMode, move_loader::solana_move_loader_program,
pubkey::Pubkey, system_program::solana_system_program,
clock::Epoch, genesis_block::OperatingMode, inflation::Inflation,
move_loader::solana_move_loader_program, pubkey::Pubkey, system_program::solana_system_program,
};
#[macro_use]
@ -23,7 +23,33 @@ extern crate solana_vote_program;
use log::*;
use solana_runtime::bank::{Bank, EnteredEpochCallback};
pub fn get(operating_mode: OperatingMode, epoch: Epoch) -> Option<Vec<(String, Pubkey)>> {
pub fn get_inflation(operating_mode: OperatingMode, epoch: Epoch) -> Option<Inflation> {
match operating_mode {
OperatingMode::Development => {
if epoch == 0 {
Some(Inflation::default())
} else {
None
}
}
OperatingMode::SoftLaunch => {
if epoch == 0 {
// No inflation at epoch 0
Some(Inflation::new_disabled())
} else if epoch == std::u64::MAX {
// Inflation starts
//
// The epoch of std::u64::MAX - 1 is a placeholder and is expected to be reduced in
// a future hard fork.
Some(Inflation::default())
} else {
None
}
}
}
}
pub fn get_programs(operating_mode: OperatingMode, epoch: Epoch) -> Option<Vec<(String, Pubkey)>> {
match operating_mode {
OperatingMode::Development => {
if epoch == 0 {
@ -80,7 +106,10 @@ pub fn get_entered_epoch_callback(operating_mode: OperatingMode) -> EnteredEpoch
bank.epoch(),
operating_mode
);
if let Some(new_programs) = get(operating_mode, bank.epoch()) {
if let Some(inflation) = get_inflation(operating_mode, bank.epoch()) {
bank.set_inflation(inflation);
}
if let Some(new_programs) = get_programs(operating_mode, bank.epoch()) {
for (name, program_id) in new_programs.iter() {
info!("Registering {} at {}", name, program_id);
bank.register_native_instruction_processor(name, program_id);
@ -97,24 +126,49 @@ mod tests {
#[test]
fn test_id_uniqueness() {
let mut unique = HashSet::new();
let ids = get(OperatingMode::Development, 0).unwrap();
let ids = get_programs(OperatingMode::Development, 0).unwrap();
assert!(ids.into_iter().all(move |id| unique.insert(id)));
}
#[test]
fn test_development_inflation() {
assert_eq!(
get_inflation(OperatingMode::Development, 0).unwrap(),
Inflation::default()
);
assert_eq!(get_inflation(OperatingMode::Development, 1), None);
}
#[test]
fn test_development_programs() {
assert_eq!(get(OperatingMode::Development, 0).unwrap().len(), 10);
assert_eq!(get(OperatingMode::Development, 1), None);
assert_eq!(
get_programs(OperatingMode::Development, 0).unwrap().len(),
10
);
assert_eq!(get_programs(OperatingMode::Development, 1), None);
}
#[test]
fn test_softlaunch_inflation() {
assert_eq!(
get_inflation(OperatingMode::SoftLaunch, 0).unwrap(),
Inflation::new_disabled()
);
assert_eq!(get_inflation(OperatingMode::SoftLaunch, 1), None);
assert_eq!(
get_inflation(OperatingMode::SoftLaunch, std::u64::MAX).unwrap(),
Inflation::default()
);
}
#[test]
fn test_softlaunch_programs() {
assert_eq!(
get(OperatingMode::SoftLaunch, 0),
get_programs(OperatingMode::SoftLaunch, 0),
Some(vec![solana_stake_program!(), solana_vote_program!(),])
);
assert_eq!(get(OperatingMode::SoftLaunch, 1), None);
assert!(get(OperatingMode::SoftLaunch, std::u64::MAX - 1).is_some());
assert!(get(OperatingMode::SoftLaunch, std::u64::MAX).is_some());
assert_eq!(get_programs(OperatingMode::SoftLaunch, 1), None);
assert!(get_programs(OperatingMode::SoftLaunch, std::u64::MAX - 1).is_some());
assert!(get_programs(OperatingMode::SoftLaunch, std::u64::MAX).is_some());
}
}

View File

@ -151,13 +151,16 @@ impl LocalCluster {
match genesis_block.operating_mode {
OperatingMode::SoftLaunch => {
genesis_block.native_instruction_processors =
solana_genesis_programs::get(genesis_block.operating_mode, 0).unwrap()
solana_genesis_programs::get_programs(genesis_block.operating_mode, 0).unwrap()
}
// create_genesis_block_with_leader() assumes OperatingMode::Development so do
// nothing...
OperatingMode::Development => (),
}
genesis_block.inflation =
solana_genesis_programs::get_inflation(genesis_block.operating_mode, 0).unwrap();
genesis_block
.native_instruction_processors
.extend_from_slice(&config.native_instruction_processors);

View File

@ -237,7 +237,7 @@ pub struct Bank {
epoch_schedule: EpochSchedule,
/// inflation specs
inflation: Inflation,
inflation: Arc<RwLock<Inflation>>,
/// cache of vote_account and stake_account state for this fork
stakes: RwLock<Stakes>,
@ -341,7 +341,7 @@ impl Bank {
parent.signature_count() as usize,
),
capitalization: AtomicU64::new(parent.capitalization()),
inflation: parent.inflation,
inflation: parent.inflation.clone(),
transaction_count: AtomicU64::new(parent.transaction_count()),
stakes: RwLock::new(parent.stakes.read().unwrap().clone_with_epoch(epoch)),
epoch_stakes: parent.epoch_stakes.clone(),
@ -520,15 +520,17 @@ impl Bank {
// period: time that has passed as a fraction of a year, basically the length of
// an epoch as a fraction of a year
// years_elapsed = slots_elapsed / slots/year
// years_elapsed = slots_elapsed / slots/year
let period = self.epoch_schedule.get_slots_in_epoch(epoch) as f64 / self.slots_per_year;
let inflation = self.inflation.read().unwrap();
let validator_rewards =
self.inflation.validator(year) * self.capitalization() as f64 * period;
(*inflation).validator(year) * self.capitalization() as f64 * period;
let validator_points = self.stakes.write().unwrap().claim_points();
let storage_rewards = self.inflation.storage(year) * self.capitalization() as f64 * period;
let storage_rewards = (*inflation).storage(year) * self.capitalization() as f64 * period;
let storage_points = self.storage_accounts.write().unwrap().claim_points();
@ -695,7 +697,7 @@ impl Bank {
self.epoch_schedule = genesis_block.epoch_schedule;
self.inflation = genesis_block.inflation;
self.inflation = Arc::new(RwLock::new(genesis_block.inflation));
self.rent_collector = RentCollector::new(
self.epoch,
@ -1286,11 +1288,12 @@ impl Bank {
self.rc.parent = RwLock::new(Some(parent.clone()));
}
pub fn set_inflation(&self, inflation: Inflation) {
*self.inflation.write().unwrap() = inflation;
}
pub fn set_entered_epoch_callback(&self, entered_epoch_callback: EnteredEpochCallback) {
std::mem::replace(
&mut *self.entered_epoch_callback.write().unwrap(),
Some(entered_epoch_callback),
);
*self.entered_epoch_callback.write().unwrap() = Some(entered_epoch_callback);
}
pub fn get_account(&self, pubkey: &Pubkey) -> Option<Account> {
@ -1426,7 +1429,7 @@ impl Bank {
/// Return the inflation parameters of the Bank
pub fn inflation(&self) -> Inflation {
self.inflation
*self.inflation.read().unwrap()
}
/// Return the total capititalization of the Bank
@ -1705,6 +1708,35 @@ mod tests {
assert_eq!(bank1.capitalization(), 42 * 42);
}
#[test]
fn test_bank_inflation() {
let key = Pubkey::default();
let bank = Arc::new(Bank::new(&GenesisBlock {
accounts: (0..42)
.into_iter()
.map(|_| (Pubkey::new_rand(), Account::new(42, 0, &key)))
.collect(),
..GenesisBlock::default()
}));
assert_eq!(bank.capitalization(), 42 * 42);
// With inflation
bank.set_entered_epoch_callback(Box::new(move |bank: &mut Bank| {
let mut inflation = Inflation::default();
inflation.initial = 1_000_000.0;
bank.set_inflation(inflation)
}));
let bank1 = Bank::new_from_parent(&bank, &key, MINIMUM_SLOTS_PER_EPOCH + 1);
assert_ne!(bank.capitalization(), bank1.capitalization());
// Without inflation
bank.set_entered_epoch_callback(Box::new(move |bank: &mut Bank| {
bank.set_inflation(Inflation::new_disabled())
}));
let bank2 = Bank::new_from_parent(&bank, &key, MINIMUM_SLOTS_PER_EPOCH * 2 + 1);
assert_eq!(bank.capitalization(), bank2.capitalization());
}
#[test]
fn test_bank_update_rewards() {
// create a bank that ticks really slowly...
@ -1739,7 +1771,7 @@ mod tests {
let ((validator_id, validator_account), (archiver_id, archiver_account)) =
crate::storage_utils::tests::create_storage_accounts_with_credits(100);
// set up stakes,vote, and storage accounts
// set up stakes, vote, and storage accounts
bank.store_account(&stake.0, &stake.1);
bank.store_account(&validator_id, &validator_account);
bank.store_account(&archiver_id, &archiver_account);

View File

@ -42,6 +42,16 @@ impl Default for Inflation {
}
impl Inflation {
pub fn new_disabled() -> Self {
Self {
initial: 0.0,
terminal: 0.0,
taper: 0.0,
foundation: 0.0,
foundation_term: 0.0,
storage: 0.0,
}
}
/// inflation rate at year
pub fn total(&self, year: f64) -> f64 {
let tapered = self.initial * ((1.0 - self.taper).powf(year));