@@ -239,11 +239,17 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc
239239 return & rpc.Subscription {}, rpc .ErrNotificationsUnsupported
240240 }
241241
242- rpcSub := notifier .CreateSubscription ()
242+ var (
243+ rpcSub = notifier .CreateSubscription ()
244+ matchedLogs = make (chan []Log )
245+ )
246+
247+ logsSub , err := api .events .SubscribeLogs (crit , matchedLogs )
248+ if err != nil {
249+ return nil , err
250+ }
243251
244252 go func () {
245- matchedLogs := make (chan []Log )
246- logsSub := api .events .SubscribeLogs (crit , matchedLogs )
247253
248254 for {
249255 select {
@@ -276,18 +282,20 @@ type FilterCriteria struct {
276282// used to retrieve logs when the state changes. This method cannot be
277283// used to fetch logs that are already stored in the state.
278284//
285+ // Default criteria for the from and to block are "latest".
286+ // Using "latest" as block number will return logs for mined blocks.
287+ // Using "pending" as block number returns logs for not yet mined (pending) blocks.
288+ // In case logs are removed (chain reorg) previously returned logs are returned
289+ // again but with the removed property set to true.
290+ //
291+ // In case "fromBlock" > "toBlock" an error is returned.
292+ //
279293// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter
280- func (api * PublicFilterAPI ) NewFilter (crit FilterCriteria ) rpc.ID {
281- var (
282- logs = make (chan []Log )
283- logsSub = api .events .SubscribeLogs (crit , logs )
284- )
285-
286- if crit .FromBlock == nil {
287- crit .FromBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
288- }
289- if crit .ToBlock == nil {
290- crit .ToBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
294+ func (api * PublicFilterAPI ) NewFilter (crit FilterCriteria ) (rpc.ID , error ) {
295+ logs := make (chan []Log )
296+ logsSub , err := api .events .SubscribeLogs (crit , logs )
297+ if err != nil {
298+ return rpc .ID ("" ), err
291299 }
292300
293301 api .filtersMu .Lock ()
@@ -312,7 +320,7 @@ func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) rpc.ID {
312320 }
313321 }()
314322
315- return logsSub .ID
323+ return logsSub .ID , nil
316324}
317325
318326// GetLogs returns logs matching the given argument that are stored within the state.
@@ -363,28 +371,38 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]Log
363371 api .filtersMu .Unlock ()
364372
365373 if ! found || f .typ != LogsSubscription {
366- return [] Log {}, nil
374+ return nil , fmt . Errorf ( "filter not found" )
367375 }
368376
369377 filter := New (api .backend , api .useMipMap )
370- filter .SetBeginBlock (f .crit .FromBlock .Int64 ())
371- filter .SetEndBlock (f .crit .ToBlock .Int64 ())
378+ if f .crit .FromBlock != nil {
379+ filter .SetBeginBlock (f .crit .FromBlock .Int64 ())
380+ } else {
381+ filter .SetBeginBlock (rpc .LatestBlockNumber .Int64 ())
382+ }
383+ if f .crit .ToBlock != nil {
384+ filter .SetEndBlock (f .crit .ToBlock .Int64 ())
385+ } else {
386+ filter .SetEndBlock (rpc .LatestBlockNumber .Int64 ())
387+ }
372388 filter .SetAddresses (f .crit .Addresses )
373389 filter .SetTopics (f .crit .Topics )
374390
375- logs , err := filter .Find (ctx )
376- return returnLogs (logs ), err
391+ logs , err := filter .Find (ctx )
392+ if err != nil {
393+ return nil , err
394+ }
395+ return returnLogs (logs ), nil
377396}
378397
379398// GetFilterChanges returns the logs for the filter with the given id since
380399// last time is was called. This can be used for polling.
381400//
382401// For pending transaction and block filters the result is []common.Hash.
383- // (pending)Log filters return []Log. If the filter could not be found
384- // []interface{}{} is returned.
402+ // (pending)Log filters return []Log.
385403//
386404// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges
387- func (api * PublicFilterAPI ) GetFilterChanges (id rpc.ID ) interface {} {
405+ func (api * PublicFilterAPI ) GetFilterChanges (id rpc.ID ) ( interface {}, error ) {
388406 api .filtersMu .Lock ()
389407 defer api .filtersMu .Unlock ()
390408
@@ -400,15 +418,15 @@ func (api *PublicFilterAPI) GetFilterChanges(id rpc.ID) interface{} {
400418 case PendingTransactionsSubscription , BlocksSubscription :
401419 hashes := f .hashes
402420 f .hashes = nil
403- return returnHashes (hashes )
404- case PendingLogsSubscription , LogsSubscription :
421+ return returnHashes (hashes ), nil
422+ case LogsSubscription :
405423 logs := f .logs
406424 f .logs = nil
407- return returnLogs (logs )
425+ return returnLogs (logs ), nil
408426 }
409427 }
410428
411- return []interface {}{}
429+ return []interface {}{}, fmt . Errorf ( "filter not found" )
412430}
413431
414432// returnHashes is a helper that will return an empty hash array case the given hash array is nil,
@@ -443,15 +461,11 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
443461 return err
444462 }
445463
446- if raw .From == nil || raw .From .Int64 () < 0 {
447- args .FromBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
448- } else {
464+ if raw .From != nil {
449465 args .FromBlock = big .NewInt (raw .From .Int64 ())
450466 }
451467
452- if raw .ToBlock == nil || raw .ToBlock .Int64 () < 0 {
453- args .ToBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
454- } else {
468+ if raw .ToBlock != nil {
455469 args .ToBlock = big .NewInt (raw .ToBlock .Int64 ())
456470 }
457471
0 commit comments