Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor cli-output large functions and add starting epoch for rewards #3085

Merged
merged 2 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 80 additions & 73 deletions cli-output/src/cli_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,84 @@ impl VerboseDisplay for CliStakeState {
}
}

fn show_inactive_stake(
me: &CliStakeState,
f: &mut fmt::Formatter,
delegated_stake: u64,
) -> fmt::Result {
if let Some(deactivation_epoch) = me.deactivation_epoch {
if me.current_epoch > deactivation_epoch {
let deactivating_stake = me.deactivating_stake.or(me.active_stake);
if let Some(deactivating_stake) = deactivating_stake {
writeln!(
f,
"Inactive Stake: {}",
build_balance_message(
delegated_stake - deactivating_stake,
me.use_lamports_unit,
true
),
)?;
writeln!(
f,
"Deactivating Stake: {}",
build_balance_message(deactivating_stake, me.use_lamports_unit, true),
)?;
}
}
writeln!(
f,
"Stake deactivates starting from epoch: {deactivation_epoch}"
)?;
}
if let Some(delegated_vote_account_address) = &me.delegated_vote_account_address {
writeln!(
f,
"Delegated Vote Account Address: {delegated_vote_account_address}"
)?;
}
Ok(())
}

fn show_active_stake(
me: &CliStakeState,
f: &mut fmt::Formatter,
delegated_stake: u64,
) -> fmt::Result {
if me
.deactivation_epoch
.map(|d| me.current_epoch <= d)
.unwrap_or(true)
{
let active_stake = me.active_stake.unwrap_or(0);
writeln!(
f,
"Active Stake: {}",
build_balance_message(active_stake, me.use_lamports_unit, true),
)?;
let activating_stake = me.activating_stake.or_else(|| {
if me.active_stake.is_none() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think might be simplified:

me.active_stake.is_none().then_some(delegated_stake)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think another PR is best, I just wanted to move the logic as-is to make sure functionality is identical.

Some(delegated_stake)
} else {
None
}
});
if let Some(activating_stake) = activating_stake {
writeln!(
f,
"Activating Stake: {}",
build_balance_message(activating_stake, me.use_lamports_unit, true),
)?;
writeln!(
f,
"Stake activates starting from epoch: {}",
me.activation_epoch.unwrap()
)?;
}
}
Ok(())
}

impl fmt::Display for CliStakeState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn show_authorized(f: &mut fmt::Formatter, authorized: &CliAuthorized) -> fmt::Result {
Expand Down Expand Up @@ -1374,79 +1452,8 @@ impl fmt::Display for CliStakeState {
"Delegated Stake: {}",
build_balance_message(delegated_stake, self.use_lamports_unit, true)
)?;
if self
.deactivation_epoch
.map(|d| self.current_epoch <= d)
.unwrap_or(true)
{
let active_stake = self.active_stake.unwrap_or(0);
writeln!(
f,
"Active Stake: {}",
build_balance_message(active_stake, self.use_lamports_unit, true),
)?;
let activating_stake = self.activating_stake.or_else(|| {
if self.active_stake.is_none() {
Some(delegated_stake)
} else {
None
}
});
if let Some(activating_stake) = activating_stake {
writeln!(
f,
"Activating Stake: {}",
build_balance_message(
activating_stake,
self.use_lamports_unit,
true
),
)?;
writeln!(
f,
"Stake activates starting from epoch: {}",
self.activation_epoch.unwrap()
)?;
}
}

if let Some(deactivation_epoch) = self.deactivation_epoch {
if self.current_epoch > deactivation_epoch {
let deactivating_stake = self.deactivating_stake.or(self.active_stake);
if let Some(deactivating_stake) = deactivating_stake {
writeln!(
f,
"Inactive Stake: {}",
build_balance_message(
delegated_stake - deactivating_stake,
self.use_lamports_unit,
true
),
)?;
writeln!(
f,
"Deactivating Stake: {}",
build_balance_message(
deactivating_stake,
self.use_lamports_unit,
true
),
)?;
}
}
writeln!(
f,
"Stake deactivates starting from epoch: {deactivation_epoch}"
)?;
}
if let Some(delegated_vote_account_address) =
&self.delegated_vote_account_address
{
writeln!(
f,
"Delegated Vote Account Address: {delegated_vote_account_address}"
)?;
}
show_active_stake(self, f, delegated_stake)?;
show_inactive_stake(self, f, delegated_stake)?;
} else {
writeln!(f, "Stake account is undelegated")?;
}
Expand Down
6 changes: 6 additions & 0 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ pub enum CliCommand {
use_lamports_unit: bool,
with_rewards: Option<usize>,
use_csv: bool,
starting_epoch: Option<u64>,
},
StakeAuthorize {
stake_account_pubkey: Pubkey,
Expand Down Expand Up @@ -344,6 +345,7 @@ pub enum CliCommand {
use_lamports_unit: bool,
use_csv: bool,
with_rewards: Option<usize>,
starting_epoch: Option<u64>,
},
WithdrawFromVoteAccount {
vote_account_pubkey: Pubkey,
Expand Down Expand Up @@ -1325,13 +1327,15 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
use_lamports_unit,
with_rewards,
use_csv,
starting_epoch,
} => process_show_stake_account(
&rpc_client,
config,
stake_account_pubkey,
*use_lamports_unit,
*with_rewards,
*use_csv,
*starting_epoch,
),
CliCommand::ShowStakeHistory {
use_lamports_unit,
Expand Down Expand Up @@ -1494,13 +1498,15 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
use_lamports_unit,
use_csv,
with_rewards,
starting_epoch,
} => process_show_vote_account(
&rpc_client,
config,
vote_account_pubkey,
*use_lamports_unit,
*use_csv,
*with_rewards,
*starting_epoch,
),
CliCommand::WithdrawFromVoteAccount {
vote_account_pubkey,
Expand Down
32 changes: 28 additions & 4 deletions cli/src/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,14 @@ impl StakeSubCommands for App<'_, '_> {
.takes_value(false)
.help("Format stake rewards data in csv"),
)
.arg(
Arg::with_name("starting_epoch")
.long("starting-epoch")
.takes_value(true)
.value_name("NUM")
.requires("with_rewards")
.help("Start displaying from epoch NUM"),
)
.arg(
Arg::with_name("num_rewards_epochs")
.long("num-rewards-epochs")
Expand Down Expand Up @@ -1329,12 +1337,14 @@ pub fn parse_show_stake_account(
} else {
None
};
let starting_epoch = value_of(matches, "starting_epoch");
Ok(CliCommandInfo::without_signers(
CliCommand::ShowStakeAccount {
pubkey: stake_account_pubkey,
use_lamports_unit,
with_rewards,
use_csv,
starting_epoch,
},
))
}
Expand Down Expand Up @@ -2541,10 +2551,18 @@ pub(crate) fn fetch_epoch_rewards(
rpc_client: &RpcClient,
address: &Pubkey,
mut num_epochs: usize,
starting_epoch: Option<u64>,
) -> Result<Vec<CliEpochReward>, Box<dyn std::error::Error>> {
let mut all_epoch_rewards = vec![];
let epoch_schedule = rpc_client.get_epoch_schedule()?;
let mut rewards_epoch = rpc_client.get_epoch_info()?.epoch;
let mut rewards_epoch = if let Some(epoch) = starting_epoch {
epoch
} else {
rpc_client
.get_epoch_info()?
.epoch
.saturating_sub(num_epochs as u64)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand why do we subtract num_epochs now (before we didn't). Before we subtract 1 in the loop before calling get_inflation_reward so maybe should be also here subtract 1?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the loop was proceeding backwards by epoch before always from the newest epoch. I reversed the direction to now start at the older epoch and then move forward.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

num_epochs has to be at least 1. So it will subtract 1 here in the default case.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, everything looks fine

};

let mut process_reward =
|reward: &Option<RpcInflationReward>| -> Result<(), Box<dyn std::error::Error>> {
Expand All @@ -2559,14 +2577,14 @@ pub(crate) fn fetch_epoch_rewards(
Ok(())
};

while num_epochs > 0 && rewards_epoch > 0 {
rewards_epoch = rewards_epoch.saturating_sub(1);
while num_epochs > 0 {
if let Ok(rewards) = rpc_client.get_inflation_reward(&[*address], Some(rewards_epoch)) {
process_reward(&rewards[0])?;
} else {
eprintln!("Rewards not available for epoch {rewards_epoch}");
}
num_epochs = num_epochs.saturating_sub(1);
rewards_epoch = rewards_epoch.saturating_add(1);
}

Ok(all_epoch_rewards)
Expand All @@ -2579,6 +2597,7 @@ pub fn process_show_stake_account(
use_lamports_unit: bool,
with_rewards: Option<usize>,
use_csv: bool,
starting_epoch: Option<u64>,
) -> ProcessResult {
let stake_account = rpc_client.get_account(stake_account_address)?;
if stake_account.owner != stake::program::id() {
Expand Down Expand Up @@ -2614,7 +2633,12 @@ pub fn process_show_stake_account(

if state.stake_type == CliStakeType::Stake && state.activation_epoch.is_some() {
let epoch_rewards = with_rewards.and_then(|num_epochs| {
match fetch_epoch_rewards(rpc_client, stake_account_address, num_epochs) {
match fetch_epoch_rewards(
rpc_client,
stake_account_address,
num_epochs,
starting_epoch,
) {
Ok(rewards) => Some(rewards),
Err(error) => {
eprintln!("Failed to fetch epoch rewards: {error:?}");
Expand Down
18 changes: 17 additions & 1 deletion cli/src/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,14 @@ impl VoteSubCommands for App<'_, '_> {
.takes_value(false)
.help("Format rewards in a CSV table"),
)
.arg(
Arg::with_name("starting_epoch")
.long("starting-epoch")
.takes_value(true)
.value_name("NUM")
.requires("with_rewards")
.help("Start displaying from epoch NUM"),
)
.arg(
Arg::with_name("num_rewards_epochs")
.long("num-rewards-epochs")
Expand Down Expand Up @@ -675,12 +683,14 @@ pub fn parse_vote_get_account_command(
} else {
None
};
let starting_epoch = value_of(matches, "starting_epoch");
Ok(CliCommandInfo::without_signers(
CliCommand::ShowVoteAccount {
pubkey: vote_account_pubkey,
use_lamports_unit,
use_csv,
with_rewards,
starting_epoch,
},
))
}
Expand Down Expand Up @@ -1261,6 +1271,7 @@ pub fn process_show_vote_account(
use_lamports_unit: bool,
use_csv: bool,
with_rewards: Option<usize>,
starting_epoch: Option<u64>,
) -> ProcessResult {
let (vote_account, vote_state) =
get_vote_account(rpc_client, vote_account_address, config.commitment)?;
Expand Down Expand Up @@ -1288,7 +1299,12 @@ pub fn process_show_vote_account(

let epoch_rewards =
with_rewards.and_then(|num_epochs| {
match crate::stake::fetch_epoch_rewards(rpc_client, vote_account_address, num_epochs) {
match crate::stake::fetch_epoch_rewards(
rpc_client,
vote_account_address,
num_epochs,
starting_epoch,
) {
Ok(rewards) => Some(rewards),
Err(error) => {
eprintln!("Failed to fetch epoch rewards: {error:?}");
Expand Down
Loading