Skip to content

Commit 24014ad

Browse files
committed
blockchain: add test for InitConsistentState
1 parent b3abff6 commit 24014ad

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

blockchain/utxocache_test.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"crypto/sha256"
88
"encoding/binary"
99
"fmt"
10+
"path/filepath"
1011
"reflect"
1112
"sync"
1213
"testing"
@@ -765,3 +766,117 @@ func TestFlushOnPrune(t *testing.T) {
765766
return nil
766767
})
767768
}
769+
770+
func TestInitConsistentState(t *testing.T) {
771+
// Boilerplate for creating a chain.
772+
dbName := "TestFlushOnPrune"
773+
chain, tearDown, err := ChainSetup(dbName, &chaincfg.MainNetParams)
774+
if err != nil {
775+
panic(fmt.Sprintf("error loading blockchain with database: %v", err))
776+
}
777+
defer tearDown()
778+
chain.utxoCache.maxTotalMemoryUsage = 10 * 1024 * 1024
779+
chain.utxoCache.cachedEntries.maxTotalMemoryUsage = chain.utxoCache.maxTotalMemoryUsage
780+
781+
// Read blocks from the file.
782+
blocks, err := loadBlocks("blk_0_to_14131.dat")
783+
if err != nil {
784+
t.Fatalf("failed to read block from file. %v", err)
785+
}
786+
787+
// Sync up to height 13,000. Flush the utxocache at height 11_000.
788+
cacheFlushHeight := 9000
789+
initialSyncHeight := 12_000
790+
for i, block := range blocks {
791+
if i == 0 {
792+
// Skip the genesis block.
793+
continue
794+
}
795+
796+
isMainChain, _, err := chain.ProcessBlock(block, BFNone)
797+
if err != nil {
798+
t.Fatal(err)
799+
}
800+
801+
if !isMainChain {
802+
t.Fatalf("expected block %s to be on the main chain", block.Hash())
803+
}
804+
805+
if i == cacheFlushHeight {
806+
err = chain.FlushUtxoCache(FlushRequired)
807+
if err != nil {
808+
t.Fatal(err)
809+
}
810+
}
811+
if i == initialSyncHeight {
812+
break
813+
}
814+
}
815+
816+
// Sanity check.
817+
if chain.BestSnapshot().Height != int32(initialSyncHeight) {
818+
t.Fatalf("expected the chain to sync up to height %d", initialSyncHeight)
819+
}
820+
821+
// Close the database without flushing the utxocache. This leaves the
822+
// chaintip at height 13,000 but the utxocache consistent state at 11,000.
823+
err = chain.db.Close()
824+
if err != nil {
825+
t.Fatal(err)
826+
}
827+
chain.db = nil
828+
829+
// Re-open the database and pass the re-opened db to internal structs.
830+
dbPath := filepath.Join(testDbRoot, dbName)
831+
ndb, err := database.Open(testDbType, dbPath, blockDataNet)
832+
if err != nil {
833+
t.Fatal(err)
834+
}
835+
chain.db = ndb
836+
chain.utxoCache.db = ndb
837+
chain.index.db = ndb
838+
839+
// Sanity check to see that the utxo cache was flushed before the
840+
// current chain tip.
841+
var statusBytes []byte
842+
ndb.View(func(dbTx database.Tx) error {
843+
statusBytes = dbFetchUtxoStateConsistency(dbTx)
844+
return nil
845+
})
846+
statusHash, err := chainhash.NewHash(statusBytes)
847+
if err != nil {
848+
t.Fatal(err)
849+
}
850+
if !statusHash.IsEqual(blocks[cacheFlushHeight].Hash()) {
851+
t.Fatalf("expected the utxocache to be flushed at "+
852+
"block hash %s but got %s",
853+
blocks[cacheFlushHeight].Hash(), statusHash)
854+
}
855+
856+
// Call InitConsistentState. This will make the utxocache catch back
857+
// up to the tip.
858+
err = chain.InitConsistentState(chain.bestChain.tip(), nil)
859+
if err != nil {
860+
t.Fatal(err)
861+
}
862+
863+
// Sync the reset of the blocks.
864+
for i, block := range blocks {
865+
if i <= initialSyncHeight {
866+
continue
867+
}
868+
isMainChain, _, err := chain.ProcessBlock(block, BFNone)
869+
if err != nil {
870+
t.Fatal(err)
871+
}
872+
873+
if !isMainChain {
874+
t.Fatalf("expected block %s to be on the main chain", block.Hash())
875+
}
876+
}
877+
878+
if chain.BestSnapshot().Height != blocks[len(blocks)-1].Height() {
879+
t.Fatalf("expected the chain to sync up to height %d",
880+
blocks[len(blocks)-1].Height())
881+
}
882+
}

0 commit comments

Comments
 (0)