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
|