Rename CommonSubset to Subset.

This commit is contained in:
Andreas Fackler 2018-08-14 15:06:51 +02:00 committed by Nick Sanders
parent 6bcf365cf8
commit d93ea7b561
9 changed files with 62 additions and 66 deletions

View File

@ -31,7 +31,7 @@ In addition to **validators**, the algorithms support **observers**: These don't
- [x] **[Queueing Honey Badger](https://github.com/poanetwork/hbbft/blob/master/src/queueing_honey_badger.rs):** Works exactly like Dynamic Honey Badger, but includes a built in transaction queue.
- [x] **[Subset](https://github.com/poanetwork/hbbft/blob/master/src/common_subset.rs):** Each node inputs data. The nodes agree on a subset of suggested data.
- [x] **[Subset](https://github.com/poanetwork/hbbft/blob/master/src/subset.rs):** Each node inputs data. The nodes agree on a subset of suggested data.
- [x] **[Broadcast](https://github.com/poanetwork/hbbft/blob/master/src/broadcast.rs):** A proposer node inputs data and every node receives this output.

View File

@ -9,9 +9,9 @@ use rand::Rand;
use serde::{Deserialize, Serialize};
use super::{Batch, ErrorKind, MessageContent, Result, Step};
use common_subset::{self as cs, CommonSubset};
use fault_log::{Fault, FaultKind, FaultLog};
use messaging::{DistAlgorithm, NetworkInfo};
use subset::{self as cs, Subset};
use threshold_decryption::{self as td, ThresholdDecryption};
use traits::{Contribution, NodeUidT};
@ -62,7 +62,7 @@ where
#[derive(Debug)]
enum SubsetState<N: Rand> {
/// The algorithm is ongoing: the set of accepted contributions is still undecided.
Ongoing(CommonSubset<N>),
Ongoing(Subset<N>),
/// The algorithm is complete. This contains the set of accepted proposers.
Complete(BTreeSet<N>),
}
@ -76,7 +76,7 @@ where
match self {
SubsetState::Ongoing(ref mut cs) => cs.input(proposal),
SubsetState::Complete(_) => return Ok(cs::Step::default()),
}.map_err(|err| ErrorKind::InputCommonSubset(err).into())
}.map_err(|err| ErrorKind::InputSubset(err).into())
}
/// Handles a message in the Subset instance, unless it has already completed.
@ -84,7 +84,7 @@ where
match self {
SubsetState::Ongoing(ref mut cs) => cs.handle_message(sender_id, msg),
SubsetState::Complete(_) => return Ok(cs::Step::default()),
}.map_err(|err| ErrorKind::HandleCommonSubsetMessage(err).into())
}.map_err(|err| ErrorKind::HandleSubsetMessage(err).into())
}
/// Returns the number of contributions that we have already received or, after completion, how
@ -124,9 +124,9 @@ where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
N: NodeUidT + Rand,
{
/// Creates a new `CommonSubset` instance.
/// Creates a new `Subset` instance.
pub fn new(netinfo: Arc<NetworkInfo<N>>, epoch: u64) -> Result<Self> {
let cs = CommonSubset::new(netinfo.clone(), epoch).map_err(ErrorKind::CreateCommonSubset)?;
let cs = Subset::new(netinfo.clone(), epoch).map_err(ErrorKind::CreateSubset)?;
Ok(EpochState {
epoch,
netinfo,
@ -149,14 +149,14 @@ where
self.subset.received_proposals()
}
/// Handles a message for the Common Subset or a Threshold Decryption instance.
/// Handles a message for the Subset or a Threshold Decryption instance.
pub fn handle_message_content(
&mut self,
sender_id: &N,
content: MessageContent<N>,
) -> Result<Step<C, N>> {
match content {
MessageContent::CommonSubset(cs_msg) => {
MessageContent::Subset(cs_msg) => {
let cs_step = self.subset.handle_message(sender_id, cs_msg)?;
self.process_subset(cs_step)
}
@ -219,14 +219,14 @@ where
fn process_subset(&mut self, cs_step: cs::Step<N>) -> Result<Step<C, N>> {
let mut step = Step::default();
let mut cs_outputs = step.extend_with(cs_step, |cs_msg| {
MessageContent::CommonSubset(cs_msg).with_epoch(self.epoch)
MessageContent::Subset(cs_msg).with_epoch(self.epoch)
});
if let Some(cs_output) = cs_outputs.pop_front() {
self.subset = SubsetState::Complete(cs_output.keys().cloned().collect());
step.extend(self.send_decryption_shares(cs_output)?);
}
if !cs_outputs.is_empty() {
error!("Multiple outputs from a single Common Subset instance.");
error!("Multiple outputs from a single Subset instance.");
}
Ok(step)
}

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
use bincode;
use failure::{Backtrace, Context, Fail};
use common_subset;
use subset;
use threshold_decryption;
/// Honey badger error variants.
@ -11,15 +11,12 @@ use threshold_decryption;
pub enum ErrorKind {
#[fail(display = "ProposeBincode error: {}", _0)]
ProposeBincode(bincode::ErrorKind),
#[fail(display = "Failed to instantiate Common Subset: {}", _0)]
CreateCommonSubset(common_subset::Error),
#[fail(
display = "Failed to input contribution to Common Subset: {}",
_0
)]
InputCommonSubset(common_subset::Error),
#[fail(display = "Failed to handle Common Subset message: {}", _0)]
HandleCommonSubsetMessage(common_subset::Error),
#[fail(display = "Failed to instantiate Subset: {}", _0)]
CreateSubset(subset::Error),
#[fail(display = "Failed to input contribution to Subset: {}", _0)]
InputSubset(subset::Error),
#[fail(display = "Failed to handle Subset message: {}", _0)]
HandleSubsetMessage(subset::Error),
#[fail(display = "Threshold decryption error: {}", _0)]
ThresholdDecryption(threshold_decryption::Error),
#[fail(display = "Unknown sender")]

View File

@ -22,7 +22,7 @@ pub struct HoneyBadger<C, N: Rand> {
pub(super) has_input: bool,
/// The subalgorithms for ongoing epochs.
pub(super) epochs: BTreeMap<u64, EpochState<C, N>>,
/// The maximum number of `CommonSubset` instances that we run simultaneously.
/// The maximum number of `Subset` instances that we run simultaneously.
pub(super) max_future_epochs: u64,
/// Messages for future epochs that couldn't be handled yet.
pub(super) incoming_queue: BTreeMap<u64, Vec<(N, MessageContent<N>)>>,

View File

@ -1,13 +1,13 @@
use rand::Rand;
use common_subset;
use subset;
use threshold_decryption;
/// The content of a `HoneyBadger` message. It should be further annotated with an epoch.
#[derive(Clone, Debug, Deserialize, Rand, Serialize)]
pub enum MessageContent<N: Rand> {
/// A message belonging to the common subset algorithm in the given epoch.
CommonSubset(common_subset::Message<N>),
/// A message belonging to the subset algorithm in the given epoch.
Subset(subset::Message<N>),
/// A decrypted share of the output of `proposer_id`.
DecryptionShare {
proposer_id: N,

View File

@ -11,15 +11,15 @@
//! ## How it works
//!
//! In every epoch, every validator encrypts their contribution and proposes it to the others.
//! A `CommonSubset` instance determines which proposals are accepted and will be part of the new
//! A `Subset` instance determines which proposals are accepted and will be part of the new
//! batch. Using threshold encryption, the nodes collaboratively decrypt all accepted
//! contributions. Invalid contributions (that e.g. cannot be deserialized) are discarded - their
//! proposers must be faulty -, and the remaining ones are output as the new batch. The next epoch
//! begins as soon as the validators propose new contributions again.
//!
//! So it is essentially an endlessly repeating `CommonSubset`, but with the proposed values
//! So it is essentially an endlessly repeating `Subset`, but with the proposed values
//! encrypted. The encryption makes it harder for an attacker to try and censor a particular value
//! by influencing the set of proposals that make it into the common subset, because they don't
//! by influencing the set of proposals that make it into the subset, because they don't
//! know the decrypted values before the subset is determined.
mod batch;

View File

@ -59,13 +59,13 @@
//! number of _transactions_, and output a sequence of batches. Each batch contains a set of
//! transactions that were input by the nodes, and usually multiple transactions from each node.
//!
//! [**Common Subset**](common_subset/index.html)
//! [**Subset**](subset/index.html)
//!
//! Each node inputs one item. The output is a set of at least _N - f_ nodes' IDs, together with
//! their items, and will be the same in every correct node.
//!
//! This is the main building block of Honey Badger: In each epoch, every node proposes a number of
//! transactions. Using the Common Subset protocol, they agree on at least _N - f_ of those
//! transactions. Using the Subset protocol, they agree on at least _N - f_ of those
//! proposals. The batch contains the union of these sets of transactions.
//!
//! [**Reliable Broadcast**](broadcast/index.html)
@ -74,7 +74,7 @@
//! if the proposer is faulty it is guaranteed that either none of the correct nodes output
//! anything, or all of them have the same output.
//!
//! This is used in Common Subset to send each node's proposal to the other nodes.
//! This is used in Subset to send each node's proposal to the other nodes.
//!
//! [**Binary Agreement**](agreement/index.html)
//!
@ -125,13 +125,13 @@ extern crate tiny_keccak;
pub mod agreement;
pub mod broadcast;
pub mod coin;
pub mod common_subset;
pub mod dynamic_honey_badger;
pub mod fault_log;
mod fmt;
pub mod honey_badger;
pub mod messaging;
pub mod queueing_honey_badger;
pub mod subset;
pub mod sync_key_gen;
pub mod threshold_decryption;
pub mod transaction_queue;

View File

@ -1,10 +1,10 @@
//! # Asynchronous Common Subset algorithm.
//! # Asynchronous Subset algorithm.
//!
//! The Asynchronous Common Subset protocol assumes a network of _N_ nodes that send signed
//! The Asynchronous Subset protocol assumes a network of _N_ nodes that send signed
//! messages to each other, with at most _f_ of them malicious, where _3 f < N_. Handling the
//! networking and signing is the responsibility of the user: only when a message has been
//! verified to be "from node i" (e.g. using cryptographic signatures), it can be handed to the
//! `CommonSubset` instance.
//! `Subset` instance.
//!
//! Each node proposes an element for inclusion. Under the above conditions, the protocol
//! guarantees that all correct nodes output the same set, consisting of at least _N - f_ of the
@ -12,15 +12,15 @@
//!
//! ## How it works
//!
//! * `CommonSubset` instantiates one `Broadcast` algorithm for each of the participating nodes.
//! * `Subset` instantiates one `Broadcast` algorithm for each of the participating nodes.
//! At least _N - f_ of these - the ones whose proposer is not faulty - will eventually output
//! 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 common set. Whenever an element is
//! 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
//! remaining ones, where we haven't provided input yet.
//! * Once all `Agreement` instances have decided, `CommonSubset` returns the set of all proposed
//! * Once all `Agreement` instances have decided, `Subset` returns the set of all proposed
//! values for which the decision was "yes".
use std::collections::{BTreeMap, BTreeSet};
@ -34,7 +34,7 @@ use messaging::{self, DistAlgorithm, NetworkInfo};
use rand::Rand;
use traits::NodeUidT;
/// A common subset error.
/// A subset error.
#[derive(Clone, PartialEq, Debug, Fail)]
pub enum Error {
#[fail(display = "NewAgreement error: {}", _0)]
@ -55,13 +55,13 @@ pub enum Error {
NoSuchBroadcastInstance,
}
/// A common subset result.
/// A subset result.
pub type Result<T> = ::std::result::Result<T, Error>;
// TODO: Make this a generic argument of `CommonSubset`.
// TODO: Make this a generic argument of `Subset`.
type ProposedValue = Vec<u8>;
/// Message from Common Subset to remote nodes.
/// Message from Subset to remote nodes.
#[derive(Serialize, Deserialize, Clone, Debug, Rand)]
pub enum Message<N: Rand> {
/// A message for the broadcast algorithm concerning the set element proposed by the given node.
@ -71,9 +71,9 @@ pub enum Message<N: Rand> {
Agreement(N, agreement::Message),
}
/// Asynchronous Common Subset algorithm instance
/// Asynchronous Subset algorithm instance
#[derive(Debug)]
pub struct CommonSubset<N: Rand> {
pub struct Subset<N: Rand> {
/// Shared network information.
netinfo: Arc<NetworkInfo<N>>,
broadcast_instances: BTreeMap<N, Broadcast<N>>,
@ -84,9 +84,9 @@ pub struct CommonSubset<N: Rand> {
decided: bool,
}
pub type Step<N> = messaging::Step<CommonSubset<N>>;
pub type Step<N> = messaging::Step<Subset<N>>;
impl<N: NodeUidT + Rand> DistAlgorithm for CommonSubset<N> {
impl<N: NodeUidT + Rand> DistAlgorithm for Subset<N> {
type NodeUid = N;
type Input = ProposedValue;
type Output = BTreeMap<N, ProposedValue>;
@ -122,7 +122,7 @@ impl<N: NodeUidT + Rand> DistAlgorithm for CommonSubset<N> {
}
}
impl<N: NodeUidT + Rand> CommonSubset<N> {
impl<N: NodeUidT + Rand> Subset<N> {
pub fn new(netinfo: Arc<NetworkInfo<N>>, session_id: u64) -> Result<Self> {
// Create all broadcast instances.
let mut broadcast_instances: BTreeMap<N, Broadcast<N>> = BTreeMap::new();
@ -143,7 +143,7 @@ impl<N: NodeUidT + Rand> CommonSubset<N> {
);
}
Ok(CommonSubset {
Ok(Subset {
netinfo,
broadcast_instances,
agreement_instances,
@ -153,7 +153,7 @@ impl<N: NodeUidT + Rand> CommonSubset<N> {
})
}
/// Common Subset input message handler. It receives a value for broadcast
/// Subset input message handler. It receives a value for broadcast
/// and redirects it to the corresponding broadcast instance.
pub fn send_proposed_value(&mut self, value: ProposedValue) -> Result<Step<N>> {
if !self.netinfo.is_validator() {

View File

@ -1,5 +1,5 @@
#![deny(unused_must_use)]
//! Integration tests of the Asynchronous Common Subset protocol.
//! Integration tests of the Asynchronous Subset protocol.
extern crate env_logger;
extern crate hbbft;
@ -19,15 +19,15 @@ use std::collections::{BTreeMap, BTreeSet};
use std::iter::once;
use std::sync::Arc;
use hbbft::common_subset::CommonSubset;
use hbbft::messaging::NetworkInfo;
use hbbft::subset::Subset;
use network::{Adversary, MessageScheduler, NodeUid, SilentAdversary, TestNetwork, TestNode};
type ProposedValue = Vec<u8>;
fn test_common_subset<A: Adversary<CommonSubset<NodeUid>>>(
mut network: TestNetwork<A, CommonSubset<NodeUid>>,
fn test_subset<A: Adversary<Subset<NodeUid>>>(
mut network: TestNetwork<A, Subset<NodeUid>>,
inputs: &BTreeMap<NodeUid, ProposedValue>,
) {
let ids: Vec<NodeUid> = network.nodes.keys().cloned().collect();
@ -54,7 +54,7 @@ fn test_common_subset<A: Adversary<CommonSubset<NodeUid>>>(
}
let output = expected.unwrap();
assert!(once(&output).eq(network.observer.outputs()));
// The Common Subset algorithm guarantees that more than two thirds of the proposed elements
// The Subset algorithm guarantees that more than two thirds of the proposed elements
// are in the set.
assert!(output.len() * 3 > inputs.len() * 2);
// Verify that the set's elements match the proposed values.
@ -67,22 +67,21 @@ fn new_network<A, F>(
good_num: usize,
bad_num: usize,
adversary: F,
) -> TestNetwork<A, CommonSubset<NodeUid>>
) -> TestNetwork<A, Subset<NodeUid>>
where
A: Adversary<CommonSubset<NodeUid>>,
A: Adversary<Subset<NodeUid>>,
F: Fn(BTreeMap<NodeUid, Arc<NetworkInfo<NodeUid>>>) -> A,
{
// This returns an error in all but the first test.
let _ = env_logger::try_init();
let new_common_subset = |netinfo: Arc<NetworkInfo<NodeUid>>| {
CommonSubset::new(netinfo, 0).expect("new Common Subset instance")
};
TestNetwork::new(good_num, bad_num, adversary, new_common_subset)
let new_subset =
|netinfo: Arc<NetworkInfo<NodeUid>>| Subset::new(netinfo, 0).expect("new Subset instance");
TestNetwork::new(good_num, bad_num, adversary, new_subset)
}
#[test]
fn test_common_subset_3_out_of_4_nodes_propose() {
fn test_subset_3_out_of_4_nodes_propose() {
let proposed_value = Vec::from("Fake news");
let proposing_ids: BTreeSet<NodeUid> = (0..3).map(NodeUid).collect();
let proposals: BTreeMap<NodeUid, ProposedValue> = proposing_ids
@ -91,11 +90,11 @@ fn test_common_subset_3_out_of_4_nodes_propose() {
.collect();
let adversary = |_| SilentAdversary::new(MessageScheduler::First);
let network = new_network(3, 1, adversary);
test_common_subset(network, &proposals);
test_subset(network, &proposals);
}
#[test]
fn test_common_subset_5_nodes_different_proposed_values() {
fn test_subset_5_nodes_different_proposed_values() {
let proposed_values = vec![
Vec::from("Alpha"),
Vec::from("Bravo"),
@ -110,14 +109,14 @@ fn test_common_subset_5_nodes_different_proposed_values() {
.collect();
let adversary = |_| SilentAdversary::new(MessageScheduler::Random);
let network = new_network(5, 0, adversary);
test_common_subset(network, &proposals);
test_subset(network, &proposals);
}
#[test]
fn test_common_subset_1_node() {
fn test_subset_1_node() {
let proposals: BTreeMap<NodeUid, ProposedValue> =
once((NodeUid(0), Vec::from("Node 0 is the greatest!"))).collect();
let adversary = |_| SilentAdversary::new(MessageScheduler::Random);
let network = new_network(1, 0, adversary);
test_common_subset(network, &proposals);
test_subset(network, &proposals);
}