Add Honey Badger builder.

This commit is contained in:
Andreas Fackler 2018-06-28 21:31:27 +02:00
parent 0f92010fe4
commit 1a3016d94d
4 changed files with 87 additions and 42 deletions

View File

@ -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),

View File

@ -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(())

View File

@ -32,6 +32,76 @@ error_chain!{
}
}
/// A Honey Badger builder, to configure the parameters and create new instances of `HoneyBadger`.
pub struct HoneyBadgerBuilder<NodeUid> {
/// Shared network data.
netinfo: Rc<NetworkInfo<NodeUid>>,
/// 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<NodeUid: Ord + Clone + Debug> HoneyBadgerBuilder<NodeUid> {
/// Creates a new builder for Honey Badger.
pub fn new(netinfo: Rc<NetworkInfo<NodeUid>>) -> 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<Tx>(&self) -> HoneyBadgerResult<HoneyBadger<Tx, NodeUid>>
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<Tx, TI>(
&self,
txs: TI,
) -> HoneyBadgerResult<HoneyBadger<Tx, NodeUid>>
where
TI: IntoIterator<Item = Tx>,
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<Tx, NodeUid> {
/// 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<TI>(
netinfo: Rc<NetworkInfo<NodeUid>>,
batch_size: usize,
max_future_epochs: usize,
txs: TI,
) -> HoneyBadgerResult<Self>
where
TI: IntoIterator<Item = Tx>,
{
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<I: IntoIterator<Item = Tx>>(&mut self, txs: I) {
self.buffer.extend(txs);

View File

@ -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<NetworkInfo<NodeUid>>) -> HoneyBadger<usize, NodeUid> {
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<A, F>(new_adversary: F, num_txs: usize)