parent
ea589d018a
commit
4a90ba6926
@ -3,15 +3,12 @@ name = "simulations"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
|
||||
[dependencies]
|
||||
rand = { version = "0.8", features = ["small_rng"] }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_with = "2.3"
|
||||
serde_with = "2"
|
||||
serde_json = "1.0"
|
||||
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
|
@ -103,7 +103,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
>(std::fs::File::open(config)?)?;
|
||||
#[allow(clippy::unit_arg)]
|
||||
let overlay = FlatOverlay::new(cfg.overlay_settings);
|
||||
let node_ids = (0..cfg.node_count).collect::<Vec<_>>();
|
||||
let node_ids = (0..cfg.node_count).map(From::from).collect::<Vec<_>>();
|
||||
let mut rng = thread_rng();
|
||||
let layout = overlay.layout(&node_ids, &mut rng);
|
||||
let leaders = overlay.leaders(&node_ids, 1, &mut rng).collect();
|
||||
|
@ -30,6 +30,7 @@ fn leader_receive_proposal(
|
||||
.iter()
|
||||
.filter_map(|&sender| network.send_message_cost(rng, sender, node))
|
||||
.max()
|
||||
.map(From::from)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@ -46,6 +47,7 @@ fn receive_proposal(
|
||||
.filter_map(|&sender| network.send_message_cost(rng, sender, node))
|
||||
.max()
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
|
||||
fn receive_commit(
|
||||
@ -66,6 +68,7 @@ fn receive_commit(
|
||||
})
|
||||
.max()
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
@ -236,7 +239,7 @@ impl Node for CarnotNode {
|
||||
Self { id, rng, settings }
|
||||
}
|
||||
|
||||
fn id(&self) -> usize {
|
||||
fn id(&self) -> NodeId {
|
||||
self.id
|
||||
}
|
||||
|
||||
@ -256,7 +259,7 @@ impl Node for CarnotNode {
|
||||
Some(parent) => {
|
||||
solver(&mut self.rng, self.id, &parent, &self.settings.network)
|
||||
}
|
||||
None => Duration::ZERO,
|
||||
None => Duration::ZERO.into(),
|
||||
}
|
||||
}
|
||||
ChildCommitteeReceiverSolver(solver) => solver(
|
||||
@ -286,9 +289,9 @@ impl Node for CarnotNode {
|
||||
}
|
||||
};
|
||||
|
||||
overall_steps_time += step_time
|
||||
overall_steps_time += step_time.0
|
||||
}
|
||||
|
||||
overall_steps_time
|
||||
overall_steps_time.into()
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,120 @@
|
||||
pub mod carnot;
|
||||
|
||||
// std
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
time::Duration,
|
||||
};
|
||||
// crates
|
||||
use rand::Rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use self::carnot::CarnotStep;
|
||||
// internal
|
||||
|
||||
pub type NodeId = usize;
|
||||
pub type CommitteeId = usize;
|
||||
pub type StepTime = Duration;
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct NodeId(usize);
|
||||
|
||||
impl NodeId {
|
||||
#[inline]
|
||||
pub const fn new(id: usize) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn inner(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for NodeId {
|
||||
fn from(id: usize) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct CommitteeId(usize);
|
||||
|
||||
impl CommitteeId {
|
||||
#[inline]
|
||||
pub const fn new(id: usize) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for CommitteeId {
|
||||
fn from(id: usize) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_with::serde_as]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct StepTime(#[serde_as(as = "serde_with::DurationMilliSeconds")] Duration);
|
||||
|
||||
impl From<Duration> for StepTime {
|
||||
fn from(duration: Duration) -> Self {
|
||||
Self(duration)
|
||||
}
|
||||
}
|
||||
|
||||
impl StepTime {
|
||||
#[inline]
|
||||
pub const fn new(duration: Duration) -> Self {
|
||||
Self(duration)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn into_inner(&self) -> Duration {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn from_millis(millis: u64) -> Self {
|
||||
Self(Duration::from_millis(millis))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn from_secs(secs: u64) -> Self {
|
||||
Self(Duration::from_secs(secs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for StepTime {
|
||||
type Target = Duration;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for StepTime {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl core::iter::Sum<Self> for StepTime {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
Self(iter.into_iter().map(|s| s.0).sum())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::iter::Sum<Duration> for StepTime {
|
||||
fn sum<I: Iterator<Item = Duration>>(iter: I) -> Self {
|
||||
Self(iter.into_iter().sum())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::iter::Sum<StepTime> for Duration {
|
||||
fn sum<I: Iterator<Item = StepTime>>(iter: I) -> Self {
|
||||
iter.into_iter().map(|s| s.0).sum()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Node: Clone {
|
||||
type Settings;
|
||||
|
@ -18,7 +18,7 @@ impl Overlay<CarnotNode> for FlatOverlay {
|
||||
}
|
||||
|
||||
fn nodes(&self) -> Vec<NodeId> {
|
||||
(0..10).collect()
|
||||
(0..10).map(NodeId::from).collect()
|
||||
}
|
||||
|
||||
fn leaders<R: Rng>(
|
||||
@ -33,16 +33,16 @@ impl Overlay<CarnotNode> for FlatOverlay {
|
||||
|
||||
fn layout<R: Rng>(&self, nodes: &[NodeId], _rng: &mut R) -> Layout {
|
||||
let committees = std::iter::once((
|
||||
0,
|
||||
0.into(),
|
||||
Committee {
|
||||
nodes: nodes.iter().copied().collect(),
|
||||
role: CarnotRole::Leader,
|
||||
},
|
||||
))
|
||||
.collect();
|
||||
let parent = std::iter::once((0, 0)).collect();
|
||||
let children = std::iter::once((0, vec![0])).collect();
|
||||
let layers = std::iter::once((0, vec![0])).collect();
|
||||
let parent = std::iter::once((0.into(), 0.into())).collect();
|
||||
let children = std::iter::once((0.into(), vec![0.into()])).collect();
|
||||
let layers = std::iter::once((0.into(), vec![0.into()])).collect();
|
||||
Layout::new(committees, parent, children, layers)
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ pub struct Layout {
|
||||
pub from_committee: HashMap<NodeId, CommitteeId>,
|
||||
pub parent: HashMap<CommitteeId, CommitteeId>,
|
||||
pub children: HashMap<CommitteeId, Vec<CommitteeId>>,
|
||||
pub layers: HashMap<usize, Vec<CommitteeId>>,
|
||||
pub layers: HashMap<CommitteeId, Vec<CommitteeId>>,
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
@ -37,7 +37,7 @@ impl Layout {
|
||||
committees: HashMap<CommitteeId, Committee>,
|
||||
parent: HashMap<CommitteeId, CommitteeId>,
|
||||
children: HashMap<CommitteeId, Vec<CommitteeId>>,
|
||||
layers: HashMap<usize, Vec<usize>>,
|
||||
layers: HashMap<CommitteeId, Vec<CommitteeId>>,
|
||||
) -> Self {
|
||||
let from_committee = committees
|
||||
.iter()
|
||||
|
@ -6,7 +6,7 @@ use rand::seq::IteratorRandom;
|
||||
use super::{Committee, Layout, Overlay};
|
||||
use crate::node::{
|
||||
carnot::{CarnotNode, CarnotRole},
|
||||
NodeId,
|
||||
CommitteeId, NodeId,
|
||||
};
|
||||
|
||||
pub enum TreeType {
|
||||
@ -57,14 +57,17 @@ impl TreeOverlay {
|
||||
|
||||
// Check for leaf nodes.
|
||||
if right_child_id <= properties.committee_count {
|
||||
children.insert(committee_id, vec![left_child_id, right_child_id]);
|
||||
children.insert(
|
||||
committee_id.into(),
|
||||
vec![left_child_id.into(), right_child_id.into()],
|
||||
);
|
||||
has_children = true;
|
||||
}
|
||||
|
||||
// Root node has no parent.
|
||||
if committee_id > 0 {
|
||||
let parent_id = get_parent_id(committee_id);
|
||||
parents.insert(committee_id, parent_id);
|
||||
parents.insert(committee_id.into(), parent_id.into());
|
||||
}
|
||||
|
||||
let role = match (committee_id, has_children) {
|
||||
@ -78,12 +81,12 @@ impl TreeOverlay {
|
||||
role,
|
||||
};
|
||||
|
||||
committees.insert(committee_id, committee);
|
||||
committees.insert(committee_id.into(), committee);
|
||||
|
||||
layers
|
||||
.entry(get_layer(committee_id))
|
||||
.or_insert_with(Vec::new)
|
||||
.push(committee_id);
|
||||
.push(committee_id.into());
|
||||
}
|
||||
|
||||
Layout::new(committees, parents, children, layers)
|
||||
@ -99,7 +102,7 @@ impl Overlay<CarnotNode> for TreeOverlay {
|
||||
|
||||
fn nodes(&self) -> Vec<NodeId> {
|
||||
let properties = get_tree_properties(&self.settings);
|
||||
(0..properties.node_count).collect()
|
||||
(0..properties.node_count).map(From::from).collect()
|
||||
}
|
||||
|
||||
fn leaders<R: rand::Rng>(
|
||||
@ -139,8 +142,8 @@ fn get_parent_id(id: usize) -> usize {
|
||||
}
|
||||
|
||||
/// Get a layer in a tree of a given committee id.
|
||||
fn get_layer(id: usize) -> usize {
|
||||
(id as f64 + 1.).log2().floor() as usize
|
||||
fn get_layer(id: usize) -> CommitteeId {
|
||||
CommitteeId::new((id as f64 + 1.).log2().floor() as usize)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -173,24 +176,33 @@ mod tests {
|
||||
});
|
||||
let nodes = overlay.nodes();
|
||||
let layout = overlay.layout(&nodes, &mut rng);
|
||||
assert_eq!(layout.children[&0], vec![1, 2]);
|
||||
assert_eq!(layout.parent[&1], 0);
|
||||
assert_eq!(layout.parent[&2], 0);
|
||||
assert_eq!(
|
||||
layout.children[&CommitteeId::new(0)],
|
||||
vec![1.into(), 2.into()]
|
||||
);
|
||||
assert_eq!(layout.parent[&CommitteeId::new(1)], 0.into());
|
||||
assert_eq!(layout.parent[&CommitteeId::new(2)], 0.into());
|
||||
|
||||
assert_eq!(layout.children[&1], vec![3, 4]);
|
||||
assert_eq!(layout.children[&2], vec![5, 6]);
|
||||
assert_eq!(
|
||||
layout.children[&CommitteeId::new(1)],
|
||||
vec![3.into(), 4.into()]
|
||||
);
|
||||
assert_eq!(
|
||||
layout.children[&CommitteeId::new(2)],
|
||||
vec![5.into(), 6.into()]
|
||||
);
|
||||
|
||||
assert_eq!(layout.parent[&3], 1);
|
||||
assert_eq!(layout.children.get(&3), None);
|
||||
assert_eq!(layout.parent[&CommitteeId::new(3)], 1.into());
|
||||
assert_eq!(layout.children.get(&CommitteeId::new(3)), None);
|
||||
|
||||
assert_eq!(layout.parent[&4], 1);
|
||||
assert_eq!(layout.children.get(&4), None);
|
||||
assert_eq!(layout.parent[&CommitteeId::new(4)], 1.into());
|
||||
assert_eq!(layout.children.get(&CommitteeId::new(4)), None);
|
||||
|
||||
assert_eq!(layout.parent[&5], 2);
|
||||
assert_eq!(layout.children.get(&5), None);
|
||||
assert_eq!(layout.parent[&CommitteeId::new(5)], 2.into());
|
||||
assert_eq!(layout.children.get(&CommitteeId::new(5)), None);
|
||||
|
||||
assert_eq!(layout.parent[&6], 2);
|
||||
assert_eq!(layout.children.get(&6), None);
|
||||
assert_eq!(layout.parent[&CommitteeId::new(6)], 2.into());
|
||||
assert_eq!(layout.children.get(&CommitteeId::new(6)), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -207,15 +219,15 @@ mod tests {
|
||||
// 2^h - 1
|
||||
assert_eq!(layout.committees.len(), 1023);
|
||||
|
||||
let root_nodes = &layout.committees[&0].nodes;
|
||||
let root_nodes = &layout.committees[&CommitteeId::new(0)].nodes;
|
||||
assert_eq!(root_nodes.len(), 10);
|
||||
assert_eq!(root_nodes.first(), Some(&0));
|
||||
assert_eq!(root_nodes.last(), Some(&9));
|
||||
assert_eq!(root_nodes.first(), Some(&NodeId::new(0)));
|
||||
assert_eq!(root_nodes.last(), Some(&NodeId::new(9)));
|
||||
|
||||
let last_nodes = &layout.committees[&1022].nodes;
|
||||
let last_nodes = &layout.committees[&CommitteeId::new(1022)].nodes;
|
||||
assert_eq!(last_nodes.len(), 10);
|
||||
assert_eq!(last_nodes.first(), Some(&10220));
|
||||
assert_eq!(last_nodes.last(), Some(&10229));
|
||||
assert_eq!(last_nodes.first(), Some(&NodeId::new(10220)));
|
||||
assert_eq!(last_nodes.last(), Some(&NodeId::new(10229)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -229,11 +241,26 @@ mod tests {
|
||||
let nodes = overlay.nodes();
|
||||
let layout = overlay.layout(&nodes, &mut rng);
|
||||
|
||||
assert_eq!(layout.committees[&0].role, CarnotRole::Root);
|
||||
assert_eq!(layout.committees[&1].role, CarnotRole::Intermediate);
|
||||
assert_eq!(layout.committees[&2].role, CarnotRole::Intermediate);
|
||||
assert_eq!(layout.committees[&3].role, CarnotRole::Leaf);
|
||||
assert_eq!(layout.committees[&6].role, CarnotRole::Leaf);
|
||||
assert_eq!(
|
||||
layout.committees[&CommitteeId::new(0)].role,
|
||||
CarnotRole::Root
|
||||
);
|
||||
assert_eq!(
|
||||
layout.committees[&CommitteeId::new(1)].role,
|
||||
CarnotRole::Intermediate
|
||||
);
|
||||
assert_eq!(
|
||||
layout.committees[&CommitteeId::new(2)].role,
|
||||
CarnotRole::Intermediate
|
||||
);
|
||||
assert_eq!(
|
||||
layout.committees[&CommitteeId::new(3)].role,
|
||||
CarnotRole::Leaf
|
||||
);
|
||||
assert_eq!(
|
||||
layout.committees[&CommitteeId::new(6)].role,
|
||||
CarnotRole::Leaf
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -246,8 +273,14 @@ mod tests {
|
||||
});
|
||||
let nodes = overlay.nodes();
|
||||
let layout = overlay.layout(&nodes, &mut rng);
|
||||
assert_eq!(layout.layers[&0], vec![0]);
|
||||
assert_eq!(layout.layers[&1], vec![1, 2]);
|
||||
assert_eq!(layout.layers[&2], vec![3, 4, 5, 6]);
|
||||
assert_eq!(layout.layers[&CommitteeId::new(0)], vec![0.into()]);
|
||||
assert_eq!(
|
||||
layout.layers[&CommitteeId::new(1)],
|
||||
vec![1.into(), 2.into()]
|
||||
);
|
||||
assert_eq!(
|
||||
layout.layers[&CommitteeId::new(2)],
|
||||
vec![3.into(), 4.into(), 5.into(), 6.into()]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::node::carnot::{
|
||||
CarnotRole, CARNOT_INTERMEDIATE_STEPS, CARNOT_LEADER_STEPS, CARNOT_LEAF_STEPS,
|
||||
CARNOT_ROOT_STEPS, CARNOT_UNKNOWN_MESSAGE_RECEIVED_STEPS,
|
||||
};
|
||||
use crate::node::{Node, NodeId, StepTime};
|
||||
use crate::node::{CommitteeId, Node, NodeId, StepTime};
|
||||
use crate::overlay::Layout;
|
||||
use rand::Rng;
|
||||
use std::collections::HashMap;
|
||||
@ -93,14 +93,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn get_layer_nodes(layer_committees: &[NodeId], layout: &Layout) -> Vec<(NodeId, NodeId)> {
|
||||
fn get_layer_nodes(
|
||||
layer_committees: &[CommitteeId],
|
||||
layout: &Layout,
|
||||
) -> Vec<(CommitteeId, NodeId)> {
|
||||
layer_committees
|
||||
.iter()
|
||||
.flat_map(|committee_id| get_committee_nodes(committee_id, layout))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_committee_nodes(committee: &NodeId, layout: &Layout) -> Vec<(NodeId, NodeId)> {
|
||||
fn get_committee_nodes(committee: &CommitteeId, layout: &Layout) -> Vec<(CommitteeId, NodeId)> {
|
||||
layout.committees[committee]
|
||||
.nodes
|
||||
.clone()
|
||||
@ -145,7 +148,6 @@ mod test {
|
||||
NetworkBehaviour::new(Duration::from_millis(100), 0.0),
|
||||
))
|
||||
.collect();
|
||||
|
||||
let node_settings: CarnotNodeSettings = CarnotNodeSettings {
|
||||
steps_costs: CARNOT_STEPS_COSTS.iter().cloned().collect(),
|
||||
network: Network::new(RegionsData::new(regions, network_behaviour)),
|
||||
@ -344,11 +346,15 @@ mod test {
|
||||
steps_costs: CARNOT_STEPS_COSTS.iter().cloned().collect(),
|
||||
network: Network::new(RegionsData::new(regions, network_behaviour)),
|
||||
layout: overlay.layout(&node_ids, &mut rng),
|
||||
leaders: leaders.clone(),
|
||||
leaders: leaders.clone().into_iter().map(From::from).collect(),
|
||||
};
|
||||
|
||||
let mut runner =
|
||||
ConsensusRunner::<CarnotNode>::new(&mut rng, layout, leaders, Rc::new(node_settings));
|
||||
let mut runner = ConsensusRunner::<CarnotNode>::new(
|
||||
&mut rng,
|
||||
layout,
|
||||
leaders.into_iter().map(From::from).collect(),
|
||||
Rc::new(node_settings),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Duration::from_millis(7800),
|
||||
@ -402,11 +408,15 @@ mod test {
|
||||
steps_costs: CARNOT_STEPS_COSTS.iter().cloned().collect(),
|
||||
network: Network::new(RegionsData::new(regions, network_behaviour)),
|
||||
layout: overlay.layout(&node_ids, &mut rng),
|
||||
leaders: leaders.clone(),
|
||||
leaders: leaders.clone().into_iter().map(From::from).collect(),
|
||||
};
|
||||
|
||||
let mut runner =
|
||||
ConsensusRunner::<CarnotNode>::new(&mut rng, layout, leaders, Rc::new(node_settings));
|
||||
let mut runner = ConsensusRunner::<CarnotNode>::new(
|
||||
&mut rng,
|
||||
layout,
|
||||
leaders.into_iter().map(From::from).collect(),
|
||||
Rc::new(node_settings),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Duration::from_millis(7800),
|
||||
|
Loading…
x
Reference in New Issue
Block a user