diff --git a/shared_model/interfaces/common_objects/signable_hash.hpp b/shared_model/interfaces/common_objects/signable_hash.hpp index 40c091533b..da16dd7cc4 100644 --- a/shared_model/interfaces/common_objects/signable_hash.hpp +++ b/shared_model/interfaces/common_objects/signable_hash.hpp @@ -18,7 +18,6 @@ #ifndef IROHA_SHARED_MODEL_SIGNABLE_HASH_HPP #define IROHA_SHARED_MODEL_SIGNABLE_HASH_HPP -#include #include #include "interfaces/common_objects/signature.hpp" @@ -28,23 +27,28 @@ namespace shared_model { namespace interface { /** - * Hash class for SigWrapper type. It's required since std::unordered_set - * uses hash inside and it should be declared explicitly for user-defined - * types. + * Property class for SignatureSetType that contains hashing and comparison + * operations. */ - class SignableHash { + class SignatureSetTypeOps { public: /** - * Operator which actually calculates hash. Uses boost::hash_combine to - * calculate hash from several fields. - * @param sig - item to find hash from - * @return calculated hash + * @param sig is item to find hash from + * @return calculated hash of public key */ size_t operator()(const types::SignatureType &sig) const { - std::size_t seed = 0; - boost::hash_combine(seed, sig->publicKey().blob()); - boost::hash_combine(seed, sig->signedData().blob()); - return seed; + return std::hash{}(sig->publicKey().hex()); + } + + /** + * Function for set elements uniqueness by public key + * @param lhs + * @param rhs + * @return true, if public keys are the same + */ + bool operator()(const types::SignatureType &lhs, + const types::SignatureType &rhs) const { + return lhs->publicKey() == rhs->publicKey(); } }; /** @@ -54,8 +58,9 @@ namespace shared_model { * limitations: it requires to have write access for elements for some * internal operations. */ - using SignatureSetType = - std::unordered_set; + using SignatureSetType = std::unordered_set; } // namespace interface } // namespace shared_model diff --git a/test/module/irohad/consensus/yac/CMakeLists.txt b/test/module/irohad/consensus/yac/CMakeLists.txt index d216caa87a..3cf40ea7c0 100644 --- a/test/module/irohad/consensus/yac/CMakeLists.txt +++ b/test/module/irohad/consensus/yac/CMakeLists.txt @@ -102,4 +102,6 @@ target_link_libraries(yac_crypto_provider_test addtest(supermajority_checker_test supermajority_checker_test.cpp) target_link_libraries(supermajority_checker_test yac + shared_model_cryptography + shared_model_stateless_validation ) diff --git a/test/module/irohad/consensus/yac/supermajority_checker_test.cpp b/test/module/irohad/consensus/yac/supermajority_checker_test.cpp index 4ff61d4624..1714cb3c90 100644 --- a/test/module/irohad/consensus/yac/supermajority_checker_test.cpp +++ b/test/module/irohad/consensus/yac/supermajority_checker_test.cpp @@ -17,7 +17,14 @@ #include +#include "backend/protobuf/common_objects/signature.hpp" +#include "builders/protobuf/common_objects/proto_peer_builder.hpp" +#include "builders/protobuf/common_objects/proto_signature_builder.hpp" #include "consensus/yac/impl/supermajority_checker_impl.hpp" +#include "cryptography/public_key.hpp" +#include "cryptography/signed.hpp" +#include "interfaces/common_objects/peer.hpp" +#include "interfaces/common_objects/types.hpp" #include "logger/logger.hpp" using namespace iroha::consensus::yac; @@ -87,3 +94,38 @@ TEST_F(SupermajorityCheckerTest, RejectProofNegativeCase) { ASSERT_FALSE(hasReject(5, 6, 7)); ASSERT_FALSE(hasReject(6, 6, 7)); } + +/** + * @given a pair of peers and a pair different signatures by the first peer + * @when hasSupermajority is called + * @then it return false + */ +TEST_F(SupermajorityCheckerTest, PublicKeyUniqueness) { + using namespace shared_model::crypto; + std::vector> peers; + auto make_peer_key = [&peers](const std::string &key) { + PublicKey pub_key(key); + peers.emplace_back(clone(shared_model::proto::PeerBuilder() + .address("localhost") + .pubkey(pub_key) + .build())); + return pub_key; + }; + + auto peer_key = make_peer_key(std::string(32, '0')); + make_peer_key(std::string(32, '1')); + + auto make_sig = [](const PublicKey &peer_key, const std::string &sig) { + return shared_model::interface::types::SignatureType( + std::static_pointer_cast( + std::make_shared( + shared_model::proto::SignatureBuilder() + .publicKey(peer_key) + .signedData(Signed(sig)) + .build()))); + }; + shared_model::interface::SignatureSetType signatures{make_sig(peer_key, "1"), + make_sig(peer_key, "2")}; + + ASSERT_FALSE(hasSupermajority(signatures, peers)); +}