func btcdbSetup(dataDir, dbType string) (log btclog.Logger, db btcdb.Db, cleanup func()) { // Setup logging backendLogger := btclog.NewDefaultBackendLogger() log = btclog.NewSubsystemLogger(backendLogger, "") btcdb.UseLogger(log) // Setup database access blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + dbType if dbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(dataDir, "mainnet", dbName) log.Infof("loading db %v", dbType) db, err := btcdb.OpenDB(dbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } log.Infof("db load complete") cleanup = func() { db.Close() backendLogger.Flush() } return }
func main() { var err error var dbType string var datadir string var shastring string flag.StringVar(&dbType, "dbtype", "", "Database backend to use for the Block Chain") flag.StringVar(&datadir, "datadir", "", "Directory to store data") flag.StringVar(&shastring, "s", "", "Block sha to process") flag.Parse() log, err = seelog.LoggerFromWriterWithMinLevel(os.Stdout, seelog.TraceLvl) if err != nil { fmt.Fprintf(os.Stderr, "failed to create logger: %v", err) return } defer log.Flush() btcdb.UseLogger(log) if len(dbType) == 0 { dbType = "sqlite" } if len(datadir) == 0 { datadir = filepath.Join(btcdHomeDir(), "data") } datadir = filepath.Join(datadir, "mainnet") blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + dbType if dbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(datadir, dbName) log.Infof("loading db") db, err := btcdb.OpenDB(dbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") _, height, err := db.NewestSha() log.Infof("loaded block height %v", height) sha, err := getSha(db, shastring) if err != nil { log.Infof("Invalid block %v", shastring) return } err = db.DropAfterBlockBySha(&sha) if err != nil { log.Warnf("failed %v", err) } }
func main() { cfg := config{ DbType: "leveldb", DataDir: defaultDataDir, } parser := flags.NewParser(&cfg, flags.Default) _, err := parser.Parse() if err != nil { if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { parser.WriteHelp(os.Stderr) } return } backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") btcdb.UseLogger(log) var testnet string if cfg.TestNet3 { testnet = "testnet" } else { testnet = "mainnet" } cfg.DataDir = filepath.Join(cfg.DataDir, testnet) blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("loading db") db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") _, height, err := db.NewestSha() log.Infof("loaded block height %v", height) sha, err := getSha(db, cfg.ShaString) if err != nil { log.Infof("Invalid block hash %v", cfg.ShaString) return } err = db.DropAfterBlockBySha(&sha) if err != nil { log.Warnf("failed %v", err) } }
// openDB is used to open an existing database based on the database type and // name. func openDB(dbType, dbName string) (btcdb.Db, error) { // Handle memdb specially since it has no files on disk. if dbType == "memdb" { db, err := btcdb.OpenDB(dbType) if err != nil { return nil, fmt.Errorf("error opening db: %v", err) } return db, nil } dbPath := filepath.Join(testDbRoot, dbName) db, err := btcdb.OpenDB(dbType, dbPath) if err != nil { return nil, fmt.Errorf("error opening db: %v", err) } return db, nil }
// loadBlockDB opens the block database and returns a handle to it. func loadBlockDB() (btcdb.Db, error) { // The database name is based on the database type. dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) // The regression test is special in that it needs a clean database for // each run, so remove it now if it already exists. removeRegressionDB(dbPath) log.Infof("[BMGR] Loading block database from '%s'", dbPath) db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { // Return the error if it's not because the database doesn't // exist. if err != btcdb.DbDoesNotExist { return nil, err } // Create the db if it does not exist. err = os.MkdirAll(cfg.DataDir, 0700) if err != nil { return nil, err } db, err = btcdb.CreateDB(cfg.DbType, dbPath) if err != nil { return nil, err } } // Get the latest block height from the database. _, height, err := db.NewestSha() if err != nil { db.Close() return nil, err } // Insert the appropriate genesis block for the bitcoin network being // connected to if needed. if height == -1 { genesis := btcutil.NewBlock(activeNetParams.genesisBlock) _, err := db.InsertBlock(genesis) if err != nil { db.Close() return nil, err } log.Infof("[BMGR] Inserted genesis block %v", activeNetParams.genesisHash) height = 0 } log.Infof("[BMGR] Block database loaded with block height %d", height) return db, nil }
func btcdbSetup(dataDir, dbType string) (db btcdb.Db, err error) { // Setup database access blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + dbType if dbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(dataDir, "mainnet", dbName) db, err = btcdb.OpenDB(dbType, dbPath) return }
// loadBlockDB opens the block database and returns a handle to it. func loadBlockDB() (btcdb.Db, error) { // The database name is based on the database type. dbType := cfg.DbType dbName := blockDbNamePrefix + "_" + dbType if dbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) fmt.Printf("Loading block database from '%s'\n", dbPath) db, err := btcdb.OpenDB(dbType, dbPath) if err != nil { return nil, err } return db, nil }
func TestEmptyDB(t *testing.T) { dbname := "tstdbempty" dbnamever := dbname + ".ver" _ = os.RemoveAll(dbname) _ = os.RemoveAll(dbnamever) db, err := btcdb.CreateDB("leveldb", dbname) if err != nil { t.Errorf("Failed to open test database %v", err) return } defer os.RemoveAll(dbname) defer os.RemoveAll(dbnamever) sha, height, err := db.NewestSha() if !sha.IsEqual(&btcwire.ShaHash{}) { t.Errorf("sha not zero hash") } if height != -1 { t.Errorf("height not -1 %v", height) } // This is a reopen test if err := db.Close(); err != nil { t.Errorf("Close: unexpected error: %v", err) } db, err = btcdb.OpenDB("leveldb", dbname) if err != nil { t.Errorf("Failed to open test database %v", err) return } defer func() { if err := db.Close(); err != nil { t.Errorf("Close: unexpected error: %v", err) } }() sha, height, err = db.NewestSha() if !sha.IsEqual(&btcwire.ShaHash{}) { t.Errorf("sha not zero hash") } if height != -1 { t.Errorf("height not -1 %v", height) } }
// setupBlockDB loads (or creates when needed) the block database taking into // account the selected database backend. It also contains additional logic // such warning the user if there are multiple databases which consume space on // the file system and ensuring the regression test database is clean when in // regression test mode. func setupBlockDB() (btcdb.Db, error) { // The memdb backend does not have a file path associated with it, so // handle it uniquely. We also don't want to worry about the multiple // database type warnings when running with the memory database. if cfg.DbType == "memdb" { btcdLog.Infof("Creating block database in memory.") db, err := btcdb.CreateDB(cfg.DbType) if err != nil { return nil, err } return db, nil } warnMultipeDBs() // The database name is based on the database type. dbPath := blockDbPath(cfg.DbType) // The regression test is special in that it needs a clean database for // each run, so remove it now if it already exists. removeRegressionDB(dbPath) btcdLog.Infof("Loading block database from '%s'", dbPath) db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { // Return the error if it's not because the database // doesn't exist. if err != btcdb.DbDoesNotExist { return nil, err } // Create the db if it does not exist. err = os.MkdirAll(cfg.DataDir, 0700) if err != nil { return nil, err } db, err = btcdb.CreateDB(cfg.DbType, dbPath) if err != nil { return nil, err } } return db, nil }
// TestCreateOpenUnsupported ensures that attempting to create or open an // unsupported database type is handled properly. func TestCreateOpenUnsupported(t *testing.T) { // Ensure creating a database with an unsupported type fails with the // expected error. dbType := "unsupported" _, err := btcdb.CreateDB(dbType, "unsupportedcreatetest") if err != btcdb.ErrDbUnknownType { t.Errorf("TestCreateOpenUnsupported: expected error not "+ "received - got: %v, want %v", err, btcdb.ErrDbUnknownType) return } // Ensure opening a database with the new type fails with the expected // error. _, err = btcdb.OpenDB(dbType, "unsupportedopentest") if err != btcdb.ErrDbUnknownType { t.Errorf("TestCreateOpenUnsupported: expected error not "+ "received - got: %v, want %v", err, btcdb.ErrDbUnknownType) return } }
// loadBlockDB opens the block database and returns a handle to it. func loadBlockDB() (btcdb.Db, error) { // The database name is based on the database type. dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("Loading block database from '%s'", dbPath) db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { // Return the error if it's not because the database doesn't // exist. if err != btcdb.ErrDbDoesNotExist { return nil, err } // Create the db if it does not exist. err = os.MkdirAll(cfg.DataDir, 0700) if err != nil { return nil, err } db, err = btcdb.CreateDB(cfg.DbType, dbPath) if err != nil { return nil, err } } // Get the latest block height from the database. _, height, err := db.NewestSha() if err != nil { db.Close() return nil, err } log.Infof("Block database loaded with block height %d", height) return db, nil }
// TestCreateOpenFail ensures that errors which occur while opening or closing // a database are handled properly. func TestCreateOpenFail(t *testing.T) { // bogusCreateDB is a function which acts as a bogus create and open // driver function that intentionally returns a failure which can be // detected. dbType := "createopenfail" openError := fmt.Errorf("failed to create or open database for "+ "database type [%v]", dbType) bogusCreateDB := func(args ...interface{}) (btcdb.Db, error) { return nil, openError } // Create and add driver that intentionally fails when created or opened // to ensure errors on database open and create are handled properly. driver := btcdb.DriverDB{ DbType: dbType, CreateDB: bogusCreateDB, OpenDB: bogusCreateDB, } btcdb.AddDBDriver(driver) // Ensure creating a database with the new type fails with the expected // error. _, err := btcdb.CreateDB(dbType, "createfailtest") if err != openError { t.Errorf("TestCreateOpenFail: expected error not received - "+ "got: %v, want %v", err, openError) return } // Ensure opening a database with the new type fails with the expected // error. _, err = btcdb.OpenDB(dbType, "openfailtest") if err != openError { t.Errorf("TestCreateOpenFail: expected error not received - "+ "got: %v, want %v", err, openError) return } }
func main() { end := int64(-1) cfg := config{ DbType: "leveldb", DataDir: defaultDataDir, } parser := flags.NewParser(&cfg, flags.Default) _, err := parser.Parse() if err != nil { if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { parser.WriteHelp(os.Stderr) } return } backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") btcdb.UseLogger(log) var testnet string if cfg.TestNet3 { testnet = "testnet" } else { testnet = "mainnet" } cfg.DataDir = filepath.Join(cfg.DataDir, testnet) blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("loading db %v", cfg.DbType) db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") height, err := getHeight(db, cfg.ShaString) if err != nil { log.Infof("Invalid block %v", cfg.ShaString) return } if cfg.EShaString != "" { end, err = getHeight(db, cfg.EShaString) if err != nil { log.Infof("Invalid end block %v", cfg.EShaString) return } } else { end = height + 1 } log.Infof("height %v end %v", height, end) var fo io.WriteCloser if cfg.OutFile != "" { fo, err = os.Create(cfg.OutFile) if err != nil { log.Warnf("failed to open file %v, err %v", cfg.OutFile, err) } defer func() { if err := fo.Close(); err != nil { log.Warn("failed to close file %v %v", cfg.OutFile, err) } }() } for ; height < end; height++ { if cfg.Progress && height%int64(1) == 0 { log.Infof("Processing block %v", height) } err = DumpBlock(db, height, fo, cfg.RawBlock, cfg.FmtBlock, cfg.ShowTx) if err != nil { break } } if cfg.Progress { height-- log.Infof("Processing block %v", height) } }
func main() { end := int64(-1) cfg := config{ DbType: "leveldb", DataDir: defaultDataDir, } parser := flags.NewParser(&cfg, flags.Default) _, err := parser.Parse() if err != nil { if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { parser.WriteHelp(os.Stderr) } return } backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") btcdb.UseLogger(log) // Multiple networks can't be selected simultaneously. funcName := "main" numNets := 0 // Count number of network flags passed; assign active network params // while we're at it if cfg.TestNet3 { numNets++ activeNetParams = &btcnet.TestNet3Params } if cfg.RegressionTest { numNets++ activeNetParams = &btcnet.RegressionNetParams } if cfg.SimNet { numNets++ activeNetParams = &btcnet.SimNetParams } if numNets > 1 { str := "%s: The testnet, regtest, and simnet params can't be " + "used together -- choose one of the three" err := fmt.Errorf(str, funcName) fmt.Fprintln(os.Stderr, err) parser.WriteHelp(os.Stderr) return } cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams)) blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("loading db %v", cfg.DbType) db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") height, err := getHeight(db, cfg.ShaString) if err != nil { log.Infof("Invalid block %v", cfg.ShaString) return } if cfg.EShaString != "" { end, err = getHeight(db, cfg.EShaString) if err != nil { log.Infof("Invalid end block %v", cfg.EShaString) return } } else { end = height + 1 } log.Infof("height %v end %v", height, end) var fo io.WriteCloser if cfg.OutFile != "" { fo, err = os.Create(cfg.OutFile) if err != nil { log.Warnf("failed to open file %v, err %v", cfg.OutFile, err) } defer func() { if err := fo.Close(); err != nil { log.Warn("failed to close file %v %v", cfg.OutFile, err) } }() } for ; height < end; height++ { if cfg.Progress && height%int64(1) == 0 { log.Infof("Processing block %v", height) } err = DumpBlock(db, height, fo, cfg.RawBlock, cfg.FmtBlock, cfg.ShowTx) if err != nil { break } } if cfg.Progress { height-- log.Infof("Processing block %v", height) } }
func main() { cfg := config{ DbType: "leveldb", DataDir: filepath.Join(btcdHomeDir(), "data"), } parser := flags.NewParser(&cfg, flags.Default) _, err := parser.Parse() if err != nil { if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { parser.WriteHelp(os.Stderr) } return } log, err = seelog.LoggerFromWriterWithMinLevel(os.Stdout, seelog.TraceLvl) if err != nil { fmt.Fprintf(os.Stderr, "failed to create logger: %v", err) return } defer log.Flush() btcdb.UseLogger(log) var testnet string if cfg.TestNet3 { testnet = "testnet" } else { testnet = "mainnet" } cfg.DataDir = filepath.Join(cfg.DataDir, testnet) blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("loading db") db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") _, height, err := db.NewestSha() log.Infof("loaded block height %v", height) sha, err := getSha(db, cfg.ShaString) if err != nil { log.Infof("Invalid block hash %v", cfg.ShaString) return } err = db.DropAfterBlockBySha(&sha) if err != nil { log.Warnf("failed %v", err) } }
func main() { var err error var dbType string var datadir string var shastring, eshastring, outfile string var rflag, fflag, tflag bool var progress int end := int64(-1) flag.StringVar(&dbType, "dbtype", "", "Database backend to use for the Block Chain") flag.StringVar(&datadir, "datadir", ".", "Directory to store data") flag.StringVar(&shastring, "s", "", "Block sha to process") flag.StringVar(&eshastring, "e", "", "Block sha to process") flag.StringVar(&outfile, "o", "", "outfile") flag.BoolVar(&rflag, "r", false, "raw block") flag.BoolVar(&fflag, "f", false, "fmt block") flag.BoolVar(&tflag, "t", false, "show transactions") flag.IntVar(&progress, "p", 0, "show progress") flag.Parse() log, err = seelog.LoggerFromWriterWithMinLevel(os.Stdout, seelog.InfoLvl) if err != nil { fmt.Fprintf(os.Stderr, "failed to create logger: %v", err) return } defer log.Flush() btcdb.UseLogger(log) if len(dbType) == 0 { dbType = "sqlite" } if len(datadir) == 0 { datadir = filepath.Join(btcdHomeDir(), "data") } datadir = filepath.Join(datadir, "mainnet") blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + dbType if dbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(datadir, dbName) log.Infof("loading db %v", dbType) db, err := btcdb.OpenDB(dbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") height, err := getHeight(db, shastring) if err != nil { log.Infof("Invalid block %v", shastring) return } if eshastring != "" { end, err = getHeight(db, eshastring) if err != nil { log.Infof("Invalid end block %v", eshastring) return } } else { end = height + 1 } log.Infof("height %v end %v", height, end) var fo io.WriteCloser if outfile != "" { fo, err = os.Create(outfile) if err != nil { log.Warnf("failed to open file %v, err %v", outfile, err) } defer func() { if err := fo.Close(); err != nil { log.Warn("failed to close file %v %v", outfile, err) } }() } for ; height < end; height++ { if progress != 0 && height%int64(progress) == 0 { log.Infof("Processing block %v", height) } err = DumpBlock(db, height, fo, rflag, fflag, tflag) if err != nil { break } } if progress != 0 { height-- log.Infof("Processing block %v", height) } }
func testBackout(t *testing.T) { // simplified basic operation is: // 1) fetch block from remote server // 2) look up all txin (except coinbase in db) // 3) insert block // Ignore db remove errors since it means we didn't have an old one. dbname := fmt.Sprintf("tstdbop2") dbnamever := dbname + ".ver" _ = os.RemoveAll(dbname) _ = os.RemoveAll(dbnamever) db, err := btcdb.CreateDB("leveldb", dbname) if err != nil { t.Errorf("Failed to open test database %v", err) return } defer os.RemoveAll(dbname) defer os.RemoveAll(dbnamever) defer db.Close() testdatafile := filepath.Join("..", "testdata", "blocks1-256.bz2") blocks, err := loadBlocks(t, testdatafile) if len(blocks) < 120 { t.Errorf("test data too small") return } err = nil for height := int64(0); height < int64(len(blocks)); height++ { if height == 100 { t.Logf("Syncing at block height 100") db.Sync() } if height == 120 { t.Logf("Simulating unexpected application quit") // Simulate unexpected application quit db.RollbackClose() break } block := blocks[height] newheight, err := db.InsertBlock(block) if err != nil { t.Errorf("failed to insert block %v err %v", height, err) return } if newheight != height { t.Errorf("height mismatch expect %v returned %v", height, newheight) return } } // db was closed at height 120, so no cleanup is possible. // reopen db db, err = btcdb.OpenDB("leveldb", dbname) if err != nil { t.Errorf("Failed to open test database %v", err) return } defer func() { if err := db.Close(); err != nil { t.Errorf("Close: unexpected error: %v", err) } }() sha, err := blocks[99].Sha() if err != nil { t.Errorf("failed to get block 99 sha err %v", err) return } if _, err := db.ExistsSha(sha); err != nil { t.Errorf("ExistsSha: unexpected error: %v") } _, err = db.FetchBlockBySha(sha) if err != nil { t.Errorf("failed to load block 99 from db %v", err) return } sha, err = blocks[119].Sha() if err != nil { t.Errorf("failed to get block 110 sha err %v", err) return } if _, err := db.ExistsSha(sha); err != nil { t.Errorf("ExistsSha: unexpected error: %v") } _, err = db.FetchBlockBySha(sha) if err != nil { t.Errorf("loaded block 119 from db") return } block := blocks[119] mblock := block.MsgBlock() txsha, err := mblock.Transactions[0].TxSha() exists, err := db.ExistsTxSha(&txsha) if err != nil { t.Errorf("ExistsTxSha: unexpected error %v ", err) } if !exists { t.Errorf("tx %v not located db\n", txsha) } _, err = db.FetchTxBySha(&txsha) if err != nil { t.Errorf("tx %v not located db\n", txsha) return } }
func main() { cfg := config{ DbType: "leveldb", DataDir: defaultDataDir, } parser := flags.NewParser(&cfg, flags.Default) _, err := parser.Parse() if err != nil { if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { parser.WriteHelp(os.Stderr) } return } backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") btcdb.UseLogger(log) // Multiple networks can't be selected simultaneously. funcName := "main" numNets := 0 // Count number of network flags passed; assign active network params // while we're at it if cfg.TestNet3 { numNets++ activeNetParams = &btcnet.TestNet3Params } if cfg.RegressionTest { numNets++ activeNetParams = &btcnet.RegressionNetParams } if cfg.SimNet { numNets++ activeNetParams = &btcnet.SimNetParams } if numNets > 1 { str := "%s: The testnet, regtest, and simnet params can't be " + "used together -- choose one of the three" err := fmt.Errorf(str, funcName) fmt.Fprintln(os.Stderr, err) parser.WriteHelp(os.Stderr) return } cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams)) blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("loading db") db, err := btcdb.OpenDB(cfg.DbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") _, height, err := db.NewestSha() log.Infof("loaded block height %v", height) sha, err := getSha(db, cfg.ShaString) if err != nil { log.Infof("Invalid block hash %v", cfg.ShaString) return } err = db.DropAfterBlockBySha(&sha) if err != nil { log.Warnf("failed %v", err) } }
func testBackout(t *testing.T, mode int) { // simplified basic operation is: // 1) fetch block from remote server // 2) look up all txin (except coinbase in db) // 3) insert block // Ignore db remove errors since it means we didn't have an old one. dbname := "tstdbop2" _ = os.Remove(dbname) db, err := btcdb.CreateDB("sqlite", dbname) if err != nil { t.Errorf("Failed to open test database %v", err) return } defer os.Remove(dbname) defer db.Close() switch mode { case dbTmDefault: // default // no setup case dbTmNormal: // explicit normal db.SetDBInsertMode(btcdb.InsertNormal) case dbTmFast: // fast mode db.SetDBInsertMode(btcdb.InsertFast) if sqldb, ok := db.(*sqlite3.SqliteDb); ok { sqldb.TempTblMax = 100 } else { t.Errorf("not right type") } } // Since we are dealing with small dataset, reduce cache size sqlite3.SetBlockCacheSize(db, 2) sqlite3.SetTxCacheSize(db, 3) testdatafile := filepath.Join("testdata", "blocks1-256.bz2") blocks, err := loadBlocks(t, testdatafile) if len(blocks) < 120 { t.Errorf("test data too small") return } err = nil for height := int64(1); height < int64(len(blocks)); height++ { if height == 100 { t.Logf("Syncing at block height 100") db.Sync() } if height == 120 { t.Logf("Simulating unexpected application quit") // Simulate unexpected application quit db.RollbackClose() break } block := blocks[height] newheight, err := db.InsertBlock(block) if err != nil { t.Errorf("failed to insert block %v err %v", height, err) break } if newheight != height { t.Errorf("height mismatch expect %v returned %v", height, newheight) break } } // db was closed at height 120, so no cleanup is possible. // reopen db db, err = btcdb.OpenDB("sqlite", dbname) if err != nil { t.Errorf("Failed to open test database %v", err) return } defer db.Close() sha, err := blocks[99].Sha() if err != nil { t.Errorf("failed to get block 99 sha err %v", err) return } _ = db.ExistsSha(sha) _, err = db.FetchBlockBySha(sha) if err != nil { t.Errorf("failed to load block 99 from db", err) } sha, err = blocks[110].Sha() if err != nil { t.Errorf("failed to get block 110 sha err %v", err) return } _ = db.ExistsSha(sha) _, err = db.FetchBlockBySha(sha) if err == nil { t.Errorf("loaded block 110 from db, failure expected") return } block := blocks[110] mblock := block.MsgBlock() txsha, err := mblock.Transactions[0].TxSha(block.ProtocolVersion()) _, _, _, err = db.FetchTxBySha(&txsha) _, err = db.FetchTxUsedBySha(&txsha) block = blocks[99] mblock = block.MsgBlock() txsha, err = mblock.Transactions[0].TxSha(block.ProtocolVersion()) oldused, err := db.FetchTxUsedBySha(&txsha) err = db.InsertTx(&txsha, 99, 1024, 1048, oldused) if err == nil { t.Errorf("dup insert of tx succeeded") return } }