Skip to content

Commit 1048eb6

Browse files
committed
harness: fix create_mock_epoch_stake formula
1 parent 478208c commit 1048eb6

File tree

1 file changed

+135
-11
lines changed

1 file changed

+135
-11
lines changed

harness/src/epoch_stake.rs

Lines changed: 135 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,149 @@ use {solana_pubkey::Pubkey, std::collections::HashMap};
66
/// The total epoch stake is calculated by summing all vote account stakes.
77
pub type EpochStake = HashMap<Pubkey, u64>;
88

9-
/// Create an `EpochStake` instance with a few mocked-out vote accounts to
10-
/// achieve the provided total stake.
9+
/// Create an `EpochStake` instance with a few mocked-out entries (vote accounts
10+
/// with stake) to achieve the provided total stake.
1111
pub fn create_mock_epoch_stake(target_total: u64) -> EpochStake {
12+
const BASE_STAKE_PER_ACCOUNT: u64 = 100_000_000_000; // 100 SOL
13+
1214
let mut epoch_stake = HashMap::new();
1315

1416
if target_total == 0 {
1517
return epoch_stake;
1618
}
1719

18-
let num_accounts = target_total.div_ceil(1_000_000_000);
19-
20-
let base_stake = target_total / num_accounts;
21-
let remainder = target_total % base_stake;
20+
let num_accounts = target_total / BASE_STAKE_PER_ACCOUNT;
21+
let remainder = target_total % BASE_STAKE_PER_ACCOUNT;
2222

23-
std::iter::repeat_n(base_stake, num_accounts as usize - 1)
24-
.chain(std::iter::once(base_stake + remainder))
25-
.for_each(|stake| {
26-
epoch_stake.insert(Pubkey::new_unique(), stake);
27-
});
23+
if num_accounts == 0 {
24+
epoch_stake.insert(Pubkey::new_unique(), target_total);
25+
} else {
26+
std::iter::repeat_n(BASE_STAKE_PER_ACCOUNT, num_accounts as usize - 1)
27+
.chain(std::iter::once(BASE_STAKE_PER_ACCOUNT + remainder))
28+
.for_each(|stake| {
29+
epoch_stake.insert(Pubkey::new_unique(), stake);
30+
});
31+
}
2832

2933
epoch_stake
3034
}
35+
36+
#[cfg(test)]
37+
mod tests {
38+
use super::*;
39+
40+
#[test]
41+
fn test_zero_stake() {
42+
let epoch_stake = create_mock_epoch_stake(0);
43+
assert_eq!(epoch_stake.len(), 0);
44+
assert_eq!(epoch_stake.values().sum::<u64>(), 0);
45+
}
46+
47+
#[test]
48+
fn test_num_accounts_zero() {
49+
// Target < 100 SOL, results in num_accounts = 0
50+
// Should create single account with full amount
51+
52+
// 1 lamport
53+
let epoch_stake = create_mock_epoch_stake(1);
54+
assert_eq!(epoch_stake.len(), 1);
55+
assert_eq!(epoch_stake.values().sum::<u64>(), 1);
56+
57+
// 50 SOL
58+
let epoch_stake = create_mock_epoch_stake(50_000_000_000);
59+
assert_eq!(epoch_stake.len(), 1);
60+
assert_eq!(epoch_stake.values().sum::<u64>(), 50_000_000_000);
61+
62+
// 99.999999999 SOL
63+
let epoch_stake = create_mock_epoch_stake(99_999_999_999);
64+
assert_eq!(epoch_stake.len(), 1);
65+
assert_eq!(epoch_stake.values().sum::<u64>(), 99_999_999_999);
66+
}
67+
68+
#[test]
69+
fn test_num_accounts_one() {
70+
// 100 SOL <= target < 200 SOL, results in num_accounts = 1
71+
72+
// Exactly 100 SOL, no remainder
73+
let epoch_stake = create_mock_epoch_stake(100_000_000_000);
74+
assert_eq!(epoch_stake.len(), 1);
75+
assert_eq!(epoch_stake.values().sum::<u64>(), 100_000_000_000);
76+
assert!(epoch_stake.values().all(|&s| s == 100_000_000_000));
77+
78+
// 150 SOL, with remainder
79+
let epoch_stake = create_mock_epoch_stake(150_000_000_000);
80+
assert_eq!(epoch_stake.len(), 1);
81+
assert_eq!(epoch_stake.values().sum::<u64>(), 150_000_000_000);
82+
assert!(epoch_stake.values().all(|&s| s == 150_000_000_000));
83+
84+
// 199.999999999 SOL, with remainder
85+
let epoch_stake = create_mock_epoch_stake(199_999_999_999);
86+
assert_eq!(epoch_stake.len(), 1);
87+
assert_eq!(epoch_stake.values().sum::<u64>(), 199_999_999_999);
88+
}
89+
90+
#[test]
91+
fn test_num_accounts_two() {
92+
// 200 SOL <= target < 300 SOL, results in num_accounts = 2
93+
94+
// Exactly 200 SOL, no remainder -> [100, 100]
95+
let epoch_stake = create_mock_epoch_stake(200_000_000_000);
96+
assert_eq!(epoch_stake.len(), 2);
97+
assert_eq!(epoch_stake.values().sum::<u64>(), 200_000_000_000);
98+
assert!(epoch_stake.values().all(|&s| s == 100_000_000_000));
99+
100+
// 250 SOL, with remainder -> [100, 150]
101+
let epoch_stake = create_mock_epoch_stake(250_000_000_000);
102+
assert_eq!(epoch_stake.len(), 2);
103+
assert_eq!(epoch_stake.values().sum::<u64>(), 250_000_000_000);
104+
let mut stakes: Vec<u64> = epoch_stake.values().copied().collect();
105+
stakes.sort();
106+
assert_eq!(stakes, vec![100_000_000_000, 150_000_000_000]);
107+
108+
// 299.999999999 SOL, with remainder -> [100, 199.999999999]
109+
let epoch_stake = create_mock_epoch_stake(299_999_999_999);
110+
assert_eq!(epoch_stake.len(), 2);
111+
assert_eq!(epoch_stake.values().sum::<u64>(), 299_999_999_999);
112+
let mut stakes: Vec<u64> = epoch_stake.values().copied().collect();
113+
stakes.sort();
114+
assert_eq!(stakes, vec![100_000_000_000, 199_999_999_999]);
115+
}
116+
117+
#[test]
118+
fn test_num_accounts_greater_than_two() {
119+
// target >= 300 SOL, results in num_accounts > 2
120+
121+
// Exactly 300 SOL, no remainder -> [100, 100, 100]
122+
let epoch_stake = create_mock_epoch_stake(300_000_000_000);
123+
assert_eq!(epoch_stake.len(), 3);
124+
assert_eq!(epoch_stake.values().sum::<u64>(), 300_000_000_000);
125+
assert!(epoch_stake.values().all(|&s| s == 100_000_000_000));
126+
127+
// 350 SOL, with remainder -> [100, 100, 150]
128+
let epoch_stake = create_mock_epoch_stake(350_000_000_000);
129+
assert_eq!(epoch_stake.len(), 3);
130+
assert_eq!(epoch_stake.values().sum::<u64>(), 350_000_000_000);
131+
let mut stakes: Vec<u64> = epoch_stake.values().copied().collect();
132+
stakes.sort();
133+
assert_eq!(
134+
stakes,
135+
vec![100_000_000_000, 100_000_000_000, 150_000_000_000]
136+
);
137+
138+
// 1000 SOL, no remainder -> [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
139+
let epoch_stake = create_mock_epoch_stake(1_000_000_000_000);
140+
assert_eq!(epoch_stake.len(), 10);
141+
assert_eq!(epoch_stake.values().sum::<u64>(), 1_000_000_000_000);
142+
assert!(epoch_stake.values().all(|&s| s == 100_000_000_000));
143+
144+
// 1234.567890123 SOL, with remainder
145+
let epoch_stake = create_mock_epoch_stake(1_234_567_890_123);
146+
assert_eq!(epoch_stake.len(), 12);
147+
assert_eq!(epoch_stake.values().sum::<u64>(), 1_234_567_890_123);
148+
let mut stakes: Vec<u64> = epoch_stake.values().copied().collect();
149+
stakes.sort();
150+
// Should have 11 accounts with 100 SOL and 1 account with 134.567890123 SOL
151+
assert_eq!(stakes.iter().filter(|&&s| s == 100_000_000_000).count(), 11);
152+
assert_eq!(stakes.iter().filter(|&&s| s == 134_567_890_123).count(), 1);
153+
}
154+
}

0 commit comments

Comments
 (0)