mirror of https://github.com/poanetwork/hbbft.git
Separate ValidatorMap from NetworkInfo.
This commit is contained in:
parent
9488d3f936
commit
838b92ab8d
|
@ -270,7 +270,7 @@ impl<NodeUid: Clone + Debug + Ord> Agreement<NodeUid> {
|
|||
session_id: u64,
|
||||
proposer_id: NodeUid,
|
||||
) -> AgreementResult<Self> {
|
||||
let invocation_id = netinfo.invocation_id();
|
||||
let invocation_id = netinfo.validator_map().invocation_id();
|
||||
if let Some(proposer_i) = netinfo.node_index(&proposer_id) {
|
||||
Ok(Agreement {
|
||||
netinfo: netinfo.clone(),
|
||||
|
@ -668,7 +668,7 @@ impl<NodeUid: Clone + Debug + Ord> Agreement<NodeUid> {
|
|||
self.conf_round = false;
|
||||
self.epoch += 1;
|
||||
let nonce = Nonce::new(
|
||||
self.netinfo.invocation_id().as_ref(),
|
||||
self.netinfo.validator_map().invocation_id().as_ref(),
|
||||
self.session_id,
|
||||
self.netinfo.node_index(&self.proposer_id).unwrap(),
|
||||
self.epoch,
|
||||
|
|
|
@ -5,8 +5,7 @@ use rand::Rand;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{ChangeState, JoinPlan};
|
||||
use crypto::{PublicKey, PublicKeySet};
|
||||
use messaging::NetworkInfo;
|
||||
use messaging::{NetworkInfo, ValidatorMap};
|
||||
|
||||
/// A batch of transactions the algorithm has output.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
|
@ -19,7 +18,7 @@ pub struct Batch<C, NodeUid> {
|
|||
/// this epoch.
|
||||
change: ChangeState<NodeUid>,
|
||||
/// The public network info, if `change` is not `None`.
|
||||
pub_netinfo: Option<(PublicKeySet, BTreeMap<NodeUid, PublicKey>)>,
|
||||
validator_map: Option<ValidatorMap<NodeUid>>,
|
||||
}
|
||||
|
||||
impl<C, NodeUid: Ord + Rand + Clone + Debug> Batch<C, NodeUid> {
|
||||
|
@ -29,7 +28,7 @@ impl<C, NodeUid: Ord + Rand + Clone + Debug> Batch<C, NodeUid> {
|
|||
epoch,
|
||||
contributions: BTreeMap::new(),
|
||||
change: ChangeState::None,
|
||||
pub_netinfo: None,
|
||||
validator_map: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,14 +87,11 @@ impl<C, NodeUid: Ord + Rand + Clone + Debug> Batch<C, NodeUid> {
|
|||
where
|
||||
NodeUid: Serialize + for<'r> Deserialize<'r>,
|
||||
{
|
||||
self.pub_netinfo
|
||||
.as_ref()
|
||||
.map(|&(ref pub_key_set, ref pub_keys)| JoinPlan {
|
||||
epoch: self.epoch + 1,
|
||||
change: self.change.clone(),
|
||||
pub_key_set: pub_key_set.clone(),
|
||||
pub_keys: pub_keys.clone(),
|
||||
})
|
||||
self.validator_map.as_ref().map(|validator_map| JoinPlan {
|
||||
epoch: self.epoch + 1,
|
||||
change: self.change.clone(),
|
||||
validator_map: validator_map.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the current change state, and if it is not `None`, inserts the network information so
|
||||
|
@ -107,10 +103,7 @@ impl<C, NodeUid: Ord + Rand + Clone + Debug> Batch<C, NodeUid> {
|
|||
) {
|
||||
self.change = change;
|
||||
if self.change != ChangeState::None {
|
||||
self.pub_netinfo = Some((
|
||||
netinfo.public_key_set().clone(),
|
||||
netinfo.public_key_map().clone(),
|
||||
));
|
||||
self.validator_map = Some(netinfo.validator_map().clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,12 +65,10 @@ where
|
|||
secret_key: SecretKey,
|
||||
join_plan: JoinPlan<NodeUid>,
|
||||
) -> Self {
|
||||
let netinfo = NetworkInfo::new(
|
||||
let netinfo = join_plan.validator_map.into_network_info(
|
||||
our_uid,
|
||||
SecretKeyShare::default(), // TODO: Should be an option?
|
||||
join_plan.pub_key_set,
|
||||
SecretKeyShare::default(),
|
||||
secret_key,
|
||||
join_plan.pub_keys,
|
||||
);
|
||||
DynamicHoneyBadgerBuilder {
|
||||
netinfo,
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
//! majority before that happens, key generation resets again, and is attempted for the new change.
|
||||
|
||||
use rand::Rand;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::mem;
|
||||
|
@ -66,10 +66,10 @@ use bincode;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use self::votes::{SignedVote, VoteCounter};
|
||||
use crypto::{PublicKey, PublicKeySet, SecretKey, Signature};
|
||||
use crypto::{SecretKey, Signature};
|
||||
use fault_log::{FaultKind, FaultLog};
|
||||
use honey_badger::{HoneyBadger, HoneyBadgerStep, Message as HbMessage};
|
||||
use messaging::{DistAlgorithm, NetworkInfo, Step, Target, TargetedMessage};
|
||||
use messaging::{DistAlgorithm, NetworkInfo, Step, Target, TargetedMessage, ValidatorMap};
|
||||
use sync_key_gen::{Ack, Part, PartOutcome, SyncKeyGen};
|
||||
|
||||
pub use self::batch::Batch;
|
||||
|
@ -350,7 +350,7 @@ where
|
|||
}
|
||||
debug!("{:?} Restarting DKG for {:?}.", self.our_id(), change);
|
||||
// Use the existing key shares - with the change applied - as keys for DKG.
|
||||
let mut pub_keys = self.netinfo.public_key_map().clone();
|
||||
let mut pub_keys = self.netinfo.validator_map().public_key_map().clone();
|
||||
if match *change {
|
||||
Change::Remove(ref id) => pub_keys.remove(id).is_none(),
|
||||
Change::Add(ref id, ref pk) => pub_keys.insert(id.clone(), pk.clone()).is_some(),
|
||||
|
@ -544,13 +544,11 @@ where
|
|||
/// of voting and key generation after a specific epoch, so that the new node will be in sync if it
|
||||
/// joins in the next one.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct JoinPlan<NodeUid: Ord> {
|
||||
pub struct JoinPlan<NodeUid: Ord + Clone> {
|
||||
/// The first epoch the new node will observe.
|
||||
epoch: u64,
|
||||
/// The current change. If `InProgress`, key generation for it is beginning at `epoch`.
|
||||
change: ChangeState<NodeUid>,
|
||||
/// The current public key set for threshold cryptography.
|
||||
pub_key_set: PublicKeySet,
|
||||
/// The public keys of the nodes taking part in key generation.
|
||||
pub_keys: BTreeMap<NodeUid, PublicKey>,
|
||||
/// The network's current validators.
|
||||
validator_map: ValidatorMap<NodeUid>,
|
||||
}
|
||||
|
|
170
src/messaging.rs
170
src/messaging.rs
|
@ -1,3 +1,4 @@
|
|||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
@ -139,32 +140,34 @@ impl<'a, D: DistAlgorithm + 'a> Iterator for MessageIter<'a, D> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Common data shared between algorithms: the nodes' IDs and key shares.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NetworkInfo<NodeUid> {
|
||||
our_uid: NodeUid,
|
||||
/// Common data shared between algorithms: the validators' public IDs, key shares and public keys.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ValidatorMap<NodeUid> {
|
||||
num_nodes: usize,
|
||||
num_faulty: usize,
|
||||
is_validator: bool,
|
||||
// TODO: Should this be an option? It only makes sense for validators.
|
||||
secret_key_share: SecretKeyShare,
|
||||
secret_key: SecretKey,
|
||||
public_key_set: PublicKeySet,
|
||||
public_key_shares: BTreeMap<NodeUid, PublicKeyShare>,
|
||||
public_keys: BTreeMap<NodeUid, PublicKey>,
|
||||
node_indices: BTreeMap<NodeUid, usize>,
|
||||
}
|
||||
|
||||
impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
||||
pub fn new(
|
||||
our_uid: NodeUid,
|
||||
secret_key_share: SecretKeyShare,
|
||||
public_key_set: PublicKeySet,
|
||||
secret_key: SecretKey,
|
||||
public_keys: BTreeMap<NodeUid, PublicKey>,
|
||||
) -> Self {
|
||||
impl<NodeUid: Serialize + Ord> Serialize for ValidatorMap<NodeUid> {
|
||||
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||
(&self.public_key_set, &self.public_keys).serialize(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, NodeUid: Deserialize<'de> + Ord + Clone> Deserialize<'de> for ValidatorMap<NodeUid> {
|
||||
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||
let (public_key_set, public_keys) =
|
||||
<(PublicKeySet, BTreeMap<NodeUid, PublicKey>)>::deserialize(d)?;
|
||||
Ok(ValidatorMap::new(public_key_set, public_keys))
|
||||
}
|
||||
}
|
||||
|
||||
impl<NodeUid: Clone + Ord> ValidatorMap<NodeUid> {
|
||||
pub fn new(public_key_set: PublicKeySet, public_keys: BTreeMap<NodeUid, PublicKey>) -> Self {
|
||||
let num_nodes = public_keys.len();
|
||||
let is_validator = public_keys.contains_key(&our_uid);
|
||||
let node_indices: BTreeMap<NodeUid, usize> = public_keys
|
||||
.keys()
|
||||
.enumerate()
|
||||
|
@ -174,13 +177,9 @@ impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
|||
.iter()
|
||||
.map(|(id, idx)| (id.clone(), public_key_set.public_key_share(*idx as u64)))
|
||||
.collect();
|
||||
NetworkInfo {
|
||||
our_uid,
|
||||
ValidatorMap {
|
||||
num_nodes,
|
||||
num_faulty: (num_nodes - 1) / 3,
|
||||
is_validator,
|
||||
secret_key_share,
|
||||
secret_key,
|
||||
public_key_set,
|
||||
public_key_shares,
|
||||
node_indices,
|
||||
|
@ -188,9 +187,21 @@ impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The ID of the node the algorithm runs on.
|
||||
pub fn our_uid(&self) -> &NodeUid {
|
||||
&self.our_uid
|
||||
/// Returns a `NetworkInfo` with the specified secrets and ID.
|
||||
pub fn into_network_info(
|
||||
self,
|
||||
our_uid: NodeUid,
|
||||
secret_key_share: SecretKeyShare,
|
||||
secret_key: SecretKey,
|
||||
) -> NetworkInfo<NodeUid> {
|
||||
let is_validator = self.public_keys.contains_key(&our_uid);
|
||||
NetworkInfo {
|
||||
our_uid,
|
||||
is_validator,
|
||||
secret_key_share,
|
||||
secret_key,
|
||||
validator_map: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// ID of all nodes in the network.
|
||||
|
@ -209,16 +220,6 @@ impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
|||
self.num_faulty
|
||||
}
|
||||
|
||||
/// Returns our secret key share for threshold cryptography.
|
||||
pub fn secret_key_share(&self) -> &SecretKeyShare {
|
||||
&self.secret_key_share
|
||||
}
|
||||
|
||||
/// Returns our secret key for encryption and signing.
|
||||
pub fn secret_key(&self) -> &SecretKey {
|
||||
&self.secret_key
|
||||
}
|
||||
|
||||
/// Returns the public key set for threshold cryptography.
|
||||
pub fn public_key_set(&self) -> &PublicKeySet {
|
||||
&self.public_key_set
|
||||
|
@ -229,11 +230,6 @@ impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
|||
self.public_key_shares.get(id)
|
||||
}
|
||||
|
||||
/// Returns a map of all node IDs to their public key shares.
|
||||
pub fn public_key_share_map(&self) -> &BTreeMap<NodeUid, PublicKeyShare> {
|
||||
&self.public_key_shares
|
||||
}
|
||||
|
||||
/// Returns a map of all node IDs to their public keys.
|
||||
pub fn public_key(&self, id: &NodeUid) -> Option<&PublicKey> {
|
||||
self.public_keys.get(id)
|
||||
|
@ -259,6 +255,93 @@ impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
|||
self.public_key_set.public_key().to_bytes()
|
||||
}
|
||||
|
||||
/// Returns `true` if the given node takes part in the consensus itself. If not, it is only an
|
||||
/// observer.
|
||||
pub fn is_node_validator(&self, uid: &NodeUid) -> bool {
|
||||
self.public_keys.contains_key(uid)
|
||||
}
|
||||
}
|
||||
|
||||
/// Common data shared between algorithms: the nodes' IDs and key shares.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NetworkInfo<NodeUid> {
|
||||
our_uid: NodeUid,
|
||||
is_validator: bool,
|
||||
// TODO: Should this be an option? It only makes sense for validators.
|
||||
secret_key_share: SecretKeyShare,
|
||||
secret_key: SecretKey,
|
||||
validator_map: ValidatorMap<NodeUid>,
|
||||
}
|
||||
|
||||
impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
||||
pub fn new(
|
||||
our_uid: NodeUid,
|
||||
secret_key_share: SecretKeyShare,
|
||||
public_key_set: PublicKeySet,
|
||||
secret_key: SecretKey,
|
||||
public_keys: BTreeMap<NodeUid, PublicKey>,
|
||||
) -> Self {
|
||||
let is_validator = public_keys.contains_key(&our_uid);
|
||||
NetworkInfo {
|
||||
our_uid,
|
||||
is_validator,
|
||||
secret_key_share,
|
||||
secret_key,
|
||||
validator_map: ValidatorMap::new(public_key_set, public_keys),
|
||||
}
|
||||
}
|
||||
|
||||
/// The ID of the node the algorithm runs on.
|
||||
pub fn our_uid(&self) -> &NodeUid {
|
||||
&self.our_uid
|
||||
}
|
||||
|
||||
/// ID of all nodes in the network.
|
||||
pub fn all_uids(&self) -> impl Iterator<Item = &NodeUid> {
|
||||
self.validator_map.all_uids()
|
||||
}
|
||||
|
||||
/// The total number of nodes.
|
||||
pub fn num_nodes(&self) -> usize {
|
||||
self.validator_map.num_nodes()
|
||||
}
|
||||
|
||||
/// The maximum number of faulty, Byzantine nodes up to which Honey Badger is guaranteed to be
|
||||
/// correct.
|
||||
pub fn num_faulty(&self) -> usize {
|
||||
self.validator_map.num_faulty()
|
||||
}
|
||||
|
||||
/// Returns our secret key share for threshold cryptography.
|
||||
pub fn secret_key_share(&self) -> &SecretKeyShare {
|
||||
&self.secret_key_share
|
||||
}
|
||||
|
||||
/// Returns our secret key for encryption and signing.
|
||||
pub fn secret_key(&self) -> &SecretKey {
|
||||
&self.secret_key
|
||||
}
|
||||
|
||||
/// Returns the public key set for threshold cryptography.
|
||||
pub fn public_key_set(&self) -> &PublicKeySet {
|
||||
self.validator_map.public_key_set()
|
||||
}
|
||||
|
||||
/// Returns the public key share if a node with that ID exists, otherwise `None`.
|
||||
pub fn public_key_share(&self, id: &NodeUid) -> Option<&PublicKeyShare> {
|
||||
self.validator_map.public_key_share(id)
|
||||
}
|
||||
|
||||
/// Returns a map of all node IDs to their public keys.
|
||||
pub fn public_key(&self, id: &NodeUid) -> Option<&PublicKey> {
|
||||
self.validator_map.public_key(id)
|
||||
}
|
||||
|
||||
/// The index of a node in a canonical numbering of all nodes.
|
||||
pub fn node_index(&self, id: &NodeUid) -> Option<usize> {
|
||||
self.validator_map.node_index(id)
|
||||
}
|
||||
|
||||
/// Returns `true` if this node takes part in the consensus itself. If not, it is only an
|
||||
/// observer.
|
||||
pub fn is_validator(&self) -> bool {
|
||||
|
@ -268,7 +351,12 @@ impl<NodeUid: Clone + Ord> NetworkInfo<NodeUid> {
|
|||
/// Returns `true` if the given node takes part in the consensus itself. If not, it is only an
|
||||
/// observer.
|
||||
pub fn is_node_validator(&self, uid: &NodeUid) -> bool {
|
||||
self.public_keys.contains_key(uid)
|
||||
self.validator_map.is_node_validator(uid)
|
||||
}
|
||||
|
||||
/// Returns the public validator map.
|
||||
pub fn validator_map(&self) -> &ValidatorMap<NodeUid> {
|
||||
&self.validator_map
|
||||
}
|
||||
|
||||
/// Generates a map of matching `NetworkInfo`s for testing.
|
||||
|
|
|
@ -378,12 +378,10 @@ where
|
|||
let mut netinfos = NetworkInfo::generate_map((0..(good_num + adv_num)).map(NodeUid));
|
||||
let obs_netinfo = {
|
||||
let node_ni = netinfos.values().next().unwrap();
|
||||
NetworkInfo::new(
|
||||
node_ni.validator_map().clone().into_network_info(
|
||||
NodeUid(good_num + adv_num),
|
||||
SecretKeyShare::default(),
|
||||
node_ni.public_key_set().clone(),
|
||||
rng.gen(),
|
||||
node_ni.public_key_map().clone(),
|
||||
)
|
||||
};
|
||||
let adv_netinfos = netinfos.split_off(&NodeUid(good_num));
|
||||
|
|
Loading…
Reference in New Issue