|
|
|
@ -3,10 +3,8 @@ package core |
|
|
|
|
import ( |
|
|
|
|
"bytes" |
|
|
|
|
"math" |
|
|
|
|
"math/big" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/core/types" |
|
|
|
|
"github.com/ethereum/go-ethereum/ethutil" |
|
|
|
|
"github.com/ethereum/go-ethereum/state" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -20,13 +18,12 @@ type Filter struct { |
|
|
|
|
earliest int64 |
|
|
|
|
latest int64 |
|
|
|
|
skip int |
|
|
|
|
from, to [][]byte |
|
|
|
|
address []byte |
|
|
|
|
max int |
|
|
|
|
|
|
|
|
|
Altered []AccountChange |
|
|
|
|
topics [][]byte |
|
|
|
|
|
|
|
|
|
BlockCallback func(*types.Block) |
|
|
|
|
MessageCallback func(state.Messages) |
|
|
|
|
LogsCallback func(state.Logs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create a new filter which uses a bloom filter on blocks to figure out whether a particular block
|
|
|
|
@ -35,10 +32,6 @@ func NewFilter(eth EthManager) *Filter { |
|
|
|
|
return &Filter{eth: eth} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) AddAltered(address, stateAddress []byte) { |
|
|
|
|
self.Altered = append(self.Altered, AccountChange{address, stateAddress}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set the earliest and latest block for filtering.
|
|
|
|
|
// -1 = latest block (i.e., the current block)
|
|
|
|
|
// hash = particular hash from-to
|
|
|
|
@ -50,20 +43,12 @@ func (self *Filter) SetLatestBlock(latest int64) { |
|
|
|
|
self.latest = latest |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) SetFrom(addr [][]byte) { |
|
|
|
|
self.from = addr |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) AddFrom(addr []byte) { |
|
|
|
|
self.from = append(self.from, addr) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) SetTo(addr [][]byte) { |
|
|
|
|
self.to = addr |
|
|
|
|
func (self *Filter) SetAddress(addr []byte) { |
|
|
|
|
self.address = addr |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) AddTo(addr []byte) { |
|
|
|
|
self.to = append(self.to, addr) |
|
|
|
|
func (self *Filter) SetTopics(topics [][]byte) { |
|
|
|
|
self.topics = topics |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) SetMax(max int) { |
|
|
|
@ -74,8 +59,8 @@ func (self *Filter) SetSkip(skip int) { |
|
|
|
|
self.skip = skip |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Run filters messages with the current parameters set
|
|
|
|
|
func (self *Filter) Find() []*state.Message { |
|
|
|
|
// Run filters logs with the current parameters set
|
|
|
|
|
func (self *Filter) Find() state.Logs { |
|
|
|
|
earliestBlock := self.eth.ChainManager().CurrentBlock() |
|
|
|
|
var earliestBlockNo uint64 = uint64(self.earliest) |
|
|
|
|
if self.earliest == -1 { |
|
|
|
@ -87,7 +72,7 @@ func (self *Filter) Find() []*state.Message { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
messages []*state.Message |
|
|
|
|
logs state.Logs |
|
|
|
|
block = self.eth.ChainManager().GetBlockByNumber(latestBlockNo) |
|
|
|
|
quit bool |
|
|
|
|
) |
|
|
|
@ -96,30 +81,30 @@ func (self *Filter) Find() []*state.Message { |
|
|
|
|
switch { |
|
|
|
|
case block.NumberU64() == earliestBlockNo, block.NumberU64() == 0: |
|
|
|
|
quit = true |
|
|
|
|
case self.max <= len(messages): |
|
|
|
|
case self.max <= len(logs): |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Use bloom filtering to see if this block is interesting given the
|
|
|
|
|
// current parameters
|
|
|
|
|
if self.bloomFilter(block) { |
|
|
|
|
// Get the messages of the block
|
|
|
|
|
msgs, err := self.eth.BlockProcessor().GetMessages(block) |
|
|
|
|
// Get the logs of the block
|
|
|
|
|
logs, err := self.eth.BlockProcessor().GetLogs(block) |
|
|
|
|
if err != nil { |
|
|
|
|
chainlogger.Warnln("err: filter get messages ", err) |
|
|
|
|
chainlogger.Warnln("err: filter get logs ", err) |
|
|
|
|
|
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
messages = append(messages, self.FilterMessages(msgs)...) |
|
|
|
|
logs = append(logs, self.FilterLogs(logs)...) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
block = self.eth.ChainManager().GetBlock(block.ParentHash()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
skip := int(math.Min(float64(len(messages)), float64(self.skip))) |
|
|
|
|
skip := int(math.Min(float64(len(logs)), float64(self.skip))) |
|
|
|
|
|
|
|
|
|
return messages[skip:] |
|
|
|
|
return logs[skip:] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func includes(addresses [][]byte, a []byte) (found bool) { |
|
|
|
@ -132,70 +117,37 @@ func includes(addresses [][]byte, a []byte) (found bool) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) FilterMessages(msgs []*state.Message) []*state.Message { |
|
|
|
|
var messages []*state.Message |
|
|
|
|
|
|
|
|
|
// Filter the messages for interesting stuff
|
|
|
|
|
for _, message := range msgs { |
|
|
|
|
if len(self.to) > 0 && !includes(self.to, message.To) { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(self.from) > 0 && !includes(self.from, message.From) { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var match bool |
|
|
|
|
if len(self.Altered) == 0 { |
|
|
|
|
match = true |
|
|
|
|
} |
|
|
|
|
func (self *Filter) FilterLogs(logs state.Logs) state.Logs { |
|
|
|
|
var ret state.Logs |
|
|
|
|
|
|
|
|
|
for _, accountChange := range self.Altered { |
|
|
|
|
if len(accountChange.Address) > 0 && bytes.Compare(message.To, accountChange.Address) != 0 { |
|
|
|
|
// Filter the logs for interesting stuff
|
|
|
|
|
for _, log := range logs { |
|
|
|
|
if len(self.address) > 0 && !bytes.Equal(self.address, log.Address()) { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(accountChange.StateAddress) > 0 && !includes(message.ChangedAddresses, accountChange.StateAddress) { |
|
|
|
|
for _, topic := range self.topics { |
|
|
|
|
if !includes(log.Topics(), topic) { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
match = true |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if !match { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
messages = append(messages, message) |
|
|
|
|
ret = append(ret, log) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return messages |
|
|
|
|
return ret |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) bloomFilter(block *types.Block) bool { |
|
|
|
|
var fromIncluded, toIncluded bool |
|
|
|
|
if len(self.from) > 0 { |
|
|
|
|
for _, from := range self.from { |
|
|
|
|
if types.BloomLookup(block.Bloom(), from) || bytes.Equal(block.Coinbase(), from) { |
|
|
|
|
fromIncluded = true |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
fromIncluded = true |
|
|
|
|
if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(self.to) > 0 { |
|
|
|
|
for _, to := range self.to { |
|
|
|
|
if types.BloomLookup(block.Bloom(), ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) || bytes.Equal(block.Coinbase(), to) { |
|
|
|
|
toIncluded = true |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
for _, topic := range self.topics { |
|
|
|
|
if !types.BloomLookup(block.Bloom(), topic) { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
toIncluded = true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return fromIncluded && toIncluded |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|