0280fa0264
This commit converts all block height references to int32 instead of int64. The current target block production rate is 10 mins per block which means it will take roughly 40,800 years to reach the maximum height an int32 affords. Even if the target rate were lowered to one block per minute, it would still take roughly another 4,080 years to reach the maximum. In the mean time, there is no reason to use a larger type which results in higher memory and disk space usage. However, for now, in order to avoid having to reserialize a bunch of database information, the heights are still serialized to the database as 8-byte uint64s. This is being mainly being done in preparation for further upcoming infrastructure changes which will use the smaller and more efficient 4-byte serialization in the database as well.
169 lines
4.1 KiB
Go
169 lines
4.1 KiB
Go
// Copyright (c) 2015 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package database_test
|
|
|
|
import (
|
|
"compress/bzip2"
|
|
"encoding/binary"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/btcsuite/btcutil"
|
|
)
|
|
|
|
// testReorganization performs reorganization tests for the passed DB type.
|
|
// Much of the setup is copied from the blockchain package, but the test looks
|
|
// to see if each TX in each block in the best chain can be fetched using
|
|
// FetchTxBySha. If not, then there's a bug.
|
|
func testReorganization(t *testing.T, dbType string) {
|
|
db, teardown, err := createDB(dbType, "reorganization", true)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test database (%s) %v", dbType, err)
|
|
}
|
|
defer teardown()
|
|
|
|
blocks, err := loadReorgBlocks("reorgblocks.bz2")
|
|
if err != nil {
|
|
t.Fatalf("Error loading file: %v", err)
|
|
}
|
|
|
|
for i := int32(0); i <= 2; i++ {
|
|
_, err = db.InsertBlock(blocks[i])
|
|
if err != nil {
|
|
t.Fatalf("Error inserting block %d (%v): %v", i,
|
|
blocks[i].Sha(), err)
|
|
}
|
|
var txIDs []string
|
|
for _, tx := range blocks[i].Transactions() {
|
|
txIDs = append(txIDs, tx.Sha().String())
|
|
}
|
|
}
|
|
|
|
for i := int32(1); i >= 0; i-- {
|
|
blkHash := blocks[i].Sha()
|
|
err = db.DropAfterBlockBySha(blkHash)
|
|
if err != nil {
|
|
t.Fatalf("Error removing block %d for reorganization: %v", i, err)
|
|
}
|
|
// Exercise NewestSha() to make sure DropAfterBlockBySha() updates the
|
|
// info correctly
|
|
maxHash, blkHeight, err := db.NewestSha()
|
|
if err != nil {
|
|
t.Fatalf("Error getting newest block info")
|
|
}
|
|
if !maxHash.IsEqual(blkHash) || blkHeight != i {
|
|
t.Fatalf("NewestSha returned %v (%v), expected %v (%v)", blkHeight,
|
|
maxHash, i, blkHash)
|
|
}
|
|
}
|
|
|
|
for i := int32(3); i < int32(len(blocks)); i++ {
|
|
blkHash := blocks[i].Sha()
|
|
if err != nil {
|
|
t.Fatalf("Error getting SHA for block %dA: %v", i-2, err)
|
|
}
|
|
_, err = db.InsertBlock(blocks[i])
|
|
if err != nil {
|
|
t.Fatalf("Error inserting block %dA (%v): %v", i-2, blkHash, err)
|
|
}
|
|
}
|
|
|
|
_, maxHeight, err := db.NewestSha()
|
|
if err != nil {
|
|
t.Fatalf("Error getting newest block info")
|
|
}
|
|
|
|
for i := int32(0); i <= maxHeight; i++ {
|
|
blkHash, err := db.FetchBlockShaByHeight(i)
|
|
if err != nil {
|
|
t.Fatalf("Error fetching SHA for block %d: %v", i, err)
|
|
}
|
|
block, err := db.FetchBlockBySha(blkHash)
|
|
if err != nil {
|
|
t.Fatalf("Error fetching block %d (%v): %v", i, blkHash, err)
|
|
}
|
|
for _, tx := range block.Transactions() {
|
|
_, err := db.FetchTxBySha(tx.Sha())
|
|
if err != nil {
|
|
t.Fatalf("Error fetching transaction %v: %v", tx.Sha(), err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// loadReorgBlocks reads files containing bitcoin block data (bzipped but
|
|
// otherwise in the format bitcoind writes) from disk and returns them as an
|
|
// array of btcutil.Block. This is copied from the blockchain package, which
|
|
// itself largely borrowed it from the test code in this package.
|
|
func loadReorgBlocks(filename string) ([]*btcutil.Block, error) {
|
|
filename = filepath.Join("testdata/", filename)
|
|
|
|
var blocks []*btcutil.Block
|
|
var err error
|
|
|
|
var network = wire.SimNet
|
|
var dr io.Reader
|
|
var fi io.ReadCloser
|
|
|
|
fi, err = os.Open(filename)
|
|
if err != nil {
|
|
return blocks, err
|
|
}
|
|
|
|
if strings.HasSuffix(filename, ".bz2") {
|
|
dr = bzip2.NewReader(fi)
|
|
} else {
|
|
dr = fi
|
|
}
|
|
defer fi.Close()
|
|
|
|
var block *btcutil.Block
|
|
|
|
err = nil
|
|
for height := int32(1); err == nil; height++ {
|
|
var rintbuf uint32
|
|
err = binary.Read(dr, binary.LittleEndian, &rintbuf)
|
|
if err == io.EOF {
|
|
// hit end of file at expected offset: no warning
|
|
height--
|
|
err = nil
|
|
break
|
|
}
|
|
if err != nil {
|
|
break
|
|
}
|
|
if rintbuf != uint32(network) {
|
|
break
|
|
}
|
|
err = binary.Read(dr, binary.LittleEndian, &rintbuf)
|
|
if err != nil {
|
|
return blocks, err
|
|
}
|
|
blocklen := rintbuf
|
|
|
|
rbytes := make([]byte, blocklen)
|
|
|
|
// read block
|
|
numbytes, err := dr.Read(rbytes)
|
|
if err != nil {
|
|
return blocks, err
|
|
}
|
|
if uint32(numbytes) != blocklen {
|
|
return blocks, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
block, err = btcutil.NewBlockFromBytes(rbytes)
|
|
if err != nil {
|
|
return blocks, err
|
|
}
|
|
blocks = append(blocks, block)
|
|
}
|
|
|
|
return blocks, nil
|
|
}
|