LCOV - code coverage report
Current view: top level - src/evo - deterministicmns.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 174 182 95.6 %
Date: 2025-02-23 09:33:43 Functions: 61 63 96.8 %

          Line data    Source code
       1             : // Copyright (c) 2018-2021 The Dash Core developers
       2             : // Copyright (c) 2021 The PIVX Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef PIVX_EVO_DETERMINISTICMNS_H
       7             : #define PIVX_EVO_DETERMINISTICMNS_H
       8             : 
       9             : #include "arith_uint256.h"
      10             : #include "bls/bls_wrapper.h"
      11             : #include "dbwrapper.h"
      12             : #include "evo/evodb.h"
      13             : #include "evo/providertx.h"
      14             : #include "llmq/quorums_commitment.h"
      15             : #include "netaddress.h"
      16             : #include "saltedhasher.h"
      17             : #include "serialize.h"
      18             : #include "sync.h"
      19             : #include "version.h"
      20             : 
      21             : #include <immer/map.hpp>
      22             : #include <immer/map_transient.hpp>
      23             : 
      24             : #include <unordered_map>
      25             : 
      26             : class CBlock;
      27             : class CBlockIndex;
      28             : class CValidationState;
      29             : 
      30             : class CDeterministicMNState
      31             : {
      32             : public:
      33             :     int nRegisteredHeight{-1};
      34             :     int nLastPaidHeight{0};
      35             :     int nPoSePenalty{0};
      36             :     int nPoSeRevivedHeight{-1};
      37             :     int nPoSeBanHeight{-1};
      38             :     uint16_t nRevocationReason{ProUpRevPL::REASON_NOT_SPECIFIED};
      39             : 
      40             :     // the block hash X blocks after registration, used in quorum calculations
      41             :     uint256 confirmedHash;
      42             :     // sha256(proTxHash, confirmedHash) to speed up quorum calculations
      43             :     // please note that this is NOT a double-sha256 hash
      44             :     uint256 confirmedHashWithProRegTxHash;
      45             : 
      46             :     CKeyID keyIDOwner;
      47             :     CBLSLazyPublicKey pubKeyOperator;
      48             :     CKeyID keyIDVoting;
      49             :     CService addr;
      50             :     CScript scriptPayout;
      51             :     CScript scriptOperatorPayout;
      52             : 
      53             : public:
      54       46955 :     CDeterministicMNState() {}
      55         480 :     explicit CDeterministicMNState(const ProRegPL& pl)
      56        2400 :     {
      57         480 :         keyIDOwner = pl.keyIDOwner;
      58         480 :         pubKeyOperator.Set(pl.pubKeyOperator);
      59         480 :         keyIDVoting = pl.keyIDVoting;
      60         480 :         addr = pl.addr;
      61         480 :         scriptPayout = pl.scriptPayout;
      62         480 :         scriptOperatorPayout = pl.scriptOperatorPayout;
      63         480 :     }
      64             :     template <typename Stream>
      65          90 :     CDeterministicMNState(deserialize_type, Stream& s) { s >> *this; }
      66             : 
      67        2418 :     SERIALIZE_METHODS(CDeterministicMNState, obj)
      68             :     {
      69        1209 :         READWRITE(obj.nRegisteredHeight);
      70        1209 :         READWRITE(obj.nLastPaidHeight);
      71        1209 :         READWRITE(obj.nPoSePenalty);
      72        1209 :         READWRITE(obj.nPoSeRevivedHeight);
      73        1209 :         READWRITE(obj.nPoSeBanHeight);
      74        1209 :         READWRITE(obj.nRevocationReason);
      75        1209 :         READWRITE(obj.confirmedHash);
      76        1209 :         READWRITE(obj.confirmedHashWithProRegTxHash);
      77        1209 :         READWRITE(obj.keyIDOwner);
      78        1209 :         READWRITE(obj.pubKeyOperator);
      79        1209 :         READWRITE(obj.keyIDVoting);
      80        1209 :         READWRITE(obj.addr);
      81        1209 :         READWRITE(obj.scriptPayout);
      82        1209 :         READWRITE(obj.scriptOperatorPayout);
      83        1209 :     }
      84             : 
      85          52 :     void ResetOperatorFields()
      86             :     {
      87         104 :         pubKeyOperator.Set(CBLSPublicKey());
      88          52 :         addr = CService();
      89          52 :         scriptOperatorPayout = CScript();
      90          52 :         nRevocationReason = ProUpRevPL::REASON_NOT_SPECIFIED;
      91          52 :     }
      92          52 :     void BanIfNotBanned(int height)
      93             :     {
      94          52 :         if (nPoSeBanHeight == -1) {
      95          34 :             nPoSeBanHeight = height;
      96             :         }
      97             :     }
      98         475 :     void UpdateConfirmedHash(const uint256& _proTxHash, const uint256& _confirmedHash)
      99             :     {
     100         475 :         confirmedHash = _confirmedHash;
     101         475 :         CSHA256 h;
     102         475 :         h.Write(_proTxHash.begin(), _proTxHash.size());
     103         475 :         h.Write(_confirmedHash.begin(), _confirmedHash.size());
     104         475 :         h.Finalize(confirmedHashWithProRegTxHash.begin());
     105         475 :     }
     106             : 
     107             : public:
     108             :     std::string ToString() const;
     109             :     void ToJson(UniValue& obj) const;
     110             : };
     111             : typedef std::shared_ptr<CDeterministicMNState> CDeterministicMNStatePtr;
     112             : typedef std::shared_ptr<const CDeterministicMNState> CDeterministicMNStateCPtr;
     113             : 
     114       82913 : class CDeterministicMNStateDiff
     115             : {
     116             : public:
     117             :     enum Field : uint32_t {
     118             :         Field_nRegisteredHeight                 = 0x0001,
     119             :         Field_nLastPaidHeight                   = 0x0002,
     120             :         Field_nPoSePenalty                      = 0x0004,
     121             :         Field_nPoSeRevivedHeight                = 0x0008,
     122             :         Field_nPoSeBanHeight                    = 0x0010,
     123             :         Field_nRevocationReason                 = 0x0020,
     124             :         Field_confirmedHash                     = 0x0040,
     125             :         Field_confirmedHashWithProRegTxHash     = 0x0080,
     126             :         Field_keyIDOwner                        = 0x0100,
     127             :         Field_pubKeyOperator                     = 0x0200,
     128             :         Field_keyIDVoting                       = 0x0400,
     129             :         Field_addr                              = 0x0800,
     130             :         Field_scriptPayout                      = 0x1000,
     131             :         Field_scriptOperatorPayout              = 0x2000,
     132             :     };
     133             : 
     134             : #define DMN_STATE_DIFF_ALL_FIELDS \
     135             :     DMN_STATE_DIFF_LINE(nRegisteredHeight) \
     136             :     DMN_STATE_DIFF_LINE(nLastPaidHeight) \
     137             :     DMN_STATE_DIFF_LINE(nPoSePenalty) \
     138             :     DMN_STATE_DIFF_LINE(nPoSeRevivedHeight) \
     139             :     DMN_STATE_DIFF_LINE(nPoSeBanHeight) \
     140             :     DMN_STATE_DIFF_LINE(nRevocationReason) \
     141             :     DMN_STATE_DIFF_LINE(confirmedHash) \
     142             :     DMN_STATE_DIFF_LINE(confirmedHashWithProRegTxHash) \
     143             :     DMN_STATE_DIFF_LINE(keyIDOwner) \
     144             :     DMN_STATE_DIFF_LINE(pubKeyOperator) \
     145             :     DMN_STATE_DIFF_LINE(keyIDVoting) \
     146             :     DMN_STATE_DIFF_LINE(addr) \
     147             :     DMN_STATE_DIFF_LINE(scriptPayout) \
     148             :     DMN_STATE_DIFF_LINE(scriptOperatorPayout)
     149             : 
     150             : public:
     151             :     uint32_t fields{0};
     152             :     // we reuse the state class, but only the members as noted by fields are valid
     153             :     CDeterministicMNState state;
     154             : 
     155             : public:
     156         134 :     CDeterministicMNStateDiff() {}
     157        9257 :     CDeterministicMNStateDiff(const CDeterministicMNState& a, const CDeterministicMNState& b)
     158        9257 :     {
     159             : #define DMN_STATE_DIFF_LINE(f) if (a.f != b.f) { state.f = b.f; fields |= Field_##f; }
     160        9257 :         DMN_STATE_DIFF_ALL_FIELDS
     161             : #undef DMN_STATE_DIFF_LINE
     162        9257 :     }
     163             : 
     164       54770 :     SERIALIZE_METHODS(CDeterministicMNStateDiff, obj)
     165             :     {
     166       27385 :         READWRITE(VARINT(obj.fields));
     167             : #define DMN_STATE_DIFF_LINE(f) if (obj.fields & Field_##f) READWRITE(obj.state.f);
     168       27385 :         DMN_STATE_DIFF_ALL_FIELDS
     169             : #undef DMN_STATE_DIFF_LINE
     170       27385 :     }
     171             : 
     172       10762 :     void ApplyToState(CDeterministicMNState& target) const
     173             :     {
     174             : #define DMN_STATE_DIFF_LINE(f) if (fields & Field_##f) target.f = state.f;
     175       10810 :         DMN_STATE_DIFF_ALL_FIELDS
     176             : #undef DMN_STATE_DIFF_LINE
     177       10762 :     }
     178             : };
     179             : 
     180       50452 : class CDeterministicMN
     181             : {
     182             : private:
     183             :     uint64_t internalId{std::numeric_limits<uint64_t>::max()};
     184             : 
     185             : public:
     186             :     CDeterministicMN() = delete; // no default constructor, must specify internalId
     187        4972 :     explicit CDeterministicMN(uint64_t _internalId) : internalId(_internalId)
     188             :     {
     189             :         // only non-initial values
     190        2486 :         assert(_internalId != std::numeric_limits<uint64_t>::max());
     191        2486 :     }
     192             :     // TODO: can be removed in a future version
     193             :     CDeterministicMN(const CDeterministicMN& mn, uint64_t _internalId) : CDeterministicMN(mn) {
     194             :         // only non-initial values
     195             :         assert(_internalId != std::numeric_limits<uint64_t>::max());
     196             :         internalId = _internalId;
     197             :     }
     198             : 
     199             :     template <typename Stream>
     200          18 :     CDeterministicMN(deserialize_type, Stream& s)
     201          36 :     {
     202          18 :         s >> *this;
     203          18 :     }
     204             : 
     205             :     uint256 proTxHash;
     206             :     COutPoint collateralOutpoint;
     207             :     uint16_t nOperatorReward;
     208             :     CDeterministicMNStateCPtr pdmnState;
     209             : 
     210             : public:
     211        2418 :     SERIALIZE_METHODS(CDeterministicMN, obj)
     212             :     {
     213        1209 :         READWRITE(obj.proTxHash);
     214        1209 :         READWRITE(VARINT(obj.internalId));
     215        1209 :         READWRITE(obj.collateralOutpoint);
     216        1209 :         READWRITE(obj.nOperatorReward);
     217        1209 :         READWRITE(obj.pdmnState);
     218        1209 :     }
     219             : 
     220             :     uint64_t GetInternalId() const;
     221      234734 :     bool IsPoSeBanned() const { return pdmnState->nPoSeBanHeight != -1; }
     222             : 
     223             :     std::string ToString() const;
     224             :     void ToJson(UniValue& obj) const;
     225             : };
     226             : 
     227             : typedef std::shared_ptr<const CDeterministicMN> CDeterministicMNCPtr;
     228             : 
     229             : class CDeterministicMNListDiff;
     230             : 
     231             : template <typename Stream, typename K, typename T, typename Hash, typename Equal>
     232             : void SerializeImmerMap(Stream& os, const immer::map<K, T, Hash, Equal>& m)
     233             : {
     234             :     WriteCompactSize(os, m.size());
     235             :     for (typename immer::map<K, T, Hash, Equal>::const_iterator mi = m.begin(); mi != m.end(); ++mi)
     236             :         Serialize(os, (*mi));
     237             : }
     238             : 
     239             : template <typename Stream, typename K, typename T, typename Hash, typename Equal>
     240             : void UnserializeImmerMap(Stream& is, immer::map<K, T, Hash, Equal>& m)
     241             : {
     242             :     m = immer::map<K, T, Hash, Equal>();
     243             :     unsigned int nSize = ReadCompactSize(is);
     244             :     for (unsigned int i = 0; i < nSize; i++) {
     245             :         std::pair<K, T> item;
     246             :         Unserialize(is, item);
     247             :         m = m.set(item.first, item.second);
     248             :     }
     249             : }
     250             : 
     251             : // For some reason the compiler is not able to choose the correct Serialize/Deserialize methods without a specialized
     252             : // version of SerReadWrite. It otherwise always chooses the version that calls a.Serialize()
     253             : template<typename Stream, typename K, typename T, typename Hash, typename Equal>
     254             : inline void SerReadWrite(Stream& s, const immer::map<K, T, Hash, Equal>& m, CSerActionSerialize ser_action)
     255             : {
     256             :     ::SerializeImmerMap(s, m);
     257             : }
     258             : 
     259             : template<typename Stream, typename K, typename T, typename Hash, typename Equal>
     260             : inline void SerReadWrite(Stream& s, immer::map<K, T, Hash, Equal>& obj, CSerActionUnserialize ser_action)
     261             : {
     262             :     ::UnserializeImmerMap(s, obj);
     263             : }
     264             : 
     265       27438 : class CDeterministicMNList
     266             : {
     267             : public:
     268             :     typedef immer::map<uint256, CDeterministicMNCPtr> MnMap;
     269             :     typedef immer::map<uint64_t, uint256> MnInternalIdMap;
     270             :     typedef immer::map<uint256, std::pair<uint256, uint32_t> > MnUniquePropertyMap;
     271             : 
     272             : private:
     273             :     uint256 blockHash;
     274             :     int nHeight{-1};
     275             :     uint32_t nTotalRegisteredCount{0};
     276             :     MnMap mnMap;
     277             :     MnInternalIdMap mnInternalIdMap;
     278             : 
     279             :     // map of unique properties like address and keys
     280             :     // we keep track of this as checking for duplicates would otherwise be painfully slow
     281             :     MnUniquePropertyMap mnUniquePropertyMap;
     282             : 
     283             : public:
     284      831454 :     CDeterministicMNList() {}
     285           0 :     explicit CDeterministicMNList(const uint256& _blockHash, int _height, uint32_t _totalRegisteredCount) :
     286             :         blockHash(_blockHash),
     287             :         nHeight(_height),
     288           0 :         nTotalRegisteredCount(_totalRegisteredCount)
     289             :     {
     290           0 :     }
     291             : 
     292             :     template<typename Stream>
     293         214 :     void Serialize(Stream& s) const
     294             :     {
     295         214 :         s << blockHash;
     296         214 :         s << nHeight;
     297         214 :         s << nTotalRegisteredCount;
     298             :         // Serialize the map as a vector
     299         214 :         WriteCompactSize(s, mnMap.size());
     300         432 :         for (const auto& p : mnMap) {
     301           4 :             s << *p.second;
     302             :         }
     303         214 :     }
     304             : 
     305             :     template<typename Stream>
     306           2 :     void Unserialize(Stream& s) {
     307           2 :         mnMap = MnMap();
     308           2 :         mnUniquePropertyMap = MnUniquePropertyMap();
     309           2 :         mnInternalIdMap = MnInternalIdMap();
     310             : 
     311           2 :         s >> blockHash;
     312           2 :         s >> nHeight;
     313           2 :         s >> nTotalRegisteredCount;
     314           2 :         size_t cnt = ReadCompactSize(s);
     315           2 :         for (size_t i = 0; i < cnt; i++) {
     316           0 :             AddMN(std::make_shared<CDeterministicMN>(deserialize, s), false);
     317             :         }
     318           2 :     }
     319             : 
     320             : public:
     321        5072 :     size_t GetAllMNsCount() const
     322             :     {
     323        5072 :         return mnMap.size();
     324             :     }
     325             : 
     326       16905 :     size_t GetValidMNsCount() const
     327             :     {
     328       16905 :         size_t count = 0;
     329      141512 :         for (const auto& p : mnMap) {
     330       53851 :             if (!p.second->IsPoSeBanned()) {
     331       53377 :                 count++;
     332             :             }
     333             :         }
     334       16905 :         return count;
     335             :     }
     336             : 
     337             :     template <typename Callback>
     338       61936 :     void ForEachMN(bool onlyValid, Callback&& cb) const
     339             :     {
     340      715086 :         for (const auto& p : mnMap) {
     341      295607 :             if (!onlyValid || !p.second->IsPoSeBanned()) {
     342      294209 :                 cb(p.second);
     343             :             }
     344             :         }
     345       61936 :     }
     346             : 
     347             : public:
     348      106484 :     const uint256& GetBlockHash() const      { return blockHash; }
     349      902525 :     int GetHeight() const                    { return nHeight; }
     350         486 :     uint32_t GetTotalRegisteredCount() const { return nTotalRegisteredCount; }
     351       11384 :     void SetHeight(int _height)                  { nHeight = _height; }
     352       20015 :     void SetBlockHash(const uint256& _blockHash) { blockHash = _blockHash; }
     353             : 
     354        8789 :     bool HasMN(const uint256& proTxHash) const
     355             :     {
     356        8789 :         return GetMN(proTxHash) != nullptr;
     357             :     }
     358         207 :     bool HasMNByCollateral(const COutPoint& collateralOutpoint) const
     359             :     {
     360         207 :         return GetMNByCollateral(collateralOutpoint) != nullptr;
     361             :     }
     362             :     bool HasValidMNByCollateral(const COutPoint& collateralOutpoint) const
     363             :     {
     364             :         return GetValidMNByCollateral(collateralOutpoint) != nullptr;
     365             :     }
     366             :     CDeterministicMNCPtr GetMN(const uint256& proTxHash) const;
     367             :     CDeterministicMNCPtr GetValidMN(const uint256& proTxHash) const;
     368             :     CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey& pubKey);
     369             :     CDeterministicMNCPtr GetMNByCollateral(const COutPoint& collateralOutpoint) const;
     370             :     CDeterministicMNCPtr GetValidMNByCollateral(const COutPoint& collateralOutpoint) const;
     371             :     CDeterministicMNCPtr GetMNByService(const CService& service) const;
     372             :     CDeterministicMNCPtr GetMNByInternalId(uint64_t internalId) const;
     373             :     CDeterministicMNCPtr GetMNPayee() const;
     374             : 
     375             :     /**
     376             :      * Calculates the projected MN payees for the next *count* blocks. The result is not guaranteed to be correct
     377             :      * as PoSe banning might occur later
     378             :      * @param count
     379             :      * @return
     380             :      */
     381             :     std::vector<CDeterministicMNCPtr> GetProjectedMNPayees(unsigned int nCount) const;
     382             : 
     383             :     /**
     384             :      * Calculate a quorum based on the modifier. The resulting list is deterministically sorted by score
     385             :      * @param maxSize
     386             :      * @param modifier
     387             :      * @return
     388             :      */
     389             :     std::vector<CDeterministicMNCPtr> CalculateQuorum(size_t maxSize, const uint256& modifier) const;
     390             :     std::vector<std::pair<arith_uint256, CDeterministicMNCPtr>> CalculateScores(const uint256& modifier) const;
     391             : 
     392             :     /**
     393             :      * Calculates the maximum penalty which is allowed at the height of this MN list. It is dynamic and might change
     394             :      * for every block.
     395             :      * @return
     396             :      */
     397             :     int CalcMaxPoSePenalty() const;
     398             : 
     399             :     /**
     400             :      * Returns a the given percentage from the max penalty for this MN list. Always use this method to calculate the
     401             :      * value later passed to PoSePunish. The percentage should be high enough to take per-block penalty decreasing for MNs
     402             :      * into account. This means, if you want to accept 2 failures per payment cycle, you should choose a percentage that
     403             :      * is higher then 50%, e.g. 66%.
     404             :      * @param percent
     405             :      * @return
     406             :      */
     407             :     int CalcPenalty(int percent) const;
     408             : 
     409             :     /**
     410             :      * Punishes a MN for misbehavior. If the resulting penalty score of the MN reaches the max penalty, it is banned.
     411             :      * Penalty scores are only increased when the MN is not already banned, which means that after banning the penalty
     412             :      * might appear lower then the current max penalty, while the MN is still banned.
     413             :      * @param proTxHash
     414             :      * @param penalty
     415             :      */
     416             :     void PoSePunish(const uint256& proTxHash, int penalty, bool debugLogs);
     417             : 
     418             :     /**
     419             :      * Decrease penalty score of MN by 1.
     420             :      * Only allowed on non-banned MNs.
     421             :      * @param proTxHash
     422             :      */
     423             :     void PoSeDecrease(const uint256& proTxHash);
     424             : 
     425             :     CDeterministicMNListDiff BuildDiff(const CDeterministicMNList& to) const;
     426             :     CDeterministicMNList ApplyDiff(const CBlockIndex* pindex, const CDeterministicMNListDiff& diff) const;
     427             : 
     428             :     void AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTotalCount = true);
     429             :     void UpdateMN(const CDeterministicMNCPtr& oldDmn, const CDeterministicMNStateCPtr& pdmnState);
     430             :     void UpdateMN(const uint256& proTxHash, const CDeterministicMNStateCPtr& pdmnState);
     431             :     void UpdateMN(const CDeterministicMNCPtr& oldDmn, const CDeterministicMNStateDiff& stateDiff);
     432             :     void RemoveMN(const uint256& proTxHash);
     433             : 
     434             :     template <typename T>
     435       29629 :     bool HasUniqueProperty(const T& v) const
     436             :     {
     437       29629 :         return mnUniquePropertyMap.count(::SerializeHash(v, SER_GETHASH, PROTOCOL_VERSION | ADDRV2_FORMAT)) != 0;
     438             :     }
     439             :     template <typename T>
     440      556671 :     CDeterministicMNCPtr GetUniquePropertyMN(const T& v) const
     441             :     {
     442      556671 :         auto p = mnUniquePropertyMap.find(::SerializeHash(v, SER_GETHASH, PROTOCOL_VERSION | ADDRV2_FORMAT));
     443      556671 :         if (!p) {
     444      556671 :             return nullptr;
     445             :         }
     446       23015 :         return GetMN(p->first);
     447             :     }
     448             : 
     449             : private:
     450             :     template <typename T>
     451        4426 :     void AddUniqueProperty(const CDeterministicMNCPtr& dmn, const T& v)
     452             :     {
     453        4499 :         static const T nullValue;
     454        4426 :         assert(v != nullValue);
     455             : 
     456        4426 :         auto hash = ::SerializeHash(v, SER_GETHASH, PROTOCOL_VERSION | ADDRV2_FORMAT);
     457        4426 :         auto oldEntry = mnUniquePropertyMap.find(hash);
     458        4426 :         assert(!oldEntry || oldEntry->first == dmn->proTxHash);
     459        4426 :         std::pair<uint256, uint32_t> newEntry(dmn->proTxHash, 1);
     460        4426 :         if (oldEntry) {
     461           0 :             newEntry.second = oldEntry->second + 1;
     462             :         }
     463        4426 :         mnUniquePropertyMap = mnUniquePropertyMap.set(hash, newEntry);
     464        4426 :     }
     465             :     template <typename T>
     466         353 :     void DeleteUniqueProperty(const CDeterministicMNCPtr& dmn, const T& oldValue)
     467             :     {
     468         367 :         static const T nullValue;
     469         353 :         assert(oldValue != nullValue);
     470             : 
     471         353 :         auto oldHash = ::SerializeHash(oldValue, SER_GETHASH, PROTOCOL_VERSION | ADDRV2_FORMAT);
     472         353 :         auto p = mnUniquePropertyMap.find(oldHash);
     473         353 :         assert(p && p->first == dmn->proTxHash);
     474         353 :         if (p->second == 1) {
     475         353 :             mnUniquePropertyMap = mnUniquePropertyMap.erase(oldHash);
     476             :         } else {
     477           0 :             mnUniquePropertyMap = mnUniquePropertyMap.set(oldHash, std::make_pair(dmn->proTxHash, p->second - 1));
     478             :         }
     479         353 :     }
     480             :     template <typename T>
     481       65922 :     void UpdateUniqueProperty(const CDeterministicMNCPtr& dmn, const T& oldValue, const T& newValue)
     482             :     {
     483       65922 :         if (oldValue == newValue) {
     484             :             return;
     485             :         }
     486         201 :         static const T nullValue;
     487             : 
     488         201 :         if (oldValue != nullValue) {
     489         165 :             DeleteUniqueProperty(dmn, oldValue);
     490             :         }
     491             : 
     492         201 :         if (newValue != nullValue) {
     493          98 :             AddUniqueProperty(dmn, newValue);
     494             :         }
     495             :     }
     496             : };
     497             : 
     498       18809 : class CDeterministicMNListDiff
     499             : {
     500             : public:
     501             :     int nHeight{-1}; //memory only
     502             : 
     503             :     std::vector<CDeterministicMNCPtr> addedMNs;
     504             :     // keys are all relating to the internalId of MNs
     505             :     std::map<uint64_t, CDeterministicMNStateDiff> updatedMNs;
     506             :     std::set<uint64_t> removedMns;
     507             : 
     508             : public:
     509             :     template<typename Stream>
     510       25723 :     void Serialize(Stream& s) const
     511             :     {
     512       25723 :         s << addedMNs;
     513       25723 :         WriteCompactSize(s, updatedMNs.size());
     514       52974 :         for (const auto& p : updatedMNs) {
     515       27251 :             s << VARINT(p.first);
     516       27251 :             s << p.second;
     517             :         }
     518       25723 :         WriteCompactSize(s, removedMns.size());
     519       25789 :         for (const auto& p : removedMns) {
     520          66 :             s << VARINT(p);
     521             :         }
     522       25723 :     }
     523             : 
     524             :     template<typename Stream>
     525         124 :     void Unserialize(Stream& s)
     526             :     {
     527         124 :         updatedMNs.clear();
     528         124 :         removedMns.clear();
     529             : 
     530             :         size_t tmp;
     531             :         uint64_t tmp2;
     532         124 :         s >> addedMNs;
     533         124 :         tmp = ReadCompactSize(s);
     534         258 :         for (size_t i = 0; i < tmp; i++) {
     535         268 :             CDeterministicMNStateDiff diff;
     536         134 :             s >> VARINT(tmp2);
     537         134 :             s >> diff;
     538         134 :             updatedMNs.emplace(tmp2, std::move(diff));
     539             :         }
     540         124 :         tmp = ReadCompactSize(s);
     541         124 :         for (size_t i = 0; i < tmp; i++) {
     542           0 :             s >> VARINT(tmp2);
     543           0 :             removedMns.emplace(tmp2);
     544             :         }
     545         124 :     }
     546             : 
     547             : public:
     548       18816 :     bool HasChanges() const
     549             :     {
     550       18816 :         return !addedMNs.empty() || !updatedMNs.empty() || !removedMns.empty();
     551             :     }
     552             : };
     553             : 
     554         772 : class CDeterministicMNManager
     555             : {
     556             :     static const int DISK_SNAPSHOT_PERIOD = 1440; // once per day
     557             :     static const int DISK_SNAPSHOTS = 3; // keep cache for 3 disk snapshots to have 2 full days covered
     558             :     static const int LIST_DIFFS_CACHE_SIZE = DISK_SNAPSHOT_PERIOD * DISK_SNAPSHOTS;
     559             : 
     560             : public:
     561             :     mutable RecursiveMutex cs;
     562             : 
     563             : private:
     564             :     CEvoDB& evoDb;
     565             : 
     566             :     std::unordered_map<uint256, CDeterministicMNList, StaticSaltedHasher> mnListsCache;
     567             :     std::unordered_map<uint256, CDeterministicMNListDiff, StaticSaltedHasher> mnListDiffsCache;
     568             :     const CBlockIndex* tipIndex{nullptr};
     569             : 
     570             : public:
     571             :     explicit CDeterministicMNManager(CEvoDB& _evoDb);
     572             : 
     573             :     bool ProcessBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state, bool fJustCheck);
     574             :     bool UndoBlock(const CBlock& block, const CBlockIndex* pindex);
     575             : 
     576             :     void SetTipIndex(const CBlockIndex* pindex);
     577             : 
     578             :     // the returned list will not contain the correct block hash (we can't know it yet as the coinbase TX is not updated yet)
     579             :     bool BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, CValidationState& state, CDeterministicMNList& mnListRet, bool debugLogs);
     580             :     void HandleQuorumCommitment(llmq::CFinalCommitment& qc, const CBlockIndex* pindexQuorum, CDeterministicMNList& mnList, bool debugLogs);
     581             :     void DecreasePoSePenalties(CDeterministicMNList& mnList);
     582             : 
     583             :     // to return a valid list, it must have been built first, so never call it with a block not-yet connected (e.g. from CheckBlock).
     584             :     CDeterministicMNList GetListForBlock(const CBlockIndex* pindex);
     585             :     CDeterministicMNList GetListAtChainTip();
     586             : 
     587             :     // Whether DMNs are enforced at provided height, or at the chain-tip
     588             :     bool IsDIP3Enforced(int nHeight) const;
     589             :     bool IsDIP3Enforced() const;
     590             : 
     591             :     // Whether Legacy MNs are disabled at provided height, or at the chain-tip
     592             :     bool LegacyMNObsolete(int nHeight) const;
     593             :     bool LegacyMNObsolete() const;
     594             : 
     595             :     // Get the list of members for a given quorum type and index
     596             :     std::vector<CDeterministicMNCPtr> GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum);
     597             : 
     598             : private:
     599             :     void CleanupCache(int nHeight);
     600             : };
     601             : 
     602             : extern std::unique_ptr<CDeterministicMNManager> deterministicMNManager;
     603             : 
     604             : #endif // PIVX_EVO_DETERMINISTICMNS_H

Generated by: LCOV version 1.14