Skip to content

Commit

Permalink
refactor: replace [u8;32] seed with u64
Browse files Browse the repository at this point in the history
Additionally:
- removes util functions to generate & encode
seed to hex
  • Loading branch information
enigbe committed May 20, 2024
1 parent b24174e commit b1f5833
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 63 deletions.
23 changes: 3 additions & 20 deletions sim-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,6 @@ fn deserialize_f64_greater_than_zero(x: String) -> Result<f64, String> {
}
}

/// Deserializes a hexadecimal seed string into a byte array
fn deserialize_fix_seed(hex: String) -> Result<[u8; 32], String> {
if hex.len() != 64 {
return Err("Seed hex must be 64-characters long.".to_string());
}

hex::decode(hex)
.map(|byte_vec| {
let mut seed = [0; 32];
let seed_from_hex = byte_vec.as_slice();
seed.clone_from_slice(seed_from_hex);
seed
})
.map_err(|e| e.to_string())
}

#[derive(Parser)]
#[command(version, about)]
struct Cli {
Expand Down Expand Up @@ -90,10 +74,9 @@ struct Cli {
/// Do not create an output file containing the simulations results
#[clap(long, default_value_t = false)]
no_results: bool,
/// Seed to run random activity generator "deterministically", i.e. in the same order.
/// Expected values are hexadecimal-encoded [u8;32] seeds, e.g. hex::encode([42;32])
#[clap(long, short, value_parser = clap::builder::StringValueParser::new().try_map(deserialize_fix_seed))]
fix_seed: Option<[u8; 32]>,
/// Seed to run random activity generator deterministically.
#[clap(long, short, value_parser = clap::builder::RangedU64ValueParser::<u64>::new().range(0..u64::MAX))]
fix_seed: Option<u64>,
}

#[tokio::main]
Expand Down
10 changes: 5 additions & 5 deletions sim-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ pub struct Simulation {
activity_multiplier: f64,
/// Configurations for printing results to CSV. Results are not written if this option is None.
write_results: Option<WriteResults>,
/// Seed to deterministically run the random activity generator
seed: Option<[u8; 32]>,
/// Seed to deterministically run the random activity generator.
seed: Option<u64>,
}

#[derive(Clone)]
Expand Down Expand Up @@ -439,7 +439,7 @@ impl Simulation {
expected_payment_msat: u64,
activity_multiplier: f64,
write_results: Option<WriteResults>,
seed: Option<[u8; 32]>,
seed: Option<u64>,
) -> Self {
let (shutdown_trigger, shutdown_listener) = triggered::trigger();
Self {
Expand Down Expand Up @@ -726,7 +726,7 @@ impl Simulation {

async fn activity_executors(
&self,
seed: Option<[u8; 32]>,
seed: Option<u64>,
) -> Result<Vec<ExecutorKit>, SimulationError> {
let mut generators = Vec::new();

Expand Down Expand Up @@ -761,7 +761,7 @@ impl Simulation {
/// that have sufficient capacity to generate payments of our expected payment amount.
async fn random_activity_nodes(
&self,
seed: Option<[u8; 32]>,
seed: Option<u64>,
) -> Result<Vec<ExecutorKit>, SimulationError> {
// Collect capacity of each node from its view of its own channels. Total capacity is divided by two to
// avoid double counting capacity (as each node has a counterparty in the channel).
Expand Down
59 changes: 21 additions & 38 deletions sim-lib/src/random_activity.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::fmt;
use rand::{rngs::ThreadRng, CryptoRng, Rng, RngCore, SeedableRng};
use rand::{RngCore, SeedableRng};
use rand_chacha::ChaCha8Rng;
use std::fmt::Display;
use thiserror::Error;
Expand Down Expand Up @@ -29,7 +29,7 @@ pub enum RandomActivityError {
pub struct NetworkGraphView {
node_picker: WeightedIndex<u64>,
nodes: Vec<(NodeInfo, u64)>,
seed: Option<[u8; 32]>,
seed: Option<u64>,
}

impl NetworkGraphView {
Expand All @@ -38,7 +38,7 @@ impl NetworkGraphView {
/// send to itself).
pub fn new(
nodes: Vec<(NodeInfo, u64)>,
seed: Option<[u8; 32]>,
seed: Option<u64>,
) -> Result<Self, RandomActivityError> {
if nodes.len() < 2 {
return Err(RandomActivityError::ValueError(
Expand Down Expand Up @@ -112,7 +112,7 @@ pub struct RandomPaymentActivity {
expected_payment_amt: u64,
source_capacity: u64,
event_dist: Exp<f64>,
seed: Option<[u8; 32]>,
seed: Option<u64>,
}

impl RandomPaymentActivity {
Expand All @@ -123,7 +123,7 @@ impl RandomPaymentActivity {
source_capacity_msat: u64,
expected_payment_amt: u64,
multiplier: f64,
seed: Option<[u8; 32]>,
seed: Option<u64>,
) -> Result<Self, RandomActivityError> {
if source_capacity_msat == 0 {
return Err(RandomActivityError::ValueError(
Expand Down Expand Up @@ -208,10 +208,6 @@ fn events_per_month(source_capacity_msat: u64, multiplier: f64, expected_payment
(source_capacity_msat as f64 * multiplier) / expected_payment_amt as f64
}

trait SimRng: CryptoRng + RngCore {}
impl SimRng for ChaCha8Rng {}
impl SimRng for ThreadRng {}

impl PaymentGenerator for RandomPaymentActivity {
/// Returns the time that the payments should start. This will always be 0 for the RandomPaymentActivity type.
fn payment_start(&self) -> Duration {
Expand Down Expand Up @@ -287,21 +283,19 @@ impl Display for RandomPaymentActivity {
}

/// Random number generator that takes an optional seed with which deterministic
/// behaviour can be simulated
fn sim_rng(seed: Option<[u8; 32]>) -> impl SimRng {
/// behaviour can be simulated.
fn sim_rng(seed: Option<u64>) -> Box<dyn RngCore> {
match seed {
Some(seed) => rand_chacha::ChaCha8Rng::from_seed(seed),
Some(seed) => Box::new(ChaCha8Rng::seed_from_u64(seed)),
None => {
let mut thread_rng = rand::thread_rng();
ChaCha8Rng::seed_from_u64(thread_rng.gen::<u64>())
let thread_rng = rand::thread_rng();
Box::new(thread_rng)
},
}
}

#[cfg(test)]
mod tests {
use crate::test_utils::{generate_random_seed, seed_hex};

mod test_network_graph_view {
use ntest::timeout;

Expand All @@ -313,7 +307,7 @@ mod tests {
// Check that we need, at least, two nodes
for i in 0..2 {
assert!(matches!(
NetworkGraphView::new(create_nodes(i, 42 * (i as u64 + 1)), None),
NetworkGraphView::new(create_nodes(i, 42 * (i as u64 + 1)), Some(u64::MAX)),
Err(RandomActivityError::ValueError { .. })
));
}
Expand All @@ -323,18 +317,18 @@ mod tests {
let mut nodes = create_nodes(1, 0);
nodes.extend(create_nodes(1, 21));
assert!(matches!(
NetworkGraphView::new(nodes, None),
NetworkGraphView::new(nodes, Some(u64::MAX)),
Err(RandomActivityError::InsufficientCapacity { .. })
));

// All of them are 0
assert!(matches!(
NetworkGraphView::new(create_nodes(2, 0), None),
NetworkGraphView::new(create_nodes(2, 0), Some(u64::MAX)),
Err(RandomActivityError::InsufficientCapacity { .. })
));

// Otherwise we should be good
assert!(NetworkGraphView::new(create_nodes(2, 42), None).is_ok());
assert!(NetworkGraphView::new(create_nodes(2, 42), Some(u64::MAX)).is_ok());
}

#[test]
Expand Down Expand Up @@ -364,7 +358,7 @@ mod tests {
nodes.extend(create_nodes(big_node_count, big_node_capacity));
let big_node = nodes.last().unwrap().0.pubkey;

let view = NetworkGraphView::new(nodes, None).unwrap();
let view = NetworkGraphView::new(nodes, Some(u64::MAX)).unwrap();

for _ in 0..10 {
view.choose_destination(big_node);
Expand All @@ -386,15 +380,15 @@ mod tests {
2 * expected_payment,
expected_payment,
1.0,
Some([42; 32])
Some(u64::MAX)
)
.is_ok());
assert!(matches!(
RandomPaymentActivity::new(
2 * expected_payment,
expected_payment + 1,
1.0,
Some([42; 32])
Some(u64::MAX)
),
Err(RandomActivityError::InsufficientCapacity { .. })
));
Expand All @@ -406,7 +400,7 @@ mod tests {
0,
get_random_int(1, 10),
get_random_int(1, 10) as f64,
Some([42; 32])
Some(u64::MAX)
),
Err(RandomActivityError::ValueError { .. })
));
Expand All @@ -415,7 +409,7 @@ mod tests {
get_random_int(1, 10),
0,
get_random_int(1, 10) as f64,
Some([42; 32])
Some(u64::MAX)
),
Err(RandomActivityError::ValueError { .. })
));
Expand All @@ -424,7 +418,7 @@ mod tests {
get_random_int(1, 10),
get_random_int(1, 10),
0.0,
Some([42; 32])
Some(u64::MAX)
),
Err(RandomActivityError::ValueError { .. })
));
Expand Down Expand Up @@ -459,7 +453,7 @@ mod tests {
let expected_payment = get_random_int(1, 100);
let source_capacity = 2 * expected_payment;
let pag =
RandomPaymentActivity::new(source_capacity, expected_payment, 1.0, Some([42; 32]))
RandomPaymentActivity::new(source_capacity, expected_payment, 1.0, Some(u64::MAX))
.unwrap();

// Wrong cases
Expand All @@ -486,15 +480,4 @@ mod tests {
));
}
}

#[test]
fn random_seed_generation() {
let seed = generate_random_seed();
let seed_hex = seed_hex(seed);
let hex_decode = hex::decode(seed_hex).expect("Hex decoding failed");

for (i, e) in hex_decode.into_iter().enumerate() {
assert_eq!(e, seed[i]);
}
}
}

0 comments on commit b1f5833

Please sign in to comment.