Remove non-threshold keys from NetworkInfo.

This commit is contained in:
Andreas Fackler 2019-08-25 14:41:50 +02:00 committed by Andreas Fackler
parent 66033a9f7f
commit 0e50c2f473
17 changed files with 296 additions and 278 deletions

View File

@ -32,7 +32,7 @@ log = "0.4.6"
rand = "0.6.5"
rand_derive = "0.5.0"
reed-solomon-erasure = "3.1.1"
serde = { version = "1.0.89", features = ["derive"] }
serde = { version = "1.0.89", features = ["derive", "rc"] }
threshold_crypto = "0.3.1"
tiny-keccak = "1.4"

View File

@ -11,10 +11,11 @@ use rand_derive::Rand;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use signifix::metric;
use hbbft::crypto::SecretKey;
use hbbft::dynamic_honey_badger::DynamicHoneyBadger;
use hbbft::queueing_honey_badger::{Batch, QueueingHoneyBadger};
use hbbft::sender_queue::{Message, SenderQueue};
use hbbft::{ConsensusProtocol, CpStep, NetworkInfo, Step, Target};
use hbbft::{to_pub_keys, ConsensusProtocol, CpStep, NetworkInfo, PubKeyMap, Step, Target};
const VERSION: &str = env!("CARGO_PKG_VERSION");
const USAGE: &str = "
@ -247,13 +248,19 @@ where
rng: &mut R,
) -> TestNetwork<D>
where
F: Fn(NetworkInfo<NodeId>, &mut R) -> (D, CpStep<D>),
F: Fn(NetworkInfo<NodeId>, SecretKey, PubKeyMap<NodeId>, &mut R) -> (D, CpStep<D>),
{
let node_ids = (0..(good_num + adv_num)).map(NodeId);
let netinfos =
NetworkInfo::generate_map(node_ids, rng).expect("Failed to create `NetworkInfo` map");
// Generate keys for signing and encrypting messages, and for threshold cryptography.
let sec_keys: BTreeMap<_, SecretKey> = node_ids.map(|id| (id, rng.gen())).collect();
let pub_keys = to_pub_keys(&sec_keys);
let netinfos = NetworkInfo::generate_map(pub_keys.keys().cloned(), rng)
.expect("Failed to create `NetworkInfo` map");
let new_node = |(id, netinfo): (NodeId, NetworkInfo<_>)| {
(id, TestNode::new(new_algo(netinfo, rng), hw_quality))
let algo = new_algo(netinfo, sec_keys[&id].clone(), pub_keys.clone(), rng);
(id, TestNode::new(algo, hw_quality))
};
let mut network = TestNetwork {
nodes: netinfos.into_iter().map(new_node).collect(),
@ -416,10 +423,10 @@ fn main() {
.map(|_| rng.sample_iter(&Standard).take(args.flag_tx_size).collect())
.collect();
let new_honey_badger = |netinfo: NetworkInfo<NodeId>, rng: &mut OsRng| {
let new_honey_badger = |netinfo: NetworkInfo<NodeId>, secret_key, pub_keys, rng: &mut OsRng| {
let our_id = *netinfo.our_id();
let peer_ids: Vec<_> = netinfo.other_ids().cloned().collect();
let dhb = DynamicHoneyBadger::builder().build(netinfo);
let dhb = DynamicHoneyBadger::builder().build(netinfo, secret_key, pub_keys);
let (qhb, qhb_step) = QueueingHoneyBadger::builder(dhb)
.batch_size(args.flag_b)
.build_with_transactions(txs.clone(), rng)

View File

@ -28,9 +28,13 @@ use std::{cmp, env, fmt, fs, io, ops, process, time};
use rand::{self, Rng};
use hbbft::crypto::SecretKey;
use hbbft::dynamic_honey_badger::Batch;
use hbbft::sender_queue::SenderQueueableOutput;
use hbbft::{self, ConsensusProtocol, Contribution, CpStep, Fault, NetworkInfo, NodeIdT, Step};
use hbbft::{
self, to_pub_keys, ConsensusProtocol, Contribution, CpStep, Fault, NetworkInfo, NodeIdT,
PubKeyMap, Step,
};
pub use self::adversary::Adversary;
pub use self::err::CrankError;
@ -281,6 +285,10 @@ where
{
/// The node ID for the new node.
pub id: D::NodeId,
/// This node's secret key.
pub secret_key: SecretKey,
/// The validators' public keys.
pub pub_keys: PubKeyMap<D::NodeId>,
/// Network info struct, containing keys and other information.
pub netinfo: NetworkInfo<D::NodeId>,
/// Whether or not the node is marked faulty.
@ -749,8 +757,13 @@ where
I: IntoIterator<Item = D::NodeId>,
R: rand::Rng,
{
// Generate keys for signing and encrypting messages.
let sec_keys: BTreeMap<_, SecretKey> =
node_ids.into_iter().map(|id| (id, rng.gen())).collect();
let pub_keys: PubKeyMap<D::NodeId> = to_pub_keys(sec_keys.iter());
// Generate a new set of cryptographic keys for threshold cryptography.
let net_infos = NetworkInfo::generate_map(node_ids, &mut rng)
let net_infos = NetworkInfo::generate_map(pub_keys.keys().cloned(), &mut rng)
.map_err(CrankError::InitialKeyGeneration)?;
assert!(
@ -769,6 +782,8 @@ where
let (algorithm, step) = cons(NewNodeInfo {
id: id.clone(),
secret_key: sec_keys[&id].clone(),
pub_keys: pub_keys.clone(),
netinfo,
faulty: is_faulty,
});

View File

@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use std::sync::Arc;
use super::{ChangeState, JoinPlan, Params};
use crate::{NetworkInfo, NodeIdT};
use crate::{NetworkInfo, NodeIdT, PubKeyMap};
/// A batch of transactions the algorithm has output.
#[derive(Clone, Debug)]
@ -16,6 +16,8 @@ pub struct Batch<C, N: Ord> {
/// The current state of adding or removing a node: whether any is in progress, or completed
/// this epoch.
pub(super) change: ChangeState<N>,
/// The current set of public keys.
pub(super) pub_keys: PubKeyMap<N>,
/// The network info that applies to the _next_ epoch.
pub(super) netinfo: Arc<NetworkInfo<N>>,
/// Parameters controlling Honey Badger's behavior and performance.
@ -39,6 +41,11 @@ impl<C, N: NodeIdT> Batch<C, N> {
&self.change
}
/// Returns the map of public keys, by node ID.
pub fn public_keys(&self) -> &PubKeyMap<N> {
&self.pub_keys
}
/// Returns the `NetworkInfo` containing the information about the validators that will produce
/// the _next_ epoch after this one.
pub fn network_info(&self) -> &Arc<NetworkInfo<N>> {
@ -98,8 +105,8 @@ impl<C, N: NodeIdT> Batch<C, N> {
Some(JoinPlan {
era: self.epoch + 1,
change: self.change.clone(),
pub_keys: self.pub_keys.clone(),
pub_key_set: self.netinfo.public_key_set().clone(),
pub_keys: self.netinfo.public_key_map().clone(),
params: self.params.clone(),
})
}
@ -114,8 +121,8 @@ impl<C, N: NodeIdT> Batch<C, N> {
&& self.era == other.era
&& self.contributions == other.contributions
&& self.change == other.change
&& self.pub_keys == other.pub_keys
&& self.netinfo.public_key_set() == other.netinfo.public_key_set()
&& self.netinfo.public_key_map() == other.netinfo.public_key_map()
&& self.params == other.params
}
}

View File

@ -6,9 +6,9 @@ use std::sync::Arc;
use crate::crypto::{SecretKey, SecretKeySet};
use serde::{de::DeserializeOwned, Serialize};
use super::{DynamicHoneyBadger, EncryptionSchedule, JoinPlan, Result, Step, VoteCounter};
use crate::honey_badger::{HoneyBadger, Params, SubsetHandlingStrategy};
use crate::{Contribution, NetworkInfo, NodeIdT};
use super::{DynamicHoneyBadger, EncryptionSchedule, JoinPlan, Result, Step};
use crate::honey_badger::{Params, SubsetHandlingStrategy};
use crate::{to_pub_keys, Contribution, NetworkInfo, NodeIdT, PubKeyMap};
/// A Dynamic Honey Badger builder, to configure the parameters and create new instances of
/// `DynamicHoneyBadger`.
@ -84,30 +84,20 @@ where
}
/// Creates a new Dynamic Honey Badger instance with an empty buffer.
pub fn build(&mut self, netinfo: NetworkInfo<N>) -> DynamicHoneyBadger<C, N> {
let DynamicHoneyBadgerBuilder {
era,
epoch,
params,
_phantom,
} = self;
let arc_netinfo = Arc::new(netinfo.clone());
let honey_badger = HoneyBadger::builder(arc_netinfo.clone())
.session_id(*era)
.epoch(*epoch)
.params(params.clone())
.build();
DynamicHoneyBadger {
netinfo,
max_future_epochs: params.max_future_epochs,
era: *era,
vote_counter: VoteCounter::new(arc_netinfo, 0),
key_gen_msg_buffer: Vec::new(),
honey_badger,
key_gen_state: None,
}
pub fn build(
&mut self,
netinfo: NetworkInfo<N>,
secret_key: SecretKey,
pub_keys: PubKeyMap<N>,
) -> DynamicHoneyBadger<C, N> {
DynamicHoneyBadger::new(
secret_key,
pub_keys,
Arc::new(netinfo),
self.params.clone(),
self.era,
self.epoch,
)
}
/// Creates a new `DynamicHoneyBadger` configured to start a new network as a single validator.
@ -120,9 +110,9 @@ where
let pk_set = sk_set.public_keys();
let sks = sk_set.secret_key_share(0);
let sk = rng.gen::<SecretKey>();
let pub_keys = once((our_id.clone(), sk.public_key())).collect();
let netinfo = NetworkInfo::new(our_id, sks, pk_set, sk, pub_keys);
Ok(self.build(netinfo))
let pub_keys = to_pub_keys(once((&our_id, &sk)));
let netinfo = NetworkInfo::new(our_id.clone(), sks, pk_set, once(our_id));
Ok(self.build(netinfo, sk, pub_keys))
}
/// Creates a new `DynamicHoneyBadger` configured to join the network at the epoch specified in

View File

@ -1,9 +1,7 @@
use std::collections::BTreeMap;
use crate::crypto::PublicKey;
use serde::{Deserialize, Serialize};
use super::EncryptionSchedule;
use crate::PubKeyMap;
/// A node change action: adding or removing a node.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Hash, Debug)]
@ -11,7 +9,7 @@ pub enum Change<N: Ord> {
/// Change the set of validators to the one in the provided map. There are no restrictions on
/// the new set of validators. In particular, it can be disjoint with the current set of
/// validators.
NodeChange(BTreeMap<N, PublicKey>),
NodeChange(PubKeyMap<N>),
/// Change the threshold encryption schedule.
/// Increase frequency to prevent censorship or decrease frequency for increased throughput.
EncryptionSchedule(EncryptionSchedule),

View File

@ -17,29 +17,29 @@ use super::{
};
use crate::fault_log::{Fault, FaultLog};
use crate::honey_badger::{self, HoneyBadger, Message as HbMessage};
use crate::sync_key_gen::{Ack, AckOutcome, Part, PartOutcome, SyncKeyGen};
use crate::util;
use crate::{ConsensusProtocol, Contribution, Epoched, NetworkInfo, NodeIdT, Target};
use crate::sync_key_gen::{Ack, AckOutcome, Part, PartOutcome, PubKeyMap, SyncKeyGen};
use crate::{util, ConsensusProtocol, Contribution, Epoched, NetworkInfo, NodeIdT, Target};
/// A Honey Badger instance that can handle adding and removing nodes.
#[derive(Derivative)]
#[derivative(Debug)]
pub struct DynamicHoneyBadger<C, N: Ord> {
/// Shared network data.
pub(super) netinfo: NetworkInfo<N>,
/// This node's secret key.
secret_key: SecretKey,
/// The validators' public keys.
pub_keys: PubKeyMap<N>,
/// The maximum number of future epochs for which we handle messages simultaneously.
pub(super) max_future_epochs: u64,
max_future_epochs: u64,
/// The first epoch after the latest node change.
pub(super) era: u64,
era: u64,
/// The buffer and counter for the pending and committed change votes.
pub(super) vote_counter: VoteCounter<N>,
vote_counter: VoteCounter<N>,
/// Pending node transactions that we will propose in the next epoch.
pub(super) key_gen_msg_buffer: Vec<SignedKeyGenMsg<N>>,
key_gen_msg_buffer: Vec<SignedKeyGenMsg<N>>,
/// The `HoneyBadger` instance with the current set of nodes.
pub(super) honey_badger: HoneyBadger<InternalContrib<C, N>, N>,
honey_badger: HoneyBadger<InternalContrib<C, N>, N>,
/// The current key generation process, and the change it applies to.
pub(super) key_gen_state: Option<KeyGenState<N>>,
key_gen_state: Option<KeyGenState<N>>,
}
impl<C, N> ConsensusProtocol for DynamicHoneyBadger<C, N>
@ -77,7 +77,7 @@ where
}
fn our_id(&self) -> &N {
self.netinfo.our_id()
self.netinfo().our_id()
}
}
@ -91,6 +91,35 @@ where
DynamicHoneyBadgerBuilder::new()
}
/// Creates a new `DynamicHoneyBadger`.
pub fn new(
secret_key: SecretKey,
pub_keys: PubKeyMap<N>,
netinfo: Arc<NetworkInfo<N>>,
params: Params,
era: u64,
epoch: u64,
) -> Self {
let max_future_epochs = params.max_future_epochs;
let our_id = netinfo.our_id().clone();
let honey_badger = HoneyBadger::builder(netinfo)
.session_id(era)
.params(params)
.epoch(epoch)
.build();
let vote_counter = VoteCounter::new(our_id, secret_key.clone(), pub_keys.clone(), era);
DynamicHoneyBadger {
secret_key,
pub_keys,
max_future_epochs,
era,
vote_counter,
key_gen_msg_buffer: Vec::new(),
honey_badger,
key_gen_state: None,
}
}
/// Creates a new `DynamicHoneyBadger` ready to join the network specified in the `JoinPlan`.
pub fn new_joining<R: Rng>(
our_id: N,
@ -98,34 +127,22 @@ where
join_plan: JoinPlan<N>,
rng: &mut R,
) -> Result<(Self, Step<C, N>)> {
let netinfo = NetworkInfo::new(
our_id,
None,
join_plan.pub_key_set,
secret_key,
join_plan.pub_keys,
);
let max_future_epochs = join_plan.params.max_future_epochs;
let arc_netinfo = Arc::new(netinfo.clone());
let honey_badger = HoneyBadger::builder(arc_netinfo.clone())
.session_id(join_plan.era)
.params(join_plan.params)
.build();
let mut dhb = DynamicHoneyBadger {
netinfo,
max_future_epochs,
era: join_plan.era,
vote_counter: VoteCounter::new(arc_netinfo, join_plan.era),
key_gen_msg_buffer: Vec::new(),
honey_badger,
key_gen_state: None,
};
let step = match join_plan.change {
ChangeState::InProgress(ref change) => match change {
Change::NodeChange(change) => dhb.update_key_gen(join_plan.era, change, rng)?,
_ => Step::default(),
},
ChangeState::None | ChangeState::Complete(..) => Step::default(),
let JoinPlan {
era,
change,
pub_keys,
pub_key_set,
params,
} = join_plan;
let netinfo = Arc::new(NetworkInfo::new(our_id, None, pub_key_set, pub_keys.keys()));
let mut dhb = DynamicHoneyBadger::new(secret_key, pub_keys, netinfo, params, era, 0);
let step = match change {
ChangeState::InProgress(Change::NodeChange(new_pub_keys)) => {
dhb.update_key_gen(join_plan.era, new_pub_keys, rng)?
}
ChangeState::InProgress(Change::EncryptionSchedule(..))
| ChangeState::None
| ChangeState::Complete(..) => Step::default(),
};
Ok((dhb, step))
}
@ -167,7 +184,7 @@ where
/// This stores a pending vote for the change. It will be included in some future batch, and
/// once enough validators have been voted for the same change, it will take effect.
pub fn vote_for(&mut self, change: Change<N>) -> Result<Step<C, N>> {
if !self.netinfo.is_validator() {
if !self.netinfo().is_validator() {
return Ok(Step::default()); // TODO: Return an error?
}
let signed_vote = self.vote_counter.sign_vote_for(change)?.clone();
@ -180,9 +197,9 @@ where
/// This stores a pending vote for the change. It will be included in some future batch, and
/// once enough validators have been voted for the same change, it will take effect.
pub fn vote_to_add(&mut self, node_id: N, pub_key: PublicKey) -> Result<Step<C, N>> {
let mut pub_keys = self.netinfo.public_key_map().clone();
let mut pub_keys = (*self.pub_keys).clone();
pub_keys.insert(node_id, pub_key);
self.vote_for(Change::NodeChange(pub_keys))
self.vote_for(Change::NodeChange(Arc::new(pub_keys)))
}
/// Casts a vote to demote a validator to observer.
@ -190,9 +207,9 @@ where
/// This stores a pending vote for the change. It will be included in some future batch, and
/// once enough validators have been voted for the same change, it will take effect.
pub fn vote_to_remove(&mut self, node_id: &N) -> Result<Step<C, N>> {
let mut pub_keys = self.netinfo.public_key_map().clone();
let mut pub_keys = (*self.pub_keys).clone();
pub_keys.remove(node_id);
self.vote_for(Change::NodeChange(pub_keys))
self.vote_for(Change::NodeChange(Arc::new(pub_keys)))
}
/// Handles a message received from `sender_id`.
@ -225,9 +242,19 @@ where
}
}
/// Returns the secret key used to sign votes and key generation messages.
pub fn secret_key(&self) -> &SecretKey {
&self.secret_key
}
/// Returns the map of public keys, by node ID.
pub fn public_keys(&self) -> &PubKeyMap<N> {
&self.pub_keys
}
/// Returns the information about the node IDs in the network, and the cryptographic keys.
pub fn netinfo(&self) -> &NetworkInfo<N> {
&self.netinfo
pub fn netinfo(&self) -> &Arc<NetworkInfo<N>> {
&self.honey_badger.netinfo()
}
/// Returns a reference to the internal managed `HoneyBadger` instance.
@ -245,7 +272,7 @@ where
if self.has_input() {
return false; // We have already proposed.
}
if self.honey_badger.received_proposals() > self.netinfo.num_faulty() {
if self.honey_badger.received_proposals() > self.netinfo().num_faulty() {
return true; // At least one correct node wants to move on to the next epoch.
}
let is_our_vote = |signed_vote: &SignedVote<_>| signed_vote.voter() == self.our_id();
@ -268,7 +295,7 @@ where
message: HbMessage<N>,
rng: &mut R,
) -> Result<Step<C, N>> {
if !self.netinfo.is_node_validator(sender_id) {
if !self.netinfo().is_node_validator(sender_id) {
return Err(Error::UnknownSender);
}
// Handle the message.
@ -357,15 +384,19 @@ where
let change = if let Some(kgs) = self.take_ready_key_gen() {
// If DKG completed, apply the change, restart Honey Badger, and inform the user.
debug!("{}: DKG for complete for: {:?}", self, kgs.public_keys());
self.netinfo = kgs.key_gen.into_network_info().map_err(Error::SyncKeyGen)?;
self.pub_keys = kgs.key_gen.public_keys().clone();
let (pk_set, sk_share) = kgs.key_gen.generate().map_err(Error::SyncKeyGen)?;
let our_id = self.our_id().clone();
let all_ids = self.pub_keys.keys();
let netinfo = Arc::new(NetworkInfo::new(our_id, sk_share, pk_set, all_ids));
let params = self.honey_badger.params().clone();
self.restart_honey_badger(batch_epoch + 1, params);
ChangeState::Complete(Change::NodeChange(self.netinfo.public_key_map().clone()))
self.restart_honey_badger(batch_epoch + 1, params, netinfo);
ChangeState::Complete(Change::NodeChange(self.pub_keys.clone()))
} 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.
match change {
Change::NodeChange(ref pub_keys) => {
step.extend(self.update_key_gen(batch_epoch + 1, pub_keys, rng)?);
step.extend(self.update_key_gen(batch_epoch + 1, pub_keys.clone(), rng)?);
}
Change::EncryptionSchedule(schedule) => {
self.update_encryption_schedule(batch_epoch + 1, schedule);
@ -382,7 +413,8 @@ where
epoch: batch_epoch,
era: batch_era,
change,
netinfo: Arc::new(self.netinfo.clone()),
pub_keys: self.pub_keys.clone(),
netinfo: self.netinfo().clone(),
contributions: batch_contributions,
params: self.honey_badger.params().clone(),
});
@ -394,7 +426,7 @@ where
pub(super) fn update_encryption_schedule(&mut self, era: u64, schedule: EncryptionSchedule) {
let mut params = self.honey_badger.params().clone();
params.encryption_schedule = schedule;
self.restart_honey_badger(era, params);
self.restart_honey_badger(era, params, self.netinfo().clone());
}
/// If the winner of the vote has changed, restarts Key Generation for the set of nodes implied
@ -402,20 +434,20 @@ where
pub(super) fn update_key_gen<R: Rng>(
&mut self,
era: u64,
pub_keys: &BTreeMap<N, PublicKey>,
pub_keys: PubKeyMap<N>,
rng: &mut R,
) -> Result<Step<C, N>> {
if self.key_gen_state.as_ref().map(KeyGenState::public_keys) == Some(pub_keys) {
if self.key_gen_state.as_ref().map(KeyGenState::public_keys) == Some(&pub_keys) {
return Ok(Step::default()); // The change is the same as before. Continue DKG as is.
}
debug!("{}: Restarting DKG for {:?}.", self, pub_keys);
let params = self.honey_badger.params().clone();
self.restart_honey_badger(era, params);
self.restart_honey_badger(era, params, self.netinfo().clone());
let threshold = util::max_faulty(pub_keys.len());
let sk = self.netinfo.secret_key().clone();
let sk = self.secret_key.clone();
let our_id = self.our_id().clone();
let (key_gen, part) = SyncKeyGen::new(our_id, sk, pub_keys.clone(), threshold, rng)
.map_err(Error::SyncKeyGen)?;
let (key_gen, part) =
SyncKeyGen::new(our_id, sk, pub_keys, threshold, rng).map_err(Error::SyncKeyGen)?;
self.key_gen_state = Some(KeyGenState::new(key_gen));
if let Some(part) = part {
self.send_transaction(KeyGenMessage::Part(part))
@ -425,11 +457,15 @@ where
}
/// Starts a new `HoneyBadger` instance and resets the vote counter.
fn restart_honey_badger(&mut self, era: u64, params: Params) {
fn restart_honey_badger(&mut self, era: u64, params: Params, netinfo: Arc<NetworkInfo<N>>) {
self.era = era;
self.key_gen_msg_buffer.retain(|kg_msg| kg_msg.0 >= era);
let netinfo = Arc::new(self.netinfo.clone());
self.vote_counter = VoteCounter::new(netinfo.clone(), era);
self.vote_counter = VoteCounter::new(
self.our_id().clone(),
self.secret_key.clone(),
self.pub_keys.clone(),
era,
);
self.honey_badger = HoneyBadger::builder(netinfo)
.session_id(era)
.params(params)
@ -487,8 +523,8 @@ where
/// Signs and sends a `KeyGenMessage` and also tries to commit it.
fn send_transaction(&mut self, kg_msg: KeyGenMessage) -> Result<Step<C, N>> {
let ser = bincode::serialize(&kg_msg).map_err(|err| Error::SerializeKeyGen(*err))?;
let sig = Box::new(self.netinfo.secret_key().sign(ser));
if self.netinfo.is_validator() {
let sig = Box::new(self.secret_key.sign(ser));
if self.netinfo().is_validator() {
let our_id = self.our_id().clone();
let signed_msg = SignedKeyGenMsg(self.era, our_id, kg_msg.clone(), *sig.clone());
self.key_gen_msg_buffer.push(signed_msg);
@ -527,7 +563,7 @@ where
let ser = bincode::serialize(kg_msg).map_err(|err| Error::SerializeKeyGen(*err))?;
let verify = |opt_pk: Option<&PublicKey>| opt_pk.map_or(false, |pk| pk.verify(&sig, &ser));
let kgs = self.key_gen_state.as_ref();
let current_key = self.netinfo.public_key(node_id);
let current_key = self.pub_keys.get(node_id);
let candidate_key = kgs.and_then(|kgs| kgs.public_keys().get(node_id));
Ok(verify(current_key) || verify(candidate_key))
}

View File

@ -74,13 +74,13 @@ mod votes;
use std::collections::BTreeMap;
use crate::crypto::{PublicKey, PublicKeySet, Signature};
use serde::{Deserialize, Serialize};
use self::votes::{SignedVote, VoteCounter};
use self::votes::SignedVote;
use crate::crypto::{PublicKeySet, Signature};
use crate::honey_badger::{EncryptionSchedule, Message as HbMessage, Params};
use crate::sync_key_gen::{Ack, Part, SyncKeyGen};
use crate::NodeIdT;
use crate::{NodeIdT, PubKeyMap};
pub use self::batch::Batch;
pub use self::builder::DynamicHoneyBadgerBuilder;
@ -135,16 +135,17 @@ impl<N: Ord> Message<N> {
/// The information a new node requires to join the network as an observer. It contains the state
/// of voting and key generation after a specific epoch, so that the new node will be in sync if it
/// joins in the next one.
// TODO: Remove serde "rc" feature and deduplicate `pub_keys` and `change`. Also: validate.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct JoinPlan<N: Ord> {
/// The first epoch the new node will observe.
era: u64,
/// The current change. If `InProgress`, key generation for it is beginning at `epoch`.
change: ChangeState<N>,
/// The current set of public keys.
pub_keys: PubKeyMap<N>,
/// The current public key set for threshold cryptography.
pub_key_set: PublicKeySet,
/// The public keys of the current validators.
pub_keys: BTreeMap<N, PublicKey>,
/// Parameters controlling Honey Badger's behavior and performance.
params: Params,
}
@ -181,7 +182,7 @@ impl<N: NodeIdT> KeyGenState<N> {
}
/// Returns the map of new validators and their public keys.
fn public_keys(&self) -> &BTreeMap<N, PublicKey> {
fn public_keys(&self) -> &PubKeyMap<N> {
self.key_gen.public_keys()
}

View File

@ -1,13 +1,11 @@
use std::collections::{BTreeMap, HashMap};
use std::sync::Arc;
use crate::crypto::Signature;
use crate::crypto::{SecretKey, Signature};
use bincode;
use serde::{Deserialize, Serialize};
use super::{Change, Error, FaultKind, Result};
use crate::fault_log;
use crate::{NetworkInfo, NodeIdT};
use crate::{fault_log, util, NodeIdT, PubKeyMap};
pub type FaultLog<N> = fault_log::FaultLog<N, FaultKind>;
@ -17,8 +15,14 @@ pub type FaultLog<N> = fault_log::FaultLog<N, FaultKind>;
/// the epochs since the last reset the current _era_.
#[derive(Debug)]
pub struct VoteCounter<N: Ord> {
/// Shared network data.
netinfo: Arc<NetworkInfo<N>>,
/// This node's ID.
// TODO: Make optional for observers?
our_id: N,
/// This node's secret key,
// TODO: Make optional for observers?
secret_key: SecretKey,
/// The map of public keys.
pub_keys: PubKeyMap<N>,
/// The epoch when voting was reset.
era: u64,
/// Pending node transactions that we will propose in the next epoch.
@ -33,10 +37,12 @@ where
N: NodeIdT + Serialize,
{
/// Creates a new `VoteCounter` object with empty buffer and counter.
pub fn new(netinfo: Arc<NetworkInfo<N>>, era: u64) -> Self {
pub fn new(our_id: N, secret_key: SecretKey, pub_keys: PubKeyMap<N>, era: u64) -> Self {
VoteCounter {
our_id,
secret_key,
pub_keys: pub_keys.clone(),
era,
netinfo,
pending: BTreeMap::new(),
committed: BTreeMap::new(),
}
@ -44,7 +50,7 @@ where
/// Creates a signed vote for the given change, and inserts it into the pending votes buffer.
pub fn sign_vote_for(&mut self, change: Change<N>) -> Result<&SignedVote<N>> {
let voter = self.netinfo.our_id().clone();
let voter = self.our_id.clone();
let vote = Vote {
change,
era: self.era,
@ -54,7 +60,7 @@ where
let signed_vote = SignedVote {
vote,
voter: voter.clone(),
sig: self.netinfo.secret_key().sign(ser_vote),
sig: self.secret_key.sign(ser_vote),
};
self.pending.remove(&voter);
Ok(self.pending.entry(voter).or_insert(signed_vote))
@ -141,7 +147,7 @@ where
let change = &vote.change;
let entry = vote_counts.entry(change).or_insert(0);
*entry += 1;
if *entry > self.netinfo.num_faulty() {
if *entry > util::max_faulty(self.pub_keys.len()) {
return Some(change);
}
}
@ -152,7 +158,7 @@ where
fn validate(&self, signed_vote: &SignedVote<N>) -> Result<bool> {
let ser_vote =
bincode::serialize(&signed_vote.vote).map_err(|err| Error::SerializeVote(*err))?;
let pk_opt = self.netinfo.public_key(&signed_vote.voter);
let pk_opt = self.pub_keys.get(&signed_vote.voter);
Ok(pk_opt.map_or(false, |pk| pk.verify(&signed_vote.sig, ser_vote)))
}
}
@ -188,13 +194,14 @@ impl<N: Ord> SignedVote<N> {
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use std::iter;
use std::sync::Arc;
use super::{Change, FaultKind, SignedVote, VoteCounter};
use crate::fault_log::FaultLog;
use crate::NetworkInfo;
use rand;
use rand::{rngs, Rng};
use super::{Change, FaultKind, SecretKey, SignedVote, VoteCounter};
use crate::{fault_log::FaultLog, to_pub_keys};
/// Returns a vector of `node_num` `VoteCounter`s, and some signed example votes.
///
@ -202,21 +209,20 @@ mod tests {
/// the vote by node `i` for making `j` the only validator. Each node signed this for nodes
/// `0`, `1`, ... in order.
fn setup(node_num: usize, era: u64) -> (Vec<VoteCounter<usize>>, Vec<Vec<SignedVote<usize>>>) {
let mut rng = rand::rngs::OsRng::new().expect("could not initialize OsRng");
// Create keys for threshold cryptography.
let netinfos = NetworkInfo::generate_map(0..node_num, &mut rng)
.expect("Failed to generate `NetworkInfo` map");
let pub_keys = netinfos[&0].public_key_map().clone();
let mut rng = rngs::OsRng::new().expect("could not initialize OsRng");
// Generate keys for signing and encrypting messages.
let sec_keys: BTreeMap<_, SecretKey> = (0..node_num).map(|id| (id, rng.gen())).collect();
let pub_keys = to_pub_keys(&sec_keys);
// Create a `VoteCounter` instance for each node.
let create_counter =
|(_, netinfo): (_, NetworkInfo<_>)| VoteCounter::new(Arc::new(netinfo), era);
let mut counters: Vec<_> = netinfos.into_iter().map(create_counter).collect();
let create_counter = |(id, sk)| VoteCounter::new(id, sk, pub_keys.clone(), era);
let mut counters: Vec<_> = sec_keys.into_iter().map(create_counter).collect();
// Sign a few votes.
let sign_votes = |counter: &mut VoteCounter<usize>| {
(0..node_num)
.map(|j| Change::NodeChange(iter::once((j, pub_keys[&j])).collect()))
.map(|j| Change::NodeChange(Arc::new(iter::once((j, pub_keys[&j])).collect())))
.map(|change| counter.sign_vote_for(change).expect("sign vote").clone())
.collect::<Vec<_>>()
};

View File

@ -131,6 +131,11 @@ where
self.epoch
}
/// Returns the information about the node IDs in the network, and the threshold key shares.
pub fn netinfo(&self) -> &Arc<NetworkInfo<N>> {
&self.netinfo
}
/// Skips all epochs before the specified one.
///
/// This must only be called if it is guaranteed to be called in all instances that have not

View File

@ -143,6 +143,7 @@ pub use crate::crypto::pairing;
pub use crate::fault_log::{Fault, FaultLog};
pub use crate::messaging::{SourcedMessage, Target, TargetedMessage};
pub use crate::network_info::{NetworkInfo, ValidatorSet};
pub use crate::sync_key_gen::{to_pub_keys, PubKeyMap};
pub use crate::traits::{
ConsensusProtocol, Contribution, CpStep, Epoched, Message, NodeIdT, SessionIdT, Step,
};

View File

@ -2,7 +2,7 @@ use std::borrow::Borrow;
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use crate::crypto::{self, PublicKey, PublicKeySet, PublicKeyShare, SecretKey, SecretKeyShare};
use crate::crypto::{self, PublicKeySet, PublicKeyShare, SecretKeyShare};
use rand;
use crate::{util, NodeIdT};
@ -91,14 +91,10 @@ pub struct NetworkInfo<N> {
is_validator: bool,
/// This node's secret key share. Only validators have one.
secret_key_share: Option<SecretKeyShare>,
/// This node's secret key.
secret_key: SecretKey,
/// The public key set for threshold cryptography. Each validator has a secret key share.
public_key_set: PublicKeySet,
/// The validators' public key shares, computed from `public_key_set`.
public_key_shares: BTreeMap<N, PublicKeyShare>,
/// The validators' public keys.
public_keys: BTreeMap<N, PublicKey>,
/// The indices in the list of sorted validator IDs.
val_set: Arc<ValidatorSet<N>>,
}
@ -114,14 +110,13 @@ impl<N: NodeIdT> NetworkInfo<N> {
///
/// Panics if `public_keys` is empty or the requirement above is not satisfied, i.e. if the
/// secret key doesn't match the public key or is missing.
pub fn new<SKS: Into<Option<SecretKeyShare>>>(
pub fn new<SKS: Into<Option<SecretKeyShare>>, V: Into<ValidatorSet<N>>>(
our_id: N,
secret_key_share: SKS,
public_key_set: PublicKeySet,
secret_key: SecretKey,
public_keys: BTreeMap<N, PublicKey>,
val_set: V,
) -> Self {
let val_set = Arc::new(ValidatorSet::from(public_keys.keys()));
let val_set = Arc::new(val_set.into());
let is_validator = val_set.contains(&our_id);
let secret_key_share = secret_key_share.into();
assert_eq!(is_validator, secret_key_share.is_some());
@ -139,11 +134,9 @@ impl<N: NodeIdT> NetworkInfo<N> {
our_id,
is_validator,
secret_key_share,
secret_key,
public_key_set,
public_key_shares,
val_set,
public_keys,
}
}
@ -192,12 +185,6 @@ impl<N: NodeIdT> NetworkInfo<N> {
self.secret_key_share.as_ref()
}
/// Returns our secret key for encryption and signing.
#[inline]
pub fn secret_key(&self) -> &SecretKey {
&self.secret_key
}
/// Returns the public key set for threshold cryptography.
#[inline]
pub fn public_key_set(&self) -> &PublicKeySet {
@ -216,18 +203,6 @@ impl<N: NodeIdT> NetworkInfo<N> {
&self.public_key_shares
}
/// Returns a map of all node IDs to their public keys.
#[inline]
pub fn public_key(&self, id: &N) -> Option<&PublicKey> {
self.public_keys.get(id)
}
/// Returns a map of all node IDs to their public keys.
#[inline]
pub fn public_key_map(&self) -> &BTreeMap<N, PublicKey> {
&self.public_keys
}
/// The index of a node in a canonical numbering of all nodes. This is the index where the
/// node appears in `all_ids`.
#[inline]
@ -246,7 +221,7 @@ impl<N: NodeIdT> NetworkInfo<N> {
/// observer.
#[inline]
pub fn is_node_validator(&self, id: &N) -> bool {
self.public_keys.contains_key(id)
self.val_set.contains(id)
}
/// Returns the set of validator IDs.
@ -272,29 +247,12 @@ impl<N: NodeIdT> NetworkInfo<N> {
let sk_set = SecretKeySet::random(num_faulty, rng);
let pk_set = sk_set.public_keys();
// Generate keys for individually signing and encrypting messages.
let sec_keys: BTreeMap<_, SecretKey> =
all_ids.iter().map(|id| (id.clone(), rng.gen())).collect();
let pub_keys: BTreeMap<_, PublicKey> = sec_keys
.iter()
.map(|(id, sk)| (id.clone(), sk.public_key()))
.collect();
// Create the corresponding `NetworkInfo` for each node.
let create_netinfo = |(i, id): (usize, N)| {
let netinfo = NetworkInfo::new(
id.clone(),
sk_set.secret_key_share(i),
pk_set.clone(),
sec_keys[&id].clone(),
pub_keys.clone(),
);
Ok((id, netinfo))
let create_netinfo = |(index, id): (usize, &N)| {
let sks = sk_set.secret_key_share(index);
let netinfo = NetworkInfo::new(id.clone(), sks, pk_set.clone(), &all_ids);
Ok((id.clone(), netinfo))
};
all_ids
.into_iter()
.enumerate()
.map(create_netinfo)
.collect()
all_ids.iter().enumerate().map(create_netinfo).collect()
}
}

View File

@ -26,8 +26,7 @@ where
fn participant_change(&self) -> Option<BTreeSet<N>> {
if let ChangeState::InProgress(Change::NodeChange(pub_keys)) = self.change() {
let candidates = pub_keys.keys();
let current_validators: BTreeSet<&N> =
self.network_info().public_key_map().keys().collect();
let current_validators: BTreeSet<&N> = self.public_keys().keys().collect();
let participants = candidates.chain(current_validators).cloned().collect();
Some(participants)
} else if let ChangeState::Complete(Change::NodeChange(pub_keys)) = self.change() {
@ -143,7 +142,7 @@ where
if !self.is_removed {
return Err(Error::DynamicHoneyBadgerNotRemoved);
}
let secret_key = self.algo().netinfo().secret_key().clone();
let secret_key = self.algo().secret_key().clone();
let id = self.algo().netinfo().our_id().clone();
let (dhb, dhb_step) =
DynamicHoneyBadger::new_joining(id.clone(), secret_key, join_plan, rng)

View File

@ -57,23 +57,20 @@
//!
//! ```
//! use std::collections::BTreeMap;
//! use std::sync::Arc;
//!
//! use threshold_crypto::{PublicKey, SecretKey, SignatureShare};
//! use hbbft::sync_key_gen::{AckOutcome, PartOutcome, SyncKeyGen};
//! use threshold_crypto::{SecretKey, SignatureShare};
//! use hbbft::sync_key_gen::{to_pub_keys, AckOutcome, PartOutcome, PubKeyMap, SyncKeyGen};
//!
//! // Use the OS random number generator for any randomness:
//! let mut rng = rand::OsRng::new().expect("Could not open OS random number generator.");
//! let mut rng = rand::rngs::OsRng::new().expect("Could not open OS random number generator.");
//!
//! // Two out of four shares will suffice to sign or encrypt something.
//! let (threshold, node_num) = (1, 4);
//!
//! // Generate individual key pairs for encryption. These are not suitable for threshold schemes.
//! let sec_keys: Vec<SecretKey> = (0..node_num).map(|_| rand::random()).collect();
//! let pub_keys: BTreeMap<usize, PublicKey> = sec_keys
//! .iter()
//! .map(SecretKey::public_key)
//! .enumerate()
//! .collect();
//! let pub_keys = to_pub_keys(sec_keys.iter().enumerate());
//!
//! // Create the `SyncKeyGen` instances. The constructor also outputs the part that needs to
//! // be sent to all other participants, so we save the parts together with their sender ID.
@ -174,8 +171,15 @@
//! method above. The sum of the secret keys we received from each node is then used as our secret
//! key. No single node knows the secret master key.
use std::borrow::Borrow;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::{self, Debug, Formatter};
use std::sync::Arc;
use bincode;
use failure::Fail;
use rand;
use serde::{Deserialize, Serialize};
use crate::crypto::{
error::Error as CryptoError,
@ -184,12 +188,22 @@ use crate::crypto::{
Ciphertext, Fr, G1Affine, PublicKey, PublicKeySet, SecretKey, SecretKeyShare,
};
use crate::pairing::{CurveAffine, Field};
use bincode;
use failure::Fail;
use rand;
use serde::{Deserialize, Serialize};
use crate::NodeIdT;
use crate::{NetworkInfo, NodeIdT};
/// A map assigning to each node ID a public key, wrapped in an `Arc`.
pub type PubKeyMap<N> = Arc<BTreeMap<N, PublicKey>>;
/// Returns a `PubKeyMap` corresponding to the given secret keys.
///
/// This is mostly useful for setting up test networks.
pub fn to_pub_keys<'a, I, B, N: NodeIdT + 'a>(sec_keys: I) -> PubKeyMap<N>
where
B: Borrow<N>,
I: IntoIterator<Item = (B, &'a SecretKey)>,
{
let to_pub = |(id, sk): I::Item| (id.borrow().clone(), sk.public_key());
Arc::new(sec_keys.into_iter().map(to_pub).collect())
}
/// A local error while handling an `Ack` or `Part` message, that was not caused by that message
/// being invalid.
@ -307,7 +321,7 @@ pub struct SyncKeyGen<N> {
/// Our secret key.
sec_key: SecretKey,
/// The public keys of all nodes, by node ID.
pub_keys: BTreeMap<N, PublicKey>,
pub_keys: PubKeyMap<N>,
/// Proposed bivariate polynomials.
parts: BTreeMap<u64, ProposalState>,
/// The degree of the generated polynomial.
@ -323,7 +337,7 @@ impl<N: NodeIdT> SyncKeyGen<N> {
pub fn new<R: rand::Rng>(
our_id: N,
sec_key: SecretKey,
pub_keys: BTreeMap<N, PublicKey>,
pub_keys: PubKeyMap<N>,
threshold: usize,
rng: &mut R,
) -> Result<(SyncKeyGen<N>, Option<Part>), Error> {
@ -359,7 +373,7 @@ impl<N: NodeIdT> SyncKeyGen<N> {
}
/// Returns the map of participating nodes and their public keys.
pub fn public_keys(&self) -> &BTreeMap<N, PublicKey> {
pub fn public_keys(&self) -> &PubKeyMap<N> {
&self.pub_keys
}
@ -461,17 +475,6 @@ impl<N: NodeIdT> SyncKeyGen<N> {
Ok((pk_commit.into(), opt_sk))
}
/// Consumes the instance, generates the key set and returns a new `NetworkInfo` with the new
/// keys.
///
/// All participating nodes must have handled the exact same sequence of `Part` and `Ack`
/// messages before calling this method. Otherwise their key shares will not match.
pub fn into_network_info(self) -> Result<NetworkInfo<N>, Error> {
let (pk_set, sk_share) = self.generate()?;
let netinfo = NetworkInfo::new(self.our_id, sk_share, pk_set, self.sec_key, self.pub_keys);
Ok(netinfo)
}
/// Returns the number of nodes participating in the key generation.
pub fn num_nodes(&self) -> usize {
self.pub_keys.len()

View File

@ -1,17 +1,17 @@
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use std::time;
use hbbft::dynamic_honey_badger::{
Batch, Change, ChangeState, DynamicHoneyBadger, Input, JoinPlan,
};
use hbbft::sender_queue::{SenderQueue, Step};
use hbbft::{util, Epoched};
use hbbft::{util, Epoched, PubKeyMap};
use hbbft_testing::adversary::{Adversary, ReorderingAdversary};
use hbbft_testing::proptest::{gen_seed, NetworkDimension, TestRng, TestRngSeed};
use hbbft_testing::{NetBuilder, NewNodeInfo, Node, VirtualNet};
use proptest::{prelude::ProptestConfig, prop_compose, proptest};
use rand::{seq::SliceRandom, SeedableRng};
use threshold_crypto::PublicKey;
type DHB = SenderQueue<DynamicHoneyBadger<Vec<usize>, usize>>;
@ -108,7 +108,8 @@ fn do_drop_and_re_add(cfg: TestConfig) {
if id < num_faulty { "faulty" } else { "correct" },
id
);
let dhb = DynamicHoneyBadger::builder().build(node.netinfo.clone());
let netinfo = node.netinfo.clone();
let dhb = DynamicHoneyBadger::builder().build(netinfo, node.secret_key, node.pub_keys);
SenderQueue::builder(dhb, node.netinfo.other_ids().cloned()).build(node.id)
})
.build(&mut rng)
@ -140,17 +141,13 @@ fn do_drop_and_re_add(cfg: TestConfig) {
// Afterwards, remove specific nodes from the dynamic honey badger network.
let old_pub_keys = state.get_pub_keys();
let new_pub_keys: BTreeMap<usize, PublicKey> = old_pub_keys
.clone()
.into_iter()
.filter(|(id, _)| !nodes_for_remove.contains(id))
.collect();
let not_removed = |(id, _): &(usize, _)| !nodes_for_remove.contains(id);
let old_pub_keys_iter = (*old_pub_keys).clone().into_iter();
let new_pub_keys: PubKeyMap<usize> = Arc::new(old_pub_keys_iter.filter(not_removed).collect());
let change = Input::Change(Change::NodeChange(new_pub_keys.clone()));
state
.net
.broadcast_input(
&Input::Change(Change::NodeChange(new_pub_keys.clone())),
&mut rng,
)
.broadcast_input(&change, &mut rng)
.expect("broadcasting failed");
// We are tracking (correct) nodes' state through the process by ticking them off individually.
@ -529,14 +526,13 @@ where
}
/// Returns clone of all public keys for this network.
fn get_pub_keys(&self) -> BTreeMap<usize, PublicKey> {
fn get_pub_keys(&self) -> PubKeyMap<usize> {
self.net
.get(0)
.expect("network should have at least one node")
.algorithm()
.algo()
.netinfo()
.public_key_map()
.public_keys()
.clone()
}
}

View File

@ -7,7 +7,7 @@ use std::sync::Arc;
use hbbft::dynamic_honey_badger::{DynamicHoneyBadger, JoinPlan};
use hbbft::queueing_honey_badger::{Change, ChangeState, Input, QueueingHoneyBadger};
use hbbft::sender_queue::{Message, SenderQueue, Step};
use hbbft::{util, NetworkInfo};
use hbbft::util;
use hbbft_testing::adversary::{Adversary, NodeOrderAdversary, ReorderingAdversary};
use hbbft_testing::proptest::{gen_seed, TestRng, TestRngSeed};
use hbbft_testing::{NetBuilder, NewNodeInfo, Node, VirtualNet};
@ -16,16 +16,17 @@ use proptest::{prelude::ProptestConfig, proptest};
use rand::{Rng, SeedableRng};
type NodeId = u16;
type QHB = SenderQueue<QueueingHoneyBadger<usize, NodeId, Vec<usize>>>;
type QHB = QueueingHoneyBadger<usize, NodeId, Vec<usize>>;
type SQ = SenderQueue<QHB>;
// Send the second half of the transactions to the specified node.
fn input_second_half<A>(
net: &mut VirtualNet<QHB, A>,
net: &mut VirtualNet<SQ, A>,
id: NodeId,
num_txs: usize,
mut rng: &mut TestRng,
) where
A: Adversary<QHB>,
A: Adversary<SQ>,
{
for tx in (num_txs / 2)..num_txs {
let _ = net.send_input(id, Input::User(tx), &mut rng);
@ -33,28 +34,28 @@ fn input_second_half<A>(
}
/// Proposes `num_txs` values and expects nodes to output and order them.
fn test_queueing_honey_badger<A>(mut net: VirtualNet<QHB, A>, num_txs: usize, mut rng: &mut TestRng)
fn test_queueing_honey_badger<A>(mut net: VirtualNet<SQ, A>, num_txs: usize, mut rng: &mut TestRng)
where
A: Adversary<QHB>,
A: Adversary<SQ>,
{
let netinfo = net
// Make two copies of all public keys.
let pub_keys_add = net
.correct_nodes()
.nth(0)
.expect("At least one correct node needs to exist")
.algorithm()
.algo()
.netinfo()
.dyn_hb()
.public_keys()
.clone();
// Make two copies of all public keys.
let pub_keys_add = netinfo.public_key_map().clone();
let mut pub_keys_rm = pub_keys_add.clone();
// Get the first correct node id as candidate for removal/re-adding.
let first_correct_node = *net.correct_nodes().nth(0).unwrap().id();
// Remove the first correct node, which is to be removed.
pub_keys_rm.remove(&first_correct_node);
Arc::make_mut(&mut pub_keys_rm).remove(&first_correct_node);
// Broadcast public keys of all nodes except for the node to be removed.
let _ = net.broadcast_input(
@ -69,7 +70,7 @@ where
// Closure for checking the output of a node for ChangeSet completion containing
// all nodes but the removed node.
let has_remove = |node: &Node<QHB>| {
let has_remove = |node: &Node<SQ>| {
node.outputs().iter().any(|batch| match batch.change() {
ChangeState::Complete(Change::NodeChange(pub_keys)) => pub_keys == &pub_keys_rm,
_ => false,
@ -78,7 +79,7 @@ where
// Closure for checking the output of a node for ChangeSet completion containing
// all nodes, including the previously removed node.
let has_add = |node: &Node<QHB>| {
let has_add = |node: &Node<SQ>| {
node.outputs().iter().any(|batch| match batch.change() {
ChangeState::Complete(Change::NodeChange(pub_keys)) => pub_keys == &pub_keys_add,
_ => false,
@ -86,7 +87,7 @@ where
};
// Returns `true` if the node has not output all changes or transactions yet.
let node_busy = |node: &Node<QHB>| {
let node_busy = |node: &Node<SQ>| {
!has_remove(node) || !has_add(node) || !node.algorithm().algo().queue().is_empty()
};
@ -106,7 +107,7 @@ where
let mut rejoined_first_correct = false;
// The removed first correct node which is to be restarted as soon as all remaining
// validators agreed to add it back.
let mut saved_first_correct: Option<Node<QHB>> = None;
let mut saved_first_correct: Option<Node<SQ>> = None;
// Handle messages in random order until all nodes have output all transactions.
while net.correct_nodes().any(node_busy) {
@ -186,14 +187,14 @@ where
/// Restarts specified node on the test network for adding it back as a validator.
fn restart_node_for_add<R, A>(
net: &mut VirtualNet<QHB, A>,
mut node: Node<QHB>,
net: &mut VirtualNet<SQ, A>,
mut node: Node<SQ>,
join_plan: JoinPlan<NodeId>,
mut rng: &mut R,
) -> Step<QueueingHoneyBadger<usize, NodeId, Vec<usize>>>
where
R: rand::Rng,
A: Adversary<QHB>,
A: Adversary<SQ>,
{
let our_id = *node.id();
println!("Restarting node {} with {:?}", node.id(), join_plan);
@ -206,7 +207,7 @@ where
.cloned()
.collect();
let secret_key = node.algorithm().algo().netinfo().secret_key().clone();
let secret_key = node.algorithm().algo().dyn_hb().secret_key().clone();
let (qhb, qhb_step) =
QueueingHoneyBadger::builder_joining(our_id, secret_key, join_plan, &mut rng)
.and_then(|builder| builder.batch_size(3).build(&mut rng))
@ -220,18 +221,17 @@ where
// Allow passing `netinfo` by value. `TestNetwork` expects this function signature.
#[allow(clippy::needless_pass_by_value)]
fn new_queueing_hb(
netinfo: Arc<NetworkInfo<NodeId>>,
seed: TestRngSeed,
) -> (QHB, Step<QueueingHoneyBadger<usize, NodeId, Vec<usize>>>) {
fn new_queueing_hb(node_info: NewNodeInfo<SQ>, seed: TestRngSeed) -> (SQ, Step<QHB>) {
let mut rng: TestRng = TestRng::from_seed(seed);
let peer_ids = netinfo.other_ids().cloned();
let dhb = DynamicHoneyBadger::builder().build((*netinfo).clone());
let peer_ids = node_info.netinfo.other_ids().cloned();
let netinfo = node_info.netinfo.clone();
let dhb =
DynamicHoneyBadger::builder().build(netinfo, node_info.secret_key, node_info.pub_keys);
let (qhb, qhb_step) = QueueingHoneyBadger::builder(dhb)
.batch_size(3)
.build(&mut rng)
.expect("failed to build QueueingHoneyBadger");
let our_id = *netinfo.our_id();
let our_id = *node_info.netinfo.our_id();
let (sq, mut step) = SenderQueue::builder(qhb, peer_ids).build(our_id);
let output = step.extend_with(qhb_step, |fault| fault, Message::from);
assert!(output.is_empty());
@ -243,7 +243,7 @@ fn test_queueing_honey_badger_different_sizes<A, F>(
num_txs: usize,
seed: TestRngSeed,
) where
A: Adversary<QHB>,
A: Adversary<SQ>,
F: Fn() -> A,
{
// This returns an error in all but the first test.
@ -272,7 +272,7 @@ fn test_queueing_honey_badger_different_sizes<A, F>(
// needs to be mutable, while we are in a function which captures immutably.
// To avoid convoluted clone/borrow constructs we pass a TestRngSeed
// rather than a TestRng instance.
new_queueing_hb(Arc::new(node_info.netinfo), seed)
new_queueing_hb(node_info, seed)
})
.build(&mut rng)
.expect("Could not construct test network.");

View File

@ -3,18 +3,14 @@
use std::collections::BTreeMap;
use hbbft::crypto::{PublicKey, SecretKey};
use hbbft::sync_key_gen::{PartOutcome, SyncKeyGen};
use hbbft::crypto::SecretKey;
use hbbft::sync_key_gen::{to_pub_keys, PartOutcome, SyncKeyGen};
use hbbft::util;
fn test_sync_key_gen_with(threshold: usize, node_num: usize) {
// Generate individual key pairs for encryption. These are not suitable for threshold schemes.
let sec_keys: Vec<SecretKey> = (0..node_num).map(|_| SecretKey::random()).collect();
let pub_keys: BTreeMap<usize, PublicKey> = sec_keys
.iter()
.map(SecretKey::public_key)
.enumerate()
.collect();
let pub_keys = to_pub_keys(sec_keys.iter().enumerate());
// Create the `SyncKeyGen` instances and initial proposals.
let mut nodes = Vec::new();