func blockRecovery(ctx *cli.Context) { if len(ctx.Args()) < 1 { glog.Fatal("recover requires block number or hash") } arg := ctx.Args().First() cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain"), cfg.DatabaseCache) if err != nil { glog.Fatalln("could not open db:", err) } var block *types.Block if arg[0] == '#' { block = core.GetBlock(blockDb, core.GetCanonicalHash(blockDb, common.String2Big(arg[1:]).Uint64())) } else { block = core.GetBlock(blockDb, common.HexToHash(arg)) } if block == nil { glog.Fatalln("block not found. Recovery failed") } if err = core.WriteHeadBlockHash(blockDb, block.Hash()); err != nil { glog.Fatalln("block write err", err) } glog.Infof("Recovery succesful. New HEAD %x\n", block.Hash()) }
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Create the database in memory or in a temporary directory. var db ethdb.Database if !disk { db, _ = ethdb.NewMemDatabase() } else { dir, err := ioutil.TempDir("", "exp-core-bench") if err != nil { b.Fatalf("cannot create temporary directory: %v", err) } defer os.RemoveAll(dir) db, err = ethdb.NewLDBDatabase(dir, 0) if err != nil { b.Fatalf("cannot create temporary database: %v", err) } defer db.Close() } // Generate a chain of b.N blocks using the supplied block // generator function. genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds}) chain, _ := GenerateChain(genesis, db, b.N, gen) // Time the insertion of the new chain. // State and blocks are stored in the same DB. evmux := new(event.TypeMux) chainman, _ := NewBlockChain(db, FakePow{}, evmux) defer chainman.Stop() b.ReportAllocs() b.ResetTimer() if i, err := chainman.InsertChain(chain); err != nil { b.Fatalf("insert error (block %d): %v\n", i, err) } }
// MakeChain creates a chain manager from set command line flags. func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb common.Database) { datadir := ctx.GlobalString(DataDirFlag.Name) cache := ctx.GlobalInt(CacheFlag.Name) var err error if chainDb, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache); err != nil { Fatalf("Could not open database: %v", err) } if ctx.GlobalBool(OlympicFlag.Name) { InitOlympic() _, err := core.WriteTestNetGenesisBlock(chainDb, 42) if err != nil { glog.Fatalln(err) } } eventMux := new(event.TypeMux) pow := ethash.New() //genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB) chain, err = core.NewChainManager(chainDb, pow, eventMux) if err != nil { Fatalf("Could not start chainmanager: %v", err) } proc := core.NewBlockProcessor(chainDb, pow, chain, eventMux) chain.SetProcessor(proc) return chain, chainDb }
func tempDB() (string, Database) { dir, err := ioutil.TempDir("", "trie-bench") if err != nil { panic(fmt.Sprintf("can't create temporary directory: %v", err)) } db, err := ethdb.NewLDBDatabase(dir, 300*1024) if err != nil { panic(fmt.Sprintf("can't create temporary database: %v", err)) } return dir, db }
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. func MakeChainDatabase(ctx *cli.Context) ethdb.Database { var ( datadir = MustMakeDataDir(ctx) cache = ctx.GlobalInt(CacheFlag.Name) handles = MakeDatabaseHandles() ) chainDb, err := ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache, handles) if err != nil { Fatalf("Could not open database: %v", err) } return chainDb }
// initGenesis will initialise the given JSON format genesis file and writes it as // the zero'd block (i.e. genesis) or will fail hard if it can't succeed. func initGenesis(ctx *cli.Context) error { genesisPath := ctx.Args().First() if len(genesisPath) == 0 { utils.Fatalf("must supply path to genesis JSON file") } chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0) if err != nil { utils.Fatalf("could not open database: %v", err) } genesisFile, err := os.Open(genesisPath) if err != nil { utils.Fatalf("failed to read genesis file: %v", err) } block, err := core.WriteGenesisBlock(chainDb, genesisFile) if err != nil { utils.Fatalf("failed to write genesis block: %v", err) } glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash()) return nil }
// OpenDatabase opens an existing database with the given name (or creates one // if no previous can be found) from within the node's data directory. If the // node is an ephemeral one, a memory database is returned. func (ctx *ServiceContext) OpenDatabase(name string, cache int, handles int) (ethdb.Database, error) { if ctx.datadir == "" { return ethdb.NewMemDatabase() } return ethdb.NewLDBDatabase(filepath.Join(ctx.datadir, name), cache, handles) }
func New(config *Config) (*Expanse, error) { logger.New(config.DataDir, config.LogFile, config.Verbosity) // Let the database take 3/4 of the max open files (TODO figure out a way to get the actual limit of the open files) const dbCount = 3 ethdb.OpenFileLimit = 128 / (dbCount + 1) newdb := config.NewDB if newdb == nil { newdb = func(path string) (ethdb.Database, error) { return ethdb.NewLDBDatabase(path, config.DatabaseCache) } } // Open the chain database and perform any upgrades needed chainDb, err := newdb(filepath.Join(config.DataDir, "chaindata")) if err != nil { if errno, ok := err.(syscall.Errno); ok && datadirInUseErrnos[uint(errno)] { err = fmt.Errorf("%v (check if another instance of geth is already running with the same data directory '%s')", err, config.DataDir) } return nil, fmt.Errorf("blockchain db err: %v", err) } if db, ok := chainDb.(*ethdb.LDBDatabase); ok { db.Meter("eth/db/chaindata/") } if err := upgradeChainDatabase(chainDb); err != nil { return nil, err } if err := addMipmapBloomBins(chainDb); err != nil { return nil, err } dappDb, err := newdb(filepath.Join(config.DataDir, "dapp")) if err != nil { if errno, ok := err.(syscall.Errno); ok && datadirInUseErrnos[uint(errno)] { err = fmt.Errorf("%v (check if another instance of geth is already running with the same data directory '%s')", err, config.DataDir) } return nil, fmt.Errorf("dapp db err: %v", err) } if db, ok := dappDb.(*ethdb.LDBDatabase); ok { db.Meter("eth/db/dapp/") } nodeDb := filepath.Join(config.DataDir, "nodes") glog.V(logger.Info).Infof("Protocol Versions: %v, Network Id: %v", ProtocolVersions, config.NetworkId) if len(config.GenesisFile) > 0 { fr, err := os.Open(config.GenesisFile) if err != nil { return nil, err } block, err := core.WriteGenesisBlock(chainDb, fr) if err != nil { return nil, err } glog.V(logger.Info).Infof("Successfully wrote genesis block. New genesis hash = %x\n", block.Hash()) } // different modes switch { case config.Olympic: glog.V(logger.Error).Infoln("Starting Olympic network") fallthrough case config.DevMode: _, err := core.WriteOlympicGenesisBlock(chainDb, 42) if err != nil { return nil, err } case config.TestNet: state.StartingNonce = 1048576 // (2**20) _, err := core.WriteTestNetGenesisBlock(chainDb, 0x6d6f7264656e) if err != nil { return nil, err } } // This is for testing only. if config.GenesisBlock != nil { core.WriteTd(chainDb, config.GenesisBlock.Hash(), config.GenesisBlock.Difficulty()) core.WriteBlock(chainDb, config.GenesisBlock) core.WriteCanonicalHash(chainDb, config.GenesisBlock.Hash(), config.GenesisBlock.NumberU64()) core.WriteHeadBlockHash(chainDb, config.GenesisBlock.Hash()) } if !config.SkipBcVersionCheck { b, _ := chainDb.Get([]byte("BlockchainVersion")) bcVersion := int(common.NewValue(b).Uint()) if bcVersion != config.BlockChainVersion && bcVersion != 0 { return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run gexp upgradedb.\n", bcVersion, config.BlockChainVersion) } saveBlockchainVersion(chainDb, config.BlockChainVersion) } glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion) exp := &Expanse{ shutdownChan: make(chan bool), chainDb: chainDb, dappDb: dappDb, eventMux: &event.TypeMux{}, accountManager: config.AccountManager, DataDir: config.DataDir, etherbase: config.Etherbase, clientVersion: config.Name, // TODO should separate from Name netVersionId: config.NetworkId, NatSpec: config.NatSpec, MinerThreads: config.MinerThreads, SolcPath: config.SolcPath, AutoDAG: config.AutoDAG, PowTest: config.PowTest, GpoMinGasPrice: config.GpoMinGasPrice, GpoMaxGasPrice: config.GpoMaxGasPrice, GpoFullBlockRatio: config.GpoFullBlockRatio, GpobaseStepDown: config.GpobaseStepDown, GpobaseStepUp: config.GpobaseStepUp, GpobaseCorrectionFactor: config.GpobaseCorrectionFactor, httpclient: httpclient.New(config.DocRoot), } if config.PowTest { glog.V(logger.Info).Infof("ethash used in test mode") exp.pow, err = ethash.NewForTesting() if err != nil { return nil, err } } else { exp.pow = ethash.New() } //genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb) exp.blockchain, err = core.NewBlockChain(chainDb, exp.pow, exp.EventMux()) if err != nil { if err == core.ErrNoGenesis { return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`) } return nil, err } newPool := core.NewTxPool(exp.EventMux(), exp.blockchain.State, exp.blockchain.GasLimit) exp.txPool = newPool if exp.protocolManager, err = NewProtocolManager(config.FastSync, config.NetworkId, exp.eventMux, exp.txPool, exp.pow, exp.blockchain, chainDb); err != nil { return nil, err } exp.miner = miner.New(exp, exp.EventMux(), exp.pow) exp.miner.SetGasPrice(config.GasPrice) exp.miner.SetExtra(config.ExtraData) if config.Shh { exp.whisper = whisper.New() exp.shhVersionId = int(exp.whisper.Version()) } netprv, err := config.nodeKey() if err != nil { return nil, err } protocols := append([]p2p.Protocol{}, exp.protocolManager.SubProtocols...) if config.Shh { protocols = append(protocols, exp.whisper.Protocol()) } exp.net = &p2p.Server{ PrivateKey: netprv, Name: config.Name, MaxPeers: config.MaxPeers, MaxPendingPeers: config.MaxPendingPeers, Discovery: config.Discovery, Protocols: protocols, NAT: config.NAT, NoDial: !config.Dial, BootstrapNodes: config.parseBootNodes(), StaticNodes: config.parseNodes(staticNodes), TrustedNodes: config.parseNodes(trustedNodes), NodeDatabase: nodeDb, } if len(config.Port) > 0 { exp.net.ListenAddr = ":" + config.Port } vm.Debug = config.VmDebug return exp, nil }
func TestMipmapChain(t *testing.T) { dir, err := ioutil.TempDir("", "mipmap") if err != nil { t.Fatal(err) } defer os.RemoveAll(dir) var ( db, _ = ethdb.NewLDBDatabase(dir, 16) key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr = crypto.PubkeyToAddress(key1.PublicKey) addr2 = common.BytesToAddress([]byte("jeff")) hash1 = common.BytesToHash([]byte("topic1")) ) defer db.Close() genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr, big.NewInt(1000000)}) chain, receipts := GenerateChain(genesis, db, 1010, func(i int, gen *BlockGen) { var receipts types.Receipts switch i { case 1: receipt := types.NewReceipt(nil, new(big.Int)) receipt.Logs = vm.Logs{ &vm.Log{ Address: addr, Topics: []common.Hash{hash1}, }, } gen.AddUncheckedReceipt(receipt) receipts = types.Receipts{receipt} case 1000: receipt := types.NewReceipt(nil, new(big.Int)) receipt.Logs = vm.Logs{&vm.Log{Address: addr2}} gen.AddUncheckedReceipt(receipt) receipts = types.Receipts{receipt} } // store the receipts err := WriteReceipts(db, receipts) if err != nil { t.Fatal(err) } WriteMipmapBloom(db, uint64(i+1), receipts) }) for i, block := range chain { WriteBlock(db, block) if err := WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil { t.Fatalf("failed to insert block number: %v", err) } if err := WriteHeadBlockHash(db, block.Hash()); err != nil { t.Fatalf("failed to insert block number: %v", err) } if err := WriteBlockReceipts(db, block.Hash(), receipts[i]); err != nil { t.Fatal("error writing block receipts:", err) } } bloom := GetMipmapBloom(db, 0, 1000) if bloom.TestBytes(addr2[:]) { t.Error("address was included in bloom and should not have") } }
func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes [][2]bool, expectBlock *big.Int, expectVote bool) { // Create a temporary data directory to use and inspect later datadir := tmpdir(t) defer os.RemoveAll(datadir) // Start a instance with the requested flags set and immediately terminate if genesis != "" { json := filepath.Join(datadir, "genesis.json") if err := ioutil.WriteFile(json, []byte(genesis), 0600); err != nil { t.Fatalf("failed to write genesis file: %v", err) } runGeth(t, "--datadir", datadir, "init", json).cmd.Wait() } for _, vote := range votes { args := []string{"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir} if testnet { args = append(args, "--testnet") } if vote[0] { args = append(args, "--support-dao-fork") } if vote[1] { args = append(args, "--oppose-dao-fork") } geth := runGeth(t, append(args, []string{"--exec", "2+2", "console"}...)...) geth.cmd.Wait() } // Retrieve the DAO config flag from the database path := filepath.Join(datadir, "chaindata") if testnet && genesis == "" { path = filepath.Join(datadir, "testnet", "chaindata") } db, err := ethdb.NewLDBDatabase(path, 0, 0) if err != nil { t.Fatalf("failed to open test database: %v", err) } defer db.Close() genesisHash := common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") if testnet { genesisHash = common.HexToHash("0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303") } if genesis != "" { genesisHash = daoGenesisHash } config, err := core.GetChainConfig(db, genesisHash) if err != nil { t.Fatalf("failed to retrieve chain config: %v", err) } // Validate the DAO hard-fork block number against the expected value if config.DAOForkBlock == nil { if expectBlock != nil { t.Errorf("dao hard-fork block mismatch: have nil, want %v", expectBlock) } } else if expectBlock == nil { t.Errorf("dao hard-fork block mismatch: have %v, want nil", config.DAOForkBlock) } else if config.DAOForkBlock.Cmp(expectBlock) != 0 { t.Errorf("dao hard-fork block mismatch: have %v, want %v", config.DAOForkBlock, expectBlock) } if config.DAOForkSupport != expectVote { t.Errorf("dao hard-fork support mismatch: have %v, want %v", config.DAOForkSupport, expectVote) } }
func New(config *Config) (*Expanse, error) { // Bootstrap database logger.New(config.DataDir, config.LogFile, config.Verbosity) if len(config.LogJSON) > 0 { logger.NewJSONsystem(config.DataDir, config.LogJSON) } // Let the database take 3/4 of the max open files (TODO figure out a way to get the actual limit of the open files) const dbCount = 3 ethdb.OpenFileLimit = 128 / (dbCount + 1) newdb := config.NewDB if newdb == nil { newdb = func(path string) (common.Database, error) { return ethdb.NewLDBDatabase(path, config.DatabaseCache) } } // attempt to merge database together, upgrading from an old version if err := mergeDatabases(config.DataDir, newdb); err != nil { return nil, err } chainDb, err := newdb(filepath.Join(config.DataDir, "chaindata")) if err != nil { return nil, fmt.Errorf("blockchain db err: %v", err) } if db, ok := chainDb.(*ethdb.LDBDatabase); ok { db.Meter("eth/db/chaindata/") } dappDb, err := newdb(filepath.Join(config.DataDir, "dapp")) if err != nil { return nil, fmt.Errorf("dapp db err: %v", err) } if db, ok := dappDb.(*ethdb.LDBDatabase); ok { db.Meter("eth/db/dapp/") } nodeDb := filepath.Join(config.DataDir, "nodes") glog.V(logger.Info).Infof("Protocol Versions: %v, Network Id: %v", ProtocolVersions, config.NetworkId) if len(config.GenesisFile) > 0 { fr, err := os.Open(config.GenesisFile) if err != nil { return nil, err } block, err := core.WriteGenesisBlock(chainDb, fr) if err != nil { return nil, err } glog.V(logger.Info).Infof("Successfully wrote genesis block. New genesis hash = %x\n", block.Hash()) } if config.Olympic { _, err := core.WriteTestNetGenesisBlock(chainDb, 42) if err != nil { return nil, err } glog.V(logger.Error).Infoln("Starting Olympic network") } // This is for testing only. if config.GenesisBlock != nil { core.WriteBlock(chainDb, config.GenesisBlock) core.WriteHead(chainDb, config.GenesisBlock) } if !config.SkipBcVersionCheck { b, _ := chainDb.Get([]byte("BlockchainVersion")) bcVersion := int(common.NewValue(b).Uint()) if bcVersion != config.BlockChainVersion && bcVersion != 0 { return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run gexp upgradedb.\n", bcVersion, config.BlockChainVersion) } saveBlockchainVersion(chainDb, config.BlockChainVersion) } glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion) exp := &Expanse{ shutdownChan: make(chan bool), databasesClosed: make(chan bool), chainDb: chainDb, dappDb: dappDb, eventMux: &event.TypeMux{}, accountManager: config.AccountManager, DataDir: config.DataDir, etherbase: config.Etherbase, clientVersion: config.Name, // TODO should separate from Name netVersionId: config.NetworkId, NatSpec: config.NatSpec, MinerThreads: config.MinerThreads, SolcPath: config.SolcPath, AutoDAG: config.AutoDAG, PowTest: config.PowTest, GpoMinGasPrice: config.GpoMinGasPrice, GpoMaxGasPrice: config.GpoMaxGasPrice, GpoFullBlockRatio: config.GpoFullBlockRatio, GpobaseStepDown: config.GpobaseStepDown, GpobaseStepUp: config.GpobaseStepUp, GpobaseCorrectionFactor: config.GpobaseCorrectionFactor, } if config.PowTest { glog.V(logger.Info).Infof("ethash used in test mode") exp.pow, err = ethash.NewForTesting() if err != nil { return nil, err } } else { exp.pow = ethash.New() } //genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb) exp.chainManager, err = core.NewChainManager(chainDb, exp.pow, exp.EventMux()) if err != nil { if err == core.ErrNoGenesis { return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`) } return nil, err } exp.txPool = core.NewTxPool(exp.EventMux(), exp.chainManager.State, exp.chainManager.GasLimit) exp.blockProcessor = core.NewBlockProcessor(chainDb, exp.pow, exp.chainManager, exp.EventMux()) exp.chainManager.SetProcessor(exp.blockProcessor) exp.protocolManager = NewProtocolManager(config.NetworkId, exp.eventMux, exp.txPool, exp.pow, exp.chainManager) exp.miner = miner.New(exp, exp.EventMux(), exp.pow) exp.miner.SetGasPrice(config.GasPrice) exp.miner.SetExtra(config.ExtraData) if config.Shh { exp.whisper = whisper.New() exp.shhVersionId = int(exp.whisper.Version()) } netprv, err := config.nodeKey() if err != nil { return nil, err } protocols := append([]p2p.Protocol{}, exp.protocolManager.SubProtocols...) if config.Shh { protocols = append(protocols, exp.whisper.Protocol()) } exp.net = &p2p.Server{ PrivateKey: netprv, Name: config.Name, MaxPeers: config.MaxPeers, MaxPendingPeers: config.MaxPendingPeers, Discovery: config.Discovery, Protocols: protocols, NAT: config.NAT, NoDial: !config.Dial, BootstrapNodes: config.parseBootNodes(), StaticNodes: config.parseNodes(staticNodes), TrustedNodes: config.parseNodes(trustedNodes), NodeDatabase: nodeDb, } if len(config.Port) > 0 { exp.net.ListenAddr = ":" + config.Port } vm.Debug = config.VmDebug return exp, nil }
func BenchmarkMipmaps(b *testing.B) { dir, err := ioutil.TempDir("", "mipmap") if err != nil { b.Fatal(err) } defer os.RemoveAll(dir) var ( db, _ = ethdb.NewLDBDatabase(dir, 0, 0) key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr2 = common.BytesToAddress([]byte("jeff")) addr3 = common.BytesToAddress([]byte("expanse")) addr4 = common.BytesToAddress([]byte("random addresses please")) ) defer db.Close() genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000)}) chain, receipts := core.GenerateChain(nil, genesis, db, 100010, func(i int, gen *core.BlockGen) { var receipts types.Receipts switch i { case 2403: receipt := makeReceipt(addr1) receipts = types.Receipts{receipt} gen.AddUncheckedReceipt(receipt) case 1034: receipt := makeReceipt(addr2) receipts = types.Receipts{receipt} gen.AddUncheckedReceipt(receipt) case 34: receipt := makeReceipt(addr3) receipts = types.Receipts{receipt} gen.AddUncheckedReceipt(receipt) case 99999: receipt := makeReceipt(addr4) receipts = types.Receipts{receipt} gen.AddUncheckedReceipt(receipt) } // store the receipts err := core.WriteReceipts(db, receipts) if err != nil { b.Fatal(err) } core.WriteMipmapBloom(db, uint64(i+1), receipts) }) for i, block := range chain { 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) } if err := core.WriteBlockReceipts(db, block.Hash(), receipts[i]); err != nil { b.Fatal("error writing block receipts:", err) } } b.ResetTimer() filter := New(db) filter.SetAddresses([]common.Address{addr1, addr2, addr3, addr4}) filter.SetBeginBlock(0) filter.SetEndBlock(-1) for i := 0; i < b.N; i++ { logs := filter.Find() if len(logs) != 4 { b.Fatal("expected 4 log, got", len(logs)) } } }
func TestFilters(t *testing.T) { dir, err := ioutil.TempDir("", "mipmap") if err != nil { t.Fatal(err) } defer os.RemoveAll(dir) var ( db, _ = ethdb.NewLDBDatabase(dir, 0, 0) 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() genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr, Balance: big.NewInt(1000000)}) chain, receipts := core.GenerateChain(nil, genesis, db, 1000, func(i int, gen *core.BlockGen) { var receipts types.Receipts switch i { case 1: receipt := types.NewReceipt(nil, new(big.Int)) receipt.Logs = vm.Logs{ &vm.Log{ Address: addr, Topics: []common.Hash{hash1}, }, } gen.AddUncheckedReceipt(receipt) receipts = types.Receipts{receipt} case 2: receipt := types.NewReceipt(nil, new(big.Int)) receipt.Logs = vm.Logs{ &vm.Log{ Address: addr, Topics: []common.Hash{hash2}, }, } gen.AddUncheckedReceipt(receipt) receipts = types.Receipts{receipt} case 998: receipt := types.NewReceipt(nil, new(big.Int)) receipt.Logs = vm.Logs{ &vm.Log{ Address: addr, Topics: []common.Hash{hash3}, }, } gen.AddUncheckedReceipt(receipt) receipts = types.Receipts{receipt} case 999: receipt := types.NewReceipt(nil, new(big.Int)) receipt.Logs = vm.Logs{ &vm.Log{ Address: addr, Topics: []common.Hash{hash4}, }, } gen.AddUncheckedReceipt(receipt) receipts = types.Receipts{receipt} } // store the receipts err := core.WriteReceipts(db, receipts) 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) }) for i, block := range chain { 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) } if err := core.WriteBlockReceipts(db, block.Hash(), receipts[i]); err != nil { 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)) } }