chore: types wrapper (#104)

* chore: types wrapper
This commit is contained in:
Al Liu 2023-03-24 19:50:30 +08:00 committed by GitHub
parent ea589d018a
commit 4a90ba6926
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 214 additions and 67 deletions

View File

@ -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"] }

View File

@ -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();

View File

@ -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()
}
}

View File

@ -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;

View File

@ -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)
}
}

View File

@ -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()

View File

@ -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()]
);
}
}

View File

@ -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),