Skip to content

Commit

Permalink
consensus: Update Majority and Supermajority definitions
Browse files Browse the repository at this point in the history
Remove the definition of the two constants as multipliers and
define majority and supermajority as functions.

This eliminates the risk of computing the supermajority of 2/3
with the `0.67` multiplier, which could yield a wrong result
of 2/3+1.
  • Loading branch information
fed-franz committed Aug 20, 2024
1 parent 64e58e2 commit 31de71c
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 30 deletions.
50 changes: 27 additions & 23 deletions consensus/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,10 @@ use std::time::Duration;
/// Maximum number of iterations Consensus runs per a single round.
pub const CONSENSUS_MAX_ITER: u8 = 50;

/// Percentage number that determines quorums.
pub const SUPERMAJORITY_THRESHOLD: f64 = 0.67;
pub const MAJORITY_THRESHOLD: f64 = 0.5;

/// Total credits of steps committees
pub const PROPOSAL_COMMITTEE_CREDITS: usize = 1;
pub const VALIDATION_COMMITTEE_CREDITS: usize = 64;
pub const VALIDATION_COMMITTEE_QUORUM: f64 =
VALIDATION_COMMITTEE_CREDITS as f64 * SUPERMAJORITY_THRESHOLD;

pub const RATIFICATION_COMMITTEE_CREDITS: usize = 64;
pub const RATIFICATION_COMMITTEE_QUORUM: f64 =
RATIFICATION_COMMITTEE_CREDITS as f64 * SUPERMAJORITY_THRESHOLD;

pub const DEFAULT_BLOCK_GAS_LIMIT: u64 = 5 * 1_000_000_000;

Expand All @@ -35,32 +26,45 @@ pub const MAX_STEP_TIMEOUT: Duration = Duration::from_secs(40);
pub const TIMEOUT_INCREASE: Duration = Duration::from_secs(2);
pub const MINIMUM_BLOCK_TIME: u64 = 10;

/// Returns delta between full quorum and super_majority
pub fn validation_extra() -> usize {
VALIDATION_COMMITTEE_CREDITS - validation_committee_quorum()
// Returns `floor(value/2) + 1`
pub fn majority(value: usize) -> usize {
value / 2 + 1
}

pub fn ratification_extra() -> usize {
RATIFICATION_COMMITTEE_CREDITS - ratification_committee_quorum()
// Returns `ceil( value/3*2 )`
pub fn supermajority(value: usize) -> usize {
let sm = value as f32 / 3.0 * 2.0;
sm.ceil() as usize
}

/// Returns the quorum of a Ratification committee
pub fn ratification_quorum() -> usize {
supermajority(RATIFICATION_COMMITTEE_CREDITS)
}

/// Returns ceil of RATIFICATION_COMMITTEE_QUORUM
pub fn ratification_committee_quorum() -> usize {
RATIFICATION_COMMITTEE_QUORUM.ceil() as usize
/// Returns the quorum of a Validation committee
pub fn validation_quorum() -> usize {
supermajority(VALIDATION_COMMITTEE_CREDITS)
}

/// Returns ceil of VALIDATION_COMMITTEE_QUORUM
pub fn validation_committee_quorum() -> usize {
VALIDATION_COMMITTEE_QUORUM.ceil() as usize
/// Returns the number of credits beyond the quorum for a Validation committee
pub fn validation_extra() -> usize {
VALIDATION_COMMITTEE_CREDITS - validation_quorum()
}

/// Returns the number of credits beyond the quorum for a Ratification committee
pub fn ratification_extra() -> usize {
RATIFICATION_COMMITTEE_CREDITS - ratification_quorum()
}

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_quorum_consts() {
assert_eq!(validation_committee_quorum(), 43);
assert_eq!(ratification_committee_quorum(), 43);
fn test_quorums() {
assert_eq!(majority(VALIDATION_COMMITTEE_CREDITS), 33);
assert_eq!(validation_quorum(), 43);
assert_eq!(ratification_quorum(), 43);
assert_eq!(validation_extra(), 21);
assert_eq!(ratification_extra(), 21);
}
Expand Down
11 changes: 4 additions & 7 deletions consensus/src/user/committee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::user::provisioners::Provisioners;
use crate::user::sortition;

use super::cluster::Cluster;
use crate::config;
use crate::config::{majority, supermajority};
use node_data::bls::{PublicKey, PublicKeyBytes};
use std::collections::{BTreeMap, HashMap};
use std::fmt;
Expand Down Expand Up @@ -36,13 +36,10 @@ impl Committee {
pub fn new(provisioners: &Provisioners, cfg: &sortition::Config) -> Self {
// Generate committee using deterministic sortition.
let extracted = provisioners.create_committee(cfg);
let committee_credits = cfg.committee_credits() as f64;
let committee_credits = cfg.committee_credits();

let super_majority = (committee_credits
* config::SUPERMAJORITY_THRESHOLD)
.ceil() as usize;
let majority =
(committee_credits * config::MAJORITY_THRESHOLD) as usize + 1;
let majority = majority(committee_credits);
let super_majority = supermajority(committee_credits);

// Turn the raw vector into a hashmap where we map a pubkey to its
// occurrences.
Expand Down

0 comments on commit 31de71c

Please sign in to comment.