github.com/ethereum/go-ethereum@v1.16.1/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/filtermaps"
    32  	"github.com/ethereum/go-ethereum/core/rawdb"
    33  	"github.com/ethereum/go-ethereum/core/types"
    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(receipt)
    46  	return receipt
    47  }
    48  
    49  func BenchmarkFiltersIndexed(b *testing.B) {
    50  	benchmarkFilters(b, 0, false)
    51  }
    52  
    53  func BenchmarkFiltersHalfIndexed(b *testing.B) {
    54  	benchmarkFilters(b, 50000, false)
    55  }
    56  
    57  func BenchmarkFiltersUnindexed(b *testing.B) {
    58  	benchmarkFilters(b, 0, true)
    59  }
    60  
    61  func benchmarkFilters(b *testing.B, history uint64, noHistory bool) {
    62  	var (
    63  		db           = rawdb.NewMemoryDatabase()
    64  		backend, sys = newTestFilterSystem(db, Config{})
    65  		key1, _      = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    66  		addr1        = crypto.PubkeyToAddress(key1.PublicKey)
    67  		addr2        = common.BytesToAddress([]byte("jeff"))
    68  		addr3        = common.BytesToAddress([]byte("ethereum"))
    69  		addr4        = common.BytesToAddress([]byte("random addresses please"))
    70  
    71  		gspec = &core.Genesis{
    72  			Alloc:   types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
    73  			BaseFee: big.NewInt(params.InitialBaseFee),
    74  			Config:  params.TestChainConfig,
    75  		}
    76  	)
    77  	defer db.Close()
    78  	_, chain, receipts := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 100010, func(i int, gen *core.BlockGen) {
    79  		switch i {
    80  		case 2403:
    81  			receipt := makeReceipt(addr1)
    82  			gen.AddUncheckedReceipt(receipt)
    83  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    84  		case 1034:
    85  			receipt := makeReceipt(addr2)
    86  			gen.AddUncheckedReceipt(receipt)
    87  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    88  		case 34:
    89  			receipt := makeReceipt(addr3)
    90  			gen.AddUncheckedReceipt(receipt)
    91  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    92  		case 99999:
    93  			receipt := makeReceipt(addr4)
    94  			gen.AddUncheckedReceipt(receipt)
    95  			gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil))
    96  		}
    97  	})
    98  	// The test txs are not properly signed, can't simply create a chain
    99  	// and then import blocks. TODO(rjl493456442) try to get rid of the
   100  	// manual database writes.
   101  	gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
   102  
   103  	for i, block := range chain {
   104  		rawdb.WriteBlock(db, block)
   105  		rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
   106  		rawdb.WriteHeadBlockHash(db, block.Hash())
   107  		rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), receipts[i])
   108  	}
   109  	backend.startFilterMaps(history, noHistory, filtermaps.DefaultParams)
   110  	defer backend.stopFilterMaps()
   111  
   112  	b.ResetTimer()
   113  
   114  	filter := sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{addr1, addr2, addr3, addr4}, nil)
   115  
   116  	for i := 0; i < b.N; i++ {
   117  		filter.begin = 0
   118  		logs, _ := filter.Logs(context.Background())
   119  		if len(logs) != 4 {
   120  			b.Fatal("expected 4 logs, got", len(logs))
   121  		}
   122  	}
   123  }
   124  
   125  func TestFiltersIndexed(t *testing.T) {
   126  	testFilters(t, 0, false)
   127  }
   128  
   129  func TestFiltersHalfIndexed(t *testing.T) {
   130  	testFilters(t, 500, false)
   131  }
   132  
   133  func TestFiltersUnindexed(t *testing.T) {
   134  	testFilters(t, 0, true)
   135  }
   136  
   137  func testFilters(t *testing.T, history uint64, noHistory bool) {
   138  	var (
   139  		db           = rawdb.NewMemoryDatabase()
   140  		backend, sys = newTestFilterSystem(db, Config{})
   141  		// Sender account
   142  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   143  		addr    = crypto.PubkeyToAddress(key1.PublicKey)
   144  		signer  = types.NewLondonSigner(big.NewInt(1))
   145  		// Logging contract
   146  		contract  = common.Address{0xfe}
   147  		contract2 = common.Address{0xff}
   148  		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"}]`
   149  		/*
   150  			// SPDX-License-Identifier: GPL-3.0
   151  			pragma solidity >=0.7.0 <0.9.0;
   152  
   153  			contract Logger {
   154  				function log0() external {
   155  					assembly {
   156  						log0(0, 0)
   157  					}
   158  				}
   159  
   160  				function log1(uint t1) external {
   161  					assembly {
   162  						log1(0, 0, t1)
   163  					}
   164  				}
   165  
   166  				function log2(uint t1, uint t2) external {
   167  					assembly {
   168  						log2(0, 0, t1, t2)
   169  					}
   170  				}
   171  
   172  				function log3(uint t1, uint t2, uint t3) external {
   173  					assembly {
   174  						log3(0, 0, t1, t2, t3)
   175  					}
   176  				}
   177  
   178  				function log4(uint t1, uint t2, uint t3, uint t4) external {
   179  					assembly {
   180  						log4(0, 0, t1, t2, t3, t4)
   181  					}
   182  				}
   183  			}
   184  		*/
   185  		bytecode = common.FromHex("608060405234801561001057600080fd5b50600436106100575760003560e01c80630aa731851461005c5780632a4c08961461006657806378b9a1f314610082578063c670f8641461009e578063c683d6a3146100ba575b600080fd5b6100646100d6565b005b610080600480360381019061007b9190610143565b6100dc565b005b61009c60048036038101906100979190610196565b6100e8565b005b6100b860048036038101906100b391906101d6565b6100f2565b005b6100d460048036038101906100cf9190610203565b6100fa565b005b600080a0565b808284600080a3505050565b8082600080a25050565b80600080a150565b80828486600080a450505050565b600080fd5b6000819050919050565b6101208161010d565b811461012b57600080fd5b50565b60008135905061013d81610117565b92915050565b60008060006060848603121561015c5761015b610108565b5b600061016a8682870161012e565b935050602061017b8682870161012e565b925050604061018c8682870161012e565b9150509250925092565b600080604083850312156101ad576101ac610108565b5b60006101bb8582860161012e565b92505060206101cc8582860161012e565b9150509250929050565b6000602082840312156101ec576101eb610108565b5b60006101fa8482850161012e565b91505092915050565b6000806000806080858703121561021d5761021c610108565b5b600061022b8782880161012e565b945050602061023c8782880161012e565b935050604061024d8782880161012e565b925050606061025e8782880161012e565b9150509295919450925056fea264697066735822122073a4b156f487e59970dc1ef449cc0d51467268f676033a17188edafcee861f9864736f6c63430008110033")
   186  
   187  		hash1 = common.BytesToHash([]byte("topic1"))
   188  		hash2 = common.BytesToHash([]byte("topic2"))
   189  		hash3 = common.BytesToHash([]byte("topic3"))
   190  		hash4 = common.BytesToHash([]byte("topic4"))
   191  		hash5 = common.BytesToHash([]byte("topic5"))
   192  
   193  		gspec = &core.Genesis{
   194  			Config: params.TestChainConfig,
   195  			Alloc: types.GenesisAlloc{
   196  				addr:      {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))},
   197  				contract:  {Balance: big.NewInt(0), Code: bytecode},
   198  				contract2: {Balance: big.NewInt(0), Code: bytecode},
   199  			},
   200  			BaseFee: big.NewInt(params.InitialBaseFee),
   201  		}
   202  	)
   203  
   204  	contractABI, err := abi.JSON(strings.NewReader(abiStr))
   205  	if err != nil {
   206  		t.Fatal(err)
   207  	}
   208  
   209  	// Hack: GenerateChainWithGenesis creates a new db.
   210  	// Commit the genesis manually and use GenerateChain.
   211  	_, err = gspec.Commit(db, triedb.NewDatabase(db, nil))
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  	chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {
   216  		switch i {
   217  		case 1:
   218  			data, err := contractABI.Pack("log1", hash1.Big())
   219  			if err != nil {
   220  				t.Fatal(err)
   221  			}
   222  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   223  				Nonce:    0,
   224  				GasPrice: gen.BaseFee(),
   225  				Gas:      30000,
   226  				To:       &contract,
   227  				Data:     data,
   228  			}), signer, key1)
   229  			gen.AddTx(tx)
   230  			tx2, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   231  				Nonce:    1,
   232  				GasPrice: gen.BaseFee(),
   233  				Gas:      30000,
   234  				To:       &contract2,
   235  				Data:     data,
   236  			}), signer, key1)
   237  			gen.AddTx(tx2)
   238  		case 2:
   239  			data, err := contractABI.Pack("log2", hash2.Big(), hash1.Big())
   240  			if err != nil {
   241  				t.Fatal(err)
   242  			}
   243  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   244  				Nonce:    2,
   245  				GasPrice: gen.BaseFee(),
   246  				Gas:      30000,
   247  				To:       &contract,
   248  				Data:     data,
   249  			}), signer, key1)
   250  			gen.AddTx(tx)
   251  		case 998:
   252  			data, err := contractABI.Pack("log1", hash3.Big())
   253  			if err != nil {
   254  				t.Fatal(err)
   255  			}
   256  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   257  				Nonce:    3,
   258  				GasPrice: gen.BaseFee(),
   259  				Gas:      30000,
   260  				To:       &contract2,
   261  				Data:     data,
   262  			}), signer, key1)
   263  			gen.AddTx(tx)
   264  		case 999:
   265  			data, err := contractABI.Pack("log1", hash4.Big())
   266  			if err != nil {
   267  				t.Fatal(err)
   268  			}
   269  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   270  				Nonce:    4,
   271  				GasPrice: gen.BaseFee(),
   272  				Gas:      30000,
   273  				To:       &contract,
   274  				Data:     data,
   275  			}), signer, key1)
   276  			gen.AddTx(tx)
   277  		}
   278  	})
   279  	options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme)
   280  	options.TxLookupLimit = 0 // index all txs
   281  	bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options)
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	}
   285  	_, err = bc.InsertChain(chain)
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  
   290  	// Set block 998 as Finalized (-3)
   291  	bc.SetFinalized(chain[998].Header())
   292  
   293  	// Generate pending block
   294  	pchain, preceipts := core.GenerateChain(gspec.Config, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {
   295  		data, err := contractABI.Pack("log1", hash5.Big())
   296  		if err != nil {
   297  			t.Fatal(err)
   298  		}
   299  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   300  			Nonce:    5,
   301  			GasPrice: gen.BaseFee(),
   302  			Gas:      30000,
   303  			To:       &contract,
   304  			Data:     data,
   305  		}), signer, key1)
   306  		gen.AddTx(tx)
   307  	})
   308  	backend.setPending(pchain[0], preceipts[0])
   309  
   310  	backend.startFilterMaps(history, noHistory, filtermaps.DefaultParams)
   311  	defer backend.stopFilterMaps()
   312  
   313  	for i, tc := range []struct {
   314  		f    *Filter
   315  		want string
   316  		err  string
   317  	}{
   318  		{
   319  			f:    sys.NewBlockFilter(chain[2].Hash(), []common.Address{contract}, nil),
   320  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`,
   321  		},
   322  		{
   323  			f:    sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}),
   324  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`,
   325  		},
   326  		{
   327  			f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}),
   328  		},
   329  		{
   330  			f:    sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}),
   331  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false}]`,
   332  		},
   333  		{
   334  			f:    sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}),
   335  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`,
   336  		},
   337  		{
   338  			f:    sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}),
   339  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x0","removed":false},{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xdba3e2ea9a7d690b722d70ee605fd67ba4c00d1d3aecd5cf187a7b92ad8eb3df","transactionIndex":"0x1","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x1","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`,
   340  		},
   341  		{
   342  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}),
   343  		},
   344  		{
   345  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil),
   346  		},
   347  		{
   348  			f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}),
   349  		},
   350  		{
   351  			f:    sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   352  			want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`,
   353  		},
   354  		{
   355  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   356  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`,
   357  		},
   358  		{
   359  			f:    sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   360  			want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false}]`,
   361  		},
   362  		{
   363  			f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
   364  		},
   365  		{
   366  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   367  			err: "safe header not found",
   368  		},
   369  		{
   370  			f:   sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   371  			err: "safe header not found",
   372  		},
   373  		{
   374  			f:   sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
   375  			err: "safe header not found",
   376  		},
   377  		{
   378  			f:   sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   379  			err: errPendingLogsUnsupported.Error(),
   380  		},
   381  		{
   382  			f:   sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
   383  			err: errPendingLogsUnsupported.Error(),
   384  		},
   385  		{
   386  			f:   sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
   387  			err: errPendingLogsUnsupported.Error(),
   388  		},
   389  	} {
   390  		logs, err := tc.f.Logs(context.Background())
   391  		if err == nil && tc.err != "" {
   392  			t.Fatalf("test %d, expected error %q, got nil", i, tc.err)
   393  		} else if err != nil && err.Error() != tc.err {
   394  			t.Fatalf("test %d, expected error %q, got %q", i, tc.err, err.Error())
   395  		}
   396  		if tc.want == "" && len(logs) == 0 {
   397  			continue
   398  		}
   399  		have, err := json.Marshal(logs)
   400  		if err != nil {
   401  			t.Fatal(err)
   402  		}
   403  		if string(have) != tc.want {
   404  			t.Fatalf("test %d, have:\n%s\nwant:\n%s", i, have, tc.want)
   405  		}
   406  	}
   407  
   408  	t.Run("timeout", func(t *testing.T) {
   409  		f := sys.NewRangeFilter(0, rpc.LatestBlockNumber.Int64(), nil, nil)
   410  		ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Hour))
   411  		defer cancel()
   412  		_, err := f.Logs(ctx)
   413  		if err == nil {
   414  			t.Fatal("expected error")
   415  		}
   416  		if err != context.DeadlineExceeded {
   417  			t.Fatalf("expected context.DeadlineExceeded, got %v", err)
   418  		}
   419  	})
   420  }
   421  
   422  func TestRangeLogs(t *testing.T) {
   423  	var (
   424  		db           = rawdb.NewMemoryDatabase()
   425  		backend, sys = newTestFilterSystem(db, Config{})
   426  		gspec        = &core.Genesis{
   427  			Config:  params.TestChainConfig,
   428  			Alloc:   types.GenesisAlloc{},
   429  			BaseFee: big.NewInt(params.InitialBaseFee),
   430  		}
   431  	)
   432  	_, err := gspec.Commit(db, triedb.NewDatabase(db, nil))
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  	chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {})
   437  
   438  	options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme)
   439  	options.TxLookupLimit = 0 // index all txs
   440  	bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options)
   441  	if err != nil {
   442  		t.Fatal(err)
   443  	}
   444  	_, err = bc.InsertChain(chain[:600])
   445  	if err != nil {
   446  		t.Fatal(err)
   447  	}
   448  
   449  	backend.startFilterMaps(200, false, filtermaps.RangeTestParams)
   450  	defer backend.stopFilterMaps()
   451  
   452  	var (
   453  		testCase, event int
   454  		filter          *Filter
   455  		addresses       = []common.Address{{}}
   456  	)
   457  
   458  	expEvent := func(expEvent int, expFirst, expAfterLast uint64) {
   459  		exp := rangeLogsTestEvent{expEvent, common.NewRange[uint64](expFirst, expAfterLast-expFirst)}
   460  		event++
   461  		ev := <-filter.rangeLogsTestHook
   462  		if ev != exp {
   463  			t.Fatalf("Test case #%d: wrong test event #%d received (got %v, expected %v)", testCase, event, ev, exp)
   464  		}
   465  	}
   466  
   467  	newFilter := func(begin, end int64) {
   468  		testCase++
   469  		event = 0
   470  		filter = sys.NewRangeFilter(begin, end, addresses, nil)
   471  		filter.rangeLogsTestHook = make(chan rangeLogsTestEvent)
   472  		go func(filter *Filter) {
   473  			filter.Logs(context.Background())
   474  			// ensure that filter will not be blocked if we exit early
   475  			for range filter.rangeLogsTestHook {
   476  			}
   477  		}(filter)
   478  	}
   479  
   480  	updateHead := func() {
   481  		head := bc.CurrentBlock()
   482  		backend.fm.SetTarget(filtermaps.NewChainView(backend, head.Number.Uint64(), head.Hash()), 0, 0)
   483  		backend.fm.WaitIdle()
   484  	}
   485  
   486  	// test case #1
   487  	newFilter(300, 500)
   488  	expEvent(rangeLogsTestIndexed, 401, 501)
   489  	expEvent(rangeLogsTestSync, 0, 0)
   490  	expEvent(rangeLogsTestSynced, 401, 601)
   491  	expEvent(rangeLogsTestResults, 401, 501)
   492  	expEvent(rangeLogsTestUnindexed, 300, 401)
   493  	if _, err := bc.InsertChain(chain[600:700]); err != nil {
   494  		t.Fatal(err)
   495  	}
   496  	updateHead()
   497  	expEvent(rangeLogsTestResults, 300, 501)
   498  	expEvent(rangeLogsTestDone, 0, 0)
   499  
   500  	// test case #2
   501  	newFilter(400, int64(rpc.LatestBlockNumber))
   502  	expEvent(rangeLogsTestIndexed, 501, 701)
   503  	if _, err := bc.InsertChain(chain[700:800]); err != nil {
   504  		t.Fatal(err)
   505  	}
   506  	updateHead()
   507  	expEvent(rangeLogsTestSync, 0, 0)
   508  	expEvent(rangeLogsTestSynced, 601, 699)
   509  	expEvent(rangeLogsTestResults, 601, 699)
   510  	expEvent(rangeLogsTestUnindexed, 400, 601)
   511  	expEvent(rangeLogsTestResults, 400, 699)
   512  	expEvent(rangeLogsTestIndexed, 699, 801)
   513  	if _, err := bc.SetCanonical(chain[749]); err != nil { // set head to block 750
   514  		t.Fatal(err)
   515  	}
   516  	updateHead()
   517  	expEvent(rangeLogsTestSync, 0, 0)
   518  	expEvent(rangeLogsTestSynced, 601, 749)
   519  	expEvent(rangeLogsTestResults, 400, 749)
   520  	expEvent(rangeLogsTestIndexed, 749, 751)
   521  	expEvent(rangeLogsTestSync, 0, 0)
   522  	expEvent(rangeLogsTestSynced, 551, 751)
   523  	expEvent(rangeLogsTestResults, 400, 751)
   524  	expEvent(rangeLogsTestDone, 0, 0)
   525  
   526  	// test case #3
   527  	newFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber))
   528  	expEvent(rangeLogsTestIndexed, 750, 751)
   529  	if _, err := bc.SetCanonical(chain[739]); err != nil {
   530  		t.Fatal(err)
   531  	}
   532  	updateHead()
   533  	expEvent(rangeLogsTestSync, 0, 0)
   534  	expEvent(rangeLogsTestSynced, 551, 739)
   535  	expEvent(rangeLogsTestResults, 0, 0)
   536  	expEvent(rangeLogsTestIndexed, 740, 741)
   537  	if _, err := bc.InsertChain(chain[740:750]); err != nil {
   538  		t.Fatal(err)
   539  	}
   540  	updateHead()
   541  	expEvent(rangeLogsTestSync, 0, 0)
   542  	expEvent(rangeLogsTestSynced, 551, 739)
   543  	expEvent(rangeLogsTestResults, 0, 0)
   544  	expEvent(rangeLogsTestIndexed, 750, 751)
   545  	expEvent(rangeLogsTestSync, 0, 0)
   546  	expEvent(rangeLogsTestSynced, 551, 751)
   547  	expEvent(rangeLogsTestResults, 750, 751)
   548  	expEvent(rangeLogsTestDone, 0, 0)
   549  
   550  	// test case #4
   551  	if _, err := bc.SetCanonical(chain[499]); err != nil {
   552  		t.Fatal(err)
   553  	}
   554  	updateHead()
   555  	newFilter(400, int64(rpc.LatestBlockNumber))
   556  	expEvent(rangeLogsTestIndexed, 400, 501)
   557  	if _, err := bc.InsertChain(chain[500:650]); err != nil {
   558  		t.Fatal(err)
   559  	}
   560  	updateHead()
   561  	expEvent(rangeLogsTestSync, 0, 0)
   562  	expEvent(rangeLogsTestSynced, 451, 499)
   563  	expEvent(rangeLogsTestResults, 451, 499)
   564  	expEvent(rangeLogsTestUnindexed, 400, 451)
   565  	expEvent(rangeLogsTestResults, 400, 499)
   566  	// indexed head extension seems possible
   567  	expEvent(rangeLogsTestIndexed, 499, 651)
   568  	// further head extension causes tail unindexing in searched range
   569  	if _, err := bc.InsertChain(chain[650:750]); err != nil {
   570  		t.Fatal(err)
   571  	}
   572  	updateHead()
   573  	expEvent(rangeLogsTestSync, 0, 0)
   574  	expEvent(rangeLogsTestSynced, 551, 649)
   575  	// tail trimmed to 551; cannot merge with existing results
   576  	expEvent(rangeLogsTestResults, 551, 649)
   577  	expEvent(rangeLogsTestUnindexed, 400, 551)
   578  	expEvent(rangeLogsTestResults, 400, 649)
   579  	expEvent(rangeLogsTestIndexed, 649, 751)
   580  	expEvent(rangeLogsTestSync, 0, 0)
   581  	expEvent(rangeLogsTestSynced, 551, 751)
   582  	expEvent(rangeLogsTestResults, 400, 751)
   583  	expEvent(rangeLogsTestDone, 0, 0)
   584  
   585  	// test case #5
   586  	newFilter(400, int64(rpc.LatestBlockNumber))
   587  	expEvent(rangeLogsTestIndexed, 551, 751)
   588  	expEvent(rangeLogsTestSync, 0, 0)
   589  	expEvent(rangeLogsTestSynced, 551, 751)
   590  	expEvent(rangeLogsTestResults, 551, 751)
   591  	expEvent(rangeLogsTestUnindexed, 400, 551)
   592  	if _, err := bc.InsertChain(chain[750:1000]); err != nil {
   593  		t.Fatal(err)
   594  	}
   595  	updateHead()
   596  	expEvent(rangeLogsTestResults, 400, 751)
   597  	// indexed tail already beyond results head; revert to unindexed head search
   598  	expEvent(rangeLogsTestUnindexed, 751, 1001)
   599  	if _, err := bc.SetCanonical(chain[899]); err != nil {
   600  		t.Fatal(err)
   601  	}
   602  	updateHead()
   603  	expEvent(rangeLogsTestResults, 400, 1001)
   604  	expEvent(rangeLogsTestReorg, 400, 901)
   605  	expEvent(rangeLogsTestDone, 0, 0)
   606  }