chaincmd.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "strconv"
  7. "time"
  8. "github.com/codegangsta/cli"
  9. "github.com/ethereum/go-ethereum/cmd/utils"
  10. "github.com/ethereum/go-ethereum/common"
  11. "github.com/ethereum/go-ethereum/core"
  12. "github.com/ethereum/go-ethereum/core/state"
  13. "github.com/ethereum/go-ethereum/core/types"
  14. "github.com/ethereum/go-ethereum/logger/glog"
  15. )
  16. var (
  17. importCommand = cli.Command{
  18. Action: importChain,
  19. Name: "import",
  20. Usage: `import a blockchain file`,
  21. }
  22. exportCommand = cli.Command{
  23. Action: exportChain,
  24. Name: "export",
  25. Usage: `export blockchain into file`,
  26. }
  27. upgradedbCommand = cli.Command{
  28. Action: upgradeDB,
  29. Name: "upgradedb",
  30. Usage: "upgrade chainblock database",
  31. }
  32. removedbCommand = cli.Command{
  33. Action: removeDB,
  34. Name: "removedb",
  35. Usage: "Remove blockchain and state databases",
  36. }
  37. dumpCommand = cli.Command{
  38. Action: dump,
  39. Name: "dump",
  40. Usage: `dump a specific block from storage`,
  41. Description: `
  42. The arguments are interpreted as block numbers or hashes.
  43. Use "ethereum dump 0" to dump the genesis block.
  44. `,
  45. }
  46. )
  47. func importChain(ctx *cli.Context) {
  48. if len(ctx.Args()) != 1 {
  49. utils.Fatalf("This command requires an argument.")
  50. }
  51. chain, blockDB, stateDB, extraDB := utils.MakeChain(ctx)
  52. start := time.Now()
  53. if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
  54. utils.Fatalf("Import error: %v\n", err)
  55. }
  56. flushAll(blockDB, stateDB, extraDB)
  57. fmt.Printf("Import done in %v", time.Since(start))
  58. }
  59. func exportChain(ctx *cli.Context) {
  60. if len(ctx.Args()) != 1 {
  61. utils.Fatalf("This command requires an argument.")
  62. }
  63. chain, _, _, _ := utils.MakeChain(ctx)
  64. start := time.Now()
  65. if err := utils.ExportChain(chain, ctx.Args().First()); err != nil {
  66. utils.Fatalf("Export error: %v\n", err)
  67. }
  68. fmt.Printf("Export done in %v", time.Since(start))
  69. }
  70. func removeDB(ctx *cli.Context) {
  71. confirm, err := utils.PromptConfirm("Remove local databases?")
  72. if err != nil {
  73. utils.Fatalf("%v", err)
  74. }
  75. if confirm {
  76. fmt.Println("Removing chain and state databases...")
  77. start := time.Now()
  78. os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain"))
  79. os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state"))
  80. fmt.Printf("Removed in %v\n", time.Since(start))
  81. } else {
  82. fmt.Println("Operation aborted")
  83. }
  84. }
  85. func upgradeDB(ctx *cli.Context) {
  86. glog.Infoln("Upgrading blockchain database")
  87. chain, blockDB, stateDB, extraDB := utils.MakeChain(ctx)
  88. v, _ := blockDB.Get([]byte("BlockchainVersion"))
  89. bcVersion := int(common.NewValue(v).Uint())
  90. if bcVersion == 0 {
  91. bcVersion = core.BlockChainVersion
  92. }
  93. // Export the current chain.
  94. filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405"))
  95. exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename)
  96. if err := utils.ExportChain(chain, exportFile); err != nil {
  97. utils.Fatalf("Unable to export chain for reimport %s\n", err)
  98. }
  99. flushAll(blockDB, stateDB, extraDB)
  100. os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain"))
  101. os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state"))
  102. // Import the chain file.
  103. chain, blockDB, stateDB, extraDB = utils.MakeChain(ctx)
  104. blockDB.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes())
  105. err := utils.ImportChain(chain, exportFile)
  106. flushAll(blockDB, stateDB, extraDB)
  107. if err != nil {
  108. utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile)
  109. } else {
  110. os.Remove(exportFile)
  111. glog.Infoln("Import finished")
  112. }
  113. }
  114. func dump(ctx *cli.Context) {
  115. chain, _, stateDB, _ := utils.MakeChain(ctx)
  116. for _, arg := range ctx.Args() {
  117. var block *types.Block
  118. if hashish(arg) {
  119. block = chain.GetBlock(common.HexToHash(arg))
  120. } else {
  121. num, _ := strconv.Atoi(arg)
  122. block = chain.GetBlockByNumber(uint64(num))
  123. }
  124. if block == nil {
  125. fmt.Println("{}")
  126. utils.Fatalf("block not found")
  127. } else {
  128. state := state.New(block.Root(), stateDB)
  129. fmt.Printf("%s\n", state.Dump())
  130. }
  131. }
  132. }
  133. // hashish returns true for strings that look like hashes.
  134. func hashish(x string) bool {
  135. _, err := strconv.Atoi(x)
  136. return err != nil
  137. }
  138. func flushAll(dbs ...common.Database) {
  139. for _, db := range dbs {
  140. db.Flush()
  141. db.Close()
  142. }
  143. }