Skip to content

Commit

Permalink
Simd 118: extend EpochRewards sysvar (solana-labs#428)
Browse files Browse the repository at this point in the history
* Update EpochRewards sysvar

* Update Clone trait

* Update doctests

* Update bank to new sysvar fields

* Update runtime tests

* Update syscall test

* Update tests

* Clean up doctest EpochRewards construction
  • Loading branch information
CriesofCarrots authored Mar 28, 2024
1 parent 8246590 commit ecb4f62
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 39 deletions.
4 changes: 3 additions & 1 deletion account-decoder/src/parse_sysvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,11 @@ mod test {
);

let epoch_rewards = EpochRewards {
distribution_starting_block_height: 42,
total_rewards: 100,
distributed_rewards: 20,
distribution_complete_block_height: 42,
active: true,
..EpochRewards::default()
};
let epoch_rewards_sysvar = create_account_for_test(&epoch_rewards);
assert_eq!(
Expand Down
16 changes: 12 additions & 4 deletions programs/bpf_loader/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3317,16 +3317,20 @@ mod tests {
src_rent.burn_percent = 3;

let mut src_rewards = create_filled_type::<EpochRewards>(false);
src_rewards.distribution_starting_block_height = 42;
src_rewards.num_partitions = 2;
src_rewards.parent_blockhash = Hash::new(&[3; 32]);
src_rewards.total_points = 4;
src_rewards.total_rewards = 100;
src_rewards.distributed_rewards = 10;
src_rewards.distribution_complete_block_height = 42;
src_rewards.active = true;

let mut sysvar_cache = SysvarCache::default();
sysvar_cache.set_clock(src_clock.clone());
sysvar_cache.set_epoch_schedule(src_epochschedule.clone());
sysvar_cache.set_fees(src_fees.clone());
sysvar_cache.set_rent(src_rent.clone());
sysvar_cache.set_epoch_rewards(src_rewards);
sysvar_cache.set_epoch_rewards(src_rewards.clone());

let transaction_accounts = vec![
(
Expand Down Expand Up @@ -3519,10 +3523,14 @@ mod tests {
assert_eq!(got_rewards, src_rewards);

let mut clean_rewards = create_filled_type::<EpochRewards>(true);
clean_rewards.distribution_starting_block_height =
src_rewards.distribution_starting_block_height;
clean_rewards.num_partitions = src_rewards.num_partitions;
clean_rewards.parent_blockhash = src_rewards.parent_blockhash;
clean_rewards.total_points = src_rewards.total_points;
clean_rewards.total_rewards = src_rewards.total_rewards;
clean_rewards.distributed_rewards = src_rewards.distributed_rewards;
clean_rewards.distribution_complete_block_height =
src_rewards.distribution_complete_block_height;
clean_rewards.active = src_rewards.active;
assert!(are_bytes_equal(&got_rewards, &clean_rewards));
}
}
Expand Down
4 changes: 3 additions & 1 deletion programs/sbf/rust/sysvar/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ async fn test_sysvars() {
);

let epoch_rewards = epoch_rewards::EpochRewards {
distribution_starting_block_height: 42,
total_rewards: 100,
distributed_rewards: 50,
distribution_complete_block_height: 42,
active: true,
..epoch_rewards::EpochRewards::default()
};
program_test.add_sysvar_account(epoch_rewards::id(), &epoch_rewards);
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
Expand Down
11 changes: 6 additions & 5 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1673,13 +1673,12 @@ impl Bank {

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;

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);
// (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);

datapoint_info!(
"epoch-rewards-status-update",
Expand Down Expand Up @@ -3615,14 +3614,16 @@ impl Bank {
&self,
total_rewards: u64,
distributed_rewards: u64,
distribution_complete_block_height: u64,
distribution_starting_block_height: u64,
) {
assert!(self.is_partitioned_rewards_code_enabled());

let epoch_rewards = sysvar::epoch_rewards::EpochRewards {
total_rewards,
distributed_rewards,
distribution_complete_block_height,
distribution_starting_block_height,
active: true,
..sysvar::epoch_rewards::EpochRewards::default()
};

self.update_sysvar_account(&sysvar::epoch_rewards::id(), |account| {
Expand Down
10 changes: 7 additions & 3 deletions runtime/src/bank/sysvar_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod tests {
use {
super::*,
solana_sdk::{
feature_set, genesis_config::create_genesis_config, pubkey::Pubkey,
feature_set, genesis_config::create_genesis_config, hash::Hash, pubkey::Pubkey,
sysvar::epoch_rewards::EpochRewards,
},
std::sync::Arc,
Expand Down Expand Up @@ -121,14 +121,18 @@ mod tests {
// inject a reward sysvar for test
bank1.activate_feature(&feature_set::enable_partitioned_epoch_reward::id());
let expected_epoch_rewards = EpochRewards {
distribution_starting_block_height: 42,
num_partitions: 0,
parent_blockhash: Hash::default(),
total_points: 0,
total_rewards: 100,
distributed_rewards: 10,
distribution_complete_block_height: 42,
active: true,
};
bank1.create_epoch_rewards_sysvar(
expected_epoch_rewards.total_rewards,
expected_epoch_rewards.distributed_rewards,
expected_epoch_rewards.distribution_complete_block_height,
expected_epoch_rewards.distribution_starting_block_height,
);

bank1
Expand Down
12 changes: 10 additions & 2 deletions runtime/src/bank/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12715,9 +12715,13 @@ fn test_epoch_rewards_sysvar() {

// 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,
total_rewards,
distributed_rewards: 10,
distribution_complete_block_height: 42,
active: true,
};

bank.create_epoch_rewards_sysvar(total_rewards, 10, 42);
Expand All @@ -12732,9 +12736,13 @@ fn test_epoch_rewards_sysvar() {
assert_eq!(account.lamports(), total_rewards - 20);
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,
total_rewards,
distributed_rewards: 20,
distribution_complete_block_height: 42,
active: true,
};
assert_eq!(epoch_rewards, expected_epoch_rewards);

Expand Down
40 changes: 29 additions & 11 deletions sdk/program/src/epoch_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,37 @@
//!
//! [`sysvar::epoch_rewards`]: crate::sysvar::epoch_rewards
use std::ops::AddAssign;
use {crate::hash::Hash, solana_sdk_macro::CloneZeroed, std::ops::AddAssign};

#[repr(C)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Default, Clone, Copy, AbiExample)]
#[repr(C, align(16))]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Default, AbiExample, CloneZeroed)]
pub struct EpochRewards {
/// total rewards for the current epoch, in lamports
/// The starting block height of the rewards distribution in the current
/// epoch
pub distribution_starting_block_height: u64,

/// Number of partitions in the rewards distribution in the current epoch,
/// used to generate an EpochRewardsHasher
pub num_partitions: u64,

/// The blockhash of the parent block of the first block in the epoch, used
/// to seed an EpochRewardsHasher
pub parent_blockhash: Hash,

/// The total rewards points calculated for the current epoch, where points
/// equals the sum of (delegated stake * credits observed) for all
/// delegations
pub total_points: u128,

/// The total rewards for the current epoch, in lamports
pub total_rewards: u64,

/// distributed rewards for the current epoch, in lamports
/// The rewards currently distributed for the current epoch, in lamports
pub distributed_rewards: u64,

/// distribution of all staking rewards for the current
/// epoch will be completed at this block height
pub distribution_complete_block_height: u64,
/// Whether the rewards period (including calculation and distribution) is
/// active
pub active: bool,
}

impl EpochRewards {
Expand All @@ -38,12 +55,13 @@ mod tests {
pub fn new(
total_rewards: u64,
distributed_rewards: u64,
distribution_complete_block_height: u64,
distribution_starting_block_height: u64,
) -> Self {
Self {
total_rewards,
distributed_rewards,
distribution_complete_block_height,
distribution_starting_block_height,
..Self::default()
}
}
}
Expand All @@ -54,7 +72,7 @@ mod tests {

assert_eq!(epoch_rewards.total_rewards, 100);
assert_eq!(epoch_rewards.distributed_rewards, 0);
assert_eq!(epoch_rewards.distribution_complete_block_height, 64);
assert_eq!(epoch_rewards.distribution_starting_block_height, 64);
}

#[test]
Expand Down
54 changes: 42 additions & 12 deletions sdk/program/src/sysvar/epoch_rewards.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
//! Epoch rewards for current epoch
//!
//! The _epoch rewards_ sysvar provides access to the [`EpochRewards`] type,
//! which tracks the progress of epoch rewards distribution. It includes the
//! - total rewards for the current epoch, in lamports
//! - rewards for the current epoch distributed so far, in lamports
//! - distribution completed block height, i.e. distribution of all staking rewards for the current
//! epoch will be completed at this block height
//! which tracks whether the rewards period (including calculation and
//! distribution) is in progress, as well as the details needed to resume
//! distribution when starting from a snapshot during the rewards period. The
//! sysvar is repopulated at the start of the first block of each epoch.
//! Therefore, the sysvar contains data about the current epoch until a new
//! epoch begins. Fields in the sysvar include:
//! - distribution starting block height
//! - the number of partitions in the distribution
//! - the parent-blockhash seed used to generate the partition hasher
//! - the total rewards points calculated for the epoch
//! - total rewards for epoch, in lamports
//! - rewards for the epoch distributed so far, in lamports
//! - whether the rewards period is active
//!
//! [`EpochRewards`] implements [`Sysvar::get`] and can be loaded efficiently without
//! passing the sysvar account ID to the program.
Expand Down Expand Up @@ -43,9 +51,16 @@
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = EpochRewards::id();
//! # let l = &mut 1120560;
//! # let d = &mut vec![0, 202, 154, 59, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let l = &mut 1559040;
//! # let epoch_rewards = EpochRewards {
//! # distribution_starting_block_height: 42,
//! # total_rewards: 100,
//! # distributed_rewards: 10,
//! # active: true,
//! # ..EpochRewards::default()
//! # };
//! # let mut d: Vec<u8> = bincode::serialize(&epoch_rewards).unwrap();
//! # let a = AccountInfo::new(&p, false, false, l, &mut d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
Expand Down Expand Up @@ -86,9 +101,16 @@
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = EpochRewards::id();
//! # let l = &mut 1120560;
//! # let d = &mut vec![0, 202, 154, 59, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let l = &mut 1559040;
//! # let epoch_rewards = EpochRewards {
//! # distribution_starting_block_height: 42,
//! # total_rewards: 100,
//! # distributed_rewards: 10,
//! # active: true,
//! # ..EpochRewards::default()
//! # };
//! # let mut d: Vec<u8> = bincode::serialize(&epoch_rewards).unwrap();
//! # let a = AccountInfo::new(&p, false, false, l, &mut d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
Expand All @@ -109,9 +131,17 @@
//! # use anyhow::Result;
//! #
//! fn print_sysvar_epoch_rewards(client: &RpcClient) -> Result<()> {
//! # let epoch_rewards = EpochRewards {
//! # distribution_starting_block_height: 42,
//! # total_rewards: 100,
//! # distributed_rewards: 10,
//! # active: true,
//! # ..EpochRewards::default()
//! # };
//! # let data: Vec<u8> = bincode::serialize(&epoch_rewards)?;
//! # client.set_get_account_response(epoch_rewards::ID, Account {
//! # lamports: 1120560,
//! # data: vec![0, 202, 154, 59, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0],
//! # data,
//! # owner: solana_sdk::system_program::ID,
//! # executable: false,
//! # rent_epoch: 307,
Expand Down

0 comments on commit ecb4f62

Please sign in to comment.