diff --git a/Cargo.toml b/Cargo.toml index 688c27e..f3c7398 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/examples/simulation.rs b/examples/simulation.rs index 3fdffff..cba5e0e 100644 --- a/examples/simulation.rs +++ b/examples/simulation.rs @@ -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 where - F: Fn(NetworkInfo, &mut R) -> (D, CpStep), + F: Fn(NetworkInfo, SecretKey, PubKeyMap, &mut R) -> (D, CpStep), { 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, rng: &mut OsRng| { + let new_honey_badger = |netinfo: NetworkInfo, 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) diff --git a/hbbft_testing/src/lib.rs b/hbbft_testing/src/lib.rs index b200848..4a39ae5 100644 --- a/hbbft_testing/src/lib.rs +++ b/hbbft_testing/src/lib.rs @@ -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, /// Network info struct, containing keys and other information. pub netinfo: NetworkInfo, /// Whether or not the node is marked faulty. @@ -749,8 +757,13 @@ where I: IntoIterator, 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 = 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, }); diff --git a/src/dynamic_honey_badger/batch.rs b/src/dynamic_honey_badger/batch.rs index e50cd3a..9289688 100644 --- a/src/dynamic_honey_badger/batch.rs +++ b/src/dynamic_honey_badger/batch.rs @@ -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 { /// The current state of adding or removing a node: whether any is in progress, or completed /// this epoch. pub(super) change: ChangeState, + /// The current set of public keys. + pub(super) pub_keys: PubKeyMap, /// The network info that applies to the _next_ epoch. pub(super) netinfo: Arc>, /// Parameters controlling Honey Badger's behavior and performance. @@ -39,6 +41,11 @@ impl Batch { &self.change } + /// Returns the map of public keys, by node ID. + pub fn public_keys(&self) -> &PubKeyMap { + &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> { @@ -98,8 +105,8 @@ impl Batch { 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 Batch { && 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 } } diff --git a/src/dynamic_honey_badger/builder.rs b/src/dynamic_honey_badger/builder.rs index 61aacb1..881e3b6 100644 --- a/src/dynamic_honey_badger/builder.rs +++ b/src/dynamic_honey_badger/builder.rs @@ -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) -> DynamicHoneyBadger { - 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, + secret_key: SecretKey, + pub_keys: PubKeyMap, + ) -> DynamicHoneyBadger { + 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::(); - 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 diff --git a/src/dynamic_honey_badger/change.rs b/src/dynamic_honey_badger/change.rs index 54103ba..9ff8c8d 100644 --- a/src/dynamic_honey_badger/change.rs +++ b/src/dynamic_honey_badger/change.rs @@ -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 { /// 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), + NodeChange(PubKeyMap), /// Change the threshold encryption schedule. /// Increase frequency to prevent censorship or decrease frequency for increased throughput. EncryptionSchedule(EncryptionSchedule), diff --git a/src/dynamic_honey_badger/dynamic_honey_badger.rs b/src/dynamic_honey_badger/dynamic_honey_badger.rs index db8752c..6156987 100644 --- a/src/dynamic_honey_badger/dynamic_honey_badger.rs +++ b/src/dynamic_honey_badger/dynamic_honey_badger.rs @@ -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 { - /// Shared network data. - pub(super) netinfo: NetworkInfo, + /// This node's secret key. + secret_key: SecretKey, + /// The validators' public keys. + pub_keys: PubKeyMap, /// 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, + vote_counter: VoteCounter, /// Pending node transactions that we will propose in the next epoch. - pub(super) key_gen_msg_buffer: Vec>, + key_gen_msg_buffer: Vec>, /// The `HoneyBadger` instance with the current set of nodes. - pub(super) honey_badger: HoneyBadger, N>, + honey_badger: HoneyBadger, N>, /// The current key generation process, and the change it applies to. - pub(super) key_gen_state: Option>, + key_gen_state: Option>, } impl ConsensusProtocol for DynamicHoneyBadger @@ -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, + netinfo: Arc>, + 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( our_id: N, @@ -98,34 +127,22 @@ where join_plan: JoinPlan, rng: &mut R, ) -> Result<(Self, Step)> { - 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) -> Result> { - 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> { - 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> { - 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 { + &self.pub_keys + } + /// Returns the information about the node IDs in the network, and the cryptographic keys. - pub fn netinfo(&self) -> &NetworkInfo { - &self.netinfo + pub fn netinfo(&self) -> &Arc> { + &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, rng: &mut R, ) -> Result> { - 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( &mut self, era: u64, - pub_keys: &BTreeMap, + pub_keys: PubKeyMap, rng: &mut R, ) -> Result> { - 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>) { 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> { 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)) } diff --git a/src/dynamic_honey_badger/mod.rs b/src/dynamic_honey_badger/mod.rs index d2ed007..86d8d88 100644 --- a/src/dynamic_honey_badger/mod.rs +++ b/src/dynamic_honey_badger/mod.rs @@ -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 Message { /// 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 { /// 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, + /// The current set of public keys. + pub_keys: PubKeyMap, /// The current public key set for threshold cryptography. pub_key_set: PublicKeySet, - /// The public keys of the current validators. - pub_keys: BTreeMap, /// Parameters controlling Honey Badger's behavior and performance. params: Params, } @@ -181,7 +182,7 @@ impl KeyGenState { } /// Returns the map of new validators and their public keys. - fn public_keys(&self) -> &BTreeMap { + fn public_keys(&self) -> &PubKeyMap { self.key_gen.public_keys() } diff --git a/src/dynamic_honey_badger/votes.rs b/src/dynamic_honey_badger/votes.rs index 97039ff..55bfa35 100644 --- a/src/dynamic_honey_badger/votes.rs +++ b/src/dynamic_honey_badger/votes.rs @@ -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 = fault_log::FaultLog; @@ -17,8 +15,14 @@ pub type FaultLog = fault_log::FaultLog; /// the epochs since the last reset the current _era_. #[derive(Debug)] pub struct VoteCounter { - /// Shared network data. - netinfo: Arc>, + /// 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, /// 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>, era: u64) -> Self { + pub fn new(our_id: N, secret_key: SecretKey, pub_keys: PubKeyMap, 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) -> Result<&SignedVote> { - 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) -> Result { 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 SignedVote { #[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>, Vec>>) { - 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| { (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::>() }; diff --git a/src/honey_badger/honey_badger.rs b/src/honey_badger/honey_badger.rs index ac785d7..a267015 100644 --- a/src/honey_badger/honey_badger.rs +++ b/src/honey_badger/honey_badger.rs @@ -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> { + &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 diff --git a/src/lib.rs b/src/lib.rs index ebf50dc..a4bacf8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, }; diff --git a/src/network_info.rs b/src/network_info.rs index b9e0d15..72701dd 100644 --- a/src/network_info.rs +++ b/src/network_info.rs @@ -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 { is_validator: bool, /// This node's secret key share. Only validators have one. secret_key_share: Option, - /// 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, - /// The validators' public keys. - public_keys: BTreeMap, /// The indices in the list of sorted validator IDs. val_set: Arc>, } @@ -114,14 +110,13 @@ impl NetworkInfo { /// /// 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>>( + pub fn new>, V: Into>>( our_id: N, secret_key_share: SKS, public_key_set: PublicKeySet, - secret_key: SecretKey, - public_keys: BTreeMap, + 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 NetworkInfo { our_id, is_validator, secret_key_share, - secret_key, public_key_set, public_key_shares, val_set, - public_keys, } } @@ -192,12 +185,6 @@ impl NetworkInfo { 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 NetworkInfo { &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 { - &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 NetworkInfo { /// 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 NetworkInfo { 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() } } diff --git a/src/sender_queue/dynamic_honey_badger.rs b/src/sender_queue/dynamic_honey_badger.rs index c2670e5..68e8b9c 100644 --- a/src/sender_queue/dynamic_honey_badger.rs +++ b/src/sender_queue/dynamic_honey_badger.rs @@ -26,8 +26,7 @@ where fn participant_change(&self) -> Option> { 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) diff --git a/src/sync_key_gen.rs b/src/sync_key_gen.rs index 16ec0a3..a31d13f 100644 --- a/src/sync_key_gen.rs +++ b/src/sync_key_gen.rs @@ -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 = (0..node_num).map(|_| rand::random()).collect(); -//! let pub_keys: BTreeMap = 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 = Arc>; + +/// 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 +where + B: Borrow, + I: IntoIterator, +{ + 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 { /// Our secret key. sec_key: SecretKey, /// The public keys of all nodes, by node ID. - pub_keys: BTreeMap, + pub_keys: PubKeyMap, /// Proposed bivariate polynomials. parts: BTreeMap, /// The degree of the generated polynomial. @@ -323,7 +337,7 @@ impl SyncKeyGen { pub fn new( our_id: N, sec_key: SecretKey, - pub_keys: BTreeMap, + pub_keys: PubKeyMap, threshold: usize, rng: &mut R, ) -> Result<(SyncKeyGen, Option), Error> { @@ -359,7 +373,7 @@ impl SyncKeyGen { } /// Returns the map of participating nodes and their public keys. - pub fn public_keys(&self) -> &BTreeMap { + pub fn public_keys(&self) -> &PubKeyMap { &self.pub_keys } @@ -461,17 +475,6 @@ impl SyncKeyGen { 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, 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() diff --git a/tests/dynamic_honey_badger.rs b/tests/dynamic_honey_badger.rs index db79a38..1d91836 100644 --- a/tests/dynamic_honey_badger.rs +++ b/tests/dynamic_honey_badger.rs @@ -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, 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 = 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 = 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 { + fn get_pub_keys(&self) -> PubKeyMap { self.net .get(0) .expect("network should have at least one node") .algorithm() .algo() - .netinfo() - .public_key_map() + .public_keys() .clone() } } diff --git a/tests/queueing_honey_badger.rs b/tests/queueing_honey_badger.rs index 5cc5ef4..c7b9346 100644 --- a/tests/queueing_honey_badger.rs +++ b/tests/queueing_honey_badger.rs @@ -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>>; +type QHB = QueueingHoneyBadger>; +type SQ = SenderQueue; // Send the second half of the transactions to the specified node. fn input_second_half( - net: &mut VirtualNet, + net: &mut VirtualNet, id: NodeId, num_txs: usize, mut rng: &mut TestRng, ) where - A: Adversary, + A: Adversary, { 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( } /// Proposes `num_txs` values and expects nodes to output and order them. -fn test_queueing_honey_badger(mut net: VirtualNet, num_txs: usize, mut rng: &mut TestRng) +fn test_queueing_honey_badger(mut net: VirtualNet, num_txs: usize, mut rng: &mut TestRng) where - A: Adversary, + A: Adversary, { - 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| { + let has_remove = |node: &Node| { 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| { + let has_add = |node: &Node| { 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| { + let node_busy = |node: &Node| { !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> = None; + let mut saved_first_correct: Option> = 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( - net: &mut VirtualNet, - mut node: Node, + net: &mut VirtualNet, + mut node: Node, join_plan: JoinPlan, mut rng: &mut R, ) -> Step>> where R: rand::Rng, - A: Adversary, + A: Adversary, { 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>, - seed: TestRngSeed, -) -> (QHB, Step>>) { +fn new_queueing_hb(node_info: NewNodeInfo, seed: TestRngSeed) -> (SQ, Step) { 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( num_txs: usize, seed: TestRngSeed, ) where - A: Adversary, + A: Adversary, F: Fn() -> A, { // This returns an error in all but the first test. @@ -272,7 +272,7 @@ fn test_queueing_honey_badger_different_sizes( // 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."); diff --git a/tests/sync_key_gen.rs b/tests/sync_key_gen.rs index d3c6fcd..48d5d33 100644 --- a/tests/sync_key_gen.rs +++ b/tests/sync_key_gen.rs @@ -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 = (0..node_num).map(|_| SecretKey::random()).collect(); - let pub_keys: BTreeMap = 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();