|
|
|
@ -3,6 +3,7 @@ package ethchain |
|
|
|
|
import ( |
|
|
|
|
"bytes" |
|
|
|
|
"fmt" |
|
|
|
|
"math" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/eth-go/ethstate" |
|
|
|
|
"github.com/ethereum/eth-go/ethutil" |
|
|
|
@ -16,8 +17,8 @@ type data struct { |
|
|
|
|
// Filtering interface
|
|
|
|
|
type Filter struct { |
|
|
|
|
eth EthManager |
|
|
|
|
earliest []byte |
|
|
|
|
latest []byte |
|
|
|
|
earliest int64 |
|
|
|
|
latest int64 |
|
|
|
|
skip int |
|
|
|
|
from, to [][]byte |
|
|
|
|
max int |
|
|
|
@ -38,37 +39,33 @@ func NewFilterFromMap(object map[string]interface{}, eth EthManager) *Filter { |
|
|
|
|
filter := NewFilter(eth) |
|
|
|
|
|
|
|
|
|
if object["earliest"] != nil { |
|
|
|
|
earliest := object["earliest"] |
|
|
|
|
if e, ok := earliest.(string); ok { |
|
|
|
|
filter.SetEarliestBlock(ethutil.Hex2Bytes(e)) |
|
|
|
|
} else { |
|
|
|
|
filter.SetEarliestBlock(earliest) |
|
|
|
|
} |
|
|
|
|
val := ethutil.NewValue(object["earliest"]) |
|
|
|
|
filter.SetEarliestBlock(val.Int()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if object["latest"] != nil { |
|
|
|
|
latest := object["latest"] |
|
|
|
|
if l, ok := latest.(string); ok { |
|
|
|
|
filter.SetLatestBlock(ethutil.Hex2Bytes(l)) |
|
|
|
|
} else { |
|
|
|
|
filter.SetLatestBlock(latest) |
|
|
|
|
} |
|
|
|
|
val := ethutil.NewValue(object["latest"]) |
|
|
|
|
filter.SetLatestBlock(val.Int()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if object["to"] != nil { |
|
|
|
|
filter.AddTo(ethutil.Hex2Bytes(object["to"].(string))) |
|
|
|
|
val := ethutil.NewValue(object["to"]) |
|
|
|
|
filter.AddTo(ethutil.Hex2Bytes(val.Str())) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if object["from"] != nil { |
|
|
|
|
filter.AddFrom(ethutil.Hex2Bytes(object["from"].(string))) |
|
|
|
|
val := ethutil.NewValue(object["from"]) |
|
|
|
|
filter.AddFrom(ethutil.Hex2Bytes(val.Str())) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if object["max"] != nil { |
|
|
|
|
filter.SetMax(object["max"].(int)) |
|
|
|
|
val := ethutil.NewValue(object["max"]) |
|
|
|
|
filter.SetMax(int(val.Uint())) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if object["skip"] != nil { |
|
|
|
|
filter.SetSkip(object["skip"].(int)) |
|
|
|
|
val := ethutil.NewValue(object["skip"]) |
|
|
|
|
filter.SetSkip(int(val.Uint())) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if object["altered"] != nil { |
|
|
|
@ -85,30 +82,12 @@ func (self *Filter) AddAltered(id, address []byte) { |
|
|
|
|
// Set the earliest and latest block for filtering.
|
|
|
|
|
// -1 = latest block (i.e., the current block)
|
|
|
|
|
// hash = particular hash from-to
|
|
|
|
|
func (self *Filter) SetEarliestBlock(earliest interface{}) { |
|
|
|
|
e := ethutil.NewValue(earliest) |
|
|
|
|
|
|
|
|
|
// Check for -1 (latest) otherwise assume bytes
|
|
|
|
|
if e.Int() == -1 { |
|
|
|
|
self.earliest = self.eth.BlockChain().CurrentBlock.Hash() |
|
|
|
|
} else if e.Len() > 0 { |
|
|
|
|
self.earliest = e.Bytes() |
|
|
|
|
} else { |
|
|
|
|
panic(fmt.Sprintf("earliest has to be either -1 or a valid hash: %v (%T)", e, e.Val)) |
|
|
|
|
} |
|
|
|
|
func (self *Filter) SetEarliestBlock(earliest int64) { |
|
|
|
|
self.earliest = earliest |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) SetLatestBlock(latest interface{}) { |
|
|
|
|
l := ethutil.NewValue(latest) |
|
|
|
|
|
|
|
|
|
// Check for -1 (latest) otherwise assume bytes
|
|
|
|
|
if l.Int() == -1 { |
|
|
|
|
self.latest = self.eth.BlockChain().CurrentBlock.Hash() |
|
|
|
|
} else if l.Len() > 0 { |
|
|
|
|
self.latest = l.Bytes() |
|
|
|
|
} else { |
|
|
|
|
panic(fmt.Sprintf("latest has to be either -1 or a valid hash: %v", l)) |
|
|
|
|
} |
|
|
|
|
func (self *Filter) SetLatestBlock(latest int64) { |
|
|
|
|
self.latest = latest |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *Filter) SetFrom(addr [][]byte) { |
|
|
|
@ -137,23 +116,27 @@ func (self *Filter) SetSkip(skip int) { |
|
|
|
|
|
|
|
|
|
// Run filters messages with the current parameters set
|
|
|
|
|
func (self *Filter) Find() []*ethstate.Message { |
|
|
|
|
var messages []*ethstate.Message |
|
|
|
|
|
|
|
|
|
block := self.eth.BlockChain().GetBlock(self.latest) |
|
|
|
|
|
|
|
|
|
// skip N blocks (useful for pagination)
|
|
|
|
|
if self.skip > 0 { |
|
|
|
|
for i := 0; i < i; i++ { |
|
|
|
|
block = self.eth.BlockChain().GetBlock(block.PrevHash) |
|
|
|
|
} |
|
|
|
|
var earliestBlockNo uint64 = uint64(self.earliest) |
|
|
|
|
if self.earliest == -1 { |
|
|
|
|
earliestBlockNo = self.eth.BlockChain().CurrentBlock.Number.Uint64() |
|
|
|
|
} |
|
|
|
|
var latestBlockNo uint64 = uint64(self.latest) |
|
|
|
|
if self.latest == -1 { |
|
|
|
|
latestBlockNo = self.eth.BlockChain().CurrentBlock.Number.Uint64() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Start block filtering
|
|
|
|
|
quit := false |
|
|
|
|
for i := 1; !quit && block != nil; i++ { |
|
|
|
|
// Mark last check
|
|
|
|
|
if self.max == i || (len(self.earliest) > 0 && bytes.Compare(block.Hash(), self.earliest) == 0) { |
|
|
|
|
var ( |
|
|
|
|
messages []*ethstate.Message |
|
|
|
|
block = self.eth.BlockChain().GetBlockByNumber(latestBlockNo) |
|
|
|
|
quit bool |
|
|
|
|
) |
|
|
|
|
for i := 0; !quit && block != nil; i++ { |
|
|
|
|
// Quit on latest
|
|
|
|
|
switch { |
|
|
|
|
case block.Number.Uint64() == earliestBlockNo: |
|
|
|
|
quit = true |
|
|
|
|
case self.max <= len(messages): |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Use bloom filtering to see if this block is interesting given the
|
|
|
|
@ -173,7 +156,9 @@ func (self *Filter) Find() []*ethstate.Message { |
|
|
|
|
block = self.eth.BlockChain().GetBlock(block.PrevHash) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return messages |
|
|
|
|
skip := int(math.Min(float64(len(messages)), float64(self.skip))) |
|
|
|
|
|
|
|
|
|
return messages[skip:] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func includes(addresses [][]byte, a []byte) (found bool) { |
|
|
|
|