Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert EpochStarted messages #260

Merged
merged 1 commit into from
Oct 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions examples/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,16 +434,11 @@ fn main() {
.map(|_| Transaction::new(args.flag_tx_size))
.collect();
let new_honey_badger = |netinfo: NetworkInfo<NodeId>| {
let (dhb, dhb_step) = DynamicHoneyBadger::builder()
.build(netinfo)
.expect("`DynamicHoneyBadger` builder failed");
let (qhb, qhb_step) = QueueingHoneyBadger::builder(dhb)
let dyn_hb = DynamicHoneyBadger::builder().build(netinfo);
QueueingHoneyBadger::builder(dyn_hb)
.batch_size(args.flag_b)
.build_with_transactions(txs.clone())
.expect("instantiate QueueingHoneyBadger");
let mut step = dhb_step.convert();
step.extend(qhb_step);
(qhb, step)
.expect("instantiate QueueingHoneyBadger")
};
let hw_quality = HwQuality {
latency: Duration::from_millis(args.flag_lag),
Expand Down
34 changes: 11 additions & 23 deletions src/dynamic_honey_badger/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,7 @@ where
}

/// Creates a new Dynamic Honey Badger instance with an empty buffer.
pub fn build(
&mut self,
netinfo: NetworkInfo<N>,
) -> Result<(DynamicHoneyBadger<C, N>, Step<C, N>)> {
pub fn build(&mut self, netinfo: NetworkInfo<N>) -> DynamicHoneyBadger<C, N> {
let DynamicHoneyBadgerBuilder {
max_future_epochs,
rng,
Expand All @@ -83,12 +80,12 @@ where
} = self;
let max_future_epochs = *max_future_epochs;
let arc_netinfo = Arc::new(netinfo.clone());
let (honey_badger, hb_step) = HoneyBadger::builder(arc_netinfo.clone())
let honey_badger = HoneyBadger::builder(arc_netinfo.clone())
.max_future_epochs(max_future_epochs)
.rng(rng.sub_rng())
.subset_handling_strategy(subset_handling_strategy.clone())
.build();
let mut dhb = DynamicHoneyBadger {
DynamicHoneyBadger {
netinfo,
max_future_epochs,
start_epoch: 0,
Expand All @@ -98,23 +95,18 @@ where
key_gen_state: None,
incoming_queue: Vec::new(),
rng: Box::new(rng.sub_rng()),
};
let step = dhb.process_output(hb_step)?;
Ok((dhb, step))
}
}

/// Creates a new `DynamicHoneyBadger` configured to start a new network as a single validator.
pub fn build_first_node(
&mut self,
our_id: N,
) -> Result<(DynamicHoneyBadger<C, N>, Step<C, N>)> {
pub fn build_first_node(&mut self, our_id: N) -> Result<DynamicHoneyBadger<C, N>> {
let sk_set = SecretKeySet::random(0, &mut self.rng)?;
let pk_set = sk_set.public_keys();
let sks = sk_set.secret_key_share(0)?;
let sk: SecretKey = self.rng.gen();
let pub_keys = once((our_id.clone(), sk.public_key())).collect();
let netinfo = NetworkInfo::new(our_id, sks, pk_set, sk, pub_keys);
self.build(netinfo)
Ok(self.build(netinfo))
}

/// Creates a new `DynamicHoneyBadger` configured to join the network at the epoch specified in
Expand All @@ -133,27 +125,23 @@ where
join_plan.pub_keys,
);
let arc_netinfo = Arc::new(netinfo.clone());
let (honey_badger, hb_step) = HoneyBadger::builder(arc_netinfo.clone())
let honey_badger = HoneyBadger::builder(arc_netinfo.clone())
.max_future_epochs(self.max_future_epochs)
.build();
let start_epoch = join_plan.epoch;
let mut dhb = DynamicHoneyBadger {
netinfo,
max_future_epochs: self.max_future_epochs,
start_epoch,
start_epoch: join_plan.epoch,
vote_counter: VoteCounter::new(arc_netinfo, join_plan.epoch),
key_gen_msg_buffer: Vec::new(),
honey_badger,
key_gen_state: None,
incoming_queue: Vec::new(),
rng: Box::new(self.rng.sub_rng()),
};
let mut step = dhb.process_output(hb_step)?;
match join_plan.change {
ChangeState::InProgress(ref change) => {
step.extend(dhb.update_key_gen(join_plan.epoch, change)?)
}
ChangeState::None | ChangeState::Complete(..) => (),
let step = match join_plan.change {
ChangeState::InProgress(ref change) => dhb.update_key_gen(join_plan.epoch, change)?,
ChangeState::None | ChangeState::Complete(..) => Step::default(),
};
Ok((dhb, step))
}
Expand Down
23 changes: 12 additions & 11 deletions src/dynamic_honey_badger/dynamic_honey_badger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ where
sender_id: &N,
message: HbMessage<N>,
) -> Result<Step<C, N>> {
if !self.netinfo.is_node_validator(sender_id) {
info!("Unknown sender {:?} of message {:?}", sender_id, message);
return Err(ErrorKind::UnknownSender.into());
}
// Handle the message.
let step = self
.honey_badger
Expand Down Expand Up @@ -246,7 +250,7 @@ where
}

/// Processes all pending batches output by Honey Badger.
pub(super) fn process_output(
fn process_output(
&mut self,
hb_step: honey_badger::Step<InternalContrib<C, N>, N>,
) -> Result<Step<C, N>> {
Expand Down Expand Up @@ -295,8 +299,7 @@ where
// If DKG completed, apply the change, restart Honey Badger, and inform the user.
debug!("{:?} DKG for {:?} complete!", self.our_id(), kgs.change);
self.netinfo = kgs.key_gen.into_network_info()?;
let step_on_restart = self.restart_honey_badger(batch.epoch + 1)?;
step.extend(step_on_restart);
self.restart_honey_badger(batch.epoch + 1);
batch.set_change(ChangeState::Complete(kgs.change), &self.netinfo);
} else if let Some(change) = self.vote_counter.compute_winner().cloned() {
// If there is a new change, restart DKG. Inform the user about the current change.
Expand Down Expand Up @@ -330,7 +333,7 @@ where
} {
info!("{:?} No-op change: {:?}", self.our_id(), change);
}
let mut step = self.restart_honey_badger(epoch)?;
self.restart_honey_badger(epoch);
// TODO: This needs to be the same as `num_faulty` will be in the _new_
// `NetworkInfo` if the change goes through. It would be safer to deduplicate.
let threshold = (pub_keys.len() - 1) / 3;
Expand All @@ -339,25 +342,23 @@ where
let (key_gen, part) = SyncKeyGen::new(&mut self.rng, our_id, sk, pub_keys, threshold)?;
self.key_gen_state = Some(KeyGenState::new(key_gen, change.clone()));
if let Some(part) = part {
let step_on_send = self.send_transaction(KeyGenMessage::Part(part))?;
step.extend(step_on_send);
self.send_transaction(KeyGenMessage::Part(part))
} else {
Ok(Step::default())
}
Ok(step)
}

/// Starts a new `HoneyBadger` instance and resets the vote counter.
fn restart_honey_badger(&mut self, epoch: u64) -> Result<Step<C, N>> {
fn restart_honey_badger(&mut self, epoch: u64) {
self.start_epoch = epoch;
self.key_gen_msg_buffer.retain(|kg_msg| kg_msg.0 >= epoch);
let netinfo = Arc::new(self.netinfo.clone());
let counter = VoteCounter::new(netinfo.clone(), epoch);
mem::replace(&mut self.vote_counter, counter);
let (hb, hb_step) = HoneyBadger::builder(netinfo)
self.honey_badger = HoneyBadger::builder(netinfo)
.max_future_epochs(self.max_future_epochs)
.rng(self.rng.sub_rng())
.build();
self.honey_badger = hb;
self.process_output(hb_step)
}

/// Handles a `Part` message that was output by Honey Badger.
Expand Down
2 changes: 2 additions & 0 deletions src/dynamic_honey_badger/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub enum ErrorKind {
HandleHoneyBadgerMessageHoneyBadger(honey_badger::Error),
#[fail(display = "SyncKeyGen error: {}", _0)]
SyncKeyGen(sync_key_gen::Error),
#[fail(display = "Unknown sender")]
UnknownSender,
}

/// A dynamic honey badger error.
Expand Down
26 changes: 7 additions & 19 deletions src/honey_badger/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ use std::sync::Arc;
use rand::{self, Rand, Rng};
use serde::{Deserialize, Serialize};

use super::{HoneyBadger, Message, Step};
use super::HoneyBadger;
use honey_badger::SubsetHandlingStrategy;
use messaging::{NetworkInfo, Target};
use messaging::NetworkInfo;
use traits::{Contribution, NodeIdT};
use util::SubRng;

/// A Honey Badger builder, to configure the parameters and create new instances of `HoneyBadger`.
pub struct HoneyBadgerBuilder<C, N>
where
N: Rand,
{
pub struct HoneyBadgerBuilder<C, N> {
/// Shared network data.
netinfo: Arc<NetworkInfo<N>>,
/// The maximum number of future epochs for which we handle messages simultaneously.
Expand Down Expand Up @@ -65,26 +62,17 @@ where
self
}

/// Creates a new Honey Badger instance in epoch 0 and makes the initial `Step` on that
/// instance.
pub fn build(&mut self) -> (HoneyBadger<C, N>, Step<C, N>) {
let hb = HoneyBadger {
/// Creates a new Honey Badger instance.
pub fn build(&mut self) -> HoneyBadger<C, N> {
HoneyBadger {
netinfo: self.netinfo.clone(),
epoch: 0,
has_input: false,
epochs: BTreeMap::new(),
max_future_epochs: self.max_future_epochs as u64,
incoming_queue: BTreeMap::new(),
remote_epochs: BTreeMap::new(),
rng: Box::new(self.rng.sub_rng()),
subset_handling_strategy: self.subset_handling_strategy.clone(),
};
let step = if self.netinfo.is_validator() {
// The first message in an epoch announces the epoch transition.
Target::All.message(Message::EpochStarted(0)).into()
} else {
Step::default()
};
(hb, step)
}
}
}
4 changes: 2 additions & 2 deletions src/honey_badger/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub enum ErrorKind {
HandleSubsetMessage(subset::Error),
#[fail(display = "Threshold decryption error: {}", _0)]
ThresholdDecryption(threshold_decryption::Error),
#[fail(display = "HoneyBadger message sender is not a validator")]
SenderNotValidator,
#[fail(display = "Unknown sender")]
UnknownSender,
}

/// A honey badger error.
Expand Down
44 changes: 5 additions & 39 deletions src/honey_badger/honey_badger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};

use super::epoch_state::EpochState;
use super::{Batch, Error, ErrorKind, HoneyBadgerBuilder, Message, MessageContent, Result};
use messaging::{self, DistAlgorithm, NetworkInfo, Target};
use messaging::{self, DistAlgorithm, NetworkInfo};
use traits::{Contribution, NodeIdT};

pub use super::epoch_state::SubsetHandlingStrategy;
Expand All @@ -28,8 +28,6 @@ pub struct HoneyBadger<C, N: Rand> {
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>)>>,
/// Known current epochs of remote nodes.
pub(super) remote_epochs: BTreeMap<N, u64>,
/// A random number generator used for secret key generation.
// Boxed to avoid overloading the algorithm's type with more generics.
pub(super) rng: Box<dyn Rng + Send + Sync>,
Expand All @@ -50,7 +48,6 @@ where
.field("epochs", &self.epochs)
.field("max_future_epochs", &self.max_future_epochs)
.field("incoming_queue", &self.incoming_queue)
.field("remote_epochs", &self.remote_epochs)
.field("rng", &"<RNG>")
.finish()
}
Expand Down Expand Up @@ -118,27 +115,10 @@ where

/// Handles a message received from `sender_id`.
fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
match message {
Message::HoneyBadger { epoch, content } => {
if !self.netinfo.is_node_validator(sender_id) {
return Err(ErrorKind::SenderNotValidator.into());
}
self.handle_honey_badger_message(sender_id, epoch, content)
}
Message::EpochStarted(epoch) => {
self.handle_epoch_started(sender_id, epoch);
Ok(Step::default())
}
if !self.netinfo.is_node_validator(sender_id) {
return Err(ErrorKind::UnknownSender.into());
}
}

/// Handles a Honey Badger algorithm message in a given epoch.
fn handle_honey_badger_message(
&mut self,
sender_id: &N,
epoch: u64,
content: MessageContent<N>,
) -> Result<Step<C, N>> {
let Message { epoch, content } = message;
if epoch > self.epoch + self.max_future_epochs {
// Postpone handling this message.
self.incoming_queue
Expand All @@ -155,17 +135,6 @@ where
Ok(Step::default())
}

/// Handles an epoch start announcement.
fn handle_epoch_started(&mut self, sender_id: &N, epoch: u64) {
self.remote_epochs
.entry(sender_id.clone())
.and_modify(|e| {
if *e < epoch {
*e = epoch;
}
}).or_insert(epoch);
}

/// Returns `true` if input for the current epoch has already been provided.
pub fn has_input(&self) -> bool {
!self.netinfo.is_validator() || self.has_input
Expand All @@ -186,10 +155,7 @@ where
self.epoch += 1;
self.has_input = false;
let max_epoch = self.epoch + self.max_future_epochs;
// The first message in an epoch announces the epoch transition.
let mut step: Step<C, N> = Target::All
.message(Message::EpochStarted(self.epoch))
.into();
let mut step = Step::default();
if let Some(messages) = self.incoming_queue.remove(&max_epoch) {
let epoch_state = self.epoch_state_mut(max_epoch)?;
for (sender_id, content) in messages {
Expand Down
24 changes: 6 additions & 18 deletions src/honey_badger/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use subset;
use threshold_decryption;

/// The content of a `HoneyBadger` message. It should be further annotated with an epoch.
#[derive(Clone, Debug, Deserialize, PartialEq, Rand, Serialize)]
#[derive(Clone, Debug, Deserialize, Rand, Serialize)]
pub enum MessageContent<N: Rand> {
/// A message belonging to the subset algorithm in the given epoch.
Subset(subset::Message<N>),
Expand All @@ -17,7 +17,7 @@ pub enum MessageContent<N: Rand> {

impl<N: Rand> MessageContent<N> {
pub fn with_epoch(self, epoch: u64) -> Message<N> {
Message::HoneyBadger {
Message {
epoch,
content: self,
}
Expand All @@ -26,25 +26,13 @@ impl<N: Rand> MessageContent<N> {

/// A message sent to or received from another node's Honey Badger instance.
#[derive(Clone, Debug, Deserialize, Rand, Serialize)]
pub enum Message<N: Rand> {
/// A Honey Badger algorithm message annotated with the epoch number.
HoneyBadger {
epoch: u64,
content: MessageContent<N>,
},
/// A Honey Badger participant uses this message to announce its transition to the given
/// epoch. This message informs the recipients that this participant now accepts messages for
/// `max_future_epochs + 1` epochs counting from the given one, and drops any incoming messages
/// from earlier epochs.
EpochStarted(u64),
pub struct Message<N: Rand> {
pub(super) epoch: u64,
pub(super) content: MessageContent<N>,
}

impl<N: Rand> Message<N> {
/// Returns the epoch from which the message originated.
pub fn epoch(&self) -> u64 {
match *self {
Message::HoneyBadger { epoch, .. } => epoch,
Message::EpochStarted(epoch) => epoch,
}
self.epoch
}
}
2 changes: 1 addition & 1 deletion src/subset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub type Result<T> = ::std::result::Result<T, Error>;
type ProposedValue = Vec<u8>;

/// Message from Subset to remote nodes.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Rand)]
#[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.
Broadcast(N, broadcast::Message),
Expand Down
Loading