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 }