LCOV - code coverage report
Current view: top level - shared_model/interfaces/iroha_internal - transaction_batch_factory_impl.cpp (source / functions) Hit Total Coverage
Test: coverage_cleared.info Lines: 42 50 84.0 %
Date: 2018-12-05 17:11:35 Functions: 5 5 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 "interfaces/iroha_internal/transaction_batch_factory_impl.hpp"
       7             : 
       8             : #include <boost/range/combine.hpp>
       9             : 
      10             : #include "interfaces/iroha_internal/batch_meta.hpp"
      11             : #include "interfaces/iroha_internal/transaction_batch_impl.hpp"
      12             : #include "interfaces/transaction.hpp"
      13             : #include "validators/answer.hpp"
      14             : 
      15             : namespace {
      16             :   enum class BatchCheckResult {
      17             :     kOk,
      18             :     kNoBatchMeta,
      19             :     kIncorrectBatchMetaSize,
      20             :     kIncorrectHashes
      21             :   };
      22             :   /**
      23             :    * Check that all transactions from the collection are mentioned in batch_meta
      24             :    * and are positioned correctly
      25             :    * @param transactions to be checked
      26             :    * @return enum, reporting about success result or containing a found error
      27             :    */
      28             :   BatchCheckResult batchIsWellFormed(
      29             :       const shared_model::interface::types::SharedTxsCollectionType
      30             :           &transactions) {
      31        3548 :     auto batch_meta_opt = transactions[0]->batchMeta();
      32        3548 :     if (not batch_meta_opt and transactions.size() == 1) {
      33             :       // batch is created from one tx - there is no batch_meta in valid case
      34        1488 :       return BatchCheckResult::kOk;
      35             :     }
      36        2061 :     if (not batch_meta_opt) {
      37             :       // in all other cases batch_meta must present
      38           0 :       return BatchCheckResult::kNoBatchMeta;
      39             :     }
      40             : 
      41        2061 :     const auto &batch_hashes = batch_meta_opt->get()->reducedHashes();
      42        2061 :     if (batch_hashes.size() != transactions.size()) {
      43           0 :       return BatchCheckResult::kIncorrectBatchMetaSize;
      44             :     }
      45             : 
      46        2059 :     auto metas_and_txs = boost::combine(batch_hashes, transactions);
      47        2061 :     auto hashes_are_correct =
      48        2060 :         std::all_of(boost::begin(metas_and_txs),
      49        2060 :                     boost::end(metas_and_txs),
      50             :                     [](const auto &meta_and_tx) {
      51        2134 :                       shared_model::interface::types::HashType batch_hash;
      52        2134 :                       std::shared_ptr<shared_model::interface::Transaction> tx;
      53        2134 :                       boost::tie(batch_hash, tx) = meta_and_tx;
      54        2136 :                       return batch_hash == tx->reducedHash();
      55        2137 :                     });
      56        2061 :     if (not hashes_are_correct) {
      57           1 :       return BatchCheckResult::kIncorrectHashes;
      58             :     }
      59             : 
      60        2060 :     return BatchCheckResult::kOk;
      61        3549 :   }
      62             : }  // namespace
      63             : 
      64             : namespace shared_model {
      65             :   namespace interface {
      66             :     TransactionBatchFactoryImpl::FactoryImplResult
      67             :     TransactionBatchFactoryImpl::createTransactionBatch(
      68             :         const types::SharedTxsCollectionType &transactions) const {
      69        3544 :       std::string reason_name = "Transaction batch factory: ";
      70        3544 :       validation::ReasonsGroupType batch_reason;
      71        3546 :       batch_reason.first = reason_name;
      72             : 
      73        3548 :       bool has_at_least_one_signature = std::any_of(
      74             :           transactions.begin(), transactions.end(), [](const auto tx) {
      75        3583 :             return not boost::empty(tx->signatures());
      76           0 :           });
      77        3548 :       if (not has_at_least_one_signature) {
      78           9 :         batch_reason.second.emplace_back(
      79             :             "Transaction batch should contain at least one signature");
      80           9 :       }
      81             : 
      82        7093 :       switch (batchIsWellFormed(transactions)) {
      83             :         case BatchCheckResult::kOk:
      84        3546 :           break;
      85             :         case BatchCheckResult::kNoBatchMeta:
      86           0 :           batch_reason.second.emplace_back(
      87             :               "There is no batch meta in provided transactions");
      88           0 :           break;
      89             :         case BatchCheckResult::kIncorrectBatchMetaSize:
      90           0 :           batch_reason.second.emplace_back(
      91             :               "Sizes of batch_meta and provided transactions are different");
      92           0 :           break;
      93             :         case BatchCheckResult::kIncorrectHashes:
      94           1 :           batch_reason.second.emplace_back(
      95             :               "Hashes of provided transactions and ones in batch_meta are "
      96             :               "different");
      97           1 :           break;
      98             :       }
      99             : 
     100        3547 :       if (not batch_reason.second.empty()) {
     101           9 :         validation::Answer answer;
     102           9 :         answer.addReason(std::move(batch_reason));
     103           9 :         return iroha::expected::makeError(answer.reason());
     104           9 :       }
     105             : 
     106        3535 :       std::unique_ptr<TransactionBatch> batch_ptr =
     107        3535 :           std::make_unique<TransactionBatchImpl>(transactions);
     108        3537 :       return iroha::expected::makeValue(std::move(batch_ptr));
     109        3546 :     }
     110             : 
     111             :     TransactionBatchFactoryImpl::FactoryImplResult
     112             :     TransactionBatchFactoryImpl::createTransactionBatch(
     113             :         std::shared_ptr<Transaction> transaction) const {
     114          36 :       return createTransactionBatch(
     115          36 :           types::SharedTxsCollectionType{std::move(transaction)});
     116           0 :     }
     117             :   }  // namespace interface
     118             : }  // namespace shared_model

Generated by: LCOV version 1.13