@@ -17,6 +17,12 @@ use crate::config::persistence::pathfinder::MixNodePathfinder;
17
17
use clap:: { App , Arg , ArgMatches } ;
18
18
use config:: NymConfig ;
19
19
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 ;
20
26
21
27
pub fn command_args < ' a , ' b > ( ) -> clap:: App < ' a , ' b > {
22
28
App :: new ( "init" )
@@ -38,8 +44,7 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> {
38
44
Arg :: with_name ( "layer" )
39
45
. long ( "layer" )
40
46
. help ( "The mixnet layer of this particular node" )
41
- . takes_value ( true )
42
- . required ( true ) ,
47
+ . takes_value ( true ) ,
43
48
)
44
49
. arg (
45
50
Arg :: with_name ( "host" )
@@ -82,35 +87,78 @@ fn show_incentives_url() {
82
87
println ! ( "\n \n " ) ;
83
88
}
84
89
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
+ }
91
102
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 ( ) ;
93
111
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 ( ) ) ;
104
113
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
+ }
106
126
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
+ }
112
129
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( ) ) ;
114
144
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
+ } )
116
164
}
0 commit comments