Remove NetworkInfo from Broadcast.

This commit is contained in:
Andreas Fackler 2019-08-22 11:33:11 +02:00 committed by Andreas Fackler
parent 8ee999b73f
commit d15467eb09
7 changed files with 174 additions and 143 deletions

View File

@ -32,7 +32,7 @@
//! the consensus `result` is not an error then every successfully terminated
//! consensus node will be the same `result`.
use std::collections::{BTreeSet, HashSet};
use std::collections::HashSet;
use std::fmt::Debug;
use std::marker::{Send, Sync};
use std::net::SocketAddr;
@ -45,8 +45,7 @@ use log::{debug, error};
use crate::network::messaging::Messaging;
use crate::network::{commst, connection};
use hbbft::broadcast::{Broadcast, Message};
use hbbft::crypto::{poly::Poly, SecretKey, SecretKeySet};
use hbbft::{ConsensusProtocol, NetworkInfo, SourcedMessage};
use hbbft::{ConsensusProtocol, SourcedMessage};
/// This is a structure to start a consensus node.
pub struct Node<T> {
@ -79,29 +78,14 @@ impl<T: Clone + Debug + AsRef<[u8]> + PartialEq + Send + Sync + From<Vec<u8>> +
.collect();
node_strs.sort();
let our_id = node_strs.binary_search(&our_str).unwrap();
let all_ids: BTreeSet<_> = (0..node_strs.len()).collect();
// FIXME: This example doesn't call algorithms that use cryptography. However the keys are
// required by the interface to all algorithms in Honey Badger. Therefore we set placeholder
// keys here. A fully-featured application would need to take appropriately initialized keys
// from elsewhere.
let secret_key_set = SecretKeySet::from(Poly::zero());
let sk_share = secret_key_set.secret_key_share(our_id);
let pub_key_set = secret_key_set.public_keys();
let sk = SecretKey::default();
let pub_keys = all_ids
.iter()
.map(|id| (*id, SecretKey::default().public_key()))
.collect();
let netinfo = NetworkInfo::new(our_id, sk_share, pub_key_set, sk, pub_keys);
let num_nodes = node_strs.len();
if value.is_some() != (our_id == 0) {
panic!("Exactly the first node must propose a value.");
}
// Initialise the message delivery system and obtain TX and RX handles.
let messaging: Messaging<Message> = Messaging::new(all_ids.len());
let messaging: Messaging<Message> = Messaging::new(num_nodes);
let rxs_to_comms = messaging.rxs_to_comms();
let tx_from_comms = messaging.tx_from_comms();
let rx_to_algo = messaging.rx_to_algo();
@ -120,8 +104,9 @@ impl<T: Clone + Debug + AsRef<[u8]> + PartialEq + Send + Sync + From<Vec<u8>> +
// corresponding to this instance, and no dedicated comms task. The
// node index is 0.
let broadcast_handle = scope.spawn(move |_| {
let mut broadcast =
Broadcast::new(Arc::new(netinfo), 0).expect("failed to instantiate broadcast");
let validators = (0..num_nodes).into();
let mut broadcast = Broadcast::new(our_id, Arc::new(validators), 0)
.expect("failed to instantiate broadcast");
if let Some(v) = value {
// FIXME: Use the output.

View File

@ -14,15 +14,18 @@ use super::merkle::{Digest, MerkleTree, Proof};
use super::message::HexProof;
use super::{Error, FaultKind, Message, Result};
use crate::fault_log::Fault;
use crate::{ConsensusProtocol, NetworkInfo, NodeIdT, Target};
use crate::{ConsensusProtocol, NodeIdT, Target, ValidatorSet};
type RseResult<T> = result::Result<T, rse::Error>;
/// Broadcast algorithm instance.
#[derive(Debug)]
pub struct Broadcast<N> {
/// Shared network data.
netinfo: Arc<NetworkInfo<N>>,
/// Our ID.
// TODO: Make optional for observers?
our_id: N,
/// The set of validator IDs.
val_set: Arc<ValidatorSet<N>>,
/// The ID of the sending node.
proposer_id: N,
/// The Reed-Solomon erasure coding configuration.
@ -40,6 +43,7 @@ pub struct Broadcast<N> {
/// Whether we have already output a value.
decided: bool,
/// Number of faulty nodes to optimize performance for.
// TODO: Make this configurable: Allow numbers between 0 and N/3?
fault_estimate: usize,
/// The hashes and proofs we have received via `Echo` and `EchoHash` messages, by sender ID.
echos: BTreeMap<N, EchoContent>,
@ -79,22 +83,27 @@ impl<N: NodeIdT> ConsensusProtocol for Broadcast<N> {
}
fn our_id(&self) -> &N {
self.netinfo.our_id()
&self.our_id
}
}
impl<N: NodeIdT> Broadcast<N> {
/// Creates a new broadcast instance to be used by node `our_id` which expects a value proposal
/// from node `proposer_id`.
pub fn new(netinfo: Arc<NetworkInfo<N>>, proposer_id: N) -> Result<Self> {
let parity_shard_num = 2 * netinfo.num_faulty();
let data_shard_num = netinfo.num_nodes() - parity_shard_num;
pub fn new<V>(our_id: N, val_set: V, proposer_id: N) -> Result<Self>
where
V: Into<Arc<ValidatorSet<N>>>,
{
let val_set: Arc<ValidatorSet<N>> = val_set.into();
let parity_shard_num = 2 * val_set.num_faulty();
let data_shard_num = val_set.num() - parity_shard_num;
let coding =
Coding::new(data_shard_num, parity_shard_num).map_err(|_| Error::InvalidNodeCount)?;
let fault_estimate = netinfo.num_faulty();
let fault_estimate = val_set.num_faulty();
Ok(Broadcast {
netinfo,
our_id,
val_set,
proposer_id,
coding,
value_sent: false,
@ -131,7 +140,7 @@ impl<N: NodeIdT> Broadcast<N> {
///
/// This must be called with every message we receive from another node.
pub fn handle_message(&mut self, sender_id: &N, message: Message) -> Result<Step<N>> {
if !self.netinfo.is_node_validator(sender_id) {
if !self.val_set.contains(sender_id) {
return Err(Error::UnknownSender);
}
match message {
@ -148,6 +157,11 @@ impl<N: NodeIdT> Broadcast<N> {
&self.proposer_id
}
/// Returns the set of all validator IDs.
pub fn validator_set(&self) -> &Arc<ValidatorSet<N>> {
&self.val_set
}
/// Breaks the input value into shards of equal length and encodes them --
/// and some extra parity shards -- with a Reed-Solomon erasure coding
/// scheme. The returned value contains the shard assigned to this
@ -191,12 +205,12 @@ impl<N: NodeIdT> Broadcast<N> {
// Default result in case of `proof` error.
let mut result = Err(Error::ProofConstructionFailed);
assert_eq!(self.netinfo.num_nodes(), mtree.values().len());
assert_eq!(self.val_set.num(), mtree.values().len());
let mut step = Step::default();
// Send each proof to a node.
for (index, id) in self.netinfo.all_ids().enumerate() {
let proof = mtree.proof(index).ok_or(Error::ProofConstructionFailed)?;
for (id, index) in self.val_set.all_indices() {
let proof = mtree.proof(*index).ok_or(Error::ProofConstructionFailed)?;
if *id == *self.our_id() {
// The proof is addressed to this node.
result = Ok(proof);
@ -293,7 +307,7 @@ impl<N: NodeIdT> Broadcast<N> {
}
// Upon receiving `N - f` `Echo`s with this root hash, multicast `Ready`.
if !self.ready_sent && self.count_echos(&hash) >= self.netinfo.num_correct() {
if !self.ready_sent && self.count_echos(&hash) >= self.val_set.num_correct() {
step.extend(self.send_ready(&hash)?);
}
@ -333,7 +347,7 @@ impl<N: NodeIdT> Broadcast<N> {
self.echos
.insert(sender_id.clone(), EchoContent::Hash(*hash));
if self.ready_sent || self.count_echos(&hash) < self.netinfo.num_correct() {
if self.ready_sent || self.count_echos(&hash) < self.val_set.num_correct() {
return self.compute_output(&hash);
}
// Upon receiving `N - f` `Echo`s with this root hash, multicast `Ready`.
@ -382,13 +396,13 @@ impl<N: NodeIdT> Broadcast<N> {
let mut step = Step::default();
// Upon receiving f + 1 matching Ready(h) messages, if Ready
// has not yet been sent, multicast Ready(h).
if self.count_readys(hash) == self.netinfo.num_faulty() + 1 && !self.ready_sent {
if self.count_readys(hash) == self.val_set.num_faulty() + 1 && !self.ready_sent {
// Enqueue a broadcast of a Ready message.
step.extend(self.send_ready(hash)?);
}
// Upon receiving 2f + 1 matching Ready(h) messages, send full
// `Echo` message to every node who hasn't sent us a `CanDecode`
if self.count_readys(hash) == 2 * self.netinfo.num_faulty() + 1 {
if self.count_readys(hash) == 2 * self.val_set.num_faulty() + 1 {
step.extend(self.send_echo_remaining(hash)?);
}
@ -397,7 +411,7 @@ impl<N: NodeIdT> Broadcast<N> {
/// Sends `Echo` message to all left nodes and handles it.
fn send_echo_left(&mut self, p: Proof<Vec<u8>>) -> Result<Step<N>> {
if !self.netinfo.is_validator() {
if !self.val_set.contains(&self.our_id) {
return Ok(Step::default());
}
let echo_msg = Message::Echo(p.clone());
@ -413,7 +427,7 @@ impl<N: NodeIdT> Broadcast<N> {
/// Sends `Echo` message to remaining nodes who haven't sent `CanDecode`
fn send_echo_remaining(&mut self, hash: &Digest) -> Result<Step<N>> {
self.echo_sent = true;
if !self.netinfo.is_validator() {
if !self.val_set.contains(&self.our_id) {
return Ok(Step::default());
}
@ -441,7 +455,7 @@ impl<N: NodeIdT> Broadcast<N> {
/// Sends an `EchoHash` message and handles it. Does nothing if we are only an observer.
fn send_echo_hash(&mut self, hash: &Digest) -> Result<Step<N>> {
self.echo_hash_sent = true;
if !self.netinfo.is_validator() {
if !self.val_set.contains(&self.our_id) {
return Ok(Step::default());
}
let echo_hash_msg = Message::EchoHash(*hash);
@ -462,18 +476,18 @@ impl<N: NodeIdT> Broadcast<N> {
fn right_nodes(&self) -> impl Iterator<Item = &N> {
let our_id = self.our_id().clone();
let not_us = move |x: &&N| **x != our_id;
self.netinfo
self.val_set
.all_ids()
.cycle()
.skip_while(not_us.clone())
.skip(self.netinfo.num_correct() - self.netinfo.num_faulty() + self.fault_estimate)
.skip(self.val_set.num_correct() - self.val_set.num_faulty() + self.fault_estimate)
.take_while(not_us)
}
/// Sends a `CanDecode` message and handles it. Does nothing if we are only an observer.
fn send_can_decode(&mut self, hash: &Digest) -> Result<Step<N>> {
self.can_decode_sent.insert(hash.clone());
if !self.netinfo.is_validator() {
if !self.val_set.contains(&self.our_id) {
return Ok(Step::default());
}
@ -481,7 +495,7 @@ impl<N: NodeIdT> Broadcast<N> {
let mut step = Step::default();
let recipients = self
.netinfo
.val_set
.all_ids()
.filter(|id| match self.echos.get(id) {
Some(EchoContent::Hash(_)) | None => true,
@ -498,7 +512,7 @@ impl<N: NodeIdT> Broadcast<N> {
/// Sends a `Ready` message and handles it. Does nothing if we are only an observer.
fn send_ready(&mut self, hash: &Digest) -> Result<Step<N>> {
self.ready_sent = true;
if !self.netinfo.is_validator() {
if !self.val_set.contains(&self.our_id) {
return Ok(Step::default());
}
let ready_msg = Message::Ready(*hash);
@ -511,7 +525,7 @@ impl<N: NodeIdT> Broadcast<N> {
/// value.
fn compute_output(&mut self, hash: &Digest) -> Result<Step<N>> {
if self.decided
|| self.count_readys(hash) <= 2 * self.netinfo.num_faulty()
|| self.count_readys(hash) <= 2 * self.val_set.num_faulty()
|| self.count_echos_full(hash) < self.coding.data_shard_count()
{
return Ok(Step::default());
@ -519,7 +533,7 @@ impl<N: NodeIdT> Broadcast<N> {
// Upon receiving 2f + 1 matching Ready(h) messages, wait for N 2f Echo messages.
let mut leaf_values: Vec<Option<Box<[u8]>>> = self
.netinfo
.val_set
.all_ids()
.map(|id| {
self.echos
@ -588,7 +602,7 @@ impl<N: NodeIdT> Broadcast<N> {
/// Returns `true` if the proof is valid and has the same index as the node ID.
fn validate_proof(&self, p: &Proof<Vec<u8>>, id: &N) -> bool {
self.netinfo.node_index(id) == Some(p.index()) && p.validate(self.netinfo.num_nodes())
self.val_set.index(id) == Some(p.index()) && p.validate(self.val_set.num())
}
/// Returns the number of nodes that have sent us a full `Echo` message with this hash.

View File

@ -139,8 +139,8 @@
//!
//! ```
//! use hbbft::broadcast::{Broadcast, Error, Step};
//! use hbbft::{NetworkInfo, SourcedMessage, Target, TargetedMessage};
//! use rand::{OsRng, Rng, RngCore};
//! use hbbft::{ValidatorSet, SourcedMessage, Target, TargetedMessage};
//! use rand::{rngs::OsRng, Rng, RngCore};
//! use std::collections::{BTreeMap, BTreeSet, VecDeque};
//! use std::iter::once;
//! use std::sync::Arc;
@ -152,14 +152,12 @@
//!
//! let mut rng = OsRng::new().expect("Could not initialize OS random number generator.");
//!
//! // Create a random set of keys for testing.
//! let netinfos = NetworkInfo::generate_map(0..NUM_NODES, &mut rng)
//! .expect("Failed to create `NetworkInfo` map");
//! let validators = Arc::new(ValidatorSet::from(0..NUM_NODES));
//!
//! // Create initial nodes by instantiating a `Broadcast` for each.
//! let mut nodes = BTreeMap::new();
//! for (i, netinfo) in netinfos {
//! let bc = Broadcast::new(Arc::new(netinfo), PROPOSER_ID)?;
//! for i in 0..NUM_NODES {
//! let bc = Broadcast::new(i, validators.clone(), PROPOSER_ID)?;
//! nodes.insert(i, bc);
//! }
//!

View File

@ -142,7 +142,7 @@ pub mod util;
pub use crate::crypto::pairing;
pub use crate::fault_log::{Fault, FaultLog};
pub use crate::messaging::{SourcedMessage, Target, TargetedMessage};
pub use crate::network_info::NetworkInfo;
pub use crate::network_info::{NetworkInfo, ValidatorSet};
pub use crate::traits::{
ConsensusProtocol, Contribution, CpStep, Epoched, Message, NodeIdT, SessionIdT, Step,
};

View File

@ -1,19 +1,92 @@
use std::borrow::Borrow;
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use crate::crypto::{self, PublicKey, PublicKeySet, PublicKeyShare, SecretKey, SecretKeyShare};
use rand;
use crate::{util, NodeIdT};
/// 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()
}
}
/// Common data shared between algorithms: the nodes' IDs and key shares.
#[derive(Debug, Clone)]
pub struct NetworkInfo<N> {
/// This node's ID.
our_id: N,
/// The number _N_ of nodes in the network. Equal to the size of `public_keys`.
num_nodes: usize,
/// The number _f_ of faulty nodes that can be tolerated. Less than a third of _N_.
num_faulty: usize,
/// Whether this node is a validator. This is true if `public_keys` contains our own ID.
is_validator: bool,
/// This node's secret key share. Only validators have one.
@ -27,7 +100,7 @@ pub struct NetworkInfo<N> {
/// The validators' public keys.
public_keys: BTreeMap<N, PublicKey>,
/// The indices in the list of sorted validator IDs.
node_indices: BTreeMap<N, usize>,
val_set: Arc<ValidatorSet<N>>,
}
impl<N: NodeIdT> NetworkInfo<N> {
@ -47,29 +120,21 @@ impl<N: NodeIdT> NetworkInfo<N> {
secret_key: SecretKey,
public_keys: BTreeMap<N, PublicKey>,
) -> Self {
let num_nodes = public_keys.len();
let num_faulty = util::max_faulty(num_nodes);
assert!(3 * num_faulty < num_nodes, " 3 f >= N. This is a bug!");
let is_validator = public_keys.contains_key(&our_id);
let node_indices: BTreeMap<N, usize> = public_keys
let val_set = Arc::new(ValidatorSet::from(public_keys.keys()));
let is_validator = val_set.contains(&our_id);
let public_key_shares = public_keys
.keys()
.enumerate()
.map(|(n, id)| (id.clone(), n))
.collect();
let public_key_shares = node_indices
.iter()
.map(|(id, idx)| (id.clone(), public_key_set.public_key_share(*idx)))
.map(|(idx, id)| (id.clone(), public_key_set.public_key_share(idx)))
.collect();
NetworkInfo {
our_id,
num_nodes,
num_faulty,
is_validator,
secret_key_share: secret_key_share.into(),
secret_key,
public_key_set,
public_key_shares,
node_indices,
val_set,
public_keys,
}
}
@ -83,35 +148,34 @@ impl<N: NodeIdT> NetworkInfo<N> {
/// ID of all nodes in the network.
#[inline]
pub fn all_ids(&self) -> impl Iterator<Item = &N> + Clone {
self.public_keys.keys()
self.val_set.all_ids()
}
/// 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();
self.public_keys.keys().filter(move |id| **id != our_id)
self.all_ids().filter(move |id| **id != our_id)
}
/// The total number _N_ of nodes.
#[inline]
pub fn num_nodes(&self) -> usize {
self.num_nodes
self.val_set.num()
}
/// The maximum number _f_ of faulty, Byzantine nodes up to which Honey Badger is guaranteed to
/// be correct.
#[inline]
pub fn num_faulty(&self) -> usize {
self.num_faulty
self.val_set.num_faulty()
}
/// The minimum number _N - f_ of correct nodes 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_nodes`.
self.num_nodes - self.num_faulty
self.val_set.num_correct()
}
/// Returns our secret key share for threshold cryptography, or `None` if not a validator.
@ -160,7 +224,7 @@ impl<N: NodeIdT> NetworkInfo<N> {
/// node appears in `all_ids`.
#[inline]
pub fn node_index(&self, id: &N) -> Option<usize> {
self.node_indices.get(id).cloned()
self.val_set.index(id)
}
/// Returns `true` if this node takes part in the consensus itself. If not, it is only an
@ -177,6 +241,11 @@ impl<N: NodeIdT> NetworkInfo<N> {
self.public_keys.contains_key(id)
}
/// Returns the set of validator IDs.
pub fn validator_set(&self) -> &Arc<ValidatorSet<N>> {
&self.val_set
}
/// Generates a map of matching `NetworkInfo`s for testing.
pub fn generate_map<I, R>(
ids: I,

View File

@ -30,8 +30,10 @@ pub enum ProposalState<N, S> {
impl<N: NodeIdT, S: SessionIdT> ProposalState<N, S> {
/// Creates a new `ProposalState::Ongoing`, with a fresh broadcast and agreement instance.
pub fn new(netinfo: Arc<NetworkInfo<N>>, ba_id: BaSessionId<S>, prop_id: N) -> Result<Self> {
let agreement = BaInstance::new(netinfo.clone(), ba_id).map_err(Error::NewAgreement)?;
let broadcast = Broadcast::new(netinfo, prop_id).map_err(Error::NewBroadcast)?;
let our_id = netinfo.our_id().clone();
let validators = netinfo.validator_set().clone();
let agreement = BaInstance::new(netinfo, ba_id).map_err(Error::NewAgreement)?;
let broadcast = Broadcast::new(our_id, validators, prop_id).map_err(Error::NewBroadcast)?;
Ok(ProposalState::Ongoing(broadcast, agreement))
}

View File

@ -1,8 +1,6 @@
use std::collections::BTreeMap;
use std::iter::once;
use std::sync::{Arc, Mutex};
use hbbft::{broadcast::Broadcast, util, ConsensusProtocol, CpStep, NetworkInfo};
use hbbft::{broadcast::Broadcast, util, ConsensusProtocol, CpStep};
use hbbft_testing::adversary::{
sort_ascending, swap_random, Adversary, NetMutHandle, NodeOrderAdversary, RandomAdversary,
ReorderingAdversary,
@ -14,7 +12,6 @@ use proptest::{prelude::ProptestConfig, proptest};
use rand::{Rng, SeedableRng};
type NodeId = u16;
type NetworkInfoMap = BTreeMap<NodeId, Arc<NetworkInfo<NodeId>>>;
/// A strategy for picking the next node to handle a message.
/// The sorting algorithm used is stable - preserves message
@ -37,26 +34,16 @@ pub struct ProposeAdversary {
message_strategy: MessageSorting,
has_sent: bool,
drop_messages: bool,
// TODO this is really hacky but there's no better way to get this value
// Solution taken from binary_agreement_mitm test - ideally the new network simulator
// should be altered to store the netinfo structure alongside nodes similar to
// the way the old network simulator did it.
netinfo_mutex: Arc<Mutex<NetworkInfoMap>>,
}
impl ProposeAdversary {
/// Creates a new `ProposeAdversary`.
#[inline]
pub fn new(
message_strategy: MessageSorting,
netinfo_mutex: Arc<Mutex<NetworkInfoMap>>,
drop_messages: bool,
) -> Self {
pub fn new(message_strategy: MessageSorting, drop_messages: bool) -> Self {
ProposeAdversary {
message_strategy,
has_sent: false,
drop_messages,
netinfo_mutex,
}
}
}
@ -97,15 +84,8 @@ impl Adversary<Broadcast<NodeId>> for ProposeAdversary {
// Instantiate a temporary broadcast consensus protocol for each faulty node
// and add the generated messages to the current step.
for faulty_node in faulty_nodes {
let netinfo = self
.netinfo_mutex
.lock()
.unwrap()
.get(faulty_node.id())
.cloned()
.expect("Adversary netinfo mutex not populated");
let fake_step = Broadcast::new(netinfo, *faulty_node.id())
let validators = faulty_node.algorithm().validator_set().clone();
let fake_step = Broadcast::new(*faulty_node.id(), validators, *faulty_node.id())
.expect("broadcast instance")
.handle_input(b"Fake news".to_vec(), &mut rng)
.expect("propose");
@ -166,12 +146,8 @@ fn test_broadcast<A: Adversary<Broadcast<NodeId>>>(
}
}
fn test_broadcast_different_sizes<A, F>(
new_adversary: F,
proposed_value: &[u8],
seed: TestRngSeed,
adversary_netinfo: &Arc<Mutex<NetworkInfoMap>>,
) where
fn test_broadcast_different_sizes<A, F>(new_adversary: F, proposed_value: &[u8], seed: TestRngSeed)
where
A: Adversary<Broadcast<NodeId>>,
F: Fn() -> A,
{
@ -181,7 +157,6 @@ fn test_broadcast_different_sizes<A, F>(
.chain(once(rng.gen_range(30, 50)));
for size in sizes {
// cloning since it gets moved into a closure
let cloned_netinfo_map = adversary_netinfo.clone();
let num_faulty_nodes = util::max_faulty(size);
info!(
"Network size: {} good nodes, {} faulty nodes",
@ -197,12 +172,9 @@ fn test_broadcast_different_sizes<A, F>(
.no_time_limit()
.adversary(new_adversary())
.using(move |info| {
let netinfo = Arc::new(info.netinfo);
cloned_netinfo_map
.lock()
.unwrap()
.insert(info.id, netinfo.clone());
Broadcast::new(netinfo, proposer_id)
let validators = info.netinfo.validator_set().clone();
let id = *info.netinfo.our_id();
Broadcast::new(id, validators, proposer_id)
.expect("Failed to create a Broadcast instance.")
})
.build(&mut rng)
@ -272,7 +244,9 @@ fn do_test_8_broadcast_equal_leaves_silent(seed: TestRngSeed) {
.no_time_limit()
.adversary(ReorderingAdversary::new())
.using(move |node_info: NewNodeInfo<_>| {
Broadcast::new(Arc::new(node_info.netinfo), proposer_id)
let id = *node_info.netinfo.our_id();
let validators = node_info.netinfo.validator_set().clone();
Broadcast::new(id, validators, proposer_id)
.expect("Failed to create a Broadcast instance.")
})
.build(&mut rng)
@ -284,40 +258,29 @@ fn do_test_8_broadcast_equal_leaves_silent(seed: TestRngSeed) {
}
fn do_test_broadcast_random_delivery_silent(seed: TestRngSeed) {
test_broadcast_different_sizes(ReorderingAdversary::new, b"Foo", seed, &Default::default());
test_broadcast_different_sizes(ReorderingAdversary::new, b"Foo", seed);
}
fn do_test_broadcast_first_delivery_silent(seed: TestRngSeed) {
test_broadcast_different_sizes(NodeOrderAdversary::new, b"Foo", seed, &Default::default());
test_broadcast_different_sizes(NodeOrderAdversary::new, b"Foo", seed);
}
fn do_test_broadcast_first_delivery_adv_propose(seed: TestRngSeed) {
let adversary_netinfo: Arc<Mutex<NetworkInfoMap>> = Default::default();
let new_adversary = || {
ProposeAdversary::new(
MessageSorting::SortAscending,
adversary_netinfo.clone(),
false,
)
};
test_broadcast_different_sizes(new_adversary, b"Foo", seed, &adversary_netinfo);
let new_adversary = || ProposeAdversary::new(MessageSorting::SortAscending, false);
test_broadcast_different_sizes(new_adversary, b"Foo", seed);
}
fn do_test_broadcast_random_delivery_adv_propose(seed: TestRngSeed) {
let adversary_netinfo: Arc<Mutex<NetworkInfoMap>> = Default::default();
let new_adversary =
|| ProposeAdversary::new(MessageSorting::RandomPick, adversary_netinfo.clone(), false);
test_broadcast_different_sizes(new_adversary, b"Foo", seed, &adversary_netinfo);
let new_adversary = || ProposeAdversary::new(MessageSorting::RandomPick, false);
test_broadcast_different_sizes(new_adversary, b"Foo", seed);
}
fn do_test_broadcast_random_delivery_adv_propose_and_drop(seed: TestRngSeed) {
let adversary_netinfo: Arc<Mutex<NetworkInfoMap>> = Default::default();
let new_adversary =
|| ProposeAdversary::new(MessageSorting::RandomPick, adversary_netinfo.clone(), true);
test_broadcast_different_sizes(new_adversary, b"Foo", seed, &adversary_netinfo);
let new_adversary = || ProposeAdversary::new(MessageSorting::RandomPick, true);
test_broadcast_different_sizes(new_adversary, b"Foo", seed);
}
fn do_test_broadcast_random_adversary(seed: TestRngSeed) {
let new_adversary = || RandomAdversary::new(0.2, 0.2);
test_broadcast_different_sizes(new_adversary, b"RandomFoo", seed, &Default::default());
test_broadcast_different_sizes(new_adversary, b"RandomFoo", seed);
}