LCOV - code coverage report
Current view: top level - irohad/consensus/yac/storage/impl - yac_proposal_storage.cpp (source / functions) Hit Total Coverage
Test: coverage_cleared.info Lines: 77 78 98.7 %
Date: 2018-12-05 17:11:35 Functions: 21 21 100.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Soramitsu Co., Ltd. 2017 All Rights Reserved.
       3             :  * http://soramitsu.co.jp
       4             :  *
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at
       8             :  *
       9             :  *        http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include "consensus/yac/storage/yac_proposal_storage.hpp"
      19             : 
      20             : using namespace logger;
      21             : 
      22             : namespace iroha {
      23             :   namespace consensus {
      24             :     namespace yac {
      25             : 
      26             :       // --------| private api |--------
      27             : 
      28             :       auto YacProposalStorage::findStore(const YacHash &store_hash) {
      29             :         // find exist
      30         776 :         auto iter = std::find_if(block_storages_.begin(),
      31         776 :                                  block_storages_.end(),
      32             :                                  [&store_hash](auto block_storage) {
      33             :                                    auto storage_key =
      34          54 :                                        block_storage.getStorageKey();
      35          54 :                                    return storage_key == store_hash;
      36          54 :                                  });
      37         776 :         if (iter != block_storages_.end()) {
      38          47 :           return iter;
      39             :         }
      40             :         // insert and return new
      41         729 :         return block_storages_.emplace(
      42         729 :             block_storages_.end(),
      43         729 :             YacHash(store_hash.vote_round,
      44         729 :                     store_hash.vote_hashes.proposal_hash,
      45         729 :                     store_hash.vote_hashes.block_hash),
      46         729 :             peers_in_round_,
      47         729 :             supermajority_checker_);
      48         776 :       }
      49             : 
      50             :       // --------| public api |--------
      51             : 
      52             :       YacProposalStorage::YacProposalStorage(
      53             :           Round store_round,
      54             :           PeersNumberType peers_in_round,
      55             :           std::shared_ptr<SupermajorityChecker> supermajority_checker)
      56         729 :           : current_state_(boost::none),
      57         729 :             storage_key_(store_round),
      58         729 :             peers_in_round_(peers_in_round),
      59         729 :             supermajority_checker_(supermajority_checker) {
      60         729 :         log_ = log("ProposalStorage");
      61         729 :       }
      62             : 
      63             :       boost::optional<Answer> YacProposalStorage::insert(VoteMessage msg) {
      64        1516 :         if (shouldInsert(msg)) {
      65             :           // insert to block store
      66             : 
      67         776 :           log_->info("Vote with round [{}, {}] and hashes [{}, {}] looks valid",
      68         776 :                      msg.hash.vote_round.block_round,
      69         776 :                      msg.hash.vote_round.reject_round,
      70         776 :                      msg.hash.vote_hashes.proposal_hash,
      71         776 :                      msg.hash.vote_hashes.block_hash);
      72             : 
      73         776 :           auto iter = findStore(msg.hash);
      74         776 :           auto block_state = iter->insert(msg);
      75             : 
      76             :           // Single BlockStorage always returns CommitMessage because it
      77             :           // aggregates votes for a single hash.
      78         776 :           if (block_state) {
      79             :             // supermajority on block achieved
      80         728 :             current_state_ = std::move(block_state);
      81         728 :           } else {
      82             :             // try to find reject case
      83          48 :             auto reject_state = findRejectProof();
      84          48 :             if (reject_state) {
      85           4 :               log_->info("Found reject proof");
      86           4 :               current_state_ = std::move(reject_state);
      87           4 :             }
      88          48 :           }
      89         776 :         }
      90        1516 :         return getState();
      91           0 :       }
      92             : 
      93             :       boost::optional<Answer> YacProposalStorage::insert(
      94             :           std::vector<VoteMessage> messages) {
      95             :         std::for_each(messages.begin(), messages.end(), [this](auto vote) {
      96        1496 :           this->insert(std::move(vote));
      97        1496 :         });
      98        1465 :         return getState();
      99             :       }
     100             : 
     101             :       const Round &YacProposalStorage::getStorageKey() const {
     102             :         return storage_key_;
     103             :       }
     104             : 
     105             :       boost::optional<Answer> YacProposalStorage::getState() const {
     106        2982 :         return current_state_;
     107             :       }
     108             : 
     109             :       // --------| private api |--------
     110             : 
     111             :       bool YacProposalStorage::shouldInsert(const VoteMessage &msg) {
     112             :         return checkProposalRound(msg.hash.vote_round)
     113        1516 :             and checkPeerUniqueness(msg);
     114             :       }
     115             : 
     116             :       bool YacProposalStorage::checkProposalRound(const Round &vote_round) {
     117        1516 :         return vote_round == storage_key_;
     118             :       }
     119             : 
     120             :       bool YacProposalStorage::checkPeerUniqueness(const VoteMessage &msg) {
     121        1515 :         return std::all_of(block_storages_.begin(),
     122        1515 :                            block_storages_.end(),
     123             :                            [&msg](YacBlockStorage &storage) {
     124         796 :                              if (storage.getStorageKey() != msg.hash) {
     125          10 :                                return true;
     126             :                              }
     127         786 :                              return not storage.isContains(msg);
     128         796 :                            });
     129             :       }
     130             : 
     131             :       boost::optional<Answer> YacProposalStorage::findRejectProof() {
     132          48 :         auto max_vote = std::max_element(block_storages_.begin(),
     133          48 :                                          block_storages_.end(),
     134             :                                          [](auto &left, auto &right) {
     135           8 :                                            return left.getNumberOfVotes()
     136           8 :                                                < right.getNumberOfVotes();
     137             :                                          })
     138          48 :                             ->getNumberOfVotes();
     139             : 
     140          48 :         auto all_votes =
     141          48 :             std::accumulate(block_storages_.begin(),
     142          48 :                             block_storages_.end(),
     143             :                             0ull,
     144             :                             [](auto &acc, auto &storage) {
     145          56 :                               return acc + storage.getNumberOfVotes();
     146             :                             });
     147             : 
     148          48 :         auto is_reject = supermajority_checker_->hasReject(
     149          48 :             max_vote, all_votes, peers_in_round_);
     150             : 
     151          48 :         if (is_reject) {
     152           4 :           std::vector<VoteMessage> result;
     153           4 :           result.reserve(all_votes);
     154           4 :           std::for_each(block_storages_.begin(),
     155           4 :                         block_storages_.end(),
     156             :                         [&result](auto &storage) {
     157           8 :                           auto votes_from_block_storage = storage.getVotes();
     158           8 :                           std::move(votes_from_block_storage.begin(),
     159           8 :                                     votes_from_block_storage.end(),
     160           8 :                                     std::back_inserter(result));
     161           8 :                         });
     162             : 
     163           4 :           return Answer(RejectMessage(std::move(result)));
     164           4 :         }
     165             : 
     166          44 :         return boost::none;
     167          48 :       }
     168             : 
     169             :     }  // namespace yac
     170             :   }    // namespace consensus
     171             : }  // namespace iroha

Generated by: LCOV version 1.13