mirror of https://github.com/poanetwork/hbbft.git
Rename CommonSubset to Subset.
This commit is contained in:
parent
6bcf365cf8
commit
d93ea7b561
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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>)>>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue