Move bloom and feerate filtering to just prior to tx sending.
This will avoid sending more pointless INVs around updates, and prevents using filter updates to timetag transactions. Also adds locking for fRelayTxes.
This commit is contained in:
parent
4578215e7f
commit
b559914753
3 changed files with 38 additions and 21 deletions
34
src/main.cpp
34
src/main.cpp
|
@ -4557,12 +4557,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||
vRecv >> LIMITED_STRING(pfrom->strSubVer, MAX_SUBVERSION_LENGTH);
|
||||
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
|
||||
}
|
||||
if (!vRecv.empty())
|
||||
if (!vRecv.empty()) {
|
||||
vRecv >> pfrom->nStartingHeight;
|
||||
}
|
||||
{
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (!vRecv.empty())
|
||||
vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message
|
||||
else
|
||||
pfrom->fRelayTxes = true;
|
||||
}
|
||||
|
||||
// Disconnect if we connected to ourself
|
||||
if (nNonce == nLocalHostNonce && nNonce > 1)
|
||||
|
@ -5325,12 +5329,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||
CBloomFilter filter;
|
||||
vRecv >> filter;
|
||||
|
||||
LOCK(pfrom->cs_filter);
|
||||
|
||||
if (!filter.IsWithinSizeConstraints())
|
||||
// There is no excuse for sending a too-large filter
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
else
|
||||
{
|
||||
LOCK(pfrom->cs_filter);
|
||||
delete pfrom->pfilter;
|
||||
pfrom->pfilter = new CBloomFilter(filter);
|
||||
pfrom->pfilter->UpdateEmptyFull();
|
||||
|
@ -5798,6 +5803,12 @@ bool SendMessages(CNode* pto)
|
|||
pto->nNextInvSend = PoissonNextSend(nNow, INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound);
|
||||
}
|
||||
|
||||
// Time to send but the peer has requested we not relay transactions.
|
||||
if (fSendTrickle) {
|
||||
LOCK(pto->cs_filter);
|
||||
if (!pto->fRelayTxes) pto->setInventoryTxToSend.clear();
|
||||
}
|
||||
|
||||
// Respond to BIP35 mempool requests
|
||||
if (fSendTrickle && pto->fSendMempool) {
|
||||
std::vector<uint256> vtxid;
|
||||
|
@ -5843,6 +5854,11 @@ bool SendMessages(CNode* pto)
|
|||
for (std::set<uint256>::iterator it = pto->setInventoryTxToSend.begin(); it != pto->setInventoryTxToSend.end(); it++) {
|
||||
vInvTx.push_back(it);
|
||||
}
|
||||
CAmount filterrate = 0;
|
||||
{
|
||||
LOCK(pto->cs_feeFilter);
|
||||
filterrate = pto->minFeeFilter;
|
||||
}
|
||||
// Topologically and fee-rate sort the inventory we send for privacy and priority reasons.
|
||||
// A heap is used so that not all items need sorting if only a few are being sent.
|
||||
CompareInvMempoolOrder compareInvMempoolOrder(&mempool);
|
||||
|
@ -5850,6 +5866,7 @@ bool SendMessages(CNode* pto)
|
|||
// No reason to drain out at many times the network's capacity,
|
||||
// especially since we have many peers and some will draw much shorter delays.
|
||||
unsigned int nRelayedTransactions = 0;
|
||||
LOCK(pto->cs_filter);
|
||||
while (!vInvTx.empty() && nRelayedTransactions < INVENTORY_BROADCAST_MAX) {
|
||||
// Fetch the top element from the heap
|
||||
std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
|
||||
|
@ -5862,6 +5879,19 @@ bool SendMessages(CNode* pto)
|
|||
if (pto->filterInventoryKnown.contains(hash)) {
|
||||
continue;
|
||||
}
|
||||
// Not in the mempool anymore? don't bother sending it.
|
||||
CFeeRate feeRate;
|
||||
if (!mempool.lookupFeeRate(hash, feeRate)) {
|
||||
continue;
|
||||
}
|
||||
if (filterrate && feeRate.GetFeePerK() < filterrate) {
|
||||
continue;
|
||||
}
|
||||
if (pto->pfilter) {
|
||||
CTransaction tx;
|
||||
if (!mempool.lookup(hash, tx)) continue;
|
||||
if (!pto->pfilter->IsRelevantAndUpdate(tx)) continue;
|
||||
}
|
||||
// Send
|
||||
vInv.push_back(CInv(MSG_TX, hash));
|
||||
nRelayedTransactions++;
|
||||
|
|
13
src/net.cpp
13
src/net.cpp
|
@ -2071,19 +2071,6 @@ void RelayTransaction(const CTransaction& tx, CFeeRate feerate)
|
|||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
if(!pnode->fRelayTxes)
|
||||
continue;
|
||||
{
|
||||
LOCK(pnode->cs_feeFilter);
|
||||
if (feerate.GetFeePerK() < pnode->minFeeFilter)
|
||||
continue;
|
||||
}
|
||||
LOCK(pnode->cs_filter);
|
||||
if (pnode->pfilter)
|
||||
{
|
||||
if (pnode->pfilter->IsRelevantAndUpdate(tx))
|
||||
pnode->PushInventory(inv);
|
||||
} else
|
||||
pnode->PushInventory(inv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,7 +357,7 @@ public:
|
|||
// a) it allows us to not relay tx invs before receiving the peer's version message
|
||||
// b) the peer may tell us in its version message that we should not relay tx invs
|
||||
// unless it loads a bloom filter.
|
||||
bool fRelayTxes;
|
||||
bool fRelayTxes; //protected by cs_filter
|
||||
bool fSentAddr;
|
||||
CSemaphoreGrant grantOutbound;
|
||||
CCriticalSection cs_filter;
|
||||
|
|
Loading…
Reference in a new issue