Separate ValidatorMap from NetworkInfo.

This commit is contained in:
Andreas Fackler 2018-07-19 18:09:17 +02:00
parent 9488d3f936
commit 838b92ab8d
6 changed files with 150 additions and 75 deletions

View File

@ -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,

View File

@ -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());
}
}
}

View File

@ -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,

View File

@ -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>,
}

View File

@ -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.

View File

@ -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));