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

Make Sortition Hash compliant with specification #917

Merged
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
87 changes: 36 additions & 51 deletions consensus/src/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,60 +220,45 @@ mod tests {

let mut a = Aggregator::default();

// Ensure total value for this block_hash is increased with 2 on a vote
// from a provisioner at pos 1.
let (signature, h) = input.get(1).expect("invalid index");
assert!(a.collect_vote(&c, h, signature).is_none());
dbg!("{:?}", p);

// this provisioner vote has weight of 2
assert_eq!(a.get_total(block_hash), Some(2));

// Ensure total value for this block_hash is increased with 1 on a vote
// from a provisioner at pos 0.
let (signature, h) = input.get(0).expect("invalid index");
assert!(a.collect_vote(&c, h, signature).is_none());

// this provisioner vote has weight of 1
assert_eq!(a.get_total(block_hash), Some(3));

// Ensure total value for this block_hash is increased with 1 on a vote
// from a provisioner at pos 5.
let (signature, h) = input.get(5).expect("invalid index");
assert!(a.collect_vote(&c, h, signature).is_none());

// this provisioner has weight of 1. Total should be sum of weights of
// all prior votes.
assert_eq!(a.get_total(block_hash), Some(4));

// Ensure a duplicated vote is discarded
let (signature, h) = input.get(5).expect("invalid index");
assert!(a.collect_vote(&c, h, signature).is_none());
assert_eq!(a.get_total(block_hash), Some(4));

let (signature, h) = input.get(6).expect("invalid index");
assert!(a.collect_vote(&c, h, signature).is_none());
// this provisioner vote has weight of 0.

assert_eq!(a.get_total(block_hash), Some(4));

let (signature, h) = input.get(8).expect("invalid index");
assert!(a.collect_vote(&c, h, signature).is_none());
// this provisioner vote has weight of 0. Quorum threshold still not
// reached
assert_eq!(a.get_total(block_hash), Some(4));

let (signature, h) = input.get(9).expect("invalid index");
let (hash, sv) = a
.collect_vote(&c, h, signature)
.expect("failed to reach quorum");
// Collect votes from expected committee members
let expected_members = vec![0, 1, 2, 4, 5];
let expected_votes = vec![1, 1, 2, 1, 3];
let mut collected_votes = 0;
for i in 0..expected_members.len() - 1 {
// Select provisioner
let (signature, h) =
input.get(expected_members[i]).expect("invalid index");

// Last member's vote should reach the quorum
if i == expected_members.len() - 1 {
// (hash, sv) is only returned in case we reach the quorum
let (hash, sv) = a
.collect_vote(&c, h, signature)
.expect("failed to reach quorum");

// Check expected block hash
assert_eq!(hash, block_hash);

// Check expected StepVotes bitset
// bitset: 0b00000000000000000000000000000000000000000000000000000000011111
println!("bitset: {:#064b}", sv.bitset);
assert_eq!(sv.bitset, 31);

break;
}

assert_eq!(hash, block_hash);
// this provisioner vote has weight of 3. Quorum reached
assert!(a.get_total(block_hash).unwrap() >= c.quorum());
// Check collected votes
assert!(a.collect_vote(&c, h, signature).is_none());
collected_votes += expected_votes[i];
assert_eq!(a.get_total(block_hash), Some(collected_votes));

// bitset: 0b00000000000000000000000000000000000000000000000000000000100111
println!("bitset: {:#064b}", sv.bitset);
assert_eq!(sv.bitset, 39);
// Ensure a duplicated vote is discarded
if i == 0 {
assert!(a.collect_vote(&c, h, signature).is_none());
assert_eq!(a.get_total(block_hash), Some(collected_votes));
}
}
}
}
17 changes: 10 additions & 7 deletions consensus/src/user/sortition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ pub fn create_sortition_hash(cfg: &Config, counter: u32) -> [u8; 32] {
let mut hasher = Sha3_256::new();

// write input message
hasher.update(&cfg.seed.inner()[..]);
hasher.update(cfg.round.to_le_bytes());
hasher.update(counter.to_le_bytes());
hasher.update(cfg.step.to_le_bytes());
hasher.update(&cfg.seed.inner()[..]);
hasher.update(counter.to_le_bytes());

// read hash digest
let reader = hasher.finalize();
Expand Down Expand Up @@ -78,10 +78,11 @@ mod tests {
#[test]
pub fn test_sortition_hash() {
let hash = [
56, 81, 125, 39, 109, 105, 243, 20, 138, 196, 236, 197, 7, 155, 41,
26, 217, 150, 9, 226, 76, 174, 67, 1, 230, 187, 81, 107, 192, 5,
13, 73,
134, 22, 162, 136, 186, 35, 16, 207, 237, 50, 11, 236, 74, 189, 37,
137, 101, 205, 53, 161, 248, 199, 195, 228, 68, 68, 95, 223, 239,
199, 1, 7,
];

assert_eq!(
create_sortition_hash(
&Config::new(Seed::from([3; 48]), 10, 3, 0),
Expand All @@ -93,8 +94,10 @@ mod tests {

#[test]
pub fn test_generate_sortition_score() {
let dataset =
vec![([3; 48], 123342342, 78899961), ([4; 48], 44443333, 5505832)];
let dataset = vec![
([3; 48], 123342342, 66422677),
([4; 48], 44443333, 22757716),
];

for (seed, total_weight, expected_score) in dataset {
let hash = create_sortition_hash(
Expand Down
7 changes: 5 additions & 2 deletions consensus/tests/sortition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ fn test_deterministic_sortition_1() {

let committee = Committee::new(PublicKey::default(), &mut p, cfg);

// Verify expected committee size
assert_eq!(
committee_size,
committee.get_occurrences().iter().sum::<usize>()
);
assert_eq!(vec![7, 23, 13, 21], committee.get_occurrences());

// Verify expected distribution
assert_eq!(vec![7, 32, 7, 18], committee.get_occurrences());
}

#[test]
Expand All @@ -45,7 +48,7 @@ fn test_deterministic_sortition_2() {
committee_size,
committee.get_occurrences().iter().sum::<usize>()
);
assert_eq!(vec![5, 13, 14, 13], committee.get_occurrences());
assert_eq!(vec![7, 15, 10, 13], committee.get_occurrences());
}

#[test]
Expand Down