LCOV - code coverage report
Current view: top level - irohad/main - irohad.cpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 0 114 0.0 %
Date: 2019-03-07 14:46:43 Functions: 0 33 0.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Soramitsu Co., Ltd. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0
       4             :  */
       5             : 
       6             : #include <csignal>
       7             : #include <fstream>
       8             : #include <thread>
       9             : 
      10             : #include <gflags/gflags.h>
      11             : #include <grpc++/grpc++.h>
      12             : #include "ametsuchi/storage.hpp"
      13             : #include "common/result.hpp"
      14             : #include "crypto/keys_manager_impl.hpp"
      15             : #include "logger/logger.hpp"
      16             : #include "logger/logger_manager.hpp"
      17             : #include "main/application.hpp"
      18             : #include "main/iroha_conf_literals.hpp"
      19             : #include "main/iroha_conf_loader.hpp"
      20             : #include "main/raw_block_loader.hpp"
      21             : 
      22             : static const std::string kListenIp = "0.0.0.0";
      23             : static const std::string kLogSettingsFromConfigFile = "config_file";
      24             : static const uint32_t kMstExpirationTimeDefault = 1440;
      25           0 : static const uint32_t kMaxRoundsDelayDefault = 3000;
      26             : static const uint32_t kStaleStreamMaxRoundsDefault = 2;
      27             : 
      28             : /**
      29             :  * Gflag validator.
      30             :  * Validator for the configuration file path input argument.
      31             :  * Path is considered to be valid if it is not empty.
      32             :  * @param flag_name - flag name. Must be 'config' in this case
      33             :  * @param path      - file name. Should be path to the config file
      34             :  * @return true if argument is valid
      35             :  */
      36             : bool validate_config(const char *flag_name, std::string const &path) {
      37           0 :   return not path.empty();
      38             : }
      39             : 
      40             : /**
      41             :  * Gflag validator.
      42             :  * Validator for the keypair files path input argument.
      43             :  * Path is considered to be valid if it is not empty.
      44             :  * @param flag_name - flag name. Must be 'keypair_name' in this case
      45             :  * @param path      - file name. Should be path to the keypair files
      46             :  * @return true if argument is valid
      47             :  */
      48             : bool validate_keypair_name(const char *flag_name, std::string const &path) {
      49           0 :   return not path.empty();
      50             : }
      51             : 
      52             : /**
      53             :  * Creating input argument for the configuration file location.
      54             :  */
      55             : DEFINE_string(config, "", "Specify iroha provisioning path.");
      56             : /**
      57             :  * Registering validator for the configuration file location.
      58             :  */
      59             : DEFINE_validator(config, &validate_config);
      60             : 
      61             : /**
      62             :  * Creating input argument for the genesis block file location.
      63             :  */
      64             : DEFINE_string(genesis_block, "", "Specify file with initial block");
      65             : 
      66             : /**
      67             :  * Creating input argument for the keypair files location.
      68             :  */
      69             : DEFINE_string(keypair_name, "", "Specify name of .pub and .priv files");
      70             : /**
      71             :  * Registering validator for the keypair files location.
      72             :  */
      73             : DEFINE_validator(keypair_name, &validate_keypair_name);
      74             : 
      75             : /**
      76             :  * Creating boolean flag for overwriting already existing block storage
      77             :  */
      78             : DEFINE_bool(overwrite_ledger, false, "Overwrite ledger data if existing");
      79             : 
      80             : static bool validateVerbosity(const char *flagname, const std::string &val) {
      81           0 :   if (val == kLogSettingsFromConfigFile) {
      82           0 :     return true;
      83             :   }
      84           0 :   const auto it = config_members::LogLevels.find(val);
      85           0 :   if (it == config_members::LogLevels.end()) {
      86           0 :     std::cerr << "Invalid value for " << flagname << ": should be one of '"
      87           0 :               << kLogSettingsFromConfigFile;
      88           0 :     for (const auto &level : config_members::LogLevels) {
      89           0 :       std::cerr << "', '" << level.first;
      90             :     }
      91           0 :     std::cerr << "'." << std::endl;
      92           0 :     return false;
      93             :   }
      94           0 :   return true;
      95           0 : }
      96             : 
      97             : /// Verbosity flag for spdlog configuration
      98             : DEFINE_string(verbosity, kLogSettingsFromConfigFile, "Log verbosity");
      99             : DEFINE_validator(verbosity, &validateVerbosity);
     100             : 
     101             : std::promise<void> exit_requested;
     102             : 
     103             : logger::LoggerManagerTreePtr getDefaultLogManager() {
     104           0 :   return std::make_shared<logger::LoggerManagerTree>(logger::LoggerConfig{
     105           0 :       logger::LogLevel::kInfo, logger::getDefaultLogPatterns()});
     106           0 : }
     107             : 
     108             : int main(int argc, char *argv[]) {
     109             :   // Parsing command line arguments
     110           0 :   gflags::ParseCommandLineFlags(&argc, &argv, true);
     111             : 
     112           0 :   logger::LoggerManagerTreePtr log_manager;
     113           0 :   logger::LoggerPtr log;
     114             : 
     115             :   // If the global log level override was set in the command line arguments,
     116             :   // create a logger manager with the given log level for all subsystems:
     117           0 :   if (FLAGS_verbosity != kLogSettingsFromConfigFile) {
     118           0 :     logger::LoggerConfig cfg;
     119           0 :     cfg.log_level = config_members::LogLevels.at(FLAGS_verbosity);
     120           0 :     log_manager = std::make_shared<logger::LoggerManagerTree>(std::move(cfg));
     121           0 :     log = log_manager->getChild("Init")->getLogger();
     122           0 :   }
     123             : 
     124             :   // Check if validators are registered.
     125           0 :   if (not config_validator_registered
     126           0 :       or not keypair_name_validator_registered) {
     127             :     // Abort execution if not
     128           0 :     if (log) {
     129           0 :       log->error("Flag validator is not registered");
     130           0 :     }
     131           0 :     return EXIT_FAILURE;
     132             :   }
     133             : 
     134             :   // Reading iroha configuration file
     135           0 :   const auto config = parse_iroha_config(FLAGS_config);
     136           0 :   if (not log_manager) {
     137           0 :     log_manager = config.logger_manager.value_or(getDefaultLogManager());
     138           0 :     log = log_manager->getChild("Init")->getLogger();
     139           0 :   }
     140           0 :   log->info("config initialized");
     141             : 
     142             :   // Reading public and private key files
     143           0 :   iroha::KeysManagerImpl keysManager(
     144           0 :       FLAGS_keypair_name, log_manager->getChild("KeysManager")->getLogger());
     145           0 :   auto keypair = keysManager.loadKeys();
     146             :   // Check if both keys are read properly
     147           0 :   if (not keypair) {
     148             :     // Abort execution if not
     149           0 :     log->error("Failed to load keypair");
     150           0 :     return EXIT_FAILURE;
     151             :   }
     152             : 
     153             :   // Configuring iroha daemon
     154           0 :   Irohad irohad(
     155           0 :       config.block_store_path,
     156           0 :       config.pg_opt,
     157             :       kListenIp,  // TODO(mboldyrev) 17/10/2018: add a parameter in
     158             :                   // config file and/or command-line arguments?
     159           0 :       config.torii_port,
     160           0 :       config.internal_port,
     161           0 :       config.max_proposal_size,
     162           0 :       std::chrono::milliseconds(config.proposal_delay),
     163           0 :       std::chrono::milliseconds(config.vote_delay),
     164           0 :       std::chrono::minutes(
     165           0 :           config.mst_expiration_time.value_or(kMstExpirationTimeDefault)),
     166           0 :       *keypair,
     167           0 :       std::chrono::milliseconds(
     168           0 :           config.max_round_delay_ms.value_or(kMaxRoundsDelayDefault)),
     169           0 :       config.stale_stream_max_rounds.value_or(kStaleStreamMaxRoundsDefault),
     170           0 :       log_manager->getChild("Irohad"),
     171           0 :       boost::make_optional(config.mst_support,
     172           0 :                            iroha::GossipPropagationStrategyParams{}));
     173             : 
     174             :   // Check if iroha daemon storage was successfully initialized
     175           0 :   if (not irohad.storage) {
     176             :     // Abort execution if not
     177           0 :     log->error("Failed to initialize storage");
     178           0 :     return EXIT_FAILURE;
     179             :   }
     180             : 
     181             :   /*
     182             :    * The logic implemented below is reflected in the following truth table.
     183             :    *
     184             :   +------------+--------------+------------------+---------------+---------+
     185             :   | Blockstore | New genesis  | Overwrite ledger | Genesis block | Message |
     186             :   | presence   | block is set | flag is set      | that is used  |         |
     187             :   +------------+--------------+------------------+---------------+---------+
     188             :   | 0          | 1            | 0                | new           |         |
     189             :   | 0          | 1            | 1                | new           | warning |
     190             :   | 1          | 1            | 0                | old           | warning |
     191             :   | 1          | 1            | 1                | new           |         |
     192             :   | 0          | 0            | 0                | none          | error   |
     193             :   | 0          | 0            | 1                | none          | error   |
     194             :   | 1          | 0            | 0                | old           |         |
     195             :   | 1          | 0            | 1                | old           | warning |
     196             :   +------------+--------------+------------------+---------------+---------+
     197             :    */
     198             : 
     199             :   /// if there are any blocks in blockstore, then true
     200           0 :   bool blockstore = irohad.storage->getBlockQuery()->getTopBlockHeight() != 0;
     201             : 
     202             :   /// genesis block file is specified as launch parameter
     203           0 :   bool genesis = not FLAGS_genesis_block.empty();
     204             : 
     205             :   /// overwrite ledger flag was set as launch parameter
     206           0 :   bool overwrite = FLAGS_overwrite_ledger;
     207             : 
     208           0 :   if (genesis) {  // genesis block file is specified
     209           0 :     if (blockstore and not overwrite) {
     210           0 :       log->warn(
     211           0 :           "Passed genesis block will be ignored without --overwrite_ledger "
     212             :           "flag. Restoring existing state.");
     213           0 :     } else {
     214           0 :       iroha::main::BlockLoader loader(
     215           0 :           log_manager->getChild("GenesisBlockLoader")->getLogger());
     216           0 :       auto file = loader.loadFile(FLAGS_genesis_block);
     217           0 :       auto block = loader.parseBlock(file.value());
     218             : 
     219           0 :       if (not block) {
     220           0 :         log->error("Failed to parse genesis block.");
     221           0 :         return EXIT_FAILURE;
     222             :       }
     223             : 
     224           0 :       if (not blockstore and overwrite) {
     225           0 :         log->warn(
     226           0 :             "Blockstore is empty - there is nothing to overwrite. Inserting "
     227             :             "new genesis block.");
     228           0 :       }
     229             : 
     230             :       // clear previous storage if any
     231           0 :       irohad.dropStorage();
     232             : 
     233           0 :       irohad.storage->insertBlock(*block.value());
     234           0 :       log->info("Genesis block inserted, number of transactions: {}",
     235           0 :                 block.value()->transactions().size());
     236           0 :     }
     237           0 :   } else {  // genesis block file is not specified
     238           0 :     if (not blockstore) {
     239           0 :       log->error(
     240           0 :           "Cannot restore nor create new state. Blockstore is empty. No "
     241             :           "genesis block is provided. Please pecify new genesis block using "
     242             :           "--genesis_block parameter.");
     243           0 :       return EXIT_FAILURE;
     244             :     } else {
     245           0 :       if (overwrite) {
     246           0 :         log->warn(
     247           0 :             "No new genesis block is specified - blockstore cannot be "
     248             :             "overwritten. If you want overwrite ledger state, please "
     249             :             "specify new genesis block using --genesis_block parameter.");
     250           0 :       }
     251             :     }
     252             :   }
     253             : 
     254             :   // check if at least one block is available in the ledger
     255           0 :   auto blocks_exist = irohad.storage->getBlockQuery()->getTopBlock().match(
     256             :       [](const auto &) { return true; },
     257             :       [](iroha::expected::Error<std::string> &) { return false; });
     258             : 
     259           0 :   if (not blocks_exist) {
     260           0 :     log->error(
     261           0 :         "Unable to start the ledger. There are no blocks in the ledger. Please "
     262             :         "ensure that you are not trying to start the newer version of "
     263             :         "the ledger over incompatible version of the storage or there is "
     264             :         "enough disk space. Try to specify --genesis_block and "
     265             :         "--overwrite_ledger parameters at the same time.");
     266           0 :     return EXIT_FAILURE;
     267             :   }
     268             : 
     269             :   // init pipeline components
     270           0 :   irohad.init();
     271             : 
     272             :   auto handler = [](int s) { exit_requested.set_value(); };
     273           0 :   std::signal(SIGINT, handler);
     274           0 :   std::signal(SIGTERM, handler);
     275             : #ifdef SIGQUIT
     276           0 :   std::signal(SIGQUIT, handler);
     277             : #endif
     278             : 
     279             :   // runs iroha
     280           0 :   log->info("Running iroha");
     281           0 :   irohad.run();
     282           0 :   exit_requested.get_future().wait();
     283             : 
     284             :   // We do not care about shutting down grpc servers
     285             :   // They do all necessary work in their destructors
     286           0 :   log->info("shutting down...");
     287             : 
     288           0 :   gflags::ShutDownCommandLineFlags();
     289             : 
     290           0 :   return 0;
     291           0 : }

Generated by: LCOV version 1.13