Skip to content

Commit e21949a

Browse files
authored
Merge pull request #166 from input-output-hk/NPG-1371-requirement-for-voter-reward
Requirement for voter reward - component tests
2 parents 020dd3f + 72169a3 commit e21949a

File tree

3 files changed

+89
-35
lines changed

3 files changed

+89
-35
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/.vscode
2+
/.vs
3+
/.idea
4+
25

36
qr-code.svg
47

catalyst-toolbox/src/rewards/voters.rs

Lines changed: 85 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -136,49 +136,79 @@ mod tests {
136136
use crate::utils::assert_are_close;
137137
use jormungandr_lib::crypto::{account::Identifier, hash::Hash};
138138
use snapshot_lib::registration::{Delegations, VotingRegistration};
139-
use snapshot_lib::Fraction;
140139
use snapshot_lib::Snapshot;
140+
use snapshot_lib::{Fraction, RawSnapshot};
141141
use test_strategy::proptest;
142142

143+
const DEFAULT_TEST_THRESHOLD: usize = 1;
144+
const DEFAULT_SNAPSHOT_THRESHOLD: u64 = 1;
145+
143146
#[proptest]
144-
fn test_all_active(snapshot: Snapshot) {
147+
fn test_all_active_voters(raw_snapshot: RawSnapshot) {
148+
let snapshot = Snapshot::from_raw_snapshot(
149+
raw_snapshot,
150+
DEFAULT_SNAPSHOT_THRESHOLD.into(),
151+
Fraction::from(1),
152+
&|_vk: &Identifier| String::new(),
153+
)
154+
.unwrap();
155+
145156
let votes_count = snapshot
146157
.voting_keys()
147158
.into_iter()
148159
.map(|key| (key.clone(), HashSet::from([Hash::from([0u8; 32])])))
149160
.collect::<VoteCount>();
150-
let n_voters = votes_count.len();
161+
162+
let number_of_voters = votes_count.len();
163+
151164
let voters = snapshot.to_full_snapshot_info();
152165
let rewards = calc_voter_rewards(
153166
votes_count,
154167
voters,
155-
Threshold::new(1, HashMap::new(), Vec::new()).unwrap(),
168+
Threshold::new(DEFAULT_TEST_THRESHOLD, HashMap::new(), Vec::new()).unwrap(),
156169
Rewards::ONE,
157170
)
158171
.unwrap();
159-
if n_voters > 0 {
172+
if number_of_voters > 0 {
160173
assert_are_close(rewards.values().sum::<Rewards>(), Rewards::ONE)
161174
} else {
162175
assert_eq!(rewards.len(), 0);
163176
}
164177
}
165178

166179
#[proptest]
167-
fn test_all_inactive(snapshot: Snapshot) {
180+
fn test_all_inactive_voters(raw_snapshot: RawSnapshot) {
181+
let snapshot = Snapshot::from_raw_snapshot(
182+
raw_snapshot,
183+
DEFAULT_SNAPSHOT_THRESHOLD.into(),
184+
Fraction::from(1),
185+
&|_vk: &Identifier| String::new(),
186+
)
187+
.unwrap();
188+
168189
let votes_count = VoteCount::new();
190+
169191
let voters = snapshot.to_full_snapshot_info();
170192
let rewards = calc_voter_rewards(
171193
votes_count,
172194
voters,
173-
Threshold::new(1, HashMap::new(), Vec::new()).unwrap(),
195+
Threshold::new(DEFAULT_TEST_THRESHOLD, HashMap::new(), Vec::new()).unwrap(),
174196
Rewards::ONE,
175197
)
176198
.unwrap();
177199
assert_eq!(rewards.len(), 0);
178200
}
179201

180202
#[proptest]
181-
fn test_small(snapshot: Snapshot) {
203+
fn test_active_and_inactive_voters(raw_snapshot: RawSnapshot) {
204+
let snapshot = Snapshot::from_raw_snapshot(
205+
raw_snapshot,
206+
DEFAULT_SNAPSHOT_THRESHOLD.into(),
207+
Fraction::from(1),
208+
&|_vk: &Identifier| String::new(),
209+
)
210+
.unwrap();
211+
182212
let voting_keys = snapshot.voting_keys().collect::<Vec<_>>();
183213

184214
let votes_count = voting_keys
@@ -188,54 +218,59 @@ mod tests {
188218
(
189219
key.to_owned(),
190220
if i % 2 == 0 {
221+
// generating a random set of half active & half inactive votes
191222
HashSet::from([Hash::from([0u8; 32])])
192223
} else {
193224
HashSet::new()
194225
},
195226
)
196227
})
197228
.collect::<VoteCount>();
198-
let n_voters = votes_count
229+
230+
let number_of_active_voters = votes_count
199231
.iter()
200232
.filter(|(_, votes)| !votes.is_empty())
201233
.count();
234+
202235
let voters = snapshot.to_full_snapshot_info();
203-
let voters_active = voters
236+
237+
let active_voters = voters
204238
.clone()
205239
.into_iter()
206240
.enumerate()
207241
.filter(|(i, _utxo)| i % 2 == 0)
208242
.map(|(_, utxo)| utxo)
209243
.collect::<Vec<_>>();
210244

211-
let mut rewards = calc_voter_rewards(
245+
let mut all_rewards = calc_voter_rewards(
212246
votes_count.clone(),
213247
voters,
214248
Threshold::new(1, HashMap::new(), Vec::new()).unwrap(),
215249
Rewards::ONE,
216250
)
217251
.unwrap();
252+
218253
let rewards_no_inactive = calc_voter_rewards(
219254
votes_count,
220-
voters_active,
221-
Threshold::new(1, HashMap::new(), Vec::new()).unwrap(),
255+
active_voters,
256+
Threshold::new(DEFAULT_TEST_THRESHOLD, HashMap::new(), Vec::new()).unwrap(),
222257
Rewards::ONE,
223258
)
224259
.unwrap();
225260
// Rewards should ignore inactive voters
226-
assert_eq!(rewards, rewards_no_inactive);
227-
if n_voters > 0 {
228-
assert_are_close(rewards.values().sum::<Rewards>(), Rewards::ONE);
261+
assert_eq!(all_rewards, rewards_no_inactive);
262+
if number_of_active_voters > 0 {
263+
assert_are_close(all_rewards.values().sum::<Rewards>(), Rewards::ONE);
229264
} else {
230-
assert_eq!(rewards.len(), 0);
265+
assert_eq!(all_rewards.len(), 0);
231266
}
232267

233-
let (active, inactive): (Vec<_>, Vec<_>) = voting_keys
268+
let (active_voters_keys, inactive_voters_keys): (Vec<_>, Vec<_>) = voting_keys
234269
.into_iter()
235270
.enumerate()
236271
.partition(|(i, _vk)| i % 2 == 0);
237272

238-
let active_reward_addresses = active
273+
let active_reward_addresses = active_voters_keys
239274
.into_iter()
240275
.flat_map(|(_, vk)| {
241276
snapshot
@@ -247,27 +282,27 @@ mod tests {
247282

248283
assert!(active_reward_addresses
249284
.iter()
250-
.all(|addr| rewards.remove(addr).unwrap() > Rewards::ZERO));
285+
.all(|addr| all_rewards.remove(addr).unwrap() > Rewards::ZERO));
251286

252-
// partial test: does not check that rewards for addresses that delegated to both
253-
// active and inactive voters only come from active ones
254-
for (_, vk) in inactive {
255-
for contrib in snapshot.contributions_for_voting_key(vk.clone()) {
256-
assert!(rewards.get(&contrib.reward_address).is_none());
287+
for (_, voting_key) in inactive_voters_keys {
288+
for contrib in snapshot.contributions_for_voting_key(voting_key.clone()) {
289+
assert!(all_rewards.get(&contrib.reward_address).is_none());
257290
}
258291
}
259292
}
260293

261294
#[test]
262295
fn test_mapping() {
263296
let mut raw_snapshot = Vec::new();
264-
let voting_pub_key = Identifier::from_hex(&hex::encode([0; 32])).unwrap();
297+
let voting_public_key = Identifier::from_hex(&hex::encode([0; 32])).unwrap();
265298

266299
let mut total_stake = 0u64;
300+
267301
for i in 1..10u64 {
268302
let stake_public_key = i.to_string();
269303
let reward_address = i.to_string();
270-
let delegations = Delegations::New(vec![(voting_pub_key.clone(), 1)]);
304+
305+
let delegations = Delegations::New(vec![(voting_public_key.clone(), 1)]);
271306
raw_snapshot.push(VotingRegistration {
272307
stake_public_key,
273308
voting_power: i.into(),
@@ -282,7 +317,7 @@ mod tests {
282317
raw_snapshot.into(),
283318
0.into(),
284319
Fraction::from(1u64),
285-
&|_vk: &Identifier| String::new(),
320+
&|_voting_key: &Identifier| String::new(),
286321
)
287322
.unwrap();
288323

@@ -295,11 +330,13 @@ mod tests {
295330
Rewards::ONE,
296331
)
297332
.unwrap();
333+
298334
assert_eq!(rewards.values().sum::<Rewards>(), Rewards::ONE);
299-
for (addr, reward) in rewards {
335+
336+
for (mainnet_addresses, reward) in rewards {
300337
assert_eq!(
301338
reward,
302-
addr.parse::<Rewards>().unwrap() / Rewards::from(total_stake)
339+
mainnet_addresses.parse::<Rewards>().unwrap() / Rewards::from(total_stake)
303340
);
304341
}
305342
}
@@ -309,10 +346,10 @@ mod tests {
309346
let mut raw_snapshot = Vec::new();
310347

311348
for i in 1..10u64 {
312-
let voting_pub_key = Identifier::from_hex(&hex::encode([i as u8; 32])).unwrap();
349+
let voting_public_key = Identifier::from_hex(&hex::encode([i as u8; 32])).unwrap();
313350
let stake_public_key = i.to_string();
314351
let reward_address = i.to_string();
315-
let delegations = Delegations::New(vec![(voting_pub_key.clone(), 1)]);
352+
let delegations = Delegations::New(vec![(voting_public_key.clone(), 1)]);
316353
raw_snapshot.push(VotingRegistration {
317354
stake_public_key,
318355
voting_power: i.into(),
@@ -346,7 +383,15 @@ mod tests {
346383
}
347384

348385
#[proptest]
349-
fn test_per_category_threshold(snapshot: Snapshot) {
386+
fn test_per_category_threshold(raw_snapshot: RawSnapshot) {
387+
let snapshot = Snapshot::from_raw_snapshot(
388+
raw_snapshot,
389+
DEFAULT_SNAPSHOT_THRESHOLD.into(),
390+
Fraction::from(1),
391+
&|_vk: &Identifier| String::new(),
392+
)
393+
.unwrap();
394+
350395
use vit_servicing_station_tests::common::data::ArbitrarySnapshotGenerator;
351396

352397
let voters = snapshot.to_full_snapshot_info();
@@ -401,15 +446,20 @@ mod tests {
401446
let rewards = calc_voter_rewards(
402447
votes_count,
403448
voters.clone(),
404-
Threshold::new(1, per_challenge_threshold.clone(), proposals.clone()).unwrap(),
449+
Threshold::new(
450+
DEFAULT_TEST_THRESHOLD,
451+
per_challenge_threshold.clone(),
452+
proposals.clone(),
453+
)
454+
.unwrap(),
405455
Rewards::ONE,
406456
)
407457
.unwrap();
408458

409459
let rewards_only_active = calc_voter_rewards(
410460
only_active,
411461
voters,
412-
Threshold::new(1, per_challenge_threshold, proposals).unwrap(),
462+
Threshold::new(DEFAULT_TEST_THRESHOLD, per_challenge_threshold, proposals).unwrap(),
413463
Rewards::ONE,
414464
)
415465
.unwrap();

snapshot-lib/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub use fraction::Fraction;
22
use jormungandr_lib::{crypto::account::Identifier, interfaces::Value};
3+
use proptest::prelude::Arbitrary;
34
use registration::{Delegations, MainnetRewardAddress, VotingRegistration};
45
use serde::{Deserialize, Serialize};
56
use std::{borrow::Borrow, collections::BTreeMap, iter::Iterator, num::NonZeroU64};

0 commit comments

Comments
 (0)