LCOV - code coverage report
Current view: top level - src/bls - bls.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 258 273 94.5 %
Date: 2026-06-25 07:23:43 Functions: 204 219 93.2 %

          Line data    Source code
       1             : // Copyright (c) 2018-2025 The Dash Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #ifndef DASH_CRYPTO_BLS_H
       6             : #define DASH_CRYPTO_BLS_H
       7             : 
       8             : #include <hash.h>
       9             : #include <serialize.h>
      10             : #include <uint256.h>
      11             : #include <util/strencodings.h>
      12             : 
      13             : // bls-dash uses relic, which may define DEBUG and ERROR, which leads to many warnings in some build setups
      14             : #undef ERROR
      15             : #undef DEBUG
      16             : #include <dashbls/bls.hpp>
      17             : #include <dashbls/privatekey.hpp>
      18             : #include <dashbls/elements.hpp>
      19             : #include <dashbls/schemes.hpp>
      20             : #include <dashbls/threshold.hpp>
      21             : #undef DOUBLE
      22             : #undef SEED
      23             : 
      24             : #include <array>
      25             : #include <atomic>
      26             : #include <mutex>
      27             : #include <ranges>
      28             : 
      29             : namespace bls {
      30             :     extern std::atomic<bool> bls_legacy_scheme;
      31             : }
      32             : 
      33             : // reversed BLS12-381
      34             : constexpr int BLS_CURVE_ID_SIZE{32};
      35             : constexpr int BLS_CURVE_SECKEY_SIZE{32};
      36             : constexpr int BLS_CURVE_PUBKEY_SIZE{48};
      37             : constexpr int BLS_CURVE_SIG_SIZE{96};
      38             : 
      39             : class CBLSSignature;
      40             : class CBLSPublicKey;
      41             : 
      42             : template <typename ImplType, size_t _SerSize, typename C>
      43             : class CBLSWrapper
      44             : {
      45             :     friend class CBLSSecretKey;
      46             :     friend class CBLSPublicKey;
      47             :     friend class CBLSSignature;
      48             : 
      49             : protected:
      50             :     ImplType impl;
      51    13987451 :     bool fValid{false};
      52             :     mutable uint256 cachedHash;
      53             : 
      54             : public:
      55             :     static constexpr size_t SerSize = _SerSize;
      56             : 
      57    24861134 :     explicit CBLSWrapper() = default;
      58             : 
      59     5058764 :     CBLSWrapper(const CBLSWrapper& ref) = default;
      60     4064578 :     CBLSWrapper& operator=(const CBLSWrapper& ref) = default;
      61     3113768 :     CBLSWrapper(CBLSWrapper&& ref) noexcept
      62     1556884 :     {
      63     1556882 :         std::swap(impl, ref.impl);
      64     1556882 :         std::swap(fValid, ref.fValid);
      65     1556882 :         std::swap(cachedHash, ref.cachedHash);
      66     1556882 :     }
      67     2275872 :     CBLSWrapper& operator=(CBLSWrapper&& ref) noexcept
      68             :     {
      69     2275872 :         std::swap(impl, ref.impl);
      70     2275872 :         std::swap(fValid, ref.fValid);
      71     2275872 :         std::swap(cachedHash, ref.cachedHash);
      72     2275872 :         return *this;
      73             :     }
      74             : 
      75    18272437 :     virtual ~CBLSWrapper() = default;
      76             : 
      77       75677 :     bool operator==(const C& r) const
      78             :     {
      79       75677 :         return fValid == r.fValid && impl == r.impl;
      80             :     }
      81       16613 :     bool operator!=(const C& r) const
      82             :     {
      83       16613 :         return !((*this) == r);
      84             :     }
      85          15 :     bool operator<(const C& r) const
      86             :     {
      87          15 :         return GetHash() < r.GetHash();
      88             :     }
      89             : 
      90     6724000 :     bool IsValid() const
      91             :     {
      92     6724000 :         return fValid;
      93             :     }
      94             : 
      95     4718807 :     void Reset()
      96             :     {
      97     4718807 :         *(static_cast<C*>(this)) = C();
      98     4718807 :     }
      99             : 
     100     3829187 :     void SetBytes(Span<const uint8_t> vecBytes, const bool specificLegacyScheme)
     101             :     {
     102     3829187 :         if (vecBytes.size() != SerSize) {
     103           0 :             Reset();
     104           0 :             return;
     105             :         }
     106             : 
     107   283233347 :         if (std::ranges::all_of(vecBytes, [](uint8_t c) { return c == 0; })) {
     108     3433638 :             Reset();
     109     3433638 :         } else {
     110             :             try {
     111      395549 :                 impl = ImplType::FromBytes(bls::Bytes(vecBytes.data(), vecBytes.size()), specificLegacyScheme);
     112      395543 :                 if (impl == ImplType()) {
     113           0 :                     Reset();
     114           0 :                     cachedHash.SetNull();
     115           0 :                     return;
     116             :                 }
     117      395542 :                 fValid = true;
     118      395547 :             } catch (...) {
     119           5 :                 Reset();
     120           5 :             }
     121             :         }
     122     3829185 :         cachedHash.SetNull();
     123     3829196 :     }
     124             : 
     125       19044 :     std::vector<uint8_t> ToByteVector(const bool specificLegacyScheme) const
     126             :     {
     127       19044 :         if (!fValid) {
     128           0 :             return std::vector<uint8_t>(SerSize, 0);
     129             :         }
     130       19044 :         return impl.Serialize(specificLegacyScheme);
     131       19044 :     }
     132             : 
     133     4903282 :     std::array<uint8_t, SerSize> ToBytes(const bool specificLegacyScheme) const
     134             :     {
     135     4903282 :         if (!fValid) {
     136     3884568 :             return std::array<uint8_t, SerSize>{};
     137             :         }
     138     1018714 :         return impl.SerializeToArray(specificLegacyScheme);
     139     4903282 :     }
     140             : 
     141      105789 :     const uint256& GetHash() const
     142             :     {
     143      105789 :         if (cachedHash.IsNull()) {
     144       61378 :             cachedHash = ::SerializeHash(*this);
     145       61378 :         }
     146      105789 :         return cachedHash;
     147             :     }
     148             : 
     149        1138 :     bool SetHexStr(const std::string& str, const bool specificLegacyScheme)
     150             :     {
     151        1138 :         if (!IsHex(str)) {
     152           2 :             Reset();
     153           2 :             return false;
     154             :         }
     155        1136 :         auto b = ParseHex(str);
     156        1136 :         if (b.size() != SerSize) {
     157           6 :             Reset();
     158           6 :             return false;
     159             :         }
     160        1130 :         SetBytes(b, specificLegacyScheme);
     161        1130 :         return IsValid();
     162        1138 :     }
     163             : 
     164             :     inline void Serialize(CSizeComputer& s) const
     165             :     {
     166             :         s.seek(SerSize);
     167             :     }
     168             : 
     169             :     template <typename Stream>
     170      741725 :     inline void Serialize(Stream& s, const bool specificLegacyScheme) const
     171             :     {
     172      741725 :         const auto bytes{ToBytes(specificLegacyScheme)};
     173      741725 :         s.write(AsBytes(Span{bytes.data(), SerSize}));
     174      741725 :     }
     175             : 
     176             :     template <typename Stream>
     177      427875 :     inline void Serialize(Stream& s) const
     178             :     {
     179      427875 :         Serialize(s, bls::bls_legacy_scheme.load());
     180      427875 :     }
     181             : 
     182             :     template <typename Stream>
     183     3763902 :     inline void Unserialize(Stream& s, const bool specificLegacyScheme)
     184             :     {
     185     3763902 :         std::array<uint8_t, SerSize> vecBytes{};
     186     3763902 :         s.read(AsWritableBytes(Span{vecBytes.data(), SerSize}));
     187     3763902 :         SetBytes(vecBytes, specificLegacyScheme);
     188             : 
     189     3763902 :         if (!CheckMalleable(vecBytes, specificLegacyScheme)) {
     190             :             // If CheckMalleable failed with specificLegacyScheme, we need to try again with the opposite scheme.
     191             :             // Probably we received the BLS object sent with legacy scheme, but in the meanwhile the fork activated.
     192           0 :             SetBytes(vecBytes, !specificLegacyScheme);
     193           0 :             if (!CheckMalleable(vecBytes, !specificLegacyScheme)) {
     194             :                 // Both attempts failed
     195           0 :                 throw std::ios_base::failure("malleable BLS object");
     196             :             } else {
     197             :                 // Indeed the received vecBytes was in opposite scheme. But we can't keep it (mixing with the new scheme will lead to undefined behavior)
     198             :                 // Therefore, resetting current object (basically marking it as invalid).
     199           0 :                 Reset();
     200             :             }
     201           0 :         }
     202     3763902 :     }
     203             : 
     204             :     template <typename Stream>
     205      478006 :     inline void Unserialize(Stream& s)
     206             :     {
     207      478006 :         Unserialize(s, bls::bls_legacy_scheme.load());
     208      478006 :     }
     209             : 
     210     3826044 :     inline bool CheckMalleable(Span<uint8_t> vecBytes, const bool specificLegacyScheme) const
     211             :     {
     212     3826044 :         const auto bytes{ToBytes(specificLegacyScheme)};
     213     3826044 :         if (memcmp(vecBytes.data(), bytes.data(), SerSize)) {
     214             :             // TODO not sure if this is actually possible with the BLS libs. I'm assuming here that somewhere deep inside
     215             :             // these libs masking might happen, so that 2 different binary representations could result in the same object
     216             :             // representation
     217           0 :             return false;
     218             :         }
     219     3826044 :         return true;
     220     3826044 :     }
     221             : 
     222      302956 :     inline std::string ToString(const bool specificLegacyScheme) const
     223             :     {
     224      302956 :         auto buf = ToBytes(specificLegacyScheme);
     225      302956 :         return HexStr(buf);
     226             :     }
     227             : 
     228      255758 :     inline std::string ToString() const
     229             :     {
     230      255758 :         return ToString(bls::bls_legacy_scheme.load());
     231             :     }
     232             : };
     233             : 
     234             : struct CBLSIdImplicit : public uint256
     235             : {
     236      242856 :     CBLSIdImplicit() = default;
     237      160113 :     CBLSIdImplicit(const uint256& id)
     238       80056 :     {
     239       80057 :         memcpy(begin(), id.begin(), sizeof(uint256));
     240      160113 :     }
     241             :     static CBLSIdImplicit FromBytes(const uint8_t* buffer, const bool fLegacy)
     242             :     {
     243             :         CBLSIdImplicit instance;
     244             :         memcpy(instance.begin(), buffer, sizeof(CBLSIdImplicit));
     245             :         return instance;
     246             :     }
     247             :     [[nodiscard]] std::vector<uint8_t> Serialize(const bool fLegacy) const
     248             :     {
     249             :         return {begin(), end()};
     250             :     }
     251        7345 :     [[nodiscard]] std::array<uint8_t, 32> SerializeToArray(const bool fLegacy) const { return m_data; }
     252             : };
     253             : 
     254             : class CBLSId : public CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>
     255             : {
     256             : public:
     257             :     using CBLSWrapper::operator=;
     258             :     using CBLSWrapper::operator==;
     259             :     using CBLSWrapper::operator!=;
     260             :     using CBLSWrapper::CBLSWrapper;
     261             : 
     262       63911 :     CBLSId() = default;
     263             :     explicit CBLSId(const uint256& nHash);
     264             : };
     265             : 
     266             : //! CBLSSecretKey is invariant to BLS scheme for Creation / Serialization / Deserialization
     267             : class CBLSSecretKey : public CBLSWrapper<bls::PrivateKey, BLS_CURVE_SECKEY_SIZE, CBLSSecretKey>
     268             : {
     269             : public:
     270             :     using CBLSWrapper::operator=;
     271             :     using CBLSWrapper::operator==;
     272             :     using CBLSWrapper::operator!=;
     273             :     using CBLSWrapper::CBLSWrapper;
     274             : 
     275      153637 :     CBLSSecretKey() = default;
     276        1350 :     explicit CBLSSecretKey(Span<const unsigned char> vecBytes)
     277        1350 :     {
     278             :         // The second param here is not 'is_legacy', but `modOrder`
     279         675 :         SetBytes(vecBytes, false);
     280        1350 :     }
     281      557819 :     CBLSSecretKey(const CBLSSecretKey&) = default;
     282       13308 :     CBLSSecretKey& operator=(const CBLSSecretKey&) = default;
     283             : 
     284             :     void AggregateInsecure(const CBLSSecretKey& o);
     285             :     static CBLSSecretKey AggregateInsecure(Span<CBLSSecretKey> sks);
     286             : 
     287             : #ifndef BUILD_BITCOIN_INTERNAL
     288             :     //! MakeNewKey() is invariant to BLS scheme
     289             :     void MakeNewKey();
     290             : #endif
     291             :     //! SecretKeyShare() is invariant to BLS scheme
     292             :     bool SecretKeyShare(Span<CBLSSecretKey> msk, const CBLSId& id);
     293             : 
     294             :     //! GetPublicKey() is invariant to BLS scheme
     295             :     [[nodiscard]] CBLSPublicKey GetPublicKey() const;
     296             :     [[nodiscard]] CBLSSignature Sign(const uint256& hash, const bool specificLegacyScheme) const;
     297             : };
     298             : 
     299             : class CBLSPublicKey : public CBLSWrapper<bls::G1Element, BLS_CURVE_PUBKEY_SIZE, CBLSPublicKey>
     300             : {
     301             :     friend class CBLSSecretKey;
     302             :     friend class CBLSSignature;
     303             : 
     304             : public:
     305             :     using CBLSWrapper::operator=;
     306             :     using CBLSWrapper::operator==;
     307             :     using CBLSWrapper::operator!=;
     308             :     using CBLSWrapper::CBLSWrapper;
     309             : 
     310    12060908 :     CBLSPublicKey() = default;
     311             : 
     312             :     void AggregateInsecure(const CBLSPublicKey& o);
     313             :     static CBLSPublicKey AggregateInsecure(Span<CBLSPublicKey> pks);
     314             : 
     315             :     bool PublicKeyShare(Span<CBLSPublicKey> mpk, const CBLSId& id);
     316             :     bool DHKeyExchange(const CBLSSecretKey& sk, const CBLSPublicKey& pk);
     317             : 
     318             : };
     319             : 
     320             : class CBLSPublicKeyVersionWrapper {
     321             : private:
     322             :     CBLSPublicKey& obj;
     323             :     bool legacy;
     324             : public:
     325     2456910 :     CBLSPublicKeyVersionWrapper(CBLSPublicKey& obj, bool legacy)
     326     1228455 :             : obj(obj)
     327     1228455 :             , legacy(legacy)
     328     2456910 :     {}
     329             :     template <typename Stream>
     330      123176 :     inline void Serialize(Stream& s) const {
     331      123176 :         obj.Serialize(s, legacy);
     332      123176 :     }
     333             :     template <typename Stream>
     334     1105278 :     inline void Unserialize(Stream& s) {
     335     1105278 :         obj.Unserialize(s, legacy);
     336     1105278 :     }
     337             : };
     338             : 
     339             : class CBLSSignature : public CBLSWrapper<bls::G2Element, BLS_CURVE_SIG_SIZE, CBLSSignature>
     340             : {
     341             :     friend class CBLSSecretKey;
     342             : 
     343             : public:
     344             :     using CBLSWrapper::operator==;
     345             :     using CBLSWrapper::operator!=;
     346             :     using CBLSWrapper::CBLSWrapper;
     347             : 
     348    12421239 :     CBLSSignature() = default;
     349           2 :     explicit CBLSSignature(Span<const unsigned char> bytes, bool is_serialized_legacy)
     350           2 :     {
     351           1 :         SetBytes(bytes, is_serialized_legacy);
     352           2 :     }
     353     8638931 :     CBLSSignature(const CBLSSignature&) = default;
     354     3108231 :     CBLSSignature& operator=(const CBLSSignature&) = default;
     355             : 
     356             :     void AggregateInsecure(const CBLSSignature& o);
     357             :     static CBLSSignature AggregateInsecure(Span<CBLSSignature> sigs);
     358             :     static CBLSSignature AggregateSecure(Span<CBLSSignature> sigs, Span<CBLSPublicKey> pks, const uint256& hash);
     359             : 
     360             :     void SubInsecure(const CBLSSignature& o);
     361             :     [[nodiscard]] bool VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash, const bool specificLegacyScheme) const;
     362             :     [[nodiscard]] bool VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const;
     363             :     [[nodiscard]] bool VerifyInsecureAggregated(Span<CBLSPublicKey> pubKeys, Span<uint256> hashes) const;
     364             : 
     365             :     [[nodiscard]] bool VerifySecureAggregated(Span<CBLSPublicKey> pks, const uint256& hash) const;
     366             : 
     367             :     bool Recover(Span<CBLSSignature> sigs, Span<CBLSId> ids);
     368             : };
     369             : 
     370             : class CBLSSignatureVersionWrapper {
     371             : private:
     372             :     CBLSSignature& obj;
     373             :     bool legacy;
     374             : public:
     375     4742574 :     CBLSSignatureVersionWrapper(CBLSSignature& obj, bool legacy)
     376     2371287 :             : obj(obj)
     377     2371287 :             , legacy(legacy)
     378     4742574 :     {}
     379             :     template <typename Stream>
     380      190674 :     inline void Serialize(Stream& s) const {
     381      190674 :         obj.Serialize(s, legacy);
     382      190674 :     }
     383             :     template <typename Stream>
     384     2180613 :     inline void Unserialize(Stream& s) {
     385     2180613 :         obj.Unserialize(s, legacy);
     386     2180613 :     }
     387             : };
     388             : 
     389             : #ifndef BUILD_BITCOIN_INTERNAL
     390             : template<typename BLSObject>
     391             : class CBLSLazyWrapper
     392             : {
     393             : private:
     394             :     mutable std::mutex mutex;
     395             : 
     396     2674849 :     mutable std::array<uint8_t, BLSObject::SerSize> vecBytes{};
     397             : 
     398             :     mutable BLSObject obj;
     399     2674849 :     mutable bool objInitialized{false};
     400             : 
     401             :     // Indicates if the value contained in vecBytes is valid
     402     2674849 :     mutable bool bufValid{false};
     403     2196724 :     mutable bool bufLegacyScheme{true};
     404             : 
     405             :     mutable uint256 hash;
     406             : 
     407             : public:
     408     1912503 :     CBLSLazyWrapper() :
     409      478125 :         bufLegacyScheme(bls::bls_legacy_scheme.load())
     410     1434378 :     {}
     411             : 
     412     8786898 :     explicit CBLSLazyWrapper(const CBLSLazyWrapper& r)
     413     4393450 :     {
     414     2196719 :         *this = r;
     415     4393450 :     }
     416     5349517 :     virtual ~CBLSLazyWrapper() = default;
     417             : 
     418     2205128 :     CBLSLazyWrapper& operator=(const CBLSLazyWrapper& r)
     419             :     {
     420     2205128 :         std::unique_lock<std::mutex> l(r.mutex);
     421     2205128 :         bufValid = r.bufValid;
     422     2205128 :         bufLegacyScheme = r.bufLegacyScheme;
     423     2205128 :         if (r.bufValid) {
     424     1387039 :             vecBytes = r.vecBytes;
     425     1387039 :         } else {
     426      818089 :             std::fill(vecBytes.begin(), vecBytes.end(), 0);
     427             :         }
     428     2205085 :         objInitialized = r.objInitialized;
     429     2205085 :         if (r.objInitialized) {
     430      939590 :             obj = r.obj;
     431      939590 :         } else {
     432     1265495 :             obj.Reset();
     433             :         }
     434     2205042 :         hash = r.hash;
     435             :         return *this;
     436     2205128 :     }
     437             : 
     438             :     inline void Serialize(CSizeComputer& s) const
     439             :     {
     440             :         s.seek(BLSObject::SerSize);
     441             :     }
     442             : 
     443             :     template<typename Stream>
     444      278258 :     inline void Serialize(Stream& s, const bool specificLegacyScheme) const
     445             :     {
     446      278258 :         std::unique_lock<std::mutex> l(mutex);
     447      278258 :         if (!objInitialized && !bufValid) {
     448         907 :             std::fill(vecBytes.begin(), vecBytes.end(), 0);
     449      278258 :         } else if (!bufValid || (bufLegacyScheme != specificLegacyScheme)) {
     450       32570 :             vecBytes = obj.ToBytes(specificLegacyScheme);
     451       32570 :             bufValid = true;
     452       32570 :             bufLegacyScheme = specificLegacyScheme;
     453       32570 :             hash.SetNull();
     454       32570 :         }
     455      278258 :         s.write(MakeByteSpan(vecBytes));
     456      278258 :     }
     457             : 
     458             :     template<typename Stream>
     459      222315 :     inline void Serialize(Stream& s) const
     460             :     {
     461      222315 :         Serialize(s, bufLegacyScheme);
     462      222315 :     }
     463             : 
     464             :     template<typename Stream>
     465       92239 :     inline void Unserialize(Stream& s, const bool specificLegacyScheme) const
     466             :     {
     467       92239 :         std::unique_lock<std::mutex> l(mutex);
     468       92239 :         s.read(AsWritableBytes(Span{vecBytes.data(), BLSObject::SerSize}));
     469      186371 :         bufValid = std::any_of(vecBytes.begin(), vecBytes.end(), [](uint8_t c) { return c != 0; });
     470       92239 :         bufLegacyScheme = specificLegacyScheme;
     471       92239 :         objInitialized = false;
     472       92239 :         hash.SetNull();
     473       92239 :     }
     474             : 
     475             :     template<typename Stream>
     476       66384 :     inline void Unserialize(Stream& s) const
     477             :     {
     478       66384 :         Unserialize(s, bufLegacyScheme);
     479       66384 :     }
     480             : 
     481       27757 :     void Set(const BLSObject& _obj, const bool specificLegacyScheme)
     482             :     {
     483       27757 :         std::unique_lock<std::mutex> l(mutex);
     484       27757 :         bufValid = false;
     485       27757 :         bufLegacyScheme = specificLegacyScheme;
     486       27757 :         objInitialized = true;
     487       27757 :         obj = _obj;
     488       27757 :         hash.SetNull();
     489       27757 :     }
     490      271509 :     const BLSObject& Get() const
     491             :     {
     492      271509 :         std::unique_lock<std::mutex> l(mutex);
     493      271509 :         static BLSObject invalidObj;
     494      271509 :         if (!bufValid && !objInitialized) {
     495        2398 :             return invalidObj;
     496             :         }
     497      269111 :         if (!objInitialized) {
     498       62161 :             obj.SetBytes(vecBytes, bufLegacyScheme);
     499       62159 :             if (!obj.IsValid()) {
     500           4 :                 bufValid = false;
     501           4 :                 return invalidObj;
     502             :             }
     503       62154 :             if (!obj.CheckMalleable(vecBytes, bufLegacyScheme)) {
     504           0 :                 bufValid = false;
     505           0 :                 return invalidObj;
     506             :             }
     507       62155 :             objInitialized = true;
     508       62155 :         }
     509      269105 :         return obj;
     510      271511 :     }
     511             : 
     512     1526972 :     bool operator==(const CBLSLazyWrapper& r) const
     513             :     {
     514     1526972 :         if (&r == this) return true;
     515             :         {
     516     1472395 :             std::scoped_lock lock(mutex, r.mutex);
     517             :             // If neither bufValid or objInitialized are set, then the object is the default object.
     518     1472395 :             const bool is_default{!bufValid && !objInitialized};
     519     1472395 :             const bool r_is_default{!r.bufValid && !r.objInitialized};
     520             :             // If both are default; they are equal.
     521     1472395 :             if (is_default && r_is_default) return true;
     522             :             // If one is default and the other isn't, we are not equal
     523     1468434 :             if (is_default != r_is_default) return false;
     524             : 
     525     1313664 :             if (bufValid && r.bufValid && bufLegacyScheme == r.bufLegacyScheme) {
     526     1313660 :                 return vecBytes == r.vecBytes;
     527             :             }
     528           4 :             if (objInitialized && r.objInitialized) {
     529           4 :                 return obj == r.obj;
     530             :             }
     531     1472395 :         }
     532           0 :         return Get() == r.Get();
     533     1526972 :     }
     534             : 
     535      358819 :     bool operator!=(const CBLSLazyWrapper& r) const
     536             :     {
     537      358819 :         return !(*this == r);
     538             :     }
     539             : 
     540        8311 :     uint256 GetHash() const
     541             :     {
     542        8311 :         std::unique_lock<std::mutex> l(mutex);
     543        8311 :         if (!objInitialized && !bufValid) {
     544          11 :             std::fill(vecBytes.begin(), vecBytes.end(), 0);
     545          11 :             hash.SetNull();
     546        8311 :         } else if (!bufValid) {
     547           2 :             vecBytes = obj.ToBytes(bufLegacyScheme);
     548           2 :             bufValid = true;
     549           2 :             hash.SetNull();
     550           2 :         }
     551        8311 :         if (hash.IsNull()) {
     552        7064 :             CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
     553        7064 :             ss.write(MakeByteSpan(vecBytes));
     554        7064 :             hash = ss.GetHash();
     555        7064 :         }
     556        8311 :         return hash;
     557        8311 :     }
     558             : 
     559        4589 :     bool IsLegacy() const
     560             :     {
     561        4589 :         return bufLegacyScheme;
     562             :     }
     563             : 
     564           1 :     void SetLegacy(bool specificLegacyScheme)
     565             :     {
     566           1 :         bufLegacyScheme = specificLegacyScheme;
     567           1 :     }
     568             : 
     569       26426 :     std::string ToString() const
     570             :     {
     571       26426 :         return Get().ToString(bufLegacyScheme);
     572             :     }
     573             : };
     574             : using CBLSLazySignature = CBLSLazyWrapper<CBLSSignature>;
     575             : using CBLSLazyPublicKey = CBLSLazyWrapper<CBLSPublicKey>;
     576             : 
     577             : class CBLSLazyPublicKeyVersionWrapper {
     578             : private:
     579             :     CBLSLazyPublicKey& obj;
     580             :     bool legacy;
     581             : public:
     582      163592 :     CBLSLazyPublicKeyVersionWrapper(CBLSLazyPublicKey& obj, bool legacy)
     583       81796 :             : obj(obj)
     584       81796 :             , legacy(legacy)
     585      163592 :     {}
     586             :     template <typename Stream>
     587       55942 :     inline void Serialize(Stream& s) const {
     588       55942 :         obj.Serialize(s, legacy);
     589       55942 :     }
     590             :     template <typename Stream>
     591       25854 :     inline void Unserialize(Stream& s) {
     592       25854 :         obj.Unserialize(s, legacy);
     593       25854 :     }
     594             : };
     595             : #endif
     596             : 
     597             : using BLSVerificationVectorPtr = std::shared_ptr<std::vector<CBLSPublicKey>>;
     598             : 
     599             : bool BLSInit();
     600             : 
     601             : #endif // DASH_CRYPTO_BLS_H

Generated by: LCOV version 1.16