LCOV - code coverage report
Current view: top level - irohad/multi_sig_transactions/state/impl - mst_state.cpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 79 83 95.2 %
Date: 2019-03-07 14:46:43 Functions: 25 26 96.2 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Soramitsu Co., Ltd. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0
       4             :  */
       5             : 
       6             : #include "multi_sig_transactions/state/mst_state.hpp"
       7             : 
       8             : #include <utility>
       9             : 
      10             : #include <boost/range/algorithm/find.hpp>
      11             : #include <boost/range/combine.hpp>
      12             : #include "common/set.hpp"
      13             : #include "interfaces/iroha_internal/transaction_batch.hpp"
      14             : #include "interfaces/transaction.hpp"
      15             : #include "logger/logger.hpp"
      16             : 
      17             : namespace iroha {
      18             : 
      19             :   bool BatchHashEquality::operator()(const DataType &left_tx,
      20             :                                      const DataType &right_tx) const {
      21         135 :     return left_tx->reducedHash() == right_tx->reducedHash();
      22             :   }
      23             : 
      24             :   DefaultCompleter::DefaultCompleter(std::chrono::minutes expiration_time)
      25         278 :       : expiration_time_(expiration_time) {}
      26             : 
      27             :   bool DefaultCompleter::operator()(const DataType &batch) const {
      28           9 :     return std::all_of(batch->transactions().begin(),
      29           9 :                        batch->transactions().end(),
      30             :                        [](const auto &tx) {
      31          12 :                          return boost::size(tx->signatures()) >= tx->quorum();
      32           0 :                        });
      33             :   }
      34             : 
      35             :   bool DefaultCompleter::operator()(const DataType &batch,
      36             :                                     const TimeType &time) const {
      37          16 :     return std::any_of(batch->transactions().begin(),
      38          16 :                        batch->transactions().end(),
      39             :                        [&](const auto &tx) {
      40          18 :                          return tx->createdTime()
      41          18 :                              + expiration_time_ / std::chrono::milliseconds(1)
      42          18 :                              < time;
      43             :                        });
      44             :   }
      45             : 
      46             :   // ------------------------------| public api |-------------------------------
      47             : 
      48             :   MstState MstState::empty(logger::LoggerPtr log,
      49             :                            const CompleterType &completer) {
      50         615 :     return MstState(completer, std::move(log));
      51           0 :   }
      52             : 
      53             :   StateUpdateResult MstState::operator+=(const DataType &rhs) {
      54         112 :     auto state_update = StateUpdateResult{
      55         112 :         std::make_shared<MstState>(MstState::empty(log_, completer_)),
      56         112 :         std::make_shared<MstState>(MstState::empty(log_, completer_))};
      57         112 :     insertOne(state_update, rhs);
      58         112 :     return state_update;
      59         112 :   }
      60             : 
      61             :   StateUpdateResult MstState::operator+=(const MstState &rhs) {
      62          11 :     auto state_update = StateUpdateResult{
      63          11 :         std::make_shared<MstState>(MstState::empty(log_, completer_)),
      64          11 :         std::make_shared<MstState>(MstState::empty(log_, completer_))};
      65          29 :     for (auto &&rhs_tx : rhs.internal_state_) {
      66          18 :       insertOne(state_update, rhs_tx);
      67             :     }
      68          11 :     return state_update;
      69          11 :   }
      70             : 
      71             :   MstState MstState::operator-(const MstState &rhs) const {
      72          27 :     return MstState(this->completer_,
      73          27 :                     set_difference(this->internal_state_, rhs.internal_state_),
      74          27 :                     log_);
      75           0 :   }
      76             : 
      77             :   bool MstState::operator==(const MstState &rhs) const {
      78           1 :     return std::all_of(
      79             :         internal_state_.begin(), internal_state_.end(), [&rhs](auto &i) {
      80           3 :           return rhs.internal_state_.find(i) != rhs.internal_state_.end();
      81             :         });
      82             :   }
      83             : 
      84             :   bool MstState::isEmpty() const {
      85          97 :     return internal_state_.empty();
      86             :   }
      87             : 
      88             :   std::unordered_set<DataType,
      89             :                      iroha::model::PointerBatchHasher,
      90             :                      BatchHashEquality>
      91             :   MstState::getBatches() const {
      92          87 :     return {internal_state_.begin(), internal_state_.end()};
      93             :   }
      94             : 
      95             :   MstState MstState::eraseByTime(const TimeType &time) {
      96          50 :     MstState out = MstState::empty(log_, completer_);
      97          58 :     while (not index_.empty() and (*completer_)(index_.top(), time)) {
      98           8 :       auto iter = internal_state_.find(index_.top());
      99             : 
     100           8 :       out += *iter;
     101           8 :       internal_state_.erase(iter);
     102           8 :       index_.pop();
     103             :     }
     104          50 :     return out;
     105          50 :   }
     106             : 
     107             :   // ------------------------------| private api |------------------------------
     108             : 
     109             :   bool MstState::Less::operator()(const DataType &left,
     110             :                                   const DataType &right) const {
     111          64 :     return left->transactions().at(0)->createdTime()
     112          64 :         < right->transactions().at(0)->createdTime();
     113             :   }
     114             : 
     115             :   /**
     116             :    * Merge signatures in batches
     117             :    * @param target - batch for inserting
     118             :    * @param donor - batch with transactions to copy signatures from
     119             :    * @return return if at least one new signature was inserted
     120             :    */
     121             :   bool mergeSignaturesInBatch(DataType &target, const DataType &donor) {
     122          24 :     auto inserted_new_signatures = false;
     123          48 :     for (auto zip :
     124          24 :          boost::combine(target->transactions(), donor->transactions())) {
     125          24 :       const auto &target_tx = zip.get<0>();
     126          24 :       const auto &donor_tx = zip.get<1>();
     127          24 :       inserted_new_signatures = std::accumulate(
     128          24 :           std::begin(donor_tx->signatures()),
     129          24 :           std::end(donor_tx->signatures()),
     130          24 :           inserted_new_signatures,
     131             :           [&target_tx](bool accumulator, const auto &signature) {
     132          31 :             return target_tx->addSignature(signature.signedData(),
     133          31 :                                            signature.publicKey())
     134          31 :                 or accumulator;
     135             :           });
     136             :     }
     137          24 :     return inserted_new_signatures;
     138           0 :   }
     139             : 
     140             :   MstState::MstState(const CompleterType &completer, logger::LoggerPtr log)
     141         615 :       : MstState(completer, InternalStateType{}, std::move(log)) {}
     142             : 
     143             :   MstState::MstState(const CompleterType &completer,
     144             :                      const InternalStateType &transactions,
     145             :                      logger::LoggerPtr log)
     146         642 :       : completer_(completer),
     147         642 :         internal_state_(transactions.begin(), transactions.end()),
     148         642 :         index_(transactions.begin(), transactions.end()),
     149         642 :         log_(std::move(log)) {}
     150             : 
     151             :   void MstState::insertOne(StateUpdateResult &state_update,
     152             :                            const DataType &rhs_batch) {
     153         130 :     log_->info("batch: {}", *rhs_batch);
     154         130 :     auto corresponding = internal_state_.find(rhs_batch);
     155         130 :     if (corresponding == internal_state_.end()) {
     156             :       // when state does not contain transaction
     157         106 :       rawInsert(rhs_batch);
     158         106 :       state_update.updated_state_->rawInsert(rhs_batch);
     159         106 :       return;
     160             :     }
     161             : 
     162          24 :     DataType found = *corresponding;
     163             :     // Append new signatures to the existing state
     164          24 :     auto inserted_new_signatures = mergeSignaturesInBatch(found, rhs_batch);
     165             : 
     166          24 :     if ((*completer_)(found)) {
     167             :       // state already has completed transaction,
     168             :       // remove from state and return it
     169           8 :       internal_state_.erase(internal_state_.find(found));
     170           8 :       state_update.completed_state_->rawInsert(found);
     171           8 :       return;
     172             :     }
     173             : 
     174             :     // if batch still isn't completed, return it, if new signatures were
     175             :     // inserted
     176          16 :     if (inserted_new_signatures) {
     177          11 :       state_update.updated_state_->rawInsert(found);
     178          11 :     }
     179         130 :   }
     180             : 
     181             :   void MstState::rawInsert(const DataType &rhs_batch) {
     182         231 :     internal_state_.insert(rhs_batch);
     183         231 :     index_.push(rhs_batch);
     184         231 :   }
     185             : 
     186             :   bool MstState::contains(const DataType &element) const {
     187         728 :     return internal_state_.find(element) != internal_state_.end();
     188             :   }
     189             : 
     190             : }  // namespace iroha

Generated by: LCOV version 1.13