diff --git a/src/net.cpp b/src/net.cpp index ff893f71a..6a6189f1a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2679,6 +2679,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn fRelayTxes = false; fSentAddr = false; pfilter = new CBloomFilter(); + timeLastMempoolReq = 0; nLastBlockTime = 0; nLastTXTime = 0; nPingNonceSent = 0; diff --git a/src/net.h b/src/net.h index efcaf8240..78330e69d 100644 --- a/src/net.h +++ b/src/net.h @@ -766,6 +766,8 @@ public: std::atomic nLastBlockTime; std::atomic nLastTXTime; + // Last time a "MEMPOOL" request was serviced. + std::atomic timeLastMempoolReq; // Ping time measurement: // The pong reply we're expecting, or 0 if no pong expected. uint64_t nPingNonceSent; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 229379e8b..eaeee1e0f 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -898,7 +898,10 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam if (!pushed && inv.type == MSG_TX) { CTransaction tx; - if (mempool.lookup(inv.hash, tx)) { + int64_t txtime; + // To protect privacy, do not answer getdata using the mempool when + // that TX couldn't have been INVed in reply to a MEMPOOL request. + if (mempool.lookup(inv.hash, tx, txtime) && txtime <= pfrom->timeLastMempoolReq) { connman.PushMessage(pfrom, NetMsgType::TX, tx); pushed = true; } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 17bfaa3cb..23efd790e 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -925,15 +925,23 @@ void CTxMemPool::queryHashes(vector& vtxid) std::sort(vtxid.begin(), vtxid.end(), DepthAndScoreComparator(this)); } -bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const + +bool CTxMemPool::lookup(uint256 hash, CTransaction& result, int64_t& time) const { LOCK(cs); indexed_transaction_set::const_iterator i = mapTx.find(hash); if (i == mapTx.end()) return false; result = i->GetTx(); + time = i->GetTime(); return true; } +bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const +{ + int64_t time; + return CTxMemPool::lookup(hash, result, time); +} + bool CTxMemPool::lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const { LOCK(cs); diff --git a/src/txmempool.h b/src/txmempool.h index 07ffbd70e..4e6d327c2 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -648,6 +648,7 @@ public: } bool lookup(uint256 hash, CTransaction& result) const; + bool lookup(uint256 hash, CTransaction& result, int64_t& time) const; bool lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const; /** Estimate fee rate needed to get into the next nBlocks