merge from upstream

This commit is contained in:
Logan Collins 2018-10-24 15:55:44 -05:00
commit 92a32d827d
19 changed files with 141 additions and 125 deletions

View File

@ -22,6 +22,7 @@ travis-ci = { repository = "poanetwork/hbbft" }
[dependencies]
bincode = "1.0.0"
byteorder = "1.2.3"
derivative = "1.0.1"
env_logger = "0.5.10"
failure = "0.1"
hex_fmt = "0.2"

View File

@ -4,7 +4,7 @@
use bincode;
use crossbeam;
use crossbeam_channel::{Receiver, Sender};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use std::io;
use std::net::TcpStream;
@ -34,7 +34,7 @@ pub struct CommsTask<'a, M: 'a> {
pub node_index: usize,
}
impl<'a, M: Serialize + for<'de> Deserialize<'de> + Send + 'a> CommsTask<'a, M> {
impl<'a, M: Serialize + DeserializeOwned + Send + 'a> CommsTask<'a, M> {
pub fn new(
tx: &'a Sender<SourcedMessage<M, usize>>,
rx: &'a Receiver<M>,

View File

@ -77,7 +77,7 @@ impl<N: NodeIdT> DistAlgorithm for BinaryAgreement<N> {
type Error = Error;
fn handle_input(&mut self, input: Self::Input) -> Result<Step<N>> {
self.handle_input(input)
self.propose(input)
}
/// Receive input from a remote node.
@ -120,9 +120,14 @@ impl<N: NodeIdT> BinaryAgreement<N> {
})
}
/// Sets the input value for Binary Agreement.
pub fn handle_input(&mut self, input: bool) -> Result<Step<N>> {
if !self.can_input() {
/// Proposes a boolean value for Binary Agreement.
///
/// If more than two thirds of validators propose the same value, that will eventually be
/// output. Otherwise either output is possible.
///
/// Note that if `can_propose` returns `false`, it is already too late to affect the outcome.
pub fn propose(&mut self, input: bool) -> Result<Step<N>> {
if !self.can_propose() {
return Ok(Step::default());
}
// Set the initial estimated value to the input value.
@ -132,7 +137,9 @@ impl<N: NodeIdT> BinaryAgreement<N> {
self.handle_sbvb_step(sbvb_step)
}
/// Handles an incoming message.
/// Handles a message received from `sender_id`.
///
/// This must be called with every message we receive from another node.
pub fn handle_message(&mut self, sender_id: &N, msg: Message) -> Result<Step<N>> {
let Message { epoch, content } = msg;
if self.decision.is_some() || (epoch < self.epoch && content.can_expire()) {
@ -150,7 +157,7 @@ impl<N: NodeIdT> BinaryAgreement<N> {
/// Whether we can still input a value. It is not an error to input if this returns `false`,
/// but it will have no effect on the outcome.
pub fn can_input(&self) -> bool {
pub fn can_propose(&self) -> bool {
self.epoch == 0 && self.estimated.is_none()
}
@ -365,7 +372,7 @@ impl<N: NodeIdT> BinaryAgreement<N> {
// Invoke the coin.
let ts_step = match self.coin_state {
CoinState::Decided(_) => return Ok(Step::default()), // Coin has already decided.
CoinState::InProgress(ref mut ts) => ts.handle_input(()).map_err(Error::InvokeCoin)?,
CoinState::InProgress(ref mut ts) => ts.sign().map_err(Error::InvokeCoin)?,
};
let mut step = self.on_coin_step(ts_step)?;
step.extend(self.try_update_epoch()?);

View File

@ -21,6 +21,8 @@ pub struct Broadcast<N> {
proposer_id: N,
data_shard_num: usize,
coding: Coding,
/// If we are the proposer: whether we have already sent the `Value` messages with the shards.
value_sent: bool,
/// Whether we have already multicast `Echo`.
echo_sent: bool,
/// Whether we have already multicast `Ready`.
@ -74,6 +76,7 @@ impl<N: NodeIdT> Broadcast<N> {
proposer_id,
data_shard_num,
coding,
value_sent: false,
echo_sent: false,
ready_sent: false,
decided: false,
@ -87,6 +90,10 @@ impl<N: NodeIdT> Broadcast<N> {
if *self.netinfo.our_id() != self.proposer_id {
return Err(Error::InstanceCannotPropose);
}
if self.value_sent {
return Err(Error::MultipleInputs);
}
self.value_sent = true;
// Split the value into chunks/shards, encode them with erasure codes.
// Assemble a Merkle tree from data and parity shards. Take all proofs
// from this tree and send them, each to its own node.
@ -96,7 +103,9 @@ impl<N: NodeIdT> Broadcast<N> {
Ok(step)
}
/// Handles an incoming message.
/// Handles a message received from `sender_id`.
///
/// 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) {
return Err(Error::UnknownSender);
@ -191,9 +200,11 @@ impl<N: NodeIdT> Broadcast<N> {
}
if self.echo_sent {
info!("Node {:?} received multiple Values.", self.netinfo.our_id());
// TODO: should receiving two Values from a node be considered
// a fault? If so, return a `Fault` here. For now, ignore.
return Ok(Step::default());
if self.echos.get(self.our_id()) == Some(&p) {
return Ok(Step::default());
} else {
return Ok(Fault::new(sender_id.clone(), FaultKind::MultipleValues).into());
}
}
// If the proof is invalid, log the faulty node behavior and ignore.

View File

@ -16,6 +16,8 @@ pub enum Error {
CodingReconstructShardsTrivialReedSolomon(#[cause] rse::Error),
#[fail(display = "Instance cannot propose")]
InstanceCannotPropose,
#[fail(display = "Multiple inputs received")]
MultipleInputs,
#[fail(display = "Not implemented")]
NotImplemented,
#[fail(display = "Proof construction failed")]

View File

@ -1,8 +1,6 @@
use std::collections::BTreeMap;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
use super::{ChangeState, JoinPlan};
use {NetworkInfo, NodeIdT};
@ -83,10 +81,7 @@ impl<C, N: NodeIdT> Batch<C, N> {
/// Returns the `JoinPlan` to be sent to new observer nodes, if it is possible to join in the
/// next epoch.
pub fn join_plan(&self) -> Option<JoinPlan<N>>
where
N: Serialize + for<'r> Deserialize<'r>,
{
pub fn join_plan(&self) -> Option<JoinPlan<N>> {
if self.change == ChangeState::None {
return None;
}

View File

@ -5,7 +5,7 @@ use std::sync::Arc;
use crypto::{SecretKey, SecretKeySet, SecretKeyShare};
use rand::{self, Rand, Rng};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use super::{Change, ChangeState, DynamicHoneyBadger, JoinPlan, Result, Step, VoteCounter};
use honey_badger::{HoneyBadger, SubsetHandlingStrategy};
@ -46,8 +46,8 @@ impl<C, N> Default for DynamicHoneyBadgerBuilder<C, N> {
impl<C, N> DynamicHoneyBadgerBuilder<C, N>
where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
C: Contribution + Serialize + DeserializeOwned,
N: NodeIdT + Serialize + DeserializeOwned + Rand,
{
/// Returns a new `DynamicHoneyBadgerBuilder` configured to use the node IDs and cryptographic
/// keys specified by `netinfo`.

View File

@ -1,11 +1,11 @@
use std::collections::BTreeMap;
use std::mem;
use std::sync::Arc;
use std::{fmt, mem};
use bincode;
use crypto::Signature;
use rand::{self, Rand};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use super::votes::{SignedVote, VoteCounter};
use super::{
@ -17,10 +17,12 @@ use fault_log::{Fault, FaultKind, FaultLog};
use honey_badger::{self, HoneyBadger, Message as HbMessage};
use sync_key_gen::{Ack, Part, PartOutcome, SyncKeyGen};
use threshold_decryption::EncryptionSchedule;
use util::SubRng;
use util::{self, SubRng};
use {Contribution, DistAlgorithm, NetworkInfo, NodeIdT, Target};
/// A Honey Badger instance that can handle adding and removing nodes.
#[derive(Derivative)]
#[derivative(Debug)]
pub struct DynamicHoneyBadger<C, N: Rand> {
/// Shared network data.
pub(super) netinfo: NetworkInfo<N>,
@ -40,33 +42,14 @@ pub struct DynamicHoneyBadger<C, N: Rand> {
pub(super) incoming_queue: Vec<(N, Message<N>)>,
/// A random number generator used for secret key generation.
// Boxed to avoid overloading the algorithm's type with more generics.
#[derivative(Debug(format_with = "util::fmt_rng"))]
pub(super) rng: Box<dyn rand::Rng + Send + Sync>,
}
impl<C, N> fmt::Debug for DynamicHoneyBadger<C, N>
where
C: fmt::Debug,
N: Rand + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("DynamicHoneyBadger")
.field("netinfo", &self.netinfo)
.field("max_future_epochs", &self.max_future_epochs)
.field("start_epoch", &self.start_epoch)
.field("vote_counter", &self.vote_counter)
.field("key_gen_msg_buffer", &self.key_gen_msg_buffer)
.field("honey_badger", &self.honey_badger)
.field("key_gen_state", &self.key_gen_state)
.field("incoming_queue", &self.incoming_queue)
.field("rng", &"<RNG>")
.finish()
}
}
impl<C, N> DistAlgorithm for DynamicHoneyBadger<C, N>
where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
C: Contribution + Serialize + DeserializeOwned,
N: NodeIdT + Serialize + DeserializeOwned + Rand,
{
type NodeId = N;
type Input = Input<C, N>;
@ -98,8 +81,8 @@ where
impl<C, N> DynamicHoneyBadger<C, N>
where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
C: Contribution + Serialize + DeserializeOwned,
N: NodeIdT + Serialize + DeserializeOwned + Rand,
{
/// Returns a new `DynamicHoneyBadgerBuilder`.
pub fn builder() -> DynamicHoneyBadgerBuilder<C, N> {
@ -112,6 +95,11 @@ where
}
/// Proposes a contribution in the current epoch.
///
/// Returns an error if we already made a proposal in this epoch.
///
/// If we are the only validator, this will immediately output a batch, containing our
/// proposal.
pub fn propose(&mut self, contrib: C) -> Result<Step<C, N>> {
let key_gen_messages = self
.key_gen_msg_buffer
@ -130,6 +118,9 @@ where
}
/// Casts a vote to change the set of validators.
///
/// This stores a pending vote for the change. It will be included in some future batch, and
/// once enough validators have been voted for the same change, it will take effect.
pub fn vote_for(&mut self, change: Change<N>) -> Result<Step<C, N>> {
if !self.netinfo.is_validator() {
return Ok(Step::default()); // TODO: Return an error?
@ -139,7 +130,9 @@ where
Ok(Target::All.message(msg).into())
}
/// Handles an incoming message.
/// Handles a message received from `sender_id`.
///
/// This must be called with every message we receive from another node.
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
let epoch = message.start_epoch();
if epoch < self.start_epoch {

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use bincode;
use crypto::Signature;
use serde::{Deserialize, Serialize};
use serde::Serialize;
use super::{Change, ErrorKind, Result};
use fault_log::{FaultKind, FaultLog};
@ -28,7 +28,7 @@ pub struct VoteCounter<N> {
impl<N> VoteCounter<N>
where
N: NodeIdT + Serialize + for<'r> Deserialize<'r>,
N: NodeIdT + Serialize,
{
/// Creates a new `VoteCounter` object with empty buffer and counter.
pub fn new(netinfo: Arc<NetworkInfo<N>>, era: u64) -> Self {
@ -92,7 +92,8 @@ where
})
}
// TODO: Document and return fault logs?
/// Inserts committed votes into the counter, if they have higher numbers than the existing
/// ones.
pub fn add_committed_votes<I>(
&mut self,
proposer_id: &N,

View File

@ -37,6 +37,8 @@ pub enum FaultKind {
MultipleDecryptionShares,
/// `Broadcast` received a `Value` from a node other than the proposer.
ReceivedValueFromNonProposer,
/// `Broadcast` received multiple different `Value`s from the proposer.
MultipleValues,
/// `Broadcast` recevied an Echo message containing an invalid proof.
InvalidProof,
/// `HoneyBadger` could not deserialize bytes (i.e. a serialized Batch)

View File

@ -3,7 +3,7 @@ use std::marker::PhantomData;
use std::sync::Arc;
use rand::{self, Rand, Rng};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use super::HoneyBadger;
use honey_badger::SubsetHandlingStrategy;
@ -30,7 +30,7 @@ pub struct HoneyBadgerBuilder<C, N> {
impl<C, N> HoneyBadgerBuilder<C, N>
where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
C: Contribution + Serialize + DeserializeOwned,
N: NodeIdT + Rand,
{
/// Returns a new `HoneyBadgerBuilder` configured to use the node IDs and cryptographic keys

View File

@ -9,7 +9,7 @@ use std::sync::Arc;
use bincode;
use crypto::Ciphertext;
use rand::{Rand, Rng};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use super::{Batch, ErrorKind, MessageContent, Result, Step};
use fault_log::{Fault, FaultKind, FaultLog};
@ -191,7 +191,7 @@ pub struct EpochState<C, N: Rand> {
impl<C, N> EpochState<C, N>
where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
C: Contribution + Serialize + DeserializeOwned,
N: NodeIdT + Rand,
{
/// Creates a new `Subset` instance.

View File

@ -1,20 +1,21 @@
use std::collections::btree_map::Entry;
use std::collections::BTreeMap;
use std::fmt;
use std::sync::Arc;
use bincode;
use rand::{Rand, Rng};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use super::epoch_state::EpochState;
use super::{Batch, Error, ErrorKind, HoneyBadgerBuilder, Message, MessageContent, Result};
use {Contribution, DistAlgorithm, NetworkInfo, NodeIdT};
use {util, Contribution, DistAlgorithm, NetworkInfo, NodeIdT};
pub use super::epoch_state::SubsetHandlingStrategy;
use threshold_decryption::EncryptionSchedule;
/// An instance of the Honey Badger Byzantine fault tolerant consensus algorithm.
#[derive(Derivative)]
#[derivative(Debug)]
pub struct HoneyBadger<C, N: Rand> {
/// Shared network data.
pub(super) netinfo: Arc<NetworkInfo<N>>,
@ -30,6 +31,7 @@ pub struct HoneyBadger<C, N: Rand> {
pub(super) incoming_queue: BTreeMap<u64, Vec<(N, MessageContent<N>)>>,
/// A random number generator used for secret key generation.
// Boxed to avoid overloading the algorithm's type with more generics.
#[derivative(Debug(format_with = "util::fmt_rng"))]
pub(super) rng: Box<dyn Rng + Send + Sync>,
/// Represents the optimization strategy to use for output of the `Subset` algorithm.
pub(super) subset_handling_strategy: SubsetHandlingStrategy,
@ -37,30 +39,11 @@ pub struct HoneyBadger<C, N: Rand> {
pub(crate) encryption_schedule: EncryptionSchedule,
}
impl<C, N> fmt::Debug for HoneyBadger<C, N>
where
N: Rand + fmt::Debug,
C: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("HoneyBadger")
.field("netinfo", &self.netinfo)
.field("epoch", &self.epoch)
.field("has_input", &self.has_input)
.field("epochs", &self.epochs)
.field("max_future_epochs", &self.max_future_epochs)
.field("incoming_queue", &self.incoming_queue)
.field("rng", &"<RNG>")
.field("encryption_schedule", &self.encryption_schedule)
.finish()
}
}
pub type Step<C, N> = ::Step<HoneyBadger<C, N>>;
impl<C, N> DistAlgorithm for HoneyBadger<C, N>
where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
C: Contribution + Serialize + DeserializeOwned,
N: NodeIdT + Rand,
{
type NodeId = N;
@ -88,7 +71,7 @@ where
impl<C, N> HoneyBadger<C, N>
where
C: Contribution + Serialize + for<'r> Deserialize<'r>,
C: Contribution + Serialize + DeserializeOwned,
N: NodeIdT + Rand,
{
/// Returns a new `HoneyBadgerBuilder` configured to use the node IDs and cryptographic keys
@ -97,7 +80,12 @@ where
HoneyBadgerBuilder::new(netinfo)
}
/// Proposes a new item in the current epoch.
/// Proposes a contribution in the current epoch.
///
/// Returns an error if we already made a proposal in this epoch.
///
/// If we are the only validator, this will immediately output a batch, containing our
/// proposal.
pub fn propose(&mut self, proposal: &C) -> Result<Step<C, N>> {
if !self.netinfo.is_validator() {
return Ok(Step::default());
@ -121,7 +109,9 @@ where
}
/// Handles a message received from `sender_id`.
fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
///
/// This must be called with every message we receive from another node.
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
if !self.netinfo.is_node_validator(sender_id) {
return Err(ErrorKind::UnknownSender.into());
}

View File

@ -112,13 +112,13 @@
//! `Deserialize` traits so they can be easily serialized or included as part of other serializable
//! types.
// TODO: Remove this once https://github.com/rust-lang-nursery/error-chain/issues/245 is resolved.
#![allow(renamed_and_removed_lints)]
// We put algorithm structs in `src/algorithm/algorithm.rs`.
#![cfg_attr(feature = "cargo-clippy", allow(module_inception))]
extern crate bincode;
extern crate byteorder;
#[macro_use(Derivative)]
extern crate derivative;
#[macro_use]
extern crate failure;
extern crate hex_fmt;

View File

@ -28,11 +28,11 @@ use std::{cmp, iter};
use failure::{Backtrace, Context, Fail};
use rand::{Rand, Rng};
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Serialize};
use dynamic_honey_badger::{self, Batch as DhbBatch, DynamicHoneyBadger, Message};
use transaction_queue::TransactionQueue;
use {Contribution, DistAlgorithm, NodeIdT};
use {util, Contribution, DistAlgorithm, NodeIdT};
pub use dynamic_honey_badger::{Change, ChangeState, Input, NodeChange};
@ -107,8 +107,8 @@ pub type QueueingHoneyBadgerWithStep<T, N, Q> = (QueueingHoneyBadger<T, N, Q>, S
impl<T, N, Q> QueueingHoneyBadgerBuilder<T, N, Q>
where
T: Contribution + Serialize + for<'r> Deserialize<'r> + Clone,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
T: Contribution + Serialize + DeserializeOwned + Clone,
N: NodeIdT + Serialize + DeserializeOwned + Rand,
Q: TransactionQueue<T>,
{
/// Returns a new `QueueingHoneyBadgerBuilder` configured to use the node IDs and cryptographic
@ -140,7 +140,6 @@ where
/// Creates a new Queueing Honey Badger instance with an empty buffer.
pub fn build<R>(self, rng: R) -> QueueingHoneyBadgerWithStep<T, N, Q>
where
T: Contribution + Serialize + for<'r> Deserialize<'r>,
R: 'static + Rng + Send + Sync,
{
self.build_with_transactions(None, rng)
@ -156,7 +155,6 @@ where
) -> Result<QueueingHoneyBadgerWithStep<T, N, Q>>
where
TI: IntoIterator<Item = T>,
T: Contribution + Serialize + for<'r> Deserialize<'r>,
R: 'static + Rng + Send + Sync,
{
self.queue.extend(txs);
@ -173,12 +171,9 @@ where
/// A Honey Badger instance that can handle adding and removing nodes and manages a transaction
/// queue.
pub struct QueueingHoneyBadger<T, N, Q>
where
T: Contribution + Serialize + for<'r> Deserialize<'r>,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
Q: TransactionQueue<T>,
{
#[derive(Derivative)]
#[derivative(Debug)]
pub struct QueueingHoneyBadger<T, N: Rand, Q> {
/// The target number of transactions to be included in each batch.
batch_size: usize,
/// The internal `DynamicHoneyBadger` instance.
@ -186,31 +181,16 @@ where
/// The queue of pending transactions that haven't been output in a batch yet.
queue: Q,
/// Random number generator used for choosing transactions from the queue.
#[derivative(Debug(format_with = "util::fmt_rng"))]
rng: Box<dyn Rng + Send + Sync>,
}
impl<T, N, Q> fmt::Debug for QueueingHoneyBadger<T, N, Q>
where
T: Contribution + Serialize + for<'r> Deserialize<'r>,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
Q: TransactionQueue<T>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("QueueingHoneyBadger")
.field("batch_size", &self.batch_size)
.field("dyn_hb", &self.dyn_hb)
.field("queue", &self.queue)
.field("rng", &"<RNG>")
.finish()
}
}
pub type Step<T, N, Q> = ::Step<QueueingHoneyBadger<T, N, Q>>;
impl<T, N, Q> DistAlgorithm for QueueingHoneyBadger<T, N, Q>
where
T: Contribution + Serialize + for<'r> Deserialize<'r> + Clone,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
T: Contribution + Serialize + DeserializeOwned + Clone,
N: NodeIdT + Serialize + DeserializeOwned + Rand,
Q: TransactionQueue<T>,
{
type NodeId = N;
@ -243,8 +223,8 @@ where
impl<T, N, Q> QueueingHoneyBadger<T, N, Q>
where
T: Contribution + Serialize + for<'r> Deserialize<'r> + Clone,
N: NodeIdT + Serialize + for<'r> Deserialize<'r> + Rand,
T: Contribution + Serialize + DeserializeOwned + Clone,
N: NodeIdT + Serialize + DeserializeOwned + Rand,
Q: TransactionQueue<T>,
{
/// Returns a new `QueueingHoneyBadgerBuilder` configured to use the node IDs and cryptographic
@ -254,12 +234,22 @@ where
}
/// Adds a transaction to the queue.
///
/// This can be called at any time to append to the transaction queue. The new transaction will
/// be proposed in some future epoch.
///
/// If no proposal has yet been made for the current epoch, this may trigger one. In this case,
/// a nonempty step will returned, with the corresponding messages. (Or, if we are the only
/// validator, even with the completed batch as an output.)
pub fn push_transaction(&mut self, tx: T) -> Result<Step<T, N, Q>> {
self.queue.extend(iter::once(tx));
self.propose()
}
/// Casts a vote to change the set of validators.
///
/// This stores a pending vote for the change. It will be included in some future batch, and
/// once enough validators have been voted for the same change, it will take effect.
pub fn vote_for(&mut self, change: Change<N>) -> Result<Step<T, N, Q>> {
let mut step = self
.dyn_hb
@ -270,7 +260,9 @@ where
Ok(step)
}
/// Handles an incoming message.
/// Handles a message received from `sender_id`.
///
/// This must be called with every message we receive from another node.
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<T, N, Q>> {
let mut step = self
.dyn_hb

View File

@ -95,7 +95,7 @@ impl<N: NodeIdT + Rand> DistAlgorithm for Subset<N> {
type Error = Error;
fn handle_input(&mut self, input: Self::Input) -> Result<Step<N>> {
self.send_proposed_value(input)
self.propose(input)
}
fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<N>> {
@ -118,6 +118,10 @@ pub enum SubsetOutput<N> {
}
impl<N: NodeIdT + Rand> Subset<N> {
/// Creates a new `Subset` instance with the given session identifier.
///
/// If multiple `Subset`s are instantiated within a single network, they must use different
/// session identifiers to foil replay attacks.
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();
@ -149,9 +153,10 @@ impl<N: NodeIdT + Rand> Subset<N> {
})
}
/// 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>> {
/// Proposes a value for the subset.
///
/// Returns an error if we already made a proposal.
pub fn propose(&mut self, value: ProposedValue) -> Result<Step<N>> {
if !self.netinfo.is_validator() {
return Ok(Step::default());
}
@ -160,7 +165,9 @@ impl<N: NodeIdT + Rand> Subset<N> {
self.process_broadcast(&id, |bc| bc.handle_input(value))
}
/// Handles an incoming message.
/// Handles a message received from `sender_id`.
///
/// This must be called with every message we receive from another node.
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<N>> {
match message {
Message::Broadcast(p_id, b_msg) => self.handle_broadcast(sender_id, &p_id, b_msg),

View File

@ -137,7 +137,11 @@ impl<N: NodeIdT> ThresholdDecryption<N> {
self.shares.keys()
}
/// Handles an incoming message. If we have collected enough shares, outputs the plaintext.
/// Handles a message with a decryption share received from `sender_id`.
///
/// This must be called with every message we receive from another node.
///
/// If we have collected enough, returns the decrypted message.
pub fn handle_message(&mut self, sender_id: &N, message: Message) -> Result<Step<N>> {
if self.terminated {
return Ok(Step::default()); // Don't waste time on redundant shares.

View File

@ -120,7 +120,11 @@ impl<N: NodeIdT> ThresholdSign<N> {
Ok(step)
}
/// Handles an incoming share. If we have collected enough, returns the full signature.
/// Handles a message with a signature share received from `sender_id`.
///
/// This must be called with every message we receive from another node.
///
/// If we have collected enough, returns the full signature.
pub fn handle_message(&mut self, sender_id: &N, message: Message) -> Result<Step<N>> {
if self.terminated {
return Ok(Step::default());

View File

@ -3,6 +3,8 @@
//! Functions not large enough to warrant their own crate or module, but flexible enough to be used
//! in multiple disjunct places in the library. May also contain backports, workarounds.
use std::fmt;
use rand;
/// Workaround trait for creating new random number generators
@ -22,3 +24,8 @@ where
Box::new(rng)
}
}
/// Prints "`<RNG>`" as a placeholder for a random number generator in debug output.
pub fn fmt_rng<T>(_: T, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("<RNG>")
}