reworking messages => log

This commit is contained in:
obscuren 2015-01-28 10:23:18 +01:00
parent c54a85ee64
commit f3e78c8f3c
5 changed files with 76 additions and 114 deletions

View File

@ -330,3 +330,24 @@ func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Mes
return state.Manifest().Messages, nil return state.Manifest().Messages, nil
} }
func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
if !sm.bc.HasBlock(block.Header().ParentHash) {
return nil, ParentError(block.Header().ParentHash)
}
sm.lastAttemptedBlock = block
var (
parent = sm.bc.GetBlock(block.Header().ParentHash)
//state = state.New(parent.Trie().Copy())
state = state.New(parent.Root(), sm.db)
)
defer state.Reset()
sm.TransitionState(state, parent, block)
sm.AccumelateRewards(state, block, parent)
return state.Logs(), nil
}

View File

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

View File

@ -77,13 +77,13 @@ out:
} }
self.filterMu.RUnlock() self.filterMu.RUnlock()
case state.Messages: case state.Logs:
self.filterMu.RLock() self.filterMu.RLock()
for _, filter := range self.filters { for _, filter := range self.filters {
if filter.MessageCallback != nil { if filter.LogsCallback != nil {
msgs := filter.FilterMessages(event) msgs := filter.FilterLogs(event)
if len(msgs) > 0 { if len(msgs) > 0 {
filter.MessageCallback(msgs) filter.LogsCallback(msgs)
} }
} }
} }

View File

@ -28,14 +28,9 @@ func NewFilterFromMap(object map[string]interface{}, eth core.EthManager) *core.
filter.SetLatestBlock(val.Int()) filter.SetLatestBlock(val.Int())
} }
if object["to"] != nil { if object["address"] != nil {
val := ethutil.NewValue(object["to"]) val := ethutil.NewValue(object["address"])
filter.AddTo(fromHex(val.Str())) filter.SetAddress(fromHex(val.Str()))
}
if object["from"] != nil {
val := ethutil.NewValue(object["from"])
filter.AddFrom(fromHex(val.Str()))
} }
if object["max"] != nil { if object["max"] != nil {
@ -48,8 +43,8 @@ func NewFilterFromMap(object map[string]interface{}, eth core.EthManager) *core.
filter.SetSkip(int(val.Uint())) filter.SetSkip(int(val.Uint()))
} }
if object["altered"] != nil { if object["topics"] != nil {
filter.Altered = makeAltered(object["altered"]) filter.SetTopics(MakeTopics(object["topics"]))
} }
return filter return filter
@ -70,16 +65,13 @@ func mapToAccountChange(m map[string]interface{}) (d core.AccountChange) {
// data can come in in the following formats: // data can come in in the following formats:
// ["aabbccdd", {id: "ccddee", at: "11223344"}], "aabbcc", {id: "ccddee", at: "1122"} // ["aabbccdd", {id: "ccddee", at: "11223344"}], "aabbcc", {id: "ccddee", at: "1122"}
func makeAltered(v interface{}) (d []core.AccountChange) { func MakeTopics(v interface{}) (d [][]byte) {
if str, ok := v.(string); ok { if str, ok := v.(string); ok {
d = append(d, core.AccountChange{fromHex(str), nil}) d = append(d, fromHex(str))
} else if obj, ok := v.(map[string]interface{}); ok { } else if slice, ok := v.([]string); ok {
d = append(d, mapToAccountChange(obj))
} else if slice, ok := v.([]interface{}); ok {
for _, item := range slice { for _, item := range slice {
d = append(d, makeAltered(item)...) d = append(d, fromHex(item))
} }
} }
return return
} }

View File

@ -9,24 +9,21 @@ import (
func NewFilterFromMap(object map[string]interface{}, eth core.EthManager) *core.Filter { func NewFilterFromMap(object map[string]interface{}, eth core.EthManager) *core.Filter {
filter := ui.NewFilterFromMap(object, eth) filter := ui.NewFilterFromMap(object, eth)
if object["altered"] != nil { if object["topics"] != nil {
filter.Altered = makeAltered(object["altered"]) filter.SetTopics(makeTopics(object["topics"]))
} }
return filter return filter
} }
func makeAltered(v interface{}) (d []core.AccountChange) { func makeTopics(v interface{}) (d [][]byte) {
if qList, ok := v.(*qml.List); ok { if qList, ok := v.(*qml.List); ok {
var s []interface{} var s []string
qList.Convert(&s) qList.Convert(&s)
d = makeAltered(s) d = ui.MakeTopics(s)
} else if qMap, ok := v.(*qml.Map); ok { } else if str, ok := v.(string); ok {
var m map[string]interface{} d = ui.MakeTopics(str)
qMap.Convert(&m)
d = makeAltered(m)
} }
return return