LCOV - code coverage report
Current view: top level - irohad/consensus/yac/storage/impl - yac_proposal_storage.cpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 71 72 98.6 %
Date: 2019-03-07 14:46:43 Functions: 16 16 100.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 "consensus/yac/storage/yac_proposal_storage.hpp"
       7             : 
       8             : #include <boost/range/adaptor/transformed.hpp>
       9             : #include "logger/logger.hpp"
      10             : #include "logger/logger_manager.hpp"
      11             : 
      12             : using namespace logger;
      13             : 
      14             : namespace iroha {
      15             :   namespace consensus {
      16             :     namespace yac {
      17             : 
      18             :       // --------| private api |--------
      19             : 
      20             :       auto YacProposalStorage::findStore(const YacHash &store_hash) {
      21             :         // find exist
      22        3625 :         auto iter = std::find_if(block_storages_.begin(),
      23        3625 :                                  block_storages_.end(),
      24             :                                  [&store_hash](auto block_storage) {
      25             :                                    auto storage_key =
      26         481 :                                        block_storage.getStorageKey();
      27         481 :                                    return storage_key == store_hash;
      28         481 :                                  });
      29        3625 :         if (iter != block_storages_.end()) {
      30         473 :           return iter;
      31             :         }
      32             :         // insert and return new
      33        3152 :         return block_storages_.emplace(
      34        3152 :             block_storages_.end(),
      35        3152 :             YacHash(store_hash.vote_round,
      36        3152 :                     store_hash.vote_hashes.proposal_hash,
      37        3152 :                     store_hash.vote_hashes.block_hash),
      38        3152 :             peers_in_round_,
      39        3152 :             supermajority_checker_,
      40        3152 :             log_manager_->getChild("BlockStorage")->getLogger());
      41        3625 :       }
      42             : 
      43             :       // --------| public api |--------
      44             : 
      45             :       YacProposalStorage::YacProposalStorage(
      46             :           Round store_round,
      47             :           PeersNumberType peers_in_round,
      48             :           std::shared_ptr<SupermajorityChecker> supermajority_checker,
      49             :           logger::LoggerManagerTreePtr log_manager)
      50        3148 :           : current_state_(boost::none),
      51        3148 :             storage_key_(store_round),
      52        3148 :             peers_in_round_(peers_in_round),
      53        3148 :             supermajority_checker_(supermajority_checker),
      54        3148 :             log_manager_(std::move(log_manager)),
      55        3148 :             log_(log_manager_->getLogger()) {}
      56             : 
      57             :       boost::optional<Answer> YacProposalStorage::insert(VoteMessage msg) {
      58        7213 :         if (shouldInsert(msg)) {
      59             :           // insert to block store
      60             : 
      61        3625 :           log_->info("Vote with {} and hashes [{}, {}] looks valid",
      62        3625 :                      msg.hash.vote_round,
      63        3625 :                      msg.hash.vote_hashes.proposal_hash,
      64        3625 :                      msg.hash.vote_hashes.block_hash);
      65             : 
      66        3625 :           auto iter = findStore(msg.hash);
      67        3625 :           auto block_state = iter->insert(msg);
      68             : 
      69             :           // Single BlockStorage always returns CommitMessage because it
      70             :           // aggregates votes for a single hash.
      71        3625 :           if (block_state) {
      72             :             // supermajority on block achieved
      73        3150 :             current_state_ = std::move(block_state);
      74        3150 :           } else {
      75             :             // try to find reject case
      76         475 :             auto reject_state = findRejectProof();
      77         475 :             if (reject_state) {
      78           6 :               log_->info("Found reject proof");
      79           6 :               current_state_ = std::move(reject_state);
      80           6 :             }
      81         475 :           }
      82        3625 :         }
      83        7213 :         return getState();
      84           0 :       }
      85             : 
      86             :       boost::optional<Answer> YacProposalStorage::insert(
      87             :           std::vector<VoteMessage> messages) {
      88             :         std::for_each(messages.begin(), messages.end(), [this](auto vote) {
      89        7192 :           this->insert(std::move(vote));
      90        7192 :         });
      91        6735 :         return getState();
      92             :       }
      93             : 
      94             :       const Round &YacProposalStorage::getStorageKey() const {
      95       19835 :         return storage_key_;
      96             :       }
      97             : 
      98             :       boost::optional<Answer> YacProposalStorage::getState() const {
      99       13949 :         return current_state_;
     100             :       }
     101             : 
     102             :       // --------| private api |--------
     103             : 
     104             :       bool YacProposalStorage::shouldInsert(const VoteMessage &msg) {
     105        7213 :         return checkProposalRound(msg.hash.vote_round)
     106        7213 :             and checkPeerUniqueness(msg);
     107             :       }
     108             : 
     109             :       bool YacProposalStorage::checkProposalRound(const Round &vote_round) {
     110        7213 :         return vote_round == storage_key_;
     111             :       }
     112             : 
     113             :       bool YacProposalStorage::checkPeerUniqueness(const VoteMessage &msg) {
     114        7212 :         return std::all_of(block_storages_.begin(),
     115        7212 :                            block_storages_.end(),
     116             :                            [&msg](YacBlockStorage &storage) {
     117        4071 :                              if (storage.getStorageKey() != msg.hash) {
     118          11 :                                return true;
     119             :                              }
     120        4060 :                              return not storage.isContains(msg);
     121        4071 :                            });
     122             :       }
     123             : 
     124             :       boost::optional<Answer> YacProposalStorage::findRejectProof() {
     125         475 :         auto is_reject = not supermajority_checker_->canHaveSupermajority(
     126         475 :             block_storages_
     127             :                 | boost::adaptors::transformed([](const auto &storage) {
     128         950 :                     return storage.getNumberOfVotes();
     129             :                   }),
     130         475 :             peers_in_round_);
     131             : 
     132         475 :         if (is_reject) {
     133           6 :           std::vector<VoteMessage> result;
     134           6 :           std::for_each(block_storages_.begin(),
     135           6 :                         block_storages_.end(),
     136             :                         [&result](auto &storage) {
     137          12 :                           auto votes_from_block_storage = storage.getVotes();
     138          12 :                           std::move(votes_from_block_storage.begin(),
     139          12 :                                     votes_from_block_storage.end(),
     140          12 :                                     std::back_inserter(result));
     141          12 :                         });
     142             : 
     143           6 :           return Answer(RejectMessage(std::move(result)));
     144           6 :         }
     145             : 
     146         469 :         return boost::none;
     147         475 :       }
     148             : 
     149             :     }  // namespace yac
     150             :   }    // namespace consensus
     151             : }  // namespace iroha

Generated by: LCOV version 1.13