mirror of https://github.com/poanetwork/hbbft.git
review comment coverage
This commit is contained in:
parent
5008d11ada
commit
3393052b4b
|
@ -64,10 +64,6 @@ pub fn main() {
|
||||||
let args: Args = parse_args();
|
let args: Args = parse_args();
|
||||||
println!("{:?}", args);
|
println!("{:?}", args);
|
||||||
|
|
||||||
let node = Node::new(
|
let node = Node::new(args.bind_address, args.remote_addresses, args.value);
|
||||||
args.bind_address,
|
|
||||||
args.remote_addresses,
|
|
||||||
args.value,
|
|
||||||
);
|
|
||||||
node.run().expect("Node failed");
|
node.run().expect("Node failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,7 +428,7 @@ fn main() {
|
||||||
println!();
|
println!();
|
||||||
let num_good_nodes = args.flag_n - args.flag_f;
|
let num_good_nodes = args.flag_n - args.flag_f;
|
||||||
let txs = (0..args.flag_txs).map(|_| Transaction::new(args.flag_tx_size));
|
let txs = (0..args.flag_txs).map(|_| Transaction::new(args.flag_tx_size));
|
||||||
let sk_set = SecretKeySet::<Bls12>::new(args.flag_f, &mut rand::thread_rng());
|
let sk_set = SecretKeySet::<Bls12>::random(args.flag_f, &mut rand::thread_rng());
|
||||||
let pk_set = sk_set.public_keys();
|
let pk_set = sk_set.public_keys();
|
||||||
let new_honey_badger = |id: NodeUid, all_ids: BTreeSet<NodeUid>| {
|
let new_honey_badger = |id: NodeUid, all_ids: BTreeSet<NodeUid>| {
|
||||||
let netinfo = Rc::new(NetworkInfo::new(
|
let netinfo = Rc::new(NetworkInfo::new(
|
||||||
|
|
|
@ -65,12 +65,12 @@ pub struct AgreementMessage {
|
||||||
/// Binary Agreement instance
|
/// Binary Agreement instance
|
||||||
pub struct Agreement<NodeUid>
|
pub struct Agreement<NodeUid>
|
||||||
where
|
where
|
||||||
NodeUid: Clone + Debug,
|
NodeUid: Clone + Debug + Eq + Hash,
|
||||||
{
|
{
|
||||||
/// Shared network information.
|
/// Shared network information.
|
||||||
netinfo: Rc<NetworkInfo<NodeUid>>,
|
netinfo: Rc<NetworkInfo<NodeUid>>,
|
||||||
/// Honey Badger algorithm epoch.
|
/// Session ID, e.g, the Honey Badger algorithm epoch.
|
||||||
hb_epoch: u64,
|
session_id: u64,
|
||||||
/// Agreement algorithm epoch.
|
/// Agreement algorithm epoch.
|
||||||
epoch: u32,
|
epoch: u32,
|
||||||
/// Bin values. Reset on every epoch update.
|
/// Bin values. Reset on every epoch update.
|
||||||
|
@ -110,9 +110,6 @@ where
|
||||||
messages: VecDeque<AgreementMessage>,
|
messages: VecDeque<AgreementMessage>,
|
||||||
/// Whether the `Conf` message round has started in the current epoch.
|
/// Whether the `Conf` message round has started in the current epoch.
|
||||||
conf_round: bool,
|
conf_round: bool,
|
||||||
/// The subset of `bin_values` contained in received `Conf` messages before invoking the Common
|
|
||||||
/// Coin instance.
|
|
||||||
conf_vals: BinValues,
|
|
||||||
/// A common coin instance. It is reset on epoch update.
|
/// A common coin instance. It is reset on epoch update.
|
||||||
common_coin: CommonCoin<NodeUid, Nonce>,
|
common_coin: CommonCoin<NodeUid, Nonce>,
|
||||||
}
|
}
|
||||||
|
@ -174,11 +171,11 @@ impl<NodeUid: Clone + Debug + Eq + Hash + Ord> DistAlgorithm for Agreement<NodeU
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NodeUid: Clone + Debug + Eq + Hash + Ord> Agreement<NodeUid> {
|
impl<NodeUid: Clone + Debug + Eq + Hash + Ord> Agreement<NodeUid> {
|
||||||
pub fn new(netinfo: Rc<NetworkInfo<NodeUid>>, hb_epoch: u64) -> Self {
|
pub fn new(netinfo: Rc<NetworkInfo<NodeUid>>, session_id: u64) -> Self {
|
||||||
let invocation_id = netinfo.invocation_id();
|
let invocation_id = netinfo.invocation_id();
|
||||||
Agreement {
|
Agreement {
|
||||||
netinfo: netinfo.clone(),
|
netinfo: netinfo.clone(),
|
||||||
hb_epoch,
|
session_id,
|
||||||
epoch: 0,
|
epoch: 0,
|
||||||
bin_values: BinValues::new(),
|
bin_values: BinValues::new(),
|
||||||
received_bval: BTreeMap::new(),
|
received_bval: BTreeMap::new(),
|
||||||
|
@ -193,8 +190,7 @@ impl<NodeUid: Clone + Debug + Eq + Hash + Ord> Agreement<NodeUid> {
|
||||||
terminated: false,
|
terminated: false,
|
||||||
messages: VecDeque::new(),
|
messages: VecDeque::new(),
|
||||||
conf_round: false,
|
conf_round: false,
|
||||||
conf_vals: BinValues::None,
|
common_coin: CommonCoin::new(netinfo, Nonce::new(invocation_id.as_ref(), session_id, 0)),
|
||||||
common_coin: CommonCoin::new(netinfo, Nonce::new(invocation_id.as_ref(), hb_epoch, 0)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,15 +331,7 @@ impl<NodeUid: Clone + Debug + Eq + Hash + Ord> Agreement<NodeUid> {
|
||||||
self.extend_common_coin();
|
self.extend_common_coin();
|
||||||
|
|
||||||
if let Some(coin) = self.common_coin.next_output() {
|
if let Some(coin) = self.common_coin.next_output() {
|
||||||
// Check the termination condition: "continue looping until both a value b is output in some
|
let b = if let Some(b) = self.count_conf().1.definite() {
|
||||||
// round r, and the value Coin_r' = b for some round r' > r."
|
|
||||||
self.terminated = self.terminated || self.decision == Some(coin);
|
|
||||||
if self.terminated {
|
|
||||||
debug!("Node {:?} Agreement terminated", self.netinfo.our_uid());
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let b = if let Some(b) = self.conf_vals.definite() {
|
|
||||||
// Outputting a value is allowed only once.
|
// Outputting a value is allowed only once.
|
||||||
if self.decision.is_none() && b == coin {
|
if self.decision.is_none() && b == coin {
|
||||||
self.decide(b);
|
self.decide(b);
|
||||||
|
@ -394,12 +382,11 @@ impl<NodeUid: Clone + Debug + Eq + Hash + Ord> Agreement<NodeUid> {
|
||||||
|
|
||||||
fn try_finish_conf_round(&mut self) -> AgreementResult<()> {
|
fn try_finish_conf_round(&mut self) -> AgreementResult<()> {
|
||||||
if self.conf_round {
|
if self.conf_round {
|
||||||
let (count_vals, vals) = self.count_conf();
|
let (count_vals, _) = self.count_conf();
|
||||||
if count_vals < self.netinfo.num_nodes() - self.netinfo.num_faulty() {
|
if count_vals < self.netinfo.num_nodes() - self.netinfo.num_faulty() {
|
||||||
// Continue waiting for (N - f) `Conf` messages
|
// Continue waiting for (N - f) `Conf` messages
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
self.conf_vals = vals;
|
|
||||||
// Invoke the comon coin.
|
// Invoke the comon coin.
|
||||||
self.common_coin.input(())?;
|
self.common_coin.input(())?;
|
||||||
self.extend_common_coin();
|
self.extend_common_coin();
|
||||||
|
@ -459,11 +446,10 @@ impl<NodeUid: Clone + Debug + Eq + Hash + Ord> Agreement<NodeUid> {
|
||||||
self.received_aux.clear();
|
self.received_aux.clear();
|
||||||
self.received_conf.clear();
|
self.received_conf.clear();
|
||||||
self.conf_round = false;
|
self.conf_round = false;
|
||||||
self.conf_vals = BinValues::None;
|
|
||||||
self.epoch += 1;
|
self.epoch += 1;
|
||||||
let nonce = Nonce::new(
|
let nonce = Nonce::new(
|
||||||
self.netinfo.invocation_id().as_ref(),
|
self.netinfo.invocation_id().as_ref(),
|
||||||
self.hb_epoch,
|
self.session_id,
|
||||||
self.epoch,
|
self.epoch,
|
||||||
);
|
);
|
||||||
self.common_coin = CommonCoin::new(self.netinfo.clone(), nonce);
|
self.common_coin = CommonCoin::new(self.netinfo.clone(), nonce);
|
||||||
|
@ -479,10 +465,10 @@ impl<NodeUid: Clone + Debug + Eq + Hash + Ord> Agreement<NodeUid> {
|
||||||
struct Nonce(Vec<u8>);
|
struct Nonce(Vec<u8>);
|
||||||
|
|
||||||
impl Nonce {
|
impl Nonce {
|
||||||
pub fn new(invocation_id: &[u8], hb_epoch: u64, agreement_epoch: u32) -> Self {
|
pub fn new(invocation_id: &[u8], session_id: u64, agreement_epoch: u32) -> Self {
|
||||||
Nonce(Vec::from(format!(
|
Nonce(Vec::from(format!(
|
||||||
"Nonce for Honey Badger {:?} @ epoch {}:{}",
|
"Nonce for Honey Badger {:?}@{}:{}",
|
||||||
invocation_id, hb_epoch, agreement_epoch
|
invocation_id, session_id, agreement_epoch
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::{BTreeMap, VecDeque};
|
use std::collections::{BTreeMap, VecDeque};
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
|
use std::hash::Hash;
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@ impl Debug for BroadcastMessage {
|
||||||
/// eventually be able to decode (i.e. receive at least `f + 1` `Echo` messages).
|
/// eventually be able to decode (i.e. receive at least `f + 1` `Echo` messages).
|
||||||
/// * So a node with `2 * f + 1` `Ready`s and `f + 1` `Echos` will decode and _output_ the value,
|
/// * So a node with `2 * f + 1` `Ready`s and `f + 1` `Echos` will decode and _output_ the value,
|
||||||
/// knowing that every other good node will eventually do the same.
|
/// knowing that every other good node will eventually do the same.
|
||||||
pub struct Broadcast<N> {
|
pub struct Broadcast<N: Clone + Eq + Hash> {
|
||||||
/// Shared network data.
|
/// Shared network data.
|
||||||
netinfo: Rc<NetworkInfo<N>>,
|
netinfo: Rc<NetworkInfo<N>>,
|
||||||
/// The UID of the sending node.
|
/// The UID of the sending node.
|
||||||
|
@ -114,7 +115,7 @@ pub struct Broadcast<N> {
|
||||||
output: Option<Vec<u8>>,
|
output: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Eq + Debug + Clone + Ord> DistAlgorithm for Broadcast<N> {
|
impl<N: Eq + Debug + Clone + Hash + Ord> DistAlgorithm for Broadcast<N> {
|
||||||
type NodeUid = N;
|
type NodeUid = N;
|
||||||
// TODO: Allow anything serializable and deserializable, i.e. make this a type parameter
|
// TODO: Allow anything serializable and deserializable, i.e. make this a type parameter
|
||||||
// T: Serialize + DeserializeOwned
|
// T: Serialize + DeserializeOwned
|
||||||
|
@ -163,7 +164,7 @@ impl<N: Eq + Debug + Clone + Ord> DistAlgorithm for Broadcast<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Eq + Debug + Clone + Ord> Broadcast<N> {
|
impl<N: Eq + Debug + Clone + Hash + Ord> Broadcast<N> {
|
||||||
/// Creates a new broadcast instance to be used by node `our_id` which expects a value proposal
|
/// Creates a new broadcast instance to be used by node `our_id` which expects a value proposal
|
||||||
/// from node `proposer_id`.
|
/// from node `proposer_id`.
|
||||||
pub fn new(netinfo: Rc<NetworkInfo<N>>, proposer_id: N) -> BroadcastResult<Self> {
|
pub fn new(netinfo: Rc<NetworkInfo<N>>, proposer_id: N) -> BroadcastResult<Self> {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::collections::{BTreeMap, VecDeque};
|
use std::collections::{BTreeMap, VecDeque};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::mem::replace;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use pairing::bls12_381::Bls12;
|
use pairing::bls12_381::Bls12;
|
||||||
|
@ -46,7 +46,7 @@ impl CommonCoinMessage {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CommonCoin<N, T>
|
pub struct CommonCoin<N, T>
|
||||||
where
|
where
|
||||||
N: Debug,
|
N: Clone + Debug + Eq + Hash,
|
||||||
{
|
{
|
||||||
netinfo: Rc<NetworkInfo<N>>,
|
netinfo: Rc<NetworkInfo<N>>,
|
||||||
/// The name of this common coin. It is required to be unique for each common coin round.
|
/// The name of this common coin. It is required to be unique for each common coin round.
|
||||||
|
@ -55,8 +55,6 @@ where
|
||||||
output: Option<bool>,
|
output: Option<bool>,
|
||||||
/// Outgoing message queue.
|
/// Outgoing message queue.
|
||||||
messages: VecDeque<CommonCoinMessage>,
|
messages: VecDeque<CommonCoinMessage>,
|
||||||
/// Incoming messages buffered before we provide input to the common coin.
|
|
||||||
incoming_queue: VecDeque<(N, Signature<Bls12>)>,
|
|
||||||
/// All received threshold signature shares.
|
/// All received threshold signature shares.
|
||||||
received_shares: BTreeMap<N, Signature<Bls12>>,
|
received_shares: BTreeMap<N, Signature<Bls12>>,
|
||||||
/// Whether we provided input to the common coin.
|
/// Whether we provided input to the common coin.
|
||||||
|
@ -67,7 +65,7 @@ where
|
||||||
|
|
||||||
impl<N, T> DistAlgorithm for CommonCoin<N, T>
|
impl<N, T> DistAlgorithm for CommonCoin<N, T>
|
||||||
where
|
where
|
||||||
N: Clone + Debug + Ord,
|
N: Clone + Debug + Hash + Ord,
|
||||||
T: Clone + AsRef<[u8]>,
|
T: Clone + AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
type NodeUid = N;
|
type NodeUid = N;
|
||||||
|
@ -91,19 +89,7 @@ where
|
||||||
if self.terminated {
|
if self.terminated {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let CommonCoinMessage(share) = message;
|
let CommonCoinMessage(share) = message;
|
||||||
|
|
||||||
if !self.had_input {
|
|
||||||
self.incoming_queue.push_back((sender_id.clone(), share));
|
|
||||||
return Ok(());
|
|
||||||
} else {
|
|
||||||
let queued_msgs = replace(&mut self.incoming_queue, VecDeque::new());
|
|
||||||
for (sender_id, msg) in queued_msgs {
|
|
||||||
self.handle_share(&sender_id, msg)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.handle_share(sender_id, share)
|
self.handle_share(sender_id, share)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +117,7 @@ where
|
||||||
|
|
||||||
impl<N, T> CommonCoin<N, T>
|
impl<N, T> CommonCoin<N, T>
|
||||||
where
|
where
|
||||||
N: Clone + Debug + Ord,
|
N: Clone + Debug + Hash + Ord,
|
||||||
T: Clone + AsRef<[u8]>,
|
T: Clone + AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
pub fn new(netinfo: Rc<NetworkInfo<N>>, nonce: T) -> Self {
|
pub fn new(netinfo: Rc<NetworkInfo<N>>, nonce: T) -> Self {
|
||||||
|
@ -140,7 +126,6 @@ where
|
||||||
nonce,
|
nonce,
|
||||||
output: None,
|
output: None,
|
||||||
messages: VecDeque::new(),
|
messages: VecDeque::new(),
|
||||||
incoming_queue: VecDeque::new(),
|
|
||||||
received_shares: BTreeMap::new(),
|
received_shares: BTreeMap::new(),
|
||||||
had_input: false,
|
had_input: false,
|
||||||
terminated: false,
|
terminated: false,
|
||||||
|
@ -155,63 +140,54 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_share(&mut self, sender_id: &N, share: Signature<Bls12>) -> Result<()> {
|
fn handle_share(&mut self, sender_id: &N, share: Signature<Bls12>) -> Result<()> {
|
||||||
let node_indices = self.netinfo.node_indices();
|
if let Some(i) = self.netinfo.node_index(sender_id) {
|
||||||
if let Some(i) = node_indices.get(sender_id) {
|
let pk_i = self.netinfo.public_key_set().public_key_share(*i as u64);
|
||||||
let pk_i = self.netinfo.public_key_set().public_key_share(*i);
|
|
||||||
if !pk_i.verify(&share, &self.nonce) {
|
if !pk_i.verify(&share, &self.nonce) {
|
||||||
// Silently ignore the invalid share.
|
// Silently ignore the invalid share.
|
||||||
debug!(
|
|
||||||
"{:?} received invalid share from {:?}",
|
|
||||||
self.netinfo.our_uid(),
|
|
||||||
sender_id
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(
|
|
||||||
"{:?} received a valid share from {:?}",
|
|
||||||
self.netinfo.our_uid(),
|
|
||||||
sender_id
|
|
||||||
);
|
|
||||||
self.received_shares.insert(sender_id.clone(), share);
|
self.received_shares.insert(sender_id.clone(), share);
|
||||||
let received_shares = &self.received_shares;
|
let received_shares = &self.received_shares;
|
||||||
if received_shares.len() > self.netinfo.num_faulty() {
|
if self.had_input && received_shares.len() > self.netinfo.num_faulty() {
|
||||||
// Pass the indices of sender nodes to `combine_signatures`.
|
let sig = self.combine_and_verify_sig()?;
|
||||||
let shares: BTreeMap<&u64, &Signature<Bls12>> = self
|
|
||||||
.netinfo
|
|
||||||
.all_uids()
|
|
||||||
.iter()
|
|
||||||
.map(|id| (&node_indices[id], received_shares.get(id)))
|
|
||||||
.filter(|(_, share)| share.is_some())
|
|
||||||
.map(|(n, share)| (n, share.unwrap()))
|
|
||||||
.collect();
|
|
||||||
let sig = self.netinfo.public_key_set().combine_signatures(shares)?;
|
|
||||||
|
|
||||||
// Verify the successfully combined signature with the main public key.
|
|
||||||
if !self
|
|
||||||
.netinfo
|
|
||||||
.public_key_set()
|
|
||||||
.public_key()
|
|
||||||
.verify(&sig, &self.nonce)
|
|
||||||
{
|
|
||||||
// Abort
|
|
||||||
error!(
|
|
||||||
"{:?} main public key verification failed",
|
|
||||||
self.netinfo.our_uid()
|
|
||||||
);
|
|
||||||
self.terminated = true;
|
|
||||||
return Err(ErrorKind::VerificationFailed.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output the parity of the verified signature.
|
// Output the parity of the verified signature.
|
||||||
let parity = sig.parity();
|
let parity = sig.parity();
|
||||||
self.output = Some(parity);
|
self.output = Some(parity);
|
||||||
self.terminated = true;
|
self.terminated = true;
|
||||||
debug!("{:?} coin is {}", self.netinfo.our_uid(), parity);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ErrorKind::UnknownSender.into())
|
Err(ErrorKind::UnknownSender.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn combine_and_verify_sig(&self) -> Result<Signature<Bls12>> {
|
||||||
|
// Pass the indices of sender nodes to `combine_signatures`.
|
||||||
|
let ids_shares: BTreeMap<&N, &Signature<Bls12>> = self.received_shares.iter().collect();
|
||||||
|
let ids_u64: BTreeMap<&N, u64> = ids_shares
|
||||||
|
.keys()
|
||||||
|
.map(|&id| (id, *self.netinfo.node_index(id).unwrap() as u64))
|
||||||
|
.collect();
|
||||||
|
// Convert indices to `u64` which is an interface type for `pairing`.
|
||||||
|
let shares: BTreeMap<&u64, &Signature<Bls12>> = ids_shares
|
||||||
|
.iter()
|
||||||
|
.map(|(id, &share)| (&ids_u64[id], share))
|
||||||
|
.collect();
|
||||||
|
let sig = self.netinfo.public_key_set().combine_signatures(shares)?;
|
||||||
|
if !self
|
||||||
|
.netinfo
|
||||||
|
.public_key_set()
|
||||||
|
.public_key()
|
||||||
|
.verify(&sig, &self.nonce)
|
||||||
|
{
|
||||||
|
// Abort
|
||||||
|
error!(
|
||||||
|
"{:?} main public key verification failed",
|
||||||
|
self.netinfo.our_uid()
|
||||||
|
);
|
||||||
|
Err(ErrorKind::VerificationFailed.into())
|
||||||
|
} else {
|
||||||
|
Ok(sig)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ impl<E: Engine> PublicKey<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A signature, or a signature share.
|
/// A signature, or a signature share.
|
||||||
#[derive(Clone, PartialOrd)]
|
#[derive(Clone)]
|
||||||
pub struct Signature<E: Engine>(E::G2);
|
pub struct Signature<E: Engine>(E::G2);
|
||||||
|
|
||||||
impl<E: Engine> fmt::Debug for Signature<E> {
|
impl<E: Engine> fmt::Debug for Signature<E> {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeSet, HashMap};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
use pairing::bls12_381::Bls12;
|
use pairing::bls12_381::Bls12;
|
||||||
|
|
||||||
|
@ -131,16 +132,17 @@ impl<'a, D: DistAlgorithm + 'a> Iterator for OutputIter<'a, D> {
|
||||||
|
|
||||||
/// Common data shared between algorithms.
|
/// Common data shared between algorithms.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NetworkInfo<NodeUid> {
|
pub struct NetworkInfo<NodeUid: Clone + Eq + Hash> {
|
||||||
our_uid: NodeUid,
|
our_uid: NodeUid,
|
||||||
all_uids: BTreeSet<NodeUid>,
|
all_uids: BTreeSet<NodeUid>,
|
||||||
num_nodes: usize,
|
num_nodes: usize,
|
||||||
num_faulty: usize,
|
num_faulty: usize,
|
||||||
secret_key: SecretKey<Bls12>,
|
secret_key: SecretKey<Bls12>,
|
||||||
public_key_set: PublicKeySet<Bls12>,
|
public_key_set: PublicKeySet<Bls12>,
|
||||||
|
node_indices: HashMap<NodeUid, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NodeUid: Ord> NetworkInfo<NodeUid> {
|
impl<NodeUid: Clone + Hash + Ord> NetworkInfo<NodeUid> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
our_uid: NodeUid,
|
our_uid: NodeUid,
|
||||||
all_uids: BTreeSet<NodeUid>,
|
all_uids: BTreeSet<NodeUid>,
|
||||||
|
@ -151,6 +153,12 @@ impl<NodeUid: Ord> NetworkInfo<NodeUid> {
|
||||||
panic!("Missing own ID");
|
panic!("Missing own ID");
|
||||||
}
|
}
|
||||||
let num_nodes = all_uids.len();
|
let num_nodes = all_uids.len();
|
||||||
|
let node_indices = all_uids
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(n, id)| (id, n))
|
||||||
|
.collect();
|
||||||
NetworkInfo {
|
NetworkInfo {
|
||||||
our_uid,
|
our_uid,
|
||||||
all_uids,
|
all_uids,
|
||||||
|
@ -158,6 +166,7 @@ impl<NodeUid: Ord> NetworkInfo<NodeUid> {
|
||||||
num_faulty: (num_nodes - 1) / 3,
|
num_faulty: (num_nodes - 1) / 3,
|
||||||
secret_key,
|
secret_key,
|
||||||
public_key_set,
|
public_key_set,
|
||||||
|
node_indices,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,18 +199,17 @@ impl<NodeUid: Ord> NetworkInfo<NodeUid> {
|
||||||
&self.public_key_set
|
&self.public_key_set
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The canonical numbering of all nodes.
|
/// The index of a node in a canonical numbering of all nodes.
|
||||||
///
|
pub fn node_index(&self, id: &NodeUid) -> Option<&usize> {
|
||||||
/// FIXME: To avoid multiple computations of the same result, caching should be introduced.
|
self.node_indices.get(id)
|
||||||
pub fn node_indices(&self) -> BTreeMap<&NodeUid, u64> {
|
|
||||||
self.all_uids
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(n, id)| (id, n as u64))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the unique ID of the Honey Badger invocation.
|
/// Returns the unique ID of the Honey Badger invocation.
|
||||||
|
///
|
||||||
|
/// FIXME: Using the public key as the invocation ID either requires agreeing on the keys on
|
||||||
|
/// each invocation, or makes it unsafe to reuse keys for different invocations. A better
|
||||||
|
/// invocation ID would be one that is distributed to all nodes on each invocation and would be
|
||||||
|
/// independent from the public key, so that reusing keys would be safer.
|
||||||
pub fn invocation_id(&self) -> Vec<u8> {
|
pub fn invocation_id(&self) -> Vec<u8> {
|
||||||
self.public_key_set.public_key().to_bytes()
|
self.public_key_set.public_key().to_bytes()
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,8 @@ const GOOD_SAMPLE_SET: f64 = 400.0;
|
||||||
/// sample set. This check assumes logarithmic growth of the expected number of throws of one coin
|
/// sample set. This check assumes logarithmic growth of the expected number of throws of one coin
|
||||||
/// size.
|
/// size.
|
||||||
fn check_coin_distribution(num_samples: usize, count_true: usize, count_false: usize) {
|
fn check_coin_distribution(num_samples: usize, count_true: usize, count_false: usize) {
|
||||||
const EXPECTED_SHARE: f64 = 0.48;
|
// Maximum 40% expectation in case of 400 samples or more.
|
||||||
|
const EXPECTED_SHARE: f64 = 0.4;
|
||||||
let max_gain = GOOD_SAMPLE_SET.log2();
|
let max_gain = GOOD_SAMPLE_SET.log2();
|
||||||
let num_samples_f64 = num_samples as f64;
|
let num_samples_f64 = num_samples as f64;
|
||||||
let gain = num_samples_f64.log2().min(max_gain);
|
let gain = num_samples_f64.log2().min(max_gain);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use pairing::bls12_381::Bls12;
|
use pairing::bls12_381::Bls12;
|
||||||
|
@ -143,7 +144,10 @@ impl<D: DistAlgorithm> Adversary<D> for SilentAdversary {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of `TestNode`s representing a network.
|
/// A collection of `TestNode`s representing a network.
|
||||||
pub struct TestNetwork<A: Adversary<D>, D: DistAlgorithm> {
|
pub struct TestNetwork<A: Adversary<D>, D: DistAlgorithm>
|
||||||
|
where
|
||||||
|
<D as DistAlgorithm>::NodeUid: Hash,
|
||||||
|
{
|
||||||
pub nodes: BTreeMap<D::NodeUid, TestNode<D>>,
|
pub nodes: BTreeMap<D::NodeUid, TestNode<D>>,
|
||||||
pub adv_nodes: BTreeMap<D::NodeUid, Rc<NetworkInfo<D::NodeUid>>>,
|
pub adv_nodes: BTreeMap<D::NodeUid, Rc<NetworkInfo<D::NodeUid>>>,
|
||||||
adversary: A,
|
adversary: A,
|
||||||
|
|
Loading…
Reference in New Issue