github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/tools/bootdat_qt/bootdat_qt.go (about) 1 // This tool can import blockchain database from satoshi client to gocoin 2 package main 3 4 import ( 5 "os" 6 "fmt" 7 //"time" 8 "encoding/hex" 9 "encoding/binary" 10 "github.com/piotrnar/gocoin/lib/btc" 11 "github.com/piotrnar/gocoin/lib/chain" 12 //"github.com/piotrnar/gocoin/lib/others/blockdb" 13 //"github.com/piotrnar/gocoin/lib/others/sys" 14 ) 15 16 const ( 17 GenesisBitcoin = "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000" 18 GenesisTestnet = "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000" 19 ) 20 21 22 var ( 23 bidx map[[32]byte] *chain.BlockTreeNode 24 cnt int 25 ) 26 27 28 func walk(ch *chain.Chain, hash, hdr []byte, height, blen, txs uint32) { 29 bh := btc.NewUint256(hash) 30 if _, ok := bidx[bh.Hash]; ok { 31 println("walk: ", bh.String(), "already in") 32 return 33 } 34 v := new(chain.BlockTreeNode) 35 v.BlockHash = bh 36 v.Height = height 37 v.BlockSize = blen 38 v.TxCount = txs 39 copy(v.BlockHeader[:], hdr) 40 bidx[bh.Hash] = v 41 cnt++ 42 } 43 44 45 func main() { 46 if len(os.Args)<2 { 47 fmt.Println("Specify a path to folder containig blockchain.dat and blockchain.new") 48 fmt.Println("Output bootstrap.dat file will be written in the current folder.") 49 return 50 } 51 52 blks := chain.NewBlockDB(os.Args[1]) 53 if blks==nil { 54 return 55 } 56 fmt.Println("Loading block index...") 57 bidx = make(map[[32]byte] *chain.BlockTreeNode, 300e3) 58 blks.LoadBlockIndex(nil, walk) 59 60 var tail, nd *chain.BlockTreeNode 61 var genesis_block_hash *btc.Uint256 62 for _, v := range bidx { 63 if v==tail { 64 // skip root block (should be only one) 65 continue 66 } 67 68 par_hash := btc.NewUint256(v.BlockHeader[4:36]) 69 par, ok := bidx[par_hash.Hash] 70 if !ok { 71 genesis_block_hash = par_hash 72 } else { 73 v.Parent = par 74 if tail==nil || v.Height > tail.Height { 75 tail = v 76 } 77 } 78 } 79 80 if genesis_block_hash == nil { 81 println("genesis_block_hash not found") 82 return 83 } 84 85 var magic []byte 86 87 gen_bin, _ := hex.DecodeString(GenesisBitcoin) 88 tmp := btc.NewSha2Hash(gen_bin[:80]) 89 if genesis_block_hash.Equal(tmp) { 90 println("Bitcoin genesis block") 91 magic = []byte{0xF9,0xBE,0xB4,0xD9} 92 } 93 94 95 if magic==nil { 96 gen_bin, _ := hex.DecodeString(GenesisTestnet) 97 tmp = btc.NewSha2Hash(gen_bin[:80]) 98 if genesis_block_hash.Equal(tmp) { 99 println("Testnet3 genesis block") 100 magic = []byte{0x0B,0x11,0x09,0x07} 101 } 102 } 103 104 if magic==nil { 105 println("Unknow genesis block", genesis_block_hash.String()) 106 println("Aborting since cannot figure out the magic bytes") 107 return 108 } 109 110 var total_data, curr_data int64 111 112 for nd=tail; nd.Parent!=nil; { 113 nd.Parent.Childs = []*chain.BlockTreeNode{nd} 114 total_data += int64(nd.BlockSize) 115 nd = nd.Parent 116 } 117 fmt.Println("Writting bootstrap.dat, height", tail.Height, " magic", hex.EncodeToString(magic)) 118 f, _ := os.Create("bootstrap.dat") 119 f.Write(magic) 120 binary.Write(f, binary.LittleEndian, uint32(len(gen_bin))) 121 f.Write(gen_bin) 122 for { 123 bl, _, _ := blks.BlockGet(nd.BlockHash) 124 f.Write(magic) 125 binary.Write(f, binary.LittleEndian, uint32(len(bl))) 126 f.Write(bl) 127 curr_data += int64(nd.BlockSize) 128 if (nd.Height&0xfff)==0 { 129 fmt.Printf("\r%.1f%%...", 100*float64(curr_data)/float64(total_data)) 130 } 131 if len(nd.Childs)==0 { 132 break 133 } 134 nd = nd.Childs[0] 135 } 136 fmt.Println("\rDone ") 137 }