Skip to content

Commit

Permalink
Merge pull request #917 from dusk-network/907-make-sortition-hash-com…
Browse files Browse the repository at this point in the history
…pliant-with-specification

Make Sortition Hash compliant with specification
  • Loading branch information
fed-franz authored Aug 16, 2023
2 parents b3e849d + 54c3aa4 commit 6a0b472
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 60 deletions.
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

0 comments on commit 6a0b472

Please sign in to comment.