diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -45,6 +45,8 @@ static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; /** Minimum time between orphan transactions expire time checks in seconds */ 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. * Timeout = base + per_header * (expected number of headers) @@ -1711,6 +1713,13 @@ // messages from this peer (likely resulting in our peer eventually // disconnecting us). if (pfrom->m_tx_relay != nullptr) { + // mempool entries added before this time have likely expired from + // mapRelay + const std::chrono::seconds longlived_mempool_time = + GetTime() - RELAY_TX_CACHE_TIME; + const std::chrono::seconds mempool_req = + pfrom->m_tx_relay->m_last_mempool_req.load(); + LOCK(cs_main); while (it != pfrom->vRecvGetData.end() && it->type == MSG_TX) { @@ -1734,14 +1743,15 @@ pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second)); push = true; - } else if (pfrom->m_tx_relay->m_last_mempool_req.load().count()) { + } else { auto txinfo = g_mempool.info(TxId(inv.hash)); // To protect privacy, do not answer getdata using the mempool // when that TX couldn't have been INVed in reply to a MEMPOOL - // request. + // request, or when it's too recent to have expired from + // mapRelay. if (txinfo.tx && - txinfo.m_time <= - pfrom->m_tx_relay->m_last_mempool_req.load()) { + ((mempool_req.count() && txinfo.m_time <= mempool_req) || + (txinfo.m_time <= longlived_mempool_time))) { connman->PushMessage( pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx)); @@ -4755,8 +4765,12 @@ auto ret = mapRelay.insert( std::make_pair(txid, std::move(txinfo.tx))); 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)); } } if (vInv.size() == MAX_INV_SZ) {