aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bloom.cpp20
-rw-r--r--src/bloom.h3
-rw-r--r--src/net.cpp2
3 files changed, 19 insertions, 6 deletions
diff --git a/src/bloom.cpp b/src/bloom.cpp
index 73b04aa3d6..e773bbbbdb 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -88,16 +88,21 @@ bool CBloomFilter::IsWithinSizeConstraints() const
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
}
-bool CBloomFilter::IsTransactionRelevantToFilter(const CTransaction& tx, const uint256& hash) const
+bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash)
{
+ bool fFound = false;
// Match if the filter contains the hash of tx
// for finding tx when they appear in a block
if (contains(hash))
- return true;
+ fFound = true;
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (unsigned int i = 0; i < tx.vout.size(); i++)
{
+ const CTxOut& txout = tx.vout[i];
// Match if the filter contains any arbitrary script data element in any scriptPubKey in tx
+ // If this matches, also add the specific output that was matched.
+ // This means clients don't have to update the filter themselves when a new relevant tx
+ // is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
CScript::const_iterator pc = txout.scriptPubKey.begin();
vector<unsigned char> data;
while (pc < txout.scriptPubKey.end())
@@ -106,10 +111,17 @@ bool CBloomFilter::IsTransactionRelevantToFilter(const CTransaction& tx, const u
if (!txout.scriptPubKey.GetOp(pc, opcode, data))
break;
if (data.size() != 0 && contains(data))
- return true;
+ {
+ fFound = true;
+ insert(COutPoint(hash, i));
+ break;
+ }
}
}
+ if (fFound)
+ return true;
+
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Match if the filter contains an outpoint tx spends
diff --git a/src/bloom.h b/src/bloom.h
index 335bb5e0bb..1a8a562dad 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -64,7 +64,8 @@ public:
// (catch a filter which was just deserialized which was too big)
bool IsWithinSizeConstraints() const;
- bool IsTransactionRelevantToFilter(const CTransaction& tx, const uint256& hash) const;
+ // Also adds any outputs which match the filter to the filter (to match their spending txes)
+ bool IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash);
};
#endif /* BITCOIN_BLOOM_H */
diff --git a/src/net.cpp b/src/net.cpp
index aafc7206cd..e88efcd19e 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2034,7 +2034,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
LOCK(pnode->cs_filter);
if (pnode->pfilter)
{
- if (pnode->pfilter->IsTransactionRelevantToFilter(tx, hash))
+ if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
pnode->PushInventory(inv);
} else
pnode->PushInventory(inv);