github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/perf/sawtooth_workload/src/main.rs (about)

     1  /*
     2   * Copyright 2017 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  extern crate clap;
    18  extern crate protobuf;
    19  extern crate sawtooth_perf;
    20  extern crate sawtooth_sdk;
    21  
    22  use std::error::Error;
    23  use std::fs::File;
    24  use std::io::Read;
    25  
    26  use batch_gen::generate_signed_batches;
    27  use batch_submit::submit_signed_batches;
    28  use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
    29  
    30  use sawtooth_perf::batch_gen;
    31  use sawtooth_perf::batch_submit;
    32  
    33  use sawtooth_sdk::signing;
    34  use sawtooth_sdk::signing::secp256k1::Secp256k1PrivateKey;
    35  
    36  const APP_NAME: &str = env!("CARGO_PKG_NAME");
    37  const VERSION: &str = env!("CARGO_PKG_VERSION");
    38  
    39  fn main() {
    40      let arg_matches = App::new(APP_NAME)
    41          .version(VERSION)
    42          .setting(AppSettings::SubcommandRequiredElseHelp)
    43          .subcommand(create_batch_subcommand_args())
    44          .subcommand(create_submit_subcommand_args())
    45          .get_matches();
    46  
    47      let result = match arg_matches.subcommand() {
    48          ("batch", Some(args)) => run_batch_command(args),
    49          ("submit", Some(args)) => run_submit_command(args),
    50          _ => panic!("Should have processed a subcommand or exited before here"),
    51      };
    52  
    53      std::process::exit(match result {
    54          Ok(_) => 0,
    55          Err(err) => {
    56              eprintln!("Error: {}", err);
    57              1
    58          }
    59      });
    60  }
    61  
    62  #[inline]
    63  fn arg_error(msg: &str) -> Result<(), Box<Error>> {
    64      Err(Box::new(CliError::ArgumentError(String::from(msg))))
    65  }
    66  
    67  fn create_batch_subcommand_args<'a, 'b>() -> App<'a, 'b> {
    68      SubCommand::with_name("batch")
    69          .about(
    70              "Generates signed batches from transaction input.\n \
    71               The transaction input is expected to be length-delimited protobuf \
    72               Transaction messages, which should also be pre-signed for \
    73               submission to the validator.",
    74          )
    75          .arg(
    76              Arg::with_name("input")
    77                  .short("i")
    78                  .long("input")
    79                  .value_name("FILE")
    80                  .required(true)
    81                  .help("The source of input transactions"),
    82          )
    83          .arg(
    84              Arg::with_name("output")
    85                  .short("o")
    86                  .long("output")
    87                  .value_name("FILE")
    88                  .required(true)
    89                  .help("The target for the signed batches"),
    90          )
    91          .arg(
    92              Arg::with_name("key")
    93                  .short("k")
    94                  .long("key")
    95                  .value_name("FILE")
    96                  .required(true)
    97                  .help("The signing key for the transactions"),
    98          )
    99          .arg(
   100              Arg::with_name("max-batch-size")
   101                  .short("n")
   102                  .long("max-batch-size")
   103                  .value_name("NUMBER")
   104                  .help(
   105                      "The maximum number of transactions to include in a batch; \
   106                       Defaults to 100.",
   107                  ),
   108          )
   109  }
   110  
   111  fn run_batch_command(args: &ArgMatches) -> Result<(), Box<Error>> {
   112      let max_txns: usize = match args.value_of("max-batch-size").unwrap_or("100").parse() {
   113          Ok(n) => n,
   114          Err(_) => 0,
   115      };
   116  
   117      if max_txns == 0 {
   118          return arg_error("max-batch-size must be a number greater than 0");
   119      }
   120  
   121      let mut in_file = File::open(args.value_of("input").unwrap())?;
   122      let mut out_file = File::create(args.value_of("output").unwrap())?;
   123  
   124      let mut key_file = try!(File::open(args.value_of("key").unwrap()));
   125  
   126      let mut buf = String::new();
   127      try!(key_file.read_to_string(&mut buf));
   128      buf.pop(); // remove the new line
   129  
   130      let private_key = try!(Secp256k1PrivateKey::from_hex(&buf));
   131      let context = try!(signing::create_context("secp256k1"));
   132  
   133      if let Err(err) = generate_signed_batches(
   134          &mut in_file,
   135          &mut out_file,
   136          max_txns,
   137          context.as_ref(),
   138          &private_key,
   139      ) {
   140          return Err(Box::new(err));
   141      }
   142  
   143      Ok(())
   144  }
   145  
   146  fn create_submit_subcommand_args<'a, 'b>() -> App<'a, 'b> {
   147      SubCommand::with_name("submit")
   148          .about(
   149              "Submits signed batches to one or more targets from batch input.\n \
   150               The batch input is expected to be length-delimited protobuf \
   151               Batch messages, which should also be pre-signed for \
   152               submission to the validator.",
   153          )
   154          .arg(
   155              Arg::with_name("input")
   156                  .short("i")
   157                  .long("input")
   158                  .value_name("FILE")
   159                  .help("The source of batch transactions"),
   160          )
   161          .arg(
   162              Arg::with_name("target")
   163                  .short("t")
   164                  .long("target")
   165                  .value_name("TARGET")
   166                  .help("A Sawtooth REST API endpoint"),
   167          )
   168          .arg(
   169              Arg::with_name("rate")
   170                  .short("r")
   171                  .long("rate")
   172                  .value_name("RATE")
   173                  .help("The number of batches per second to submit to the target"),
   174          )
   175  }
   176  
   177  fn run_submit_command(args: &ArgMatches) -> Result<(), Box<Error>> {
   178      let rate: usize = match args.value_of("rate").unwrap_or("1").parse() {
   179          Ok(n) => n,
   180          Err(_) => 0,
   181      };
   182  
   183      if rate == 0 {
   184          return arg_error("rate must be a number greater than 0");
   185      }
   186  
   187      let target: String = match args.value_of("target")
   188          .unwrap_or("http://localhost:8008")
   189          .parse()
   190      {
   191          Ok(s) => s,
   192          Err(_) => String::new(),
   193      };
   194  
   195      if target == "" {
   196          return arg_error("target must be a valid http uri");
   197      }
   198  
   199      let input: String = match args.value_of("input").unwrap_or("").parse() {
   200          Ok(s) => s,
   201          Err(_) => String::new(),
   202      };
   203  
   204      if input == "" {
   205          return arg_error("an input file must be specified");
   206      }
   207  
   208      let mut in_file = File::open(args.value_of("input").unwrap())?;
   209  
   210      println!("Input: {} Target: {} Rate: {}", input, target, rate);
   211  
   212      if let Err(err) = submit_signed_batches(&mut in_file, target, rate) {
   213          return Err(Box::new(err));
   214      }
   215  
   216      Ok(())
   217  }
   218  
   219  #[derive(Debug)]
   220  enum CliError {
   221      ArgumentError(String),
   222  }
   223  
   224  impl std::fmt::Display for CliError {
   225      fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
   226          match *self {
   227              CliError::ArgumentError(ref msg) => write!(f, "ArgumentError: {}", msg),
   228          }
   229      }
   230  }
   231  
   232  impl std::error::Error for CliError {
   233      fn description(&self) -> &str {
   234          match *self {
   235              CliError::ArgumentError(ref msg) => msg,
   236          }
   237      }
   238  
   239      fn cause(&self) -> Option<&Error> {
   240          match *self {
   241              CliError::ArgumentError(_) => None,
   242          }
   243      }
   244  }