2018-05-16 05:23:57 -07:00
|
|
|
use std::collections::btree_map::Entry;
|
2018-08-03 02:18:06 -07:00
|
|
|
use std::collections::BTreeMap;
|
2018-07-11 12:15:08 -07:00
|
|
|
use std::sync::Arc;
|
2018-05-12 07:09:07 -07:00
|
|
|
|
2018-10-29 07:36:56 -07:00
|
|
|
use derivative::Derivative;
|
2018-10-02 07:24:51 -07:00
|
|
|
use rand::{Rand, Rng};
|
2018-10-24 02:38:14 -07:00
|
|
|
use serde::{de::DeserializeOwned, Serialize};
|
2018-11-12 03:24:29 -08:00
|
|
|
use serde_derive::{Deserialize, Serialize};
|
2018-05-12 07:09:07 -07:00
|
|
|
|
2018-08-03 06:24:49 -07:00
|
|
|
use super::epoch_state::EpochState;
|
2018-11-26 06:35:24 -08:00
|
|
|
use super::{Batch, Error, HoneyBadgerBuilder, Message, Result};
|
OsRng / external RNG Refactoring (#357)
* Use `OsRng` in place of `thread_rng`.
This changes the defaults of any builder by instantiating an `OsRng` instead of
a `thread_rng`, the former being much more secure than the latter.
Additionally, all the unit tests that still instantiate RNGs manually used `OsRng`s
as well; while there is no actual need for this level of security in tests, the performance overhead is very small and random number generation complexity has such a small impact on these tests that the convenience of being able to ban `thread_rng` from the codebase altogether, setting a good example and avoid issues when refactoring later greatly outweigh the negatives.
* Instead of storing random number generators in the various consensus algorithm instances, pass them in from the outside whenever they are needed.
This changes a large amount of interfaces (and in this commit is only partially done, since `DistAlgorithm` needs to be fundamentally altered as well.
It also obsoletes parts of the `util` module.
* Added an `R: Rng` type parameter to both methods of `DistAlgorithm`, forcing callers to pass in their own Rngs.
* Fixed documentation grammar and spelling in some of the altered interfaces due to RNG refactoring.
* Move `rng` argument to the end of the argument for most functions.
Also includes a reformatting due to Rust 1.30.
* Updated tests, accomodate `rng`-API changes.
* Fixed remaining compilation issues with new RNG code.
* Fix illegal `self` import outside curly braces.
* Cleaned up comments and fixed broken definition of `broadcast_input`.
* Updated existing test cases to properly work with static dispatch randomness.
* Do not use boxed `Rng`s for key generation in test networks.
* Use the passed-in `Rng` in `ReorderingAdversary`, instead of storing a boxed one.
* Fixed clippy lints after refactoring.
* Removed some no-longer necessary manual `fmt::Debug` implementations in test framework.
* Use `OsRng` even in tests in `binary_agreement_mitm`.
* Use a proper deterministic RNG in tests `binary_agreement_mitm`.
* Refactor `examples/simulation.rs` by not using `ThreadRng`, passing generic `Rng` parameters throughout and using a type alias instead of a newtype as the `Transaction`.
* Remove `thread_rng` use from `examples/node.rs`.
* Explicitly construct `InternalContrib` in `DynamicHoneyBadger::propose`.
* Fixed typo in description of `DistAlgorithm` trait.
2018-12-14 04:51:09 -08:00
|
|
|
use crate::{Contribution, DistAlgorithm, Fault, FaultKind, NetworkInfo, NodeIdT};
|
2018-05-12 07:09:07 -07:00
|
|
|
|
2018-11-18 01:18:14 -08:00
|
|
|
use super::Params;
|
2018-09-29 18:46:42 -07:00
|
|
|
|
2018-05-12 07:09:07 -07:00
|
|
|
/// An instance of the Honey Badger Byzantine fault tolerant consensus algorithm.
|
2018-10-24 04:01:52 -07:00
|
|
|
#[derive(Derivative)]
|
|
|
|
#[derivative(Debug)]
|
2018-08-02 14:27:55 -07:00
|
|
|
pub struct HoneyBadger<C, N: Rand> {
|
2018-05-29 05:17:30 -07:00
|
|
|
/// Shared network data.
|
2018-08-02 14:27:55 -07:00
|
|
|
pub(super) netinfo: Arc<NetworkInfo<N>>,
|
2018-10-24 00:42:59 -07:00
|
|
|
/// A session identifier. Different session IDs foil replay attacks in two instances with the
|
|
|
|
/// same epoch numbers and the same validators.
|
|
|
|
pub(super) session_id: u64,
|
2018-05-16 05:23:57 -07:00
|
|
|
/// The earliest epoch from which we have not yet received output.
|
2018-07-31 13:27:22 -07:00
|
|
|
pub(super) epoch: u64,
|
2018-07-09 05:29:01 -07:00
|
|
|
/// Whether we have already submitted a proposal for the current epoch.
|
2018-07-31 13:27:22 -07:00
|
|
|
pub(super) has_input: bool,
|
2018-08-03 06:24:49 -07:00
|
|
|
/// The subalgorithms for ongoing epochs.
|
|
|
|
pub(super) epochs: BTreeMap<u64, EpochState<C, N>>,
|
2018-11-18 01:18:14 -08:00
|
|
|
/// Parameters controlling Honey Badger's behavior and performance.
|
|
|
|
pub(super) params: Params,
|
2018-10-02 07:24:51 -07:00
|
|
|
}
|
|
|
|
|
2018-11-26 06:35:24 -08:00
|
|
|
/// A `HoneyBadger` step, possibly containing multiple outputs.
|
2018-12-11 05:44:36 -08:00
|
|
|
pub type Step<C, N> = crate::DaStep<HoneyBadger<C, N>>;
|
2018-07-09 04:35:26 -07:00
|
|
|
|
2018-08-02 14:27:55 -07:00
|
|
|
impl<C, N> DistAlgorithm for HoneyBadger<C, N>
|
2018-06-29 08:10:15 -07:00
|
|
|
where
|
2018-10-24 02:38:14 -07:00
|
|
|
C: Contribution + Serialize + DeserializeOwned,
|
2018-08-29 09:08:35 -07:00
|
|
|
N: NodeIdT + Rand,
|
2018-05-14 05:35:06 -07:00
|
|
|
{
|
2018-08-29 09:08:35 -07:00
|
|
|
type NodeId = N;
|
2018-07-09 05:29:01 -07:00
|
|
|
type Input = C;
|
2018-08-02 14:27:55 -07:00
|
|
|
type Output = Batch<C, N>;
|
|
|
|
type Message = Message<N>;
|
2018-05-14 05:35:06 -07:00
|
|
|
type Error = Error;
|
|
|
|
|
OsRng / external RNG Refactoring (#357)
* Use `OsRng` in place of `thread_rng`.
This changes the defaults of any builder by instantiating an `OsRng` instead of
a `thread_rng`, the former being much more secure than the latter.
Additionally, all the unit tests that still instantiate RNGs manually used `OsRng`s
as well; while there is no actual need for this level of security in tests, the performance overhead is very small and random number generation complexity has such a small impact on these tests that the convenience of being able to ban `thread_rng` from the codebase altogether, setting a good example and avoid issues when refactoring later greatly outweigh the negatives.
* Instead of storing random number generators in the various consensus algorithm instances, pass them in from the outside whenever they are needed.
This changes a large amount of interfaces (and in this commit is only partially done, since `DistAlgorithm` needs to be fundamentally altered as well.
It also obsoletes parts of the `util` module.
* Added an `R: Rng` type parameter to both methods of `DistAlgorithm`, forcing callers to pass in their own Rngs.
* Fixed documentation grammar and spelling in some of the altered interfaces due to RNG refactoring.
* Move `rng` argument to the end of the argument for most functions.
Also includes a reformatting due to Rust 1.30.
* Updated tests, accomodate `rng`-API changes.
* Fixed remaining compilation issues with new RNG code.
* Fix illegal `self` import outside curly braces.
* Cleaned up comments and fixed broken definition of `broadcast_input`.
* Updated existing test cases to properly work with static dispatch randomness.
* Do not use boxed `Rng`s for key generation in test networks.
* Use the passed-in `Rng` in `ReorderingAdversary`, instead of storing a boxed one.
* Fixed clippy lints after refactoring.
* Removed some no-longer necessary manual `fmt::Debug` implementations in test framework.
* Use `OsRng` even in tests in `binary_agreement_mitm`.
* Use a proper deterministic RNG in tests `binary_agreement_mitm`.
* Refactor `examples/simulation.rs` by not using `ThreadRng`, passing generic `Rng` parameters throughout and using a type alias instead of a newtype as the `Transaction`.
* Remove `thread_rng` use from `examples/node.rs`.
* Explicitly construct `InternalContrib` in `DynamicHoneyBadger::propose`.
* Fixed typo in description of `DistAlgorithm` trait.
2018-12-14 04:51:09 -08:00
|
|
|
fn handle_input<R: Rng>(&mut self, input: Self::Input, rng: &mut R) -> Result<Step<C, N>> {
|
|
|
|
self.propose(&input, rng)
|
2018-05-14 05:35:06 -07:00
|
|
|
}
|
|
|
|
|
OsRng / external RNG Refactoring (#357)
* Use `OsRng` in place of `thread_rng`.
This changes the defaults of any builder by instantiating an `OsRng` instead of
a `thread_rng`, the former being much more secure than the latter.
Additionally, all the unit tests that still instantiate RNGs manually used `OsRng`s
as well; while there is no actual need for this level of security in tests, the performance overhead is very small and random number generation complexity has such a small impact on these tests that the convenience of being able to ban `thread_rng` from the codebase altogether, setting a good example and avoid issues when refactoring later greatly outweigh the negatives.
* Instead of storing random number generators in the various consensus algorithm instances, pass them in from the outside whenever they are needed.
This changes a large amount of interfaces (and in this commit is only partially done, since `DistAlgorithm` needs to be fundamentally altered as well.
It also obsoletes parts of the `util` module.
* Added an `R: Rng` type parameter to both methods of `DistAlgorithm`, forcing callers to pass in their own Rngs.
* Fixed documentation grammar and spelling in some of the altered interfaces due to RNG refactoring.
* Move `rng` argument to the end of the argument for most functions.
Also includes a reformatting due to Rust 1.30.
* Updated tests, accomodate `rng`-API changes.
* Fixed remaining compilation issues with new RNG code.
* Fix illegal `self` import outside curly braces.
* Cleaned up comments and fixed broken definition of `broadcast_input`.
* Updated existing test cases to properly work with static dispatch randomness.
* Do not use boxed `Rng`s for key generation in test networks.
* Use the passed-in `Rng` in `ReorderingAdversary`, instead of storing a boxed one.
* Fixed clippy lints after refactoring.
* Removed some no-longer necessary manual `fmt::Debug` implementations in test framework.
* Use `OsRng` even in tests in `binary_agreement_mitm`.
* Use a proper deterministic RNG in tests `binary_agreement_mitm`.
* Refactor `examples/simulation.rs` by not using `ThreadRng`, passing generic `Rng` parameters throughout and using a type alias instead of a newtype as the `Transaction`.
* Remove `thread_rng` use from `examples/node.rs`.
* Explicitly construct `InternalContrib` in `DynamicHoneyBadger::propose`.
* Fixed typo in description of `DistAlgorithm` trait.
2018-12-14 04:51:09 -08:00
|
|
|
fn handle_message<R: Rng>(
|
|
|
|
&mut self,
|
|
|
|
sender_id: &Self::NodeId,
|
|
|
|
message: Self::Message,
|
|
|
|
_rng: &mut R,
|
|
|
|
) -> Result<Step<C, N>> {
|
2018-08-07 09:25:50 -07:00
|
|
|
self.handle_message(sender_id, message)
|
2018-05-14 05:35:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn terminated(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2018-08-02 14:27:55 -07:00
|
|
|
fn our_id(&self) -> &N {
|
2018-08-29 09:08:35 -07:00
|
|
|
self.netinfo.our_id()
|
2018-05-14 05:35:06 -07:00
|
|
|
}
|
2018-05-12 07:09:07 -07:00
|
|
|
}
|
|
|
|
|
2018-08-02 14:27:55 -07:00
|
|
|
impl<C, N> HoneyBadger<C, N>
|
2018-06-29 08:10:15 -07:00
|
|
|
where
|
2018-10-24 02:38:14 -07:00
|
|
|
C: Contribution + Serialize + DeserializeOwned,
|
2018-08-29 09:08:35 -07:00
|
|
|
N: NodeIdT + Rand,
|
2018-05-12 07:09:07 -07:00
|
|
|
{
|
2018-06-29 08:10:15 -07:00
|
|
|
/// Returns a new `HoneyBadgerBuilder` configured to use the node IDs and cryptographic keys
|
2018-06-28 14:07:11 -07:00
|
|
|
/// specified by `netinfo`.
|
2018-08-02 14:27:55 -07:00
|
|
|
pub fn builder(netinfo: Arc<NetworkInfo<N>>) -> HoneyBadgerBuilder<C, N> {
|
2018-06-28 14:07:11 -07:00
|
|
|
HoneyBadgerBuilder::new(netinfo)
|
|
|
|
}
|
|
|
|
|
2018-10-24 03:26:43 -07:00
|
|
|
/// Proposes a contribution in the current epoch.
|
|
|
|
///
|
|
|
|
/// Returns an error if we already made a proposal in this epoch.
|
|
|
|
///
|
|
|
|
/// If we are the only validator, this will immediately output a batch, containing our
|
|
|
|
/// proposal.
|
OsRng / external RNG Refactoring (#357)
* Use `OsRng` in place of `thread_rng`.
This changes the defaults of any builder by instantiating an `OsRng` instead of
a `thread_rng`, the former being much more secure than the latter.
Additionally, all the unit tests that still instantiate RNGs manually used `OsRng`s
as well; while there is no actual need for this level of security in tests, the performance overhead is very small and random number generation complexity has such a small impact on these tests that the convenience of being able to ban `thread_rng` from the codebase altogether, setting a good example and avoid issues when refactoring later greatly outweigh the negatives.
* Instead of storing random number generators in the various consensus algorithm instances, pass them in from the outside whenever they are needed.
This changes a large amount of interfaces (and in this commit is only partially done, since `DistAlgorithm` needs to be fundamentally altered as well.
It also obsoletes parts of the `util` module.
* Added an `R: Rng` type parameter to both methods of `DistAlgorithm`, forcing callers to pass in their own Rngs.
* Fixed documentation grammar and spelling in some of the altered interfaces due to RNG refactoring.
* Move `rng` argument to the end of the argument for most functions.
Also includes a reformatting due to Rust 1.30.
* Updated tests, accomodate `rng`-API changes.
* Fixed remaining compilation issues with new RNG code.
* Fix illegal `self` import outside curly braces.
* Cleaned up comments and fixed broken definition of `broadcast_input`.
* Updated existing test cases to properly work with static dispatch randomness.
* Do not use boxed `Rng`s for key generation in test networks.
* Use the passed-in `Rng` in `ReorderingAdversary`, instead of storing a boxed one.
* Fixed clippy lints after refactoring.
* Removed some no-longer necessary manual `fmt::Debug` implementations in test framework.
* Use `OsRng` even in tests in `binary_agreement_mitm`.
* Use a proper deterministic RNG in tests `binary_agreement_mitm`.
* Refactor `examples/simulation.rs` by not using `ThreadRng`, passing generic `Rng` parameters throughout and using a type alias instead of a newtype as the `Transaction`.
* Remove `thread_rng` use from `examples/node.rs`.
* Explicitly construct `InternalContrib` in `DynamicHoneyBadger::propose`.
* Fixed typo in description of `DistAlgorithm` trait.
2018-12-14 04:51:09 -08:00
|
|
|
pub fn propose<R: Rng>(&mut self, proposal: &C, rng: &mut R) -> Result<Step<C, N>> {
|
2018-06-29 08:20:54 -07:00
|
|
|
if !self.netinfo.is_validator() {
|
2018-07-23 09:11:45 -07:00
|
|
|
return Ok(Step::default());
|
2018-06-25 12:09:45 -07:00
|
|
|
}
|
2018-08-03 06:24:49 -07:00
|
|
|
self.has_input = true;
|
2018-08-07 09:25:50 -07:00
|
|
|
let epoch = self.epoch;
|
2018-10-25 12:11:44 -07:00
|
|
|
let step = {
|
2018-10-24 13:46:44 -07:00
|
|
|
let epoch_state = {
|
|
|
|
self.epoch_state_mut(epoch)?;
|
|
|
|
self.epochs.get_mut(&epoch).expect(
|
|
|
|
"We created the epoch_state in `self.epoch_state_mut(...)` just a moment ago.",
|
|
|
|
)
|
|
|
|
};
|
2018-10-25 11:38:16 -07:00
|
|
|
epoch_state.propose(proposal, rng)?
|
2018-10-21 13:47:44 -07:00
|
|
|
};
|
2018-10-25 05:44:28 -07:00
|
|
|
Ok(step.join(self.try_output_batches()?))
|
2018-05-12 07:09:07 -07:00
|
|
|
}
|
|
|
|
|
2018-08-07 09:25:50 -07:00
|
|
|
/// Handles a message received from `sender_id`.
|
2018-10-24 03:26:43 -07:00
|
|
|
///
|
|
|
|
/// This must be called with every message we receive from another node.
|
|
|
|
pub fn handle_message(&mut self, sender_id: &N, message: Message<N>) -> Result<Step<C, N>> {
|
2018-10-09 07:07:56 -07:00
|
|
|
if !self.netinfo.is_node_validator(sender_id) {
|
2018-11-26 06:35:24 -08:00
|
|
|
return Err(Error::UnknownSender);
|
2018-08-07 09:25:50 -07:00
|
|
|
}
|
2018-10-09 07:07:56 -07:00
|
|
|
let Message { epoch, content } = message;
|
2018-11-18 01:18:14 -08:00
|
|
|
if epoch > self.epoch + self.params.max_future_epochs {
|
2018-11-07 08:21:24 -08:00
|
|
|
Ok(Fault::new(sender_id.clone(), FaultKind::UnexpectedHbMessageEpoch).into())
|
|
|
|
} else if epoch < self.epoch {
|
|
|
|
// The message is late; discard it.
|
|
|
|
Ok(Step::default())
|
|
|
|
} else {
|
2018-10-25 05:44:28 -07:00
|
|
|
let step = self
|
2018-08-07 09:25:50 -07:00
|
|
|
.epoch_state_mut(epoch)?
|
|
|
|
.handle_message_content(sender_id, content)?;
|
2018-10-25 08:07:52 -07:00
|
|
|
Ok(step.join(self.try_output_batches()?))
|
|
|
|
}
|
2018-08-07 09:25:50 -07:00
|
|
|
}
|
|
|
|
|
2018-07-09 05:29:01 -07:00
|
|
|
/// Returns `true` if input for the current epoch has already been provided.
|
|
|
|
pub fn has_input(&self) -> bool {
|
2018-07-12 08:53:12 -07:00
|
|
|
!self.netinfo.is_validator() || self.has_input
|
2018-05-16 05:23:57 -07:00
|
|
|
}
|
|
|
|
|
2018-11-07 08:21:24 -08:00
|
|
|
/// Returns the current encryption schedule that determines in which epochs contributions are
|
|
|
|
/// encrypted.
|
2018-10-25 11:38:16 -07:00
|
|
|
pub fn get_encryption_schedule(&self) -> EncryptionSchedule {
|
2018-11-18 01:18:14 -08:00
|
|
|
self.params.encryption_schedule
|
2018-10-25 11:38:16 -07:00
|
|
|
}
|
|
|
|
|
2018-11-15 06:30:53 -08:00
|
|
|
/// Returns the epoch of the next batch that will be output.
|
|
|
|
pub fn next_epoch(&self) -> u64 {
|
2018-11-07 08:21:24 -08:00
|
|
|
self.epoch
|
|
|
|
}
|
|
|
|
|
2018-08-01 01:41:09 -07:00
|
|
|
/// Returns the number of validators from which we have already received a proposal for the
|
|
|
|
/// current epoch.
|
2018-12-03 05:30:32 -08:00
|
|
|
///
|
|
|
|
/// This can be used to find out whether our node is stalling progress. Depending on the
|
|
|
|
/// application logic, nodes may e.g. only propose when they have any pending transactions. In
|
|
|
|
/// that case, they should repeatedly call this method: if it returns _f + 1_ or more, that
|
|
|
|
/// means at least one correct node has proposed a contribution. In that case, we might want to
|
|
|
|
/// propose one, too, even if it's empty, to avoid unnecessarily delaying the next batch.
|
|
|
|
pub fn received_proposals(&self) -> usize {
|
2018-08-03 06:24:49 -07:00
|
|
|
self.epochs
|
2018-08-01 01:41:09 -07:00
|
|
|
.get(&self.epoch)
|
2018-08-03 06:24:49 -07:00
|
|
|
.map_or(0, EpochState::received_proposals)
|
2018-08-01 01:41:09 -07:00
|
|
|
}
|
|
|
|
|
2018-06-19 07:17:16 -07:00
|
|
|
/// Increments the epoch number and clears any state that is local to the finished epoch.
|
2018-10-25 08:07:52 -07:00
|
|
|
fn update_epoch(&mut self) {
|
2018-06-19 07:17:16 -07:00
|
|
|
// Clear the state of the old epoch.
|
2018-08-03 06:24:49 -07:00
|
|
|
self.epochs.remove(&self.epoch);
|
2018-06-19 07:17:16 -07:00
|
|
|
self.epoch += 1;
|
2018-07-09 05:29:01 -07:00
|
|
|
self.has_input = false;
|
2018-06-19 07:17:16 -07:00
|
|
|
}
|
|
|
|
|
2018-07-12 08:53:12 -07:00
|
|
|
/// Tries to decrypt contributions from all proposers and output those in a batch.
|
2018-08-02 14:27:55 -07:00
|
|
|
fn try_output_batches(&mut self) -> Result<Step<C, N>> {
|
2018-07-23 09:11:45 -07:00
|
|
|
let mut step = Step::default();
|
2018-08-03 06:24:49 -07:00
|
|
|
while let Some((batch, fault_log)) = self
|
|
|
|
.epochs
|
|
|
|
.get(&self.epoch)
|
|
|
|
.and_then(EpochState::try_output_batch)
|
|
|
|
{
|
|
|
|
// Queue the output and advance the epoch.
|
2018-10-25 05:44:28 -07:00
|
|
|
step.output.push(batch);
|
2018-08-03 06:24:49 -07:00
|
|
|
step.fault_log.extend(fault_log);
|
2018-10-25 08:07:52 -07:00
|
|
|
self.update_epoch();
|
2018-07-23 12:36:09 -07:00
|
|
|
}
|
2018-07-23 09:11:45 -07:00
|
|
|
Ok(step)
|
2018-06-19 07:17:16 -07:00
|
|
|
}
|
2018-08-07 09:25:50 -07:00
|
|
|
|
|
|
|
/// Returns a mutable reference to the state of the given `epoch`. Initializes a new one, if it
|
|
|
|
/// doesn't exist yet.
|
|
|
|
fn epoch_state_mut(&mut self, epoch: u64) -> Result<&mut EpochState<C, N>> {
|
|
|
|
Ok(match self.epochs.entry(epoch) {
|
|
|
|
Entry::Occupied(entry) => entry.into_mut(),
|
2018-09-29 18:46:42 -07:00
|
|
|
Entry::Vacant(entry) => entry.insert(EpochState::new(
|
|
|
|
self.netinfo.clone(),
|
2018-10-24 00:42:59 -07:00
|
|
|
self.session_id,
|
2018-09-29 18:46:42 -07:00
|
|
|
epoch,
|
2018-11-18 01:18:14 -08:00
|
|
|
self.params.subset_handling_strategy.clone(),
|
|
|
|
self.params.encryption_schedule.use_on_epoch(epoch),
|
2018-09-29 18:46:42 -07:00
|
|
|
)?),
|
2018-08-07 09:25:50 -07:00
|
|
|
})
|
|
|
|
}
|
2018-10-25 08:07:52 -07:00
|
|
|
|
|
|
|
/// Returns the maximum future epochs of the Honey Badger algorithm instance.
|
|
|
|
pub fn max_future_epochs(&self) -> u64 {
|
2018-11-18 01:18:14 -08:00
|
|
|
self.params.max_future_epochs
|
2018-10-25 08:07:52 -07:00
|
|
|
}
|
2018-11-19 05:51:32 -08:00
|
|
|
|
|
|
|
/// Returns the parameters controlling Honey Badger's behavior and performance.
|
|
|
|
pub fn params(&self) -> &Params {
|
|
|
|
&self.params
|
|
|
|
}
|
2018-05-12 07:09:07 -07:00
|
|
|
}
|
2018-11-12 03:24:29 -08:00
|
|
|
|
|
|
|
/// How frequently Threshold Encryption should be used.
|
|
|
|
#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash, Debug)]
|
|
|
|
pub enum EncryptionSchedule {
|
2018-11-26 06:35:24 -08:00
|
|
|
/// Always encrypt. All contributions are encrypted in every epoch.
|
2018-11-12 03:24:29 -08:00
|
|
|
Always,
|
2018-11-26 06:35:24 -08:00
|
|
|
/// Never encrypt. All contributions are plaintext in every epoch.
|
2018-11-12 03:24:29 -08:00
|
|
|
Never,
|
2018-11-26 06:35:24 -08:00
|
|
|
/// Every _n_-th epoch uses encryption. In all other epochs, contributions are plaintext.
|
2018-11-12 03:24:29 -08:00
|
|
|
EveryNthEpoch(u32),
|
2018-11-26 06:35:24 -08:00
|
|
|
/// With `TickTock(n, m)`, `n` epochs use encryption, followed by `m` epochs that don't.
|
|
|
|
/// `m` out of `n + m` epochs will use plaintext contributions.
|
2018-11-12 03:24:29 -08:00
|
|
|
TickTock(u32, u32),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EncryptionSchedule {
|
2018-11-26 06:35:24 -08:00
|
|
|
/// Returns `true` if the contributions in the `epoch` should be encrypted.
|
2018-11-12 03:24:29 -08:00
|
|
|
pub fn use_on_epoch(self, epoch: u64) -> bool {
|
|
|
|
match self {
|
|
|
|
EncryptionSchedule::Always => true,
|
|
|
|
EncryptionSchedule::Never => false,
|
|
|
|
EncryptionSchedule::EveryNthEpoch(n) => (epoch % u64::from(n)) == 0,
|
|
|
|
EncryptionSchedule::TickTock(on, off) => (epoch % u64::from(on + off)) <= u64::from(on),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|