Skip to content

Commit

Permalink
An adapted version of btc@ed7068302c7490e8061cb3a558a0f83a465beeea
Browse files Browse the repository at this point in the history
Handle mempool requests in send loop, subject to trickle  By eliminating queued entries from the mempool response and responding only at trickle time, this makes the mempool no longer leak transaction arrival order information (as the mempool itself is also sorted)-- at least no more than relay itself leaks it.
  • Loading branch information
furszy committed Jan 18, 2021
1 parent 9645775 commit cb4fc6c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2438,6 +2438,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
hashContinue = UINT256_ZERO;
nStartingHeight = -1;
filterInventoryKnown.reset();
fSendMempool = false;
fGetAddr = false;
nNextLocalAddrSend = 0;
nNextAddrSend = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,8 @@ class CNode
std::multimap<int64_t, CInv> mapAskFor;
std::vector<uint256> vBlockRequested;
int64_t nNextInvSend;
// Used for BIP35 mempool sending, also protected by cs_inventory
bool fSendMempool;

// Ping time measurement:
// The pong reply we're expecting, or 0 if no pong expected.
Expand Down
58 changes: 37 additions & 21 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1633,27 +1633,10 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR


else if (strCommand == NetMsgType::MEMPOOL) {
LOCK2(cs_main, pfrom->cs_filter);

std::vector<uint256> vtxid;
mempool.queryHashes(vtxid);
std::vector<CInv> vInv;
for (uint256& hash : vtxid) {
CInv inv(MSG_TX, hash);
if (pfrom->pfilter) {
CTransaction tx;
bool fInMemPool = mempool.lookup(hash, tx);
if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
if (!pfrom->pfilter->IsRelevantAndUpdate(tx)) continue;
}
vInv.emplace_back(inv);
if (vInv.size() == MAX_INV_SZ) {
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
}
if (vInv.size() > 0)
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
// todo: limit mempool request with a bandwidth limit
LOCK(pfrom->cs_inventory);
pfrom->fSendMempool = true;
}


Expand Down Expand Up @@ -2104,13 +2087,42 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
}
pto->vInventoryTierTwoToSend.clear();

// Determine transactions to relay
// Check whether periodic send should happen
bool fSendTrickle = pto->fWhitelisted;
if (pto->nNextInvSend < nNow) {
fSendTrickle = true;
// Use half the delay for outbound peers, as there is less privacy concern for them.
pto->nNextInvSend = PoissonNextSend(nNow, INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound);
}

// Respond to BIP35 mempool requests
if (fSendTrickle && pto->fSendMempool) {
std::vector<uint256> vtxid;
mempool.queryHashes(vtxid);
pto->fSendMempool = false;
// future: back port fee filter rate
LOCK(pto->cs_filter);

for (const uint256& hash : vtxid) {
CInv inv(MSG_TX, hash);
pto->setInventoryTxToSend.erase(hash);
// future: add fee filter check here..
if (pto->pfilter) {
CTransaction tx;
bool fInMemPool = mempool.lookup(hash, tx);
if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
if (!pto->pfilter->IsRelevantAndUpdate(tx)) continue;
}
pto->filterInventoryKnown.insert(hash);
vInv.emplace_back(inv);
if (vInv.size() == MAX_INV_SZ) {
connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
}
}

// Determine transactions to relay
if (fSendTrickle) {
// Produce a vector with all candidates for sending
std::vector<std::set<uint256>::iterator> vInvTx;
Expand Down Expand Up @@ -2140,6 +2152,10 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
// Send
vInv.emplace_back(CInv(MSG_TX, hash));
nRelayedTransactions++;
if (vInv.size() == MAX_INV_SZ) {
connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
pto->filterInventoryKnown.insert(hash);
}
}
Expand Down

0 comments on commit cb4fc6c

Please sign in to comment.