11package  blockchain
22
33import  (
4- 	"encoding/binary" 
54	"errors" 
65	"fmt" 
76	"io" 
@@ -10,7 +9,6 @@ import (
109	"github.com/NethermindEth/juno/core" 
1110	"github.com/NethermindEth/juno/core/felt" 
1211	"github.com/NethermindEth/juno/db" 
13- 	"github.com/bits-and-blooms/bloom/v3" 
1412)
1513
1614var  errChunkSizeReached  =  errors .New ("chunk size reached" )
@@ -26,13 +24,12 @@ type EventFilterer interface {
2624}
2725
2826type  EventFilter  struct  {
29- 	txn              db.Transaction 
30- 	fromBlock        uint64 
31- 	toBlock          uint64 
32- 	contractAddress  * felt.Felt 
33- 	keys             [][]felt.Felt 
34- 	maxScanned       uint  // maximum number of scanned blocks in single call. 
35- 	pendingBlockFn   func () * core.Block 
27+ 	txn             db.Transaction 
28+ 	fromBlock       uint64 
29+ 	toBlock         uint64 
30+ 	matcher         EventMatcher 
31+ 	maxScanned      uint  // maximum number of scanned blocks in single call. 
32+ 	pendingBlockFn  func () * core.Block 
3633}
3734
3835type  EventFilterRange  uint 
@@ -46,13 +43,12 @@ func newEventFilter(txn db.Transaction, contractAddress *felt.Felt, keys [][]fel
4643	pendingBlockFn  func () * core.Block ,
4744) * EventFilter  {
4845	return  & EventFilter {
49- 		txn :             txn ,
50- 		contractAddress : contractAddress ,
51- 		keys :            keys ,
52- 		fromBlock :       fromBlock ,
53- 		toBlock :         toBlock ,
54- 		maxScanned :      math .MaxUint ,
55- 		pendingBlockFn :  pendingBlockFn ,
46+ 		txn :            txn ,
47+ 		matcher :        NewEventMatcher (contractAddress , keys ),
48+ 		fromBlock :      fromBlock ,
49+ 		toBlock :        toBlock ,
50+ 		maxScanned :     math .MaxUint ,
51+ 		pendingBlockFn : pendingBlockFn ,
5652	}
5753}
5854
@@ -128,8 +124,6 @@ func (e *EventFilter) Events(cToken *ContinuationToken, chunkSize uint64) ([]*Fi
128124		}
129125	}
130126
131- 	filterKeysMaps  :=  makeKeysMaps (e .keys )
132- 
133127	curBlock  :=  e .fromBlock 
134128	// skip the blocks that we previously processed for this request 
135129	if  cToken  !=  nil  {
@@ -151,7 +145,7 @@ func (e *EventFilter) Events(cToken *ContinuationToken, chunkSize uint64) ([]*Fi
151145			header  =  pending .Header 
152146		}
153147
154- 		if  possibleMatches  :=  e .testBloom (header .EventsBloom ,  filterKeysMaps ); ! possibleMatches  {
148+ 		if  possibleMatches  :=  e .matcher . TestBloom (header .EventsBloom ); ! possibleMatches  {
155149			// bloom filter says no events match the filter, skip this block entirely if from is not nil 
156150			continue 
157151		}
@@ -167,7 +161,7 @@ func (e *EventFilter) Events(cToken *ContinuationToken, chunkSize uint64) ([]*Fi
167161		}
168162
169163		var  processedEvents  uint64 
170- 		matchedEvents , processedEvents , err  =  e .appendBlockEvents (matchedEvents , header , receipts ,  filterKeysMaps , cToken , chunkSize )
164+ 		matchedEvents , processedEvents , err  =  e .matcher . AppendBlockEvents (matchedEvents , header , receipts , cToken , chunkSize )
171165		if  err  !=  nil  {
172166			if  errors .Is (err , errChunkSizeReached ) {
173167				rToken  =  & ContinuationToken {fromBlock : curBlock , processedEvents : processedEvents }
@@ -182,120 +176,3 @@ func (e *EventFilter) Events(cToken *ContinuationToken, chunkSize uint64) ([]*Fi
182176	}
183177	return  matchedEvents , rToken , nil 
184178}
185- 
186- func  (e  * EventFilter ) testBloom (bloomFilter  * bloom.BloomFilter , keysMap  []map [felt.Felt ]struct {}) bool  {
187- 	possibleMatches  :=  true 
188- 	if  e .contractAddress  !=  nil  {
189- 		addrBytes  :=  e .contractAddress .Bytes ()
190- 		possibleMatches  =  bloomFilter .Test (addrBytes [:])
191- 		// bloom filter says no events from this contract 
192- 		if  ! possibleMatches  {
193- 			return  possibleMatches 
194- 		}
195- 	}
196- 
197- 	for  index , kMap  :=  range  keysMap  {
198- 		for  key  :=  range  kMap  {
199- 			keyBytes  :=  key .Bytes ()
200- 			keyAndIndexBytes  :=  binary .AppendVarint (keyBytes [:], int64 (index ))
201- 
202- 			// check if block possibly contains the event we are looking for 
203- 			possibleMatches  =  bloomFilter .Test (keyAndIndexBytes )
204- 			// possible match for this index, no need to continue checking the rest of the keys 
205- 			if  possibleMatches  {
206- 				break 
207- 			}
208- 		}
209- 
210- 		// no key on this index matches the filter 
211- 		if  ! possibleMatches  {
212- 			break 
213- 		}
214- 	}
215- 
216- 	return  possibleMatches 
217- }
218- 
219- func  (e  * EventFilter ) appendBlockEvents (matchedEventsSofar  []* FilteredEvent , header  * core.Header ,
220- 	receipts  []* core.TransactionReceipt , keysMap  []map [felt.Felt ]struct {}, cToken  * ContinuationToken , chunkSize  uint64 ,
221- ) ([]* FilteredEvent , uint64 , error ) {
222- 	processedEvents  :=  uint64 (0 )
223- 	for  _ , receipt  :=  range  receipts  {
224- 		for  i , event  :=  range  receipt .Events  {
225- 			var  blockNumber  * uint64 
226- 			// if header.Hash == nil it's a pending block 
227- 			if  header .Hash  !=  nil  {
228- 				blockNumber  =  & header .Number 
229- 			}
230- 
231- 			// if last request was interrupted mid-block, and we are still processing that block, skip events 
232- 			// that were already processed 
233- 			if  cToken  !=  nil  &&  header .Number  ==  cToken .fromBlock  &&  processedEvents  <  cToken .processedEvents  {
234- 				processedEvents ++ 
235- 				continue 
236- 			}
237- 
238- 			if  e .contractAddress  !=  nil  &&  ! event .From .Equal (e .contractAddress ) {
239- 				processedEvents ++ 
240- 				continue 
241- 			}
242- 
243- 			if  e .matchesEventKeys (event .Keys , keysMap ) {
244- 				if  uint64 (len (matchedEventsSofar )) <  chunkSize  {
245- 					matchedEventsSofar  =  append (matchedEventsSofar , & FilteredEvent {
246- 						BlockNumber :     blockNumber ,
247- 						BlockHash :       header .Hash ,
248- 						TransactionHash : receipt .TransactionHash ,
249- 						EventIndex :      i ,
250- 						Event :           event ,
251- 					})
252- 				} else  {
253- 					// we are at the capacity, return what we have accumulated so far and a continuation token 
254- 					return  matchedEventsSofar , processedEvents , errChunkSizeReached 
255- 				}
256- 			}
257- 			// count the events we processed for this block to include in the continuation token 
258- 			processedEvents ++ 
259- 		}
260- 	}
261- 	return  matchedEventsSofar , processedEvents , nil 
262- }
263- 
264- func  (e  * EventFilter ) matchesEventKeys (eventKeys  []* felt.Felt , keysMap  []map [felt.Felt ]struct {}) bool  {
265- 	// short circuit if event doest have enough keys 
266- 	for  i  :=  len (eventKeys ); i  <  len (keysMap ); i ++  {
267- 		if  len (keysMap [i ]) >  0  {
268- 			return  false 
269- 		}
270- 	}
271- 
272- 	/// e.keys = [["V1", "V2"], [], ["V3"]] means: 
273- 	/// ((event.Keys[0] == "V1" OR event.Keys[0] == "V2") AND (event.Keys[2] == "V3")). 
274- 	// 
275- 	// Essentially 
276- 	// for each event.Keys[i], (len(e.keys[i]) == 0 OR event.Keys[i] is in e.keys[i]) should hold 
277- 	for  index , eventKey  :=  range  eventKeys  {
278- 		// empty filter keys means match all 
279- 		if  index  >=  len (keysMap ) ||  len (keysMap [index ]) ==  0  {
280- 			break 
281- 		}
282- 		if  _ , found  :=  keysMap [index ][* eventKey ]; ! found  {
283- 			return  false 
284- 		}
285- 	}
286- 
287- 	return  true 
288- }
289- 
290- func  makeKeysMaps (filterKeys  [][]felt.Felt ) []map [felt.Felt ]struct {} {
291- 	filterKeysMaps  :=  make ([]map [felt.Felt ]struct {}, len (filterKeys ))
292- 	for  index , keys  :=  range  filterKeys  {
293- 		kMap  :=  make (map [felt.Felt ]struct {}, len (keys ))
294- 		for  _ , key  :=  range  keys  {
295- 			kMap [key ] =  struct {}{}
296- 		}
297- 		filterKeysMaps [index ] =  kMap 
298- 	}
299- 
300- 	return  filterKeysMaps 
301- }
0 commit comments