2016-04-14 09:18:24 -07:00
|
|
|
// Copyright 2015 The go-ethereum Authors
|
|
|
|
// This file is part of the go-ethereum library.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2015-10-12 08:54:59 -07:00
|
|
|
package filters
|
|
|
|
|
|
|
|
import (
|
2015-10-12 08:58:51 -07:00
|
|
|
"io/ioutil"
|
2015-10-12 08:54:59 -07:00
|
|
|
"math/big"
|
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/core"
|
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb"
|
|
|
|
)
|
|
|
|
|
|
|
|
func makeReceipt(addr common.Address) *types.Receipt {
|
|
|
|
receipt := types.NewReceipt(nil, new(big.Int))
|
2015-10-13 02:04:25 -07:00
|
|
|
receipt.Logs = vm.Logs{
|
2015-10-12 08:54:59 -07:00
|
|
|
&vm.Log{Address: addr},
|
2015-10-13 02:04:25 -07:00
|
|
|
}
|
2015-10-12 08:54:59 -07:00
|
|
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
|
|
|
return receipt
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkMipmaps(b *testing.B) {
|
2015-10-12 08:58:51 -07:00
|
|
|
dir, err := ioutil.TempDir("", "mipmap")
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
2015-10-12 08:54:59 -07:00
|
|
|
var (
|
2016-02-19 04:29:19 -08:00
|
|
|
db, _ = ethdb.NewLDBDatabase(dir, 0, 0)
|
2015-10-12 08:54:59 -07:00
|
|
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
|
|
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
|
|
|
addr2 = common.BytesToAddress([]byte("jeff"))
|
|
|
|
addr3 = common.BytesToAddress([]byte("ethereum"))
|
|
|
|
addr4 = common.BytesToAddress([]byte("random addresses please"))
|
|
|
|
)
|
2015-10-12 08:58:51 -07:00
|
|
|
defer db.Close()
|
2015-10-12 08:54:59 -07:00
|
|
|
|
2016-04-15 02:06:57 -07:00
|
|
|
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000)})
|
2016-07-14 08:17:03 -07:00
|
|
|
chain, receipts := core.GenerateChain(nil, genesis, db, 100010, func(i int, gen *core.BlockGen) {
|
2015-10-12 08:54:59 -07:00
|
|
|
var receipts types.Receipts
|
|
|
|
switch i {
|
|
|
|
case 2403:
|
|
|
|
receipt := makeReceipt(addr1)
|
|
|
|
receipts = types.Receipts{receipt}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
|
|
|
case 1034:
|
2015-10-12 08:54:59 -07:00
|
|
|
receipt := makeReceipt(addr2)
|
|
|
|
receipts = types.Receipts{receipt}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
2015-10-12 08:54:59 -07:00
|
|
|
case 34:
|
|
|
|
receipt := makeReceipt(addr3)
|
|
|
|
receipts = types.Receipts{receipt}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
2015-10-12 08:54:59 -07:00
|
|
|
case 99999:
|
|
|
|
receipt := makeReceipt(addr4)
|
|
|
|
receipts = types.Receipts{receipt}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
2015-10-12 08:54:59 -07:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// store the receipts
|
2015-10-22 05:43:21 -07:00
|
|
|
err := core.WriteReceipts(db, receipts)
|
2015-10-12 08:54:59 -07:00
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
2015-10-12 08:58:51 -07:00
|
|
|
core.WriteMipmapBloom(db, uint64(i+1), receipts)
|
2015-10-12 08:54:59 -07:00
|
|
|
})
|
2015-10-13 02:04:25 -07:00
|
|
|
for i, block := range chain {
|
2015-10-12 08:54:59 -07:00
|
|
|
core.WriteBlock(db, block)
|
|
|
|
if err := core.WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil {
|
|
|
|
b.Fatalf("failed to insert block number: %v", err)
|
|
|
|
}
|
|
|
|
if err := core.WriteHeadBlockHash(db, block.Hash()); err != nil {
|
|
|
|
b.Fatalf("failed to insert block number: %v", err)
|
|
|
|
}
|
2016-04-05 06:22:04 -07:00
|
|
|
if err := core.WriteBlockReceipts(db, block.Hash(), block.NumberU64(), receipts[i]); err != nil {
|
2015-10-12 08:54:59 -07:00
|
|
|
b.Fatal("error writing block receipts:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
filter := New(db)
|
2015-10-12 08:58:51 -07:00
|
|
|
filter.SetAddresses([]common.Address{addr1, addr2, addr3, addr4})
|
|
|
|
filter.SetBeginBlock(0)
|
|
|
|
filter.SetEndBlock(-1)
|
2015-10-12 08:54:59 -07:00
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
logs := filter.Find()
|
|
|
|
if len(logs) != 4 {
|
|
|
|
b.Fatal("expected 4 log, got", len(logs))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-12 08:58:51 -07:00
|
|
|
|
|
|
|
func TestFilters(t *testing.T) {
|
|
|
|
dir, err := ioutil.TempDir("", "mipmap")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
var (
|
2016-02-19 04:29:19 -08:00
|
|
|
db, _ = ethdb.NewLDBDatabase(dir, 0, 0)
|
2015-10-12 08:58:51 -07:00
|
|
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
|
|
|
addr = crypto.PubkeyToAddress(key1.PublicKey)
|
|
|
|
|
|
|
|
hash1 = common.BytesToHash([]byte("topic1"))
|
|
|
|
hash2 = common.BytesToHash([]byte("topic2"))
|
|
|
|
hash3 = common.BytesToHash([]byte("topic3"))
|
|
|
|
hash4 = common.BytesToHash([]byte("topic4"))
|
|
|
|
)
|
|
|
|
defer db.Close()
|
|
|
|
|
2016-04-15 02:06:57 -07:00
|
|
|
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr, Balance: big.NewInt(1000000)})
|
2016-07-14 08:17:03 -07:00
|
|
|
chain, receipts := core.GenerateChain(nil, genesis, db, 1000, func(i int, gen *core.BlockGen) {
|
2015-10-12 08:58:51 -07:00
|
|
|
var receipts types.Receipts
|
|
|
|
switch i {
|
|
|
|
case 1:
|
|
|
|
receipt := types.NewReceipt(nil, new(big.Int))
|
2015-10-13 02:04:25 -07:00
|
|
|
receipt.Logs = vm.Logs{
|
2015-10-12 08:58:51 -07:00
|
|
|
&vm.Log{
|
|
|
|
Address: addr,
|
|
|
|
Topics: []common.Hash{hash1},
|
|
|
|
},
|
2015-10-13 02:04:25 -07:00
|
|
|
}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
|
|
|
receipts = types.Receipts{receipt}
|
|
|
|
case 2:
|
|
|
|
receipt := types.NewReceipt(nil, new(big.Int))
|
2015-10-13 02:04:25 -07:00
|
|
|
receipt.Logs = vm.Logs{
|
2015-10-12 08:58:51 -07:00
|
|
|
&vm.Log{
|
|
|
|
Address: addr,
|
|
|
|
Topics: []common.Hash{hash2},
|
|
|
|
},
|
2015-10-13 02:04:25 -07:00
|
|
|
}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
|
|
|
receipts = types.Receipts{receipt}
|
|
|
|
case 998:
|
|
|
|
receipt := types.NewReceipt(nil, new(big.Int))
|
2015-10-13 02:04:25 -07:00
|
|
|
receipt.Logs = vm.Logs{
|
2015-10-12 08:58:51 -07:00
|
|
|
&vm.Log{
|
|
|
|
Address: addr,
|
|
|
|
Topics: []common.Hash{hash3},
|
|
|
|
},
|
2015-10-13 02:04:25 -07:00
|
|
|
}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
|
|
|
receipts = types.Receipts{receipt}
|
|
|
|
case 999:
|
|
|
|
receipt := types.NewReceipt(nil, new(big.Int))
|
2015-10-13 02:04:25 -07:00
|
|
|
receipt.Logs = vm.Logs{
|
2015-10-12 08:58:51 -07:00
|
|
|
&vm.Log{
|
|
|
|
Address: addr,
|
|
|
|
Topics: []common.Hash{hash4},
|
|
|
|
},
|
2015-10-13 02:04:25 -07:00
|
|
|
}
|
2015-10-12 08:58:51 -07:00
|
|
|
gen.AddUncheckedReceipt(receipt)
|
|
|
|
receipts = types.Receipts{receipt}
|
|
|
|
}
|
|
|
|
|
|
|
|
// store the receipts
|
2015-10-22 05:43:21 -07:00
|
|
|
err := core.WriteReceipts(db, receipts)
|
2015-10-12 08:58:51 -07:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// i is used as block number for the writes but since the i
|
|
|
|
// starts at 0 and block 0 (genesis) is already present increment
|
|
|
|
// by one
|
|
|
|
core.WriteMipmapBloom(db, uint64(i+1), receipts)
|
|
|
|
})
|
2015-10-13 02:04:25 -07:00
|
|
|
for i, block := range chain {
|
2015-10-12 08:58:51 -07:00
|
|
|
core.WriteBlock(db, block)
|
|
|
|
if err := core.WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil {
|
|
|
|
t.Fatalf("failed to insert block number: %v", err)
|
|
|
|
}
|
|
|
|
if err := core.WriteHeadBlockHash(db, block.Hash()); err != nil {
|
|
|
|
t.Fatalf("failed to insert block number: %v", err)
|
|
|
|
}
|
2016-04-05 06:22:04 -07:00
|
|
|
if err := core.WriteBlockReceipts(db, block.Hash(), block.NumberU64(), receipts[i]); err != nil {
|
2015-10-12 08:58:51 -07:00
|
|
|
t.Fatal("error writing block receipts:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
filter := New(db)
|
|
|
|
filter.SetAddresses([]common.Address{addr})
|
|
|
|
filter.SetTopics([][]common.Hash{[]common.Hash{hash1, hash2, hash3, hash4}})
|
|
|
|
filter.SetBeginBlock(0)
|
|
|
|
filter.SetEndBlock(-1)
|
|
|
|
|
|
|
|
logs := filter.Find()
|
|
|
|
if len(logs) != 4 {
|
|
|
|
t.Error("expected 4 log, got", len(logs))
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = New(db)
|
|
|
|
filter.SetAddresses([]common.Address{addr})
|
|
|
|
filter.SetTopics([][]common.Hash{[]common.Hash{hash3}})
|
|
|
|
filter.SetBeginBlock(900)
|
|
|
|
filter.SetEndBlock(999)
|
|
|
|
logs = filter.Find()
|
|
|
|
if len(logs) != 1 {
|
|
|
|
t.Error("expected 1 log, got", len(logs))
|
|
|
|
}
|
|
|
|
if len(logs) > 0 && logs[0].Topics[0] != hash3 {
|
|
|
|
t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = New(db)
|
|
|
|
filter.SetAddresses([]common.Address{addr})
|
|
|
|
filter.SetTopics([][]common.Hash{[]common.Hash{hash3}})
|
|
|
|
filter.SetBeginBlock(990)
|
|
|
|
filter.SetEndBlock(-1)
|
|
|
|
logs = filter.Find()
|
|
|
|
if len(logs) != 1 {
|
|
|
|
t.Error("expected 1 log, got", len(logs))
|
|
|
|
}
|
|
|
|
if len(logs) > 0 && logs[0].Topics[0] != hash3 {
|
|
|
|
t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = New(db)
|
|
|
|
filter.SetTopics([][]common.Hash{[]common.Hash{hash1, hash2}})
|
|
|
|
filter.SetBeginBlock(1)
|
|
|
|
filter.SetEndBlock(10)
|
|
|
|
|
|
|
|
logs = filter.Find()
|
|
|
|
if len(logs) != 2 {
|
|
|
|
t.Error("expected 2 log, got", len(logs))
|
|
|
|
}
|
|
|
|
|
|
|
|
failHash := common.BytesToHash([]byte("fail"))
|
|
|
|
filter = New(db)
|
|
|
|
filter.SetTopics([][]common.Hash{[]common.Hash{failHash}})
|
|
|
|
filter.SetBeginBlock(0)
|
|
|
|
filter.SetEndBlock(-1)
|
|
|
|
|
|
|
|
logs = filter.Find()
|
|
|
|
if len(logs) != 0 {
|
|
|
|
t.Error("expected 0 log, got", len(logs))
|
|
|
|
}
|
|
|
|
|
|
|
|
failAddr := common.BytesToAddress([]byte("failmenow"))
|
|
|
|
filter = New(db)
|
|
|
|
filter.SetAddresses([]common.Address{failAddr})
|
|
|
|
filter.SetBeginBlock(0)
|
|
|
|
filter.SetEndBlock(-1)
|
|
|
|
|
|
|
|
logs = filter.Find()
|
|
|
|
if len(logs) != 0 {
|
|
|
|
t.Error("expected 0 log, got", len(logs))
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = New(db)
|
|
|
|
filter.SetTopics([][]common.Hash{[]common.Hash{failHash}, []common.Hash{hash1}})
|
|
|
|
filter.SetBeginBlock(0)
|
|
|
|
filter.SetEndBlock(-1)
|
|
|
|
|
|
|
|
logs = filter.Find()
|
|
|
|
if len(logs) != 0 {
|
|
|
|
t.Error("expected 0 log, got", len(logs))
|
|
|
|
}
|
|
|
|
}
|