LCOV - code coverage report
Current view: top level - shared_model/validators/transactions_collection - batch_order_validator.cpp (source / functions) Hit Total Coverage
Test: coverage_cleared.info Lines: 0 66 0.0 %
Date: 2018-12-05 17:11:35 Functions: 0 2 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 "validators/transactions_collection/batch_order_validator.hpp"
       7             : 
       8             : #include <boost/format.hpp>
       9             : #include <boost/range/algorithm/find.hpp>
      10             : #include "interfaces/iroha_internal/batch_meta.hpp"
      11             : #include "interfaces/transaction.hpp"
      12             : 
      13             : namespace shared_model {
      14             :   namespace validation {
      15             :     std::string BatchOrderValidator::canFollow(
      16             :         boost::optional<std::shared_ptr<interface::Transaction>> tr1,
      17             :         boost::optional<std::shared_ptr<interface::Transaction>> tr2) const {
      18             :       boost::optional<std::shared_ptr<interface::BatchMeta>> batch1 =
      19           0 :           tr1 ? tr1.value()->batchMeta() : boost::none;
      20             :       boost::optional<std::shared_ptr<interface::BatchMeta>> batch2 =
      21           0 :           tr2 ? tr2.value()->batchMeta() : boost::none;
      22             :       // both transactions are not a part of any batch
      23           0 :       if (not batch1 and not batch2) {
      24           0 :         return "";
      25             :       }
      26             :       // beginning of a batch
      27           0 :       if (not batch1) {
      28           0 :         if (batch2.get()->reducedHashes().size() == 0) {
      29           0 :           return (boost::format("Tx %s has a batch of 0 transactions")
      30           0 :                   % tr2.value()->hash().hex())
      31           0 :               .str();
      32             :         }
      33           0 :         if (batch2.get()->reducedHashes().front()
      34           0 :             != tr2.value()->reducedHash()) {
      35           0 :           return (boost::format("Tx %s is a first transaction of a batch, but "
      36             :                                 "it's reduced hash %s doesn't match the first "
      37             :                                 "reduced hash in batch %s")
      38           0 :                   % tr2.value()->hash().hex()
      39           0 :                   % batch2.get()->reducedHashes().front().hex()
      40           0 :                   % tr2.value()->reducedHash().hex())
      41           0 :               .str();
      42             :         }
      43           0 :         return "";
      44             :       }
      45             :       // end of a batch
      46           0 :       if (not batch2) {
      47           0 :         if (batch1.get()->reducedHashes().back()
      48           0 :             != tr1.value()->reducedHash()) {
      49           0 :           return (boost::format("Tx %s is a last transaction of a batch, but "
      50             :                                 "it's reduced hash %s doesn't match the last "
      51             :                                 "reduced hash in batch %s")
      52           0 :                   % tr1.value()->hash().hex()
      53           0 :                   % batch1.get()->reducedHashes().back().hex()
      54           0 :                   % tr1.value()->reducedHash().hex())
      55           0 :               .str();
      56             :         }
      57           0 :         return "";
      58             :       }
      59             :       // inside of a batch
      60           0 :       auto it1 = boost::find(batch1.get()->reducedHashes(),
      61           0 :                              tr1.value()->reducedHash());
      62           0 :       auto it2 = boost::find(batch2.get()->reducedHashes(),
      63           0 :                              tr2.value()->reducedHash());
      64           0 :       if (it1 == end(batch1.get()->reducedHashes())
      65           0 :           or it2 == end(batch2.get()->reducedHashes())
      66           0 :           or next(it1) == end(batch1.get()->reducedHashes())
      67           0 :           or *next(it1) != *it2) {
      68             :         // end of the bach and beginning of the next
      69           0 :         if (canFollow(tr1, boost::none) == ""
      70           0 :             and canFollow(boost::none, tr2) == "") {
      71           0 :           return "";
      72             :         }
      73           0 :         return (boost::format("Tx %s is followed by %s, but their reduced"
      74             :                               "hashed doesn't follow each other in their batch"
      75             :                               "meta")
      76           0 :                 % tr1.value()->hash().hex() % tr2.value()->hash().hex())
      77           0 :             .str();
      78             :       }
      79           0 :       if (**batch1 != **batch2) {
      80           0 :         return (boost::format("Tx %s and %s are part of the same batch, but "
      81             :                               "their batch metas doesn't match")
      82           0 :                 % tr1.value()->hash().hex() % tr2.value()->hash().hex())
      83           0 :             .str();
      84             :       }
      85           0 :       return "";
      86           0 :     }
      87             : 
      88             :     Answer BatchOrderValidator::validate(
      89             :         const interface::types::SharedTxsCollectionType &transactions) const {
      90           0 :       Answer res;
      91           0 :       ReasonsGroupType reason;
      92           0 :       reason.first = "Transaction order";
      93             :       boost::optional<interface::types::SharedTxsCollectionType::value_type>
      94           0 :           prev_transaction = boost::none;
      95             : 
      96           0 :       for (auto &transaction : transactions) {
      97           0 :         auto message = canFollow(prev_transaction, transaction);
      98           0 :         if (message != "") {
      99           0 :           reason.second.push_back(message);
     100           0 :         }
     101           0 :         prev_transaction = transaction;
     102           0 :       }
     103           0 :       auto message = canFollow(prev_transaction, boost::none);
     104           0 :       if (message != "") {
     105           0 :         reason.second.push_back(message);
     106           0 :       }
     107           0 :       if (not reason.second.empty()) {
     108           0 :         res.addReason(std::move(reason));
     109           0 :       }
     110           0 :       return res;
     111           0 :     }
     112             :   }  // namespace validation
     113             : }  // namespace shared_model

Generated by: LCOV version 1.13