diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index c8e5c610e..467c54058 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -236,6 +236,16 @@ func (self *BlockChain) GetBlockByNumber(num uint64) *Block { return block } +func (self *BlockChain) GetBlockBack(num uint64) *Block { + block := self.CurrentBlock + + for ; num != 0 && block != nil; num-- { + block = self.GetBlock(block.PrevHash) + } + + return block +} + func (bc *BlockChain) BlockInfoByHash(hash []byte) BlockInfo { bi := BlockInfo{} data, _ := ethutil.Config.Db.Get(append(hash, []byte("Info")...)) diff --git a/ethchain/filter.go b/ethchain/filter.go index d9f1796f4..0a97b3f98 100644 --- a/ethchain/filter.go +++ b/ethchain/filter.go @@ -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) { diff --git a/ethutil/value.go b/ethutil/value.go index b1f887f29..dd777fa43 100644 --- a/ethutil/value.go +++ b/ethutil/value.go @@ -63,6 +63,10 @@ func (val *Value) Uint() uint64 { return uint64(Val) } else if Val, ok := val.Val.(uint64); ok { return Val + } else if Val, ok := val.Val.(float32); ok { + return uint64(Val) + } else if Val, ok := val.Val.(float64); ok { + return uint64(Val) } else if Val, ok := val.Val.(int); ok { return uint64(Val) } else if Val, ok := val.Val.(uint); ok {