LCOV - code coverage report
Current view: top level - shared_model/validators - transaction_batch_validator.cpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 41 45 91.1 %
Date: 2019-03-07 14:46:43 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 "validators/transaction_batch_validator.hpp"
       7             : 
       8             : #include <boost/range/adaptor/indirected.hpp>
       9             : #include "interfaces/iroha_internal/batch_meta.hpp"
      10             : #include "interfaces/transaction.hpp"
      11             : 
      12             : namespace {
      13             :   enum class BatchCheckResult {
      14             :     kOk,
      15             :     kNoBatchMeta,
      16             :     kIncorrectBatchMetaSize,
      17             :     kIncorrectHashes
      18             :   };
      19             :   /**
      20             :    * Check that all transactions from the collection are mentioned in batch_meta
      21             :    * and are positioned correctly
      22             :    * @param transactions to be checked
      23             :    * @return enum, reporting about success result or containing a found error
      24             :    */
      25             :   BatchCheckResult batchIsWellFormed(
      26             :       const shared_model::interface::types::TransactionsForwardCollectionType
      27             :           &transactions) {
      28             :     // equality of transactions batchMeta is checked during batch parsing
      29        5705 :     auto batch_meta_opt = transactions.begin()->batchMeta();
      30        5705 :     const auto transactions_quantity = boost::size(transactions);
      31        5662 :     if (not batch_meta_opt and transactions_quantity == 1) {
      32             :       // batch is created from one tx - there is no batch_meta in valid case
      33        5610 :       return BatchCheckResult::kOk;
      34             :     }
      35          53 :     if (not batch_meta_opt) {
      36             :       // in all other cases batch_meta must present
      37           0 :       return BatchCheckResult::kNoBatchMeta;
      38             :     }
      39             : 
      40          54 :     const auto &batch_hashes = batch_meta_opt->get()->reducedHashes();
      41          54 :     if (batch_hashes.size() != transactions_quantity) {
      42           1 :       return BatchCheckResult::kIncorrectBatchMetaSize;
      43             :     }
      44             : 
      45          53 :     auto hashes_are_correct =
      46          53 :         std::equal(boost::begin(batch_hashes),
      47          51 :                    boost::end(batch_hashes),
      48          51 :                    boost::begin(transactions),
      49          51 :                    boost::end(transactions),
      50             :                    [](const auto &tx_reduced_hash, const auto &tx) {
      51         137 :                      return tx_reduced_hash == tx.reducedHash();
      52             :                    });
      53          53 :     if (not hashes_are_correct) {
      54           1 :       return BatchCheckResult::kIncorrectHashes;
      55             :     }
      56             : 
      57          51 :     return BatchCheckResult::kOk;
      58        5617 :   }
      59             : }  // namespace
      60             : 
      61             : namespace shared_model {
      62             :   namespace validation {
      63             : 
      64             :     Answer BatchValidator::validate(
      65             :         const interface::TransactionBatch &batch) const {
      66        3992 :       auto transactions = batch.transactions();
      67        4121 :       return validate(transactions | boost::adaptors::indirected);
      68        4121 :     }
      69             : 
      70             :     Answer BatchValidator::validate(
      71             :         interface::types::TransactionsForwardCollectionType transactions)
      72             :         const {
      73        5525 :       std::string reason_name = "Transaction batch factory: ";
      74        5525 :       validation::ReasonsGroupType batch_reason;
      75        5622 :       batch_reason.first = reason_name;
      76             : 
      77        5702 :       bool has_at_least_one_signature = std::any_of(
      78             :           transactions.begin(), transactions.end(), [](const auto &tx) {
      79        5753 :             return not boost::empty(tx.signatures());
      80           0 :           });
      81        5702 :       if (not has_at_least_one_signature) {
      82          10 :         batch_reason.second.emplace_back(
      83             :             "Transaction batch should contain at least one signature");
      84             :         // no stronger check for signatures is required here
      85             :         // here we are checking only batch logic, not transaction-related
      86          10 :       }
      87             : 
      88       11261 :       switch (batchIsWellFormed(transactions)) {
      89             :         case BatchCheckResult::kOk:
      90        5642 :           break;
      91             :         case BatchCheckResult::kNoBatchMeta:
      92           0 :           batch_reason.second.emplace_back(
      93             :               "There is no batch meta in provided transactions");
      94           0 :           break;
      95             :         case BatchCheckResult::kIncorrectBatchMetaSize:
      96           1 :           batch_reason.second.emplace_back(
      97             :               "Sizes of batch_meta and provided transactions are different");
      98           1 :           break;
      99             :         case BatchCheckResult::kIncorrectHashes:
     100           1 :           batch_reason.second.emplace_back(
     101             :               "Hashes of provided transactions and ones in batch_meta are "
     102             :               "different");
     103           1 :           break;
     104             :       }
     105             : 
     106        5703 :       validation::Answer answer;
     107        5703 :       if (not batch_reason.second.empty()) {
     108          11 :         answer.addReason(std::move(batch_reason));
     109          11 :       }
     110        5680 :       return answer;
     111        5680 :     }
     112             : 
     113             :   }  // namespace validation
     114             : }  // namespace shared_model

Generated by: LCOV version 1.13