mirror of https://github.com/poanetwork/hbbft.git
Add a random_value option to HB and DHB.
This includes a threshold signature in each batch that can be used as a pseudorandom value. Also moves `EncryptionSchedule` from `threshold_decrypt` to `honey_badger`.
This commit is contained in:
parent
e4435d5622
commit
30cce9bed8
|
@ -1,6 +1,8 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crypto::Signature;
|
||||
|
||||
use super::EncryptionSchedule;
|
||||
use super::{ChangeState, JoinPlan};
|
||||
use {NetworkInfo, NodeIdT};
|
||||
|
@ -14,6 +16,8 @@ pub struct Batch<C, N> {
|
|||
pub(super) era: u64,
|
||||
/// The user contributions committed in this epoch.
|
||||
pub(super) contributions: BTreeMap<N, C>,
|
||||
/// The signature that can be used as a pseudorandom value.
|
||||
pub(super) random_value: Option<Signature>,
|
||||
/// The current state of adding or removing a node: whether any is in progress, or completed
|
||||
/// this epoch.
|
||||
pub(super) change: ChangeState<N>,
|
||||
|
@ -102,6 +106,7 @@ impl<C, N: NodeIdT> Batch<C, N> {
|
|||
pub_key_set: self.netinfo.public_key_set().clone(),
|
||||
pub_keys: self.netinfo.public_key_map().clone(),
|
||||
encryption_schedule: self.encryption_schedule,
|
||||
random_value: self.random_value.is_some(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -119,4 +124,12 @@ impl<C, N: NodeIdT> Batch<C, N> {
|
|||
&& self.netinfo.public_key_map() == other.netinfo.public_key_map()
|
||||
&& self.encryption_schedule == other.encryption_schedule
|
||||
}
|
||||
|
||||
/// Returns the signature that can be used as a pseudorandom value: None of the validators knew
|
||||
/// its value before the other of the batch were decided.
|
||||
///
|
||||
/// If the `random_value` option is `false` (default), this is `None`.
|
||||
pub fn random_value(&self) -> Option<&Signature> {
|
||||
self.random_value.as_ref()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ use crypto::{SecretKey, SecretKeySet, SecretKeyShare};
|
|||
use rand::{self, Rand, Rng};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
use super::{Change, ChangeState, DynamicHoneyBadger, JoinPlan, Result, Step, VoteCounter};
|
||||
use super::{
|
||||
Change, ChangeState, DynamicHoneyBadger, EncryptionSchedule, JoinPlan, Result, Step,
|
||||
VoteCounter,
|
||||
};
|
||||
use honey_badger::{HoneyBadger, SubsetHandlingStrategy};
|
||||
use threshold_decrypt::EncryptionSchedule;
|
||||
use util::SubRng;
|
||||
use {Contribution, NetworkInfo, NodeIdT};
|
||||
|
||||
|
@ -25,6 +27,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,
|
||||
/// Whether to generate a pseudorandom value in each epoch.
|
||||
random_value: bool,
|
||||
/// Schedule for adding threshold encryption to some percentage of rounds
|
||||
encryption_schedule: EncryptionSchedule,
|
||||
_phantom: PhantomData<(C, N)>,
|
||||
|
@ -41,6 +45,7 @@ where
|
|||
max_future_epochs: 3,
|
||||
rng: Box::new(rand::thread_rng()),
|
||||
subset_handling_strategy: SubsetHandlingStrategy::Incremental,
|
||||
random_value: false,
|
||||
encryption_schedule: EncryptionSchedule::Always,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
|
@ -85,6 +90,12 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
/// Whether to generate a pseudorandom value in each epoch.
|
||||
pub fn random_value(&mut self, random_value: bool) -> &mut Self {
|
||||
self.random_value = random_value;
|
||||
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;
|
||||
|
@ -98,6 +109,7 @@ where
|
|||
max_future_epochs,
|
||||
rng,
|
||||
subset_handling_strategy,
|
||||
random_value,
|
||||
encryption_schedule,
|
||||
_phantom,
|
||||
} = self;
|
||||
|
@ -109,6 +121,7 @@ where
|
|||
.max_future_epochs(max_future_epochs)
|
||||
.rng(rng.sub_rng())
|
||||
.subset_handling_strategy(subset_handling_strategy.clone())
|
||||
.random_value(*random_value)
|
||||
.encryption_schedule(*encryption_schedule)
|
||||
.build();
|
||||
DynamicHoneyBadger {
|
||||
|
@ -153,6 +166,7 @@ where
|
|||
let honey_badger = HoneyBadger::builder(arc_netinfo.clone())
|
||||
.max_future_epochs(self.max_future_epochs)
|
||||
.encryption_schedule(join_plan.encryption_schedule)
|
||||
.random_value(join_plan.random_value)
|
||||
.build();
|
||||
let mut dhb = DynamicHoneyBadger {
|
||||
netinfo,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crypto::PublicKey;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use threshold_decrypt::EncryptionSchedule;
|
||||
|
||||
use super::EncryptionSchedule;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash, Debug)]
|
||||
pub enum NodeChange<N> {
|
||||
|
|
|
@ -11,15 +11,14 @@ use serde::{de::DeserializeOwned, Serialize};
|
|||
|
||||
use super::votes::{SignedVote, VoteCounter};
|
||||
use super::{
|
||||
Batch, Change, ChangeState, DynamicHoneyBadgerBuilder, Error, ErrorKind, Input,
|
||||
InternalContrib, KeyGenMessage, KeyGenState, Message, NodeChange, Result, SignedKeyGenMsg,
|
||||
Step,
|
||||
Batch, Change, ChangeState, DynamicHoneyBadgerBuilder, EncryptionSchedule, Error, ErrorKind,
|
||||
Input, InternalContrib, KeyGenMessage, KeyGenState, Message, NodeChange, Result,
|
||||
SignedKeyGenMsg, Step,
|
||||
};
|
||||
use fault_log::{Fault, FaultKind, FaultLog};
|
||||
use honey_badger::{self, HoneyBadger, Message as HbMessage};
|
||||
|
||||
use sync_key_gen::{Ack, AckOutcome, Part, PartOutcome, SyncKeyGen};
|
||||
use threshold_decrypt::EncryptionSchedule;
|
||||
use util::{self, SubRng};
|
||||
use {Contribution, DistAlgorithm, Epoched, NetworkInfo, NodeIdT, Target};
|
||||
|
||||
|
@ -319,6 +318,7 @@ where
|
|||
change,
|
||||
netinfo: Arc::new(self.netinfo.clone()),
|
||||
contributions: batch_contributions,
|
||||
random_value: hb_batch.random_value,
|
||||
encryption_schedule: self.honey_badger.get_encryption_schedule(),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -79,8 +79,7 @@ use rand::Rand;
|
|||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use self::votes::{SignedVote, VoteCounter};
|
||||
use super::threshold_decrypt::EncryptionSchedule;
|
||||
use honey_badger::Message as HbMessage;
|
||||
use honey_badger::{EncryptionSchedule, Message as HbMessage};
|
||||
use sync_key_gen::{Ack, Part, SyncKeyGen};
|
||||
use NodeIdT;
|
||||
|
||||
|
@ -148,6 +147,8 @@ pub struct JoinPlan<N: Ord> {
|
|||
pub_keys: BTreeMap<N, PublicKey>,
|
||||
/// The current encryption schedule for threshold cryptography.
|
||||
encryption_schedule: EncryptionSchedule,
|
||||
/// Whether to generate a pseudorandom value in each epoch.
|
||||
random_value: bool,
|
||||
}
|
||||
|
||||
/// The ongoing key generation, together with information about the validator change.
|
||||
|
|
|
@ -22,6 +22,8 @@ pub enum FaultKind {
|
|||
InvalidCiphertext,
|
||||
/// `HoneyBadger` received a message with an invalid epoch.
|
||||
UnexpectedHbMessageEpoch,
|
||||
/// `HoneyBadger` received a signatures share for the random value even though it is disabled.
|
||||
UnexpectedSignatureShare,
|
||||
/// `ThresholdDecrypt` received multiple shares from the same sender.
|
||||
MultipleDecryptionShares,
|
||||
/// `Broadcast` received a `Value` from a node other than the proposer.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crypto::Signature;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use NodeIdT;
|
||||
|
@ -5,8 +6,15 @@ use NodeIdT;
|
|||
/// A batch of contributions the algorithm has output.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Batch<C, N> {
|
||||
/// This batch's epoch number. Each epoch produces exactly one batch.
|
||||
pub epoch: u64,
|
||||
/// The set of agreed contributions, by the contributor's node ID.
|
||||
pub contributions: BTreeMap<N, C>,
|
||||
/// The signature that can be used as a pseudorandom value: None of the validators knew
|
||||
/// its value before the other of the batch were decided.
|
||||
///
|
||||
/// If the `random_value` option is `false` (default), this is `None`.
|
||||
pub random_value: Option<Signature>,
|
||||
}
|
||||
|
||||
impl<C, N: NodeIdT> Batch<C, N> {
|
||||
|
|
|
@ -5,9 +5,8 @@ use std::sync::Arc;
|
|||
use rand::{self, Rand, Rng};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
use super::HoneyBadger;
|
||||
use super::{EncryptionSchedule, HoneyBadger};
|
||||
use honey_badger::SubsetHandlingStrategy;
|
||||
use threshold_decrypt::EncryptionSchedule;
|
||||
use util::SubRng;
|
||||
use {Contribution, NetworkInfo, NodeIdT};
|
||||
|
||||
|
@ -26,6 +25,8 @@ pub struct HoneyBadgerBuilder<C, N> {
|
|||
rng: Box<dyn Rng>,
|
||||
/// Strategy used to handle the output of the `Subset` algorithm.
|
||||
subset_handling_strategy: SubsetHandlingStrategy,
|
||||
/// Whether to generate a pseudorandom value in each epoch.
|
||||
random_value: bool,
|
||||
/// Schedule for adding threshold encryption to some percentage of rounds
|
||||
encryption_schedule: EncryptionSchedule,
|
||||
_phantom: PhantomData<C>,
|
||||
|
@ -46,6 +47,7 @@ where
|
|||
max_future_epochs: 3,
|
||||
rng: Box::new(rand::thread_rng()),
|
||||
subset_handling_strategy: SubsetHandlingStrategy::Incremental,
|
||||
random_value: false,
|
||||
encryption_schedule: EncryptionSchedule::Always,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
|
@ -87,6 +89,12 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
/// Whether to generate a pseudorandom value in each epoch.
|
||||
pub fn random_value(&mut self, random_value: bool) -> &mut Self {
|
||||
self.random_value = random_value;
|
||||
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;
|
||||
|
@ -105,6 +113,7 @@ where
|
|||
rng: Box::new(self.rng.sub_rng()),
|
||||
subset_handling_strategy: self.subset_handling_strategy.clone(),
|
||||
encryption_schedule: self.encryption_schedule,
|
||||
random_value: self.random_value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::result;
|
|||
use std::sync::Arc;
|
||||
|
||||
use bincode;
|
||||
use crypto::Ciphertext;
|
||||
use crypto::{Ciphertext, Signature};
|
||||
use log::error;
|
||||
use rand::{Rand, Rng};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
@ -17,10 +17,44 @@ use super::{Batch, ErrorKind, MessageContent, Result, Step};
|
|||
use fault_log::{Fault, FaultKind, FaultLog};
|
||||
use subset::{self as cs, Subset, SubsetOutput};
|
||||
use threshold_decrypt::{self as td, ThresholdDecrypt};
|
||||
use threshold_sign::{self as ts, ThresholdSign};
|
||||
use {Contribution, DistAlgorithm, NetworkInfo, NodeIdT};
|
||||
|
||||
type CsStep<N> = cs::Step<N>;
|
||||
|
||||
/// The status of the threshold signature for the random value.
|
||||
#[derive(Debug)]
|
||||
enum SigningState<N> {
|
||||
/// No random value is required in this epoch.
|
||||
None,
|
||||
/// Signing is ongoing.
|
||||
Ongoing(Box<ThresholdSign<N>>),
|
||||
/// Signing is complete. This contains the signature.
|
||||
Complete(Box<Signature>),
|
||||
}
|
||||
|
||||
impl<N: NodeIdT> SigningState<N> {
|
||||
/// Handles a message containing a decryption share.
|
||||
fn handle_message(&mut self, sender_id: &N, msg: ts::Message) -> ts::Result<ts::Step<N>> {
|
||||
match self {
|
||||
SigningState::None => {
|
||||
let fault_kind = FaultKind::UnexpectedSignatureShare;
|
||||
Ok(Fault::new(sender_id.clone(), fault_kind).into())
|
||||
}
|
||||
SigningState::Ongoing(ref mut ts) => ts.handle_message(sender_id, msg),
|
||||
SigningState::Complete(_) => Ok(ts::Step::default()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends the signatures shares.
|
||||
fn sign(&mut self) -> ts::Result<ts::Step<N>> {
|
||||
match self {
|
||||
SigningState::Ongoing(ref mut ts) => ts.sign(),
|
||||
SigningState::None | SigningState::Complete(_) => Ok(ts::Step::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of an encrypted contribution.
|
||||
#[derive(Debug)]
|
||||
enum DecryptionState<N> {
|
||||
|
@ -188,10 +222,13 @@ pub struct EpochState<C, N: Rand> {
|
|||
subset: SubsetState<N>,
|
||||
/// The status of threshold decryption, by proposer.
|
||||
decryption: BTreeMap<N, DecryptionState<N>>,
|
||||
/// The status of the threshold signature for the random value.
|
||||
signing: SigningState<N>,
|
||||
/// Nodes found so far in `Subset` output.
|
||||
accepted_proposers: BTreeSet<N>,
|
||||
/// Determines the behavior upon receiving proposals from `subset`.
|
||||
subset_handler: SubsetHandler<N>,
|
||||
/// Whether contributions should be encrypted in this epoch.
|
||||
require_decryption: bool,
|
||||
_phantom: PhantomData<C>,
|
||||
}
|
||||
|
@ -207,15 +244,26 @@ where
|
|||
hb_id: u64,
|
||||
epoch: u64,
|
||||
subset_handling_strategy: SubsetHandlingStrategy,
|
||||
random_value: bool,
|
||||
require_decryption: bool,
|
||||
) -> Result<Self> {
|
||||
let epoch_id = EpochId { hb_id, epoch };
|
||||
let cs = Subset::new(netinfo.clone(), epoch_id).map_err(ErrorKind::CreateSubset)?;
|
||||
let signing = if random_value {
|
||||
let rand_id = ("random_value", hb_id, epoch);
|
||||
let doc = bincode::serialize(&rand_id).map_err(|err| ErrorKind::RandBincode(*err))?;
|
||||
let ts = ThresholdSign::new_with_document(netinfo.clone(), doc)
|
||||
.map_err(ErrorKind::CreateThresholdSign)?;
|
||||
SigningState::Ongoing(Box::new(ts))
|
||||
} else {
|
||||
SigningState::None
|
||||
};
|
||||
Ok(EpochState {
|
||||
epoch,
|
||||
netinfo,
|
||||
subset: SubsetState::Ongoing(cs),
|
||||
decryption: BTreeMap::default(),
|
||||
signing,
|
||||
accepted_proposers: Default::default(),
|
||||
subset_handler: subset_handling_strategy.into(),
|
||||
require_decryption,
|
||||
|
@ -273,12 +321,24 @@ where
|
|||
.map_err(ErrorKind::ThresholdDecrypt)?;
|
||||
self.process_decryption(proposer_id, td_step)
|
||||
}
|
||||
MessageContent::SignatureShare(share) => {
|
||||
let ts_step = self
|
||||
.signing
|
||||
.handle_message(sender_id, share)
|
||||
.map_err(ErrorKind::ThresholdSign)?;
|
||||
self.process_signing(ts_step)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When contributions of transactions have been decrypted for all valid proposers in this
|
||||
/// epoch, moves those contributions into a batch, outputs the batch and updates the epoch.
|
||||
pub fn try_output_batch(&self) -> Option<(Batch<C, N>, FaultLog<N>)> {
|
||||
let random_value = match &self.signing {
|
||||
SigningState::None => None,
|
||||
SigningState::Ongoing(_) => return None,
|
||||
SigningState::Complete(signature) => Some(*signature.clone()),
|
||||
};
|
||||
let proposer_ids = self.subset.accepted_ids()?;
|
||||
let mut plaintexts = Vec::new();
|
||||
// Collect accepted plaintexts. Return if some are not decrypted yet.
|
||||
|
@ -293,6 +353,7 @@ where
|
|||
let mut batch = Batch {
|
||||
epoch: self.epoch,
|
||||
contributions: BTreeMap::new(),
|
||||
random_value,
|
||||
};
|
||||
// Deserialize the output. If it fails, the proposer of that item is faulty.
|
||||
for (id, plaintext) in plaintexts {
|
||||
|
@ -336,6 +397,8 @@ where
|
|||
}
|
||||
|
||||
if is_done {
|
||||
let ts_state = self.signing.sign().map_err(ErrorKind::ThresholdSign)?;
|
||||
step.extend(self.process_signing(ts_state)?);
|
||||
self.subset = SubsetState::Complete(self.accepted_proposers.clone());
|
||||
let faulty_shares: Vec<_> = self
|
||||
.decryption
|
||||
|
@ -373,6 +436,18 @@ where
|
|||
Ok(step)
|
||||
}
|
||||
|
||||
/// Processes a Threshold Sign step.
|
||||
fn process_signing(&mut self, ts_step: ts::Step<N>) -> Result<Step<C, N>> {
|
||||
let mut step = Step::default();
|
||||
let opt_output = step.extend_with(ts_step, |share| {
|
||||
MessageContent::SignatureShare(share).with_epoch(self.epoch)
|
||||
});
|
||||
if let Some(output) = opt_output.into_iter().next() {
|
||||
self.signing = SigningState::Complete(Box::new(output));
|
||||
}
|
||||
Ok(step)
|
||||
}
|
||||
|
||||
/// Given the output of the Subset algorithm, inputs the ciphertexts into the Threshold
|
||||
/// Decrypt instances and sends our own decryption shares.
|
||||
fn send_decryption_share(&mut self, proposer_id: N, v: &[u8]) -> Result<Step<C, N>> {
|
||||
|
|
|
@ -5,20 +5,27 @@ use failure::{Backtrace, Context, Fail};
|
|||
|
||||
use subset;
|
||||
use threshold_decrypt;
|
||||
use threshold_sign;
|
||||
|
||||
/// Honey badger error variants.
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum ErrorKind {
|
||||
#[fail(display = "ProposeBincode error: {}", _0)]
|
||||
ProposeBincode(bincode::ErrorKind),
|
||||
#[fail(display = "Error serializing random value document: {}", _0)]
|
||||
RandBincode(bincode::ErrorKind),
|
||||
#[fail(display = "Failed to instantiate Subset: {}", _0)]
|
||||
CreateSubset(subset::Error),
|
||||
#[fail(display = "Failed to instantiate ThresholdSign: {}", _0)]
|
||||
CreateThresholdSign(threshold_sign::Error),
|
||||
#[fail(display = "Failed to input contribution to Subset: {}", _0)]
|
||||
InputSubset(subset::Error),
|
||||
#[fail(display = "Failed to handle Subset message: {}", _0)]
|
||||
HandleSubsetMessage(subset::Error),
|
||||
#[fail(display = "Threshold decryption error: {}", _0)]
|
||||
ThresholdDecrypt(threshold_decrypt::Error),
|
||||
#[fail(display = "Threshold signing error: {}", _0)]
|
||||
ThresholdSign(threshold_sign::Error),
|
||||
#[fail(display = "Unknown sender")]
|
||||
UnknownSender,
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ use std::sync::Arc;
|
|||
use derivative::Derivative;
|
||||
use rand::{Rand, Rng};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use super::epoch_state::EpochState;
|
||||
use super::{Batch, Error, ErrorKind, HoneyBadgerBuilder, Message, Result};
|
||||
use {util, Contribution, DistAlgorithm, Fault, FaultKind, NetworkInfo, NodeIdT};
|
||||
|
||||
pub use super::epoch_state::SubsetHandlingStrategy;
|
||||
use threshold_decrypt::EncryptionSchedule;
|
||||
|
||||
/// An instance of the Honey Badger Byzantine fault tolerant consensus algorithm.
|
||||
#[derive(Derivative)]
|
||||
|
@ -38,6 +38,8 @@ pub struct HoneyBadger<C, N: Rand> {
|
|||
pub(super) subset_handling_strategy: SubsetHandlingStrategy,
|
||||
/// The schedule for which rounds we should use threshold encryption.
|
||||
pub(super) encryption_schedule: EncryptionSchedule,
|
||||
/// Whether to generate a pseudorandom value in each epoch.
|
||||
pub(super) random_value: bool,
|
||||
}
|
||||
|
||||
pub type Step<C, N> = ::DaStep<HoneyBadger<C, N>>;
|
||||
|
@ -185,6 +187,7 @@ where
|
|||
self.session_id,
|
||||
epoch,
|
||||
self.subset_handling_strategy.clone(),
|
||||
self.random_value,
|
||||
self.encryption_schedule.use_on_epoch(epoch),
|
||||
)?),
|
||||
})
|
||||
|
@ -195,3 +198,24 @@ where
|
|||
self.max_future_epochs
|
||||
}
|
||||
}
|
||||
|
||||
/// 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),
|
||||
}
|
||||
|
||||
impl EncryptionSchedule {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,12 @@ use serde_derive::{Deserialize, Serialize};
|
|||
|
||||
use subset;
|
||||
use threshold_decrypt;
|
||||
use threshold_sign;
|
||||
|
||||
/// The content of a `HoneyBadger` message. It should be further annotated with an epoch.
|
||||
#[derive(Clone, Debug, Deserialize, Rand, Serialize)]
|
||||
// `threshold_sign::Message` triggers this Clippy lint, but `Box<T>` doesn't implement `Rand`.
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(large_enum_variant))]
|
||||
pub enum MessageContent<N: Rand> {
|
||||
/// A message belonging to the subset algorithm in the given epoch.
|
||||
Subset(subset::Message<N>),
|
||||
|
@ -15,6 +18,8 @@ pub enum MessageContent<N: Rand> {
|
|||
proposer_id: N,
|
||||
share: threshold_decrypt::Message,
|
||||
},
|
||||
/// A share of the signature used as a pseudorandom value.
|
||||
SignatureShare(threshold_sign::Message),
|
||||
}
|
||||
|
||||
impl<N: Rand> MessageContent<N> {
|
||||
|
|
|
@ -32,5 +32,5 @@ mod message;
|
|||
pub use self::batch::Batch;
|
||||
pub use self::builder::HoneyBadgerBuilder;
|
||||
pub use self::error::{Error, ErrorKind, Result};
|
||||
pub use self::honey_badger::{HoneyBadger, Step, SubsetHandlingStrategy};
|
||||
pub use self::honey_badger::{EncryptionSchedule, HoneyBadger, Step, SubsetHandlingStrategy};
|
||||
pub use self::message::{Message, MessageContent};
|
||||
|
|
|
@ -22,27 +22,6 @@ use serde_derive::{Deserialize, Serialize};
|
|||
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),
|
||||
}
|
||||
|
||||
impl EncryptionSchedule {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A threshold decryption error.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
|
|
|
@ -21,7 +21,8 @@ use itertools::Itertools;
|
|||
use log::info;
|
||||
use rand::Rng;
|
||||
|
||||
use hbbft::honey_badger::{Batch, HoneyBadger, MessageContent};
|
||||
use hbbft::crypto::Signature;
|
||||
use hbbft::honey_badger::{Batch, EncryptionSchedule, HoneyBadger, MessageContent};
|
||||
use hbbft::sender_queue::{self, SenderQueue, Step};
|
||||
use hbbft::transaction_queue::TransactionQueue;
|
||||
use hbbft::{threshold_decrypt, DistAlgorithm, NetworkInfo, Target, TargetedMessage};
|
||||
|
@ -163,17 +164,21 @@ fn verify_output_sequence<A>(network: &TestNetwork<A, UsizeHoneyBadger>)
|
|||
where
|
||||
A: Adversary<UsizeHoneyBadger>,
|
||||
{
|
||||
let mut expected: Option<BTreeMap<&_, &_>> = None;
|
||||
let mut expected: Option<BTreeMap<&_, (&_, &_)>> = None;
|
||||
for node in network.nodes.values() {
|
||||
assert!(!node.outputs().is_empty());
|
||||
let outputs: BTreeMap<&u64, &BTreeMap<NodeId, Vec<usize>>> = node
|
||||
let outputs: BTreeMap<&u64, (&BTreeMap<NodeId, Vec<usize>>, &Signature)> = node
|
||||
.outputs()
|
||||
.iter()
|
||||
.map(
|
||||
|Batch {
|
||||
epoch,
|
||||
contributions,
|
||||
}| (epoch, contributions),
|
||||
random_value,
|
||||
}| {
|
||||
let random_value = random_value.as_ref().expect("missing random value");
|
||||
(epoch, (contributions, random_value))
|
||||
},
|
||||
).collect();
|
||||
if expected.is_none() {
|
||||
expected = Some(outputs);
|
||||
|
@ -194,7 +199,11 @@ fn new_honey_badger(
|
|||
.filter(|&&them| them != our_id)
|
||||
.cloned()
|
||||
.chain(iter::once(observer));
|
||||
SenderQueue::builder(HoneyBadger::builder(netinfo).build(), peer_ids).build(our_id)
|
||||
let hb = HoneyBadger::builder(netinfo)
|
||||
.encryption_schedule(EncryptionSchedule::EveryNthEpoch(2))
|
||||
.random_value(true)
|
||||
.build();
|
||||
SenderQueue::builder(hb, peer_ids).build(our_id)
|
||||
}
|
||||
|
||||
fn test_honey_badger_different_sizes<A, F>(new_adversary: F, num_txs: usize)
|
||||
|
|
Loading…
Reference in New Issue