github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/cmd/geth/chaincmd.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "fmt" 21 "os" 22 "path/filepath" 23 "strconv" 24 "time" 25 26 "github.com/codegangsta/cli" 27 "github.com/ethereum/go-ethereum/cmd/utils" 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/core" 30 "github.com/ethereum/go-ethereum/core/state" 31 "github.com/ethereum/go-ethereum/core/types" 32 "github.com/ethereum/go-ethereum/logger/glog" 33 ) 34 35 var ( 36 importCommand = cli.Command{ 37 Action: importChain, 38 Name: "import", 39 Usage: `import a blockchain file`, 40 } 41 exportCommand = cli.Command{ 42 Action: exportChain, 43 Name: "export", 44 Usage: `export blockchain into file`, 45 Description: ` 46 Requires a first argument of the file to write to. 47 Optional second and third arguments control the first and 48 last block to write. In this mode, the file will be appended 49 if already existing. 50 `, 51 } 52 upgradedbCommand = cli.Command{ 53 Action: upgradeDB, 54 Name: "upgradedb", 55 Usage: "upgrade chainblock database", 56 } 57 removedbCommand = cli.Command{ 58 Action: removeDB, 59 Name: "removedb", 60 Usage: "Remove blockchain and state databases", 61 } 62 dumpCommand = cli.Command{ 63 Action: dump, 64 Name: "dump", 65 Usage: `dump a specific block from storage`, 66 Description: ` 67 The arguments are interpreted as block numbers or hashes. 68 Use "ethereum dump 0" to dump the genesis block. 69 `, 70 } 71 ) 72 73 func importChain(ctx *cli.Context) { 74 if len(ctx.Args()) != 1 { 75 utils.Fatalf("This command requires an argument.") 76 } 77 chain, chainDb := utils.MakeChain(ctx) 78 start := time.Now() 79 err := utils.ImportChain(chain, ctx.Args().First()) 80 chainDb.Close() 81 if err != nil { 82 utils.Fatalf("Import error: %v", err) 83 } 84 fmt.Printf("Import done in %v", time.Since(start)) 85 } 86 87 func exportChain(ctx *cli.Context) { 88 if len(ctx.Args()) < 1 { 89 utils.Fatalf("This command requires an argument.") 90 } 91 chain, _ := utils.MakeChain(ctx) 92 start := time.Now() 93 94 var err error 95 fp := ctx.Args().First() 96 if len(ctx.Args()) < 3 { 97 err = utils.ExportChain(chain, fp) 98 } else { 99 // This can be improved to allow for numbers larger than 9223372036854775807 100 first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64) 101 last, lerr := strconv.ParseInt(ctx.Args().Get(2), 10, 64) 102 if ferr != nil || lerr != nil { 103 utils.Fatalf("Export error in parsing parameters: block number not an integer\n") 104 } 105 if first < 0 || last < 0 { 106 utils.Fatalf("Export error: block number must be greater than 0\n") 107 } 108 err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last)) 109 } 110 111 if err != nil { 112 utils.Fatalf("Export error: %v\n", err) 113 } 114 fmt.Printf("Export done in %v", time.Since(start)) 115 } 116 117 func removeDB(ctx *cli.Context) { 118 confirm, err := utils.PromptConfirm("Remove local database?") 119 if err != nil { 120 utils.Fatalf("%v", err) 121 } 122 123 if confirm { 124 fmt.Println("Removing chaindata...") 125 start := time.Now() 126 127 os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "chaindata")) 128 129 fmt.Printf("Removed in %v\n", time.Since(start)) 130 } else { 131 fmt.Println("Operation aborted") 132 } 133 } 134 135 func upgradeDB(ctx *cli.Context) { 136 glog.Infoln("Upgrading blockchain database") 137 138 chain, chainDb := utils.MakeChain(ctx) 139 v, _ := chainDb.Get([]byte("BlockchainVersion")) 140 bcVersion := int(common.NewValue(v).Uint()) 141 if bcVersion == 0 { 142 bcVersion = core.BlockChainVersion 143 } 144 145 // Export the current chain. 146 filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405")) 147 exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename) 148 if err := utils.ExportChain(chain, exportFile); err != nil { 149 utils.Fatalf("Unable to export chain for reimport %s", err) 150 } 151 chainDb.Close() 152 os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "chaindata")) 153 154 // Import the chain file. 155 chain, chainDb = utils.MakeChain(ctx) 156 chainDb.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes()) 157 err := utils.ImportChain(chain, exportFile) 158 chainDb.Close() 159 if err != nil { 160 utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)", err, exportFile) 161 } else { 162 os.Remove(exportFile) 163 glog.Infoln("Import finished") 164 } 165 } 166 167 func dump(ctx *cli.Context) { 168 chain, chainDb := utils.MakeChain(ctx) 169 for _, arg := range ctx.Args() { 170 var block *types.Block 171 if hashish(arg) { 172 block = chain.GetBlock(common.HexToHash(arg)) 173 } else { 174 num, _ := strconv.Atoi(arg) 175 block = chain.GetBlockByNumber(uint64(num)) 176 } 177 if block == nil { 178 fmt.Println("{}") 179 utils.Fatalf("block not found") 180 } else { 181 state := state.New(block.Root(), chainDb) 182 fmt.Printf("%s\n", state.Dump()) 183 } 184 } 185 chainDb.Close() 186 } 187 188 // hashish returns true for strings that look like hashes. 189 func hashish(x string) bool { 190 _, err := strconv.Atoi(x) 191 return err != nil 192 } 193 194 func closeAll(dbs ...common.Database) { 195 for _, db := range dbs { 196 db.Close() 197 } 198 }