Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2bb980a

Browse files
authoredSep 28, 2020
Defaulting to mix layer with fewest node if no argument provided (#353)
* Defaulting to mix layer with fewest node if no argument provided * cargo fmt
1 parent a5b094e commit 2bb980a

File tree

3 files changed

+90
-29
lines changed

3 files changed

+90
-29
lines changed
 

‎mixnode/src/commands/init.rs

+75-27
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ use crate::config::persistence::pathfinder::MixNodePathfinder;
1717
use clap::{App, Arg, ArgMatches};
1818
use config::NymConfig;
1919
use crypto::asymmetric::encryption;
20+
use directory_client::DirectoryClient;
21+
use log::*;
22+
use nymsphinx::params::DEFAULT_NUM_MIX_HOPS;
23+
use std::convert::TryInto;
24+
use tokio::runtime::Runtime;
25+
use topology::NymTopology;
2026

2127
pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
2228
App::new("init")
@@ -38,8 +44,7 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
3844
Arg::with_name("layer")
3945
.long("layer")
4046
.help("The mixnet layer of this particular node")
41-
.takes_value(true)
42-
.required(true),
47+
.takes_value(true),
4348
)
4449
.arg(
4550
Arg::with_name("host")
@@ -82,35 +87,78 @@ fn show_incentives_url() {
8287
println!("\n\n");
8388
}
8489

85-
pub fn execute(matches: &ArgMatches) {
86-
let id = matches.value_of("id").unwrap();
87-
println!("Initialising mixnode {}...", id);
88-
89-
let layer = matches.value_of("layer").unwrap().parse().unwrap();
90-
let mut config = crate::config::Config::new(id, layer);
90+
async fn choose_layer(matches: &ArgMatches<'_>, directory_server: String) -> u64 {
91+
let max_layer = DEFAULT_NUM_MIX_HOPS;
92+
if let Some(layer) = matches.value_of("layer").map(|layer| layer.parse::<u64>()) {
93+
if let Err(err) = layer {
94+
// if layer was overridden, it must be parsable
95+
panic!("Invalid layer value provided - {:?}", err);
96+
}
97+
let layer = layer.unwrap();
98+
if layer <= max_layer as u64 && layer > 0 {
99+
return layer;
100+
}
101+
}
91102

92-
config = override_config(config, matches);
103+
let directory_client_config = directory_client::Config::new(directory_server);
104+
let directory_client = directory_client::Client::new(directory_client_config);
105+
let topology: NymTopology = directory_client
106+
.get_topology()
107+
.await
108+
.expect("failed to obtain initial network topology!")
109+
.try_into()
110+
.unwrap();
93111

94-
let sphinx_keys = encryption::KeyPair::new();
95-
let pathfinder = MixNodePathfinder::new_from_config(&config);
96-
pemstore::store_keypair(
97-
&sphinx_keys,
98-
&pemstore::KeyPairPath::new(
99-
pathfinder.private_encryption_key().to_owned(),
100-
pathfinder.public_encryption_key().to_owned(),
101-
),
102-
)
103-
.expect("Failed to save sphinx keys");
112+
let mut lowest_layer = (0, usize::max_value());
104113

105-
println!("Saved mixnet sphinx keypair");
114+
for layer in 1..=max_layer {
115+
let nodes_count = topology
116+
.mixes()
117+
.get(&layer)
118+
.map(|layer_mixes| layer_mixes.len())
119+
.unwrap_or_else(|| 0);
120+
trace!("There are {} nodes on layer {}", nodes_count, layer);
121+
if nodes_count < lowest_layer.1 {
122+
lowest_layer.0 = layer;
123+
lowest_layer.1 = nodes_count;
124+
}
125+
}
106126

107-
let config_save_location = config.get_config_file_save_location();
108-
config
109-
.save_to_file(None)
110-
.expect("Failed to save the config file");
111-
println!("Saved configuration file to {:?}", config_save_location);
127+
lowest_layer.0 as u64
128+
}
112129

113-
println!("Mixnode configuration completed.\n\n\n");
130+
pub fn execute(matches: &ArgMatches) {
131+
// TODO: this should probably be made implicit by slapping `#[tokio::main]` on our main method
132+
// and then removing runtime from mixnode itself in `run`
133+
let mut rt = Runtime::new().unwrap();
134+
rt.block_on(async {
135+
let id = matches.value_of("id").unwrap();
136+
println!("Initialising mixnode {}...", id);
137+
let mut config = crate::config::Config::new(id);
138+
config = override_config(config, matches);
139+
let layer = choose_layer(matches, config.get_presence_directory_server()).await;
140+
// TODO: I really don't like how we override config and are presumably done with it
141+
// only to change it here
142+
config = config.with_layer(layer);
143+
debug!("Choosing layer {}", config.get_layer());
114144

115-
show_incentives_url();
145+
let sphinx_keys = encryption::KeyPair::new();
146+
let pathfinder = MixNodePathfinder::new_from_config(&config);
147+
pemstore::store_keypair(
148+
&sphinx_keys,
149+
&pemstore::KeyPairPath::new(
150+
pathfinder.private_encryption_key().to_owned(),
151+
pathfinder.public_encryption_key().to_owned(),
152+
),
153+
)
154+
.expect("Failed to save sphinx keys");
155+
println!("Saved mixnet sphinx keypair");
156+
let config_save_location = config.get_config_file_save_location();
157+
config
158+
.save_to_file(None)
159+
.expect("Failed to save the config file");
160+
println!("Saved configuration file to {:?}", config_save_location);
161+
println!("Mixnode configuration completed.\n\n\n");
162+
show_incentives_url();
163+
})
116164
}

‎mixnode/src/commands/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,30 @@
1414

1515
use crate::config::Config;
1616
use clap::ArgMatches;
17+
use nymsphinx::params::DEFAULT_NUM_MIX_HOPS;
1718

1819
pub mod init;
1920
pub mod run;
2021

2122
pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Config {
23+
let max_layer = DEFAULT_NUM_MIX_HOPS;
2224
let mut was_host_overridden = false;
2325
if let Some(host) = matches.value_of("host") {
2426
config = config.with_listening_host(host);
2527
was_host_overridden = true;
2628
}
2729

30+
if let Some(layer) = matches.value_of("layer").map(|layer| layer.parse::<u64>()) {
31+
if let Err(err) = layer {
32+
// if layer was overridden, it must be parsable
33+
panic!("Invalid layer value provided - {:?}", err);
34+
}
35+
let layer = layer.unwrap();
36+
if layer <= max_layer as u64 && layer > 0 {
37+
config = config.with_layer(layer)
38+
}
39+
}
40+
2841
if let Some(port) = matches.value_of("port").map(|port| port.parse::<u16>()) {
2942
if let Err(err) = port {
3043
// if port was overridden, it must be parsable

‎mixnode/src/config/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ impl NymConfig for Config {
8484
}
8585

8686
impl Config {
87-
pub fn new<S: Into<String>>(id: S, layer: u64) -> Self {
88-
Config::default().with_id(id).with_layer(layer)
87+
pub fn new<S: Into<String>>(id: S) -> Self {
88+
Config::default().with_id(id)
8989
}
9090

9191
// builder methods

0 commit comments

Comments
 (0)
Please sign in to comment.