Branch data 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