github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/blockchain/reorganization_test.go (about) 1 // Copyright (c) 2013-2014 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package blockchain_test 7 8 import ( 9 "compress/bzip2" 10 "encoding/binary" 11 "io" 12 "os" 13 "path/filepath" 14 "strings" 15 "testing" 16 17 "github.com/BlockABC/godash/blockchain" 18 "github.com/BlockABC/godash/wire" 19 "github.com/BlockABC/godashutil" 20 ) 21 22 // TestReorganization loads a set of test blocks which force a chain 23 // reorganization to test the block chain handling code. 24 // The test blocks were originally from a post on the bitcoin talk forums: 25 // https://bitcointalk.org/index.php?topic=46370.msg577556#msg577556 26 func TestReorganization(t *testing.T) { 27 // Intentionally load the side chain blocks out of order to ensure 28 // orphans are handled properly along with chain reorganization. 29 testFiles := []string{ 30 "blk_0_to_4.dat.bz2", 31 "blk_4A.dat.bz2", 32 "blk_5A.dat.bz2", 33 "blk_3A.dat.bz2", 34 } 35 36 var blocks []*godashutil.Block 37 for _, file := range testFiles { 38 blockTmp, err := loadBlocks(file) 39 if err != nil { 40 t.Errorf("Error loading file: %v\n", err) 41 } 42 for _, block := range blockTmp { 43 blocks = append(blocks, block) 44 } 45 } 46 47 t.Logf("Number of blocks: %v\n", len(blocks)) 48 49 // Create a new database and chain instance to run tests against. 50 chain, teardownFunc, err := chainSetup("reorg") 51 if err != nil { 52 t.Errorf("Failed to setup chain instance: %v", err) 53 return 54 } 55 defer teardownFunc() 56 57 // Since we're not dealing with the real block chain, disable 58 // checkpoints and set the coinbase maturity to 1. 59 chain.DisableCheckpoints(true) 60 blockchain.TstSetCoinbaseMaturity(1) 61 62 expectedOrphans := map[int]struct{}{5: {}, 6: {}} 63 for i := 1; i < len(blocks); i++ { 64 isOrphan, err := chain.ProcessBlock(blocks[i], blockchain.BFNone) 65 if err != nil { 66 t.Errorf("ProcessBlock fail on block %v: %v\n", i, err) 67 return 68 } 69 if _, ok := expectedOrphans[i]; !ok && isOrphan { 70 t.Errorf("ProcessBlock incorrectly returned block %v "+ 71 "is an orphan\n", i) 72 } 73 } 74 75 return 76 } 77 78 // loadBlocks reads files containing bitcoin block data (gzipped but otherwise 79 // in the format bitcoind writes) from disk and returns them as an array of 80 // godashutil.Block. This is largely borrowed from the test code in btcdb. 81 func loadBlocks(filename string) (blocks []*godashutil.Block, err error) { 82 filename = filepath.Join("testdata/", filename) 83 84 var network = wire.MainNet 85 var dr io.Reader 86 var fi io.ReadCloser 87 88 fi, err = os.Open(filename) 89 if err != nil { 90 return 91 } 92 93 if strings.HasSuffix(filename, ".bz2") { 94 dr = bzip2.NewReader(fi) 95 } else { 96 dr = fi 97 } 98 defer fi.Close() 99 100 var block *godashutil.Block 101 102 err = nil 103 for height := int64(1); err == nil; height++ { 104 var rintbuf uint32 105 err = binary.Read(dr, binary.LittleEndian, &rintbuf) 106 if err == io.EOF { 107 // hit end of file at expected offset: no warning 108 height-- 109 err = nil 110 break 111 } 112 if err != nil { 113 break 114 } 115 if rintbuf != uint32(network) { 116 break 117 } 118 err = binary.Read(dr, binary.LittleEndian, &rintbuf) 119 blocklen := rintbuf 120 121 rbytes := make([]byte, blocklen) 122 123 // read block 124 dr.Read(rbytes) 125 126 block, err = godashutil.NewBlockFromBytes(rbytes) 127 if err != nil { 128 return 129 } 130 blocks = append(blocks, block) 131 } 132 133 return 134 }