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  }