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  }