github.com/theQRL/go-zond@v0.2.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/beacon"
    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/crypto/pqcrypto"
    36  	"github.com/theQRL/go-zond/params"
    37  	"github.com/theQRL/go-zond/rpc"
    38  	"github.com/theQRL/go-zond/trie"
    39  )
    40  
    41  func makeReceipt(addr common.Address) *types.Receipt {
    42  	receipt := &types.Receipt{
    43  		Type:              types.DynamicFeeTxType,
    44  		PostState:         common.CopyBytes(nil),
    45  		CumulativeGasUsed: 0,
    46  		Status:            types.ReceiptStatusSuccessful,
    47  	}
    48  	receipt.Logs = []*types.Log{
    49  		{Address: addr},
    50  	}
    51  	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
    52  	return receipt
    53  }
    54  
    55  func BenchmarkFilters(b *testing.B) {
    56  	var (
    57  		db, _   = rawdb.NewLevelDBDatabase(b.TempDir(), 0, 0, "", false)
    58  		_, sys  = newTestFilterSystem(b, db, Config{})
    59  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    60  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
    61  		addr2   = common.BytesToAddress([]byte("jeff"))
    62  		addr3   = common.BytesToAddress([]byte("ethereum"))
    63  		addr4   = common.BytesToAddress([]byte("random addresses please"))
    64  		to, _   = common.NewAddressFromString("Z0000000000000000000000000000000000000999")
    65  
    66  		gspec = &core.Genesis{
    67  			Alloc:   core.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
    68  			BaseFee: big.NewInt(params.InitialBaseFee),
    69  			Config:  params.TestChainConfig,
    70  		}
    71  	)
    72  	defer db.Close()
    73  	_, chain, receipts := core.GenerateChainWithGenesis(gspec, beacon.NewFaker(), 100010, func(i int, gen *core.BlockGen) {
    74  		switch i {
    75  		case 2403:
    76  			receipt := makeReceipt(addr1)
    77  			gen.AddUncheckedReceipt(receipt)
    78  			gen.AddUncheckedTx(types.NewTx(&types.DynamicFeeTx{Nonce: 999, To: &to, Value: big.NewInt(999), Gas: 999, GasFeeCap: gen.BaseFee(), Data: nil}))
    79  		case 1034:
    80  			receipt := makeReceipt(addr2)
    81  			gen.AddUncheckedReceipt(receipt)
    82  			gen.AddUncheckedTx(types.NewTx(&types.DynamicFeeTx{Nonce: 999, To: &to, Value: big.NewInt(999), Gas: 999, GasFeeCap: gen.BaseFee(), Data: nil}))
    83  		case 34:
    84  			receipt := makeReceipt(addr3)
    85  			gen.AddUncheckedReceipt(receipt)
    86  			gen.AddUncheckedTx(types.NewTx(&types.DynamicFeeTx{Nonce: 999, To: &to, Value: big.NewInt(999), Gas: 999, GasFeeCap: gen.BaseFee(), Data: nil}))
    87  		case 99999:
    88  			receipt := makeReceipt(addr4)
    89  			gen.AddUncheckedReceipt(receipt)
    90  			gen.AddUncheckedTx(types.NewTx(&types.DynamicFeeTx{Nonce: 999, To: &to, Value: big.NewInt(999), Gas: 999, GasFeeCap: gen.BaseFee(), Data: nil}))
    91  		}
    92  	})
    93  	// The test txs are not properly signed, can't simply create a chain
    94  	// and then import blocks. TODO(rjl493456442) try to get rid of the
    95  	// manual database writes.
    96  	gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
    97  
    98  	for i, block := range chain {
    99  		rawdb.WriteBlock(db, block)
   100  		rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
   101  		rawdb.WriteHeadBlockHash(db, block.Hash())
   102  		rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), receipts[i])
   103  	}
   104  	b.ResetTimer()
   105  
   106  	filter := sys.NewRangeFilter(0, -1, []common.Address{addr1, addr2, addr3, addr4}, nil)
   107  
   108  	for i := 0; i < b.N; i++ {
   109  		logs, _ := filter.Logs(context.Background())
   110  		if len(logs) != 4 {
   111  			b.Fatal("expected 4 logs, got", len(logs))
   112  		}
   113  	}
   114  }
   115  
   116  func TestFilters(t *testing.T) {
   117  	var (
   118  		db           = rawdb.NewMemoryDatabase()
   119  		backend, sys = newTestFilterSystem(t, db, Config{})
   120  		// Sender account
   121  		key1, _ = pqcrypto.HexToDilithium("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   122  		addr    = key1.GetAddress()
   123  		signer  = types.NewShanghaiSigner(big.NewInt(1))
   124  		// Logging contract
   125  		contract  = common.Address{0xfe}
   126  		contract2 = common.Address{0xff}
   127  		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"}]`
   128  
   129  		/*
   130  			// SPDX-License-Identifier: GPL-3.0
   131  			// TODO(now.youtrack.cloud/issue/TGZ-30)
   132  			pragma hyperion >=0.7.0 <0.9.0;
   133  
   134  			contract Logger {
   135  			    function log0() external {
   136  			        assembly {
   137  			            log0(0, 0)
   138  			        }
   139  			    }
   140  
   141  			    function log1(uint t1) external {
   142  			        assembly {
   143  			            log1(0, 0, t1)
   144  			        }
   145  			    }
   146  
   147  			    function log2(uint t1, uint t2) external {
   148  			        assembly {
   149  			            log2(0, 0, t1, t2)
   150  			        }
   151  			    }
   152  
   153  			    function log3(uint t1, uint t2, uint t3) external {
   154  			        assembly {
   155  			            log3(0, 0, t1, t2, t3)
   156  			        }
   157  			    }
   158  
   159  			    function log4(uint t1, uint t2, uint t3, uint t4) external {
   160  			        assembly {
   161  			            log4(0, 0, t1, t2, t3, t4)
   162  			        }
   163  			    }
   164  			}
   165  		*/
   166  
   167  		bytecode = common.FromHex("608060405234801561001057600080fd5b50600436106100575760003560e01c80630aa731851461005c5780632a4c08961461006657806378b9a1f314610082578063c670f8641461009e578063c683d6a3146100ba575b600080fd5b6100646100d6565b005b610080600480360381019061007b9190610143565b6100dc565b005b61009c60048036038101906100979190610196565b6100e8565b005b6100b860048036038101906100b391906101d6565b6100f2565b005b6100d460048036038101906100cf9190610203565b6100fa565b005b600080a0565b808284600080a3505050565b8082600080a25050565b80600080a150565b80828486600080a450505050565b600080fd5b6000819050919050565b6101208161010d565b811461012b57600080fd5b50565b60008135905061013d81610117565b92915050565b60008060006060848603121561015c5761015b610108565b5b600061016a8682870161012e565b935050602061017b8682870161012e565b925050604061018c8682870161012e565b9150509250925092565b600080604083850312156101ad576101ac610108565b5b60006101bb8582860161012e565b92505060206101cc8582860161012e565b9150509250929050565b6000602082840312156101ec576101eb610108565b5b60006101fa8482850161012e565b91505092915050565b6000806000806080858703121561021d5761021c610108565b5b600061022b8782880161012e565b945050602061023c8782880161012e565b935050604061024d8782880161012e565b925050606061025e8782880161012e565b9150509295919450925056fea264697066735822122073a4b156f487e59970dc1ef449cc0d51467268f676033a17188edafcee861f9864736f6c63430008110033")
   168  
   169  		hash1 = common.BytesToHash([]byte("topic1"))
   170  		hash2 = common.BytesToHash([]byte("topic2"))
   171  		hash3 = common.BytesToHash([]byte("topic3"))
   172  		hash4 = common.BytesToHash([]byte("topic4"))
   173  		hash5 = common.BytesToHash([]byte("topic5"))
   174  
   175  		gspec = &core.Genesis{
   176  			Config: params.TestChainConfig,
   177  			Alloc: core.GenesisAlloc{
   178  				addr:      {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))},
   179  				contract:  {Balance: big.NewInt(0), Code: bytecode},
   180  				contract2: {Balance: big.NewInt(0), Code: bytecode},
   181  			},
   182  			BaseFee: big.NewInt(params.InitialBaseFee),
   183  		}
   184  	)
   185  
   186  	contractABI, err := abi.JSON(strings.NewReader(abiStr))
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  
   191  	// Hack: GenerateChainWithGenesis creates a new db.
   192  	// Commit the genesis manually and use GenerateChain.
   193  	_, err = gspec.Commit(db, trie.NewDatabase(db, nil))
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  	chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), beacon.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {
   198  		switch i {
   199  		case 1:
   200  			data, err := contractABI.Pack("log1", hash1.Big())
   201  			if err != nil {
   202  				t.Fatal(err)
   203  			}
   204  			tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
   205  				Nonce:     0,
   206  				GasFeeCap: gen.BaseFee(),
   207  				Gas:       30000,
   208  				To:        &contract,
   209  				Data:      data,
   210  			}), signer, key1)
   211  			gen.AddTx(tx)
   212  			tx2, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
   213  				Nonce:     1,
   214  				GasFeeCap: gen.BaseFee(),
   215  				Gas:       30000,
   216  				To:        &contract2,
   217  				Data:      data,
   218  			}), signer, key1)
   219  			gen.AddTx(tx2)
   220  		case 2:
   221  			data, err := contractABI.Pack("log2", hash2.Big(), hash1.Big())
   222  			if err != nil {
   223  				t.Fatal(err)
   224  			}
   225  			tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
   226  				Nonce:     2,
   227  				GasFeeCap: gen.BaseFee(),
   228  				Gas:       30000,
   229  				To:        &contract,
   230  				Data:      data,
   231  			}), signer, key1)
   232  			gen.AddTx(tx)
   233  		case 998:
   234  			data, err := contractABI.Pack("log1", hash3.Big())
   235  			if err != nil {
   236  				t.Fatal(err)
   237  			}
   238  			tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
   239  				Nonce:     3,
   240  				GasFeeCap: gen.BaseFee(),
   241  				Gas:       30000,
   242  				To:        &contract2,
   243  				Data:      data,
   244  			}), signer, key1)
   245  			gen.AddTx(tx)
   246  		case 999:
   247  			data, err := contractABI.Pack("log1", hash4.Big())
   248  			if err != nil {
   249  				t.Fatal(err)
   250  			}
   251  			tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
   252  				Nonce:     4,
   253  				GasFeeCap: gen.BaseFee(),
   254  				Gas:       30000,
   255  				To:        &contract,
   256  				Data:      data,
   257  			}), signer, key1)
   258  			gen.AddTx(tx)
   259  		}
   260  	})
   261  	var l uint64
   262  	bc, err := core.NewBlockChain(db, nil, gspec, beacon.NewFaker(), vm.Config{}, &l)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  	_, err = bc.InsertChain(chain)
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  
   271  	// Set block 998 as Finalized (-3)
   272  	bc.SetFinalized(chain[998].Header())
   273  
   274  	// Generate pending block
   275  	pchain, preceipts := core.GenerateChain(gspec.Config, chain[len(chain)-1], beacon.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {
   276  		data, err := contractABI.Pack("log1", hash5.Big())
   277  		if err != nil {
   278  			t.Fatal(err)
   279  		}
   280  		tx, err := types.SignTx(types.NewTx(&types.DynamicFeeTx{
   281  			Nonce:     5,
   282  			GasFeeCap: gen.BaseFee(),
   283  			Gas:       30000,
   284  			To:        &contract,
   285  			Data:      data,
   286  		}), signer, key1)
   287  		if err != nil {
   288  			t.Fatal(err)
   289  		}
   290  		gen.AddTx(tx)
   291  	})
   292  	backend.setPending(pchain[0], preceipts[0])
   293  
   294  	for i, tc := range []struct {
   295  		f    *Filter
   296  		want string
   297  		err  string
   298  	}{
   299  		{
   300  			f:    sys.NewBlockFilter(chain[2].Hash(), []common.Address{contract}, nil),
   301  			want: `[{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0x98d3df047a661b1186be5d1f7ae2a521fbca8ca718cd231bf65e06d09d15e98e","transactionIndex":"0x0","blockHash":"0xae2282865aec2aba624fbd1e968a22205c7d70e8feeca606035ac49865c83742","logIndex":"0x0","removed":false}]`,
   302  		},
   303  		{
   304  			f:    sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}),
   305  			want: `[{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0x5c2bb52a0eb61322131687e85eb3498b430274a69428d7bf4bdedfea8529ce9d","transactionIndex":"0x0","blockHash":"0x2272dec00c13cdd8a26b64423643d2d556bb95d2297f9d0c56ba3a682c9e1b3b","logIndex":"0x0","removed":false},{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0x98d3df047a661b1186be5d1f7ae2a521fbca8ca718cd231bf65e06d09d15e98e","transactionIndex":"0x0","blockHash":"0xae2282865aec2aba624fbd1e968a22205c7d70e8feeca606035ac49865c83742","logIndex":"0x0","removed":false},{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x298c5fda8e7c96446e298046378764104b07256380b5bec31e6afe6b5a600c9a","transactionIndex":"0x0","blockHash":"0xf59c869d2d6f3e9bfeaad15df443238beca6394588e7ca5b17cf158a25966844","logIndex":"0x0","removed":false}]`,
   306  		},
   307  		{
   308  			f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}),
   309  		},
   310  		{
   311  			f:    sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}),
   312  			want: `[{"address":"Zff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0xabd8d45a3d8a4905b0fd1a2cd7a584ed163273f1420e4a6a9a7c0003b04b0bd3","transactionIndex":"0x0","blockHash":"0xd4eacb8f32ea38ec1207219b163bb42a4bd6eabe83d91a37b49870db639b8333","logIndex":"0x0","removed":false}]`,
   313  		},
   314  		{
   315  			f:    sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}),
   316  			want: `[{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0x98d3df047a661b1186be5d1f7ae2a521fbca8ca718cd231bf65e06d09d15e98e","transactionIndex":"0x0","blockHash":"0xae2282865aec2aba624fbd1e968a22205c7d70e8feeca606035ac49865c83742","logIndex":"0x0","removed":false}]`,
   317  		},
   318  		{
   319  			f:    sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}),
   320  			want: `[{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0x5c2bb52a0eb61322131687e85eb3498b430274a69428d7bf4bdedfea8529ce9d","transactionIndex":"0x0","blockHash":"0x2272dec00c13cdd8a26b64423643d2d556bb95d2297f9d0c56ba3a682c9e1b3b","logIndex":"0x0","removed":false},{"address":"Zff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0x7f365dd50796d1941a506c40d1cd98fa01253eafb93104e991b061362236f4f5","transactionIndex":"0x1","blockHash":"0x2272dec00c13cdd8a26b64423643d2d556bb95d2297f9d0c56ba3a682c9e1b3b","logIndex":"0x1","removed":false},{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0x98d3df047a661b1186be5d1f7ae2a521fbca8ca718cd231bf65e06d09d15e98e","transactionIndex":"0x0","blockHash":"0xae2282865aec2aba624fbd1e968a22205c7d70e8feeca606035ac49865c83742","logIndex":"0x0","removed":false}]`,
   321  		},
   322  		{
   323  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}),
   324  		},
   325  		{
   326  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil),
   327  		},
   328  		{
   329  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}),
   330  		},
   331  		{
   332  			f:    sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   333  			want: `[{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x298c5fda8e7c96446e298046378764104b07256380b5bec31e6afe6b5a600c9a","transactionIndex":"0x0","blockHash":"0xf59c869d2d6f3e9bfeaad15df443238beca6394588e7ca5b17cf158a25966844","logIndex":"0x0","removed":false}]`,
   334  		},
   335  		{
   336  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   337  			want: `[{"address":"Zff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0xabd8d45a3d8a4905b0fd1a2cd7a584ed163273f1420e4a6a9a7c0003b04b0bd3","transactionIndex":"0x0","blockHash":"0xd4eacb8f32ea38ec1207219b163bb42a4bd6eabe83d91a37b49870db639b8333","logIndex":"0x0","removed":false},{"address":"Zfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x298c5fda8e7c96446e298046378764104b07256380b5bec31e6afe6b5a600c9a","transactionIndex":"0x0","blockHash":"0xf59c869d2d6f3e9bfeaad15df443238beca6394588e7ca5b17cf158a25966844","logIndex":"0x0","removed":false}]`,
   338  		},
   339  		{
   340  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   341  			want: `[{"address":"Zff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0xabd8d45a3d8a4905b0fd1a2cd7a584ed163273f1420e4a6a9a7c0003b04b0bd3","transactionIndex":"0x0","blockHash":"0xd4eacb8f32ea38ec1207219b163bb42a4bd6eabe83d91a37b49870db639b8333","logIndex":"0x0","removed":false}]`,
   342  		},
   343  		{
   344  			f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   345  		},
   346  		{
   347  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   348  			err: "safe header not found",
   349  		},
   350  		{
   351  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   352  			err: "safe header not found",
   353  		},
   354  		{
   355  			f:   sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   356  			err: "safe header not found",
   357  		},
   358  		{
   359  			f:   sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   360  			err: errPendingLogsUnsupported.Error(),
   361  		},
   362  		{
   363  			f:   sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   364  			err: errPendingLogsUnsupported.Error(),
   365  		},
   366  		{
   367  			f:   sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   368  			err: errPendingLogsUnsupported.Error(),
   369  		},
   370  	} {
   371  		logs, err := tc.f.Logs(context.Background())
   372  		if err == nil && tc.err != "" {
   373  			t.Fatalf("test %d, expected error %q, got nil", i, tc.err)
   374  		} else if err != nil && err.Error() != tc.err {
   375  			t.Fatalf("test %d, expected error %q, got %q", i, tc.err, err.Error())
   376  		}
   377  		if tc.want == "" && len(logs) == 0 {
   378  			continue
   379  		}
   380  		have, err := json.Marshal(logs)
   381  		if err != nil {
   382  			t.Fatal(err)
   383  		}
   384  		if string(have) != tc.want {
   385  			t.Fatalf("test %d, have:\n%s\nwant:\n%s", i, have, tc.want)
   386  		}
   387  	}
   388  
   389  	t.Run("timeout", func(t *testing.T) {
   390  		f := sys.NewRangeFilter(0, rpc.LatestBlockNumber.Int64(), nil, nil)
   391  		ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Hour))
   392  		defer cancel()
   393  		_, err := f.Logs(ctx)
   394  		if err == nil {
   395  			t.Fatal("expected error")
   396  		}
   397  		if err != context.DeadlineExceeded {
   398  			t.Fatalf("expected context.DeadlineExceeded, got %v", err)
   399  		}
   400  	})
   401  }