Filter accepts multiple topics per entry. Fixes #403
This commit is contained in:
		
							parent
							
								
									ac88ae86a3
								
							
						
					
					
						commit
						6e50a1e9f5
					
				| @ -17,7 +17,7 @@ type FilterOptions struct { | ||||
| 	Latest   int64 | ||||
| 
 | ||||
| 	Address [][]byte | ||||
| 	Topics  [][]byte | ||||
| 	Topics  [][][]byte | ||||
| 
 | ||||
| 	Skip int | ||||
| 	Max  int | ||||
| @ -31,7 +31,7 @@ type Filter struct { | ||||
| 	skip     int | ||||
| 	address  [][]byte | ||||
| 	max      int | ||||
| 	topics   [][]byte | ||||
| 	topics   [][][]byte | ||||
| 
 | ||||
| 	BlockCallback   func(*types.Block) | ||||
| 	PendingCallback func(*types.Block) | ||||
| @ -44,6 +44,8 @@ func NewFilter(eth Backend) *Filter { | ||||
| 	return &Filter{eth: eth} | ||||
| } | ||||
| 
 | ||||
| // SetOptions copies the filter options to the filter it self. The reason for this "silly" copy
 | ||||
| // is simply because named arguments in this case is extremely nice and readable.
 | ||||
| func (self *Filter) SetOptions(options FilterOptions) { | ||||
| 	self.earliest = options.Earliest | ||||
| 	self.latest = options.Latest | ||||
| @ -69,7 +71,7 @@ func (self *Filter) SetAddress(addr [][]byte) { | ||||
| 	self.address = addr | ||||
| } | ||||
| 
 | ||||
| func (self *Filter) SetTopics(topics [][]byte) { | ||||
| func (self *Filter) SetTopics(topics [][][]byte) { | ||||
| 	self.topics = topics | ||||
| } | ||||
| 
 | ||||
| @ -149,10 +151,18 @@ Logs: | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		max := int(math.Min(float64(len(self.topics)), float64(len(log.Topics())))) | ||||
| 		for i := 0; i < max; i++ { | ||||
| 			if !bytes.Equal(log.Topics()[i], self.topics[i]) { | ||||
| 				continue Logs | ||||
| 		logTopics := make([][]byte, len(self.topics)) | ||||
| 		copy(logTopics, log.Topics()) | ||||
| 
 | ||||
| 		for i, topics := range self.topics { | ||||
| 			for _, topic := range topics { | ||||
| 				var match bool | ||||
| 				if bytes.Equal(log.Topics()[i], topic) { | ||||
| 					match = true | ||||
| 				} | ||||
| 				if !match { | ||||
| 					continue Logs | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| @ -177,8 +187,15 @@ func (self *Filter) bloomFilter(block *types.Block) bool { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for _, topic := range self.topics { | ||||
| 		if !types.BloomLookup(block.Bloom(), topic) { | ||||
| 	for _, sub := range self.topics { | ||||
| 		var included bool | ||||
| 		for _, topic := range sub { | ||||
| 			if types.BloomLookup(block.Bloom(), topic) { | ||||
| 				included = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		if !included { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -6,7 +6,6 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/eth" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/state" | ||||
| 	"github.com/ethereum/go-ethereum/ui" | ||||
| 	"github.com/ethereum/go-ethereum/xeth" | ||||
| 	"github.com/obscuren/otto" | ||||
| ) | ||||
| @ -96,17 +95,3 @@ func (self *JSEthereum) toVal(v interface{}) otto.Value { | ||||
| 
 | ||||
| 	return result | ||||
| } | ||||
| 
 | ||||
| func (self *JSEthereum) Messages(object map[string]interface{}) otto.Value { | ||||
| 	filter := ui.NewFilterFromMap(object, self.ethereum) | ||||
| 
 | ||||
| 	logs := filter.Find() | ||||
| 	var jslogs []JSLog | ||||
| 	for _, m := range logs { | ||||
| 		jslogs = append(jslogs, NewJSLog(m)) | ||||
| 	} | ||||
| 
 | ||||
| 	v, _ := self.vm.ToValue(jslogs) | ||||
| 
 | ||||
| 	return v | ||||
| } | ||||
|  | ||||
							
								
								
									
										18
									
								
								rpc/args.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								rpc/args.go
									
									
									
									
									
								
							| @ -197,7 +197,7 @@ type FilterOptions struct { | ||||
| 	Earliest int64 | ||||
| 	Latest   int64 | ||||
| 	Address  interface{} | ||||
| 	Topic    []string | ||||
| 	Topic    []interface{} | ||||
| 	Skip     int | ||||
| 	Max      int | ||||
| } | ||||
| @ -220,10 +220,20 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions { | ||||
| 
 | ||||
| 	opts.Earliest = options.Earliest | ||||
| 	opts.Latest = options.Latest | ||||
| 	opts.Topics = make([][]byte, len(options.Topic)) | ||||
| 	for i, topic := range options.Topic { | ||||
| 		opts.Topics[i] = fromHex(topic) | ||||
| 
 | ||||
| 	topics := make([][][]byte, len(options.Topic)) | ||||
| 	for i, topicDat := range options.Topic { | ||||
| 		if slice, ok := topicDat.([]interface{}); ok { | ||||
| 			topics[i] = make([][]byte, len(slice)) | ||||
| 			for j, topic := range slice { | ||||
| 				topics[i][j] = fromHex(topic.(string)) | ||||
| 			} | ||||
| 		} else if str, ok := topicDat.(string); ok { | ||||
| 			topics[i] = make([][]byte, 1) | ||||
| 			topics[i][0] = fromHex(str) | ||||
| 		} | ||||
| 	} | ||||
| 	opts.Topics = topics | ||||
| 
 | ||||
| 	return opts | ||||
| } | ||||
|  | ||||
							
								
								
									
										76
									
								
								ui/filter.go
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								ui/filter.go
									
									
									
									
									
								
							| @ -1,77 +1 @@ | ||||
| package ui | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/ethereum/go-ethereum/core" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| ) | ||||
| 
 | ||||
| func fromHex(s string) []byte { | ||||
| 	if len(s) > 1 { | ||||
| 		if s[0:2] == "0x" { | ||||
| 			s = s[2:] | ||||
| 		} | ||||
| 		return ethutil.Hex2Bytes(s) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func NewFilterFromMap(object map[string]interface{}, eth core.Backend) *core.Filter { | ||||
| 	filter := core.NewFilter(eth) | ||||
| 
 | ||||
| 	if object["earliest"] != nil { | ||||
| 		val := ethutil.NewValue(object["earliest"]) | ||||
| 		filter.SetEarliestBlock(val.Int()) | ||||
| 	} | ||||
| 
 | ||||
| 	if object["latest"] != nil { | ||||
| 		val := ethutil.NewValue(object["latest"]) | ||||
| 		filter.SetLatestBlock(val.Int()) | ||||
| 	} | ||||
| 
 | ||||
| 	if object["address"] != nil { | ||||
| 		//val := ethutil.NewValue(object["address"])
 | ||||
| 		//filter.SetAddress(fromHex(val.Str()))
 | ||||
| 	} | ||||
| 
 | ||||
| 	if object["max"] != nil { | ||||
| 		val := ethutil.NewValue(object["max"]) | ||||
| 		filter.SetMax(int(val.Uint())) | ||||
| 	} | ||||
| 
 | ||||
| 	if object["skip"] != nil { | ||||
| 		val := ethutil.NewValue(object["skip"]) | ||||
| 		filter.SetSkip(int(val.Uint())) | ||||
| 	} | ||||
| 
 | ||||
| 	if object["topics"] != nil { | ||||
| 		filter.SetTopics(MakeTopics(object["topics"])) | ||||
| 	} | ||||
| 
 | ||||
| 	return filter | ||||
| } | ||||
| 
 | ||||
| // Conversion methodn
 | ||||
| func mapToAccountChange(m map[string]interface{}) (d core.AccountChange) { | ||||
| 	if str, ok := m["id"].(string); ok { | ||||
| 		d.Address = fromHex(str) | ||||
| 	} | ||||
| 
 | ||||
| 	if str, ok := m["at"].(string); ok { | ||||
| 		d.StateAddress = fromHex(str) | ||||
| 	} | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // data can come in in the following formats:
 | ||||
| // ["aabbccdd", {id: "ccddee", at: "11223344"}], "aabbcc", {id: "ccddee", at: "1122"}
 | ||||
| func MakeTopics(v interface{}) (d [][]byte) { | ||||
| 	if str, ok := v.(string); ok { | ||||
| 		d = append(d, fromHex(str)) | ||||
| 	} else if slice, ok := v.([]string); ok { | ||||
| 		for _, item := range slice { | ||||
| 			d = append(d, fromHex(item)) | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user