Example #1
0
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
}
Example #2
0
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)
	}

}
Example #3
0
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)
	}

}
Example #4
0
// 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
}
Example #5
0
// 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
}
Example #6
0
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
}
Example #7
0
// 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
}
Example #8
0
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)
	}
}
Example #9
0
// 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
}
Example #10
0
// 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
	}
}
Example #11
0
// 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
}
Example #12
0
// 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
	}
}
Example #13
0
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)
	}
}
Example #14
0
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)
	}
}
Example #15
0
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)
	}

}
Example #16
0
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)
	}
}
Example #17
0
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
	}
}
Example #18
0
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)
	}

}
Example #19
0
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
	}
}