Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #include "validation/impl/chain_validator_impl.hpp"
7 :
8 : #include "ametsuchi/mutable_storage.hpp"
9 : #include "ametsuchi/peer_query.hpp"
10 : #include "consensus/yac/supermajority_checker.hpp"
11 : #include "cryptography/public_key.hpp"
12 : #include "interfaces/common_objects/peer.hpp"
13 : #include "interfaces/iroha_internal/block.hpp"
14 : #include "logger/logger.hpp"
15 : #include "validation/utils.hpp"
16 :
17 : namespace iroha {
18 : namespace validation {
19 : ChainValidatorImpl::ChainValidatorImpl(
20 : std::shared_ptr<consensus::yac::SupermajorityChecker>
21 : supermajority_checker,
22 : logger::LoggerPtr log)
23 254 : : supermajority_checker_(supermajority_checker),
24 254 : log_(std::move(log)) {}
25 :
26 : bool ChainValidatorImpl::validateAndApply(
27 : rxcpp::observable<std::shared_ptr<shared_model::interface::Block>>
28 : blocks,
29 : ametsuchi::MutableStorage &storage) const {
30 7 : log_->info("validate chain...");
31 :
32 7 : return storage.apply(
33 7 : blocks,
34 : [this](const auto &block, auto &queries, const auto &top_hash) {
35 9 : return this->validateBlock(block, queries, top_hash);
36 : });
37 0 : }
38 :
39 : bool ChainValidatorImpl::validatePreviousHash(
40 : const shared_model::interface::Block &block,
41 : const shared_model::interface::types::HashType &top_hash) const {
42 9 : auto same_prev_hash = block.prevHash() == top_hash;
43 :
44 9 : if (not same_prev_hash) {
45 2 : log_->info(
46 2 : "Previous hash {} of block does not match top block hash {} "
47 : "in storage",
48 2 : block.prevHash().hex(),
49 2 : top_hash.hex());
50 2 : }
51 :
52 9 : return same_prev_hash;
53 0 : }
54 :
55 : bool ChainValidatorImpl::validatePeerSupermajority(
56 : const shared_model::interface::Block &block,
57 : const std::vector<std::shared_ptr<shared_model::interface::Peer>>
58 : &peers) const {
59 7 : const auto &signatures = block.signatures();
60 7 : auto has_supermajority = supermajority_checker_->hasSupermajority(
61 7 : boost::size(signatures), peers.size())
62 7 : and peersSubset(signatures, peers);
63 :
64 7 : if (not has_supermajority) {
65 2 : log_->info(
66 2 : "Block does not contain signatures of supermajority of "
67 : "peers. Block signatures public keys: [{}], ledger peers "
68 : "public keys: [{}]",
69 2 : std::accumulate(std::next(std::begin(signatures)),
70 2 : std::end(signatures),
71 2 : signatures.front().publicKey().hex(),
72 : [](auto acc, auto &sig) {
73 1 : return acc + ", " + sig.publicKey().hex();
74 0 : }),
75 2 : std::accumulate(std::next(std::begin(peers)),
76 2 : std::end(peers),
77 2 : peers.front()->pubkey().hex(),
78 : [](auto acc, auto &peer) {
79 3 : return acc + ", " + peer->pubkey().hex();
80 0 : }));
81 2 : }
82 :
83 7 : return has_supermajority;
84 7 : }
85 :
86 : bool ChainValidatorImpl::validateBlock(
87 : const shared_model::interface::Block &block,
88 : ametsuchi::PeerQuery &queries,
89 : const shared_model::interface::types::HashType &top_hash) const {
90 9 : log_->info("validate block: height {}, hash {}",
91 9 : block.height(),
92 9 : block.hash().hex());
93 :
94 9 : auto peers = queries.getLedgerPeers();
95 9 : if (not peers) {
96 0 : log_->info("Cannot retrieve peers from storage");
97 0 : return false;
98 : }
99 :
100 9 : return validatePreviousHash(block, top_hash)
101 9 : and validatePeerSupermajority(block, *peers);
102 9 : }
103 :
104 : } // namespace validation
105 : } // namespace iroha
|