github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/tools/importblocks/importblocks.go (about)

     1  // This tool can import blockchain database from satoshi client to gocoin
     2  package main
     3  
     4  import (
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/piotrnar/gocoin/lib/btc"
    10  	"github.com/piotrnar/gocoin/lib/chain"
    11  	"github.com/piotrnar/gocoin/lib/others/blockdb"
    12  	"github.com/piotrnar/gocoin/lib/others/sys"
    13  )
    14  
    15  const Trust = true // Set this to false if you want to re-check all scripts
    16  
    17  var (
    18  	Magic               [4]byte
    19  	GocoinHomeDir       string
    20  	BtcRootDir          string
    21  	GenesisBlock        *btc.Uint256
    22  	prev_EcdsaVerifyCnt uint64
    23  )
    24  
    25  func stat(totnsec, pernsec int64, totbytes, perbytes uint64, height uint32) {
    26  	totmbs := float64(totbytes) / (1024 * 1024)
    27  	perkbs := float64(perbytes) / (1024)
    28  	var x string
    29  	cn := btc.EcdsaVerifyCnt() - prev_EcdsaVerifyCnt
    30  	if cn > 0 {
    31  		x = fmt.Sprintf("|  %d -> %d us/ecdsa", cn, uint64(pernsec)/cn/1e3)
    32  		prev_EcdsaVerifyCnt += cn
    33  	}
    34  	fmt.Printf("%.1fMB of data processed. We are at height %d. Processing speed %.3fMB/sec, recent: %.1fKB/s %s\n",
    35  		totmbs, height, totmbs/(float64(totnsec)/1e9), perkbs/(float64(pernsec)/1e9), x)
    36  }
    37  
    38  func import_blockchain(dir string) {
    39  	BlockDatabase := blockdb.NewBlockDB(dir, Magic)
    40  	chain := chain.NewChainExt(GocoinHomeDir, GenesisBlock, false, nil, nil)
    41  
    42  	var bl *btc.Block
    43  	var er error
    44  	var dat []byte
    45  	var totbytes, perbytes uint64
    46  
    47  	fmt.Println("Be patient while importing Satoshi's database... ")
    48  	start := time.Now().UnixNano()
    49  	prv := start
    50  	for {
    51  		now := time.Now().UnixNano()
    52  		if now-prv >= 10e9 {
    53  			stat(now-start, now-prv, totbytes, perbytes, chain.LastBlock().Height)
    54  			prv = now // show progress each 10 seconds
    55  			perbytes = 0
    56  		}
    57  
    58  		dat, er = BlockDatabase.FetchNextBlock()
    59  		if dat == nil || er != nil {
    60  			println("END of DB file")
    61  			break
    62  		}
    63  
    64  		bl, er = btc.NewBlock(dat[:])
    65  		if er != nil {
    66  			println("Block inconsistent:", er.Error())
    67  			break
    68  		}
    69  
    70  		bl.Trusted.Store(Trust)
    71  
    72  		_, _, er = chain.CheckBlock(bl)
    73  
    74  		if er != nil {
    75  			if er.Error() != "Genesis" {
    76  				println("CheckBlock failed:", er.Error())
    77  				os.Exit(1) // Such a thing should not happen, so let's better abort here.
    78  			}
    79  			continue
    80  		}
    81  
    82  		er = chain.AcceptBlock(bl)
    83  		if er != nil {
    84  			println("AcceptBlock failed:", er.Error())
    85  			os.Exit(1) // Such a thing should not happen, so let's better abort here.
    86  		}
    87  
    88  		totbytes += uint64(len(bl.Raw))
    89  		perbytes += uint64(len(bl.Raw))
    90  	}
    91  
    92  	stop := time.Now().UnixNano()
    93  	stat(stop-start, stop-prv, totbytes, perbytes, chain.LastBlock().Height)
    94  
    95  	fmt.Println("Satoshi's database import finished in", (stop-start)/1e9, "seconds")
    96  
    97  	fmt.Println("Now saving the new database...")
    98  	chain.Close()
    99  	fmt.Println("Database saved. No more imports should be needed.")
   100  }
   101  
   102  func RemoveLastSlash(p string) string {
   103  	if len(p) > 0 && os.IsPathSeparator(p[len(p)-1]) {
   104  		return p[:len(p)-1]
   105  	}
   106  	return p
   107  }
   108  
   109  func exists(fn string) bool {
   110  	_, e := os.Lstat(fn)
   111  	return e == nil
   112  }
   113  
   114  func main() {
   115  	if len(os.Args) < 2 {
   116  		fmt.Println("Specify at least one parameter - a path to the blk0000?.dat files.")
   117  		fmt.Println("By default it should be:", sys.BitcoinHome()+"blocks")
   118  		fmt.Println()
   119  		fmt.Println("If you specify a second parameter, that's where output data will be stored.")
   120  		fmt.Println("Otherwise the output data will go to Gocoin's default data folder.")
   121  		return
   122  	}
   123  
   124  	BtcRootDir = RemoveLastSlash(os.Args[1])
   125  	fn := BtcRootDir + string(os.PathSeparator) + "blk00000.dat"
   126  	fmt.Println("Looking for file", fn, "...")
   127  	f, e := os.Open(fn)
   128  	if e != nil {
   129  		println(e.Error())
   130  		os.Exit(1)
   131  	}
   132  	_, e = f.Read(Magic[:])
   133  	f.Close()
   134  	if e != nil {
   135  		println(e.Error())
   136  		os.Exit(1)
   137  	}
   138  
   139  	if len(os.Args) > 2 {
   140  		GocoinHomeDir = RemoveLastSlash(os.Args[2]) + string(os.PathSeparator)
   141  	} else {
   142  		GocoinHomeDir = sys.BitcoinHome() + "gocoin" + string(os.PathSeparator)
   143  	}
   144  
   145  	if Magic == [4]byte{0x0B, 0x11, 0x09, 0x07} {
   146  		// testnet3
   147  		fmt.Println("There are Testnet3 blocks")
   148  		GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")
   149  		GocoinHomeDir += "tstnet" + string(os.PathSeparator)
   150  	} else if Magic == [4]byte{0xF9, 0xBE, 0xB4, 0xD9} {
   151  		fmt.Println("There are valid Bitcoin blocks")
   152  		GenesisBlock = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
   153  		GocoinHomeDir += "btcnet" + string(os.PathSeparator)
   154  	} else {
   155  		println("blk00000.dat has an unexpected magic")
   156  		os.Exit(1)
   157  	}
   158  
   159  	fmt.Println("Importing blockchain data into", GocoinHomeDir, "...")
   160  
   161  	if exists(GocoinHomeDir+"blockchain.dat") ||
   162  		exists(GocoinHomeDir+"blockchain.idx") ||
   163  		exists(GocoinHomeDir+"unspent") {
   164  		println("Destination folder contains some database files.")
   165  		println("Either move them somewhere else or delete manually.")
   166  		println("None of the following files/folders must exist before you proceed:")
   167  		println(" *", GocoinHomeDir+"blockchain.dat")
   168  		println(" *", GocoinHomeDir+"blockchain.idx")
   169  		println(" *", GocoinHomeDir+"unspent")
   170  		os.Exit(1)
   171  	}
   172  
   173  	import_blockchain(BtcRootDir)
   174  }