github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/eth/filters/filter_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package filters
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"math/big"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/ethereum/go-ethereum/accounts/abi"
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/consensus/ethash"
    30  	"github.com/ethereum/go-ethereum/core"
    31  	"github.com/ethereum/go-ethereum/core/rawdb"
    32  	"github.com/ethereum/go-ethereum/core/types"
    33  	"github.com/ethereum/go-ethereum/core/vm"
    34  	"github.com/ethereum/go-ethereum/crypto"
    35  	"github.com/ethereum/go-ethereum/params"
    36  	"github.com/ethereum/go-ethereum/rpc"
    37  	"github.com/ethereum/go-ethereum/triedb"
    38  )
    39  
    40  func makeReceipt(addr common.Address) *types.Receipt {
    41  	receipt := types.NewReceipt(nil, false, 0)
    42  	receipt.Logs = []*types.Log{
    43  		{Address: addr},
    44  	}
    45  	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
    46  	return receipt
    47  }
    48  
    49  func BenchmarkFilters(b *testing.B) {
    50  	var (
    51  		db, _   = rawdb.NewLevelDBDatabase(b.TempDir(), 0, 0, "", false)
    52  		_, sys  = newTestFilterSystem(b, db, Config{})
    53  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    54  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
    55  		addr2   = common.BytesToAddress([]byte("jeff"))
    56  		addr3   = common.BytesToAddress([]byte("ethereum"))
    57  		addr4   = common.BytesToAddress([]byte("random addresses please"))
    58  
    59  		gspec = &core.Genesis{
    60  			Alloc:   types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
    61  			BaseFee: big.NewInt(params.InitialBaseFee),
    62  			Config:  params.TestChainConfig,
    63  		}
    64  	)
    65  	defer db.Close()
    66  	_, chain, receipts := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 100010, func(i int, gen *core.BlockGen) {
    67  		switch i {
    68  		case 2403:
    69  			receipt := makeReceipt(addr1)
    70  			gen.AddUncheckedReceipt(receipt)
    71  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    72  		case 1034:
    73  			receipt := makeReceipt(addr2)
    74  			gen.AddUncheckedReceipt(receipt)
    75  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    76  		case 34:
    77  			receipt := makeReceipt(addr3)
    78  			gen.AddUncheckedReceipt(receipt)
    79  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    80  		case 99999:
    81  			receipt := makeReceipt(addr4)
    82  			gen.AddUncheckedReceipt(receipt)
    83  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    84  		}
    85  	})
    86  	// The test txs are not properly signed, can't simply create a chain
    87  	// and then import blocks. TODO(rjl493456442) try to get rid of the
    88  	// manual database writes.
    89  	gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
    90  
    91  	for i, block := range chain {
    92  		rawdb.WriteBlock(db, block)
    93  		rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
    94  		rawdb.WriteHeadBlockHash(db, block.Hash())
    95  		rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), receipts[i])
    96  	}
    97  	b.ResetTimer()
    98  
    99  	filter := sys.NewRangeFilter(0, -1, []common.Address{addr1, addr2, addr3, addr4}, nil)
   100  
   101  	for i := 0; i < b.N; i++ {
   102  		filter.begin = 0
   103  		logs, _ := filter.Logs(context.Background())
   104  		if len(logs) != 4 {
   105  			b.Fatal("expected 4 logs, got", len(logs))
   106  		}
   107  	}
   108  }
   109  
   110  func TestFilters(t *testing.T) {
   111  	var (
   112  		db           = rawdb.NewMemoryDatabase()
   113  		backend, sys = newTestFilterSystem(t, db, Config{})
   114  		// Sender account
   115  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   116  		addr    = crypto.PubkeyToAddress(key1.PublicKey)
   117  		signer  = types.NewLondonSigner(big.NewInt(1))
   118  		// Logging contract
   119  		contract  = common.Address{0xfe}
   120  		contract2 = common.Address{0xff}
   121  		abiStr    = `[{"inputs":[],"name":"log0","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"}],"name":"log1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"}],"name":"log2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"},{"internalType":"uint256","name":"t3","type":"uint256"}],"name":"log3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"},{"internalType":"uint256","name":"t3","type":"uint256"},{"internalType":"uint256","name":"t4","type":"uint256"}],"name":"log4","outputs":[],"stateMutability":"nonpayable","type":"function"}]`
   122  		/*
   123  			// SPDX-License-Identifier: GPL-3.0
   124  			pragma solidity >=0.7.0 <0.9.0;
   125  
   126  			contract Logger {
   127  				function log0() external {
   128  					assembly {
   129  						log0(0, 0)
   130  					}
   131  				}
   132  
   133  				function log1(uint t1) external {
   134  					assembly {
   135  						log1(0, 0, t1)
   136  					}
   137  				}
   138  
   139  				function log2(uint t1, uint t2) external {
   140  					assembly {
   141  						log2(0, 0, t1, t2)
   142  					}
   143  				}
   144  
   145  				function log3(uint t1, uint t2, uint t3) external {
   146  					assembly {
   147  						log3(0, 0, t1, t2, t3)
   148  					}
   149  				}
   150  
   151  				function log4(uint t1, uint t2, uint t3, uint t4) external {
   152  					assembly {
   153  						log4(0, 0, t1, t2, t3, t4)
   154  					}
   155  				}
   156  			}
   157  		*/
   158  		bytecode = common.FromHex("608060405234801561001057600080fd5b50600436106100575760003560e01c80630aa731851461005c5780632a4c08961461006657806378b9a1f314610082578063c670f8641461009e578063c683d6a3146100ba575b600080fd5b6100646100d6565b005b610080600480360381019061007b9190610143565b6100dc565b005b61009c60048036038101906100979190610196565b6100e8565b005b6100b860048036038101906100b391906101d6565b6100f2565b005b6100d460048036038101906100cf9190610203565b6100fa565b005b600080a0565b808284600080a3505050565b8082600080a25050565b80600080a150565b80828486600080a450505050565b600080fd5b6000819050919050565b6101208161010d565b811461012b57600080fd5b50565b60008135905061013d81610117565b92915050565b60008060006060848603121561015c5761015b610108565b5b600061016a8682870161012e565b935050602061017b8682870161012e565b925050604061018c8682870161012e565b9150509250925092565b600080604083850312156101ad576101ac610108565b5b60006101bb8582860161012e565b92505060206101cc8582860161012e565b9150509250929050565b6000602082840312156101ec576101eb610108565b5b60006101fa8482850161012e565b91505092915050565b6000806000806080858703121561021d5761021c610108565b5b600061022b8782880161012e565b945050602061023c8782880161012e565b935050604061024d8782880161012e565b925050606061025e8782880161012e565b9150509295919450925056fea264697066735822122073a4b156f487e59970dc1ef449cc0d51467268f676033a17188edafcee861f9864736f6c63430008110033")
   159  
   160  		hash1 = common.BytesToHash([]byte("topic1"))
   161  		hash2 = common.BytesToHash([]byte("topic2"))
   162  		hash3 = common.BytesToHash([]byte("topic3"))
   163  		hash4 = common.BytesToHash([]byte("topic4"))
   164  		hash5 = common.BytesToHash([]byte("topic5"))
   165  
   166  		gspec = &core.Genesis{
   167  			Config: params.TestChainConfig,
   168  			Alloc: types.GenesisAlloc{
   169  				addr:      {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))},
   170  				contract:  {Balance: big.NewInt(0), Code: bytecode},
   171  				contract2: {Balance: big.NewInt(0), Code: bytecode},
   172  			},
   173  			BaseFee: big.NewInt(params.InitialBaseFee),
   174  		}
   175  	)
   176  
   177  	contractABI, err := abi.JSON(strings.NewReader(abiStr))
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  
   182  	// Hack: GenerateChainWithGenesis creates a new db.
   183  	// Commit the genesis manually and use GenerateChain.
   184  	_, err = gspec.Commit(db, triedb.NewDatabase(db, nil))
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  	chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {
   189  		switch i {
   190  		case 1:
   191  			data, err := contractABI.Pack("log1", hash1.Big())
   192  			if err != nil {
   193  				t.Fatal(err)
   194  			}
   195  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   196  				Nonce:    0,
   197  				GasPrice: gen.BaseFee(),
   198  				Gas:      30000,
   199  				To:       &contract,
   200  				Data:     data,
   201  			}), signer, key1)
   202  			gen.AddTx(tx)
   203  			tx2, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   204  				Nonce:    1,
   205  				GasPrice: gen.BaseFee(),
   206  				Gas:      30000,
   207  				To:       &contract2,
   208  				Data:     data,
   209  			}), signer, key1)
   210  			gen.AddTx(tx2)
   211  		case 2:
   212  			data, err := contractABI.Pack("log2", hash2.Big(), hash1.Big())
   213  			if err != nil {
   214  				t.Fatal(err)
   215  			}
   216  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   217  				Nonce:    2,
   218  				GasPrice: gen.BaseFee(),
   219  				Gas:      30000,
   220  				To:       &contract,
   221  				Data:     data,
   222  			}), signer, key1)
   223  			gen.AddTx(tx)
   224  		case 998:
   225  			data, err := contractABI.Pack("log1", hash3.Big())
   226  			if err != nil {
   227  				t.Fatal(err)
   228  			}
   229  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   230  				Nonce:    3,
   231  				GasPrice: gen.BaseFee(),
   232  				Gas:      30000,
   233  				To:       &contract2,
   234  				Data:     data,
   235  			}), signer, key1)
   236  			gen.AddTx(tx)
   237  		case 999:
   238  			data, err := contractABI.Pack("log1", hash4.Big())
   239  			if err != nil {
   240  				t.Fatal(err)
   241  			}
   242  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   243  				Nonce:    4,
   244  				GasPrice: gen.BaseFee(),
   245  				Gas:      30000,
   246  				To:       &contract,
   247  				Data:     data,
   248  			}), signer, key1)
   249  			gen.AddTx(tx)
   250  		}
   251  	})
   252  	var l uint64
   253  	bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
   254  	if err != nil {
   255  		t.Fatal(err)
   256  	}
   257  	_, err = bc.InsertChain(chain)
   258  	if err != nil {
   259  		t.Fatal(err)
   260  	}
   261  
   262  	// Set block 998 as Finalized (-3)
   263  	bc.SetFinalized(chain[998].Header())
   264  
   265  	// Generate pending block
   266  	pchain, preceipts := core.GenerateChain(gspec.Config, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {
   267  		data, err := contractABI.Pack("log1", hash5.Big())
   268  		if err != nil {
   269  			t.Fatal(err)
   270  		}
   271  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   272  			Nonce:    5,
   273  			GasPrice: gen.BaseFee(),
   274  			Gas:      30000,
   275  			To:       &contract,
   276  			Data:     data,
   277  		}), signer, key1)
   278  		gen.AddTx(tx)
   279  	})
   280  	backend.setPending(pchain[0], preceipts[0])
   281  
   282  	for i, tc := range []struct {
   283  		f    *Filter
   284  		want string
   285  		err  string
   286  	}{
   287  		{
   288  			f:    sys.NewBlockFilter(chain[2].Hash(), []common.Address{contract}, nil),
   289  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`,
   290  		},
   291  		{
   292  			f:    sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}),
   293  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`,
   294  		},
   295  		{
   296  			f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}),
   297  		},
   298  		{
   299  			f:    sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}),
   300  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`,
   301  		},
   302  		{
   303  			f:    sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}),
   304  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`,
   305  		},
   306  		{
   307  			f:    sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}),
   308  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xdba3e2ea9a7d690b722d70ee605fd67ba4c00d1d3aecd5cf187a7b92ad8eb3df","transactionIndex":"0x1","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x1","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`,
   309  		},
   310  		{
   311  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}),
   312  		},
   313  		{
   314  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil),
   315  		},
   316  		{
   317  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}),
   318  		},
   319  		{
   320  			f:    sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   321  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`,
   322  		},
   323  		{
   324  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   325  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`,
   326  		},
   327  		{
   328  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   329  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`,
   330  		},
   331  		{
   332  			f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   333  		},
   334  		{
   335  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   336  			err: "safe header not found",
   337  		},
   338  		{
   339  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   340  			err: "safe header not found",
   341  		},
   342  		{
   343  			f:   sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   344  			err: "safe header not found",
   345  		},
   346  		{
   347  			f:   sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   348  			err: errPendingLogsUnsupported.Error(),
   349  		},
   350  		{
   351  			f:   sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   352  			err: errPendingLogsUnsupported.Error(),
   353  		},
   354  		{
   355  			f:   sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   356  			err: errPendingLogsUnsupported.Error(),
   357  		},
   358  	} {
   359  		logs, err := tc.f.Logs(context.Background())
   360  		if err == nil && tc.err != "" {
   361  			t.Fatalf("test %d, expected error %q, got nil", i, tc.err)
   362  		} else if err != nil && err.Error() != tc.err {
   363  			t.Fatalf("test %d, expected error %q, got %q", i, tc.err, err.Error())
   364  		}
   365  		if tc.want == "" && len(logs) == 0 {
   366  			continue
   367  		}
   368  		have, err := json.Marshal(logs)
   369  		if err != nil {
   370  			t.Fatal(err)
   371  		}
   372  		if string(have) != tc.want {
   373  			t.Fatalf("test %d, have:\n%s\nwant:\n%s", i, have, tc.want)
   374  		}
   375  	}
   376  
   377  	t.Run("timeout", func(t *testing.T) {
   378  		f := sys.NewRangeFilter(0, rpc.LatestBlockNumber.Int64(), nil, nil)
   379  		ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Hour))
   380  		defer cancel()
   381  		_, err := f.Logs(ctx)
   382  		if err == nil {
   383  			t.Fatal("expected error")
   384  		}
   385  		if err != context.DeadlineExceeded {
   386  			t.Fatalf("expected context.DeadlineExceeded, got %v", err)
   387  		}
   388  	})
   389  }