Merge pull request #218 from poanetwork/afck-rename

Rename Agreement to BinaryAgreement.
This commit is contained in:
Vladimir Komendantskiy 2018-08-30 10:57:14 +01:00 committed by GitHub
commit aa067d29e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 137 additions and 134 deletions

View File

@ -4,9 +4,9 @@ use std::sync::Arc;
use itertools::Itertools;
use super::bool_multimap::BoolMultimap;
use super::bool_set::BoolSet;
use super::sbv_broadcast::{self, SbvBroadcast};
use super::{AgreementContent, Error, Message, Nonce, Result, Step};
use agreement::bool_set::BoolSet;
use super::{Error, Message, MessageContent, Nonce, Result, Step};
use coin::{self, Coin, CoinMessage};
use messaging::{DistAlgorithm, NetworkInfo, Target};
use traits::NodeIdT;
@ -39,14 +39,14 @@ impl<N> From<bool> for CoinState<N> {
/// Binary Agreement instance
#[derive(Debug)]
pub struct Agreement<N> {
pub struct BinaryAgreement<N> {
/// Shared network information.
netinfo: Arc<NetworkInfo<N>>,
/// Session ID, e.g, the Honey Badger algorithm epoch.
session_id: u64,
/// The ID of the proposer of the value for this agreement instance.
/// The ID of the proposer of the value for this Binary Agreement instance.
proposer_id: N,
/// Agreement algorithm epoch.
/// Binary Agreement algorithm epoch.
epoch: u32,
/// This epoch's Synchronized Binary Value Broadcast instance.
sbv_broadcast: SbvBroadcast<N>,
@ -65,14 +65,14 @@ pub struct Agreement<N> {
decision: Option<bool>,
/// A cache for messages for future epochs that cannot be handled yet.
// TODO: Find a better solution for this; defend against spam.
incoming_queue: BTreeMap<u32, Vec<(N, AgreementContent)>>,
incoming_queue: BTreeMap<u32, Vec<(N, MessageContent)>>,
/// The values we found in the first _N - f_ `Aux` messages that were in `bin_values`.
conf_values: Option<BoolSet>,
/// The state of this epoch's coin.
coin_state: CoinState<N>,
}
impl<N: NodeIdT> DistAlgorithm for Agreement<N> {
impl<N: NodeIdT> DistAlgorithm for BinaryAgreement<N> {
type NodeId = N;
type Input = bool;
type Output = bool;
@ -109,12 +109,12 @@ impl<N: NodeIdT> DistAlgorithm for Agreement<N> {
}
}
impl<N: NodeIdT> Agreement<N> {
impl<N: NodeIdT> BinaryAgreement<N> {
pub fn new(netinfo: Arc<NetworkInfo<N>>, session_id: u64, proposer_id: N) -> Result<Self> {
if !netinfo.is_node_validator(&proposer_id) {
return Err(Error::UnknownProposer);
}
Ok(Agreement {
Ok(BinaryAgreement {
netinfo: netinfo.clone(),
session_id,
proposer_id,
@ -130,7 +130,7 @@ impl<N: NodeIdT> Agreement<N> {
})
}
/// Sets the input value for agreement.
/// Sets the input value for Binary Agreement.
fn handle_input(&mut self, input: bool) -> Result<Step<N>> {
if self.epoch != 0 || self.estimated.is_some() {
return Err(Error::InputNotAccepted);
@ -151,13 +151,13 @@ impl<N: NodeIdT> Agreement<N> {
fn handle_message_content(
&mut self,
sender_id: &N,
content: AgreementContent,
content: MessageContent,
) -> Result<Step<N>> {
match content {
AgreementContent::SbvBroadcast(msg) => self.handle_sbv_broadcast(sender_id, msg),
AgreementContent::Conf(v) => self.handle_conf(sender_id, v),
AgreementContent::Term(v) => self.handle_term(sender_id, v),
AgreementContent::Coin(msg) => self.handle_coin(sender_id, *msg),
MessageContent::SbvBroadcast(msg) => self.handle_sbv_broadcast(sender_id, msg),
MessageContent::Conf(v) => self.handle_conf(sender_id, v),
MessageContent::Term(v) => self.handle_term(sender_id, v),
MessageContent::Coin(msg) => self.handle_coin(sender_id, *msg),
}
}
@ -176,7 +176,7 @@ impl<N: NodeIdT> Agreement<N> {
fn handle_sbvb_step(&mut self, sbvb_step: sbv_broadcast::Step<N>) -> Result<Step<N>> {
let mut step = Step::default();
let output = step.extend_with(sbvb_step, |msg| {
AgreementContent::SbvBroadcast(msg).with_epoch(self.epoch)
MessageContent::SbvBroadcast(msg).with_epoch(self.epoch)
});
if self.conf_values.is_some() {
return Ok(step); // The `Conf` round has already started.
@ -250,11 +250,11 @@ impl<N: NodeIdT> Agreement<N> {
return Ok(self.try_finish_conf_round()?);
}
self.send(AgreementContent::Conf(values))
self.send(MessageContent::Conf(values))
}
/// Multicasts and handles a message. Does nothing if we are only an observer.
fn send(&mut self, content: AgreementContent) -> Result<Step<N>> {
fn send(&mut self, content: MessageContent) -> Result<Step<N>> {
if !self.netinfo.is_validator() {
return Ok(Step::default());
}
@ -270,7 +270,7 @@ impl<N: NodeIdT> Agreement<N> {
fn on_coin_step(&mut self, coin_step: coin::Step<N, Nonce>) -> Result<Step<N>> {
let mut step = Step::default();
let epoch = self.epoch;
let to_msg = |c_msg| AgreementContent::Coin(Box::new(c_msg)).with_epoch(epoch);
let to_msg = |c_msg| MessageContent::Coin(Box::new(c_msg)).with_epoch(epoch);
let coin_output = step.extend_with(coin_step, to_msg);
if let Some(coin) = coin_output.into_iter().next() {
self.coin_state = coin.into();
@ -287,7 +287,7 @@ impl<N: NodeIdT> Agreement<N> {
/// the unique conf value agrees with the coin, terminates and decides on that value.
fn try_update_epoch(&mut self) -> Result<Step<N>> {
if self.decision.is_some() {
// Avoid an infinite regression without making an Agreement step.
// Avoid an infinite regression without making a Binary Agreement step.
return Ok(Step::default());
}
let coin = match self.coin_state.value() {
@ -329,7 +329,7 @@ impl<N: NodeIdT> Agreement<N> {
if self.decision.is_some() {
return Step::default();
}
// Output the agreement value.
// Output the Binary Agreement value.
let mut step = Step::default();
step.output.push_back(b);
// Latch the decided state.
@ -342,7 +342,7 @@ impl<N: NodeIdT> Agreement<N> {
b
);
if self.netinfo.is_validator() {
let msg = AgreementContent::Term(b).with_epoch(self.epoch + 1);
let msg = MessageContent::Term(b).with_epoch(self.epoch + 1);
step.messages.push_back(Target::All.message(msg));
}
step
@ -383,7 +383,7 @@ impl<N: NodeIdT> Agreement<N> {
self.epoch += 1;
self.coin_state = self.coin_state();
debug!(
"{:?} Agreement instance {:?} started epoch {}, {} terminated",
"{:?} BinaryAgreement instance {:?} started epoch {}, {} terminated",
self.netinfo.our_id(),
self.proposer_id,
self.epoch,

View File

@ -1,4 +1,4 @@
//! # Binary Byzantine agreement protocol
//! # Binary Agreement
//!
//! The Binary Agreement protocol allows each node to input one binary (`bool`) value, and will
//! output a binary value. The output is guaranteed to have been input by at least one correct
@ -63,7 +63,7 @@
//! * After _f + 1_ nodes have sent us their coin shares, we receive the coin output and assign it
//! to `s`.
mod agreement;
mod binary_agreement;
mod bool_multimap;
pub mod bool_set;
mod sbv_broadcast;
@ -74,9 +74,9 @@ use self::bool_set::BoolSet;
use coin::{self, CoinMessage};
use messaging;
pub use self::agreement::Agreement;
pub use self::binary_agreement::BinaryAgreement;
/// An agreement error.
/// An Binary Agreement error.
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
pub enum Error {
#[fail(display = "HandleCoin error: {}", _0)]
@ -89,13 +89,13 @@ pub enum Error {
InputNotAccepted,
}
/// An agreement result.
/// An Binary Agreement result.
pub type Result<T> = ::std::result::Result<T, Error>;
pub type Step<N> = messaging::Step<Agreement<N>>;
pub type Step<N> = messaging::Step<BinaryAgreement<N>>;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum AgreementContent {
pub enum MessageContent {
/// Synchronized Binary Value Broadcast message.
SbvBroadcast(sbv_broadcast::Message),
/// `Conf` message.
@ -106,7 +106,7 @@ pub enum AgreementContent {
Coin(Box<CoinMessage>),
}
impl AgreementContent {
impl MessageContent {
/// Creates an message with a given epoch number.
pub fn with_epoch(self, epoch: u32) -> Message {
Message {
@ -118,31 +118,31 @@ impl AgreementContent {
/// Returns `true` if this message can be ignored if its epoch has already passed.
pub fn can_expire(&self) -> bool {
match *self {
AgreementContent::Term(_) => false,
MessageContent::Term(_) => false,
_ => true,
}
}
}
/// Messages sent during the binary Byzantine agreement stage.
/// Messages sent during the Binary Agreement stage.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Rand)]
pub struct Message {
pub epoch: u32,
pub content: AgreementContent,
pub content: MessageContent,
}
// NOTE: Extending rand_derive to correctly generate random values from boxes would make this
// implementation obsolete; however at the time of this writing, `rand::Rand` is already deprecated
// with no replacement in sight.
impl rand::Rand for AgreementContent {
impl rand::Rand for MessageContent {
fn rand<R: rand::Rng>(rng: &mut R) -> Self {
let message_type = *rng.choose(&["sbvb", "conf", "term", "coin"]).unwrap();
match message_type {
"sbvb" => AgreementContent::SbvBroadcast(rand::random()),
"conf" => AgreementContent::Conf(rand::random()),
"term" => AgreementContent::Term(rand::random()),
"coin" => AgreementContent::Coin(Box::new(rand::random())),
"sbvb" => MessageContent::SbvBroadcast(rand::random()),
"conf" => MessageContent::Conf(rand::random()),
"term" => MessageContent::Term(rand::random()),
"coin" => MessageContent::Coin(Box::new(rand::random())),
_ => unreachable!(),
}
}
@ -156,11 +156,11 @@ impl Nonce {
invocation_id: &[u8],
session_id: u64,
proposer_id: usize,
agreement_epoch: u32,
binary_agreement_epoch: u32,
) -> Self {
Nonce(Vec::from(format!(
"Nonce for Honey Badger {:?}@{}:{}:{}",
invocation_id, session_id, agreement_epoch, proposer_id
invocation_id, session_id, binary_agreement_epoch, proposer_id
)))
}
}

View File

@ -1,6 +1,6 @@
//! # Synchronized Binary Value Broadcast
//!
//! This performs the `BVal` and `Aux` steps for `Agreement`.
//! This performs the `BVal` and `Aux` steps for `BinaryAgreement`.
//!
//! Validators input binary values, and each node outputs a set of one or two binary values.
//! These outputs are not necessarily the same in each node, but it is guaranteed that whenever two

View File

@ -63,9 +63,9 @@ pub enum FaultKind {
InvalidVoteSignature,
/// A validator committed an invalid vote in `DynamicHoneyBadger`.
InvalidCommittedVote,
/// `Agreement` received a duplicate `BVal` message.
/// `BinaryAgreement` received a duplicate `BVal` message.
DuplicateBVal,
/// `Agreement` received a duplicate `Aux` message.
/// `BinaryAgreement` received a duplicate `Aux` message.
DuplicateAux,
}

View File

@ -76,7 +76,7 @@
//!
//! This is used in Subset to send each node's proposal to the other nodes.
//!
//! [**Binary Agreement**](agreement/index.html)
//! [**Binary Agreement**](binary_agreement/index.html)
//!
//! Each node inputs a binary value: `true` or `false`. As output, either all correct nodes receive
//! `true` or all correct nodes receive `false`. The output is guaranteed to be a value that was
@ -137,7 +137,7 @@ extern crate serde_derive;
pub extern crate threshold_crypto as crypto;
extern crate tiny_keccak;
pub mod agreement;
pub mod binary_agreement;
pub mod broadcast;
pub mod coin;
pub mod dynamic_honey_badger;

View File

@ -17,17 +17,17 @@
//! the element proposed by that node.
//! * It also instantiates Binary Agreement for each participating node, to decide whether
//! that node's proposed element should be included in the set. Whenever an element is
//! received via broadcast, we input "yes" (`true`) into the corresponding `Agreement` instance.
//! * When _N - f_ `Agreement` instances have decided "yes", we input "no" (`false`) into the
//! received via broadcast, we input "yes" (`true`) into the corresponding `BinaryAgreement` instance.
//! * When _N - f_ `BinaryAgreement` instances have decided "yes", we input "no" (`false`) into the
//! remaining ones, where we haven't provided input yet.
//! * Once all `Agreement` instances have decided, `Subset` returns the set of all proposed
//! * Once all `BinaryAgreement` instances have decided, `Subset` returns the set of all proposed
//! values for which the decision was "yes".
use std::collections::{BTreeMap, BTreeSet};
use std::result;
use std::sync::Arc;
use agreement::{self, Agreement};
use binary_agreement::{self, BinaryAgreement};
use broadcast::{self, Broadcast};
use fmt::HexBytes;
use messaging::{self, DistAlgorithm, NetworkInfo};
@ -37,20 +37,20 @@ use traits::NodeIdT;
/// A subset error.
#[derive(Clone, PartialEq, Debug, Fail)]
pub enum Error {
#[fail(display = "NewAgreement error: {}", _0)]
NewAgreement(agreement::Error),
#[fail(display = "ProcessAgreementAgreement0 error: {}", _0)]
ProcessAgreementAgreement0(agreement::Error),
#[fail(display = "ProcessAgreementAgreement1 error: {}", _0)]
ProcessAgreementAgreement1(agreement::Error),
#[fail(display = "NewBinaryAgreement error: {}", _0)]
NewBinaryAgreement(binary_agreement::Error),
#[fail(display = "ProcessBinaryAgreement0 error: {}", _0)]
ProcessBinaryAgreement0(binary_agreement::Error),
#[fail(display = "ProcessBinaryAgreement1 error: {}", _0)]
ProcessBinaryAgreement1(binary_agreement::Error),
#[fail(display = "NewBroadcast error: {}", _0)]
NewBroadcast(broadcast::Error),
#[fail(display = "ProcessBroadcastBroadcast error: {}", _0)]
ProcessBroadcastBroadcast(broadcast::Error),
#[fail(display = "Multiple agreement results")]
MultipleAgreementResults,
#[fail(display = "No such agreement instance")]
NoSuchAgreementInstance,
#[fail(display = "Multiple Binary Agreement results")]
MultipleBinaryAgreementResults,
#[fail(display = "No such Binary Agreement instance")]
NoSuchBinaryAgreementInstance,
#[fail(display = "No such broadcast instance")]
NoSuchBroadcastInstance,
}
@ -66,9 +66,9 @@ type ProposedValue = Vec<u8>;
pub enum Message<N: Rand> {
/// A message for the broadcast algorithm concerning the set element proposed by the given node.
Broadcast(N, broadcast::Message),
/// A message for the agreement algorithm concerning the set element proposed by the given
/// A message for the Binary Agreement algorithm concerning the set element proposed by the given
/// node.
Agreement(N, agreement::Message),
BinaryAgreement(N, binary_agreement::Message),
}
/// Subset algorithm instance
@ -77,9 +77,9 @@ pub struct Subset<N: Rand> {
/// Shared network information.
netinfo: Arc<NetworkInfo<N>>,
broadcast_instances: BTreeMap<N, Broadcast<N>>,
agreement_instances: BTreeMap<N, Agreement<N>>,
ba_instances: BTreeMap<N, BinaryAgreement<N>>,
broadcast_results: BTreeMap<N, ProposedValue>,
agreement_results: BTreeMap<N, bool>,
ba_results: BTreeMap<N, bool>,
/// Whether the instance has decided on a value.
decided: bool,
}
@ -109,12 +109,14 @@ impl<N: NodeIdT + Rand> DistAlgorithm for Subset<N> {
) -> Result<Step<N>> {
match message {
Message::Broadcast(p_id, b_msg) => self.handle_broadcast(sender_id, &p_id, b_msg),
Message::Agreement(p_id, a_msg) => self.handle_agreement(sender_id, &p_id, a_msg),
Message::BinaryAgreement(p_id, a_msg) => {
self.handle_binary_agreement(sender_id, &p_id, a_msg)
}
}
}
fn terminated(&self) -> bool {
self.agreement_instances.values().all(Agreement::terminated)
self.ba_instances.values().all(BinaryAgreement::terminated)
}
fn our_id(&self) -> &Self::NodeId {
@ -133,22 +135,22 @@ impl<N: NodeIdT + Rand> Subset<N> {
);
}
// Create all agreement instances.
let mut agreement_instances: BTreeMap<N, Agreement<N>> = BTreeMap::new();
// Create all Binary Agreement instances.
let mut ba_instances: BTreeMap<N, BinaryAgreement<N>> = BTreeMap::new();
for proposer_id in netinfo.all_ids() {
agreement_instances.insert(
ba_instances.insert(
proposer_id.clone(),
Agreement::new(netinfo.clone(), session_id, proposer_id.clone())
.map_err(Error::NewAgreement)?,
BinaryAgreement::new(netinfo.clone(), session_id, proposer_id.clone())
.map_err(Error::NewBinaryAgreement)?,
);
}
Ok(Subset {
netinfo,
broadcast_instances,
agreement_instances,
ba_instances,
broadcast_results: BTreeMap::new(),
agreement_results: BTreeMap::new(),
ba_results: BTreeMap::new(),
decided: false,
})
}
@ -180,17 +182,17 @@ impl<N: NodeIdT + Rand> Subset<N> {
self.process_broadcast(proposer_id, |bc| bc.handle_message(sender_id, bmessage))
}
/// Receives an agreement message from a remote node `sender_id` concerning
/// Receives a Binary Agreement message from a remote node `sender_id` concerning
/// a value proposed by the node `proposer_id`.
fn handle_agreement(
fn handle_binary_agreement(
&mut self,
sender_id: &N,
proposer_id: &N,
amessage: agreement::Message,
amessage: binary_agreement::Message,
) -> Result<Step<N>> {
// Send the message to the local instance of Agreement
self.process_agreement(proposer_id, |agreement| {
agreement.handle_message(sender_id, amessage)
// Send the message to the local instance of Binary Agreement.
self.process_binary_agreement(proposer_id, |binary_agreement| {
binary_agreement.handle_message(sender_id, amessage)
})
}
@ -218,35 +220,35 @@ impl<N: NodeIdT + Rand> Subset<N> {
}
};
self.broadcast_results.insert(proposer_id.clone(), value);
let set_agreement_input = |agreement: &mut Agreement<N>| {
if agreement.accepts_input() {
agreement.handle_input(true)
let set_binary_agreement_input = |ba: &mut BinaryAgreement<N>| {
if ba.accepts_input() {
ba.handle_input(true)
} else {
Ok(agreement::Step::default())
Ok(binary_agreement::Step::default())
}
};
step.extend(self.process_agreement(proposer_id, set_agreement_input)?);
step.extend(self.process_binary_agreement(proposer_id, set_binary_agreement_input)?);
Ok(step)
}
/// Callback to be invoked on receipt of the decision value of the Agreement
/// Callback to be invoked on receipt of the decision value of the Binary Agreement
/// instance `id`.
fn process_agreement<F>(&mut self, proposer_id: &N, f: F) -> Result<Step<N>>
fn process_binary_agreement<F>(&mut self, proposer_id: &N, f: F) -> Result<Step<N>>
where
F: FnOnce(&mut Agreement<N>) -> result::Result<agreement::Step<N>, agreement::Error>,
F: FnOnce(&mut BinaryAgreement<N>) -> binary_agreement::Result<binary_agreement::Step<N>>,
{
let mut step = Step::default();
let value = {
let agreement = self
.agreement_instances
let binary_agreement = self
.ba_instances
.get_mut(proposer_id)
.ok_or(Error::NoSuchAgreementInstance)?;
if agreement.terminated() {
.ok_or(Error::NoSuchBinaryAgreementInstance)?;
if binary_agreement.terminated() {
return Ok(step);
}
let to_msg = |a_msg| Message::Agreement(proposer_id.clone(), a_msg);
let to_msg = |a_msg| Message::BinaryAgreement(proposer_id.clone(), a_msg);
let output = step.extend_with(
f(agreement).map_err(Error::ProcessAgreementAgreement0)?,
f(binary_agreement).map_err(Error::ProcessBinaryAgreement0)?,
to_msg,
);
if let Some(output) = output.into_iter().next() {
@ -255,69 +257,68 @@ impl<N: NodeIdT + Rand> Subset<N> {
return Ok(step);
}
};
if self
.agreement_results
.insert(proposer_id.clone(), value)
.is_some()
{
return Err(Error::MultipleAgreementResults);
if self.ba_results.insert(proposer_id.clone(), value).is_some() {
return Err(Error::MultipleBinaryAgreementResults);
}
debug!(
"{:?} Updated Agreement results: {:?}",
"{:?} Updated Binary Agreement results: {:?}",
self.netinfo.our_id(),
self.agreement_results
self.ba_results
);
if value && self.count_true() == self.netinfo.num_correct() {
// Upon delivery of value 1 from at least N f instances of BA, provide
// input 0 to each instance of BA that has not yet been provided input.
for (id, agreement) in &mut self.agreement_instances {
if agreement.accepts_input() {
let to_msg = |a_msg| Message::Agreement(id.clone(), a_msg);
for (id, binary_agreement) in &mut self.ba_instances {
if binary_agreement.accepts_input() {
let to_msg = |a_msg| Message::BinaryAgreement(id.clone(), a_msg);
for output in step.extend_with(
agreement
binary_agreement
.handle_input(false)
.map_err(Error::ProcessAgreementAgreement1)?,
.map_err(Error::ProcessBinaryAgreement1)?,
to_msg,
) {
if self.agreement_results.insert(id.clone(), output).is_some() {
return Err(Error::MultipleAgreementResults);
if self.ba_results.insert(id.clone(), output).is_some() {
return Err(Error::MultipleBinaryAgreementResults);
}
}
}
}
}
step.output.extend(self.try_agreement_completion());
step.output.extend(self.try_binary_agreement_completion());
Ok(step)
}
/// Returns the number of agreement instances that have decided "yes".
/// Returns the number of Binary Agreement instances that have decided "yes".
fn count_true(&self) -> usize {
self.agreement_results.values().filter(|v| **v).count()
self.ba_results.values().filter(|v| **v).count()
}
fn try_agreement_completion(&mut self) -> Option<BTreeMap<N, ProposedValue>> {
fn try_binary_agreement_completion(&mut self) -> Option<BTreeMap<N, ProposedValue>> {
if self.decided || self.count_true() < self.netinfo.num_correct() {
return None;
}
// Once all instances of BA have completed, let C ⊂ [1..N] be
// the indexes of each BA that delivered 1. Wait for the output
// v_j for each RBC_j such that j∈C. Finally output j∈C v_j.
if self.agreement_results.len() < self.netinfo.num_nodes() {
if self.ba_results.len() < self.netinfo.num_nodes() {
return None;
}
debug!(
"{:?} All Agreement instances have terminated",
"{:?} All Binary Agreement instances have terminated",
self.netinfo.our_id()
);
// All instances of Agreement that delivered `true` (or "1" in the paper).
// All instances of BinaryAgreement that delivered `true` (or "1" in the paper).
let delivered_1: BTreeSet<&N> = self
.agreement_results
.ba_results
.iter()
.filter(|(_, v)| **v)
.map(|(k, _)| k)
.collect();
debug!("Agreement instances that delivered 1: {:?}", delivered_1);
debug!(
"Binary Agreement instances that delivered 1: {:?}",
delivered_1
);
// Results of Broadcast instances in `delivered_1`
let broadcast_results: BTreeMap<N, ProposedValue> = self
@ -328,7 +329,10 @@ impl<N: NodeIdT + Rand> Subset<N> {
.collect();
if delivered_1.len() == broadcast_results.len() {
debug!("{:?} Agreement instances completed:", self.netinfo.our_id());
debug!(
"{:?} Binary Agreement instances completed:",
self.netinfo.our_id()
);
for (id, result) in &broadcast_results {
debug!(" {:?} → {:?}", id, HexBytes(&result));
}

View File

@ -1,7 +1,7 @@
#![deny(unused_must_use)]
//! Tests of the Binary Byzantine Agreement protocol. Only one proposer instance
//! Tests of the Binary Agreement protocol. Only one proposer instance
//! is tested. Each of the nodes in the simulated network run only one instance
//! of Agreement. This way we only test correctness of the protocol and not
//! of Binary Agreement. This way we only test correctness of the protocol and not
//! message dispatch between multiple proposers.
//!
//! There are three properties that are tested:
@ -33,13 +33,13 @@ use std::sync::Arc;
use rand::Rng;
use hbbft::agreement::Agreement;
use hbbft::binary_agreement::BinaryAgreement;
use hbbft::messaging::NetworkInfo;
use network::{Adversary, MessageScheduler, NodeId, SilentAdversary, TestNetwork, TestNode};
fn test_agreement<A: Adversary<Agreement<NodeId>>>(
mut network: TestNetwork<A, Agreement<NodeId>>,
fn test_binary_agreement<A: Adversary<BinaryAgreement<NodeId>>>(
mut network: TestNetwork<A, BinaryAgreement<NodeId>>,
input: Option<bool>,
) {
let ids: Vec<NodeId> = network.nodes.keys().cloned().collect();
@ -64,9 +64,9 @@ fn test_agreement<A: Adversary<Agreement<NodeId>>>(
assert!(expected.iter().eq(network.observer.outputs()));
}
fn test_agreement_different_sizes<A, F>(new_adversary: F)
fn test_binary_agreement_different_sizes<A, F>(new_adversary: F)
where
A: Adversary<Agreement<NodeId>>,
A: Adversary<BinaryAgreement<NodeId>>,
F: Fn(usize, usize) -> A,
{
// This returns an error in all but the first test.
@ -85,12 +85,11 @@ where
num_good_nodes, num_faulty_nodes, input
);
let adversary = |_| new_adversary(num_good_nodes, num_faulty_nodes);
let new_agreement = |netinfo: Arc<NetworkInfo<NodeId>>| {
Agreement::new(netinfo, 0, NodeId(0)).expect("agreement instance")
let new_ba = |netinfo: Arc<NetworkInfo<NodeId>>| {
BinaryAgreement::new(netinfo, 0, NodeId(0)).expect("Binary Agreement instance")
};
let network =
TestNetwork::new(num_good_nodes, num_faulty_nodes, adversary, new_agreement);
test_agreement(network, input);
let network = TestNetwork::new(num_good_nodes, num_faulty_nodes, adversary, new_ba);
test_binary_agreement(network, input);
info!(
"Test success: {} good nodes and {} faulty nodes, input: {:?}",
num_good_nodes, num_faulty_nodes, input
@ -100,13 +99,13 @@ where
}
#[test]
fn test_agreement_random_silent() {
fn test_binary_agreement_random_silent() {
let new_adversary = |_: usize, _: usize| SilentAdversary::new(MessageScheduler::Random);
test_agreement_different_sizes(new_adversary);
test_binary_agreement_different_sizes(new_adversary);
}
#[test]
fn test_agreement_first_silent() {
fn test_binary_agreement_first_silent() {
let new_adversary = |_: usize, _: usize| SilentAdversary::new(MessageScheduler::First);
test_agreement_different_sizes(new_adversary);
test_binary_agreement_different_sizes(new_adversary);
}