Repository: bitcoin/bitcoin
File: src/txorphanage.h (C/C++)

Code before:

    std::vector<OrphanTxBase> GetOrphanTransactions() const;

    /** Get the total usage (weight) of all orphans. If an orphan has multiple announcers, its usage is
     * only counted once within this total. */
    unsigned int TotalOrphanUsage() const { return m_total_orphan_usage; }

protected:
    struct OrphanTx : public OrphanTxBase {
        size_t list_pos;
    };

    /** Total usage (weight) of all entries in m_orphans. */
    unsigned int m_total_orphan_usage{0};

    /** Map from wtxid to orphan transaction record. Limited by
     *  -maxorphantx/DEFAULT_MAX_ORPHAN_TRANSACTIONS */
    std::map<Wtxid, OrphanTx> m_orphans;

    /** Which peer provided the orphans that need to be reconsidered */
    std::map<NodeId, std::set<Wtxid>> m_peer_work_set;

    using OrphanMap = decltype(m_orphans);

    struct IteratorComparator
    {
        template<typename I>
        bool operator()(const I& a, const I& b) const
        {
            return a->first < b->first;
        }
    };

    /** Index from the parents' COutPoint into the m_orphans. Used
     *  to remove orphan transactions from the m_orphans */
    std::map<COutPoint, std::set<OrphanMap::iterator, IteratorComparator>> m_outpoint_to_orphan_it;

    /** Orphan transactions in vector for quick random eviction */
    std::vector<OrphanMap::iterator> m_orphan_list;

    /** Timestamp for the next scheduled sweep of expired orphans */
    NodeSeconds m_next_sweep{0s};
};

#endif // BITCOIN_TXORPHANAGE_H


Review comment (suggestion):
If we permit 4MWu per-peer reservation, and have a 1000 peers, we're not very far away from the `unsigned int` limit $2^{32}-1$. We were thinking about using only 1/10 of that for inbound, so we're really still a factor 10x away, but that still feels close enough that perhaps this should be an `int64_t` instead.

(can be done as a follow-up, since this isn't a concern with the current orphan eviction policies)

Code after:

    std::vector<OrphanTxBase> GetOrphanTransactions() const;

    /** Get the total usage (weight) of all orphans. If an orphan has multiple announcers, its usage is
     * only counted once within this total. */
    unsigned int TotalOrphanUsage() const { return m_total_orphan_usage; }

    /** Total usage (weight) of orphans for which this peer is an announcer. If an orphan has multiple
     * announcers, its weight will be accounted for in each PeerOrphanInfo, so the total of all
     * peers' UsageByPeer() may be larger than TotalOrphanBytes(). */
    unsigned int UsageByPeer(NodeId peer) const {
        auto peer_it = m_peer_orphanage_info.find(peer);
        return peer_it == m_peer_orphanage_info.end() ? 0 : peer_it->second.m_total_usage;
    }

    /** Check consistency between PeerOrphanInfo and m_orphans. Recalculate counters and ensure they
     * match what is cached. */
    void SanityCheck() const;

protected:
    struct OrphanTx : public OrphanTxBase {
        size_t list_pos;
    };

    /** Total usage (weight) of all entries in m_orphans. */
    unsigned int m_total_orphan_usage{0};

    /** Total number of <peer, tx> pairs. Can be larger than m_orphans.size() because multiple peers
     * may have announced the same orphan. */
    unsigned int m_total_announcements{0};

    /** Map from wtxid to orphan transaction record. Limited by
     *  -maxorphantx/DEFAULT_MAX_ORPHAN_TRANSACTIONS */
    std::map<Wtxid, OrphanTx> m_orphans;

    struct PeerOrphanInfo {
        /** List of transactions that should be reconsidered: added to in AddChildrenToWorkSet,
         * removed from one-by-one with each call to GetTxToReconsider. The wtxids may refer to
         * transactions that are no longer present in orphanage; these are lazily removed in
         * GetTxToReconsider. */
        std::set<Wtxid> m_work_set;

        /** Total weight of orphans for which this peer is an announcer.
         * If orphans are provided by different peers, its weight will be accounted for in each
         * PeerOrphanInfo, so the total of all peers' m_total_usage may be larger than
         * m_total_orphan_size. If a peer is removed as an announcer, even if the orphan still
         * remains in the orphanage, this number will be decremented. */
        unsigned int m_total_usage{0};
    };
    std::map<NodeId, PeerOrphanInfo> m_peer_orphanage_info;