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
|