github.com/devfans/go-ethereum@v1.5.10-0.20170326212234-7419d0c38291/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  	"io/ioutil"
    22  	"math/big"
    23  	"os"
    24  	"testing"
    25  
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/core"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/crypto"
    30  	"github.com/ethereum/go-ethereum/ethdb"
    31  	"github.com/ethereum/go-ethereum/event"
    32  	"github.com/ethereum/go-ethereum/params"
    33  )
    34  
    35  func makeReceipt(addr common.Address) *types.Receipt {
    36  	receipt := types.NewReceipt(nil, new(big.Int))
    37  	receipt.Logs = []*types.Log{
    38  		{Address: addr},
    39  	}
    40  	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
    41  	return receipt
    42  }
    43  
    44  func BenchmarkMipmaps(b *testing.B) {
    45  	dir, err := ioutil.TempDir("", "mipmap")
    46  	if err != nil {
    47  		b.Fatal(err)
    48  	}
    49  	defer os.RemoveAll(dir)
    50  
    51  	var (
    52  		db, _   = ethdb.NewLDBDatabase(dir, 0, 0)
    53  		mux     = new(event.TypeMux)
    54  		backend = &testBackend{mux, db}
    55  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    56  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
    57  		addr2   = common.BytesToAddress([]byte("jeff"))
    58  		addr3   = common.BytesToAddress([]byte("ethereum"))
    59  		addr4   = common.BytesToAddress([]byte("random addresses please"))
    60  	)
    61  	defer db.Close()
    62  
    63  	genesis := core.GenesisBlockForTesting(db, addr1, big.NewInt(1000000))
    64  	chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 100010, func(i int, gen *core.BlockGen) {
    65  		var receipts types.Receipts
    66  		switch i {
    67  		case 2403:
    68  			receipt := makeReceipt(addr1)
    69  			receipts = types.Receipts{receipt}
    70  			gen.AddUncheckedReceipt(receipt)
    71  		case 1034:
    72  			receipt := makeReceipt(addr2)
    73  			receipts = types.Receipts{receipt}
    74  			gen.AddUncheckedReceipt(receipt)
    75  		case 34:
    76  			receipt := makeReceipt(addr3)
    77  			receipts = types.Receipts{receipt}
    78  			gen.AddUncheckedReceipt(receipt)
    79  		case 99999:
    80  			receipt := makeReceipt(addr4)
    81  			receipts = types.Receipts{receipt}
    82  			gen.AddUncheckedReceipt(receipt)
    83  
    84  		}
    85  
    86  		// store the receipts
    87  		err := core.WriteReceipts(db, receipts)
    88  		if err != nil {
    89  			b.Fatal(err)
    90  		}
    91  		core.WriteMipmapBloom(db, uint64(i+1), receipts)
    92  	})
    93  	for i, block := range chain {
    94  		core.WriteBlock(db, block)
    95  		if err := core.WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil {
    96  			b.Fatalf("failed to insert block number: %v", err)
    97  		}
    98  		if err := core.WriteHeadBlockHash(db, block.Hash()); err != nil {
    99  			b.Fatalf("failed to insert block number: %v", err)
   100  		}
   101  		if err := core.WriteBlockReceipts(db, block.Hash(), block.NumberU64(), receipts[i]); err != nil {
   102  			b.Fatal("error writing block receipts:", err)
   103  		}
   104  	}
   105  	b.ResetTimer()
   106  
   107  	filter := New(backend, true)
   108  	filter.SetAddresses([]common.Address{addr1, addr2, addr3, addr4})
   109  	filter.SetBeginBlock(0)
   110  	filter.SetEndBlock(-1)
   111  
   112  	for i := 0; i < b.N; i++ {
   113  		logs, _ := filter.Find(context.Background())
   114  		if len(logs) != 4 {
   115  			b.Fatal("expected 4 logs, got", len(logs))
   116  		}
   117  	}
   118  }
   119  
   120  func TestFilters(t *testing.T) {
   121  	dir, err := ioutil.TempDir("", "mipmap")
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	defer os.RemoveAll(dir)
   126  
   127  	var (
   128  		db, _   = ethdb.NewLDBDatabase(dir, 0, 0)
   129  		mux     = new(event.TypeMux)
   130  		backend = &testBackend{mux, db}
   131  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   132  		addr    = crypto.PubkeyToAddress(key1.PublicKey)
   133  
   134  		hash1 = common.BytesToHash([]byte("topic1"))
   135  		hash2 = common.BytesToHash([]byte("topic2"))
   136  		hash3 = common.BytesToHash([]byte("topic3"))
   137  		hash4 = common.BytesToHash([]byte("topic4"))
   138  	)
   139  	defer db.Close()
   140  
   141  	genesis := core.GenesisBlockForTesting(db, addr, big.NewInt(1000000))
   142  	chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 1000, func(i int, gen *core.BlockGen) {
   143  		var receipts types.Receipts
   144  		switch i {
   145  		case 1:
   146  			receipt := types.NewReceipt(nil, new(big.Int))
   147  			receipt.Logs = []*types.Log{
   148  				{
   149  					Address: addr,
   150  					Topics:  []common.Hash{hash1},
   151  				},
   152  			}
   153  			gen.AddUncheckedReceipt(receipt)
   154  			receipts = types.Receipts{receipt}
   155  		case 2:
   156  			receipt := types.NewReceipt(nil, new(big.Int))
   157  			receipt.Logs = []*types.Log{
   158  				{
   159  					Address: addr,
   160  					Topics:  []common.Hash{hash2},
   161  				},
   162  			}
   163  			gen.AddUncheckedReceipt(receipt)
   164  			receipts = types.Receipts{receipt}
   165  		case 998:
   166  			receipt := types.NewReceipt(nil, new(big.Int))
   167  			receipt.Logs = []*types.Log{
   168  				{
   169  					Address: addr,
   170  					Topics:  []common.Hash{hash3},
   171  				},
   172  			}
   173  			gen.AddUncheckedReceipt(receipt)
   174  			receipts = types.Receipts{receipt}
   175  		case 999:
   176  			receipt := types.NewReceipt(nil, new(big.Int))
   177  			receipt.Logs = []*types.Log{
   178  				{
   179  					Address: addr,
   180  					Topics:  []common.Hash{hash4},
   181  				},
   182  			}
   183  			gen.AddUncheckedReceipt(receipt)
   184  			receipts = types.Receipts{receipt}
   185  		}
   186  
   187  		// store the receipts
   188  		err := core.WriteReceipts(db, receipts)
   189  		if err != nil {
   190  			t.Fatal(err)
   191  		}
   192  		// i is used as block number for the writes but since the i
   193  		// starts at 0 and block 0 (genesis) is already present increment
   194  		// by one
   195  		core.WriteMipmapBloom(db, uint64(i+1), receipts)
   196  	})
   197  	for i, block := range chain {
   198  		core.WriteBlock(db, block)
   199  		if err := core.WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil {
   200  			t.Fatalf("failed to insert block number: %v", err)
   201  		}
   202  		if err := core.WriteHeadBlockHash(db, block.Hash()); err != nil {
   203  			t.Fatalf("failed to insert block number: %v", err)
   204  		}
   205  		if err := core.WriteBlockReceipts(db, block.Hash(), block.NumberU64(), receipts[i]); err != nil {
   206  			t.Fatal("error writing block receipts:", err)
   207  		}
   208  	}
   209  
   210  	filter := New(backend, true)
   211  	filter.SetAddresses([]common.Address{addr})
   212  	filter.SetTopics([][]common.Hash{{hash1, hash2, hash3, hash4}})
   213  	filter.SetBeginBlock(0)
   214  	filter.SetEndBlock(-1)
   215  
   216  	logs, _ := filter.Find(context.Background())
   217  	if len(logs) != 4 {
   218  		t.Error("expected 4 log, got", len(logs))
   219  	}
   220  
   221  	filter = New(backend, true)
   222  	filter.SetAddresses([]common.Address{addr})
   223  	filter.SetTopics([][]common.Hash{{hash3}})
   224  	filter.SetBeginBlock(900)
   225  	filter.SetEndBlock(999)
   226  	logs, _ = filter.Find(context.Background())
   227  	if len(logs) != 1 {
   228  		t.Error("expected 1 log, got", len(logs))
   229  	}
   230  	if len(logs) > 0 && logs[0].Topics[0] != hash3 {
   231  		t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0])
   232  	}
   233  
   234  	filter = New(backend, true)
   235  	filter.SetAddresses([]common.Address{addr})
   236  	filter.SetTopics([][]common.Hash{{hash3}})
   237  	filter.SetBeginBlock(990)
   238  	filter.SetEndBlock(-1)
   239  	logs, _ = filter.Find(context.Background())
   240  	if len(logs) != 1 {
   241  		t.Error("expected 1 log, got", len(logs))
   242  	}
   243  	if len(logs) > 0 && logs[0].Topics[0] != hash3 {
   244  		t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0])
   245  	}
   246  
   247  	filter = New(backend, true)
   248  	filter.SetTopics([][]common.Hash{{hash1, hash2}})
   249  	filter.SetBeginBlock(1)
   250  	filter.SetEndBlock(10)
   251  
   252  	logs, _ = filter.Find(context.Background())
   253  	if len(logs) != 2 {
   254  		t.Error("expected 2 log, got", len(logs))
   255  	}
   256  
   257  	failHash := common.BytesToHash([]byte("fail"))
   258  	filter = New(backend, true)
   259  	filter.SetTopics([][]common.Hash{{failHash}})
   260  	filter.SetBeginBlock(0)
   261  	filter.SetEndBlock(-1)
   262  
   263  	logs, _ = filter.Find(context.Background())
   264  	if len(logs) != 0 {
   265  		t.Error("expected 0 log, got", len(logs))
   266  	}
   267  
   268  	failAddr := common.BytesToAddress([]byte("failmenow"))
   269  	filter = New(backend, true)
   270  	filter.SetAddresses([]common.Address{failAddr})
   271  	filter.SetBeginBlock(0)
   272  	filter.SetEndBlock(-1)
   273  
   274  	logs, _ = filter.Find(context.Background())
   275  	if len(logs) != 0 {
   276  		t.Error("expected 0 log, got", len(logs))
   277  	}
   278  
   279  	filter = New(backend, true)
   280  	filter.SetTopics([][]common.Hash{{failHash}, {hash1}})
   281  	filter.SetBeginBlock(0)
   282  	filter.SetEndBlock(-1)
   283  
   284  	logs, _ = filter.Find(context.Background())
   285  	if len(logs) != 0 {
   286  		t.Error("expected 0 log, got", len(logs))
   287  	}
   288  }