From 1a3016d94d5ddbad4fe6839be45272dfaf2294e7 Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Thu, 28 Jun 2018 21:31:27 +0200 Subject: [PATCH] Add Honey Badger builder. --- examples/simulation.rs | 7 ++- src/dynamic_honey_badger.rs | 11 ++-- src/honey_badger.rs | 104 ++++++++++++++++++++++++------------ tests/honey_badger.rs | 7 ++- 4 files changed, 87 insertions(+), 42 deletions(-) diff --git a/examples/simulation.rs b/examples/simulation.rs index 7058c62..3831c89 100644 --- a/examples/simulation.rs +++ b/examples/simulation.rs @@ -25,7 +25,7 @@ use serde::Serialize; use signifix::{metric, TryFrom}; use hbbft::crypto::SecretKeySet; -use hbbft::honey_badger::{Batch, HoneyBadger}; +use hbbft::honey_badger::{Batch, HoneyBadger, HoneyBadgerBuilder}; use hbbft::messaging::{DistAlgorithm, NetworkInfo, Target}; const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -436,7 +436,10 @@ fn main() { sk_set.secret_key_share(id.0 as u64), pk_set.clone(), )); - HoneyBadger::new(netinfo, args.flag_b, 0, txs.clone()).expect("Instantiate honey_badger") + HoneyBadgerBuilder::new(netinfo) + .batch_size(args.flag_b) + .build_with_transactions(txs.clone()) + .expect("Instantiate honey_badger") }; let hw_quality = HwQuality { latency: Duration::from_millis(args.flag_lag), diff --git a/src/dynamic_honey_badger.rs b/src/dynamic_honey_badger.rs index 7656fe5..54c46e7 100644 --- a/src/dynamic_honey_badger.rs +++ b/src/dynamic_honey_badger.rs @@ -57,7 +57,7 @@ use clear_on_drop::ClearOnDrop; use serde::{Deserialize, Serialize}; use crypto::{PublicKey, PublicKeySet, SecretKey, Signature}; -use honey_badger::{self, Batch as HbBatch, HoneyBadger, Message as HbMessage}; +use honey_badger::{self, Batch as HbBatch, HoneyBadger, HoneyBadgerBuilder, Message as HbMessage}; use messaging::{DistAlgorithm, NetworkInfo, Target, TargetedMessage}; use sync_key_gen::{Accept, Propose, SyncKeyGen}; @@ -165,8 +165,9 @@ where where Tx: Serialize + for<'r> Deserialize<'r> + Debug + Hash + Eq, { - let honey_badger = - HoneyBadger::new(Rc::new(self.netinfo.clone()), self.batch_size, 0, None)?; + let honey_badger = HoneyBadgerBuilder::new(Rc::new(self.netinfo.clone())) + .batch_size(self.batch_size) + .build()?; let dyn_hb = DynamicHoneyBadger { netinfo: self.netinfo.clone(), batch_size: self.batch_size, @@ -445,7 +446,9 @@ where let old_buf = self.honey_badger.drain_buffer(); let outputs = (self.honey_badger.output_iter()).flat_map(HbBatch::into_tx_iter); let buffer = outputs.chain(old_buf).filter(Transaction::is_user); - HoneyBadger::new(netinfo, self.batch_size, 0, buffer)? + HoneyBadgerBuilder::new(netinfo) + .batch_size(self.batch_size) + .build_with_transactions(buffer)? }; self.honey_badger = honey_badger; Ok(()) diff --git a/src/honey_badger.rs b/src/honey_badger.rs index 3a97036..c666ee9 100644 --- a/src/honey_badger.rs +++ b/src/honey_badger.rs @@ -32,6 +32,76 @@ error_chain!{ } } +/// A Honey Badger builder, to configure the parameters and create new instances of `HoneyBadger`. +pub struct HoneyBadgerBuilder { + /// Shared network data. + netinfo: Rc>, + /// The target number of transactions to be included in each batch. + // TODO: Do experiments and pick a suitable default. + batch_size: usize, + /// The maximum number of future epochs for which we handle messages simultaneously. + max_future_epochs: usize, +} + +impl HoneyBadgerBuilder { + /// Creates a new builder for Honey Badger. + pub fn new(netinfo: Rc>) -> Self { + HoneyBadgerBuilder { + netinfo, + batch_size: 100, + max_future_epochs: 3, + } + } + + /// Sets the target number of transactions per batch. + pub fn batch_size(&mut self, batch_size: usize) -> &mut Self { + self.batch_size = batch_size; + self + } + + /// Sets the maximum number of future epochs for which we handle messages simultaneously. + pub fn max_future_epochs(&mut self, max_future_epochs: usize) -> &mut Self { + self.max_future_epochs = max_future_epochs; + self + } + + /// Creates a new Honey Badger instance with an empty buffer. + pub fn build(&self) -> HoneyBadgerResult> + where + Tx: Serialize + for<'r> Deserialize<'r> + Debug + Hash + Eq, + { + self.build_with_transactions(None) + } + + /// Returns a new Honey Badger instance that starts with the given transactions in its buffer. + pub fn build_with_transactions( + &self, + txs: TI, + ) -> HoneyBadgerResult> + where + TI: IntoIterator, + Tx: Serialize + for<'r> Deserialize<'r> + Debug + Hash + Eq, + { + let mut honey_badger = HoneyBadger { + netinfo: self.netinfo.clone(), + buffer: Vec::new(), + epoch: 0, + common_subsets: BTreeMap::new(), + batch_size: self.batch_size, + max_future_epochs: self.max_future_epochs as u64, + messages: MessageQueue(VecDeque::new()), + output: VecDeque::new(), + incoming_queue: BTreeMap::new(), + received_shares: BTreeMap::new(), + decrypted_selections: BTreeMap::new(), + ciphertexts: BTreeMap::new(), + }; + honey_badger.buffer.extend(txs); + honey_badger.propose()?; + Ok(honey_badger) + } +} + /// An instance of the Honey Badger Byzantine fault tolerant consensus algorithm. pub struct HoneyBadger { /// Shared network data. @@ -127,40 +197,6 @@ where Tx: Serialize + for<'r> Deserialize<'r> + Debug + Hash + Eq, NodeUid: Ord + Clone + Debug, { - /// Returns a new Honey Badger instance with the given parameters, starting at epoch `0`. - /// - /// The `batch_size` is the target number of transactions that get committed in every epoch. - /// - /// No messages belonging to `epoch + max_future_epochs + 1` or later will be sent before the - /// batch for `epoch` has been output. If that guarantee is not needed, setting it to a higher - /// value can improve speed. - pub fn new( - netinfo: Rc>, - batch_size: usize, - max_future_epochs: usize, - txs: TI, - ) -> HoneyBadgerResult - where - TI: IntoIterator, - { - let mut honey_badger = HoneyBadger { - netinfo, - buffer: txs.into_iter().collect(), - epoch: 0, - common_subsets: BTreeMap::new(), - batch_size, - max_future_epochs: max_future_epochs as u64, - messages: MessageQueue(VecDeque::new()), - output: VecDeque::new(), - incoming_queue: BTreeMap::new(), - received_shares: BTreeMap::new(), - decrypted_selections: BTreeMap::new(), - ciphertexts: BTreeMap::new(), - }; - honey_badger.propose()?; - Ok(honey_badger) - } - /// Adds transactions into the buffer. pub fn add_transactions>(&mut self, txs: I) { self.buffer.extend(txs); diff --git a/tests/honey_badger.rs b/tests/honey_badger.rs index 0f5901c..b2fc096 100644 --- a/tests/honey_badger.rs +++ b/tests/honey_badger.rs @@ -18,7 +18,7 @@ use std::rc::Rc; use rand::Rng; -use hbbft::honey_badger::{self, Batch, HoneyBadger, MessageContent}; +use hbbft::honey_badger::{self, Batch, HoneyBadger, HoneyBadgerBuilder, MessageContent}; use hbbft::messaging::{NetworkInfo, Target, TargetedMessage}; use network::{ @@ -181,7 +181,10 @@ where } fn new_honey_badger(netinfo: Rc>) -> HoneyBadger { - HoneyBadger::new(netinfo, 12, 0, 0..5).expect("Instantiate honey_badger") + HoneyBadgerBuilder::new(netinfo) + .batch_size(12) + .build_with_transactions(0..5) + .expect("Instantiate honey_badger") } fn test_honey_badger_different_sizes(new_adversary: F, num_txs: usize)