diff --git a/src/bloom.cpp b/src/bloom.cpp index 73b04aa3..e773bbbb 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 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 335bb5e0..1a8a562d 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 aafc7206..e88efcd1 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);