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 :
15 : namespace iroha {
16 : namespace validation {
17 : ChainValidatorImpl::ChainValidatorImpl(
18 : std::shared_ptr<consensus::yac::SupermajorityChecker>
19 : supermajority_checker)
20 252 : : supermajority_checker_(supermajority_checker),
21 252 : log_(logger::log("ChainValidator")) {}
22 :
23 : bool ChainValidatorImpl::validateAndApply(
24 : rxcpp::observable<std::shared_ptr<shared_model::interface::Block>>
25 : blocks,
26 : ametsuchi::MutableStorage &storage) const {
27 7 : log_->info("validate chain...");
28 :
29 7 : return storage.apply(
30 7 : blocks,
31 : [this](const auto &block, auto &queries, const auto &top_hash) {
32 9 : return this->validateBlock(block, queries, top_hash);
33 : });
34 0 : }
35 :
36 : bool ChainValidatorImpl::validatePreviousHash(
37 : const shared_model::interface::Block &block,
38 : const shared_model::interface::types::HashType &top_hash) const {
39 9 : auto same_prev_hash = block.prevHash() == top_hash;
40 :
41 9 : if (not same_prev_hash) {
42 2 : log_->info(
43 : "Previous hash {} of block does not match top block hash {} "
44 : "in storage",
45 2 : block.prevHash().hex(),
46 2 : top_hash.hex());
47 2 : }
48 :
49 9 : return same_prev_hash;
50 : }
51 :
52 : bool ChainValidatorImpl::validatePeerSupermajority(
53 : const shared_model::interface::Block &block,
54 : const std::vector<std::shared_ptr<shared_model::interface::Peer>>
55 : &peers) const {
56 7 : const auto &signatures = block.signatures();
57 7 : auto has_supermajority =
58 7 : supermajority_checker_->hasSupermajority(signatures, peers);
59 :
60 7 : if (not has_supermajority) {
61 2 : log_->info(
62 : "Block does not contain signatures of supermajority of "
63 : "peers. Block signatures public keys: [{}], ledger peers "
64 : "public keys: [{}]",
65 2 : std::accumulate(std::next(std::begin(signatures)),
66 2 : std::end(signatures),
67 2 : signatures.front().publicKey().hex(),
68 : [](auto acc, auto &sig) {
69 1 : return acc + ", " + sig.publicKey().hex();
70 0 : }),
71 2 : std::accumulate(std::next(std::begin(peers)),
72 2 : std::end(peers),
73 2 : peers.front()->pubkey().hex(),
74 : [](auto acc, auto &peer) {
75 3 : return acc + ", " + peer->pubkey().hex();
76 0 : }));
77 2 : }
78 :
79 7 : return has_supermajority;
80 7 : }
81 :
82 : bool ChainValidatorImpl::validateBlock(
83 : const shared_model::interface::Block &block,
84 : ametsuchi::PeerQuery &queries,
85 : const shared_model::interface::types::HashType &top_hash) const {
86 9 : log_->info("validate block: height {}, hash {}",
87 9 : block.height(),
88 9 : block.hash().hex());
89 :
90 9 : auto peers = queries.getLedgerPeers();
91 9 : if (not peers) {
92 : log_->info("Cannot retrieve peers from storage");
93 0 : return false;
94 : }
95 :
96 9 : return validatePreviousHash(block, top_hash)
97 9 : and validatePeerSupermajority(block, *peers);
98 9 : }
99 :
100 : } // namespace validation
101 : } // namespace iroha
|