Finish Committee
wrapper (#251)
* Committee type wrapper --------- Co-authored-by: danielsanchezq <sanchez.quiros.daniel@gmail.com>
This commit is contained in:
parent
95bfd24f6d
commit
a0cb738b9f
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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.
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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 },
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user