Add stake calculation tests with inflation/slashing (#13605)
* Add stake calculation tests with inflation/slashing * Clean up the test
This commit is contained in:
parent
215ddecaa5
commit
42421e77a9
|
@ -406,11 +406,11 @@ impl Delegation {
|
||||||
|
|
||||||
(
|
(
|
||||||
current_effective_stake,
|
current_effective_stake,
|
||||||
self.stake - current_effective_stake,
|
delegated_stake - current_effective_stake,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// no history or I've dropped out of history, so assume fully effective
|
// no history or I've dropped out of history, so assume fully effective
|
||||||
(self.stake, 0)
|
(delegated_stake, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2057,6 +2057,159 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_inflation_and_slashing_with_activating_and_deactivating_stake() {
|
||||||
|
// some really boring delegation and stake_history setup
|
||||||
|
let (delegated_stake, mut stake, stake_history) = {
|
||||||
|
let cluster_stake = 1_000;
|
||||||
|
let delegated_stake = 700;
|
||||||
|
|
||||||
|
let stake = Delegation {
|
||||||
|
stake: delegated_stake,
|
||||||
|
activation_epoch: 0,
|
||||||
|
deactivation_epoch: 4,
|
||||||
|
..Delegation::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut stake_history = StakeHistory::default();
|
||||||
|
stake_history.add(
|
||||||
|
0,
|
||||||
|
StakeHistoryEntry {
|
||||||
|
effective: cluster_stake,
|
||||||
|
activating: delegated_stake,
|
||||||
|
..StakeHistoryEntry::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let newly_effective_at_epoch1 = (cluster_stake as f64 * 0.25) as u64;
|
||||||
|
assert_eq!(newly_effective_at_epoch1, 250);
|
||||||
|
stake_history.add(
|
||||||
|
1,
|
||||||
|
StakeHistoryEntry {
|
||||||
|
effective: cluster_stake + newly_effective_at_epoch1,
|
||||||
|
activating: delegated_stake - newly_effective_at_epoch1,
|
||||||
|
..StakeHistoryEntry::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let newly_effective_at_epoch2 =
|
||||||
|
((cluster_stake + newly_effective_at_epoch1) as f64 * 0.25) as u64;
|
||||||
|
assert_eq!(newly_effective_at_epoch2, 312);
|
||||||
|
stake_history.add(
|
||||||
|
2,
|
||||||
|
StakeHistoryEntry {
|
||||||
|
effective: cluster_stake
|
||||||
|
+ newly_effective_at_epoch1
|
||||||
|
+ newly_effective_at_epoch2,
|
||||||
|
activating: delegated_stake
|
||||||
|
- newly_effective_at_epoch1
|
||||||
|
- newly_effective_at_epoch2,
|
||||||
|
..StakeHistoryEntry::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
stake_history.add(
|
||||||
|
3,
|
||||||
|
StakeHistoryEntry {
|
||||||
|
effective: cluster_stake + delegated_stake,
|
||||||
|
..StakeHistoryEntry::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
stake_history.add(
|
||||||
|
4,
|
||||||
|
StakeHistoryEntry {
|
||||||
|
effective: cluster_stake + delegated_stake,
|
||||||
|
deactivating: delegated_stake,
|
||||||
|
..StakeHistoryEntry::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let newly_not_effective_stake_at_epoch5 =
|
||||||
|
((cluster_stake + delegated_stake) as f64 * 0.25) as u64;
|
||||||
|
assert_eq!(newly_not_effective_stake_at_epoch5, 425);
|
||||||
|
stake_history.add(
|
||||||
|
5,
|
||||||
|
StakeHistoryEntry {
|
||||||
|
effective: cluster_stake + delegated_stake
|
||||||
|
- newly_not_effective_stake_at_epoch5,
|
||||||
|
deactivating: delegated_stake - newly_not_effective_stake_at_epoch5,
|
||||||
|
..StakeHistoryEntry::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
(delegated_stake, stake, stake_history)
|
||||||
|
};
|
||||||
|
|
||||||
|
// helper closures
|
||||||
|
let calculate_each_staking_status = |stake: &Delegation, epoch_count: usize| -> Vec<_> {
|
||||||
|
(0..epoch_count)
|
||||||
|
.map(|epoch| {
|
||||||
|
stake.stake_activating_and_deactivating(
|
||||||
|
epoch as u64,
|
||||||
|
Some(&stake_history),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
let adjust_staking_status = |rate: f64, status: &Vec<_>| {
|
||||||
|
status
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(a, b, c)| {
|
||||||
|
(
|
||||||
|
(a as f64 * rate) as u64,
|
||||||
|
(b as f64 * rate) as u64,
|
||||||
|
(c as f64 * rate) as u64,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected_staking_status_transition = vec![
|
||||||
|
(0, 700, 0),
|
||||||
|
(250, 450, 0),
|
||||||
|
(562, 138, 0),
|
||||||
|
(700, 0, 0),
|
||||||
|
(700, 0, 700),
|
||||||
|
(275, 0, 275),
|
||||||
|
(0, 0, 0),
|
||||||
|
];
|
||||||
|
let expected_staking_status_transition_base = vec![
|
||||||
|
(0, 700, 0),
|
||||||
|
(250, 450, 0),
|
||||||
|
(562, 138 + 1, 0), // +1 is needed for rounding
|
||||||
|
(700, 0, 0),
|
||||||
|
(700, 0, 700),
|
||||||
|
(275 + 1, 0, 275 + 1), // +1 is needed for rounding
|
||||||
|
(0, 0, 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
// normal stake activating and deactivating transition test, just in case
|
||||||
|
assert_eq!(
|
||||||
|
expected_staking_status_transition,
|
||||||
|
calculate_each_staking_status(&stake, expected_staking_status_transition.len())
|
||||||
|
);
|
||||||
|
|
||||||
|
// 10% inflation rewards assuming some sizable epochs passed!
|
||||||
|
let rate = 1.10;
|
||||||
|
stake.stake = (delegated_stake as f64 * rate) as u64;
|
||||||
|
let expected_staking_status_transition =
|
||||||
|
adjust_staking_status(rate, &expected_staking_status_transition_base);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
expected_staking_status_transition,
|
||||||
|
calculate_each_staking_status(&stake, expected_staking_status_transition_base.len()),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 50% slashing!!!
|
||||||
|
let rate = 0.5;
|
||||||
|
stake.stake = (delegated_stake as f64 * rate) as u64;
|
||||||
|
let expected_staking_status_transition =
|
||||||
|
adjust_staking_status(rate, &expected_staking_status_transition_base);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
expected_staking_status_transition,
|
||||||
|
calculate_each_staking_status(&stake, expected_staking_status_transition_base.len()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stop_activating_after_deactivation() {
|
fn test_stop_activating_after_deactivation() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
Loading…
Reference in New Issue