Skip to content

Commit

Permalink
Cli: fix inflation rewards effective slot, block time (anza-xyz#4226)
Browse files Browse the repository at this point in the history
* Remove lines no longer correct

* Add verbose display for slot, block time for individual rewards

* Populate rewards with correct block times

* Deprecate incorrect rewards metadata

* Change alignment to accommodate huge balance amounts

* Formally deprecate fields

* Use CliEpochRewardsMetadata::default to handle deprecation warnings
  • Loading branch information
CriesofCarrots authored Jan 8, 2025
1 parent 324b055 commit ae6e34c
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 17 deletions.
71 changes: 64 additions & 7 deletions cli-output/src/cli_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,11 +1021,19 @@ pub struct CliKeyedEpochReward {
pub reward: Option<CliEpochReward>,
}

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CliEpochRewardsMetadata {
pub epoch: Epoch,
#[deprecated(
since = "2.2.0",
note = "Please use CliEpochReward::effective_slot per reward"
)]
pub effective_slot: Slot,
#[deprecated(
since = "2.2.0",
note = "Please use CliEpochReward::block_time per reward"
)]
pub block_time: UnixTimestamp,
}

Expand All @@ -1038,7 +1046,59 @@ pub struct CliKeyedEpochRewards {
}

impl QuietDisplay for CliKeyedEpochRewards {}
impl VerboseDisplay for CliKeyedEpochRewards {}
impl VerboseDisplay for CliKeyedEpochRewards {
fn write_str(&self, w: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.rewards.is_empty() {
writeln!(w, "No rewards found in epoch")?;
return Ok(());
}

if let Some(metadata) = &self.epoch_metadata {
writeln!(w, "Epoch: {}", metadata.epoch)?;
}
writeln!(w, "Epoch Rewards:")?;
writeln!(
w,
" {:<44} {:<11} {:<23} {:<18} {:<20} {:>14} {:>7} {:>10}",
"Address",
"Reward Slot",
"Time",
"Amount",
"New Balance",
"Percent Change",
"APR",
"Commission"
)?;
for keyed_reward in &self.rewards {
match &keyed_reward.reward {
Some(reward) => {
writeln!(
w,
" {:<44} {:<11} {:<23} ◎{:<17.9} ◎{:<19.9} {:>13.9}% {:>7} {:>10}",
keyed_reward.address,
reward.effective_slot,
Utc.timestamp_opt(reward.block_time, 0).unwrap(),
lamports_to_sol(reward.amount),
lamports_to_sol(reward.post_balance),
reward.percent_change,
reward
.apr
.map(|apr| format!("{apr:.2}%"))
.unwrap_or_default(),
reward
.commission
.map(|commission| format!("{commission}%"))
.unwrap_or_else(|| "-".to_string()),
)?;
}
None => {
writeln!(w, " {:<44} No rewards in epoch", keyed_reward.address,)?;
}
}
}
Ok(())
}
}

impl fmt::Display for CliKeyedEpochRewards {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand All @@ -1049,22 +1109,19 @@ impl fmt::Display for CliKeyedEpochRewards {

if let Some(metadata) = &self.epoch_metadata {
writeln!(f, "Epoch: {}", metadata.epoch)?;
writeln!(f, "Reward Slot: {}", metadata.effective_slot)?;
let timestamp = metadata.block_time;
writeln!(f, "Block Time: {}", unix_timestamp_to_string(timestamp))?;
}
writeln!(f, "Epoch Rewards:")?;
writeln!(
f,
" {:<44} {:<18} {:<18} {:>14} {:>14} {:>10}",
" {:<44} {:<18} {:<18} {:>14} {:>7} {:>10}",
"Address", "Amount", "New Balance", "Percent Change", "APR", "Commission"
)?;
for keyed_reward in &self.rewards {
match &keyed_reward.reward {
Some(reward) => {
writeln!(
f,
" {:<44} ◎{:<17.9} ◎{:<17.9} {:>13.9}% {:>14} {:>10}",
" {:<44} ◎{:<17.9} ◎{:<17.9} {:>13.9}% {:>7} {:>10}",
keyed_reward.address,
lamports_to_sol(reward.amount),
lamports_to_sol(reward.post_balance),
Expand Down
27 changes: 19 additions & 8 deletions cli/src/inflation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ use {
},
solana_remote_wallet::remote_wallet::RemoteWalletManager,
solana_rpc_client::rpc_client::RpcClient,
solana_sdk::{clock::Epoch, pubkey::Pubkey},
std::rc::Rc,
solana_sdk::{
clock::{Epoch, Slot, UnixTimestamp},
pubkey::Pubkey,
},
std::{collections::HashMap, rc::Rc},
};

#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -114,23 +117,31 @@ fn process_rewards(
let epoch_schedule = rpc_client.get_epoch_schedule()?;

let mut epoch_rewards: Vec<CliKeyedEpochReward> = vec![];
let mut block_times: HashMap<Slot, UnixTimestamp> = HashMap::new();
let epoch_metadata = if let Some(Some(first_reward)) = rewards.iter().find(|&v| v.is_some()) {
let (epoch_start_time, epoch_end_time) =
crate::stake::get_epoch_boundary_timestamps(rpc_client, first_reward, &epoch_schedule)?;
for (reward, address) in rewards.iter().zip(addresses) {
let cli_reward = reward.as_ref().and_then(|reward| {
crate::stake::make_cli_reward(reward, epoch_start_time, epoch_end_time)
});
let cli_reward = if let Some(reward) = reward {
let block_time = if let Some(block_time) = block_times.get(&reward.effective_slot) {
*block_time
} else {
let block_time = rpc_client.get_block_time(reward.effective_slot)?;
block_times.insert(reward.effective_slot, block_time);
block_time
};
crate::stake::make_cli_reward(reward, block_time, epoch_start_time, epoch_end_time)
} else {
None
};
epoch_rewards.push(CliKeyedEpochReward {
address: address.to_string(),
reward: cli_reward,
});
}
let block_time = rpc_client.get_block_time(first_reward.effective_slot)?;
Some(CliEpochRewardsMetadata {
epoch: first_reward.epoch,
effective_slot: first_reward.effective_slot,
block_time,
..CliEpochRewardsMetadata::default()
})
} else {
None
Expand Down
7 changes: 5 additions & 2 deletions cli/src/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2544,6 +2544,7 @@ pub fn get_epoch_boundary_timestamps(

pub fn make_cli_reward(
reward: &RpcInflationReward,
block_time: UnixTimestamp,
epoch_start_time: UnixTimestamp,
epoch_end_time: UnixTimestamp,
) -> Option<CliEpochReward> {
Expand All @@ -2564,7 +2565,7 @@ pub fn make_cli_reward(
percent_change: rate_change * 100.0,
apr: Some(apr * 100.0),
commission: reward.commission,
block_time: epoch_end_time,
block_time,
})
} else {
None
Expand Down Expand Up @@ -2593,7 +2594,9 @@ pub(crate) fn fetch_epoch_rewards(
if let Some(reward) = reward {
let (epoch_start_time, epoch_end_time) =
get_epoch_boundary_timestamps(rpc_client, reward, &epoch_schedule)?;
if let Some(cli_reward) = make_cli_reward(reward, epoch_start_time, epoch_end_time)
let block_time = rpc_client.get_block_time(reward.effective_slot)?;
if let Some(cli_reward) =
make_cli_reward(reward, block_time, epoch_start_time, epoch_end_time)
{
all_epoch_rewards.push(cli_reward);
}
Expand Down

0 comments on commit ae6e34c

Please sign in to comment.