Skip to content

Commit

Permalink
Rust simulation 2024-10-08
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit 70cfea62e8bc80eba7d0072e4ecad5f01fc3a2e1
Author: Simon Gellis <[email protected]>
Date:   Tue Oct 8 17:47:39 2024 -0400

    Use a Clock to make time easier to work with

commit bebf58bf0358698fd2277af50a5b9ee490cff261
Author: Simon Gellis <[email protected]>
Date:   Tue Oct 8 16:59:04 2024 -0400

    Model coordinates geographically

commit 1d577133b39cf9b920ee454984d0775c5f53c0a0
Author: Simon Gellis <[email protected]>
Date:   Tue Oct 8 14:47:49 2024 -0400

    Update data (and variable names) to reflect stake pools

commit cba2a17cc8304d852c45a103e2da49bd5361029a
Author: Simon Gellis <[email protected]>
Date:   Tue Oct 8 14:40:54 2024 -0400

    Use simplified chainsync/blockfetch to improve sim accuracy
  • Loading branch information
SupernaviX committed Oct 8, 2024
1 parent 4616dc1 commit bbce7d5
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 175 deletions.
41 changes: 16 additions & 25 deletions sim-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion sim-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ anyhow = "1"
clap = { version = "4", features = ["derive"] }
ctrlc = "3"
futures = "0.3"
netsim-async = { git = "https://github.com/input-output-hk/ce-netsim.git" }
netsim-async = { git = "https://github.com/SupernaviX/ce-netsim.git", rev = "8569a6f" }
rand = "0.8"
rand_chacha = "0.3"
rand_distr = "0.4"
Expand Down
46 changes: 46 additions & 0 deletions sim-rs/src/clock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::{
ops::Add,
time::{Duration, Instant},
};

use serde::Serialize;
use tokio::time::{self, Sleep};

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Timestamp(Duration);
impl Add<Duration> for Timestamp {
type Output = Timestamp;

fn add(self, rhs: Duration) -> Self::Output {
Timestamp(self.0 + rhs)
}
}

impl Serialize for Timestamp {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u128(self.0.as_nanos())
}
}

#[derive(Clone)]
pub struct Clock {
start: Instant,
}

impl Clock {
pub fn new(start: Instant) -> Self {
Self { start }
}

pub fn now(&self) -> Timestamp {
Timestamp(self.start.elapsed())
}

pub fn wait_until(&self, timestamp: Timestamp) -> Sleep {
let instant = self.start + timestamp.0;
time::sleep_until(instant.into())
}
}
64 changes: 40 additions & 24 deletions sim-rs/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
use std::{fmt::Display, fs, path::Path, time::Duration};

use anyhow::Result;
use netsim_async::geo::{self, Location};
use serde::{Deserialize, Serialize};

use crate::probability::FloatDistribution;

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct PoolId(usize);
impl Display for PoolId {
pub struct NodeId(usize);
impl Display for NodeId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl PoolId {
impl NodeId {
pub fn to_inner(self) -> usize {
self.0
}
Expand Down Expand Up @@ -45,7 +46,7 @@ impl From<DistributionConfig> for FloatDistribution {
#[derive(Debug, Deserialize)]
struct RawConfig {
seed: Option<u64>,
pools: Vec<RawPoolConfig>,
nodes: Vec<RawNodeConfig>,
links: Vec<RawLinkConfig>,
block_generation_probability: f64,
max_block_size: u64,
Expand All @@ -55,20 +56,21 @@ struct RawConfig {
}

#[derive(Debug, Deserialize)]
struct RawPoolConfig {
stake: u64,
struct RawNodeConfig {
location: (f64, f64),
stake: Option<u64>,
}

#[derive(Debug, Deserialize)]
struct RawLinkConfig {
pools: [usize; 2],
latency_ms: u64,
nodes: (usize, usize),
latency_ms: Option<u64>,
}

#[derive(Debug, Clone)]
pub struct SimConfiguration {
pub seed: u64,
pub pools: Vec<PoolConfiguration>,
pub nodes: Vec<NodeConfiguration>,
pub links: Vec<LinkConfiguration>,
pub block_generation_probability: f64,
pub max_block_size: u64,
Expand All @@ -78,43 +80,45 @@ pub struct SimConfiguration {
}

#[derive(Debug, Clone)]
pub struct PoolConfiguration {
pub id: PoolId,
pub struct NodeConfiguration {
pub id: NodeId,
pub location: Location,
pub stake: u64,
pub peers: Vec<PoolId>,
pub peers: Vec<NodeId>,
}

#[derive(Debug, Clone)]
pub struct LinkConfiguration {
pub pools: [PoolId; 2],
pub nodes: (NodeId, NodeId),
pub latency: Duration,
}

impl From<RawConfig> for SimConfiguration {
fn from(value: RawConfig) -> Self {
let mut pools: Vec<PoolConfiguration> = value
.pools
let mut nodes: Vec<NodeConfiguration> = value
.nodes
.into_iter()
.enumerate()
.map(|(index, raw)| PoolConfiguration {
id: PoolId(index),
stake: raw.stake,
.map(|(index, raw)| NodeConfiguration {
id: NodeId(index),
location: to_netsim_location(raw.location),
stake: raw.stake.unwrap_or_default(),
peers: vec![],
})
.collect();
let mut links = vec![];
for link in value.links {
let [id1, id2] = link.pools;
pools[id1].peers.push(PoolId(id2));
pools[id2].peers.push(PoolId(id1));
let (id1, id2) = link.nodes;
nodes[id1].peers.push(NodeId(id2));
nodes[id2].peers.push(NodeId(id1));
links.push(LinkConfiguration {
pools: [PoolId(id1), PoolId(id2)],
latency: Duration::from_millis(link.latency_ms),
nodes: (NodeId(id1), NodeId(id2)),
latency: compute_latency(nodes[id1].location, nodes[id2].location, link.latency_ms),
});
}
Self {
seed: value.seed.unwrap_or_default(),
pools,
nodes,
links,
block_generation_probability: value.block_generation_probability,
max_block_size: value.max_block_size,
Expand All @@ -125,6 +129,18 @@ impl From<RawConfig> for SimConfiguration {
}
}

fn to_netsim_location((lat, long): (f64, f64)) -> Location {
((lat * 10000.) as i64, (long * 10000.) as u64)
}

fn compute_latency(loc1: Location, loc2: Location, extra_ms: Option<u64>) -> Duration {
let geo_latency = geo::latency_between_locations(loc1, loc2, 1.)
.map(|l| l.to_duration())
.unwrap_or(Duration::ZERO);
let extra_latency = Duration::from_millis(extra_ms.unwrap_or(5));
geo_latency + extra_latency
}

pub fn read_config(filename: &Path) -> Result<SimConfiguration> {
let file = fs::read_to_string(filename)?;
let raw_config: RawConfig = toml::from_str(&file)?;
Expand Down
Loading

0 comments on commit bbce7d5

Please sign in to comment.