mirror of https://github.com/poanetwork/hbbft.git
added an optional observer node in the net framework
This commit is contained in:
parent
5dc52e0e51
commit
7811bff741
|
@ -22,7 +22,7 @@ use std::{cmp, collections, env, fmt, fs, io, ops, process, time};
|
||||||
|
|
||||||
use rand;
|
use rand;
|
||||||
use rand::{Rand, Rng};
|
use rand::{Rand, Rng};
|
||||||
use threshold_crypto as crypto;
|
use threshold_crypto::{self as crypto, SecretKeyShare};
|
||||||
|
|
||||||
use hbbft::dynamic_honey_badger::Batch;
|
use hbbft::dynamic_honey_badger::Batch;
|
||||||
use hbbft::util::SubRng;
|
use hbbft::util::SubRng;
|
||||||
|
@ -302,7 +302,7 @@ pub struct NetBuilder<D, I>
|
||||||
where
|
where
|
||||||
D: DistAlgorithm,
|
D: DistAlgorithm,
|
||||||
{
|
{
|
||||||
/// Iterator used to create node ids.
|
/// Iterator used to create validator node ids.
|
||||||
node_ids: I,
|
node_ids: I,
|
||||||
/// Number of faulty nodes in the network.
|
/// Number of faulty nodes in the network.
|
||||||
num_faulty: usize,
|
num_faulty: usize,
|
||||||
|
@ -318,6 +318,9 @@ where
|
||||||
message_limit: Option<usize>,
|
message_limit: Option<usize>,
|
||||||
/// Optional time limit.
|
/// Optional time limit.
|
||||||
time_limit: Option<time::Duration>,
|
time_limit: Option<time::Duration>,
|
||||||
|
/// Optional observer node ID. It must not be a member of `node_ids` for the latter are
|
||||||
|
/// validator node IDs.
|
||||||
|
observer_id: Option<D::NodeId>,
|
||||||
/// Random number generator used to generate keys.
|
/// Random number generator used to generate keys.
|
||||||
rng: Option<Box<dyn Rng>>,
|
rng: Option<Box<dyn Rng>>,
|
||||||
}
|
}
|
||||||
|
@ -336,6 +339,7 @@ where
|
||||||
.field("crank_limit", &self.crank_limit)
|
.field("crank_limit", &self.crank_limit)
|
||||||
.field("message_limit", &self.message_limit)
|
.field("message_limit", &self.message_limit)
|
||||||
.field("time_limit", &self.time_limit)
|
.field("time_limit", &self.time_limit)
|
||||||
|
.field("observer_id", &self.observer_id)
|
||||||
.field("rng", &"<RNG>")
|
.field("rng", &"<RNG>")
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
@ -368,6 +372,7 @@ where
|
||||||
message_limit: None,
|
message_limit: None,
|
||||||
time_limit: DEFAULT_TIME_LIMIT,
|
time_limit: DEFAULT_TIME_LIMIT,
|
||||||
rng: None,
|
rng: None,
|
||||||
|
observer_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,6 +461,15 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Override the default observer setting.
|
||||||
|
///
|
||||||
|
/// Adds an additional, observer node to the network.
|
||||||
|
#[inline]
|
||||||
|
pub fn observer_id(mut self, observer_id: D::NodeId) -> Self {
|
||||||
|
self.observer_id = Some(observer_id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor function (with step).
|
/// Constructor function (with step).
|
||||||
///
|
///
|
||||||
/// The constructor function is used to construct each node in the network. Any step returned
|
/// The constructor function is used to construct each node in the network. Any step returned
|
||||||
|
@ -513,9 +527,13 @@ where
|
||||||
|
|
||||||
// Note: Closure is not redundant, won't compile without it.
|
// Note: Closure is not redundant, won't compile without it.
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]
|
#[cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]
|
||||||
let mut net = VirtualNet::new(self.node_ids, self.num_faulty as usize, rng, move |node| {
|
let mut net = VirtualNet::new(
|
||||||
cons(node)
|
self.node_ids,
|
||||||
})?;
|
self.num_faulty as usize,
|
||||||
|
rng,
|
||||||
|
self.observer_id,
|
||||||
|
move |node| cons(node),
|
||||||
|
)?;
|
||||||
|
|
||||||
if self.adversary.is_some() {
|
if self.adversary.is_some() {
|
||||||
net.adversary = self.adversary;
|
net.adversary = self.adversary;
|
||||||
|
@ -569,6 +587,8 @@ where
|
||||||
time_limit: Option<time::Duration>,
|
time_limit: Option<time::Duration>,
|
||||||
/// The instant the network was created.
|
/// The instant the network was created.
|
||||||
start_time: time::Instant,
|
start_time: time::Instant,
|
||||||
|
/// Optional observer node ID.
|
||||||
|
observer_id: Option<D::NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> fmt::Debug for VirtualNet<D>
|
impl<D> fmt::Debug for VirtualNet<D>
|
||||||
|
@ -700,6 +720,11 @@ where
|
||||||
msgs.sort_by(f);
|
msgs.sort_by(f);
|
||||||
self.messages.extend(msgs);
|
self.messages.extend(msgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the observer node ID if it is defined and `None` otherwise.
|
||||||
|
pub fn observer_id(&self) -> Option<&D::NodeId> {
|
||||||
|
self.observer_id.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> VirtualNet<D>
|
impl<D> VirtualNet<D>
|
||||||
|
@ -726,6 +751,7 @@ where
|
||||||
node_ids: I,
|
node_ids: I,
|
||||||
faulty: usize,
|
faulty: usize,
|
||||||
mut rng: R,
|
mut rng: R,
|
||||||
|
observer_id: Option<D::NodeId>,
|
||||||
cons: F,
|
cons: F,
|
||||||
) -> Result<Self, crypto::error::Error>
|
) -> Result<Self, crypto::error::Error>
|
||||||
where
|
where
|
||||||
|
@ -734,22 +760,29 @@ where
|
||||||
R: rand::Rng,
|
R: rand::Rng,
|
||||||
{
|
{
|
||||||
// Generate a new set of cryptographic keys for threshold cryptography.
|
// Generate a new set of cryptographic keys for threshold cryptography.
|
||||||
let net_infos = NetworkInfo::generate_map(node_ids, &mut rng)?;
|
let netinfos = NetworkInfo::generate_map(node_ids, &mut rng)?;
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
faulty * 3 < net_infos.len(),
|
faulty * 3 < netinfos.len(),
|
||||||
"Too many faulty nodes requested, `f` must satisfy `3f < total_nodes`."
|
"Too many faulty nodes requested, `f` must satisfy `3f < total_nodes`."
|
||||||
);
|
);
|
||||||
|
let observer_netinfo = observer_id.map(|observer_id| {
|
||||||
|
let node_ni = netinfos.values().next().unwrap();
|
||||||
|
NetworkInfo::new(
|
||||||
|
observer_id,
|
||||||
|
SecretKeyShare::default(),
|
||||||
|
node_ni.public_key_set().clone(),
|
||||||
|
rng.gen(),
|
||||||
|
node_ni.public_key_map().clone(),
|
||||||
|
)
|
||||||
|
});
|
||||||
let mut steps = collections::BTreeMap::new();
|
let mut steps = collections::BTreeMap::new();
|
||||||
let mut messages = collections::VecDeque::new();
|
let mut messages = collections::VecDeque::new();
|
||||||
|
let mut nodes: collections::BTreeMap<_, _> = netinfos
|
||||||
let mut nodes = net_infos
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, (id, netinfo))| {
|
.map(|(idx, (id, netinfo))| {
|
||||||
let is_faulty = idx < faulty;
|
let is_faulty = idx < faulty;
|
||||||
|
|
||||||
let (algorithm, step) = cons(NewNodeInfo {
|
let (algorithm, step) = cons(NewNodeInfo {
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
netinfo,
|
netinfo,
|
||||||
|
@ -759,7 +792,19 @@ where
|
||||||
steps.insert(id.clone(), step);
|
steps.insert(id.clone(), step);
|
||||||
(id, Node::new(algorithm, is_faulty))
|
(id, Node::new(algorithm, is_faulty))
|
||||||
}).collect();
|
}).collect();
|
||||||
|
// Add the observer node if required.
|
||||||
|
let observer_id = observer_netinfo.map(|netinfo| {
|
||||||
|
let id = netinfo.our_id().clone();
|
||||||
|
let (algorithm, step) = cons(NewNodeInfo {
|
||||||
|
id: id.clone(),
|
||||||
|
netinfo,
|
||||||
|
faulty: false,
|
||||||
|
rng: rng.sub_rng(),
|
||||||
|
});
|
||||||
|
steps.insert(id.clone(), step);
|
||||||
|
nodes.insert(id.clone(), Node::new(algorithm, false));
|
||||||
|
id
|
||||||
|
});
|
||||||
let mut message_count: usize = 0;
|
let mut message_count: usize = 0;
|
||||||
// For every recorded step, apply it.
|
// For every recorded step, apply it.
|
||||||
for (sender, step) in steps {
|
for (sender, step) in steps {
|
||||||
|
@ -782,6 +827,7 @@ where
|
||||||
message_limit: None,
|
message_limit: None,
|
||||||
time_limit: None,
|
time_limit: None,
|
||||||
start_time: time::Instant::now(),
|
start_time: time::Instant::now(),
|
||||||
|
observer_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue