Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #ifndef IROHA_SIGNABLE_HPP
7 : #define IROHA_SIGNABLE_HPP
8 :
9 : #include "interfaces/base/model_primitive.hpp"
10 :
11 : #include <boost/functional/hash.hpp>
12 : #include <boost/optional.hpp>
13 : #include <unordered_set>
14 : #include "cryptography/default_hash_provider.hpp"
15 : #include "interfaces/common_objects/range_types.hpp"
16 : #include "interfaces/common_objects/signature.hpp"
17 : #include "interfaces/common_objects/types.hpp"
18 : #include "utils/string_builder.hpp"
19 :
20 : namespace shared_model {
21 :
22 : namespace crypto {
23 : class Signed;
24 : class PublicKey;
25 : } // namespace crypto
26 :
27 : namespace interface {
28 :
29 : /**
30 : * Interface provides signatures and adds them to model object
31 : * @tparam Model - your model
32 : */
33 : template <typename Model,
34 : typename HashProvider = shared_model::crypto::Sha3_256>
35 : class Signable : public ModelPrimitive<Model> {
36 : public:
37 : /**
38 : * @return attached signatures
39 : */
40 : virtual types::SignatureRangeType signatures() const = 0;
41 :
42 : /**
43 : * Attach signature to object
44 : * @param signature - signature object for insertion
45 : * @return true, if signature was added
46 : */
47 : virtual bool addSignature(const crypto::Signed &signed_blob,
48 : const crypto::PublicKey &public_key) = 0;
49 :
50 : /**
51 : * @return time of creation
52 : */
53 : virtual types::TimestampType createdTime() const = 0;
54 :
55 : /**
56 : * @return object payload (everything except signatures)
57 : */
58 : virtual const types::BlobType &payload() const = 0;
59 :
60 : /**
61 : * @return blob representation of object include signatures
62 : */
63 : virtual const types::BlobType &blob() const = 0;
64 :
65 : /**
66 : * Provides comparison based on equality of objects and signatures.
67 : * @param rhs - another model object
68 : * @return true, if objects totally equal
69 : */
70 : bool operator==(const Model &rhs) const override {
71 83 : return equalsByValue(rhs)
72 : // is_permutation consumes ~O(N^2)
73 83 : and std::is_permutation(signatures().begin(),
74 65 : signatures().end(),
75 65 : rhs.signatures().begin());
76 0 : }
77 :
78 : /**
79 : * Provides comaprison based on equality objects only
80 : * @param rhs - another model object
81 : * @return true, if hashes of objects are equal
82 : */
83 : bool equalsByValue(const Model &rhs) const {
84 89 : return this->hash() == rhs.hash();
85 : }
86 :
87 : virtual const types::HashType &hash() const {
88 23083 : if (hash_ == boost::none) {
89 11460 : hash_.emplace(HashProvider::makeHash(payload()));
90 11460 : }
91 23084 : return *hash_;
92 0 : }
93 :
94 : // ------------------------| Primitive override |-------------------------
95 :
96 : std::string toString() const override {
97 0 : return detail::PrettyStringBuilder()
98 0 : .init("Signable")
99 0 : .append("created_time", std::to_string(createdTime()))
100 0 : .appendAll(signatures(),
101 : [](auto &signature) { return signature.toString(); })
102 0 : .finalize();
103 0 : }
104 :
105 : protected:
106 : /**
107 : * Type of set of signatures
108 : *
109 : * Note: we can't use const SignatureType due to unordered_set
110 : * limitations: it requires to have write access for elements for some
111 : * internal operations.
112 : */
113 :
114 : protected:
115 : class SignatureSetTypeOps {
116 : public:
117 : /**
118 : * @param sig is item to find hash from
119 : * @return calculated hash of public key
120 : */
121 : template <typename T>
122 : size_t operator()(const T &sig) const {
123 27399 : return std::hash<std::string>{}(sig.publicKey().hex());
124 : }
125 :
126 : /**
127 : * Function for set elements uniqueness by public key
128 : * @param lhs
129 : * @param rhs
130 : * @return true, if public keys are the same
131 : */
132 : template <typename T>
133 : bool operator()(const T &lhs, const T &rhs) const {
134 112 : return lhs.publicKey() == rhs.publicKey();
135 : }
136 : };
137 :
138 : template <typename T>
139 : using SignatureSetType =
140 : std::unordered_set<T, SignatureSetTypeOps, SignatureSetTypeOps>;
141 :
142 : private:
143 : mutable boost::optional<types::HashType> hash_;
144 : };
145 :
146 : } // namespace interface
147 : } // namespace shared_model
148 :
149 : #endif // IROHA_SIGNABLE_HPP
|