Line data Source code
1 : // Copyright (c) 2021-2022 The Bitcoin 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_TXORPHANAGE_H 6 : #define BITCOIN_TXORPHANAGE_H 7 : 8 : #include <net.h> 9 : #include <primitives/block.h> 10 : #include <primitives/transaction.h> 11 : #include <sync.h> 12 : 13 : #include <map> 14 : #include <set> 15 : 16 : /** A class to track orphan transactions (failed on TX_MISSING_INPUTS) 17 : * Since we cannot distinguish orphans from bad transactions with 18 : * non-existent inputs, we heavily limit the number of orphans 19 : * we keep and the duration we keep them for. 20 : */ 21 : class TxOrphanage { 22 : public: 23 : /** Add a new orphan transaction */ 24 : bool AddTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex); 25 : 26 : /** Check if we already have an orphan transaction (by txid or wtxid) */ 27 : bool HaveTx(const GenTxid& gtxid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex); 28 : 29 : /** Extract a transaction from a peer's work set 30 : * Returns nullptr if there are no transactions to work on. 31 : * Otherwise returns the transaction reference, and removes 32 : * it from the work set. 33 : */ 34 : CTransactionRef GetTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex); 35 : 36 : /** Erase an orphan by txid */ 37 : int EraseTx(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex); 38 : 39 : /** Erase all orphans announced by a peer (eg, after that peer disconnects) */ 40 : void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex); 41 : 42 : /** Erase all orphans included in or invalidated by a new block */ 43 : void EraseForBlock(const CBlock& block) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex); 44 : 45 : /** Limit the orphanage to the given maximum */ 46 : void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex); 47 : 48 : /** Add any orphans that list a particular tx as a parent into the from peer's work set */ 49 : void AddChildrenToWorkSet(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);; 50 : 51 : /** Does this peer have any work to do? */ 52 : bool HaveTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);; 53 : 54 : /** Return how many entries exist in the orphange */ 55 0 : size_t Size() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) 56 : { 57 0 : LOCK(m_mutex); 58 0 : return m_orphans.size(); 59 0 : } 60 : 61 : protected: 62 : /** Guards orphan transactions */ 63 : mutable Mutex m_mutex; 64 : 65 : struct OrphanTx { 66 : CTransactionRef tx; 67 : NodeId fromPeer; 68 : int64_t nTimeExpire; 69 : size_t list_pos; 70 : }; 71 : 72 : /** Map from txid to orphan transaction record. Limited by 73 : * -maxorphantx/DEFAULT_MAX_ORPHAN_TRANSACTIONS */ 74 : std::map<uint256, OrphanTx> m_orphans GUARDED_BY(m_mutex); 75 : 76 : /** Which peer provided the orphans that need to be reconsidered */ 77 : std::map<NodeId, std::set<uint256>> m_peer_work_set GUARDED_BY(m_mutex); 78 : 79 : using OrphanMap = decltype(m_orphans); 80 : 81 : struct IteratorComparator 82 : { 83 : template<typename I> 84 0 : bool operator()(const I& a, const I& b) const 85 : { 86 0 : return &(*a) < &(*b); 87 : } 88 : }; 89 : 90 : /** Index from the parents' COutPoint into the m_orphans. Used 91 : * to remove orphan transactions from the m_orphans */ 92 : std::map<COutPoint, std::set<OrphanMap::iterator, IteratorComparator>> m_outpoint_to_orphan_it GUARDED_BY(m_mutex); 93 : 94 : /** Orphan transactions in vector for quick random eviction */ 95 : std::vector<OrphanMap::iterator> m_orphan_list GUARDED_BY(m_mutex); 96 : 97 : /** Index from wtxid into the m_orphans to lookup orphan 98 : * transactions using their witness ids. */ 99 : std::map<uint256, OrphanMap::iterator> m_wtxid_to_orphan_it GUARDED_BY(m_mutex); 100 : 101 : /** Erase an orphan by txid */ 102 : int EraseTxNoLock(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(m_mutex); 103 : }; 104 : 105 : #endif // BITCOIN_TXORPHANAGE_H