Skip to content

Commit

Permalink
Populate partitioned-rewards PDA during calculation (#34624)
Browse files Browse the repository at this point in the history
* Add epoch_rewards_partition_data module

* Rename variable

* Pass hasher's parent_blockhash up to begin_partitioned_rewards

* Populate epoch rewards partition data account in begin_partitioned_rewards

* Fix method name
  • Loading branch information
Tyera authored Jan 12, 2024
1 parent 22fcffe commit 4385ed1
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 6 deletions.
41 changes: 40 additions & 1 deletion runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ use {
UPDATED_HASHES_PER_TICK4, UPDATED_HASHES_PER_TICK5, UPDATED_HASHES_PER_TICK6,
},
epoch_info::EpochInfo,
epoch_rewards_partition_data::{
get_epoch_rewards_partition_data_address, EpochRewardsPartitionDataVersion, HasherKind,
PartitionData,
},
epoch_schedule::EpochSchedule,
feature,
feature_set::{self, include_loaded_accounts_data_size_in_fee_calculation, FeatureSet},
Expand Down Expand Up @@ -890,6 +894,7 @@ struct PartitionedRewardsCalculation {
foundation_rate: f64,
prev_epoch_duration_in_years: f64,
capitalization: u64,
parent_blockhash: Hash,
}

/// result of calculating the stake rewards at beginning of new epoch
Expand All @@ -907,6 +912,8 @@ struct CalculateRewardsAndDistributeVoteRewardsResult {
distributed_rewards: u64,
/// stake rewards that still need to be distributed, grouped by partition
stake_rewards_by_partition: Vec<StakeRewards>,
/// blockhash of parent, used to create EpochRewardsHasher
parent_blockhash: Hash,
}

pub(crate) type StakeRewards = Vec<StakeReward>;
Expand Down Expand Up @@ -1595,23 +1602,28 @@ impl Bank {
total_rewards,
distributed_rewards,
stake_rewards_by_partition,
parent_blockhash,
} = self.calculate_rewards_and_distribute_vote_rewards(
parent_epoch,
reward_calc_tracer,
thread_pool,
rewards_metrics,
);

let num_partitions = stake_rewards_by_partition.len();

let slot = self.slot();
let credit_start = self.block_height() + self.get_reward_calculation_num_blocks();
let credit_end_exclusive = credit_start + stake_rewards_by_partition.len() as u64;
let credit_end_exclusive = credit_start + num_partitions 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_end_exclusive), total capital will increase by (total_rewards - distributed_rewards)
self.create_epoch_rewards_sysvar(total_rewards, distributed_rewards, credit_end_exclusive);

self.create_epoch_rewards_partition_data_account(num_partitions, parent_blockhash);

datapoint_info!(
"epoch-rewards-status-update",
("start_slot", slot, i64),
Expand Down Expand Up @@ -2377,6 +2389,7 @@ impl Bank {
foundation_rate,
prev_epoch_duration_in_years,
capitalization,
parent_blockhash,
}
}

Expand All @@ -2397,6 +2410,7 @@ impl Bank {
foundation_rate,
prev_epoch_duration_in_years,
capitalization,
parent_blockhash,
} = self.calculate_rewards_for_partitioning(
prev_epoch,
reward_calc_tracer,
Expand Down Expand Up @@ -2466,6 +2480,7 @@ impl Bank {
total_rewards: validator_rewards_paid + total_stake_rewards_lamports,
distributed_rewards: validator_rewards_paid,
stake_rewards_by_partition,
parent_blockhash,
}
}

Expand Down Expand Up @@ -3579,6 +3594,30 @@ impl Bank {
self.log_epoch_rewards_sysvar("update");
}

/// Create the persistent PDA containing the epoch-rewards data
fn create_epoch_rewards_partition_data_account(
&self,
num_partitions: usize,
parent_blockhash: Hash,
) {
let epoch_rewards_partition_data = EpochRewardsPartitionDataVersion::V0(PartitionData {
num_partitions,
parent_blockhash,
hasher_kind: HasherKind::Sip13,
});
let address = get_epoch_rewards_partition_data_address(self.epoch());

let data_len = bincode::serialized_size(&epoch_rewards_partition_data).unwrap() as usize;
let account_balance = self.get_minimum_balance_for_rent_exemption(data_len);
let new_account = AccountSharedData::new_data(
account_balance,
&epoch_rewards_partition_data,
&solana_sdk::stake::program::id(),
)
.unwrap();
self.store_account_and_update_capitalization(&address, &new_account);
}

fn update_recent_blockhashes_locked(&self, locked_blockhash_queue: &BlockhashQueue) {
#[allow(deprecated)]
self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
Expand Down
6 changes: 3 additions & 3 deletions runtime/src/epoch_rewards_hasher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub(crate) fn hash_rewards_into_partitions(
num_partitions: usize,
) -> Vec<StakeRewards> {
let hasher = EpochRewardsHasher::new(num_partitions, parent_blockhash);
let mut result = vec![vec![]; num_partitions];
let mut rewards = vec![vec![]; num_partitions];

for reward in stake_rewards {
// clone here so the hasher's state is re-used on each call to `hash_address_to_partition`.
Expand All @@ -55,9 +55,9 @@ pub(crate) fn hash_rewards_into_partitions(
let partition_index = hasher
.clone()
.hash_address_to_partition(&reward.stake_pubkey);
result[partition_index].push(reward);
rewards[partition_index].push(reward);
}
result
rewards
}

#[cfg(test)]
Expand Down
34 changes: 34 additions & 0 deletions sdk/program/src/epoch_rewards_partition_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use {
crate::{hash::Hash, pubkey::Pubkey},
serde_derive::{Deserialize, Serialize},
};

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub enum EpochRewardsPartitionDataVersion {
V0(PartitionData),
}

#[repr(u8)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub enum HasherKind {
Sip13,
}

/// Data about a rewards partitions for an epoch
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct PartitionData {
/// Number of partitions used for epoch rewards this epoch
pub num_partitions: usize,
/// Blockhash of the last block of the previous epoch, used to create EpochRewardsHasher
pub parent_blockhash: Hash,
/// Kind of hasher used to generate partitions
pub hasher_kind: HasherKind,
}

pub fn get_epoch_rewards_partition_data_address(epoch: u64) -> Pubkey {
let (address, _bump_seed) = Pubkey::find_program_address(
&[b"EpochRewardsPartitionData", &epoch.to_le_bytes()],
&crate::stake::program::id(),
);
address
}
1 change: 1 addition & 0 deletions sdk/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ pub mod ed25519_program;
pub mod entrypoint;
pub mod entrypoint_deprecated;
pub mod epoch_rewards;
pub mod epoch_rewards_partition_data;
pub mod epoch_schedule;
pub mod feature;
pub mod fee_calculator;
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ pub use solana_program::{
account_info, address_lookup_table, alt_bn128, big_mod_exp, blake3, borsh, borsh0_10, borsh0_9,
borsh1, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock, config,
custom_heap_default, custom_panic_default, debug_account_data, declare_deprecated_sysvar_id,
declare_sysvar_id, decode_error, ed25519_program, epoch_rewards, epoch_schedule,
fee_calculator, impl_sysvar_get, incinerator, instruction, keccak, lamports,
declare_sysvar_id, decode_error, ed25519_program, epoch_rewards, epoch_rewards_partition_data,
epoch_schedule, fee_calculator, impl_sysvar_get, incinerator, instruction, keccak, lamports,
loader_instruction, loader_upgradeable_instruction, loader_v4, loader_v4_instruction, message,
msg, native_token, nonce, poseidon, program, program_error, program_memory, program_option,
program_pack, rent, sanitize, sdk_ids, secp256k1_program, secp256k1_recover, serde_varint,
Expand Down

0 comments on commit 4385ed1

Please sign in to comment.