Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
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
5 changes: 5 additions & 0 deletions cli/src/cluster_query.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
stake::is_stake_program_v2_enabled,
};
use chrono::{Local, TimeZone};
use clap::{value_t, value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand};
Expand Down Expand Up @@ -1349,6 +1350,8 @@ pub fn process_show_stakes(
let stake_history = from_account(&stake_history_account).ok_or_else(|| {
CliError::RpcRequestError("Failed to deserialize stake history".to_string())
})?;
// At v1.6, this check can be removed and simply passed as `true`
let stake_program_v2_enabled = is_stake_program_v2_enabled(rpc_client);

let mut stake_accounts: Vec<CliKeyedStakeState> = vec![];
for (stake_pubkey, stake_account) in all_stake_accounts {
Expand All @@ -1364,6 +1367,7 @@ pub fn process_show_stakes(
use_lamports_unit,
&stake_history,
&clock,
stake_program_v2_enabled,
),
});
}
Expand All @@ -1382,6 +1386,7 @@ pub fn process_show_stakes(
use_lamports_unit,
&stake_history,
&clock,
stake_program_v2_enabled,
),
});
}
Expand Down
21 changes: 18 additions & 3 deletions cli/src/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use solana_sdk::{
account::from_account,
account_utils::StateMut,
clock::{Clock, Epoch, Slot, UnixTimestamp, SECONDS_PER_DAY},
feature, feature_set,
message::Message,
pubkey::Pubkey,
system_instruction::SystemError,
Expand Down Expand Up @@ -1501,6 +1502,7 @@ pub fn build_stake_state(
use_lamports_unit: bool,
stake_history: &StakeHistory,
clock: &Clock,
stake_program_v2_enabled: bool,
) -> CliStakeState {
match stake_state {
StakeState::Stake(
Expand All @@ -1512,9 +1514,12 @@ pub fn build_stake_state(
stake,
) => {
let current_epoch = clock.epoch;
let (active_stake, activating_stake, deactivating_stake) = stake
.delegation
.stake_activating_and_deactivating(current_epoch, Some(stake_history));
let (active_stake, activating_stake, deactivating_stake) =
stake.delegation.stake_activating_and_deactivating(
current_epoch,
Some(stake_history),
stake_program_v2_enabled,
);
let lockup = if lockup.is_in_force(clock, None) {
Some(lockup.into())
} else {
Expand Down Expand Up @@ -1710,6 +1715,7 @@ pub fn process_show_stake_account(
use_lamports_unit,
&stake_history,
&clock,
is_stake_program_v2_enabled(rpc_client), // At v1.6, this check can be removed and simply passed as `true`
);

if state.stake_type == CliStakeType::Stake {
Expand Down Expand Up @@ -1880,6 +1886,15 @@ pub fn process_delegate_stake(
}
}

pub fn is_stake_program_v2_enabled(rpc_client: &RpcClient) -> bool {
rpc_client
.get_account(&feature_set::stake_program_v2::id())
.ok()
.and_then(|account| feature::from_account(&account))
.and_then(|feature| feature.activated_at)
.is_some()
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
7 changes: 5 additions & 2 deletions core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,8 +1039,11 @@ impl JsonRpcRequestProcessor {
solana_sdk::account::from_account::<StakeHistory>(&stake_history_account)
.ok_or_else(Error::internal_error)?;

let (active, activating, deactivating) =
delegation.stake_activating_and_deactivating(epoch, Some(&stake_history));
let (active, activating, deactivating) = delegation.stake_activating_and_deactivating(
epoch,
Some(&stake_history),
bank.stake_program_v2_enabled(),
);
let stake_activation_state = if deactivating > 0 {
StakeActivationState::Deactivating
} else if activating > 0 {
Expand Down
15 changes: 12 additions & 3 deletions ledger/src/staking_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,10 @@ pub(crate) mod tests {
let result: Vec<_> = epoch_stakes_and_lockouts(&bank, first_leader_schedule_epoch);
assert_eq!(
result,
vec![(leader_stake.stake(first_leader_schedule_epoch, None), None)]
vec![(
leader_stake.stake(first_leader_schedule_epoch, None, true),
None
)]
);

// epoch stakes and lockouts are saved off for the future epoch, should
Expand All @@ -244,8 +247,14 @@ pub(crate) mod tests {
let stake_history =
from_account::<StakeHistory>(&bank.get_account(&stake_history::id()).unwrap()).unwrap();
let mut expected = vec![
(leader_stake.stake(bank.epoch(), Some(&stake_history)), None),
(other_stake.stake(bank.epoch(), Some(&stake_history)), None),
(
leader_stake.stake(bank.epoch(), Some(&stake_history), true),
None,
),
(
other_stake.stake(bank.epoch(), Some(&stake_history), true),
None,
),
];

expected.sort();
Expand Down
52 changes: 35 additions & 17 deletions programs/stake/src/legacy_stake_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub struct Stake {

impl Stake {
pub fn stake(&self, epoch: Epoch, history: Option<&StakeHistory>) -> u64 {
self.delegation.stake(epoch, history)
self.delegation.stake(epoch, history, false)
}

pub fn redeem_rewards(
Expand Down Expand Up @@ -145,7 +145,7 @@ impl Stake {
for (epoch, final_epoch_credits, initial_epoch_credits) in
new_vote_state.epoch_credits().iter().copied()
{
let stake = u128::from(self.delegation.stake(epoch, stake_history));
let stake = u128::from(self.delegation.stake(epoch, stake_history, false));

// figure out how much this stake has seen that
// for which the vote account has a record
Expand Down Expand Up @@ -596,7 +596,9 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
.check(&signers, StakeAuthorize::Withdrawer)?;
// if we have a deactivation epoch and we're in cooldown
let staked = if clock.epoch >= stake.delegation.deactivation_epoch {
stake.delegation.stake(clock.epoch, Some(stake_history))
stake
.delegation
.stake(clock.epoch, Some(stake_history), false)
} else {
// Assume full stake if the stake account hasn't been
// de-activated, because in the future the exposed stake
Expand Down Expand Up @@ -693,11 +695,12 @@ pub fn calculate_points(
}
}

// utility function, used by runtime::Stakes, tests
// utility function, used by runtime::Stakes and tests
pub fn new_stake_history_entry<'a, I>(
epoch: Epoch,
stakes: I,
history: Option<&StakeHistory>,
fix_stake_deactivate: bool,
) -> StakeHistoryEntry
where
I: Iterator<Item = &'a Delegation>,
Expand All @@ -708,7 +711,10 @@ where
(a.0 + b.0, a.1 + b.1, a.2 + b.2)
}
let (effective, activating, deactivating) = stakes.fold((0, 0, 0), |sum, stake| {
add(sum, stake.stake_activating_and_deactivating(epoch, history))
add(
sum,
stake.stake_activating_and_deactivating(epoch, history, fix_stake_deactivate),
)
});

StakeHistoryEntry {
Expand Down Expand Up @@ -1041,6 +1047,7 @@ mod tests {
epoch,
delegations.iter().chain(bootstrap_delegation.iter()),
Some(&stake_history),
false,
);
stake_history.add(epoch, entry);
}
Expand All @@ -1063,25 +1070,34 @@ mod tests {
let mut stake_history = StakeHistory::default();
// assert that this stake follows step function if there's no history
assert_eq!(
stake.stake_activating_and_deactivating(stake.activation_epoch, Some(&stake_history)),
stake.stake_activating_and_deactivating(
stake.activation_epoch,
Some(&stake_history),
false
),
(0, stake.stake, 0)
);
for epoch in stake.activation_epoch + 1..stake.deactivation_epoch {
assert_eq!(
stake.stake_activating_and_deactivating(epoch, Some(&stake_history)),
stake.stake_activating_and_deactivating(epoch, Some(&stake_history), false),
(stake.stake, 0, 0)
);
}
// assert that this stake is full deactivating
assert_eq!(
stake.stake_activating_and_deactivating(stake.deactivation_epoch, Some(&stake_history)),
stake.stake_activating_and_deactivating(
stake.deactivation_epoch,
Some(&stake_history),
false
),
(stake.stake, 0, stake.stake)
);
// assert that this stake is fully deactivated if there's no history
assert_eq!(
stake.stake_activating_and_deactivating(
stake.deactivation_epoch + 1,
Some(&stake_history)
Some(&stake_history),
false,
),
(0, 0, 0)
);
Expand All @@ -1096,7 +1112,7 @@ mod tests {
);
// assert that this stake is broken, because above setup is broken
assert_eq!(
stake.stake_activating_and_deactivating(1, Some(&stake_history)),
stake.stake_activating_and_deactivating(1, Some(&stake_history), false),
(0, stake.stake, 0)
);

Expand All @@ -1111,7 +1127,7 @@ mod tests {
);
// assert that this stake is broken, because above setup is broken
assert_eq!(
stake.stake_activating_and_deactivating(2, Some(&stake_history)),
stake.stake_activating_and_deactivating(2, Some(&stake_history), false),
(increment, stake.stake - increment, 0)
);

Expand All @@ -1130,7 +1146,8 @@ mod tests {
assert_eq!(
stake.stake_activating_and_deactivating(
stake.deactivation_epoch + 1,
Some(&stake_history)
Some(&stake_history),
false,
),
(stake.stake, 0, stake.stake) // says "I'm still waiting for deactivation"
);
Expand All @@ -1148,7 +1165,8 @@ mod tests {
assert_eq!(
stake.stake_activating_and_deactivating(
stake.deactivation_epoch + 2,
Some(&stake_history)
Some(&stake_history),
false,
),
(stake.stake - increment, 0, stake.stake - increment) // hung, should be lower
);
Expand Down Expand Up @@ -1213,7 +1231,7 @@ mod tests {
(0, history.deactivating)
};
assert_eq!(
stake.stake_activating_and_deactivating(epoch, Some(&stake_history)),
stake.stake_activating_and_deactivating(epoch, Some(&stake_history), false),
(expected_stake, expected_activating, expected_deactivating)
);
}
Expand All @@ -1240,7 +1258,7 @@ mod tests {
for epoch in 0..epochs {
let stake = delegations
.iter()
.map(|delegation| delegation.stake(epoch, Some(&stake_history)))
.map(|delegation| delegation.stake(epoch, Some(&stake_history), false))
.sum::<u64>();
max_stake = max_stake.max(stake);
min_stake = min_stake.min(stake);
Expand Down Expand Up @@ -1299,15 +1317,15 @@ mod tests {

let mut prev_total_effective_stake = delegations
.iter()
.map(|delegation| delegation.stake(0, Some(&stake_history)))
.map(|delegation| delegation.stake(0, Some(&stake_history), false))
.sum::<u64>();

// uncomment and add ! for fun with graphing
// eprintln("\n{:8} {:8} {:8}", " epoch", " total", " delta");
for epoch in 1..epochs {
let total_effective_stake = delegations
.iter()
.map(|delegation| delegation.stake(epoch, Some(&stake_history)))
.map(|delegation| delegation.stake(epoch, Some(&stake_history), false))
.sum::<u64>();

let delta = if total_effective_stake > prev_total_effective_stake {
Expand Down
Loading