aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Maxwell <greg@xiph.org>2016-05-20 16:19:26 +0000
committerGregory Maxwell <greg@xiph.org>2016-05-25 18:05:58 +0000
commit7e908c7b826cedbf29560ce7a668af809ee71524 (patch)
treeb28d1f37652e06bde2db6127cbb3378ee35c7617
parent8844ef15ded02d5ed86fb95aaf251235fcef2396 (diff)
downloadbitcoin-7e908c7b826cedbf29560ce7a668af809ee71524.tar.xz
Do not use mempool for GETDATA for tx accepted after the last mempool req.
The ability to GETDATA a transaction which has not (yet) been relayed is a privacy loss vector. The use of the mempool for this was added as part of the mempool p2p message and is only needed to fetch transactions returned by it.
-rw-r--r--src/main.cpp6
-rw-r--r--src/net.cpp1
-rw-r--r--src/net.h3
-rw-r--r--src/txmempool.cpp10
-rw-r--r--src/txmempool.h1
5 files changed, 19 insertions, 2 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 9ba90b4ead..2ee6bc5310 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4503,7 +4503,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) {
pfrom->PushMessage(NetMsgType::TX, tx);
pushed = true;
}
@@ -5902,6 +5905,7 @@ bool SendMessages(CNode* pto)
vInv.clear();
}
}
+ pto->timeLastMempoolReq = GetTime();
}
// Determine transactions to relay
diff --git a/src/net.cpp b/src/net.cpp
index bbd23d292a..df3221e841 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2396,6 +2396,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
fRelayTxes = false;
fSentAddr = false;
pfilter = new CBloomFilter();
+ timeLastMempoolReq = 0;
nPingNonceSent = 0;
nPingUsecStart = 0;
nPingUsecTime = 0;
diff --git a/src/net.h b/src/net.h
index 998ee49260..66cc912a52 100644
--- a/src/net.h
+++ b/src/net.h
@@ -17,6 +17,7 @@
#include "sync.h"
#include "uint256.h"
+#include <atomic>
#include <deque>
#include <stdint.h>
@@ -413,6 +414,8 @@ public:
// Used for BIP35 mempool sending, also protected by cs_inventory
bool fSendMempool;
+ // Last time a "MEMPOOL" request was serviced.
+ std::atomic<int64_t> timeLastMempoolReq;
// Ping time measurement:
// The pong reply we're expecting, or 0 if no pong expected.
uint64_t nPingNonceSent;
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index aa5df6ca4e..4f17e7f8ca 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -789,15 +789,23 @@ void CTxMemPool::queryHashes(vector<uint256>& 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 3e1d387975..75cf0f4c12 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -602,6 +602,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