diff --git a/irohad/consensus/yac/CMakeLists.txt b/irohad/consensus/yac/CMakeLists.txt index 29a5d23807..473035b247 100644 --- a/irohad/consensus/yac/CMakeLists.txt +++ b/irohad/consensus/yac/CMakeLists.txt @@ -34,6 +34,7 @@ add_library(yac storage/impl/yac_block_storage.cpp storage/impl/yac_proposal_storage.cpp storage/impl/yac_vote_storage.cpp + storage/impl/buffered_cleanup_strategy.cpp ) target_link_libraries(yac supermajority_check diff --git a/irohad/consensus/yac/impl/cluster_order.cpp b/irohad/consensus/yac/impl/cluster_order.cpp index a4c3e73ecb..ab928d5014 100644 --- a/irohad/consensus/yac/impl/cluster_order.cpp +++ b/irohad/consensus/yac/impl/cluster_order.cpp @@ -22,8 +22,8 @@ namespace iroha { std::vector> order) : order_(std::move(order)) {} - // TODO : 24/03/2018 x3medima17: make it const, IR-1164 - const shared_model::interface::Peer& ClusterOrdering::currentLeader() { + // TODO : 24/03/2018 x3medima17: make it const, IR-1164 + const shared_model::interface::Peer &ClusterOrdering::currentLeader() { if (index_ >= order_.size()) { index_ = 0; } diff --git a/irohad/consensus/yac/storage/buffered_cleanup_strategy.hpp b/irohad/consensus/yac/storage/buffered_cleanup_strategy.hpp new file mode 100644 index 0000000000..e83bf92885 --- /dev/null +++ b/irohad/consensus/yac/storage/buffered_cleanup_strategy.hpp @@ -0,0 +1,77 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef IROHA_BUFFERED_CLEANUP_STRATEGY_HPP +#define IROHA_BUFFERED_CLEANUP_STRATEGY_HPP + +#include "consensus/yac/storage/cleanup_strategy.hpp" + +#include +#include + +#include "consensus/yac/outcome_messages.hpp" + +namespace iroha { + namespace consensus { + namespace yac { + class BufferedCleanupStrategy : public CleanupStrategy { + public: + using RoundType = Round; + + /** + * The method finalizes passed round. On Commit message it purges last + * reject round if commit is greater. + * @param consensus_round - finalized round of the consensus + * @param answer - the output of the round + * @return rounds to be removed, if any. + */ + boost::optional finalize( + RoundType consensus_round, Answer answer) override; + + bool shouldCreateRound(const RoundType &round) override; + + private: + /** + * Remove all rounds before last committed + * @return rounds to be removed. Also, the same rounds are removed from + * created_rounds_ collection + */ + RoundsType truncateCreatedRounds(); + + /** + * @return the lowest round from last committed and last rejected + * rounds, if the operation can't be applied - returns none + */ + boost::optional minimalRound() const; + + /** + * The method creates round into created_rounds_ collection + * @param round - round for insertion + */ + void createRound(const Round &round); + + /** + * Checks whether we should add round into created_rounds_ collection + * @param round - round for checking + * @return true if could be inserted + */ + bool isRequiredCreation(const Round &round) const; + + /// all stored rounds + std::priority_queue, + std::greater> + created_rounds_; + + /// maximal reject round, could empty if commit happened + boost::optional last_reject_round_; + /// maximal commit round + boost::optional last_commit_round_; + }; + } // namespace yac + } // namespace consensus +} // namespace iroha + +#endif // IROHA_BUFFERED_CLEANUP_STRATEGY_HPP diff --git a/irohad/consensus/yac/storage/cleanup_strategy.hpp b/irohad/consensus/yac/storage/cleanup_strategy.hpp new file mode 100644 index 0000000000..b25a93144e --- /dev/null +++ b/irohad/consensus/yac/storage/cleanup_strategy.hpp @@ -0,0 +1,48 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef IROHA_CLEANUP_STRATEGY_HPP +#define IROHA_CLEANUP_STRATEGY_HPP + +#include + +#include + +#include "consensus/round.hpp" +#include "consensus/yac/storage/storage_result.hpp" + +namespace iroha { + namespace consensus { + namespace yac { + class CleanupStrategy { + public: + /** + * Collection of rounds type + */ + using RoundsType = std::vector; + + /** + * Notify strategy about new rounds + * @param round - new round + * @param answer - outcome of round + * @return a collection of rounds for removing from the state + */ + virtual boost::optional finalize(Round round, + Answer answer) = 0; + + /** + * The method checks whether we should add a new round + * @param round - round for creation + * @return true if round should be created + */ + virtual bool shouldCreateRound(const Round &round) = 0; + + virtual ~CleanupStrategy() = default; + }; + } // namespace yac + } // namespace consensus +} // namespace iroha + +#endif // IROHA_CLEANUP_STRATEGY_HPP diff --git a/irohad/consensus/yac/storage/impl/buffered_cleanup_strategy.cpp b/irohad/consensus/yac/storage/impl/buffered_cleanup_strategy.cpp new file mode 100644 index 0000000000..174cf209f0 --- /dev/null +++ b/irohad/consensus/yac/storage/impl/buffered_cleanup_strategy.cpp @@ -0,0 +1,90 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "consensus/yac/storage/buffered_cleanup_strategy.hpp" + +#include "common/visitor.hpp" + +using namespace iroha::consensus::yac; + +boost::optional BufferedCleanupStrategy::finalize( + RoundType consensus_round, Answer answer) { + using OptRefRoundType = boost::optional &; + auto &target_round = iroha::visit_in_place( + answer, + [this]( + const iroha::consensus::yac::CommitMessage &msg) -> OptRefRoundType { + // greater commit removes last reject because previous rejects are not + // required anymore for the consensus + if (last_commit_round_ and last_reject_round_ + and *last_commit_round_ < *last_reject_round_) { + last_reject_round_ = boost::none; + } + return last_commit_round_; + }, + [this](const iroha::consensus::yac::RejectMessage &msg) + -> OptRefRoundType { return last_reject_round_; }); + + if (not target_round or *target_round < consensus_round) { + target_round = consensus_round; + } + + auto removed_rounds = truncateCreatedRounds(); + if (removed_rounds.empty()) { + return boost::none; + } else { + return removed_rounds; + } +} + +CleanupStrategy::RoundsType BufferedCleanupStrategy::truncateCreatedRounds() { + CleanupStrategy::RoundsType removed; + if (last_commit_round_) { + while (*last_commit_round_ > created_rounds_.top()) { + removed.push_back(created_rounds_.top()); + created_rounds_.pop(); + } + } + return removed; +} + +boost::optional +BufferedCleanupStrategy::minimalRound() const { + // both values unavailable + if (not last_reject_round_ and not last_commit_round_) { + return boost::none; + } + + // both values present + if (last_commit_round_ and last_reject_round_) { + return std::min(*last_commit_round_, *last_reject_round_); + } + + // one value present + return last_commit_round_ ? last_commit_round_ : last_reject_round_; +} + +bool BufferedCleanupStrategy::shouldCreateRound(const Round &round) { + if (isRequiredCreation(round)) { + createRound(round); + return true; + } else { + return false; + } +} + +void BufferedCleanupStrategy::createRound(const Round &round) { + created_rounds_.push(round); +} + +bool BufferedCleanupStrategy::isRequiredCreation(const Round &round) const { + // TODO: 13/12/2018 @muratovv possible DOS-attack on consensus IR-128 + auto min_round = minimalRound(); + if (min_round) { + return *min_round <= round; + } else { + return true; + } +} diff --git a/irohad/consensus/yac/storage/impl/yac_vote_storage.cpp b/irohad/consensus/yac/storage/impl/yac_vote_storage.cpp index 47723117aa..e03543c491 100644 --- a/irohad/consensus/yac/storage/impl/yac_vote_storage.cpp +++ b/irohad/consensus/yac/storage/impl/yac_vote_storage.cpp @@ -1,18 +1,6 @@ /** - * Copyright Soramitsu Co., Ltd. 2017 All Rights Reserved. - * http://soramitsu.co.jp - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 */ #include "consensus/yac/storage/yac_vote_storage.hpp" @@ -20,6 +8,7 @@ #include #include +#include "common/bind.hpp" #include "consensus/yac/storage/yac_proposal_storage.hpp" namespace iroha { @@ -36,25 +25,60 @@ namespace iroha { }); } - auto YacVoteStorage::findProposalStorage(const VoteMessage &msg, - PeersNumberType peers_in_round) { - auto val = getProposalStorage(msg.hash.vote_round); + boost::optional::iterator> + YacVoteStorage::findProposalStorage(const VoteMessage &msg, + PeersNumberType peers_in_round) { + const auto &round = msg.hash.vote_round; + auto val = getProposalStorage(round); if (val != proposal_storages_.end()) { return val; } - return proposal_storages_.emplace( - proposal_storages_.end(), - msg.hash.vote_round, - peers_in_round, - std::make_shared()); + if (strategy_->shouldCreateRound(round)) { + return proposal_storages_.emplace( + proposal_storages_.end(), + msg.hash.vote_round, + peers_in_round, + std::make_shared()); + } else { + return boost::none; + } + } + + void YacVoteStorage::remove(const iroha::consensus::Round &round) { + auto val = getProposalStorage(round); + if (val != proposal_storages_.end()) { + proposal_storages_.erase(val); + } + auto state = processing_state_.find(round); + if (state != processing_state_.end()) { + processing_state_.erase(state); + } } // --------| public api |-------- + YacVoteStorage::YacVoteStorage( + std::shared_ptr cleanup_strategy) + : strategy_(std::move(cleanup_strategy)) {} + boost::optional YacVoteStorage::store( std::vector state, PeersNumberType peers_in_round) { - auto storage = findProposalStorage(state.at(0), peers_in_round); - return storage->insert(state); + return findProposalStorage(state.at(0), peers_in_round) | + [this, &state](auto &&storage) { + const auto &round = storage->getStorageKey(); + return storage->insert(state) | + [this, &round]( + auto &&insert_outcome) -> boost::optional { + this->strategy_->finalize(round, insert_outcome) | + [this](auto &&remove) { + std::for_each( + remove.begin(), + remove.end(), + [this](const auto &round) { this->remove(round); }); + }; + return insert_outcome; + }; + }; } bool YacVoteStorage::isCommitted(const Round &round) { diff --git a/irohad/consensus/yac/storage/yac_vote_storage.hpp b/irohad/consensus/yac/storage/yac_vote_storage.hpp index a198a7ab64..5e9132b409 100644 --- a/irohad/consensus/yac/storage/yac_vote_storage.hpp +++ b/irohad/consensus/yac/storage/yac_vote_storage.hpp @@ -12,6 +12,7 @@ #include #include "consensus/yac/outcome_messages.hpp" // because messages passed by value +#include "consensus/yac/storage/cleanup_strategy.hpp" #include "consensus/yac/storage/storage_result.hpp" // for Answer #include "consensus/yac/storage/yac_common.hpp" // for ProposalHash #include "consensus/yac/storage/yac_proposal_storage.hpp" @@ -75,12 +76,23 @@ namespace iroha { * This parameter used on creation of proposal storage * @return - iter for required proposal storage */ - auto findProposalStorage(const VoteMessage &msg, - PeersNumberType peers_in_round); + boost::optional::iterator> + findProposalStorage(const VoteMessage &msg, + PeersNumberType peers_in_round); + + /** + * Remove proposal storage by round + */ + void remove(const Round &round); public: // --------| public api |-------- + /** + * @param cleanup_strategy - strategy for removing elements from storage + */ + YacVoteStorage(std::shared_ptr cleanup_strategy); + /** * Insert votes in storage * @param state - current message with votes @@ -119,6 +131,9 @@ namespace iroha { private: // --------| fields |-------- + // TODO: 2019-02-28 @muratovv refactor proposal_storages_ & + // processing_state_ with separate entity IR-360 + /** * Active proposal storages */ @@ -131,6 +146,12 @@ namespace iroha { */ std::unordered_map processing_state_; + + /** + * Provides strategy managing rounds (adding and removing) for the + * storage + */ + std::shared_ptr strategy_; }; } // namespace yac diff --git a/irohad/consensus/yac/transport/impl/network_impl.cpp b/irohad/consensus/yac/transport/impl/network_impl.cpp index 60f2447e2b..2efb1cf349 100644 --- a/irohad/consensus/yac/transport/impl/network_impl.cpp +++ b/irohad/consensus/yac/transport/impl/network_impl.cpp @@ -10,6 +10,7 @@ #include "consensus/yac/storage/yac_common.hpp" #include "consensus/yac/transport/yac_pb_converters.hpp" +#include "consensus/yac/vote_message.hpp" #include "interfaces/common_objects/peer.hpp" #include "logger/logger.hpp" #include "network/impl/grpc_channel_builder.hpp" diff --git a/irohad/consensus/yac/transport/impl/network_impl.hpp b/irohad/consensus/yac/transport/impl/network_impl.hpp index 0390dbfa39..d61f8bd4d7 100644 --- a/irohad/consensus/yac/transport/impl/network_impl.hpp +++ b/irohad/consensus/yac/transport/impl/network_impl.hpp @@ -13,6 +13,7 @@ #include #include "consensus/yac/outcome_messages.hpp" +#include "consensus/yac/vote_message.hpp" #include "interfaces/common_objects/peer.hpp" #include "interfaces/common_objects/types.hpp" #include "logger/logger.hpp" @@ -22,10 +23,6 @@ namespace iroha { namespace consensus { namespace yac { - struct CommitMessage; - struct RejectMessage; - struct VoteMessage; - /** * Class which provides implementation of transport for consensus based on * grpc diff --git a/irohad/consensus/yac/yac_hash_provider.hpp b/irohad/consensus/yac/yac_hash_provider.hpp index 52c4475c4b..8a6e192d76 100644 --- a/irohad/consensus/yac/yac_hash_provider.hpp +++ b/irohad/consensus/yac/yac_hash_provider.hpp @@ -29,6 +29,8 @@ namespace iroha { class YacHash { public: + // TODO: 2019-02-08 @muratovv IR-288 refactor YacHash: default ctor, + // block signature param, code in the header. YacHash(Round round, ProposalHash proposal, BlockHash block) : vote_round{round}, vote_hashes{std::move(proposal), std::move(block)} {} diff --git a/irohad/main/impl/consensus_init.cpp b/irohad/main/impl/consensus_init.cpp index 6ab9fae4cd..0f05c4918c 100644 --- a/irohad/main/impl/consensus_init.cpp +++ b/irohad/main/impl/consensus_init.cpp @@ -9,6 +9,7 @@ #include "consensus/yac/impl/yac_crypto_provider_impl.hpp" #include "consensus/yac/impl/yac_gate_impl.hpp" #include "consensus/yac/impl/yac_hash_provider_impl.hpp" +#include "consensus/yac/storage/buffered_cleanup_strategy.hpp" #include "consensus/yac/storage/yac_proposal_storage.hpp" #include "consensus/yac/transport/impl/network_impl.hpp" @@ -69,8 +70,11 @@ namespace iroha { async_call, std::shared_ptr common_objects_factory) { + std::shared_ptr + cleanup_strategy = std::make_shared< + iroha::consensus::yac::BufferedCleanupStrategy>(); return Yac::create( - YacVoteStorage(), + YacVoteStorage(cleanup_strategy), createNetwork(std::move(async_call)), createCryptoProvider(keypair, std::move(common_objects_factory)), createTimer(delay_milliseconds), diff --git a/test/integration/consensus/consensus_sunny_day.cpp b/test/integration/consensus/consensus_sunny_day.cpp index e875837f63..6a22a53070 100644 --- a/test/integration/consensus/consensus_sunny_day.cpp +++ b/test/integration/consensus/consensus_sunny_day.cpp @@ -8,6 +8,7 @@ #include "consensus/yac/cluster_order.hpp" #include "consensus/yac/impl/timer_impl.hpp" +#include "consensus/yac/storage/buffered_cleanup_strategy.hpp" #include "consensus/yac/storage/yac_proposal_storage.hpp" #include "consensus/yac/storage/yac_vote_storage.hpp" #include "consensus/yac/transport/impl/network_impl.hpp" @@ -61,6 +62,7 @@ class FixedCryptoProvider : public MockYacCryptoProvider { class ConsensusSunnyDayTest : public ::testing::Test { public: + std::shared_ptr cleanup_strategy; std::unique_ptr server; std::shared_ptr network; std::shared_ptr crypto; @@ -84,6 +86,8 @@ class ConsensusSunnyDayTest : public ::testing::Test { } void SetUp() override { + cleanup_strategy = + std::make_shared(); auto async_call = std::make_shared< iroha::network::AsyncGrpcClient>(); network = std::make_shared(async_call); @@ -99,7 +103,11 @@ class ConsensusSunnyDayTest : public ::testing::Test { auto order = ClusterOrdering::create(default_peers); ASSERT_TRUE(order); - yac = Yac::create(YacVoteStorage(), network, crypto, timer, order.value()); + yac = Yac::create(YacVoteStorage(cleanup_strategy), + network, + crypto, + timer, + order.value()); network->subscribe(yac); grpc::ServerBuilder builder; diff --git a/test/module/irohad/consensus/yac/CMakeLists.txt b/test/module/irohad/consensus/yac/CMakeLists.txt index 4869076aa4..53f7b439c6 100644 --- a/test/module/irohad/consensus/yac/CMakeLists.txt +++ b/test/module/irohad/consensus/yac/CMakeLists.txt @@ -78,3 +78,9 @@ addtest(supermajority_checker_test supermajority_checker_test.cpp) target_link_libraries(supermajority_checker_test yac ) + +addtest(buffered_cleanup_strategy_test buffered_cleanup_strategy_test.cpp) +target_link_libraries(buffered_cleanup_strategy_test + yac + consensus_round + ) diff --git a/test/module/irohad/consensus/yac/buffered_cleanup_strategy_test.cpp b/test/module/irohad/consensus/yac/buffered_cleanup_strategy_test.cpp new file mode 100644 index 0000000000..f42b22e2e0 --- /dev/null +++ b/test/module/irohad/consensus/yac/buffered_cleanup_strategy_test.cpp @@ -0,0 +1,91 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "consensus/yac/storage/buffered_cleanup_strategy.hpp" + +#include + +#include + +using namespace iroha::consensus::yac; + +using Round = iroha::consensus::Round; + +class BufferedCleanupStrategyTest : public ::testing::Test { + public: + std::shared_ptr strategy_; + + void SetUp() override { + strategy_ = std::make_shared(); + } + + RejectMessage makeMockReject() { + return RejectMessage({}); + } + + CommitMessage makeMockCommit() { + return CommitMessage({}); + } +}; + +/** + * Reject first case + * @given empty strategy + * @when insert reject message for (1, 1) + * @and insert commit message for (1, 2) + * @then checks that reject is inserted and there is nothing to delete + * @and checks commit is inserted and reject is removed + */ +TEST_F(BufferedCleanupStrategyTest, RejectFirstCase) { + ASSERT_TRUE(strategy_->shouldCreateRound({1, 1})); + ASSERT_EQ(boost::none, strategy_->finalize({1, 1}, makeMockReject())); + + ASSERT_TRUE(strategy_->shouldCreateRound({1, 2})); + + auto removed_rounds = strategy_->finalize({1, 2}, makeMockCommit()); + ASSERT_TRUE(removed_rounds); + ASSERT_EQ(1, removed_rounds->size()); + ASSERT_EQ((Round{1, 1}), removed_rounds->at(0)); +} + +/** + * On new commit case + * @given strategy with committed (1,1) are rejected (2,1) states + * @when commit for (2, 2) is finalized + * @then previous rounds (1, 1) and (2, 1) are removed + */ +TEST_F(BufferedCleanupStrategyTest, OnNewCommitCase) { + strategy_->shouldCreateRound({1, 1}); + ASSERT_FALSE(strategy_->finalize({1, 1}, makeMockCommit())); + + strategy_->shouldCreateRound({2, 1}); + ASSERT_FALSE(strategy_->finalize({1, 2}, makeMockReject())); + + strategy_->shouldCreateRound({2, 2}); + auto removed = strategy_->finalize({2, 2}, makeMockCommit()); + ASSERT_TRUE(removed); + ASSERT_EQ(2, removed->size()); + ASSERT_EQ((Round{1, 1}), removed->at(0)); + ASSERT_EQ((Round{2, 1}), removed->at(1)); +} + +/** + * Many not finalized rounds + * @given initialized strategy + * @and create many uncommitted rounds from (1, 1) to (1, 9) + * @when invoke finalization for (1, 7) + * @then check that all rounds before (1, 7) are removed + */ +TEST_F(BufferedCleanupStrategyTest, FinalizeWhenManyRounds) { + for (auto i = 1u; i < 10; ++i) { + ASSERT_TRUE(strategy_->shouldCreateRound(Round{1, i})); + } + auto removed = strategy_->finalize({1, 7}, makeMockCommit()); + ASSERT_TRUE(removed); + ASSERT_EQ(6, removed->size()); + for (auto i = 0u; i < 6; ++i) { + ASSERT_EQ((Round{1, i + 1}), removed->at(i)); + } +} diff --git a/test/module/irohad/consensus/yac/yac_fixture.hpp b/test/module/irohad/consensus/yac/yac_fixture.hpp index 7de6d3997d..503a88cb00 100644 --- a/test/module/irohad/consensus/yac/yac_fixture.hpp +++ b/test/module/irohad/consensus/yac/yac_fixture.hpp @@ -9,6 +9,7 @@ #include #include "consensus/yac/cluster_order.hpp" +#include "consensus/yac/storage/buffered_cleanup_strategy.hpp" #include "consensus/yac/yac.hpp" #include "module/irohad/consensus/yac/mock_yac_crypto_provider.hpp" @@ -53,7 +54,13 @@ namespace iroha { } void initYac(ClusterOrdering ordering) { - yac = Yac::create(YacVoteStorage(), network, crypto, timer, ordering); + yac = Yac::create( + YacVoteStorage(std::make_shared< + iroha::consensus::yac::BufferedCleanupStrategy>()), + network, + crypto, + timer, + ordering); network->subscribe(yac); } }; diff --git a/test/module/irohad/consensus/yac/yac_simple_cold_case_test.cpp b/test/module/irohad/consensus/yac/yac_simple_cold_case_test.cpp index d2122aa0b2..1faa65e424 100644 --- a/test/module/irohad/consensus/yac/yac_simple_cold_case_test.cpp +++ b/test/module/irohad/consensus/yac/yac_simple_cold_case_test.cpp @@ -147,7 +147,9 @@ TEST_F(YacTest, PropagateCommitBeforeNotifyingSubscribersApplyVote) { }); for (size_t i = 0; i < default_peers.size(); ++i) { - yac->onState({createVote(YacHash{}, std::to_string(i))}); + yac->onState({createVote( + YacHash(iroha::consensus::Round(1, 0), "proposal_hash", "block_hash"), + std::to_string(i))}); } // verify that on_commit subscribers are notified @@ -178,14 +180,17 @@ TEST_F(YacTest, PropagateCommitBeforeNotifyingSubscribersApplyReject) { std::vector commit; + auto yac_hash = + YacHash(iroha::consensus::Round(1, 0), "proposal_hash", "block_hash"); + auto f = (default_peers.size() - 1) / 3; for (size_t i = 0; i < 2 * f; ++i) { - auto vote = createVote(YacHash{}, std::to_string(i)); + auto vote = createVote(yac_hash, std::to_string(i)); yac->onState({vote}); commit.push_back(vote); } - auto vote = createVote(YacHash{}, std::to_string(2 * f + 1)); + auto vote = createVote(yac_hash, std::to_string(2 * f + 1)); RejectMessage reject( {vote, createVote(YacHash(iroha::consensus::Round{1, 1}, "", "my_block"), diff --git a/test/module/irohad/consensus/yac/yac_test_util.hpp b/test/module/irohad/consensus/yac/yac_test_util.hpp index c2731dffc3..20f63e6d90 100644 --- a/test/module/irohad/consensus/yac/yac_test_util.hpp +++ b/test/module/irohad/consensus/yac/yac_test_util.hpp @@ -34,6 +34,16 @@ namespace iroha { inline VoteMessage createVote(YacHash hash, const std::string &pub_key) { VoteMessage vote; + + auto signature = std::make_shared(); + EXPECT_CALL(*signature, publicKey()) + .WillRepeatedly(::testing::ReturnRefOfCopy( + shared_model::crypto::PublicKey(pub_key))); + EXPECT_CALL(*signature, signedData()) + .WillRepeatedly(::testing::ReturnRefOfCopy( + shared_model::crypto::Signed(pub_key))); + + hash.block_signature = signature; vote.hash = std::move(hash); vote.signature = createSig(pub_key); return vote;