Line data Source code
1 : // Copyright (c) 2019-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 BITCOIN_INSTANTSEND_DB_H 6 : #define BITCOIN_INSTANTSEND_DB_H 7 : 8 : #include <saltedhasher.h> 9 : #include <sync.h> 10 : #include <uint256.h> 11 : #include <util/hasher.h> 12 : 13 : #include <instantsend/lock.h> 14 : #include <unordered_lru_cache.h> 15 : 16 : #include <gsl/pointers.h> 17 : 18 : #include <cstdint> 19 : #include <memory> 20 : #include <unordered_map> 21 : 22 : class CBlock; 23 : class CBlockIndex; 24 : class CDBBatch; 25 : class CDBWrapper; 26 : class COutPoint; 27 : namespace util { 28 : struct DbWrapperParams; 29 : } // namespace util 30 : 31 : namespace instantsend { 32 : class CInstantSendDb 33 : { 34 : private: 35 : mutable Mutex cs_db; 36 : 37 : static constexpr int CURRENT_VERSION{1}; 38 : 39 : int best_confirmed_height GUARDED_BY(cs_db){0}; 40 : 41 : std::unique_ptr<CDBWrapper> db GUARDED_BY(cs_db){nullptr}; 42 : mutable Uint256LruHashMap<InstantSendLockPtr, 10000> islockCache GUARDED_BY(cs_db); 43 : mutable Uint256LruHashMap<uint256, 10000> txidCache GUARDED_BY(cs_db); 44 : 45 : mutable unordered_lru_cache<COutPoint, uint256, SaltedOutpointHasher, 10000> outpointCache GUARDED_BY(cs_db); 46 : void WriteInstantSendLockMined(CDBBatch& batch, const uint256& hash, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_db); 47 : 48 : void RemoveInstantSendLockMined(CDBBatch& batch, const uint256& hash, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_db); 49 : 50 : /** 51 : * This method removes a InstantSend Lock from the database and is called when a tx with an IS lock is confirmed and Chainlocked 52 : * @param batch Object used to batch many calls together 53 : * @param hash The hash of the InstantSend Lock 54 : * @param islock The InstantSend Lock object itself 55 : * @param keep_cache Should we still keep corresponding entries in the cache or not 56 : */ 57 : void RemoveInstantSendLock(CDBBatch& batch, const uint256& hash, const InstantSendLock& islock, 58 : bool keep_cache = true) EXCLUSIVE_LOCKS_REQUIRED(cs_db); 59 : /** 60 : * Marks an InstantSend Lock as archived. 61 : * @param batch Object used to batch many calls together 62 : * @param hash The hash of the InstantSend Lock 63 : * @param nHeight The height that the transaction was included at 64 : */ 65 : void WriteInstantSendLockArchived(CDBBatch& batch, const uint256& hash, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_db); 66 : /** 67 : * Gets a vector of IS Lock hashes of the IS Locks which rely on or are children of the parent IS Lock 68 : * @param parent The hash of the parent IS Lock 69 : * @return Returns a vector of IS Lock hashes 70 : */ 71 : std::vector<uint256> GetInstantSendLocksByParent(const uint256& parent) const EXCLUSIVE_LOCKS_REQUIRED(cs_db); 72 : 73 : /** 74 : * See GetInstantSendLockByHash 75 : */ 76 : InstantSendLockPtr GetInstantSendLockByHashInternal(const uint256& hash, bool use_cache = true) const EXCLUSIVE_LOCKS_REQUIRED(cs_db); 77 : 78 : /** 79 : * See GetInstantSendLockHashByTxid 80 : */ 81 : uint256 GetInstantSendLockHashByTxidInternal(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_db); 82 : 83 : 84 : void Upgrade(const util::DbWrapperParams& db_params) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 85 : 86 : public: 87 : explicit CInstantSendDb(const util::DbWrapperParams& db_params); 88 : ~CInstantSendDb(); 89 : 90 : /** 91 : * This method is called when an InstantSend Lock is processed and adds the lock to the database 92 : * @param hash The hash of the InstantSend Lock 93 : * @param islock The InstantSend Lock object itself 94 : */ 95 : void WriteNewInstantSendLock(const uint256& hash, const InstantSendLockPtr& islock) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 96 : /** 97 : * This method updates a DB entry for an InstantSend Lock from being not included in a block to being included in a block 98 : * @param hash The hash of the InstantSend Lock 99 : * @param nHeight The height that the transaction was included at 100 : */ 101 : void WriteInstantSendLockMined(const uint256& hash, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 102 : /** 103 : * Archives and deletes all IS Locks which were mined into a block before nUntilHeight 104 : * @param nUntilHeight Removes all IS Locks confirmed up until nUntilHeight 105 : * @return returns an unordered_map of the hash of the IS Locks and a pointer object to the IS Locks for all IS Locks which were removed 106 : */ 107 : Uint256HashMap<InstantSendLockPtr> RemoveConfirmedInstantSendLocks(int nUntilHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 108 : /** 109 : * Removes IS Locks from the archive if the tx was confirmed 100 blocks before nUntilHeight 110 : * @param nUntilHeight the height from which to base the remove of archive IS Locks 111 : */ 112 : void RemoveArchivedInstantSendLocks(int nUntilHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 113 : void WriteBlockInstantSendLocks(const gsl::not_null<std::shared_ptr<const CBlock>>& pblock, gsl::not_null<const CBlockIndex*> pindexConnected) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 114 : void RemoveBlockInstantSendLocks(const gsl::not_null<std::shared_ptr<const CBlock>>& pblock, gsl::not_null<const CBlockIndex*> pindexDisconnected) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 115 : bool KnownInstantSendLock(const uint256& islockHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 116 : /** 117 : * Gets the number of IS Locks which have not been confirmed by a block 118 : * @return size_t value of the number of IS Locks not confirmed by a block 119 : */ 120 : size_t GetInstantSendLockCount() const EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 121 : /** 122 : * Gets a pointer to the IS Lock based on the hash 123 : * @param hash The hash of the IS Lock 124 : * @param use_cache Should we try using the cache first or not 125 : * @return A Pointer object to the IS Lock, returns nullptr if it doesn't exist 126 : */ 127 333 : InstantSendLockPtr GetInstantSendLockByHash(const uint256& hash, bool use_cache = true) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db) 128 : { 129 333 : LOCK(cs_db); 130 333 : return GetInstantSendLockByHashInternal(hash, use_cache); 131 333 : }; 132 : /** 133 : * Gets an IS Lock hash based on the txid the IS Lock is for 134 : * @param txid The txid which is being searched for 135 : * @return Returns the hash the IS Lock of the specified txid, returns uint256() if it doesn't exist 136 : */ 137 681989 : uint256 GetInstantSendLockHashByTxid(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db) 138 : { 139 681989 : LOCK(cs_db); 140 681989 : return GetInstantSendLockHashByTxidInternal(txid); 141 681989 : }; 142 : /** 143 : * Gets an IS Lock pointer from the txid given 144 : * @param txid The txid for which the IS Lock Pointer is being returned 145 : * @return Returns the IS Lock Pointer associated with the txid, returns nullptr if it doesn't exist 146 : */ 147 : InstantSendLockPtr GetInstantSendLockByTxid(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 148 : /** 149 : * Gets an IS Lock pointer from an input given 150 : * @param outpoint Since all inputs are really just outpoints that are being spent 151 : * @return IS Lock Pointer associated with that input. 152 : */ 153 : InstantSendLockPtr GetInstantSendLockByInput(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 154 : /** 155 : * Called when a ChainLock invalidated a IS Lock, removes any chained/children IS Locks and the invalidated IS Lock 156 : * @param islockHash IS Lock hash which has been invalidated 157 : * @param txid Transaction id associated with the islockHash 158 : * @param nHeight height of the block which received a chainlock and invalidated the IS Lock 159 : * @return A vector of IS Lock hashes of all IS Locks removed 160 : */ 161 : std::vector<uint256> RemoveChainedInstantSendLocks(const uint256& islockHash, const uint256& txid, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_db); 162 : }; 163 : } // namespace instantsend 164 : 165 : #endif // BITCOIN_INSTANTSEND_DB_H