github.com/theQRL/go-zond@v0.1.1/zond/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/theQRL/go-zond/accounts/abi"
    28  	"github.com/theQRL/go-zond/common"
    29  	"github.com/theQRL/go-zond/consensus/ethash"
    30  	"github.com/theQRL/go-zond/core"
    31  	"github.com/theQRL/go-zond/core/rawdb"
    32  	"github.com/theQRL/go-zond/core/types"
    33  	"github.com/theQRL/go-zond/core/vm"
    34  	"github.com/theQRL/go-zond/crypto"
    35  	"github.com/theQRL/go-zond/params"
    36  	"github.com/theQRL/go-zond/rpc"
    37  	"github.com/theQRL/go-zond/trie"
    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:   core.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, trie.NewDatabase(db, trie.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  		logs, _ := filter.Logs(context.Background())
   103  		if len(logs) != 4 {
   104  			b.Fatal("expected 4 logs, got", len(logs))
   105  		}
   106  	}
   107  }
   108  
   109  func TestFilters(t *testing.T) {
   110  	var (
   111  		db     = rawdb.NewMemoryDatabase()
   112  		_, sys = newTestFilterSystem(t, db, Config{})
   113  		// Sender account
   114  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   115  		addr    = crypto.PubkeyToAddress(key1.PublicKey)
   116  		signer  = types.NewLondonSigner(big.NewInt(1))
   117  		// Logging contract
   118  		contract  = common.Address{0xfe}
   119  		contract2 = common.Address{0xff}
   120  		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"}]`
   121  		/*
   122  			// SPDX-License-Identifier: GPL-3.0
   123  			pragma solidity >=0.7.0 <0.9.0;
   124  
   125  			contract Logger {
   126  			    function log0() external {
   127  			        assembly {
   128  			            log0(0, 0)
   129  			        }
   130  			    }
   131  
   132  			    function log1(uint t1) external {
   133  			        assembly {
   134  			            log1(0, 0, t1)
   135  			        }
   136  			    }
   137  
   138  			    function log2(uint t1, uint t2) external {
   139  			        assembly {
   140  			            log2(0, 0, t1, t2)
   141  			        }
   142  			    }
   143  
   144  			    function log3(uint t1, uint t2, uint t3) external {
   145  			        assembly {
   146  			            log3(0, 0, t1, t2, t3)
   147  			        }
   148  			    }
   149  
   150  			    function log4(uint t1, uint t2, uint t3, uint t4) external {
   151  			        assembly {
   152  			            log4(0, 0, t1, t2, t3, t4)
   153  			        }
   154  			    }
   155  			}
   156  		*/
   157  		bytecode = common.FromHex("608060405234801561001057600080fd5b50600436106100575760003560e01c80630aa731851461005c5780632a4c08961461006657806378b9a1f314610082578063c670f8641461009e578063c683d6a3146100ba575b600080fd5b6100646100d6565b005b610080600480360381019061007b9190610143565b6100dc565b005b61009c60048036038101906100979190610196565b6100e8565b005b6100b860048036038101906100b391906101d6565b6100f2565b005b6100d460048036038101906100cf9190610203565b6100fa565b005b600080a0565b808284600080a3505050565b8082600080a25050565b80600080a150565b80828486600080a450505050565b600080fd5b6000819050919050565b6101208161010d565b811461012b57600080fd5b50565b60008135905061013d81610117565b92915050565b60008060006060848603121561015c5761015b610108565b5b600061016a8682870161012e565b935050602061017b8682870161012e565b925050604061018c8682870161012e565b9150509250925092565b600080604083850312156101ad576101ac610108565b5b60006101bb8582860161012e565b92505060206101cc8582860161012e565b9150509250929050565b6000602082840312156101ec576101eb610108565b5b60006101fa8482850161012e565b91505092915050565b6000806000806080858703121561021d5761021c610108565b5b600061022b8782880161012e565b945050602061023c8782880161012e565b935050604061024d8782880161012e565b925050606061025e8782880161012e565b9150509295919450925056fea264697066735822122073a4b156f487e59970dc1ef449cc0d51467268f676033a17188edafcee861f9864736f6c63430008110033")
   158  
   159  		hash1 = common.BytesToHash([]byte("topic1"))
   160  		hash2 = common.BytesToHash([]byte("topic2"))
   161  		hash3 = common.BytesToHash([]byte("topic3"))
   162  		hash4 = common.BytesToHash([]byte("topic4"))
   163  		hash5 = common.BytesToHash([]byte("topic5"))
   164  
   165  		gspec = &core.Genesis{
   166  			Config: params.TestChainConfig,
   167  			Alloc: core.GenesisAlloc{
   168  				addr:      {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))},
   169  				contract:  {Balance: big.NewInt(0), Code: bytecode},
   170  				contract2: {Balance: big.NewInt(0), Code: bytecode},
   171  			},
   172  			BaseFee: big.NewInt(params.InitialBaseFee),
   173  		}
   174  	)
   175  
   176  	contractABI, err := abi.JSON(strings.NewReader(abiStr))
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  
   181  	// Hack: GenerateChainWithGenesis creates a new db.
   182  	// Commit the genesis manually and use GenerateChain.
   183  	_, err = gspec.Commit(db, trie.NewDatabase(db, nil))
   184  	if err != nil {
   185  		t.Fatal(err)
   186  	}
   187  	chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {
   188  		switch i {
   189  		case 1:
   190  			data, err := contractABI.Pack("log1", hash1.Big())
   191  			if err != nil {
   192  				t.Fatal(err)
   193  			}
   194  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   195  				Nonce:    0,
   196  				GasPrice: gen.BaseFee(),
   197  				Gas:      30000,
   198  				To:       &contract,
   199  				Data:     data,
   200  			}), signer, key1)
   201  			gen.AddTx(tx)
   202  			tx2, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   203  				Nonce:    1,
   204  				GasPrice: gen.BaseFee(),
   205  				Gas:      30000,
   206  				To:       &contract2,
   207  				Data:     data,
   208  			}), signer, key1)
   209  			gen.AddTx(tx2)
   210  		case 2:
   211  			data, err := contractABI.Pack("log2", hash2.Big(), hash1.Big())
   212  			if err != nil {
   213  				t.Fatal(err)
   214  			}
   215  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   216  				Nonce:    2,
   217  				GasPrice: gen.BaseFee(),
   218  				Gas:      30000,
   219  				To:       &contract,
   220  				Data:     data,
   221  			}), signer, key1)
   222  			gen.AddTx(tx)
   223  		case 998:
   224  			data, err := contractABI.Pack("log1", hash3.Big())
   225  			if err != nil {
   226  				t.Fatal(err)
   227  			}
   228  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   229  				Nonce:    3,
   230  				GasPrice: gen.BaseFee(),
   231  				Gas:      30000,
   232  				To:       &contract2,
   233  				Data:     data,
   234  			}), signer, key1)
   235  			gen.AddTx(tx)
   236  		case 999:
   237  			data, err := contractABI.Pack("log1", hash4.Big())
   238  			if err != nil {
   239  				t.Fatal(err)
   240  			}
   241  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   242  				Nonce:    4,
   243  				GasPrice: gen.BaseFee(),
   244  				Gas:      30000,
   245  				To:       &contract,
   246  				Data:     data,
   247  			}), signer, key1)
   248  			gen.AddTx(tx)
   249  		}
   250  	})
   251  	var l uint64
   252  	bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
   253  	if err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	_, err = bc.InsertChain(chain)
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  
   261  	// Set block 998 as Finalized (-3)
   262  	bc.SetFinalized(chain[998].Header())
   263  
   264  	// Generate pending block
   265  	pchain, preceipts := core.GenerateChain(gspec.Config, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {
   266  		data, err := contractABI.Pack("log1", hash5.Big())
   267  		if err != nil {
   268  			t.Fatal(err)
   269  		}
   270  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   271  			Nonce:    5,
   272  			GasPrice: gen.BaseFee(),
   273  			Gas:      30000,
   274  			To:       &contract,
   275  			Data:     data,
   276  		}), signer, key1)
   277  		gen.AddTx(tx)
   278  	})
   279  	sys.backend.(*testBackend).pendingBlock = pchain[0]
   280  	sys.backend.(*testBackend).pendingReceipts = 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  			f:    sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}),
   292  			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}]`,
   293  		}, {
   294  			f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}),
   295  		}, {
   296  			f:    sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}),
   297  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`,
   298  		}, {
   299  			f:    sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}),
   300  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`,
   301  		}, {
   302  			f:    sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}),
   303  			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}]`,
   304  		}, {
   305  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}),
   306  		}, {
   307  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil),
   308  		}, {
   309  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}),
   310  		}, {
   311  			f:    sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   312  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`,
   313  		}, {
   314  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   315  			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}]`,
   316  		}, {
   317  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   318  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`,
   319  		}, {
   320  			f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   321  		}, {
   322  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   323  			err: "safe header not found",
   324  		}, {
   325  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   326  			err: "safe header not found",
   327  		}, {
   328  			f:   sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   329  			err: "safe header not found",
   330  		}, {
   331  			f:    sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   332  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xc7245899e5817f16fa99cf5ad2d9c1e4b98443a565a673ec9c764640443ef037","logIndex":"0x0","removed":false}]`,
   333  		}, {
   334  			f:    sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   335  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xc7245899e5817f16fa99cf5ad2d9c1e4b98443a565a673ec9c764640443ef037","logIndex":"0x0","removed":false}]`,
   336  		}, {
   337  			f:   sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   338  			err: "invalid block range",
   339  		},
   340  	} {
   341  		logs, err := tc.f.Logs(context.Background())
   342  		if err == nil && tc.err != "" {
   343  			t.Fatalf("test %d, expected error %q, got nil", i, tc.err)
   344  		} else if err != nil && err.Error() != tc.err {
   345  			t.Fatalf("test %d, expected error %q, got %q", i, tc.err, err.Error())
   346  		}
   347  		if tc.want == "" && len(logs) == 0 {
   348  			continue
   349  		}
   350  		have, err := json.Marshal(logs)
   351  		if err != nil {
   352  			t.Fatal(err)
   353  		}
   354  		if string(have) != tc.want {
   355  			t.Fatalf("test %d, have:\n%s\nwant:\n%s", i, have, tc.want)
   356  		}
   357  	}
   358  
   359  	t.Run("timeout", func(t *testing.T) {
   360  		f := sys.NewRangeFilter(0, -1, nil, nil)
   361  		ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Hour))
   362  		defer cancel()
   363  		_, err := f.Logs(ctx)
   364  		if err == nil {
   365  			t.Fatal("expected error")
   366  		}
   367  		if err != context.DeadlineExceeded {
   368  			t.Fatalf("expected context.DeadlineExceeded, got %v", err)
   369  		}
   370  	})
   371  }