mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-12 21:02:38 -03:00
77a36033b5
c58c249a5b
net_processing: indicate more work to do when orphans are ready to reconsider (Anthony Towns)ecb0a3e425
net_processing: Don't process tx after processing orphans (Anthony Towns)c583775706
net_processing: only process orphans before messages (Anthony Towns)be2304676b
txorphange: Drop redundant originator arg from GetTxToReconsider (Anthony Towns)a4fe09973a
txorphanage: index workset by originating peer (Anthony Towns) Pull request description: We currently process orphans by assigning them to the peer that provided a missing parent; instead assign them to the peer that provided the orphan in the first place. This prevents a peer from being able to marginally delay another peer's transactions and also simplifies the internal API slightly. Because we're now associating orphan processing with the peer that provided the orphan originally, we no longer process orphans immediately after receiving the parent, but defer until a future call to `ProcessMessage`. Based on #26295 ACKs for top commit: naumenkogs: utACKc58c249a5b
glozow: ACKc58c249a5b
mzumsande: Code Review ACKc58c249a5b
Tree-SHA512: 3186c346f21e60440266a2a80a9d23d7b96071414e14b2b3bfe50457c04c18b1eab109c3d8c2a7726a6b10a2eda1f0512510a52c102da112820a26f5d96f12de
105 lines
3.7 KiB
C++
105 lines
3.7 KiB
C++
// Copyright (c) 2021-2022 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef BITCOIN_TXORPHANAGE_H
|
|
#define BITCOIN_TXORPHANAGE_H
|
|
|
|
#include <net.h>
|
|
#include <primitives/block.h>
|
|
#include <primitives/transaction.h>
|
|
#include <sync.h>
|
|
|
|
#include <map>
|
|
#include <set>
|
|
|
|
/** A class to track orphan transactions (failed on TX_MISSING_INPUTS)
|
|
* Since we cannot distinguish orphans from bad transactions with
|
|
* non-existent inputs, we heavily limit the number of orphans
|
|
* we keep and the duration we keep them for.
|
|
*/
|
|
class TxOrphanage {
|
|
public:
|
|
/** Add a new orphan transaction */
|
|
bool AddTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
|
|
|
/** Check if we already have an orphan transaction (by txid or wtxid) */
|
|
bool HaveTx(const GenTxid& gtxid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
|
|
|
/** Extract a transaction from a peer's work set
|
|
* Returns nullptr if there are no transactions to work on.
|
|
* Otherwise returns the transaction reference, and removes
|
|
* it from the work set.
|
|
*/
|
|
CTransactionRef GetTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
|
|
|
/** Erase an orphan by txid */
|
|
int EraseTx(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
|
|
|
/** Erase all orphans announced by a peer (eg, after that peer disconnects) */
|
|
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
|
|
|
/** Erase all orphans included in or invalidated by a new block */
|
|
void EraseForBlock(const CBlock& block) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
|
|
|
/** Limit the orphanage to the given maximum */
|
|
void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
|
|
|
/** Add any orphans that list a particular tx as a parent into the from peer's work set */
|
|
void AddChildrenToWorkSet(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);;
|
|
|
|
/** Does this peer have any work to do? */
|
|
bool HaveTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);;
|
|
|
|
/** Return how many entries exist in the orphange */
|
|
size_t Size() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
|
{
|
|
LOCK(m_mutex);
|
|
return m_orphans.size();
|
|
}
|
|
|
|
protected:
|
|
/** Guards orphan transactions */
|
|
mutable Mutex m_mutex;
|
|
|
|
struct OrphanTx {
|
|
CTransactionRef tx;
|
|
NodeId fromPeer;
|
|
int64_t nTimeExpire;
|
|
size_t list_pos;
|
|
};
|
|
|
|
/** Map from txid to orphan transaction record. Limited by
|
|
* -maxorphantx/DEFAULT_MAX_ORPHAN_TRANSACTIONS */
|
|
std::map<uint256, OrphanTx> m_orphans GUARDED_BY(m_mutex);
|
|
|
|
/** Which peer provided the orphans that need to be reconsidered */
|
|
std::map<NodeId, std::set<uint256>> m_peer_work_set GUARDED_BY(m_mutex);
|
|
|
|
using OrphanMap = decltype(m_orphans);
|
|
|
|
struct IteratorComparator
|
|
{
|
|
template<typename I>
|
|
bool operator()(const I& a, const I& b) const
|
|
{
|
|
return &(*a) < &(*b);
|
|
}
|
|
};
|
|
|
|
/** 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 GUARDED_BY(m_mutex);
|
|
|
|
/** Orphan transactions in vector for quick random eviction */
|
|
std::vector<OrphanMap::iterator> m_orphan_list GUARDED_BY(m_mutex);
|
|
|
|
/** Index from wtxid into the m_orphans to lookup orphan
|
|
* transactions using their witness ids. */
|
|
std::map<uint256, OrphanMap::iterator> m_wtxid_to_orphan_it GUARDED_BY(m_mutex);
|
|
|
|
/** Erase an orphan by txid */
|
|
int _EraseTx(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
|
|
};
|
|
|
|
#endif // BITCOIN_TXORPHANAGE_H
|