mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-13 03:09:37 +01:00
This param is no longer needed since orphan parent requests are added to the TxRequestTracker directly.
178 lines
7.7 KiB
C++
178 lines
7.7 KiB
C++
// Copyright (c) 2024 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_NODE_TXDOWNLOADMAN_H
|
|
#define BITCOIN_NODE_TXDOWNLOADMAN_H
|
|
|
|
#include <net.h>
|
|
#include <policy/packages.h>
|
|
#include <txorphanage.h>
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
class CBlock;
|
|
class CRollingBloomFilter;
|
|
class CTxMemPool;
|
|
class GenTxid;
|
|
class TxRequestTracker;
|
|
namespace node {
|
|
class TxDownloadManagerImpl;
|
|
|
|
/** Maximum number of in-flight transaction requests from a peer. It is not a hard limit, but the threshold at which
|
|
* point the OVERLOADED_PEER_TX_DELAY kicks in. */
|
|
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT = 100;
|
|
/** Maximum number of transactions to consider for requesting, per peer. It provides a reasonable DoS limit to
|
|
* per-peer memory usage spent on announcements, while covering peers continuously sending INVs at the maximum
|
|
* rate (by our own policy, see INVENTORY_BROADCAST_PER_SECOND) for several minutes, while not receiving
|
|
* the actual transaction (from any peer) in response to requests for them. */
|
|
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS = 5000;
|
|
/** How long to delay requesting transactions via txids, if we have wtxid-relaying peers */
|
|
static constexpr auto TXID_RELAY_DELAY{2s};
|
|
/** How long to delay requesting transactions from non-preferred peers */
|
|
static constexpr auto NONPREF_PEER_TX_DELAY{2s};
|
|
/** How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT). */
|
|
static constexpr auto OVERLOADED_PEER_TX_DELAY{2s};
|
|
/** How long to wait before downloading a transaction from an additional peer */
|
|
static constexpr auto GETDATA_TX_INTERVAL{60s};
|
|
struct TxDownloadOptions {
|
|
/** Read-only reference to mempool. */
|
|
const CTxMemPool& m_mempool;
|
|
/** RNG provided by caller. */
|
|
FastRandomContext& m_rng;
|
|
/** Maximum number of transactions allowed in orphanage. */
|
|
const uint32_t m_max_orphan_txs;
|
|
/** Instantiate TxRequestTracker as deterministic (used for tests). */
|
|
bool m_deterministic_txrequest{false};
|
|
};
|
|
struct TxDownloadConnectionInfo {
|
|
/** Whether this peer is preferred for transaction download. */
|
|
const bool m_preferred;
|
|
/** Whether this peer has Relay permissions. */
|
|
const bool m_relay_permissions;
|
|
/** Whether this peer supports wtxid relay. */
|
|
const bool m_wtxid_relay;
|
|
};
|
|
struct PackageToValidate {
|
|
Package m_txns;
|
|
std::vector<NodeId> m_senders;
|
|
/** Construct a 1-parent-1-child package. */
|
|
explicit PackageToValidate(const CTransactionRef& parent,
|
|
const CTransactionRef& child,
|
|
NodeId parent_sender,
|
|
NodeId child_sender) :
|
|
m_txns{parent, child},
|
|
m_senders{parent_sender, child_sender}
|
|
{}
|
|
|
|
// Move ctor
|
|
PackageToValidate(PackageToValidate&& other) : m_txns{std::move(other.m_txns)}, m_senders{std::move(other.m_senders)} {}
|
|
// Copy ctor
|
|
PackageToValidate(const PackageToValidate& other) = default;
|
|
|
|
// Move assignment
|
|
PackageToValidate& operator=(PackageToValidate&& other) {
|
|
this->m_txns = std::move(other.m_txns);
|
|
this->m_senders = std::move(other.m_senders);
|
|
return *this;
|
|
}
|
|
|
|
std::string ToString() const {
|
|
Assume(m_txns.size() == 2);
|
|
return strprintf("parent %s (wtxid=%s, sender=%d) + child %s (wtxid=%s, sender=%d)",
|
|
m_txns.front()->GetHash().ToString(),
|
|
m_txns.front()->GetWitnessHash().ToString(),
|
|
m_senders.front(),
|
|
m_txns.back()->GetHash().ToString(),
|
|
m_txns.back()->GetWitnessHash().ToString(),
|
|
m_senders.back());
|
|
}
|
|
};
|
|
struct RejectedTxTodo
|
|
{
|
|
bool m_should_add_extra_compact_tx;
|
|
std::vector<Txid> m_unique_parents;
|
|
std::optional<PackageToValidate> m_package_to_validate;
|
|
};
|
|
|
|
|
|
/**
|
|
* Class responsible for deciding what transactions to request and, once
|
|
* downloaded, whether and how to validate them. It is also responsible for
|
|
* deciding what transaction packages to validate and how to resolve orphan
|
|
* transactions. Its data structures include TxRequestTracker for scheduling
|
|
* requests, rolling bloom filters for remembering transactions that have
|
|
* already been {accepted, rejected, confirmed}, an orphanage, and a registry of
|
|
* each peer's transaction relay-related information.
|
|
*
|
|
* Caller needs to interact with TxDownloadManager:
|
|
* - ValidationInterface callbacks.
|
|
* - When a potential transaction relay peer connects or disconnects.
|
|
* - When a transaction or package is accepted or rejected from mempool
|
|
* - When a inv, notfound, or tx message is received
|
|
* - To get instructions for which getdata messages to send
|
|
*
|
|
* This class is not thread-safe. Access must be synchronized using an
|
|
* external mutex.
|
|
*/
|
|
class TxDownloadManager {
|
|
const std::unique_ptr<TxDownloadManagerImpl> m_impl;
|
|
|
|
public:
|
|
explicit TxDownloadManager(const TxDownloadOptions& options);
|
|
~TxDownloadManager();
|
|
|
|
// Responses to chain events. TxDownloadManager is not an actual client of ValidationInterface, these are called through PeerManager.
|
|
void ActiveTipChange();
|
|
void BlockConnected(const std::shared_ptr<const CBlock>& pblock);
|
|
void BlockDisconnected();
|
|
|
|
/** Creates a new PeerInfo. Saves the connection info to calculate tx announcement delays later. */
|
|
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info);
|
|
|
|
/** Deletes all txrequest announcements and orphans for a given peer. */
|
|
void DisconnectedPeer(NodeId nodeid);
|
|
|
|
/** Consider adding this tx hash to txrequest. Should be called whenever a new inv has been received.
|
|
* Also called internally when a transaction is missing parents so that we can request them.
|
|
* Returns true if this was a dropped inv (p2p_inv=true and we already have the tx), false otherwise. */
|
|
bool AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now);
|
|
|
|
/** Get getdata requests to send. */
|
|
std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
|
|
|
|
/** Should be called when a notfound for a tx has been received. */
|
|
void ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes);
|
|
|
|
/** Respond to successful transaction submission to mempool */
|
|
void MempoolAcceptedTx(const CTransactionRef& tx);
|
|
|
|
/** Respond to transaction rejected from mempool */
|
|
RejectedTxTodo MempoolRejectedTx(const CTransactionRef& ptx, const TxValidationState& state, NodeId nodeid, bool first_time_failure);
|
|
|
|
/** Respond to package rejected from mempool */
|
|
void MempoolRejectedPackage(const Package& package);
|
|
|
|
/** Marks a tx as ReceivedResponse in txrequest and checks whether AlreadyHaveTx.
|
|
* Return a bool indicating whether this tx should be validated. If false, optionally, a
|
|
* PackageToValidate. */
|
|
std::pair<bool, std::optional<PackageToValidate>> ReceivedTx(NodeId nodeid, const CTransactionRef& ptx);
|
|
|
|
/** Whether there are any orphans to reconsider for this peer. */
|
|
bool HaveMoreWork(NodeId nodeid) const;
|
|
|
|
/** Returns next orphan tx to consider, or nullptr if none exist. */
|
|
CTransactionRef GetTxToReconsider(NodeId nodeid);
|
|
|
|
/** Check that all data structures are empty. */
|
|
void CheckIsEmpty() const;
|
|
|
|
/** Check that all data structures that track per-peer information have nothing for this peer. */
|
|
void CheckIsEmpty(NodeId nodeid) const;
|
|
|
|
/** Wrapper for TxOrphanage::GetOrphanTransactions */
|
|
std::vector<TxOrphanage::OrphanTxBase> GetOrphanTransactions() const;
|
|
};
|
|
} // namespace node
|
|
#endif // BITCOIN_NODE_TXDOWNLOADMAN_H
|