Skip to content

Commit

Permalink
Add epoch to threshold functions to allow dynamically sized committees
Browse files Browse the repository at this point in the history
  • Loading branch information
pls148 committed Nov 21, 2024
1 parent ecb5b00 commit 6533334
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 33 deletions.
6 changes: 3 additions & 3 deletions crates/hotshot/src/traits/election/randomized_committee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,17 +163,17 @@ impl<TYPES: NodeType> Membership<TYPES> for RandomizedCommittee<TYPES> {
}

/// Get the voting success threshold for the committee
fn success_threshold(&self) -> NonZeroU64 {
fn success_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(((self.stake_table.len() as u64 * 2) / 3) + 1).unwrap()
}

/// Get the voting failure threshold for the committee
fn failure_threshold(&self) -> NonZeroU64 {
fn failure_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(((self.stake_table.len() as u64) / 3) + 1).unwrap()
}

/// Get the voting upgrade threshold for the committee
fn upgrade_threshold(&self) -> NonZeroU64 {
fn upgrade_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(max(
(self.stake_table.len() as u64 * 9) / 10,
((self.stake_table.len() as u64 * 2) / 3) + 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use std::{
num::NonZeroU64,
};

use ethereum_types::U256;
use hotshot_types::{
traits::{
election::Membership,
Expand All @@ -21,6 +20,7 @@ use hotshot_types::{
},
PeerConfig,
};
use primitive_types::U256;
use rand::{rngs::StdRng, Rng};
use utils::anytrace::Result;

Expand Down Expand Up @@ -231,20 +231,20 @@ impl<TYPES: NodeType, CONFIG: QuorumFilterConfig> Membership<TYPES>
}

/// Get the voting success threshold for the committee
fn success_threshold(&self) -> NonZeroU64 {
let len = self.stake_table.len() / 2; // Divide by two as we are flipping between odds and evens
fn success_threshold(&self, epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
let len = self.total_nodes(epoch);
NonZeroU64::new(((len as u64 * 2) / 3) + 1).unwrap()
}

/// Get the voting failure threshold for the committee
fn failure_threshold(&self) -> NonZeroU64 {
let len = self.stake_table.len() / 2; // Divide by two as we are flipping between odds and evens
fn failure_threshold(&self, epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
let len = self.total_nodes(epoch);
NonZeroU64::new(((len as u64) / 3) + 1).unwrap()
}

/// Get the voting upgrade threshold for the committee
fn upgrade_threshold(&self) -> NonZeroU64 {
let len = self.stake_table.len() / 2; // Divide by two as we are flipping between odds and evens
fn upgrade_threshold(&self, epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
let len = self.total_nodes(epoch);
NonZeroU64::new(max((len as u64 * 9) / 10, ((len as u64 * 2) / 3) + 1)).unwrap()
}
}
6 changes: 3 additions & 3 deletions crates/hotshot/src/traits/election/static_committee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,17 @@ impl<TYPES: NodeType> Membership<TYPES> for StaticCommittee<TYPES> {
}

/// Get the voting success threshold for the committee
fn success_threshold(&self) -> NonZeroU64 {
fn success_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(((self.stake_table.len() as u64 * 2) / 3) + 1).unwrap()
}

/// Get the voting failure threshold for the committee
fn failure_threshold(&self) -> NonZeroU64 {
fn failure_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(((self.stake_table.len() as u64) / 3) + 1).unwrap()
}

/// Get the voting upgrade threshold for the committee
fn upgrade_threshold(&self) -> NonZeroU64 {
fn upgrade_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(max(
(self.stake_table.len() as u64 * 9) / 10,
((self.stake_table.len() as u64 * 2) / 3) + 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,17 @@ impl<TYPES: NodeType> Membership<TYPES> for StaticCommitteeLeaderForTwoViews<TYP
}

/// Get the voting success threshold for the committee
fn success_threshold(&self) -> NonZeroU64 {
fn success_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(((self.stake_table.len() as u64 * 2) / 3) + 1).unwrap()
}

/// Get the voting failure threshold for the committee
fn failure_threshold(&self) -> NonZeroU64 {
fn failure_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(((self.stake_table.len() as u64) / 3) + 1).unwrap()
}

/// Get the voting upgrade threshold for the committee
fn upgrade_threshold(&self) -> NonZeroU64 {
fn upgrade_threshold(&self, _epoch: <TYPES as NodeType>::Epoch) -> NonZeroU64 {
NonZeroU64::new(((self.stake_table.len() as u64 * 9) / 10) + 1).unwrap()
}
}
2 changes: 1 addition & 1 deletion crates/testing/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ pub async fn build_assembled_sig<
let real_qc_pp: <TYPES::SignatureKey as SignatureKey>::QcParams =
<TYPES::SignatureKey as SignatureKey>::public_parameter(
stake_table.clone(),
U256::from(CERT::threshold(membership)),
U256::from(CERT::threshold(membership, epoch)),
);
let total_nodes = stake_table.len();
let signers = bitvec![1; total_nodes];
Expand Down
35 changes: 25 additions & 10 deletions crates/types/src/simple_certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,22 @@ use crate::{
/// Trait which allows use to inject different threshold calculations into a Certificate type
pub trait Threshold<TYPES: NodeType> {
/// Calculate a threshold based on the membership
fn threshold<MEMBERSHIP: Membership<TYPES>>(membership: &MEMBERSHIP) -> u64;
fn threshold<MEMBERSHIP: Membership<TYPES>>(
membership: &MEMBERSHIP,
epoch: <TYPES as NodeType>::Epoch,
) -> u64;
}

/// Defines a threshold which is 2f + 1 (Amount needed for Quorum)
#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
pub struct SuccessThreshold {}

impl<TYPES: NodeType> Threshold<TYPES> for SuccessThreshold {
fn threshold<MEMBERSHIP: Membership<TYPES>>(membership: &MEMBERSHIP) -> u64 {
membership.success_threshold().into()
fn threshold<MEMBERSHIP: Membership<TYPES>>(
membership: &MEMBERSHIP,
epoch: <TYPES as NodeType>::Epoch,
) -> u64 {
membership.success_threshold(epoch).into()
}
}

Expand All @@ -55,8 +61,11 @@ impl<TYPES: NodeType> Threshold<TYPES> for SuccessThreshold {
pub struct OneHonestThreshold {}

impl<TYPES: NodeType> Threshold<TYPES> for OneHonestThreshold {
fn threshold<MEMBERSHIP: Membership<TYPES>>(membership: &MEMBERSHIP) -> u64 {
membership.failure_threshold().into()
fn threshold<MEMBERSHIP: Membership<TYPES>>(
membership: &MEMBERSHIP,
epoch: <TYPES as NodeType>::Epoch,
) -> u64 {
membership.failure_threshold(epoch).into()
}
}

Expand All @@ -65,8 +74,11 @@ impl<TYPES: NodeType> Threshold<TYPES> for OneHonestThreshold {
pub struct UpgradeThreshold {}

impl<TYPES: NodeType> Threshold<TYPES> for UpgradeThreshold {
fn threshold<MEMBERSHIP: Membership<TYPES>>(membership: &MEMBERSHIP) -> u64 {
membership.upgrade_threshold().into()
fn threshold<MEMBERSHIP: Membership<TYPES>>(
membership: &MEMBERSHIP,
epoch: <TYPES as NodeType>::Epoch,
) -> u64 {
membership.upgrade_threshold(epoch).into()
}
}

Expand Down Expand Up @@ -156,7 +168,7 @@ impl<TYPES: NodeType, VOTEABLE: Voteable + 'static, THRESHOLD: Threshold<TYPES>>
}
let real_qc_pp = <TYPES::SignatureKey as SignatureKey>::public_parameter(
membership.stake_table(epoch),
U256::from(Self::threshold(membership)),
U256::from(Self::threshold(membership, epoch)),
);
let Ok(commit) = self.data_commitment(upgrade_lock).await else {
return false;
Expand All @@ -167,8 +179,11 @@ impl<TYPES: NodeType, VOTEABLE: Voteable + 'static, THRESHOLD: Threshold<TYPES>>
self.signatures.as_ref().unwrap(),
)
}
fn threshold<MEMBERSHIP: Membership<TYPES>>(membership: &MEMBERSHIP) -> u64 {
THRESHOLD::threshold(membership)
fn threshold<MEMBERSHIP: Membership<TYPES>>(
membership: &MEMBERSHIP,
epoch: <TYPES as NodeType>::Epoch,
) -> u64 {
THRESHOLD::threshold(membership, epoch)
}
fn data(&self) -> &Self::Voteable {
&self.data
Expand Down
6 changes: 3 additions & 3 deletions crates/types/src/traits/election.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ pub trait Membership<TYPES: NodeType>: Clone + Debug + Send + Sync {
fn total_nodes(&self, epoch: TYPES::Epoch) -> usize;

/// Returns the threshold for a specific `Membership` implementation
fn success_threshold(&self) -> NonZeroU64;
fn success_threshold(&self, epoch: TYPES::Epoch) -> NonZeroU64;

/// Returns the threshold for a specific `Membership` implementation
fn failure_threshold(&self) -> NonZeroU64;
fn failure_threshold(&self, epoch: TYPES::Epoch) -> NonZeroU64;

/// Returns the threshold required to upgrade the network protocol
fn upgrade_threshold(&self) -> NonZeroU64;
fn upgrade_threshold(&self, epoch: TYPES::Epoch) -> NonZeroU64;
}
9 changes: 6 additions & 3 deletions crates/types/src/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ pub trait Certificate<TYPES: NodeType>: HasViewNumber<TYPES> {
) -> impl std::future::Future<Output = bool>;
/// Returns the amount of stake needed to create this certificate
// TODO: Make this a static ratio of the total stake of `Membership`
fn threshold<MEMBERSHIP: Membership<TYPES>>(membership: &MEMBERSHIP) -> u64;
fn threshold<MEMBERSHIP: Membership<TYPES>>(
membership: &MEMBERSHIP,
epoch: <TYPES as NodeType>::Epoch,
) -> u64;
/// Get the commitment which was voted on
fn data(&self) -> &Self::Voteable;
/// Get the vote commitment which the votes commit to
Expand Down Expand Up @@ -199,12 +202,12 @@ impl<
*total_stake_casted += stake_table_entry.stake();
total_vote_map.insert(key, (vote.signature(), vote_commitment));

if *total_stake_casted >= CERT::threshold(membership).into() {
if *total_stake_casted >= CERT::threshold(membership, epoch).into() {
// Assemble QC
let real_qc_pp: <<TYPES as NodeType>::SignatureKey as SignatureKey>::QcParams =
<TYPES::SignatureKey as SignatureKey>::public_parameter(
stake_table,
U256::from(CERT::threshold(membership)),
U256::from(CERT::threshold(membership, epoch)),
);

let real_qc_sig = <TYPES::SignatureKey as SignatureKey>::assemble(
Expand Down

0 comments on commit 6533334

Please sign in to comment.