From af05c44659ec962251b7fc300c2b55037da1953b Mon Sep 17 00:00:00 2001 From: Vladimir Komendantskiy Date: Tue, 9 Oct 2018 15:07:56 +0100 Subject: [PATCH] Revert "Spam protection part 1: remote epoch tracking in HoneyBadger (#219)" This reverts commit b649dc6268c5bc77cde36353d2a7e49d11aaa4ea. --- examples/simulation.rs | 11 ++--- src/dynamic_honey_badger/builder.rs | 34 +++++--------- .../dynamic_honey_badger.rs | 23 +++++----- src/dynamic_honey_badger/error.rs | 2 + src/honey_badger/builder.rs | 26 +++-------- src/honey_badger/error.rs | 4 +- src/honey_badger/honey_badger.rs | 44 +++---------------- src/honey_badger/message.rs | 24 +++------- src/subset.rs | 2 +- tests/dynamic_honey_badger.rs | 11 ++--- tests/honey_badger.rs | 9 ++-- tests/net_dynamic_hb.rs | 3 +- tests/queueing_honey_badger.rs | 9 +--- 13 files changed, 59 insertions(+), 143 deletions(-) diff --git a/examples/simulation.rs b/examples/simulation.rs index a3d7bc15..5987b3d4 100644 --- a/examples/simulation.rs +++ b/examples/simulation.rs @@ -434,16 +434,11 @@ fn main() { .map(|_| Transaction::new(args.flag_tx_size)) .collect(); let new_honey_badger = |netinfo: NetworkInfo| { - 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), diff --git a/src/dynamic_honey_badger/builder.rs b/src/dynamic_honey_badger/builder.rs index e5d7ad87..53367e31 100644 --- a/src/dynamic_honey_badger/builder.rs +++ b/src/dynamic_honey_badger/builder.rs @@ -71,10 +71,7 @@ where } /// Creates a new Dynamic Honey Badger instance with an empty buffer. - pub fn build( - &mut self, - netinfo: NetworkInfo, - ) -> Result<(DynamicHoneyBadger, Step)> { + pub fn build(&mut self, netinfo: NetworkInfo) -> DynamicHoneyBadger { let DynamicHoneyBadgerBuilder { max_future_epochs, rng, @@ -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, @@ -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, Step)> { + pub fn build_first_node(&mut self, our_id: N) -> Result> { 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 @@ -133,14 +125,13 @@ 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, @@ -148,12 +139,9 @@ where 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)) } diff --git a/src/dynamic_honey_badger/dynamic_honey_badger.rs b/src/dynamic_honey_badger/dynamic_honey_badger.rs index 9151dad9..bb4b02f1 100644 --- a/src/dynamic_honey_badger/dynamic_honey_badger.rs +++ b/src/dynamic_honey_badger/dynamic_honey_badger.rs @@ -193,6 +193,10 @@ where sender_id: &N, message: HbMessage, ) -> Result> { + 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 @@ -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, N>, ) -> Result> { @@ -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. @@ -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; @@ -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> { + 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. diff --git a/src/dynamic_honey_badger/error.rs b/src/dynamic_honey_badger/error.rs index a74ae398..75a2aa81 100644 --- a/src/dynamic_honey_badger/error.rs +++ b/src/dynamic_honey_badger/error.rs @@ -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. diff --git a/src/honey_badger/builder.rs b/src/honey_badger/builder.rs index f878331b..2d891e7e 100644 --- a/src/honey_badger/builder.rs +++ b/src/honey_badger/builder.rs @@ -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 -where - N: Rand, -{ +pub struct HoneyBadgerBuilder { /// Shared network data. netinfo: Arc>, /// The maximum number of future epochs for which we handle messages simultaneously. @@ -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, Step) { - let hb = HoneyBadger { + /// Creates a new Honey Badger instance. + pub fn build(&mut self) -> HoneyBadger { + 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) + } } } diff --git a/src/honey_badger/error.rs b/src/honey_badger/error.rs index 1b3d51fe..809c0726 100644 --- a/src/honey_badger/error.rs +++ b/src/honey_badger/error.rs @@ -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. diff --git a/src/honey_badger/honey_badger.rs b/src/honey_badger/honey_badger.rs index ff237af0..ddf28ce5 100644 --- a/src/honey_badger/honey_badger.rs +++ b/src/honey_badger/honey_badger.rs @@ -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; @@ -28,8 +28,6 @@ pub struct HoneyBadger { pub(super) max_future_epochs: u64, /// Messages for future epochs that couldn't be handled yet. pub(super) incoming_queue: BTreeMap)>>, - /// Known current epochs of remote nodes. - pub(super) remote_epochs: BTreeMap, /// A random number generator used for secret key generation. // Boxed to avoid overloading the algorithm's type with more generics. pub(super) rng: Box, @@ -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", &"") .finish() } @@ -118,27 +115,10 @@ where /// Handles a message received from `sender_id`. fn handle_message(&mut self, sender_id: &N, message: Message) -> Result> { - 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, - ) -> Result> { + let Message { epoch, content } = message; if epoch > self.epoch + self.max_future_epochs { // Postpone handling this message. self.incoming_queue @@ -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 @@ -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 = 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 { diff --git a/src/honey_badger/message.rs b/src/honey_badger/message.rs index 852bfcfd..c4c5dd86 100644 --- a/src/honey_badger/message.rs +++ b/src/honey_badger/message.rs @@ -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 { /// A message belonging to the subset algorithm in the given epoch. Subset(subset::Message), @@ -17,7 +17,7 @@ pub enum MessageContent { impl MessageContent { pub fn with_epoch(self, epoch: u64) -> Message { - Message::HoneyBadger { + Message { epoch, content: self, } @@ -26,25 +26,13 @@ impl MessageContent { /// A message sent to or received from another node's Honey Badger instance. #[derive(Clone, Debug, Deserialize, Rand, Serialize)] -pub enum Message { - /// A Honey Badger algorithm message annotated with the epoch number. - HoneyBadger { - epoch: u64, - content: MessageContent, - }, - /// 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 { + pub(super) epoch: u64, + pub(super) content: MessageContent, } impl Message { - /// 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 } } diff --git a/src/subset.rs b/src/subset.rs index abb84f60..b3777ff9 100644 --- a/src/subset.rs +++ b/src/subset.rs @@ -62,7 +62,7 @@ pub type Result = ::std::result::Result; type ProposedValue = Vec; /// Message from Subset to remote nodes. -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Rand)] +#[derive(Serialize, Deserialize, Clone, Debug, Rand)] pub enum Message { /// A message for the broadcast algorithm concerning the set element proposed by the given node. Broadcast(N, broadcast::Message), diff --git a/tests/dynamic_honey_badger.rs b/tests/dynamic_honey_badger.rs index 716c827e..7ca9e37a 100644 --- a/tests/dynamic_honey_badger.rs +++ b/tests/dynamic_honey_badger.rs @@ -22,7 +22,7 @@ use std::sync::Arc; use itertools::Itertools; use rand::Rng; -use hbbft::dynamic_honey_badger::{Batch, Change, ChangeState, DynamicHoneyBadger, Input, Step}; +use hbbft::dynamic_honey_badger::{Batch, Change, ChangeState, DynamicHoneyBadger, Input}; use hbbft::messaging::NetworkInfo; use hbbft::transaction_queue::TransactionQueue; @@ -121,10 +121,8 @@ where // Allow passing `netinfo` by value. `TestNetwork` expects this function signature. #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] -fn new_dynamic_hb(netinfo: Arc>) -> (UsizeDhb, Step, NodeId>) { - DynamicHoneyBadger::builder() - .build((*netinfo).clone()) - .expect("`new_dynamic_hb` failed") +fn new_dynamic_hb(netinfo: Arc>) -> UsizeDhb { + DynamicHoneyBadger::builder().build((*netinfo).clone()) } fn test_dynamic_honey_badger_different_sizes(new_adversary: F, num_txs: usize) @@ -146,8 +144,7 @@ where num_good_nodes, num_adv_nodes ); let adversary = |adv_nodes| new_adversary(num_good_nodes, num_adv_nodes, adv_nodes); - let network = - TestNetwork::new_with_step(num_good_nodes, num_adv_nodes, adversary, new_dynamic_hb); + let network = TestNetwork::new(num_good_nodes, num_adv_nodes, adversary, new_dynamic_hb); test_dynamic_honey_badger(network, num_txs); } } diff --git a/tests/honey_badger.rs b/tests/honey_badger.rs index 66a3adea..333a5ad7 100644 --- a/tests/honey_badger.rs +++ b/tests/honey_badger.rs @@ -22,7 +22,7 @@ use std::sync::Arc; use itertools::Itertools; use rand::Rng; -use hbbft::honey_badger::{self, Batch, HoneyBadger, MessageContent, Step}; +use hbbft::honey_badger::{self, Batch, HoneyBadger, MessageContent}; use hbbft::messaging::{NetworkInfo, Target, TargetedMessage}; use hbbft::threshold_decryption; use hbbft::transaction_queue::TransactionQueue; @@ -184,9 +184,7 @@ where } } -fn new_honey_badger( - netinfo: Arc>, -) -> (UsizeHoneyBadger, Step, NodeId>) { +fn new_honey_badger(netinfo: Arc>) -> UsizeHoneyBadger { HoneyBadger::builder(netinfo).build() } @@ -208,8 +206,7 @@ where num_good_nodes, num_adv_nodes ); let adversary = |adv_nodes| new_adversary(num_good_nodes, num_adv_nodes, adv_nodes); - let network = - TestNetwork::new_with_step(num_good_nodes, num_adv_nodes, adversary, new_honey_badger); + let network = TestNetwork::new(num_good_nodes, num_adv_nodes, adversary, new_honey_badger); test_honey_badger(network, num_txs); } } diff --git a/tests/net_dynamic_hb.rs b/tests/net_dynamic_hb.rs index 9f486c27..69587e0c 100644 --- a/tests/net_dynamic_hb.rs +++ b/tests/net_dynamic_hb.rs @@ -101,12 +101,11 @@ fn do_drop_and_readd(cfg: TestConfig) { .time_limit(time::Duration::from_secs(30 * cfg.dimension.size() as u64)) // Ensure runs are reproducible. .rng(rng.gen::()) - .using_step(move |node| { + .using(move |node| { println!("Constructing new dynamic honey badger node #{}", node.id); DynamicHoneyBadger::builder() .rng(node.rng) .build(node.netinfo) - .expect("cannot build instance") }).build() .expect("could not construct test network"); diff --git a/tests/queueing_honey_badger.rs b/tests/queueing_honey_badger.rs index 516a2285..e202f948 100644 --- a/tests/queueing_honey_badger.rs +++ b/tests/queueing_honey_badger.rs @@ -106,13 +106,8 @@ where fn new_queueing_hb( netinfo: Arc>, ) -> (QueueingHoneyBadger, Step) { - let (dhb, dhb_step) = DynamicHoneyBadger::builder() - .build((*netinfo).clone()) - .expect("`new_queueing_hb` failed"); - let (qhb, qhb_step) = QueueingHoneyBadger::builder(dhb).batch_size(3).build(); - let mut step = dhb_step.convert(); - step.extend(qhb_step); - (qhb, step) + let dyn_hb = DynamicHoneyBadger::builder().build((*netinfo).clone()); + QueueingHoneyBadger::builder(dyn_hb).batch_size(3).build() } fn test_queueing_honey_badger_different_sizes(new_adversary: F, num_txs: usize)