core/bloombits, eth/filters: handle null topics (#15195)

When implementing the new bloombits based filter, I've accidentally broke null
topics by removing the special casing of common.Hash{} filter rules, which
acted as the wildcard topic until now.

This PR fixes the regression, but instead of using the magic hash
common.Hash{} as the null wildcard, the PR reworks the code to handle nil
topics during parsing, converting a JSON null into nil []common.Hash topic.
This commit is contained in:
Péter Szilágyi
2017-09-27 13:14:52 +03:00
committed by Felix Lange
parent 860e697b00
commit 2ab2a9f131
7 changed files with 68 additions and 48 deletions

View File

@ -60,7 +60,9 @@ type Filter struct {
// New creates a new filter which uses a bloom filter on blocks to figure out whether
// a particular block is interesting or not.
func New(backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter {
// Flatten the address and topic filter clauses into a single filter system
// Flatten the address and topic filter clauses into a single bloombits filter
// system. Since the bloombits are not positional, nil topics are permitted,
// which get flattened into a nil byte slice.
var filters [][][]byte
if len(addresses) > 0 {
filter := make([][]byte, len(addresses))
@ -235,32 +237,24 @@ Logs:
if len(addresses) > 0 && !includes(addresses, log.Address) {
continue
}
logTopics := make([]common.Hash, len(topics))
copy(logTopics, log.Topics)
// If the to filtered topics is greater than the amount of topics in logs, skip.
if len(topics) > len(log.Topics) {
continue Logs
}
for i, topics := range topics {
var match bool
match := len(topics) == 0 // empty rule set == wildcard
for _, topic := range topics {
// common.Hash{} is a match all (wildcard)
if (topic == common.Hash{}) || log.Topics[i] == topic {
if log.Topics[i] == topic {
match = true
break
}
}
if !match {
continue Logs
}
}
ret = append(ret, log)
}
return ret
}
@ -273,16 +267,15 @@ func bloomFilter(bloom types.Bloom, addresses []common.Address, topics [][]commo
break
}
}
if !included {
return false
}
}
for _, sub := range topics {
var included bool
included := len(sub) == 0 // empty rule set == wildcard
for _, topic := range sub {
if (topic == common.Hash{}) || types.BloomLookup(bloom, topic) {
if types.BloomLookup(bloom, topic) {
included = true
break
}
@ -291,6 +284,5 @@ func bloomFilter(bloom types.Bloom, addresses []common.Address, topics [][]commo
return false
}
}
return true
}