Merge #16851: Continue relaying transactions after they expire from mapRelay

168b781fe7f3f13b24c52a151f36de4cdd0a340a Continue relaying transactions after they expire from mapRelay (Anthony Towns)

Pull request description:

  This change allows peers to request transactions even after they've expired from mapRelay and even if they're not doing mempool requests. This is intended to allow for CPFP of old transactions -- if parent tx P wasn't relayed due to low fees, then a higher fee rate child C is relayed, peers will currently request the parent P, but we prior to this patch, we will not relay it due to it not being in mapRelay.

ACKs for top commit:
  MarcoFalke:
    re-ACK 168b781fe7f3f13b24c52a151f36de4cdd0a340a (only change is comment fixup)
  sdaftuar:
    re-ACK 168b781fe7f3f13b24c52a151f36de4cdd0a340a
  sipa:
    ACK 168b781fe7f3f13b24c52a151f36de4cdd0a340a

Tree-SHA512: b206666dd1450cd0a161ae55fd1a7eda2c3d226842ba27d91fe463b551fd924b65b92551b14d6786692e15cf9a9a989666550dfc980b48ab0f8d4ca305bc7762
This commit is contained in:
MarcoFalke 2019-10-24 17:50:38 -04:00 committed by PastaPastaPasta
parent 7d687f916d
commit f181b0284a

View File

@ -80,6 +80,8 @@ static const unsigned int MAX_GETDATA_SZ = 1000;
static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60;
/** Minimum time between orphan transactions expire time checks in seconds */ /** Minimum time between orphan transactions expire time checks in seconds */
static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60;
/** How long to cache transactions in mapRelay for normal relay */
static constexpr std::chrono::seconds RELAY_TX_CACHE_TIME{15 * 60};
/** Headers download timeout expressed in microseconds /** Headers download timeout expressed in microseconds
* Timeout = base + per_header * (expected number of headers) */ * Timeout = base + per_header * (expected number of headers) */
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes
@ -1814,6 +1816,10 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
const CNetMsgMaker msgMaker(pfrom->GetSendVersion()); const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
{ {
// mempool entries added before this time have likely expired from mapRelay
const std::chrono::seconds longlived_mempool_time = GetTime<std::chrono::seconds>() - RELAY_TX_CACHE_TIME;
const std::chrono::seconds mempool_req = pfrom->m_tx_relay->m_last_mempool_req.load();
LOCK(cs_main); LOCK(cs_main);
while (it != pfrom->vRecvGetData.end() && it->IsKnownType()) { while (it != pfrom->vRecvGetData.end() && it->IsKnownType()) {
@ -1851,11 +1857,15 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *mi->second)); connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *mi->second));
} }
push = true; push = true;
} else if (pfrom->m_tx_relay->m_last_mempool_req.load().count()) { } else {
auto txinfo = mempool.info(inv.hash); auto txinfo = mempool.info(inv.hash);
// To protect privacy, do not answer getdata using the mempool when // To protect privacy, do not answer getdata using the mempool when
// that TX couldn't have been INVed in reply to a MEMPOOL request. // that TX couldn't have been INVed in reply to a MEMPOOL request,
if (txinfo.tx && txinfo.m_time <= pfrom->m_tx_relay->m_last_mempool_req.load()) { // or when it's too recent to have expired from mapRelay.
if (txinfo.tx && (
(mempool_req.count() && txinfo.m_time <= mempool_req)
|| (txinfo.m_time <= longlived_mempool_time)))
{
if (dstx) { if (dstx) {
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::DSTX, dstx)); connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::DSTX, dstx));
} else { } else {
@ -4897,7 +4907,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
auto ret = mapRelay.insert(std::make_pair(hash, std::move(txinfo.tx))); auto ret = mapRelay.insert(std::make_pair(hash, std::move(txinfo.tx)));
if (ret.second) { if (ret.second) {
vRelayExpiration.push_back(std::make_pair(nNow + 15 * 60 * 1000000, ret.first)); vRelayExpiration.push_back(std::make_pair(nNow + std::chrono::microseconds{RELAY_TX_CACHE_TIME}.count(), ret.first));
} }
} }
int nInvType = CCoinJoin::GetDSTX(hash) ? MSG_DSTX : MSG_TX; int nInvType = CCoinJoin::GetDSTX(hash) ? MSG_DSTX : MSG_TX;