1
0
mirror of synced 2025-02-03 03:14:43 +00:00

Finish Committee wrapper (#251)

* Committee type wrapper

---------

Co-authored-by: danielsanchezq <sanchez.quiros.daniel@gmail.com>
This commit is contained in:
Al Liu 2023-07-07 16:08:19 +08:00 committed by GitHub
parent 95bfd24f6d
commit a0cb738b9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 131 additions and 20 deletions

View File

@ -7,6 +7,7 @@ edition = "2021"
serde = { version = "1.0", features = ["derive"], optional = true }
blake2 = "0.10"
bls-signatures = "0.14"
digest = "0.10"
integer-encoding = "3"
sha2 = "0.10"
rand = "0.8"

View File

@ -1,16 +1,5 @@
use crate::{Committee, CommitteeId, NodeId};
use blake2::{digest::typenum::U32, Blake2b, Digest};
use std::collections::{HashMap, HashSet};
fn blake2b_hash(committee: &Committee) -> CommitteeId {
let mut hasher = Blake2b::<U32>::new();
let mut tmp = committee.iter().collect::<Vec<_>>();
tmp.sort();
for member in tmp {
hasher.update(member);
}
CommitteeId::new(hasher.finalize().into())
}
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub(super) struct Tree {
@ -59,7 +48,6 @@ impl Tree {
nodes[n * committee_size..(n + 1) * committee_size]
.iter()
.cloned()
.map(From::from)
.collect()
})
.collect();
@ -73,7 +61,10 @@ impl Tree {
}
}
let hashes = committees.iter().map(blake2b_hash).collect::<Vec<_>>();
let hashes = committees
.iter()
.map(Committee::id::<blake2::Blake2b<digest::typenum::U32>>)
.collect::<Vec<_>>();
(hashes, committees.into_iter().enumerate().collect())
}
@ -88,8 +79,8 @@ impl Tree {
}
pub(super) fn parent_committee_from_member_id(&self, id: &NodeId) -> Committee {
let Some(committee_id) = self.committee_id_by_member_id(id) else { return HashSet::new(); };
let Some(parent_id) = self.parent_committee(committee_id) else { return HashSet::new(); };
let Some(committee_id) = self.committee_id_by_member_id(id) else { return Committee::new(); };
let Some(parent_id) = self.parent_committee(committee_id) else { return Committee::new(); };
self.committee_by_committee_idx(self.committee_id_to_index[parent_id])
.cloned()
.unwrap_or_default()

View File

@ -1,17 +1,15 @@
// std
use std::collections::HashSet;
use std::hash::Hash;
// crates
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
mod committee;
pub use committee::CommitteeId;
pub use committee::{Committee, CommitteeId};
pub type View = i64;
pub type NodeId = [u8; 32];
pub type BlockId = [u8; 32];
pub type Committee = HashSet<NodeId>;
/// The way the consensus engine communicates with the rest of the system is by returning
/// actions to be performed.

View File

@ -1,3 +1,7 @@
use std::collections::BTreeSet;
use crate::NodeId;
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CommitteeId(pub(crate) [u8; 32]);
@ -35,3 +39,118 @@ impl core::fmt::Display for CommitteeId {
Ok(())
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
#[repr(transparent)]
pub struct Committee {
members: BTreeSet<NodeId>,
}
impl Committee {
#[inline]
pub const fn new() -> Self {
Self {
members: BTreeSet::new(),
}
}
#[inline]
pub fn hash<D: digest::Digest>(
&self,
) -> digest::generic_array::GenericArray<u8, <D as digest::OutputSizeUser>::OutputSize> {
let mut hasher = D::new();
for member in &self.members {
hasher.update(member);
}
hasher.finalize()
}
#[inline]
pub fn contains(&self, node_id: &NodeId) -> bool {
self.members.contains(node_id)
}
#[inline]
pub fn insert(&mut self, node_id: NodeId) {
self.members.insert(node_id);
}
#[inline]
pub fn remove(&mut self, node_id: &NodeId) {
self.members.remove(node_id);
}
#[inline]
pub fn is_empty(&self) -> bool {
self.members.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.members.len()
}
#[inline]
pub fn extend<'a>(&mut self, other: impl IntoIterator<Item = &'a NodeId>) {
self.members.extend(other);
}
#[inline]
pub fn id<D: digest::Digest<OutputSize = digest::typenum::U32>>(&self) -> CommitteeId {
CommitteeId::new(self.hash::<D>().into())
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &NodeId> {
self.members.iter()
}
}
impl<'a, T> From<T> for Committee
where
T: Iterator<Item = &'a NodeId>,
{
fn from(members: T) -> Self {
Self {
members: members.into_iter().copied().collect(),
}
}
}
impl core::iter::FromIterator<[u8; 32]> for Committee {
fn from_iter<T: IntoIterator<Item = [u8; 32]>>(iter: T) -> Self {
Self {
members: iter.into_iter().collect(),
}
}
}
impl<'a> core::iter::FromIterator<&'a [u8; 32]> for Committee {
fn from_iter<T: IntoIterator<Item = &'a [u8; 32]>>(iter: T) -> Self {
Self {
members: iter.into_iter().copied().collect(),
}
}
}
impl core::iter::IntoIterator for Committee {
type Item = NodeId;
type IntoIter = std::collections::btree_set::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.members.into_iter()
}
}
impl<'a> core::iter::IntoIterator for &'a Committee {
type Item = &'a NodeId;
type IntoIter = std::collections::btree_set::Iter<'a, NodeId>;
fn into_iter(self) -> Self::IntoIter {
self.members.iter()
}
}

View File

@ -180,7 +180,7 @@ where
let fountain = F::new(fountain_settings);
let private_key = PrivateKey::new(private_key);
let self_committee = carnot.self_committee();
let leader_committee = [carnot.id()].into_iter().collect::<HashSet<_>>();
let leader_committee = [carnot.id()].into_iter().collect::<Committee>();
let tally_settings = CarnotTallySettings {
threshold: carnot.super_majority_threshold(),
participating_nodes: carnot.child_committees().into_iter().flatten().collect(),
@ -248,6 +248,7 @@ where
}
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
enum Output<Tx: Clone + Eq + Hash> {
Send(consensus_engine::Send),
BroadcastTimeoutQc { timeout_qc: TimeoutQc },

View File

@ -494,6 +494,7 @@ impl<L: UpdateableLeaderSelection, O: Overlay<LeaderSelection = L>> Node for Car
}
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
enum Output<Tx: Clone + Eq + Hash> {
Send(consensus_engine::Send),
BroadcastTimeoutQc {