2019-08-22 02:33:11 -07:00
|
|
|
use std::borrow::Borrow;
|
2018-10-10 07:11:27 -07:00
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
2019-08-22 02:33:11 -07:00
|
|
|
use std::sync::Arc;
|
2018-10-10 07:11:27 -07:00
|
|
|
|
2019-08-25 05:41:50 -07:00
|
|
|
use crate::crypto::{self, PublicKeySet, PublicKeyShare, SecretKeyShare};
|
2018-10-10 07:11:27 -07:00
|
|
|
use rand;
|
|
|
|
|
2018-12-11 05:44:36 -08:00
|
|
|
use crate::{util, NodeIdT};
|
2018-10-10 07:11:27 -07:00
|
|
|
|
2019-08-22 02:33:11 -07:00
|
|
|
/// The set of all node IDs of the network's validators.
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct ValidatorSet<N> {
|
|
|
|
num_faulty: usize,
|
|
|
|
indices: BTreeMap<N, usize>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<I, N> From<I> for ValidatorSet<N>
|
|
|
|
where
|
|
|
|
I: IntoIterator,
|
|
|
|
I::Item: Borrow<N>,
|
|
|
|
N: NodeIdT,
|
|
|
|
{
|
|
|
|
fn from(i: I) -> Self {
|
|
|
|
let indices: BTreeMap<N, usize> = i
|
|
|
|
.into_iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(n, id)| (id.borrow().clone(), n))
|
|
|
|
.collect();
|
|
|
|
let num_faulty = util::max_faulty(indices.len());
|
|
|
|
assert!(3 * num_faulty < indices.len(), "3 f >= N. This is a bug!");
|
|
|
|
ValidatorSet {
|
|
|
|
num_faulty,
|
|
|
|
indices,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<N: NodeIdT> ValidatorSet<N> {
|
|
|
|
/// Returns `true` if the given ID belongs to a known validator.
|
|
|
|
#[inline]
|
|
|
|
pub fn contains(&self, id: &N) -> bool {
|
|
|
|
self.indices.contains_key(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the validators index in the ordered list of all IDs.
|
|
|
|
#[inline]
|
|
|
|
pub fn index(&self, id: &N) -> Option<usize> {
|
|
|
|
self.indices.get(id).cloned()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The total number _N_ of validators.
|
|
|
|
#[inline]
|
|
|
|
pub fn num(&self) -> usize {
|
|
|
|
self.indices.len()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The maximum number _f_ of faulty, Byzantine validators up to which Honey Badger is
|
|
|
|
/// guaranteed to be correct.
|
|
|
|
#[inline]
|
|
|
|
pub fn num_faulty(&self) -> usize {
|
|
|
|
self.num_faulty
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The minimum number _N - f_ of correct validators with which Honey Badger is guaranteed to
|
|
|
|
/// be correct.
|
|
|
|
#[inline]
|
|
|
|
pub fn num_correct(&self) -> usize {
|
|
|
|
// As asserted in `new`, `num_faulty` is never greater than `num`.
|
|
|
|
self.num() - self.num_faulty
|
|
|
|
}
|
|
|
|
|
|
|
|
/// IDs of all validators in the network.
|
|
|
|
#[inline]
|
|
|
|
pub fn all_ids(&self) -> impl Iterator<Item = &N> + Clone {
|
|
|
|
self.indices.keys()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// IDs and indices of all validators in the network.
|
|
|
|
#[inline]
|
|
|
|
pub fn all_indices(&self) -> impl Iterator<Item = (&N, &usize)> + Clone {
|
|
|
|
self.indices.iter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:11:27 -07:00
|
|
|
/// Common data shared between algorithms: the nodes' IDs and key shares.
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct NetworkInfo<N> {
|
2018-12-12 04:39:52 -08:00
|
|
|
/// This node's ID.
|
2018-10-10 07:11:27 -07:00
|
|
|
our_id: N,
|
2018-12-12 04:39:52 -08:00
|
|
|
/// Whether this node is a validator. This is true if `public_keys` contains our own ID.
|
2018-10-10 07:11:27 -07:00
|
|
|
is_validator: bool,
|
2018-12-12 04:39:52 -08:00
|
|
|
/// This node's secret key share. Only validators have one.
|
2018-11-22 04:00:02 -08:00
|
|
|
secret_key_share: Option<SecretKeyShare>,
|
2018-12-12 04:39:52 -08:00
|
|
|
/// The public key set for threshold cryptography. Each validator has a secret key share.
|
2018-10-10 07:11:27 -07:00
|
|
|
public_key_set: PublicKeySet,
|
2018-12-12 04:39:52 -08:00
|
|
|
/// The validators' public key shares, computed from `public_key_set`.
|
2018-10-10 07:11:27 -07:00
|
|
|
public_key_shares: BTreeMap<N, PublicKeyShare>,
|
2018-12-12 04:39:52 -08:00
|
|
|
/// The indices in the list of sorted validator IDs.
|
2019-08-22 02:33:11 -07:00
|
|
|
val_set: Arc<ValidatorSet<N>>,
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<N: NodeIdT> NetworkInfo<N> {
|
2018-11-26 06:35:24 -08:00
|
|
|
/// Creates a new `NetworkInfo` with the given ID and keys.
|
|
|
|
///
|
|
|
|
/// All nodes in the network must share the same public information. Validators' IDs must be
|
|
|
|
/// keys in the `public_keys` map, and their secret key share must match their share in the
|
|
|
|
/// `public_key_set`.
|
2018-12-12 04:39:52 -08:00
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
2019-08-23 01:29:31 -07:00
|
|
|
/// Panics if `public_keys` is empty or the requirement above is not satisfied, i.e. if the
|
|
|
|
/// secret key doesn't match the public key or is missing.
|
2019-08-25 05:41:50 -07:00
|
|
|
pub fn new<SKS: Into<Option<SecretKeyShare>>, V: Into<ValidatorSet<N>>>(
|
2018-10-10 07:11:27 -07:00
|
|
|
our_id: N,
|
2018-11-22 04:00:02 -08:00
|
|
|
secret_key_share: SKS,
|
2018-10-10 07:11:27 -07:00
|
|
|
public_key_set: PublicKeySet,
|
2019-08-25 05:41:50 -07:00
|
|
|
val_set: V,
|
2018-10-10 07:11:27 -07:00
|
|
|
) -> Self {
|
2019-08-25 05:41:50 -07:00
|
|
|
let val_set = Arc::new(val_set.into());
|
2019-08-22 02:33:11 -07:00
|
|
|
let is_validator = val_set.contains(&our_id);
|
2019-08-23 01:29:31 -07:00
|
|
|
let secret_key_share = secret_key_share.into();
|
|
|
|
assert_eq!(is_validator, secret_key_share.is_some());
|
|
|
|
let public_key_shares: BTreeMap<N, PublicKeyShare> = val_set
|
|
|
|
.all_indices()
|
|
|
|
.map(|(id, idx)| (id.clone(), public_key_set.public_key_share(idx)))
|
2018-10-10 07:11:27 -07:00
|
|
|
.collect();
|
2019-08-23 01:29:31 -07:00
|
|
|
if let Some(sks) = &secret_key_share {
|
|
|
|
assert_eq!(
|
|
|
|
Some(&sks.public_key_share()),
|
|
|
|
public_key_shares.get(&our_id)
|
|
|
|
);
|
|
|
|
}
|
2018-10-10 07:11:27 -07:00
|
|
|
NetworkInfo {
|
|
|
|
our_id,
|
|
|
|
is_validator,
|
2019-08-23 01:29:31 -07:00
|
|
|
secret_key_share,
|
2018-10-10 07:11:27 -07:00
|
|
|
public_key_set,
|
|
|
|
public_key_shares,
|
2019-08-22 02:33:11 -07:00
|
|
|
val_set,
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The ID of the node the algorithm runs on.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn our_id(&self) -> &N {
|
|
|
|
&self.our_id
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ID of all nodes in the network.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2019-06-12 08:02:39 -07:00
|
|
|
pub fn all_ids(&self) -> impl Iterator<Item = &N> + Clone {
|
2019-08-22 02:33:11 -07:00
|
|
|
self.val_set.all_ids()
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
2019-07-23 02:23:42 -07:00
|
|
|
/// ID of all nodes in the network except this one.
|
|
|
|
#[inline]
|
|
|
|
pub fn other_ids(&self) -> impl Iterator<Item = &N> + Clone {
|
|
|
|
let our_id = self.our_id.clone();
|
2019-08-22 02:33:11 -07:00
|
|
|
self.all_ids().filter(move |id| **id != our_id)
|
2019-07-23 02:23:42 -07:00
|
|
|
}
|
|
|
|
|
2018-10-10 07:11:27 -07:00
|
|
|
/// The total number _N_ of nodes.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn num_nodes(&self) -> usize {
|
2019-08-22 02:33:11 -07:00
|
|
|
self.val_set.num()
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The maximum number _f_ of faulty, Byzantine nodes up to which Honey Badger is guaranteed to
|
|
|
|
/// be correct.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn num_faulty(&self) -> usize {
|
2019-08-22 02:33:11 -07:00
|
|
|
self.val_set.num_faulty()
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The minimum number _N - f_ of correct nodes with which Honey Badger is guaranteed to be
|
|
|
|
/// correct.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn num_correct(&self) -> usize {
|
2019-08-22 02:33:11 -07:00
|
|
|
self.val_set.num_correct()
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
2018-11-22 04:00:02 -08:00
|
|
|
/// Returns our secret key share for threshold cryptography, or `None` if not a validator.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-11-22 04:00:02 -08:00
|
|
|
pub fn secret_key_share(&self) -> Option<&SecretKeyShare> {
|
|
|
|
self.secret_key_share.as_ref()
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the public key set for threshold cryptography.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn public_key_set(&self) -> &PublicKeySet {
|
|
|
|
&self.public_key_set
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the public key share if a node with that ID exists, otherwise `None`.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn public_key_share(&self, id: &N) -> Option<&PublicKeyShare> {
|
|
|
|
self.public_key_shares.get(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a map of all node IDs to their public key shares.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn public_key_share_map(&self) -> &BTreeMap<N, PublicKeyShare> {
|
|
|
|
&self.public_key_shares
|
|
|
|
}
|
|
|
|
|
2018-10-24 00:42:59 -07:00
|
|
|
/// The index of a node in a canonical numbering of all nodes. This is the index where the
|
|
|
|
/// node appears in `all_ids`.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn node_index(&self, id: &N) -> Option<usize> {
|
2019-08-22 02:33:11 -07:00
|
|
|
self.val_set.index(id)
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns `true` if this node takes part in the consensus itself. If not, it is only an
|
|
|
|
/// observer.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn is_validator(&self) -> bool {
|
|
|
|
self.is_validator
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns `true` if the given node takes part in the consensus itself. If not, it is only an
|
|
|
|
/// observer.
|
2018-10-25 05:44:28 -07:00
|
|
|
#[inline]
|
2018-10-10 07:11:27 -07:00
|
|
|
pub fn is_node_validator(&self, id: &N) -> bool {
|
2019-08-25 05:41:50 -07:00
|
|
|
self.val_set.contains(id)
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
|
2019-08-22 02:33:11 -07:00
|
|
|
/// Returns the set of validator IDs.
|
|
|
|
pub fn validator_set(&self) -> &Arc<ValidatorSet<N>> {
|
|
|
|
&self.val_set
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:11:27 -07:00
|
|
|
/// Generates a map of matching `NetworkInfo`s for testing.
|
|
|
|
pub fn generate_map<I, R>(
|
|
|
|
ids: I,
|
|
|
|
rng: &mut R,
|
|
|
|
) -> Result<BTreeMap<N, NetworkInfo<N>>, crypto::error::Error>
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = N>,
|
|
|
|
R: rand::Rng,
|
|
|
|
{
|
2018-12-11 05:44:36 -08:00
|
|
|
use crate::crypto::SecretKeySet;
|
2018-10-10 07:11:27 -07:00
|
|
|
|
|
|
|
let all_ids: BTreeSet<N> = ids.into_iter().collect();
|
2018-11-22 04:00:02 -08:00
|
|
|
let num_faulty = util::max_faulty(all_ids.len());
|
2018-10-10 07:11:27 -07:00
|
|
|
|
|
|
|
// Generate the keys for threshold cryptography.
|
2018-10-06 03:33:07 -07:00
|
|
|
let sk_set = SecretKeySet::random(num_faulty, rng);
|
2018-10-10 07:11:27 -07:00
|
|
|
let pk_set = sk_set.public_keys();
|
|
|
|
|
|
|
|
// Create the corresponding `NetworkInfo` for each node.
|
2019-08-25 05:41:50 -07:00
|
|
|
let create_netinfo = |(index, id): (usize, &N)| {
|
|
|
|
let sks = sk_set.secret_key_share(index);
|
|
|
|
let netinfo = NetworkInfo::new(id.clone(), sks, pk_set.clone(), &all_ids);
|
|
|
|
Ok((id.clone(), netinfo))
|
2018-10-10 07:11:27 -07:00
|
|
|
};
|
2019-08-25 05:41:50 -07:00
|
|
|
all_ids.iter().enumerate().map(create_netinfo).collect()
|
2018-10-10 07:11:27 -07:00
|
|
|
}
|
|
|
|
}
|