Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

Use pubkey as identifier in SignatureSetType #1193

Merged
merged 5 commits into from
Apr 26, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions shared_model/interfaces/common_objects/signable_hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#ifndef IROHA_SHARED_MODEL_SIGNABLE_HASH_HPP
#define IROHA_SHARED_MODEL_SIGNABLE_HASH_HPP

#include <boost/functional/hash.hpp>
#include <unordered_set>

#include "interfaces/common_objects/signature.hpp"
Expand All @@ -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<std::string>{}(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();
}
};
/**
Expand All @@ -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<types::SignatureType, SignableHash>;
using SignatureSetType = std::unordered_set<types::SignatureType,
SignatureSetTypeOps,
SignatureSetTypeOps>;
} // namespace interface
} // namespace shared_model

Expand Down
2 changes: 2 additions & 0 deletions test/module/irohad/consensus/yac/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,6 @@ addtest(supermajority_checker_test supermajority_checker_test.cpp)
target_link_libraries(supermajority_checker_test
yac
model
shared_model_cryptography
shared_model_stateless_validation
)
44 changes: 44 additions & 0 deletions test/module/irohad/consensus/yac/supermajority_checker_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@

#include <gtest/gtest.h>

#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"
#include "utils/polymorphic_wrapper.hpp"

using namespace iroha::consensus::yac;

Expand Down Expand Up @@ -87,3 +95,39 @@ 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<std::shared_ptr<shared_model::interface::Peer>> 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 peer1_key = make_peer_key(std::string(32, '0'));
auto peer2_key = make_peer_key(std::string(32, '1'));

auto make_sig = [](const PublicKey &peer_key, const std::string &sig) {
return shared_model::detail::PolymorphicWrapper<
shared_model::interface::Signature>(
std::static_pointer_cast<shared_model::interface::Signature>(
std::make_shared<shared_model::proto::Signature>(
shared_model::proto::SignatureBuilder()
.publicKey(peer_key)
.signedData(Signed(sig))
.build())));
};
shared_model::interface::SignatureSetType signatures{
make_sig(peer1_key, "1"), make_sig(peer1_key, "2")};

ASSERT_FALSE(hasSupermajority(signatures, peers));
}