Populate EpochRewards with correct data (#763)
* Populate EpochRewards::parent_blockhash correctly * Populate EpochRewards::num_partitions correctly * Add new internal struct to be extended * Add CalculateValidatorRewardsResult::total_points * Add PartitionedRewardsCalculation::total_points * Add CalculateRewardsAndDistributeVoteRewardsResult::total_points * Populate EpochRewards::total_points correctly * Nit: reorder fields to match struct definition * Use Self::last_blockhash() to get parent_blockhash
This commit is contained in:
parent
aed1a5e452
commit
180a186c7d
|
@ -1,12 +1,13 @@
|
|||
use {
|
||||
super::{
|
||||
epoch_rewards_hasher::hash_rewards_into_partitions, Bank,
|
||||
CalculateRewardsAndDistributeVoteRewardsResult, EpochRewardCalculateParamInfo,
|
||||
PartitionedRewardsCalculation, StakeRewardCalculationPartitioned, VoteRewardsAccounts,
|
||||
CalculateRewardsAndDistributeVoteRewardsResult, CalculateValidatorRewardsResult,
|
||||
EpochRewardCalculateParamInfo, PartitionedRewardsCalculation,
|
||||
StakeRewardCalculationPartitioned, VoteRewardsAccounts,
|
||||
},
|
||||
crate::bank::{
|
||||
PrevEpochInflationRewards, RewardCalcTracer, RewardCalculationEvent, RewardsMetrics,
|
||||
StakeRewardCalculation, VoteAccount,
|
||||
VoteAccount,
|
||||
},
|
||||
log::info,
|
||||
rayon::{
|
||||
|
@ -38,6 +39,7 @@ impl Bank {
|
|||
let CalculateRewardsAndDistributeVoteRewardsResult {
|
||||
total_rewards,
|
||||
distributed_rewards,
|
||||
total_points,
|
||||
stake_rewards_by_partition,
|
||||
} = self.calculate_rewards_and_distribute_vote_rewards(
|
||||
parent_epoch,
|
||||
|
@ -49,11 +51,19 @@ impl Bank {
|
|||
let slot = self.slot();
|
||||
let credit_start = self.block_height() + self.get_reward_calculation_num_blocks();
|
||||
|
||||
let num_partitions = stake_rewards_by_partition.len() as u64;
|
||||
|
||||
self.set_epoch_reward_status_active(stake_rewards_by_partition);
|
||||
|
||||
// create EpochRewards sysvar that holds the balance of undistributed rewards with
|
||||
// (total_rewards, distributed_rewards, credit_start), total capital will increase by (total_rewards - distributed_rewards)
|
||||
self.create_epoch_rewards_sysvar(total_rewards, distributed_rewards, credit_start);
|
||||
self.create_epoch_rewards_sysvar(
|
||||
total_rewards,
|
||||
distributed_rewards,
|
||||
credit_start,
|
||||
num_partitions,
|
||||
total_points,
|
||||
);
|
||||
|
||||
datapoint_info!(
|
||||
"epoch-rewards-status-update",
|
||||
|
@ -82,6 +92,7 @@ impl Bank {
|
|||
foundation_rate,
|
||||
prev_epoch_duration_in_years,
|
||||
capitalization,
|
||||
total_points,
|
||||
} = self.calculate_rewards_for_partitioning(
|
||||
prev_epoch,
|
||||
reward_calc_tracer,
|
||||
|
@ -150,6 +161,7 @@ impl Bank {
|
|||
CalculateRewardsAndDistributeVoteRewardsResult {
|
||||
total_rewards: validator_rewards_paid + total_stake_rewards_lamports,
|
||||
distributed_rewards: validator_rewards_paid,
|
||||
total_points,
|
||||
stake_rewards_by_partition,
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +210,11 @@ impl Bank {
|
|||
|
||||
let old_vote_balance_and_staked = self.stakes_cache.stakes().vote_balance_and_staked();
|
||||
|
||||
let (vote_account_rewards, mut stake_rewards) = self
|
||||
let CalculateValidatorRewardsResult {
|
||||
vote_rewards_accounts: vote_account_rewards,
|
||||
stake_reward_calculation: mut stake_rewards,
|
||||
total_points,
|
||||
} = self
|
||||
.calculate_validator_rewards(
|
||||
prev_epoch,
|
||||
validator_rewards,
|
||||
|
@ -231,6 +247,7 @@ impl Bank {
|
|||
foundation_rate,
|
||||
prev_epoch_duration_in_years,
|
||||
capitalization,
|
||||
total_points,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +259,7 @@ impl Bank {
|
|||
reward_calc_tracer: Option<impl RewardCalcTracer>,
|
||||
thread_pool: &ThreadPool,
|
||||
metrics: &mut RewardsMetrics,
|
||||
) -> Option<(VoteRewardsAccounts, StakeRewardCalculation)> {
|
||||
) -> Option<CalculateValidatorRewardsResult> {
|
||||
let stakes = self.stakes_cache.stakes();
|
||||
let reward_calculate_param = self.get_epoch_reward_calculate_param_info(&stakes);
|
||||
|
||||
|
@ -253,14 +270,21 @@ impl Bank {
|
|||
metrics,
|
||||
)
|
||||
.map(|point_value| {
|
||||
self.calculate_stake_vote_rewards(
|
||||
let total_points = point_value.points;
|
||||
let (vote_rewards_accounts, stake_reward_calculation) = self
|
||||
.calculate_stake_vote_rewards(
|
||||
&reward_calculate_param,
|
||||
rewarded_epoch,
|
||||
point_value,
|
||||
thread_pool,
|
||||
reward_calc_tracer,
|
||||
metrics,
|
||||
)
|
||||
);
|
||||
CalculateValidatorRewardsResult {
|
||||
vote_rewards_accounts,
|
||||
stake_reward_calculation,
|
||||
total_points,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -478,8 +502,11 @@ mod tests {
|
|||
&mut rewards_metrics,
|
||||
);
|
||||
|
||||
let vote_rewards = &calculated_rewards.as_ref().unwrap().0;
|
||||
let stake_rewards = &calculated_rewards.as_ref().unwrap().1;
|
||||
let vote_rewards = &calculated_rewards.as_ref().unwrap().vote_rewards_accounts;
|
||||
let stake_rewards = &calculated_rewards
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.stake_reward_calculation;
|
||||
|
||||
let total_vote_rewards: u64 = vote_rewards
|
||||
.rewards
|
||||
|
|
|
@ -214,7 +214,9 @@ mod tests {
|
|||
|
||||
// Set up epoch_rewards sysvar with rewards with 1e9 lamports to distribute.
|
||||
let total_rewards = 1_000_000_000;
|
||||
bank.create_epoch_rewards_sysvar(total_rewards, 0, 42);
|
||||
let num_partitions = 2; // num_partitions is arbitrary and unimportant for this test
|
||||
let total_points = (total_rewards * 42) as u128; // total_points is arbitrary for the purposes of this test
|
||||
bank.create_epoch_rewards_sysvar(total_rewards, 0, 42, num_partitions, total_points);
|
||||
let pre_epoch_rewards_account = bank.get_account(&sysvar::epoch_rewards::id()).unwrap();
|
||||
let expected_balance =
|
||||
bank.get_minimum_balance_for_rent_exemption(pre_epoch_rewards_account.data().len());
|
||||
|
|
|
@ -5,7 +5,7 @@ mod epoch_rewards_hasher;
|
|||
mod sysvar;
|
||||
|
||||
use {
|
||||
super::Bank,
|
||||
super::{Bank, StakeRewardCalculation},
|
||||
crate::{stake_account::StakeAccount, stake_history::StakeHistory},
|
||||
solana_accounts_db::{
|
||||
partitioned_rewards::PartitionedEpochRewardsConfig, stake_rewards::StakeReward,
|
||||
|
@ -50,6 +50,13 @@ pub(super) struct VoteRewardsAccounts {
|
|||
pub(super) accounts_to_store: Vec<Option<AccountSharedData>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct CalculateValidatorRewardsResult {
|
||||
vote_rewards_accounts: VoteRewardsAccounts,
|
||||
stake_reward_calculation: StakeRewardCalculation,
|
||||
total_points: u128,
|
||||
}
|
||||
|
||||
/// hold reward calc info to avoid recalculation across functions
|
||||
pub(super) struct EpochRewardCalculateParamInfo<'a> {
|
||||
pub(super) stake_history: StakeHistory,
|
||||
|
@ -69,6 +76,7 @@ pub(super) struct PartitionedRewardsCalculation {
|
|||
pub(super) foundation_rate: f64,
|
||||
pub(super) prev_epoch_duration_in_years: f64,
|
||||
pub(super) capitalization: u64,
|
||||
total_points: u128,
|
||||
}
|
||||
|
||||
/// result of calculating the stake rewards at beginning of new epoch
|
||||
|
@ -84,6 +92,10 @@ pub(super) struct CalculateRewardsAndDistributeVoteRewardsResult {
|
|||
pub(super) total_rewards: u64,
|
||||
/// distributed vote rewards
|
||||
pub(super) distributed_rewards: u64,
|
||||
/// total rewards points calculated for the current epoch, where points
|
||||
/// equals the sum of (delegated stake * credits observed) for all
|
||||
/// delegations
|
||||
pub(super) total_points: u128,
|
||||
/// stake rewards that still need to be distributed, grouped by partition
|
||||
pub(super) stake_rewards_by_partition: Vec<StakeRewards>,
|
||||
}
|
||||
|
|
|
@ -20,22 +20,30 @@ impl Bank {
|
|||
}
|
||||
|
||||
/// Create EpochRewards sysvar with calculated rewards
|
||||
/// This method must be called before a new Bank advances its
|
||||
/// last_blockhash.
|
||||
pub(in crate::bank) fn create_epoch_rewards_sysvar(
|
||||
&self,
|
||||
total_rewards: u64,
|
||||
distributed_rewards: u64,
|
||||
distribution_starting_block_height: u64,
|
||||
num_partitions: u64,
|
||||
total_points: u128,
|
||||
) {
|
||||
assert!(self.is_partitioned_rewards_code_enabled());
|
||||
|
||||
assert!(total_rewards >= distributed_rewards);
|
||||
|
||||
let parent_blockhash = self.last_blockhash();
|
||||
|
||||
let epoch_rewards = sysvar::epoch_rewards::EpochRewards {
|
||||
distribution_starting_block_height,
|
||||
num_partitions,
|
||||
parent_blockhash,
|
||||
total_points,
|
||||
total_rewards,
|
||||
distributed_rewards,
|
||||
distribution_starting_block_height,
|
||||
active: true,
|
||||
..sysvar::epoch_rewards::EpochRewards::default()
|
||||
};
|
||||
|
||||
self.update_sysvar_account(&sysvar::epoch_rewards::id(), |account| {
|
||||
|
@ -109,9 +117,10 @@ mod tests {
|
|||
super::*,
|
||||
crate::bank::tests::create_genesis_config,
|
||||
solana_sdk::{
|
||||
account::ReadableAccount, epoch_schedule::EpochSchedule, feature_set, hash::Hash,
|
||||
native_token::LAMPORTS_PER_SOL,
|
||||
account::ReadableAccount, epoch_schedule::EpochSchedule, feature_set,
|
||||
native_token::LAMPORTS_PER_SOL, pubkey::Pubkey,
|
||||
},
|
||||
std::sync::Arc,
|
||||
};
|
||||
|
||||
/// Test `EpochRewards` sysvar creation, distribution, and burning.
|
||||
|
@ -126,13 +135,15 @@ mod tests {
|
|||
bank.activate_feature(&feature_set::enable_partitioned_epoch_reward::id());
|
||||
|
||||
let total_rewards = 1_000_000_000; // a large rewards so that the sysvar account is rent-exempted.
|
||||
let num_partitions = 2; // num_partitions is arbitrary and unimportant for this test
|
||||
let total_points = (total_rewards * 42) as u128; // total_points is arbitrary for the purposes of this test
|
||||
|
||||
// create epoch rewards sysvar
|
||||
let expected_epoch_rewards = sysvar::epoch_rewards::EpochRewards {
|
||||
distribution_starting_block_height: 42,
|
||||
num_partitions: 0,
|
||||
parent_blockhash: Hash::default(),
|
||||
total_points: 0,
|
||||
num_partitions,
|
||||
parent_blockhash: bank.last_blockhash(),
|
||||
total_points,
|
||||
total_rewards,
|
||||
distributed_rewards: 10,
|
||||
active: true,
|
||||
|
@ -144,7 +155,7 @@ mod tests {
|
|||
sysvar::epoch_rewards::EpochRewards::default()
|
||||
);
|
||||
|
||||
bank.create_epoch_rewards_sysvar(total_rewards, 10, 42);
|
||||
bank.create_epoch_rewards_sysvar(total_rewards, 10, 42, num_partitions, total_points);
|
||||
let account = bank.get_account(&sysvar::epoch_rewards::id()).unwrap();
|
||||
let expected_balance = bank.get_minimum_balance_for_rent_exemption(account.data().len());
|
||||
// Expected balance is the sysvar rent-exempt balance
|
||||
|
@ -152,6 +163,24 @@ mod tests {
|
|||
let epoch_rewards: sysvar::epoch_rewards::EpochRewards = from_account(&account).unwrap();
|
||||
assert_eq!(epoch_rewards, expected_epoch_rewards);
|
||||
|
||||
// Create a child bank to test parent_blockhash
|
||||
let parent_blockhash = bank.last_blockhash();
|
||||
let parent_slot = bank.slot();
|
||||
let bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::default(), parent_slot + 1);
|
||||
// Also note that running `create_epoch_rewards_sysvar()` against a bank
|
||||
// with an existing EpochRewards sysvar clobbers the previous values
|
||||
bank.create_epoch_rewards_sysvar(total_rewards, 10, 42, num_partitions, total_points);
|
||||
|
||||
let expected_epoch_rewards = sysvar::epoch_rewards::EpochRewards {
|
||||
distribution_starting_block_height: 42,
|
||||
num_partitions,
|
||||
parent_blockhash,
|
||||
total_points,
|
||||
total_rewards,
|
||||
distributed_rewards: 10,
|
||||
active: true,
|
||||
};
|
||||
|
||||
let epoch_rewards = bank.get_epoch_rewards_sysvar();
|
||||
assert_eq!(epoch_rewards, expected_epoch_rewards);
|
||||
|
||||
|
@ -163,9 +192,9 @@ mod tests {
|
|||
let epoch_rewards: sysvar::epoch_rewards::EpochRewards = from_account(&account).unwrap();
|
||||
let expected_epoch_rewards = sysvar::epoch_rewards::EpochRewards {
|
||||
distribution_starting_block_height: 42,
|
||||
num_partitions: 0,
|
||||
parent_blockhash: Hash::default(),
|
||||
total_points: 0,
|
||||
num_partitions,
|
||||
parent_blockhash,
|
||||
total_points,
|
||||
total_rewards,
|
||||
distributed_rewards: 20,
|
||||
active: true,
|
||||
|
|
|
@ -6,7 +6,7 @@ mod tests {
|
|||
use {
|
||||
super::*,
|
||||
solana_sdk::{
|
||||
feature_set, genesis_config::create_genesis_config, hash::Hash, pubkey::Pubkey,
|
||||
feature_set, genesis_config::create_genesis_config, pubkey::Pubkey,
|
||||
sysvar::epoch_rewards::EpochRewards,
|
||||
},
|
||||
std::sync::Arc,
|
||||
|
@ -120,11 +120,13 @@ mod tests {
|
|||
|
||||
// inject a reward sysvar for test
|
||||
bank1.activate_feature(&feature_set::enable_partitioned_epoch_reward::id());
|
||||
let num_partitions = 2; // num_partitions is arbitrary and unimportant for this test
|
||||
let total_points = 42_000; // total_points is arbitrary for the purposes of this test
|
||||
let expected_epoch_rewards = EpochRewards {
|
||||
distribution_starting_block_height: 42,
|
||||
num_partitions: 0,
|
||||
parent_blockhash: Hash::default(),
|
||||
total_points: 0,
|
||||
num_partitions,
|
||||
parent_blockhash: bank1.parent().unwrap().last_blockhash(),
|
||||
total_points,
|
||||
total_rewards: 100,
|
||||
distributed_rewards: 10,
|
||||
active: true,
|
||||
|
@ -133,6 +135,8 @@ mod tests {
|
|||
expected_epoch_rewards.total_rewards,
|
||||
expected_epoch_rewards.distributed_rewards,
|
||||
expected_epoch_rewards.distribution_starting_block_height,
|
||||
num_partitions,
|
||||
total_points,
|
||||
);
|
||||
|
||||
bank1
|
||||
|
|
Loading…
Reference in New Issue