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_INSTANTSEND_H 6 : #define BITCOIN_INSTANTSEND_INSTANTSEND_H 7 : 8 : #include <instantsend/db.h> 9 : #include <instantsend/lock.h> 10 : 11 : #include <net_types.h> 12 : #include <protocol.h> 13 : #include <saltedhasher.h> 14 : #include <sync.h> 15 : #include <threadsafety.h> 16 : #include <unordered_lru_cache.h> 17 : 18 : #include <optional> 19 : #include <vector> 20 : 21 : class CBlockIndex; 22 : class CDataStream; 23 : class CSporkManager; 24 : namespace Consensus { 25 : struct LLMQParams; 26 : } // namespace Consensus 27 : namespace util { 28 : struct DbWrapperParams; 29 : } // namespace util 30 : typedef std::shared_ptr<const CTransaction> CTransactionRef; 31 : 32 : namespace instantsend { 33 : 34 : struct PendingISLockFromPeer { 35 : NodeId node_id; 36 : InstantSendLockPtr islock; 37 : }; 38 : 39 : struct PendingISLockEntry : PendingISLockFromPeer { 40 : uint256 islock_hash; 41 : }; 42 : 43 0 : struct PendingState { 44 0 : bool m_pending_work{false}; 45 : std::vector<PendingISLockEntry> m_pending_is; 46 : }; 47 : } // namespace instantsend 48 : 49 : namespace llmq { 50 : 51 : class CInstantSendManager 52 : { 53 : private: 54 : instantsend::CInstantSendDb db; 55 : CSporkManager& spork_manager; 56 : 57 : mutable Mutex cs_pendingLocks; 58 : // Incoming and not verified yet 59 : Uint256HashMap<instantsend::PendingISLockFromPeer> pendingInstantSendLocks GUARDED_BY(cs_pendingLocks); 60 : // Tried to verify but there is no tx yet 61 : Uint256HashMap<instantsend::PendingISLockFromPeer> pendingNoTxInstantSendLocks GUARDED_BY(cs_pendingLocks); 62 : 63 : // TXs which are neither IS locked nor ChainLocked. We use this to determine for which TXs we need to retry IS 64 : // locking of child TXs 65 : struct NonLockedTxInfo { 66 : const CBlockIndex* pindexMined; 67 : CTransactionRef tx; 68 : Uint256HashSet children; 69 : }; 70 : 71 : mutable Mutex cs_nonLocked; 72 : Uint256HashMap<NonLockedTxInfo> nonLockedTxs GUARDED_BY(cs_nonLocked); 73 : std::unordered_map<COutPoint, uint256, SaltedOutpointHasher> nonLockedTxsByOutpoints GUARDED_BY(cs_nonLocked); 74 : 75 : mutable Mutex cs_pendingRetry; 76 : Uint256HashSet pendingRetryTxs GUARDED_BY(cs_pendingRetry); 77 : 78 : mutable Mutex cs_timingsTxSeen; 79 : Uint256HashMap<SteadyClock::time_point> timingsTxSeen GUARDED_BY(cs_timingsTxSeen); 80 : 81 : mutable Mutex cs_height_cache; 82 : static constexpr size_t MAX_BLOCK_HEIGHT_CACHE{16384}; 83 : mutable unordered_lru_cache<uint256, int, StaticSaltedHasher, MAX_BLOCK_HEIGHT_CACHE> m_cached_block_heights 84 : GUARDED_BY(cs_height_cache); 85 : mutable int m_cached_tip_height GUARDED_BY(cs_height_cache){-1}; 86 : 87 : public: 88 : CInstantSendManager() = delete; 89 : CInstantSendManager(const CInstantSendManager&) = delete; 90 : CInstantSendManager& operator=(const CInstantSendManager&) = delete; 91 : explicit CInstantSendManager(CSporkManager& sporkman, const util::DbWrapperParams& db_params); 92 : ~CInstantSendManager(); 93 : 94 : void AddNonLockedTx(const CTransactionRef& tx, const CBlockIndex* pindexMined) 95 : EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_timingsTxSeen); 96 : void RemoveNonLockedTx(const uint256& txid, bool retryChildren) 97 : EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry); 98 : 99 : instantsend::InstantSendLockPtr AttachISLockToTx(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 100 : 101 : std::unordered_map<const CBlockIndex*, Uint256HashMap<CTransactionRef>> RetrieveISConflicts( 102 : const uint256& islockHash, const instantsend::InstantSendLock& islock) 103 : EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks); 104 : bool HasTxForLock(const uint256& islockHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 105 : 106 : bool IsLocked(const uint256& txHash) const; 107 : bool IsWaitingForTx(const uint256& txHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 108 : instantsend::InstantSendLockPtr GetConflictingLock(const CTransaction& tx) const; 109 : 110 : /* Helpers for communications between CInstantSendManager & NetInstantSend */ 111 : // This helper returns up to 32 pending locks and remove them from queue of pending 112 : [[nodiscard]] instantsend::PendingState FetchPendingLocks() EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 113 : void EnqueueInstantSendLock(NodeId from, const uint256& hash, std::shared_ptr<instantsend::InstantSendLock> islock) 114 : EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 115 : [[nodiscard]] std::vector<CTransactionRef> PrepareTxToRetry() 116 : EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry); 117 : 118 : void RemoveBlockISLocks(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex); 119 : void WriteBlockISLocks(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex); 120 : void WriteNewISLock(const uint256& hash, const instantsend::InstantSendLockPtr& islock, std::optional<int> minedHeight); 121 : void AddPendingISLock(const uint256& hash, const instantsend::InstantSendLockPtr& islock, NodeId from) 122 : EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 123 : 124 : bool PreVerifyIsLock(const uint256& hash, const instantsend::InstantSendLockPtr& islock, NodeId from) const; 125 : 126 : bool AlreadyHave(const CInv& inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 127 : bool GetInstantSendLockByHash(const uint256& hash, instantsend::InstantSendLock& ret) const 128 : EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 129 : instantsend::InstantSendLockPtr GetInstantSendLockByTxid(const uint256& txid) const; 130 : 131 : void TransactionIsRemoved(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(!cs_height_cache); 132 : void RemoveConflictingLock(const uint256& islockHash, const instantsend::InstantSendLock& islock) 133 : EXCLUSIVE_LOCKS_REQUIRED(!cs_height_cache); 134 : void TryEmplacePendingLock(const uint256& hash, const NodeId id, const instantsend::InstantSendLockPtr& islock) 135 : EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks); 136 : 137 : size_t GetInstantSendLockCount() const; 138 : 139 0 : struct Counts { 140 0 : size_t m_verified{0}; 141 0 : size_t m_unverified{0}; 142 0 : size_t m_awaiting_tx{0}; 143 0 : size_t m_unprotected_tx{0}; 144 : }; 145 : Counts GetCounts() const EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks, !cs_nonLocked); 146 : 147 : void CacheBlockHeight(const CBlockIndex* const block_index) const EXCLUSIVE_LOCKS_REQUIRED(!cs_height_cache); 148 : void CacheDisconnectBlock(const CBlockIndex* pindexDisconnected) EXCLUSIVE_LOCKS_REQUIRED(!cs_height_cache); 149 : std::optional<int> GetCachedHeight(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_height_cache); 150 : void CacheTipHeight(const CBlockIndex* const tip) const EXCLUSIVE_LOCKS_REQUIRED(!cs_height_cache); 151 : int GetTipHeight() const EXCLUSIVE_LOCKS_REQUIRED(!cs_height_cache); 152 : 153 : bool IsInstantSendEnabled() const; 154 : Uint256HashMap<instantsend::InstantSendLockPtr> RemoveConfirmedInstantSendLocks(const CBlockIndex* pindex) 155 : EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry); 156 : }; 157 : } // namespace llmq 158 : 159 : #endif // BITCOIN_INSTANTSEND_INSTANTSEND_H