Line data Source code
1 : // Copyright (c) 2014-2025 The Dash Core developers 2 : // Distributed under the MIT/X11 software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #ifndef BITCOIN_GOVERNANCE_SUPERBLOCK_H 6 : #define BITCOIN_GOVERNANCE_SUPERBLOCK_H 7 : 8 : #include <consensus/amount.h> 9 : #include <governance/object.h> 10 : #include <script/script.h> 11 : #include <script/standard.h> 12 : #include <sync.h> 13 : #include <uint256.h> 14 : 15 : #include <atomic> 16 : #include <map> 17 : #include <memory> 18 : #include <string> 19 : #include <vector> 20 : 21 : class CChain; 22 : class CDeterministicMNList; 23 : class CTransaction; 24 : class CTxOut; 25 : 26 : CAmount ParsePaymentAmount(const std::string& strAmount); 27 : 28 : /** 29 : * Governance Object Payment 30 : */ 31 : class CGovernancePayment 32 : { 33 : private: 34 : bool fValid; 35 : 36 : public: 37 : CScript script; 38 : CAmount nAmount; 39 : uint256 proposalHash; 40 : 41 1000 : CGovernancePayment() : 42 500 : fValid(false), 43 500 : script(), 44 500 : nAmount(0), 45 500 : proposalHash(0) 46 500 : { 47 1000 : } 48 : 49 : CGovernancePayment(const CTxDestination& destIn, CAmount nAmountIn, const uint256& proposalHash); 50 : 51 954 : bool IsValid() const { return fValid; } 52 : }; 53 : 54 : 55 : /** 56 : * Trigger : Superblock 57 : * 58 : * - Create payments on the network 59 : * 60 : * object structure: 61 : * { 62 : * "governance_object_id" : last_id, 63 : * "type" : govtypes.trigger, 64 : * "subtype" : "superblock", 65 : * "superblock_name" : superblock_name, 66 : * "start_epoch" : start_epoch, 67 : * "payment_addresses" : "addr1|addr2|addr3", 68 : * "payment_amounts" : "amount1|amount2|amount3" 69 : * } 70 : */ 71 : class CSuperblock : public CGovernanceObject 72 : { 73 : private: 74 : uint256 nGovObjHash; 75 : 76 : int nBlockHeight; 77 : SeenObjectStatus nStatus; 78 : std::vector<CGovernancePayment> vecPayments; 79 : 80 : void ParsePaymentSchedule(const std::string& strPaymentAddresses, const std::string& strPaymentAmounts, const std::string& strProposalHashes); 81 : 82 : public: 83 : CSuperblock(); 84 : CSuperblock(int nBlockHeight, std::vector<CGovernancePayment> vecPayments); 85 : explicit CSuperblock(const CGovernanceObject& obj, uint256& nHash); 86 : 87 : static bool IsValidBlockHeight(int nBlockHeight); 88 : static void GetNearestSuperblocksHeights(int nBlockHeight, int& nLastSuperblockRet, int& nNextSuperblockRet); 89 : static CAmount GetPaymentsLimit(const CChain& active_chain, int nBlockHeight); 90 : 91 10080 : SeenObjectStatus GetStatus() const { return nStatus; } 92 188 : void SetStatus(SeenObjectStatus nStatusIn) { nStatus = nStatusIn; } 93 : 94 : std::string GetHexStrData() const; 95 : 96 : // TELL THE ENGINE WE EXECUTED THIS EVENT 97 98 : void SetExecuted() { nStatus = SeenObjectStatus::Executed; } 98 : 99 5770 : int GetBlockHeight() const 100 : { 101 5770 : return nBlockHeight; 102 : } 103 : 104 3836 : uint256 GetGovernanceObjHash() const { return nGovObjHash; } 105 : 106 285 : int CountPayments() const { return (int)vecPayments.size(); } 107 : bool GetPayment(int nPaymentIndex, CGovernancePayment& paymentRet); 108 : CAmount GetPaymentsTotalAmount(); 109 : 110 : bool IsValid(const CChain& active_chain, const CTransaction& txNew, int nBlockHeight, CAmount blockReward, bool is_v24); 111 : bool IsExpired(int heightToTest) const; 112 : 113 : std::vector<uint256> GetProposalHashes() const; 114 : }; 115 : 116 : using CSuperblock_sptr = std::shared_ptr<CSuperblock>; 117 : 118 : namespace governance { 119 : 120 : /** 121 : * Owns the set of active superblock triggers. Trigger lifecycle is fully 122 : * owned here; CGovernanceManager pushes new TRIGGER objects in via 123 : * AddTrigger() and notifies us via RemoveTrigger() when it erases the 124 : * underlying object from its store. Each entry holds a strong reference 125 : * to the underlying CGovernanceObject so we never look it up by hash. 126 : * 127 : * Lifetime: typically owned by CChainstateHelper, which outlives the 128 : * paired CGovernanceManager. The govman drives m_loaded via SetLoaded() 129 : * from LoadCache() and Clear()s us in its destructor, so IsValid() and 130 : * the trigger map track the live govman's state. 131 : */ 132 3063 : class SuperblockManager 133 : { 134 : public: 135 341959 : bool IsValid() const { return m_loaded; } 136 2831 : void SetLoaded(bool loaded) { m_loaded = loaded; } 137 : 138 : /** Register a TRIGGER governance object. Returns true if the resulting 139 : * trigger is live (not already height-expired). */ 140 : bool AddTrigger(std::shared_ptr<CGovernanceObject> obj, int cachedHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 141 : 142 : /** Single-direction notification from CGovernanceManager when it erases 143 : * a TRIGGER object from its store. */ 144 : void RemoveTrigger(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 145 : 146 : /** Prune triggers that are invalid or height-expired. Calls 147 : * PrepareDeletion() on the underlying object so CGovernanceManager 148 : * picks it up on its own sweep. */ 149 : void Clean(int cachedHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 150 : 151 : void Clear() EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 152 : 153 : std::vector<CSuperblock_sptr> GetActiveTriggers() const EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 154 : 155 : bool GetBestSuperblock(const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& sbRet, int nBlockHeight) const 156 : EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 157 : 158 : bool IsSuperblockTriggered(const CDeterministicMNList& tip_mn_list, int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 159 : 160 : bool IsValidSuperblock(const CChain& active_chain, const CDeterministicMNList& tip_mn_list, const CTransaction& txNew, 161 : int nBlockHeight, CAmount blockReward, bool is_v24) const EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 162 : 163 : bool GetSuperblockPayments(const CDeterministicMNList& tip_mn_list, int nBlockHeight, 164 : std::vector<CTxOut>& voutSuperblockRet) const EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 165 : 166 : void ExecuteBestSuperblock(const CDeterministicMNList& tip_mn_list, int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_sb); 167 : 168 : private: 169 : struct TriggerEntry { 170 : CSuperblock_sptr sb; 171 : std::shared_ptr<CGovernanceObject> obj; 172 : }; 173 : 174 : bool GetBestSuperblockInternal(const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& sbRet, 175 : int nBlockHeight) const EXCLUSIVE_LOCKS_REQUIRED(cs_sb); 176 : 177 : mutable Mutex cs_sb; 178 3063 : std::atomic<bool> m_loaded{false}; 179 : std::map<uint256, TriggerEntry> m_triggers GUARDED_BY(cs_sb); 180 : }; 181 : 182 : } // namespace governance 183 : 184 : #endif // BITCOIN_GOVERNANCE_SUPERBLOCK_H