LCOV - code coverage report
Current view: top level - irohad/multi_sig_transactions/state/impl - mst_state.cpp (source / functions) Hit Total Coverage
Test: coverage_cleared.info Lines: 71 74 95.9 %
Date: 2018-12-05 17:11:35 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             : 
      16             : namespace iroha {
      17             : 
      18             :   bool BatchHashEquality::operator()(const DataType &left_tx,
      19             :                                      const DataType &right_tx) const {
      20         101 :     return left_tx->reducedHash() == right_tx->reducedHash();
      21             :   }
      22             : 
      23             :   bool DefaultCompleter::operator()(const DataType &batch) const {
      24          18 :     return std::all_of(batch->transactions().begin(),
      25          18 :                        batch->transactions().end(),
      26             :                        [](const auto &tx) {
      27          18 :                          return boost::size(tx->signatures()) >= tx->quorum();
      28           0 :                        });
      29             :   }
      30             : 
      31             :   bool DefaultCompleter::operator()(const DataType &tx,
      32             :                                     const TimeType &time) const {
      33          12 :     return false;
      34             :   }
      35             : 
      36             :   // ------------------------------| public api |-------------------------------
      37             : 
      38             :   MstState MstState::empty(const CompleterType &completer) {
      39         586 :     return MstState(completer);
      40             :   }
      41             : 
      42             :   StateUpdateResult MstState::operator+=(const DataType &rhs) {
      43         103 :     auto state_update = StateUpdateResult{
      44         103 :         std::make_shared<MstState>(MstState::empty(completer_)),
      45         103 :         std::make_shared<MstState>(MstState::empty(completer_))};
      46         103 :     insertOne(state_update, rhs);
      47         103 :     return state_update;
      48         103 :   }
      49             : 
      50             :   StateUpdateResult MstState::operator+=(const MstState &rhs) {
      51          11 :     auto state_update = StateUpdateResult{
      52          11 :         std::make_shared<MstState>(MstState::empty(completer_)),
      53          11 :         std::make_shared<MstState>(MstState::empty(completer_))};
      54          29 :     for (auto &&rhs_tx : rhs.internal_state_) {
      55          18 :       insertOne(state_update, rhs_tx);
      56             :     }
      57          11 :     return state_update;
      58          11 :   }
      59             : 
      60             :   MstState MstState::operator-(const MstState &rhs) const {
      61          25 :     return MstState(this->completer_,
      62          25 :                     set_difference(this->internal_state_, rhs.internal_state_));
      63           0 :   }
      64             : 
      65             :   bool MstState::operator==(const MstState &rhs) const {
      66           1 :     return std::all_of(
      67             :         internal_state_.begin(), internal_state_.end(), [&rhs](auto &i) {
      68           3 :           return rhs.internal_state_.find(i) != rhs.internal_state_.end();
      69             :         });
      70             :   }
      71             : 
      72             :   bool MstState::isEmpty() const {
      73          89 :     return internal_state_.empty();
      74             :   }
      75             : 
      76             :   std::unordered_set<DataType,
      77             :                      iroha::model::PointerBatchHasher,
      78             :                      BatchHashEquality>
      79             :   MstState::getBatches() const {
      80          84 :     return {internal_state_.begin(), internal_state_.end()};
      81             :   }
      82             : 
      83             :   MstState MstState::eraseByTime(const TimeType &time) {
      84          46 :     MstState out = MstState::empty(completer_);
      85          54 :     while (not index_.empty() and (*completer_)(index_.top(), time)) {
      86           8 :       auto iter = internal_state_.find(index_.top());
      87             : 
      88           8 :       out += *iter;
      89           8 :       internal_state_.erase(iter);
      90           8 :       index_.pop();
      91             :     }
      92             :     return out;
      93          46 :   }
      94             : 
      95             :   // ------------------------------| private api |------------------------------
      96             : 
      97             :   bool MstState::Less::operator()(const DataType &left,
      98             :                                   const DataType &right) const {
      99          61 :     return left->transactions().at(0)->createdTime()
     100          61 :         < right->transactions().at(0)->createdTime();
     101             :   }
     102             : 
     103             :   /**
     104             :    * Merge signatures in batches
     105             :    * @param target - batch for inserting
     106             :    * @param donor - batch with transactions to copy signatures from
     107             :    * @return return if at least one new signature was inserted
     108             :    */
     109             :   bool mergeSignaturesInBatch(DataType &target, const DataType &donor) {
     110          23 :     auto inserted_new_signatures = false;
     111          46 :     for (auto zip :
     112             :          boost::combine(target->transactions(), donor->transactions())) {
     113          23 :       const auto &target_tx = zip.get<0>();
     114          23 :       const auto &donor_tx = zip.get<1>();
     115          23 :       inserted_new_signatures = std::accumulate(
     116          23 :           std::begin(donor_tx->signatures()),
     117          23 :           std::end(donor_tx->signatures()),
     118          23 :           inserted_new_signatures,
     119             :           [&target_tx](bool accumulator, const auto &signature) {
     120          28 :             return target_tx->addSignature(signature.signedData(),
     121          28 :                                            signature.publicKey())
     122          28 :                 or accumulator;
     123             :           });
     124             :     }
     125          23 :     return inserted_new_signatures;
     126           0 :   }
     127             : 
     128             :   MstState::MstState(const CompleterType &completer)
     129         586 :       : MstState(completer, InternalStateType{}) {}
     130             : 
     131             :   MstState::MstState(const CompleterType &completer,
     132             :                      const InternalStateType &transactions)
     133         611 :       : completer_(completer),
     134         611 :         internal_state_(transactions.begin(), transactions.end()),
     135         611 :         index_(transactions.begin(), transactions.end()) {
     136         611 :     log_ = logger::log("MstState");
     137         611 :   }
     138             : 
     139             :   void MstState::insertOne(StateUpdateResult &state_update,
     140             :                            const DataType &rhs_batch) {
     141         121 :     log_->info("batch: {}", rhs_batch->toString());
     142         121 :     auto corresponding = internal_state_.find(rhs_batch);
     143         121 :     if (corresponding == internal_state_.end()) {
     144             :       // when state does not contain transaction
     145          98 :       rawInsert(rhs_batch);
     146          98 :       state_update.updated_state_->rawInsert(rhs_batch);
     147          98 :       return;
     148             :     }
     149             : 
     150          23 :     DataType found = *corresponding;
     151             :     // Append new signatures to the existing state
     152          23 :     auto inserted_new_signatures = mergeSignaturesInBatch(found, rhs_batch);
     153             : 
     154          23 :     if ((*completer_)(found)) {
     155             :       // state already has completed transaction,
     156             :       // remove from state and return it
     157           7 :       internal_state_.erase(internal_state_.find(found));
     158           7 :       state_update.completed_state_->rawInsert(found);
     159           7 :       return;
     160             :     }
     161             : 
     162             :     // if batch still isn't completed, return it, if new signatures were
     163             :     // inserted
     164          16 :     if (inserted_new_signatures) {
     165          11 :       state_update.updated_state_->rawInsert(found);
     166          11 :     }
     167         121 :   }
     168             : 
     169             :   void MstState::rawInsert(const DataType &rhs_batch) {
     170         214 :     internal_state_.insert(rhs_batch);
     171         214 :     index_.push(rhs_batch);
     172         214 :   }
     173             : 
     174             : }  // namespace iroha

Generated by: LCOV version 1.13