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
|