mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
eth/filters: Simple refactor of log filters to support iterative retrieval
This commit is contained in:
parent
ee445a2ba4
commit
82844f06f2
1 changed files with 34 additions and 19 deletions
|
|
@ -85,8 +85,7 @@ func (f *Filter) SetTopics(topics [][]common.Hash) {
|
||||||
f.topics = topics
|
f.topics = topics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run filters logs with the current parameters set
|
func (f *Filter) FindOnce(ctx context.Context) ([]*vm.Log, error) {
|
||||||
func (f *Filter) Find(ctx context.Context) ([]*vm.Log, error) {
|
|
||||||
head, _ := f.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
|
head, _ := f.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
|
||||||
if head == nil {
|
if head == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -106,12 +105,28 @@ func (f *Filter) Find(ctx context.Context) ([]*vm.Log, error) {
|
||||||
// uses the mipmap bloom filters to check for fast inclusion and uses
|
// uses the mipmap bloom filters to check for fast inclusion and uses
|
||||||
// higher range probability in order to ensure at least a false positive
|
// higher range probability in order to ensure at least a false positive
|
||||||
if !f.useMipMap || len(f.addresses) == 0 {
|
if !f.useMipMap || len(f.addresses) == 0 {
|
||||||
return f.getLogs(ctx, beginBlockNo, endBlockNo)
|
logs, blockNumber, err := f.getLogs(ctx, beginBlockNo, endBlockNo)
|
||||||
}
|
f.begin = int64(blockNumber + 1)
|
||||||
return f.mipFind(beginBlockNo, endBlockNo, 0), nil
|
return logs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Filter) mipFind(start, end uint64, depth int) (logs []*vm.Log) {
|
logs, blockNumber := f.mipFind(beginBlockNo, endBlockNo, 0)
|
||||||
|
f.begin = int64(blockNumber + 1)
|
||||||
|
return logs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run filters logs with the current parameters set
|
||||||
|
func (f *Filter) Find(ctx context.Context) (logs []*vm.Log, err error) {
|
||||||
|
for {
|
||||||
|
newLogs, err := f.FindOnce(ctx)
|
||||||
|
if len(newLogs) == 0 || err != nil {
|
||||||
|
return logs, err
|
||||||
|
}
|
||||||
|
logs = append(logs, newLogs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Filter) mipFind(start, end uint64, depth int) (logs []*vm.Log, blockNumber uint64) {
|
||||||
level := core.MIPMapLevels[depth]
|
level := core.MIPMapLevels[depth]
|
||||||
// normalise numerator so we can work in level specific batches and
|
// normalise numerator so we can work in level specific batches and
|
||||||
// work with the proper range checks
|
// work with the proper range checks
|
||||||
|
|
@ -126,27 +141,24 @@ func (f *Filter) mipFind(start, end uint64, depth int) (logs []*vm.Log) {
|
||||||
start := uint64(math.Max(float64(num), float64(start)))
|
start := uint64(math.Max(float64(num), float64(start)))
|
||||||
end := uint64(math.Min(float64(num+level-1), float64(end)))
|
end := uint64(math.Min(float64(num+level-1), float64(end)))
|
||||||
if depth+1 == len(core.MIPMapLevels) {
|
if depth+1 == len(core.MIPMapLevels) {
|
||||||
l, _ := f.getLogs(context.Background(), start, end)
|
l, blockNumber, _ := f.getLogs(context.Background(), start, end)
|
||||||
logs = append(logs, l...)
|
return l, blockNumber
|
||||||
} else {
|
} else {
|
||||||
logs = append(logs, f.mipFind(start, end, depth+1)...)
|
return f.mipFind(start, end, depth+1)
|
||||||
}
|
}
|
||||||
// break so we don't check the same range for each
|
|
||||||
// possible address. Checks on multiple addresses
|
|
||||||
// are handled further down the stack.
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return logs
|
return nil, end
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Filter) getLogs(ctx context.Context, start, end uint64) (logs []*vm.Log, err error) {
|
func (f *Filter) getLogs(ctx context.Context, start, end uint64) (logs []*vm.Log, blockNumber uint64, err error) {
|
||||||
for i := start; i <= end; i++ {
|
for i := start; i <= end; i++ {
|
||||||
header, err := f.backend.HeaderByNumber(ctx, rpc.BlockNumber(i))
|
blockNumber := rpc.BlockNumber(i)
|
||||||
|
header, err := f.backend.HeaderByNumber(ctx, blockNumber)
|
||||||
if header == nil || err != nil {
|
if header == nil || err != nil {
|
||||||
return logs, err
|
return logs, end, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use bloom filtering to see if this block is interesting given the
|
// Use bloom filtering to see if this block is interesting given the
|
||||||
|
|
@ -155,17 +167,20 @@ func (f *Filter) getLogs(ctx context.Context, start, end uint64) (logs []*vm.Log
|
||||||
// Get the logs of the block
|
// Get the logs of the block
|
||||||
receipts, err := f.backend.GetReceipts(ctx, header.Hash())
|
receipts, err := f.backend.GetReceipts(ctx, header.Hash())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, end, err
|
||||||
}
|
}
|
||||||
var unfiltered []*vm.Log
|
var unfiltered []*vm.Log
|
||||||
for _, receipt := range receipts {
|
for _, receipt := range receipts {
|
||||||
unfiltered = append(unfiltered, ([]*vm.Log)(receipt.Logs)...)
|
unfiltered = append(unfiltered, ([]*vm.Log)(receipt.Logs)...)
|
||||||
}
|
}
|
||||||
logs = append(logs, filterLogs(unfiltered, nil, nil, f.addresses, f.topics)...)
|
logs = filterLogs(unfiltered, nil, nil, f.addresses, f.topics)
|
||||||
|
if len(logs) > 0 {
|
||||||
|
return logs, uint64(blockNumber), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return logs, nil
|
return logs, end, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func includes(addresses []common.Address, a common.Address) bool {
|
func includes(addresses []common.Address, a common.Address) bool {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue