From 9253fc337e4f36029f90f31b1b4e116d0a77ae05 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 27 May 2015 00:52:02 +0200 Subject: cmd/geth: exit the console cleanly when interrupted This fix applies mostly to unsupported terminals that do not trigger the special interrupt handling in liner. Supported terminals were covered because liner.Prompt returns an error if Ctrl-C is pressed. --- cmd/geth/js.go | 64 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 20 deletions(-) (limited to 'cmd/geth') diff --git a/cmd/geth/js.go b/cmd/geth/js.go index 0fb234d45..706bc6554 100644 --- a/cmd/geth/js.go +++ b/cmd/geth/js.go @@ -22,6 +22,7 @@ import ( "fmt" "math/big" "os" + "os/signal" "path/filepath" "strings" @@ -47,7 +48,8 @@ type dumbterm struct{ r *bufio.Reader } func (r dumbterm) Prompt(p string) (string, error) { fmt.Print(p) - return r.r.ReadString('\n') + line, err := r.r.ReadString('\n') + return strings.TrimSuffix(line, "\n"), err } func (r dumbterm) PasswordPrompt(p string) (string, error) { @@ -182,30 +184,52 @@ func (self *jsre) exec(filename string) error { } func (self *jsre) interactive() { - for { - input, err := self.Prompt(self.ps1) - if err != nil { - break + // Read input lines. + prompt := make(chan string) + inputln := make(chan string) + go func() { + defer close(inputln) + for { + line, err := self.Prompt(<-prompt) + if err != nil { + return + } + inputln <- line } - if input == "" { - continue + }() + // Wait for Ctrl-C, too. + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt) + + defer func() { + if self.atexit != nil { + self.atexit() } - str += input + "\n" - self.setIndent() - if indentCount <= 0 { - if input == "exit" { - break + self.re.Stop(false) + }() + for { + prompt <- self.ps1 + select { + case <-sig: + fmt.Println("caught interrupt, exiting") + return + case input, ok := <-inputln: + if !ok || indentCount <= 0 && input == "exit" { + return + } + if input == "" { + continue + } + str += input + "\n" + self.setIndent() + if indentCount <= 0 { + hist := str[:len(str)-1] + self.AppendHistory(hist) + self.parseInput(str) + str = "" } - hist := str[:len(str)-1] - self.AppendHistory(hist) - self.parseInput(str) - str = "" } } - if self.atexit != nil { - self.atexit() - } - self.re.Stop(false) } func (self *jsre) withHistory(op func(*os.File)) { -- cgit v1.2.3 From 3f91ee4ff824b38b7775f4e9f51a4160f5edc19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 27 May 2015 16:46:46 +0300 Subject: cmd/geth: expand admin.progress() to something meaningful --- cmd/geth/admin.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cmd/geth') diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go index 8f9a009d7..f0be444c6 100644 --- a/cmd/geth/admin.go +++ b/cmd/geth/admin.go @@ -262,8 +262,8 @@ func (js *jsre) setHead(call otto.FunctionCall) otto.Value { } func (js *jsre) downloadProgress(call otto.FunctionCall) otto.Value { - current, max := js.ethereum.Downloader().Stats() - v, _ := call.Otto.ToValue(fmt.Sprintf("%d/%d", current, max)) + pending, cached := js.ethereum.Downloader().Stats() + v, _ := call.Otto.ToValue(map[string]interface{}{"pending": pending, "cached": cached}) return v } -- cgit v1.2.3 From 3b9808f23ca4eb1621a92aad80de5c89269f17fe Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 27 May 2015 13:29:34 +0200 Subject: cmd/geth, cmd/utils: don't use Ethereum for import, export and upgradedb The blockchain commands don't need the full stack. With this change, p2p, miner, downloader, etc are no longer started for blockchain operations. --- cmd/geth/main.go | 113 ++++++++++++++++--------------------------------------- 1 file changed, 33 insertions(+), 80 deletions(-) (limited to 'cmd/geth') diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 0cbf8e41a..f849063fa 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -41,6 +41,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" ) @@ -282,17 +283,12 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.SolcPathFlag, } app.Before = func(ctx *cli.Context) error { + utils.SetupLogger(ctx) if ctx.GlobalBool(utils.PProfEanbledFlag.Name) { utils.StartPProf(ctx) } return nil } - - // missing: - // flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") - // flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0") - // flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false") - } func main() { @@ -516,53 +512,25 @@ func importchain(ctx *cli.Context) { if len(ctx.Args()) != 1 { utils.Fatalf("This command requires an argument.") } - - cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) - cfg.SkipBcVersionCheck = true - - ethereum, err := eth.New(cfg) - if err != nil { - utils.Fatalf("%v\n", err) - } - - chainmgr := ethereum.ChainManager() + chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) start := time.Now() - err = utils.ImportChain(chainmgr, ctx.Args().First()) - if err != nil { + if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { utils.Fatalf("Import error: %v\n", err) } - - // force database flush - ethereum.BlockDb().Flush() - ethereum.StateDb().Flush() - ethereum.ExtraDb().Flush() - + flushAll(blockDB, stateDB, extraDB) fmt.Printf("Import done in %v", time.Since(start)) - - return } func exportchain(ctx *cli.Context) { if len(ctx.Args()) != 1 { utils.Fatalf("This command requires an argument.") } - - cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) - cfg.SkipBcVersionCheck = true - - ethereum, err := eth.New(cfg) - if err != nil { - utils.Fatalf("%v\n", err) - } - - chainmgr := ethereum.ChainManager() + chain, _, _, _ := utils.GetChain(ctx) start := time.Now() - err = utils.ExportChain(chainmgr, ctx.Args().First()) - if err != nil { + if err := utils.ExportChain(chain, ctx.Args().First()); err != nil { utils.Fatalf("Export error: %v\n", err) } fmt.Printf("Export done in %v", time.Since(start)) - return } func removeDb(ctx *cli.Context) { @@ -585,76 +553,54 @@ func removeDb(ctx *cli.Context) { } func upgradeDb(ctx *cli.Context) { - fmt.Println("Upgrade blockchain DB") + glog.Infoln("Upgrading blockchain database") - cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) - cfg.SkipBcVersionCheck = true - - ethereum, err := eth.New(cfg) - if err != nil { - utils.Fatalf("%v\n", err) - } - - v, _ := ethereum.BlockDb().Get([]byte("BlockchainVersion")) + chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) + v, _ := blockDB.Get([]byte("BlockchainVersion")) bcVersion := int(common.NewValue(v).Uint()) - if bcVersion == 0 { bcVersion = core.BlockChainVersion } + // Export the current chain. filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405")) exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename) - - err = utils.ExportChain(ethereum.ChainManager(), exportFile) - if err != nil { + if err := utils.ExportChain(chain, exportFile); err != nil { utils.Fatalf("Unable to export chain for reimport %s\n", err) } - - ethereum.BlockDb().Close() - ethereum.StateDb().Close() - ethereum.ExtraDb().Close() - + flushAll(blockDB, stateDB, extraDB) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) - ethereum, err = eth.New(cfg) - if err != nil { - utils.Fatalf("%v\n", err) - } - - ethereum.BlockDb().Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes()) - - err = utils.ImportChain(ethereum.ChainManager(), exportFile) + // Import the chain file. + chain, blockDB, stateDB, extraDB = utils.GetChain(ctx) + blockDB.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes()) + err := utils.ImportChain(chain, exportFile) + flushAll(blockDB, stateDB, extraDB) if err != nil { utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile) + } else { + os.Remove(exportFile) + glog.Infoln("Import finished") } - - // force database flush - ethereum.BlockDb().Flush() - ethereum.StateDb().Flush() - ethereum.ExtraDb().Flush() - - os.Remove(exportFile) - - fmt.Println("Import finished") } func dump(ctx *cli.Context) { - chainmgr, _, stateDb := utils.GetChain(ctx) + chain, _, stateDB, _ := utils.GetChain(ctx) for _, arg := range ctx.Args() { var block *types.Block if hashish(arg) { - block = chainmgr.GetBlock(common.HexToHash(arg)) + block = chain.GetBlock(common.HexToHash(arg)) } else { num, _ := strconv.Atoi(arg) - block = chainmgr.GetBlockByNumber(uint64(num)) + block = chain.GetBlockByNumber(uint64(num)) } if block == nil { fmt.Println("{}") utils.Fatalf("block not found") } else { - statedb := state.New(block.Root(), stateDb) - fmt.Printf("%s\n", statedb.Dump()) + state := state.New(block.Root(), stateDB) + fmt.Printf("%s\n", state.Dump()) } } } @@ -707,3 +653,10 @@ func hashish(x string) bool { _, err := strconv.Atoi(x) return err != nil } + +func flushAll(dbs ...common.Database) { + for _, db := range dbs { + db.Flush() + db.Close() + } +} -- cgit v1.2.3 From 651030c98d0173db272aaee814c99f0a664d992b Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 27 May 2015 13:43:49 +0200 Subject: cmd/geth: move blockchain commands to chaincmd.go --- cmd/geth/blocktest.go | 120 ----------------------------------- cmd/geth/blocktestcmd.go | 120 +++++++++++++++++++++++++++++++++++ cmd/geth/chaincmd.go | 159 +++++++++++++++++++++++++++++++++++++++++++++++ cmd/geth/main.go | 153 +++------------------------------------------ 4 files changed, 286 insertions(+), 266 deletions(-) delete mode 100644 cmd/geth/blocktest.go create mode 100644 cmd/geth/blocktestcmd.go create mode 100644 cmd/geth/chaincmd.go (limited to 'cmd/geth') diff --git a/cmd/geth/blocktest.go b/cmd/geth/blocktest.go deleted file mode 100644 index 81a64b5f2..000000000 --- a/cmd/geth/blocktest.go +++ /dev/null @@ -1,120 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/codegangsta/cli" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/tests" -) - -var blocktestCmd = cli.Command{ - Action: runBlockTest, - Name: "blocktest", - Usage: `loads a block test file`, - Description: ` -The first argument should be a block test file. -The second argument is the name of a block test from the file. - -The block test will be loaded into an in-memory database. -If loading succeeds, the RPC server is started. Clients will -be able to interact with the chain defined by the test. -`, -} - -func runBlockTest(ctx *cli.Context) { - var ( - file, testname string - rpc bool - ) - args := ctx.Args() - switch { - case len(args) == 1: - file = args[0] - case len(args) == 2: - file, testname = args[0], args[1] - case len(args) == 3: - file, testname = args[0], args[1] - rpc = true - default: - utils.Fatalf(`Usage: ethereum blocktest [ [ "rpc" ] ]`) - } - bt, err := tests.LoadBlockTests(file) - if err != nil { - utils.Fatalf("%v", err) - } - - // run all tests if no test name is specified - if testname == "" { - ecode := 0 - for name, test := range bt { - fmt.Printf("----------------- Running Block Test %q\n", name) - ethereum, err := runOneBlockTest(ctx, test) - if err != nil { - fmt.Println(err) - fmt.Println("FAIL") - ecode = 1 - } - if ethereum != nil { - ethereum.Stop() - ethereum.WaitForShutdown() - } - } - os.Exit(ecode) - return - } - // otherwise, run the given test - test, ok := bt[testname] - if !ok { - utils.Fatalf("Test file does not contain test named %q", testname) - } - ethereum, err := runOneBlockTest(ctx, test) - if err != nil { - utils.Fatalf("%v", err) - } - defer ethereum.Stop() - if rpc { - fmt.Println("Block Test post state validated, starting RPC interface.") - startEth(ctx, ethereum) - utils.StartRPC(ethereum, ctx) - ethereum.WaitForShutdown() - } -} - -func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) { - cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) - cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() } - cfg.MaxPeers = 0 // disable network - cfg.Shh = false // disable whisper - cfg.NAT = nil // disable port mapping - - ethereum, err := eth.New(cfg) - if err != nil { - return nil, err - } - if err := ethereum.Start(); err != nil { - return nil, err - } - - // import the genesis block - ethereum.ResetWithGenesisBlock(test.Genesis) - - // import pre accounts - statedb, err := test.InsertPreState(ethereum) - if err != nil { - return ethereum, fmt.Errorf("InsertPreState: %v", err) - } - - if err := test.TryBlocksInsert(ethereum.ChainManager()); err != nil { - return ethereum, fmt.Errorf("Block Test load error: %v", err) - } - - if err := test.ValidatePostState(statedb); err != nil { - return ethereum, fmt.Errorf("post state validation failed: %v", err) - } - return ethereum, nil -} diff --git a/cmd/geth/blocktestcmd.go b/cmd/geth/blocktestcmd.go new file mode 100644 index 000000000..f4dcb0286 --- /dev/null +++ b/cmd/geth/blocktestcmd.go @@ -0,0 +1,120 @@ +package main + +import ( + "fmt" + "os" + + "github.com/codegangsta/cli" + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/tests" +) + +var blocktestCommand = cli.Command{ + Action: runBlockTest, + Name: "blocktest", + Usage: `loads a block test file`, + Description: ` +The first argument should be a block test file. +The second argument is the name of a block test from the file. + +The block test will be loaded into an in-memory database. +If loading succeeds, the RPC server is started. Clients will +be able to interact with the chain defined by the test. +`, +} + +func runBlockTest(ctx *cli.Context) { + var ( + file, testname string + rpc bool + ) + args := ctx.Args() + switch { + case len(args) == 1: + file = args[0] + case len(args) == 2: + file, testname = args[0], args[1] + case len(args) == 3: + file, testname = args[0], args[1] + rpc = true + default: + utils.Fatalf(`Usage: ethereum blocktest [ [ "rpc" ] ]`) + } + bt, err := tests.LoadBlockTests(file) + if err != nil { + utils.Fatalf("%v", err) + } + + // run all tests if no test name is specified + if testname == "" { + ecode := 0 + for name, test := range bt { + fmt.Printf("----------------- Running Block Test %q\n", name) + ethereum, err := runOneBlockTest(ctx, test) + if err != nil { + fmt.Println(err) + fmt.Println("FAIL") + ecode = 1 + } + if ethereum != nil { + ethereum.Stop() + ethereum.WaitForShutdown() + } + } + os.Exit(ecode) + return + } + // otherwise, run the given test + test, ok := bt[testname] + if !ok { + utils.Fatalf("Test file does not contain test named %q", testname) + } + ethereum, err := runOneBlockTest(ctx, test) + if err != nil { + utils.Fatalf("%v", err) + } + defer ethereum.Stop() + if rpc { + fmt.Println("Block Test post state validated, starting RPC interface.") + startEth(ctx, ethereum) + utils.StartRPC(ethereum, ctx) + ethereum.WaitForShutdown() + } +} + +func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) { + cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) + cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() } + cfg.MaxPeers = 0 // disable network + cfg.Shh = false // disable whisper + cfg.NAT = nil // disable port mapping + + ethereum, err := eth.New(cfg) + if err != nil { + return nil, err + } + if err := ethereum.Start(); err != nil { + return nil, err + } + + // import the genesis block + ethereum.ResetWithGenesisBlock(test.Genesis) + + // import pre accounts + statedb, err := test.InsertPreState(ethereum) + if err != nil { + return ethereum, fmt.Errorf("InsertPreState: %v", err) + } + + if err := test.TryBlocksInsert(ethereum.ChainManager()); err != nil { + return ethereum, fmt.Errorf("Block Test load error: %v", err) + } + + if err := test.ValidatePostState(statedb); err != nil { + return ethereum, fmt.Errorf("post state validation failed: %v", err) + } + return ethereum, nil +} diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go new file mode 100644 index 000000000..e17d1dc9b --- /dev/null +++ b/cmd/geth/chaincmd.go @@ -0,0 +1,159 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "time" + + "github.com/codegangsta/cli" + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/logger/glog" +) + +var ( + importCommand = cli.Command{ + Action: importChain, + Name: "import", + Usage: `import a blockchain file`, + } + exportCommand = cli.Command{ + Action: exportChain, + Name: "export", + Usage: `export blockchain into file`, + } + upgradedbCommand = cli.Command{ + Action: upgradeDB, + Name: "upgradedb", + Usage: "upgrade chainblock database", + } + removedbCommand = cli.Command{ + Action: removeDB, + Name: "removedb", + Usage: "Remove blockchain and state databases", + } + dumpCommand = cli.Command{ + Action: dump, + Name: "dump", + Usage: `dump a specific block from storage`, + Description: ` +The arguments are interpreted as block numbers or hashes. +Use "ethereum dump 0" to dump the genesis block. +`, + } +) + +func importChain(ctx *cli.Context) { + if len(ctx.Args()) != 1 { + utils.Fatalf("This command requires an argument.") + } + chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) + start := time.Now() + if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { + utils.Fatalf("Import error: %v\n", err) + } + flushAll(blockDB, stateDB, extraDB) + fmt.Printf("Import done in %v", time.Since(start)) +} + +func exportChain(ctx *cli.Context) { + if len(ctx.Args()) != 1 { + utils.Fatalf("This command requires an argument.") + } + chain, _, _, _ := utils.GetChain(ctx) + start := time.Now() + if err := utils.ExportChain(chain, ctx.Args().First()); err != nil { + utils.Fatalf("Export error: %v\n", err) + } + fmt.Printf("Export done in %v", time.Since(start)) +} + +func removeDB(ctx *cli.Context) { + confirm, err := utils.PromptConfirm("Remove local databases?") + if err != nil { + utils.Fatalf("%v", err) + } + + if confirm { + fmt.Println("Removing chain and state databases...") + start := time.Now() + + os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) + os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) + + fmt.Printf("Removed in %v\n", time.Since(start)) + } else { + fmt.Println("Operation aborted") + } +} + +func upgradeDB(ctx *cli.Context) { + glog.Infoln("Upgrading blockchain database") + + chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) + v, _ := blockDB.Get([]byte("BlockchainVersion")) + bcVersion := int(common.NewValue(v).Uint()) + if bcVersion == 0 { + bcVersion = core.BlockChainVersion + } + + // Export the current chain. + filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405")) + exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename) + if err := utils.ExportChain(chain, exportFile); err != nil { + utils.Fatalf("Unable to export chain for reimport %s\n", err) + } + flushAll(blockDB, stateDB, extraDB) + os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) + os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) + + // Import the chain file. + chain, blockDB, stateDB, extraDB = utils.GetChain(ctx) + blockDB.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes()) + err := utils.ImportChain(chain, exportFile) + flushAll(blockDB, stateDB, extraDB) + if err != nil { + utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile) + } else { + os.Remove(exportFile) + glog.Infoln("Import finished") + } +} + +func dump(ctx *cli.Context) { + chain, _, stateDB, _ := utils.GetChain(ctx) + for _, arg := range ctx.Args() { + var block *types.Block + if hashish(arg) { + block = chain.GetBlock(common.HexToHash(arg)) + } else { + num, _ := strconv.Atoi(arg) + block = chain.GetBlockByNumber(uint64(num)) + } + if block == nil { + fmt.Println("{}") + utils.Fatalf("block not found") + } else { + state := state.New(block.Root(), stateDB) + fmt.Printf("%s\n", state.Dump()) + } + } +} + +// hashish returns true for strings that look like hashes. +func hashish(x string) bool { + _, err := strconv.Atoi(x) + return err != nil +} + +func flushAll(dbs ...common.Database) { + for _, db := range dbs { + db.Flush() + db.Close() + } +} diff --git a/cmd/geth/main.go b/cmd/geth/main.go index f849063fa..9bf0fe610 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -24,28 +24,23 @@ import ( "fmt" "io" "io/ioutil" + _ "net/http/pprof" "os" "path/filepath" "runtime" "strconv" "strings" - "time" "github.com/codegangsta/cli" "github.com/ethereum/ethash" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/logger/glog" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" ) -import _ "net/http/pprof" const ( ClientIdentifier = "Geth" @@ -69,7 +64,12 @@ func init() { app.Action = run app.HideVersion = true // we have a command to print the version app.Commands = []cli.Command{ - blocktestCmd, + blocktestCommand, + importCommand, + exportCommand, + upgradedbCommand, + removedbCommand, + dumpCommand, { Action: makedag, Name: "makedag", @@ -194,15 +194,6 @@ nodes. }, }, }, - { - Action: dump, - Name: "dump", - Usage: `dump a specific block from storage`, - Description: ` -The arguments are interpreted as block numbers or hashes. -Use "ethereum dump 0" to dump the genesis block. -`, - }, { Action: console, Name: "console", @@ -222,26 +213,6 @@ The JavaScript VM exposes a node admin interface as well as the Ðapp JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console `, }, - { - Action: importchain, - Name: "import", - Usage: `import a blockchain file`, - }, - { - Action: exportchain, - Name: "export", - Usage: `export blockchain into file`, - }, - { - Action: upgradeDb, - Name: "upgradedb", - Usage: "upgrade chainblock database", - }, - { - Action: removeDb, - Name: "removedb", - Usage: "Remove blockchain and state databases", - }, } app.Flags = []cli.Flag{ utils.IdentityFlag, @@ -508,103 +479,6 @@ func accountImport(ctx *cli.Context) { fmt.Printf("Address: %x\n", acct) } -func importchain(ctx *cli.Context) { - if len(ctx.Args()) != 1 { - utils.Fatalf("This command requires an argument.") - } - chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) - start := time.Now() - if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { - utils.Fatalf("Import error: %v\n", err) - } - flushAll(blockDB, stateDB, extraDB) - fmt.Printf("Import done in %v", time.Since(start)) -} - -func exportchain(ctx *cli.Context) { - if len(ctx.Args()) != 1 { - utils.Fatalf("This command requires an argument.") - } - chain, _, _, _ := utils.GetChain(ctx) - start := time.Now() - if err := utils.ExportChain(chain, ctx.Args().First()); err != nil { - utils.Fatalf("Export error: %v\n", err) - } - fmt.Printf("Export done in %v", time.Since(start)) -} - -func removeDb(ctx *cli.Context) { - confirm, err := utils.PromptConfirm("Remove local databases?") - if err != nil { - utils.Fatalf("%v", err) - } - - if confirm { - fmt.Println("Removing chain and state databases...") - start := time.Now() - - os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) - os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) - - fmt.Printf("Removed in %v\n", time.Since(start)) - } else { - fmt.Println("Operation aborted") - } -} - -func upgradeDb(ctx *cli.Context) { - glog.Infoln("Upgrading blockchain database") - - chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) - v, _ := blockDB.Get([]byte("BlockchainVersion")) - bcVersion := int(common.NewValue(v).Uint()) - if bcVersion == 0 { - bcVersion = core.BlockChainVersion - } - - // Export the current chain. - filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405")) - exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename) - if err := utils.ExportChain(chain, exportFile); err != nil { - utils.Fatalf("Unable to export chain for reimport %s\n", err) - } - flushAll(blockDB, stateDB, extraDB) - os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) - os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) - - // Import the chain file. - chain, blockDB, stateDB, extraDB = utils.GetChain(ctx) - blockDB.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes()) - err := utils.ImportChain(chain, exportFile) - flushAll(blockDB, stateDB, extraDB) - if err != nil { - utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile) - } else { - os.Remove(exportFile) - glog.Infoln("Import finished") - } -} - -func dump(ctx *cli.Context) { - chain, _, stateDB, _ := utils.GetChain(ctx) - for _, arg := range ctx.Args() { - var block *types.Block - if hashish(arg) { - block = chain.GetBlock(common.HexToHash(arg)) - } else { - num, _ := strconv.Atoi(arg) - block = chain.GetBlockByNumber(uint64(num)) - } - if block == nil { - fmt.Println("{}") - utils.Fatalf("block not found") - } else { - state := state.New(block.Root(), stateDB) - fmt.Printf("%s\n", state.Dump()) - } - } -} - func makedag(ctx *cli.Context) { args := ctx.Args() wrongArgs := func() { @@ -647,16 +521,3 @@ func version(c *cli.Context) { fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH")) fmt.Printf("GOROOT=%s\n", runtime.GOROOT()) } - -// hashish returns true for strings that look like hashes. -func hashish(x string) bool { - _, err := strconv.Atoi(x) - return err != nil -} - -func flushAll(dbs ...common.Database) { - for _, db := range dbs { - db.Flush() - db.Close() - } -} -- cgit v1.2.3 From 74706a0f029fe74ea15e366904d827da03091fef Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 27 May 2015 14:50:31 +0200 Subject: cmd/geth, cmd/utils: rename utils.Get* -> utils.Make* The renaming should make it clearer that these functions create a new instance for every call. @obscuren suggested this renaming a while ago. --- cmd/geth/chaincmd.go | 10 +++++----- cmd/geth/main.go | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'cmd/geth') diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index e17d1dc9b..1aed800f6 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -52,7 +52,7 @@ func importChain(ctx *cli.Context) { if len(ctx.Args()) != 1 { utils.Fatalf("This command requires an argument.") } - chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) + chain, blockDB, stateDB, extraDB := utils.MakeChain(ctx) start := time.Now() if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { utils.Fatalf("Import error: %v\n", err) @@ -65,7 +65,7 @@ func exportChain(ctx *cli.Context) { if len(ctx.Args()) != 1 { utils.Fatalf("This command requires an argument.") } - chain, _, _, _ := utils.GetChain(ctx) + chain, _, _, _ := utils.MakeChain(ctx) start := time.Now() if err := utils.ExportChain(chain, ctx.Args().First()); err != nil { utils.Fatalf("Export error: %v\n", err) @@ -95,7 +95,7 @@ func removeDB(ctx *cli.Context) { func upgradeDB(ctx *cli.Context) { glog.Infoln("Upgrading blockchain database") - chain, blockDB, stateDB, extraDB := utils.GetChain(ctx) + chain, blockDB, stateDB, extraDB := utils.MakeChain(ctx) v, _ := blockDB.Get([]byte("BlockchainVersion")) bcVersion := int(common.NewValue(v).Uint()) if bcVersion == 0 { @@ -113,7 +113,7 @@ func upgradeDB(ctx *cli.Context) { os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) // Import the chain file. - chain, blockDB, stateDB, extraDB = utils.GetChain(ctx) + chain, blockDB, stateDB, extraDB = utils.MakeChain(ctx) blockDB.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes()) err := utils.ImportChain(chain, exportFile) flushAll(blockDB, stateDB, extraDB) @@ -126,7 +126,7 @@ func upgradeDB(ctx *cli.Context) { } func dump(ctx *cli.Context) { - chain, _, stateDB, _ := utils.GetChain(ctx) + chain, _, stateDB, _ := utils.MakeChain(ctx) for _, arg := range ctx.Args() { var block *types.Block if hashish(arg) { diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 9bf0fe610..eecd7546a 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -394,7 +394,7 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) { } func accountList(ctx *cli.Context) { - am := utils.GetAccountManager(ctx) + am := utils.MakeAccountManager(ctx) accts, err := am.Accounts() if err != nil { utils.Fatalf("Could not list accounts: %v", err) @@ -436,7 +436,7 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase } func accountCreate(ctx *cli.Context) { - am := utils.GetAccountManager(ctx) + am := utils.MakeAccountManager(ctx) passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true) acct, err := am.NewAccount(passphrase) if err != nil { @@ -455,7 +455,7 @@ func importWallet(ctx *cli.Context) { utils.Fatalf("Could not read wallet file: %v", err) } - am := utils.GetAccountManager(ctx) + am := utils.MakeAccountManager(ctx) passphrase := getPassPhrase(ctx, "", false) acct, err := am.ImportPreSaleKey(keyJson, passphrase) @@ -470,7 +470,7 @@ func accountImport(ctx *cli.Context) { if len(keyfile) == 0 { utils.Fatalf("keyfile must be given as argument") } - am := utils.GetAccountManager(ctx) + am := utils.MakeAccountManager(ctx) passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true) acct, err := am.Import(keyfile, passphrase) if err != nil { -- cgit v1.2.3 From 67effb94b6fadac7b207cb5333c91f578326762e Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 27 May 2015 16:02:08 +0200 Subject: cmd/geth, cmd/utils: make chain importing interruptible Interrupting import with Ctrl-C could cause database corruption because the signal wasn't handled. utils.ImportChain now checks for a queued interrupt on every batch. --- cmd/geth/chaincmd.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'cmd/geth') diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 1aed800f6..6245c691b 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -54,10 +54,11 @@ func importChain(ctx *cli.Context) { } chain, blockDB, stateDB, extraDB := utils.MakeChain(ctx) start := time.Now() - if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { - utils.Fatalf("Import error: %v\n", err) - } + err := utils.ImportChain(chain, ctx.Args().First()) flushAll(blockDB, stateDB, extraDB) + if err != nil { + utils.Fatalf("Import error: %v", err) + } fmt.Printf("Import done in %v", time.Since(start)) } @@ -106,7 +107,7 @@ func upgradeDB(ctx *cli.Context) { filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405")) exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename) if err := utils.ExportChain(chain, exportFile); err != nil { - utils.Fatalf("Unable to export chain for reimport %s\n", err) + utils.Fatalf("Unable to export chain for reimport %s", err) } flushAll(blockDB, stateDB, extraDB) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) @@ -118,7 +119,7 @@ func upgradeDB(ctx *cli.Context) { err := utils.ImportChain(chain, exportFile) flushAll(blockDB, stateDB, extraDB) if err != nil { - utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile) + utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)", err, exportFile) } else { os.Remove(exportFile) glog.Infoln("Import finished") -- cgit v1.2.3 From e84bbcce3c335b863eb6304ad910047054b68c20 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 28 May 2015 01:20:03 +0200 Subject: cmd/geth: don't flush databases after import --- cmd/geth/chaincmd.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'cmd/geth') diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 6245c691b..947532f40 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -55,7 +55,7 @@ func importChain(ctx *cli.Context) { chain, blockDB, stateDB, extraDB := utils.MakeChain(ctx) start := time.Now() err := utils.ImportChain(chain, ctx.Args().First()) - flushAll(blockDB, stateDB, extraDB) + closeAll(blockDB, stateDB, extraDB) if err != nil { utils.Fatalf("Import error: %v", err) } @@ -109,7 +109,7 @@ func upgradeDB(ctx *cli.Context) { if err := utils.ExportChain(chain, exportFile); err != nil { utils.Fatalf("Unable to export chain for reimport %s", err) } - flushAll(blockDB, stateDB, extraDB) + closeAll(blockDB, stateDB, extraDB) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) @@ -117,7 +117,7 @@ func upgradeDB(ctx *cli.Context) { chain, blockDB, stateDB, extraDB = utils.MakeChain(ctx) blockDB.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes()) err := utils.ImportChain(chain, exportFile) - flushAll(blockDB, stateDB, extraDB) + closeAll(blockDB, stateDB, extraDB) if err != nil { utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)", err, exportFile) } else { @@ -152,9 +152,8 @@ func hashish(x string) bool { return err != nil } -func flushAll(dbs ...common.Database) { +func closeAll(dbs ...common.Database) { for _, db := range dbs { - db.Flush() db.Close() } } -- cgit v1.2.3 From 9138955ba534ec074ecf55c4d02e2f3e72b29faa Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Thu, 28 May 2015 15:20:05 +0200 Subject: Validate account length and avoid slicing in logging --- cmd/geth/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cmd/geth') diff --git a/cmd/geth/main.go b/cmd/geth/main.go index eecd7546a..f82a121e7 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -340,13 +340,13 @@ func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (pass var err error // Load startup keys. XXX we are going to need a different format - if len(account) == 0 { + if !((len(account) == 40) || (len(account) == 42)) { // with or without 0x utils.Fatalf("Invalid account address '%s'", account) } // Attempt to unlock the account 3 times attempts := 3 for tries := 0; tries < attempts; tries++ { - msg := fmt.Sprintf("Unlocking account %s...%s | Attempt %d/%d", account[:8], account[len(account)-6:], tries+1, attempts) + msg := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", account, tries+1, attempts) passphrase = getPassPhrase(ctx, msg, false) err = am.Unlock(common.HexToAddress(account), passphrase) if err == nil { -- cgit v1.2.3 From d51d74eb55535db7670ad336d186ea64c6a2ff81 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 28 May 2015 17:43:05 +0200 Subject: cmd/geth: bump version v0.9.26 --- cmd/geth/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd/geth') diff --git a/cmd/geth/main.go b/cmd/geth/main.go index f82a121e7..ab46fdd3e 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -44,7 +44,7 @@ import ( const ( ClientIdentifier = "Geth" - Version = "0.9.25" + Version = "0.9.26" ) var ( -- cgit v1.2.3