github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/src/server/cli.rs (about) 1 /* 2 * Copyright 2018 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * ------------------------------------------------------------------------------ 16 */ 17 18 use clap::{App, Arg, ArgMatches}; 19 use cpython::{PyDict, PyResult, Python}; 20 21 const DISTRIBUTION_NAME: &str = "sawtooth-validator"; 22 const VERSION: &str = env!("CARGO_PKG_VERSION"); 23 24 pub fn wrap_in_pydict(py: Python, matches: &ArgMatches) -> PyResult<PyDict> { 25 let (bind_component, bind_network, bind_consensus) = parse_bindings(matches); 26 27 let pydict = PyDict::new(py); 28 29 pydict.set_item(py, "bind_component", bind_component)?; 30 pydict.set_item(py, "bind_network", bind_network)?; 31 pydict.set_item(py, "bind_consensus", bind_consensus)?; 32 pydict.set_item(py, "config_dir", matches.value_of("config_dir"))?; 33 pydict.set_item(py, "endpoint", matches.value_of("endpoint"))?; 34 pydict.set_item( 35 py, 36 "maximum_peer_connectivity", 37 matches 38 .value_of("maximum_peer_connectivity") 39 .and_then(|s| s.parse::<u32>().ok()), 40 )?; 41 pydict.set_item( 42 py, 43 "minimum_peer_connectivity", 44 matches 45 .value_of("minimum-peer-connectivity") 46 .and_then(|s| s.parse::<u32>().ok()), 47 )?; 48 pydict.set_item(py, "opentsdb_db", matches.value_of("opentsdb-db"))?; 49 pydict.set_item(py, "opentsdb_url", matches.value_of("opentsdb-url"))?; 50 pydict.set_item(py, "peering", matches.value_of("peering"))?; 51 pydict.set_item(py, "peers", parse_comma_separated_args("peers", matches))?; 52 pydict.set_item(py, "roles", parse_roles(matches, py))?; 53 pydict.set_item(py, "scheduler", matches.value_of("scheduler"))?; 54 pydict.set_item(py, "seeds", parse_comma_separated_args("seeds", matches))?; 55 pydict.set_item(py, "verbose", matches.occurrences_of("verbose"))?; 56 pydict.set_item( 57 py, 58 "state_pruning_block_depth", 59 matches 60 .value_of("state_pruning_block_depth") 61 .and_then(|s| s.parse::<u32>().ok()), 62 )?; 63 64 Ok(pydict) 65 } 66 67 pub fn parse_args<'a>() -> ArgMatches<'a> { 68 let app = App::new(DISTRIBUTION_NAME) 69 .version(VERSION) 70 .about("Configures and starts a Sawtooth validator.") 71 .arg( 72 Arg::with_name("config_dir") 73 .long("config-dir") 74 .takes_value(true) 75 .help("specify the configuration directory"), 76 ) 77 .arg( 78 Arg::with_name("bind") 79 .short("B") 80 .long("bind") 81 .takes_value(true) 82 .multiple(true) 83 .help( 84 "set the URL for the network or validator \ 85 component service endpoints with the format \ 86 network:<endpoint>, component:<endpoint>, or \ 87 consensus:<endpoint>. Use multiple --bind options \ 88 to specify all endpoints.", 89 ), 90 ) 91 .arg( 92 Arg::with_name("peering") 93 .short("P") 94 .long("peering") 95 .takes_value(true) 96 .possible_values(&["static", "dynamic"]) 97 .help( 98 "determine peering type for the validator: \ 99 'static' (must use --peers to list peers) or \ 100 'dynamic' (processes any static peers first, \ 101 then starts topology buildout).", 102 ), 103 ) 104 .arg( 105 Arg::with_name("endpoint") 106 .short("E") 107 .long("endpoint") 108 .takes_value(true) 109 .help("specifies the advertised network endpoint URL"), 110 ) 111 .arg( 112 Arg::with_name("seeds") 113 .short("s") 114 .long("seeds") 115 .takes_value(true) 116 .multiple(true) 117 .help( 118 "provide URI(s) for the initial connection to \ 119 the validator network, in the format \ 120 tcp://<hostname>:<port>. Specify multiple URIs \ 121 in a comma-separated list. Repeating the --seeds \ 122 option is also accepted.", 123 ), 124 ) 125 .arg( 126 Arg::with_name("peers") 127 .short("p") 128 .long("peers") 129 .takes_value(true) 130 .multiple(true) 131 .help( 132 "list static peers to attempt to connect to \ 133 in the format tcp://<hostname>:<port>. Specify \ 134 multiple peers in a comma-separated list. \ 135 Repeating the --peers option is also accepted.", 136 ), 137 ) 138 .arg( 139 Arg::with_name("verbose") 140 .short("v") 141 .long("verbose") 142 .multiple(true) 143 .help("enable more verbose output to stderr"), 144 ) 145 .arg( 146 Arg::with_name("scheduler") 147 .long("scheduler") 148 .takes_value(true) 149 .possible_values(&["serial", "parallel"]) 150 .help("set scheduler type: serial or parallel"), 151 ) 152 .arg( 153 Arg::with_name("network_auth") 154 .long("network-auth") 155 .takes_value(true) 156 .possible_values(&["trust", "challenge"]) 157 .help( 158 "identify type of authorization required to join validator \ 159 network.", 160 ), 161 ) 162 .arg( 163 Arg::with_name("opentsdb-url") 164 .long("opentsdb-url") 165 .takes_value(true) 166 .help( 167 "specify host and port for Open TSDB database used for \ 168 metrics", 169 ), 170 ) 171 .arg( 172 Arg::with_name("opentsdb-db") 173 .long("opentsdb-db") 174 .takes_value(true) 175 .help("specify name of database used for storing metrics"), 176 ) 177 .arg( 178 Arg::with_name("minimum_peer_connectivity") 179 .long("minimum-peer-connectivity") 180 .takes_value(true) 181 .validator(is_positive_integer) 182 .help( 183 "set the minimum number of peers required before stopping \ 184 peer search", 185 ), 186 ) 187 .arg( 188 Arg::with_name("maximum_peer_connectivity") 189 .long("maximum-peer-connectivity") 190 .takes_value(true) 191 .validator(is_positive_integer) 192 .help("set the maximum number of peers to accept"), 193 ) 194 .arg( 195 Arg::with_name("state_pruning_block_depth") 196 .long("state-pruning-block-depth") 197 .takes_value(true) 198 .validator(is_positive_integer) 199 .help( 200 "set the block depth below which state roots are \ 201 pruned from the global state database.", 202 ), 203 ); 204 205 app.get_matches() 206 } 207 208 fn is_positive_integer(arg_value: String) -> Result<(), String> { 209 match arg_value.parse::<u32>() { 210 Ok(i) if i > 0 => Ok(()), 211 _ => Err("The value must be a positive number, greater than 0".into()), 212 } 213 } 214 215 fn parse_roles<'a>(matches: &'a ArgMatches, py: Python) -> Option<PyDict> { 216 match matches.value_of("network_auth") { 217 Some(network_auth) => { 218 let auth_dict = PyDict::new(py); 219 auth_dict.set_item(py, "network", network_auth).unwrap(); 220 Some(auth_dict) 221 } 222 None => None, 223 } 224 } 225 226 fn parse_bindings<'a>( 227 matches: &'a ArgMatches, 228 ) -> (Option<&'a str>, Option<&'a str>, Option<&'a str>) { 229 let mut bind_network = None; 230 let mut bind_component = None; 231 let mut bind_consensus = None; 232 233 if let Some(bindings) = parse_multiple_args("bind", matches) { 234 for binding in bindings { 235 if binding.starts_with("network") { 236 bind_network = Some(binding.splitn(2, ':').skip(1).collect::<Vec<_>>()[0]); 237 } 238 239 if binding.starts_with("component") { 240 bind_component = Some(binding.splitn(2, ':').skip(1).collect::<Vec<_>>()[0]); 241 } 242 243 if binding.starts_with("consensus") { 244 bind_consensus = Some(binding.splitn(2, ':').skip(1).collect::<Vec<_>>()[0]); 245 } 246 } 247 }; 248 249 (bind_component, bind_network, bind_consensus) 250 } 251 252 fn parse_comma_separated_args(name: &str, matches: &ArgMatches) -> Option<Vec<String>> { 253 parse_multiple_args(name, matches).map(|arglist| { 254 arglist 255 .join(",") 256 .split(',') 257 .map(String::from) 258 .collect::<Vec<String>>() 259 }) 260 } 261 262 fn parse_multiple_args<'a>(name: &str, matches: &'a ArgMatches) -> Option<Vec<&'a str>> { 263 matches.values_of(name).map(|vals| vals.collect()) 264 }