add configuration options for optional/periodic encryption scheduling

This commit is contained in:
Logan Collins 2018-10-17 12:27:00 -05:00
parent f8bf552165
commit 813a76bb5f
7 changed files with 55 additions and 3 deletions

View File

@ -7,10 +7,11 @@ use crypto::{SecretKey, SecretKeySet, SecretKeyShare};
use rand::{self, Rand, Rng};
use serde::{Deserialize, Serialize};
use super::{ChangeState, DynamicHoneyBadger, JoinPlan, Result, Step, VoteCounter};
use super::{Change, ChangeState, DynamicHoneyBadger, JoinPlan, Result, Step, VoteCounter};
use honey_badger::{HoneyBadger, SubsetHandlingStrategy};
use util::SubRng;
use {Contribution, NetworkInfo, NodeIdT};
use threshold_decryption::EncryptionSchedule;
/// A Dynamic Honey Badger builder, to configure the parameters and create new instances of
/// `DynamicHoneyBadger`.
@ -24,6 +25,8 @@ pub struct DynamicHoneyBadgerBuilder<C, N> {
rng: Box<dyn rand::Rng>,
/// Strategy used to handle the output of the `Subset` algorithm.
subset_handling_strategy: SubsetHandlingStrategy,
/// Schedule for adding threshold encryption to some percentage of rounds
encryption_schedule: EncryptionSchedule,
_phantom: PhantomData<(C, N)>,
}
@ -35,6 +38,7 @@ impl<C, N> Default for DynamicHoneyBadgerBuilder<C, N> {
max_future_epochs: 3,
rng: Box::new(rand::thread_rng()),
subset_handling_strategy: SubsetHandlingStrategy::Incremental,
encryption_schedule: EncryptionSchedule::Always,
_phantom: PhantomData,
}
}
@ -78,6 +82,12 @@ where
self
}
/// Sets the schedule to use for threshold encryption.
pub fn encryption_schedule(&mut self, encryption_schedule: EncryptionSchedule) -> &mut Self {
self.encryption_schedule = encryption_schedule;
self
}
/// Creates a new Dynamic Honey Badger instance with an empty buffer.
pub fn build(&mut self, netinfo: NetworkInfo<N>) -> DynamicHoneyBadger<C, N> {
let DynamicHoneyBadgerBuilder {
@ -85,6 +95,7 @@ where
max_future_epochs,
rng,
subset_handling_strategy,
encryption_schedule,
_phantom,
} = self;
let epoch = *epoch;
@ -94,6 +105,7 @@ where
.max_future_epochs(max_future_epochs)
.rng(rng.sub_rng())
.subset_handling_strategy(subset_handling_strategy.clone())
.encryption_schedule(*encryption_schedule)
.build();
DynamicHoneyBadger {
netinfo,
@ -150,7 +162,12 @@ where
rng: Box::new(self.rng.sub_rng()),
};
let step = match join_plan.change {
ChangeState::InProgress(ref change) => dhb.update_key_gen(join_plan.epoch, change)?,
ChangeState::InProgress(ref change) => {
match change {
Change::Add(_,_) | Change::Remove(_) => dhb.update_key_gen(join_plan.epoch, change)?,
_ => Step::default(),
}
},
ChangeState::None | ChangeState::Complete(..) => Step::default(),
};
Ok((dhb, step))

View File

@ -1,12 +1,16 @@
use crypto::PublicKey;
use threshold_decryption::EncryptionSchedule;
/// A node change action: adding or removing a node.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Hash, Debug)]
pub enum Change<N> {
// TODO: Refactor so that node changes are in a sub-enum of a Change.
/// Add a node. The public key is used only temporarily, for key generation.
Add(N, PublicKey),
/// Remove a node.
Remove(N),
/// Change the threshold encryption schedule. i.e., to increase frequency to prevent censorship or decrease for performance.
EncryptionSchedule(EncryptionSchedule),
}
impl<N> Change<N> {
@ -15,6 +19,7 @@ impl<N> Change<N> {
match *self {
Change::Add(ref id, _) => Some(id),
Change::Remove(_) => None,
Change::EncryptionSchedule(_) => None,
}
}
}

View File

@ -301,7 +301,10 @@ where
ChangeState::Complete(kgs.change)
} 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.
step.extend(self.update_key_gen(batch_epoch + 1, &change)?);
step.extend(match change {
Change::Add(_,_) | Change::Remove(_) => self.update_key_gen(batch_epoch + 1, &change)?,
Change::EncryptionSchedule(_) => Step::default(), // TODO: Should this `step` contain something?
});
ChangeState::InProgress(change)
} else {
ChangeState::None
@ -335,6 +338,7 @@ where
if match *change {
Change::Remove(ref id) => pub_keys.remove(id).is_none(),
Change::Add(ref id, ref pk) => pub_keys.insert(id.clone(), pk.clone()).is_some(),
_ => unreachable!(), // Unreachable by construction. Will be more clear once Change is refactored to have `NodeChange` so there won't be other variants.
} {
info!("{:?} No-op change: {:?}", self.our_id(), change);
}

View File

@ -176,6 +176,7 @@ impl<N: NodeIdT> KeyGenState<N> {
match self.change {
Change::Add(ref id, ref pk) if id == node_id => Some(pk),
Change::Add(_, _) | Change::Remove(_) => None,
Change::EncryptionSchedule(_) => None,
}
}
}

View File

@ -9,6 +9,7 @@ use super::HoneyBadger;
use honey_badger::SubsetHandlingStrategy;
use util::SubRng;
use {Contribution, NetworkInfo, NodeIdT};
use threshold_decryption::EncryptionSchedule;
/// A Honey Badger builder, to configure the parameters and create new instances of `HoneyBadger`.
pub struct HoneyBadgerBuilder<C, N> {
@ -22,6 +23,8 @@ pub struct HoneyBadgerBuilder<C, N> {
rng: Box<dyn Rng>,
/// Strategy used to handle the output of the `Subset` algorithm.
subset_handling_strategy: SubsetHandlingStrategy,
/// Schedule for adding threshold encryption to some percentage of rounds
encryption_schedule: EncryptionSchedule,
_phantom: PhantomData<C>,
}
@ -39,6 +42,7 @@ where
max_future_epochs: 3,
rng: Box::new(rand::thread_rng()),
subset_handling_strategy: SubsetHandlingStrategy::Incremental,
encryption_schedule: EncryptionSchedule::Always,
_phantom: PhantomData,
}
}
@ -70,6 +74,12 @@ where
self
}
/// Sets the schedule to use for threshold encryption.
pub fn encryption_schedule(&mut self, encryption_schedule: EncryptionSchedule) -> &mut Self {
self.encryption_schedule = encryption_schedule;
self
}
/// Creates a new Honey Badger instance.
pub fn build(&mut self) -> HoneyBadger<C, N> {
HoneyBadger {
@ -81,6 +91,7 @@ where
incoming_queue: BTreeMap::new(),
rng: Box::new(self.rng.sub_rng()),
subset_handling_strategy: self.subset_handling_strategy.clone(),
encryption_schedule: self.encryption_schedule,
}
}
}

View File

@ -12,6 +12,7 @@ use super::{Batch, Error, ErrorKind, HoneyBadgerBuilder, Message, MessageContent
use {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.
pub struct HoneyBadger<C, N: Rand> {
@ -32,6 +33,8 @@ pub struct HoneyBadger<C, N: Rand> {
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,
/// The schedule for which rounds we should use threshold encryption.
pub(super) encryption_schedule: EncryptionSchedule,
}
impl<C, N> fmt::Debug for HoneyBadger<C, N>
@ -48,6 +51,7 @@ where
.field("max_future_epochs", &self.max_future_epochs)
.field("incoming_queue", &self.incoming_queue)
.field("rng", &"<RNG>")
.field("encryption_schedule", &self.encryption_schedule)
.finish()
}
}

View File

@ -17,6 +17,16 @@ use crypto::{self, Ciphertext, DecryptionShare};
use fault_log::{Fault, FaultKind, FaultLog};
use {DistAlgorithm, NetworkInfo, NodeIdT, Target};
/// How frequently Threshold Encryption should be used.
#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash, Debug)]
pub enum EncryptionSchedule {
Always,
Never,
EveryNthEpoch(u32),
/// How many with encryption, followed by how many without encryption.
TickTock(u32, u32),
}
/// A threshold decryption error.
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
pub enum Error {