From bc45e5c6de3052a4c853387dea0af5cd9207f1f7 Mon Sep 17 00:00:00 2001
From: Gustav Simonsson <gustav.simonsson@gmail.com>
Date: Thu, 26 Feb 2015 13:22:09 +0100
Subject: Integrate eth_accounts and eth_transact to use new account manager

* Add from to eth_transact / xeth.Transact and add static pass in lieu
  of integrating with native Mist window for user passphrase entry
* Make eth_accounts return AccountManager.Accounts()
* Add a Generate Key menu item in Mist
---
 cmd/mist/assets/qml/main.qml | 5 +++++
 cmd/mist/bindings.go         | 4 ++--
 cmd/mist/gui.go              | 7 +++++++
 cmd/mist/ui_lib.go           | 1 +
 4 files changed, 15 insertions(+), 2 deletions(-)

(limited to 'cmd')

diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml
index f9ee6939d..7f72d35f4 100644
--- a/cmd/mist/assets/qml/main.qml
+++ b/cmd/mist/assets/qml/main.qml
@@ -190,6 +190,11 @@ ApplicationWindow {
                 }
             }
 
+            MenuItem {
+                text: "Generate key"
+                shortcut: "Ctrl+k"
+                onTriggered: gui.generateKey()
+            }
         }
 
         Menu {
diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go
index f21aa3135..fd89eb7e2 100644
--- a/cmd/mist/bindings.go
+++ b/cmd/mist/bindings.go
@@ -49,7 +49,7 @@ func (gui *Gui) LogPrint(level logger.LogLevel, msg string) {
 		}
 	*/
 }
-func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, error) {
+func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
 	var data string
 	if len(recipient) == 0 {
 		code, err := ethutil.Compile(d, false)
@@ -61,7 +61,7 @@ func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, err
 		data = ethutil.Bytes2Hex(utils.FormatTransactionData(d))
 	}
 
-	return gui.xeth.Transact(recipient, value, gas, gasPrice, data)
+	return gui.xeth.Transact(from, recipient, value, gas, gasPrice, data)
 }
 
 // functions that allow Gui to implement interface guilogger.LogSystem
diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go
index 869b689dd..bc6e9ed53 100644
--- a/cmd/mist/gui.go
+++ b/cmd/mist/gui.go
@@ -175,6 +175,13 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
 func (gui *Gui) ImportKey(filePath string) {
 }
 
+func (gui *Gui) GenerateKey() {
+	_, err := gui.eth.AccountManager().NewAccount("hurr")
+	if err != nil {
+		// TODO: UI feedback?
+	}
+}
+
 func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
 	context.SetVar("lib", gui)
 	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go
index 098e8fca5..af78f0c10 100644
--- a/cmd/mist/ui_lib.go
+++ b/cmd/mist/ui_lib.go
@@ -171,6 +171,7 @@ func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
 	object := mapToTxParams(params)
 
 	return self.XEth.Transact(
+		object["from"],
 		object["to"],
 		object["value"],
 		object["gas"],
-- 
cgit v1.2.3


From a2810c06d7cfc64e1636fe4ecfd5e35cc52b0d2b Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Sat, 7 Mar 2015 12:39:52 +0100
Subject: cmd/ethereum: add account commands

---
 cmd/ethereum/main.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++------
 cmd/utils/flags.go   | 48 +++++++++++++++----------------
 2 files changed, 93 insertions(+), 34 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 1133bd6f7..f12616e17 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -21,6 +21,7 @@
 package main
 
 import (
+	"bufio"
 	"fmt"
 	"os"
 	"runtime"
@@ -34,6 +35,7 @@ import (
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/state"
+	"github.com/peterh/liner"
 )
 
 const (
@@ -60,6 +62,23 @@ func init() {
 The output of this command is supposed to be machine-readable.
 `,
 		},
+		{
+			Action: accountList,
+			Name:   "account",
+			Usage:  "manage accounts",
+			Subcommands: []cli.Command{
+				{
+					Action: accountList,
+					Name:   "list",
+					Usage:  "print account addresses",
+				},
+				{
+					Action: accountCreate,
+					Name:   "new",
+					Usage:  "create a new account",
+				},
+			},
+		},
 		{
 			Action: dump,
 			Name:   "dump",
@@ -93,8 +112,6 @@ runtime will execute the file and exit.
 	app.Flags = []cli.Flag{
 		utils.BootnodesFlag,
 		utils.DataDirFlag,
-		utils.KeyRingFlag,
-		utils.KeyStoreFlag,
 		utils.ListenPortFlag,
 		utils.LogFileFlag,
 		utils.LogFormatFlag,
@@ -166,6 +183,37 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
 	}
 }
 
+func accountList(ctx *cli.Context) {
+	am := utils.GetAccountManager(ctx)
+	accts, err := am.Accounts()
+	if err != nil {
+		utils.Fatalf("Could not list accounts: %v", err)
+	}
+	for _, acct := range accts {
+		fmt.Printf("Address: %#x\n", acct)
+	}
+}
+
+func accountCreate(ctx *cli.Context) {
+	am := utils.GetAccountManager(ctx)
+	auth, err := readPassword("Passphrase: ", true)
+	if err != nil {
+		utils.Fatalf("%v", err)
+	}
+	confirm, err := readPassword("Repeat Passphrase: ", false)
+	if err != nil {
+		utils.Fatalf("%v", err)
+	}
+	if auth != confirm {
+		utils.Fatalf("Passphrases did not match.")
+	}
+	acct, err := am.NewAccount(auth)
+	if err != nil {
+		utils.Fatalf("Could not create the account: %v", err)
+	}
+	fmt.Printf("Address: %#x\n", acct.Address)
+}
+
 func importchain(ctx *cli.Context) {
 	if len(ctx.Args()) != 1 {
 		utils.Fatalf("This command requires an argument.")
@@ -201,12 +249,6 @@ func dump(ctx *cli.Context) {
 	}
 }
 
-// hashish returns true for strings that look like hashes.
-func hashish(x string) bool {
-	_, err := strconv.Atoi(x)
-	return err != nil
-}
-
 func version(c *cli.Context) {
 	fmt.Printf(`%v %v
 PV=%d
@@ -216,3 +258,24 @@ GOPATH=%s
 GOROOT=%s
 `, ClientIdentifier, Version, eth.ProtocolVersion, runtime.GOOS, runtime.Version(), os.Getenv("GOPATH"), runtime.GOROOT())
 }
+
+// hashish returns true for strings that look like hashes.
+func hashish(x string) bool {
+	_, err := strconv.Atoi(x)
+	return err != nil
+}
+
+func readPassword(prompt string, warnTerm bool) (string, error) {
+	if liner.TerminalSupported() {
+		lr := liner.NewLiner()
+		defer lr.Close()
+		return lr.PasswordPrompt(prompt)
+	}
+	if warnTerm {
+		fmt.Println("!! Unsupported terminal, password will be echoed.")
+	}
+	fmt.Print(prompt)
+	input, err := bufio.NewReader(os.Stdin).ReadString('\n')
+	fmt.Println()
+	return input, err
+}
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index fb80ac708..4f3ecd2b2 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -4,8 +4,10 @@ import (
 	"crypto/ecdsa"
 	"path"
 	"runtime"
+	"time"
 
 	"github.com/codegangsta/cli"
+	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/eth"
@@ -30,16 +32,6 @@ var (
 		Name:  "vm",
 		Usage: "Virtual Machine type: 0 is standard VM, 1 is debug VM",
 	}
-	KeyRingFlag = cli.StringFlag{
-		Name:  "keyring",
-		Usage: "Name of keyring to be used",
-		Value: "",
-	}
-	KeyStoreFlag = cli.StringFlag{
-		Name:  "keystore",
-		Usage: `Where to store keyrings: "db" or "file"`,
-		Value: "db",
-	}
 	DataDirFlag = cli.StringFlag{
 		Name:  "datadir",
 		Usage: "Data directory to be used",
@@ -145,22 +137,20 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
 
 func GetEthereum(clientID, version string, ctx *cli.Context) *eth.Ethereum {
 	ethereum, err := eth.New(&eth.Config{
-		Name:         p2p.MakeName(clientID, version),
-		KeyStore:     ctx.GlobalString(KeyStoreFlag.Name),
-		DataDir:      ctx.GlobalString(DataDirFlag.Name),
-		LogFile:      ctx.GlobalString(LogFileFlag.Name),
-		LogLevel:     ctx.GlobalInt(LogLevelFlag.Name),
-		LogFormat:    ctx.GlobalString(LogFormatFlag.Name),
-		MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
-
-		MaxPeers:  ctx.GlobalInt(MaxPeersFlag.Name),
-		Port:      ctx.GlobalString(ListenPortFlag.Name),
-		NAT:       GetNAT(ctx),
-		NodeKey:   GetNodeKey(ctx),
-		KeyRing:   ctx.GlobalString(KeyRingFlag.Name),
-		Shh:       true,
-		Dial:      true,
-		BootNodes: ctx.GlobalString(BootnodesFlag.Name),
+		Name:           p2p.MakeName(clientID, version),
+		DataDir:        ctx.GlobalString(DataDirFlag.Name),
+		LogFile:        ctx.GlobalString(LogFileFlag.Name),
+		LogLevel:       ctx.GlobalInt(LogLevelFlag.Name),
+		LogFormat:      ctx.GlobalString(LogFormatFlag.Name),
+		MinerThreads:   ctx.GlobalInt(MinerThreadsFlag.Name),
+		AccountManager: GetAccountManager(ctx),
+		MaxPeers:       ctx.GlobalInt(MaxPeersFlag.Name),
+		Port:           ctx.GlobalString(ListenPortFlag.Name),
+		NAT:            GetNAT(ctx),
+		NodeKey:        GetNodeKey(ctx),
+		Shh:            true,
+		Dial:           true,
+		BootNodes:      ctx.GlobalString(BootnodesFlag.Name),
 	})
 	if err != nil {
 		exit(err)
@@ -176,3 +166,9 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database) {
 	}
 	return core.NewChainManager(db, new(event.TypeMux)), db
 }
+
+func GetAccountManager(ctx *cli.Context) *accounts.AccountManager {
+	dataDir := ctx.GlobalString(DataDirFlag.Name)
+	ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
+	return accounts.NewAccountManager(ks, 300*time.Second)
+}
-- 
cgit v1.2.3


From fb53a9362e1238d8edb466d77427dc3cbb13eb20 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Sun, 8 Mar 2015 01:52:49 +0100
Subject: accounts: AccountManager -> Manager

---
 cmd/utils/flags.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'cmd')

diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 4f3ecd2b2..e6eee20a7 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -167,8 +167,8 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database) {
 	return core.NewChainManager(db, new(event.TypeMux)), db
 }
 
-func GetAccountManager(ctx *cli.Context) *accounts.AccountManager {
+func GetAccountManager(ctx *cli.Context) *accounts.Manager {
 	dataDir := ctx.GlobalString(DataDirFlag.Name)
 	ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
-	return accounts.NewAccountManager(ks, 300*time.Second)
+	return accounts.NewManager(ks, 300*time.Second)
 }
-- 
cgit v1.2.3


From 2dacb51fb02816c7591bfdbaaf7a160e122e5590 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Mon, 9 Mar 2015 16:58:06 +0100
Subject: cmd/blocktest: simplify to fix build

block tests only need the chain, not all of ethereum.
---
 cmd/blocktest/flags.go |  41 -----------
 cmd/blocktest/main.go  | 182 +++++++++----------------------------------------
 2 files changed, 34 insertions(+), 189 deletions(-)
 delete mode 100644 cmd/blocktest/flags.go

(limited to 'cmd')

diff --git a/cmd/blocktest/flags.go b/cmd/blocktest/flags.go
deleted file mode 100644
index c811e5b85..000000000
--- a/cmd/blocktest/flags.go
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-	This file is part of go-ethereum
-
-	go-ethereum is free software: you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation, either version 3 of the License, or
-	(at your option) any later version.
-
-	go-ethereum is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @authors
- * 	Gustav Simonsson <gustav.simonsson@gmail.com>
- */
-package main
-
-import (
-	"flag"
-	"fmt"
-	"os"
-)
-
-var (
-	TestFile string
-)
-
-func Init() {
-	flag.Usage = func() {
-		fmt.Fprintf(os.Stderr, "%s <testfile>\n", os.Args[0])
-		flag.PrintDefaults()
-	}
-	flag.Parse()
-
-	TestFile = flag.Arg(0)
-}
diff --git a/cmd/blocktest/main.go b/cmd/blocktest/main.go
index 4a05b8bee..b96f42710 100644
--- a/cmd/blocktest/main.go
+++ b/cmd/blocktest/main.go
@@ -25,34 +25,26 @@ package main
 
 import (
 	"bytes"
-	"crypto/ecdsa"
 	"encoding/hex"
 	"encoding/json"
+	"flag"
 	"fmt"
 	"io/ioutil"
 	"log"
 	"math/big"
-	"path"
+	"os"
 	"runtime"
-	"strconv"
 	"strings"
-	"time"
 
 	"github.com/ethereum/go-ethereum/cmd/utils"
+	"github.com/ethereum/go-ethereum/core"
 	types "github.com/ethereum/go-ethereum/core/types"
-	"github.com/ethereum/go-ethereum/eth"
-	"github.com/ethereum/go-ethereum/ethutil"
+	"github.com/ethereum/go-ethereum/ethdb"
+	"github.com/ethereum/go-ethereum/event"
 	"github.com/ethereum/go-ethereum/logger"
-	"github.com/ethereum/go-ethereum/p2p"
-	"github.com/ethereum/go-ethereum/p2p/nat"
 	"github.com/ethereum/go-ethereum/rlp"
 )
 
-const (
-	ClientIdentifier = "Ethereum(G)"
-	Version          = "0.8.6"
-)
-
 type Account struct {
 	Balance string
 	Code    string
@@ -78,6 +70,7 @@ type BlockHeader struct {
 	TransactionsTrie string
 	UncleHash        string
 }
+
 type Tx struct {
 	Data     string
 	GasLimit string
@@ -103,103 +96,40 @@ type Test struct {
 	Pre                map[string]Account
 }
 
-var (
-	Identifier       string
-	KeyRing          string
-	DiffTool         bool
-	DiffType         string
-	KeyStore         string
-	StartRpc         bool
-	StartWebSockets  bool
-	RpcListenAddress string
-	RpcPort          int
-	WsPort           int
-	OutboundPort     string
-	ShowGenesis      bool
-	AddPeer          string
-	MaxPeer          int
-	GenAddr          bool
-	BootNodes        string
-	NodeKey          *ecdsa.PrivateKey
-	NAT              nat.Interface
-	SecretFile       string
-	ExportDir        string
-	NonInteractive   bool
-	Datadir          string
-	LogFile          string
-	ConfigFile       string
-	DebugFile        string
-	LogLevel         int
-	LogFormat        string
-	Dump             bool
-	DumpHash         string
-	DumpNumber       int
-	VmType           int
-	ImportChain      string
-	SHH              bool
-	Dial             bool
-	PrintVersion     bool
-	MinerThreads     int
-)
-
-// flags specific to cli client
-var (
-	StartMining    bool
-	StartJsConsole bool
-	InputFile      string
-)
-
 func main() {
-	init_vars()
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, "%s <testfile>\n", os.Args[0])
+		flag.PrintDefaults()
+	}
+	flag.Parse()
 
-	Init()
+	runtime.GOMAXPROCS(runtime.NumCPU())
+	logger.AddLogSystem(logger.NewStdLogSystem(os.Stderr, log.LstdFlags, logger.DebugDetailLevel))
+	defer func() { logger.Flush() }()
 
-	if len(TestFile) < 1 {
-		log.Fatal("Please specify test file")
+	if len(os.Args) < 2 {
+		utils.Fatalf("Please specify a test file as the first argument.")
 	}
-	blocks, err := loadBlocksFromTestFile(TestFile)
+	blocks, err := loadBlocksFromTestFile(os.Args[1])
 	if err != nil {
-		panic(err)
+		utils.Fatalf("Could not load blocks: %v", err)
 	}
 
-	runtime.GOMAXPROCS(runtime.NumCPU())
+	chain := memchain()
+	chain.ResetWithGenesisBlock(blocks[0])
+	if err = chain.InsertChain(types.Blocks{blocks[1]}); err != nil {
+		utils.Fatalf("Error: %v", err)
+	} else {
+		fmt.Println("PASS")
+	}
+}
 
-	defer func() {
-		logger.Flush()
-	}()
-
-	utils.HandleInterrupt()
-
-	utils.InitConfig(VmType, ConfigFile, Datadir, "ethblocktest")
-
-	ethereum, err := eth.New(&eth.Config{
-		Name:         p2p.MakeName(ClientIdentifier, Version),
-		KeyStore:     KeyStore,
-		DataDir:      Datadir,
-		LogFile:      LogFile,
-		LogLevel:     LogLevel,
-		LogFormat:    LogFormat,
-		MaxPeers:     MaxPeer,
-		Port:         OutboundPort,
-		NAT:          NAT,
-		KeyRing:      KeyRing,
-		Shh:          true,
-		Dial:         Dial,
-		BootNodes:    BootNodes,
-		NodeKey:      NodeKey,
-		MinerThreads: MinerThreads,
-	})
-
-	utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
-	utils.StartEthereum(ethereum)
-
-	ethereum.ChainManager().ResetWithGenesisBlock(blocks[0])
-
-	// fmt.Println("HURR: ", hex.EncodeToString(ethutil.Encode(blocks[0].RlpData())))
-
-	go ethereum.ChainManager().InsertChain(types.Blocks{blocks[1]})
-	fmt.Println("OK! ")
-	ethereum.WaitForShutdown()
+func memchain() *core.ChainManager {
+	db, err := ethdb.NewMemDatabase()
+	if err != nil {
+		utils.Fatalf("Could not create in-memory database: %v", err)
+	}
+	return core.NewChainManager(db, new(event.TypeMux))
 }
 
 func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) {
@@ -207,9 +137,8 @@ func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) {
 	if err != nil {
 		return
 	}
-	bt := *new(map[string]Test)
-	err = json.Unmarshal(fileContent, &bt)
-	if err != nil {
+	bt := make(map[string]Test)
+	if err = json.Unmarshal(fileContent, &bt); err != nil {
 		return
 	}
 
@@ -272,49 +201,6 @@ func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) {
 	return
 }
 
-func init_vars() {
-	VmType = 0
-	Identifier = ""
-	KeyRing = ""
-	KeyStore = "db"
-	RpcListenAddress = "127.0.0.1"
-	RpcPort = 8545
-	WsPort = 40404
-	StartRpc = true
-	StartWebSockets = false
-	NonInteractive = false
-	GenAddr = false
-	SecretFile = ""
-	ExportDir = ""
-	LogFile = ""
-
-	timeStr := strconv.FormatInt(time.Now().UnixNano(), 10)
-
-	Datadir = path.Join(ethutil.DefaultDataDir(), timeStr)
-	ConfigFile = path.Join(ethutil.DefaultDataDir(), timeStr, "conf.ini")
-
-	DebugFile = ""
-	LogLevel = 5
-	LogFormat = "std"
-	DiffTool = false
-	DiffType = "all"
-	ShowGenesis = false
-	ImportChain = ""
-	Dump = false
-	DumpHash = ""
-	DumpNumber = -1
-	StartMining = false
-	StartJsConsole = false
-	PrintVersion = false
-	MinerThreads = runtime.NumCPU()
-
-	Dial = false
-	OutboundPort = "30303"
-	BootNodes = ""
-	MaxPeer = 1
-
-}
-
 func hex_decode(s string) (res []byte, err error) {
 	return hex.DecodeString(strings.TrimPrefix(s, "0x"))
 }
-- 
cgit v1.2.3


From 73d1ebe244644c2d74a1c0c38a3b339e72140886 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Mon, 9 Mar 2015 22:51:50 +0100
Subject: cmd/utils: add NewApp

---
 cmd/ethereum/main.go |  6 +-----
 cmd/utils/flags.go   | 11 +++++++++++
 2 files changed, 12 insertions(+), 5 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index f12616e17..f5215c587 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -45,12 +45,10 @@ const (
 
 var (
 	clilogger = logger.NewLogger("CLI")
-	app       = cli.NewApp()
+	app       = utils.NewApp(Version, "the go-ethereum command line interface")
 )
 
 func init() {
-	app.Version = Version
-	app.Usage = "the go-ethereum command-line client"
 	app.Action = run
 	app.HideVersion = true // we have a command to print the version
 	app.Commands = []cli.Command{
@@ -107,8 +105,6 @@ runtime will execute the file and exit.
 			Usage:  `import a blockchain file`,
 		},
 	}
-	app.Author = ""
-	app.Email = ""
 	app.Flags = []cli.Flag{
 		utils.BootnodesFlag,
 		utils.DataDirFlag,
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index e6eee20a7..2156963c4 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -19,6 +19,17 @@ import (
 	"github.com/ethereum/go-ethereum/p2p/nat"
 )
 
+// NewApp creates an app with sane defaults.
+func NewApp(version, usage string) *cli.App {
+	app := cli.NewApp()
+	app.Name = path.Base(os.Args[0])
+	app.Author = ""
+	app.Email = ""
+	app.Version = version
+	app.Usage = usage
+	return app
+}
+
 // These are all the command line flags we support.
 // If you add to this list, please remember to include the
 // flag in the appropriate command definition.
-- 
cgit v1.2.3


From a11f1d6a7ec2eaa1a348776072c49019368a5ef3 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Mon, 9 Mar 2015 23:00:27 +0100
Subject: rpc: add dataDir parameter and JSON-RPC handler

---
 cmd/ethereum/main.go |  4 +---
 cmd/utils/cmd.go     | 12 ------------
 cmd/utils/flags.go   | 18 ++++++++++++++++++
 3 files changed, 19 insertions(+), 15 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index f5215c587..4855a3e4a 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -170,9 +170,7 @@ func runjs(ctx *cli.Context) {
 func startEth(ctx *cli.Context, eth *eth.Ethereum) {
 	utils.StartEthereum(eth)
 	if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
-		addr := ctx.GlobalString(utils.RPCListenAddrFlag.Name)
-		port := ctx.GlobalInt(utils.RPCPortFlag.Name)
-		utils.StartRpc(eth, addr, port)
+		utils.StartRPC(eth, ctx)
 	}
 	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
 		eth.Miner().Start()
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 3c3d3955d..79ae7888a 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -34,9 +34,7 @@ import (
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/rlp"
-	rpchttp "github.com/ethereum/go-ethereum/rpc/http"
 	"github.com/ethereum/go-ethereum/state"
-	"github.com/ethereum/go-ethereum/xeth"
 )
 
 var clilogger = logger.NewLogger("CLI")
@@ -165,16 +163,6 @@ func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, Secre
 	clilogger.Infof("Main address %x\n", keyManager.Address())
 }
 
-func StartRpc(ethereum *eth.Ethereum, RpcListenAddress string, RpcPort int) {
-	var err error
-	ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum), RpcListenAddress, RpcPort)
-	if err != nil {
-		clilogger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err)
-	} else {
-		go ethereum.RpcServer.Start()
-	}
-}
-
 func FormatTransactionData(data string) []byte {
 	d := ethutil.StringToByteFunc(data, func(s string) (ret []byte) {
 		slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000)
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 2156963c4..2995ebad8 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -2,6 +2,10 @@ package utils
 
 import (
 	"crypto/ecdsa"
+	"fmt"
+	"net"
+	"net/http"
+	"os"
 	"path"
 	"runtime"
 	"time"
@@ -17,6 +21,8 @@ import (
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/p2p"
 	"github.com/ethereum/go-ethereum/p2p/nat"
+	"github.com/ethereum/go-ethereum/rpc"
+	"github.com/ethereum/go-ethereum/xeth"
 )
 
 // NewApp creates an app with sane defaults.
@@ -183,3 +189,15 @@ func GetAccountManager(ctx *cli.Context) *accounts.Manager {
 	ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
 	return accounts.NewManager(ks, 300*time.Second)
 }
+
+func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
+	addr := ctx.GlobalString(RPCListenAddrFlag.Name)
+	port := ctx.GlobalInt(RPCPortFlag.Name)
+	dataDir := ctx.GlobalString(DataDirFlag.Name)
+
+	l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
+	if err != nil {
+		Fatalf("Can't listen on %s:%d: %v", addr, port, err)
+	}
+	go http.Serve(l, rpc.JSONRPC(xeth.New(eth), dataDir))
+}
-- 
cgit v1.2.3


From 697f6748b8df6b50157f81eb7959d856d3eb688e Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Mon, 9 Mar 2015 23:03:20 +0100
Subject: cmd/mist: use cli library and package accounts

---
 cmd/mist/assets/qml/views/info.qml |  41 ------------
 cmd/mist/bindings.go               |  29 ---------
 cmd/mist/debugger.go               |   8 ++-
 cmd/mist/flags.go                  | 130 -------------------------------------
 cmd/mist/gui.go                    |  53 ++-------------
 cmd/mist/main.go                   | 101 ++++++++++++++--------------
 6 files changed, 58 insertions(+), 304 deletions(-)
 delete mode 100644 cmd/mist/flags.go

(limited to 'cmd')

diff --git a/cmd/mist/assets/qml/views/info.qml b/cmd/mist/assets/qml/views/info.qml
index b2d2f521c..0187bba6d 100644
--- a/cmd/mist/assets/qml/views/info.qml
+++ b/cmd/mist/assets/qml/views/info.qml
@@ -54,7 +54,6 @@ Rectangle {
 			height: 200
 			anchors {
 				left: parent.left
-				right: logLevelSlider.left
 				bottom: parent.bottom
 				top: parent.top
 			}
@@ -107,46 +106,6 @@ Rectangle {
 				}
 			}
 		}
-
-		/*
-		TableView {
-			id: logView
-			headerVisible: false
-			anchors {
-				right: logLevelSlider.left
-				left: parent.left
-				bottom: parent.bottom
-				top: parent.top
-			}
-
-			TableViewColumn{ role: "description" ; title: "log" }
-
-			model: logModel
-		}
-		*/
-
-		Slider {
-			id: logLevelSlider
-			value: gui.getLogLevelInt()
-			anchors {
-				right: parent.right
-				top: parent.top
-				bottom: parent.bottom
-
-				rightMargin: 5
-				leftMargin: 5
-				topMargin: 5
-				bottomMargin: 5
-			}
-
-			orientation: Qt.Vertical
-			maximumValue: 5
-			stepSize: 1
-
-			onValueChanged: {
-				gui.setLogLevel(value)
-			}
-		}
 	}
 
 	property var logModel: ListModel {
diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go
index fd89eb7e2..b473cc985 100644
--- a/cmd/mist/bindings.go
+++ b/cmd/mist/bindings.go
@@ -28,7 +28,6 @@ import (
 	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/ethutil"
-	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/state"
 )
 
@@ -37,18 +36,6 @@ type plugin struct {
 	Path string `json:"path"`
 }
 
-// LogPrint writes to the GUI log.
-func (gui *Gui) LogPrint(level logger.LogLevel, msg string) {
-	/*
-		str := strings.TrimRight(s, "\n")
-		lines := strings.Split(str, "\n")
-
-		view := gui.getObjectByName("infoView")
-		for _, line := range lines {
-			view.Call("addLog", line)
-		}
-	*/
-}
 func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
 	var data string
 	if len(recipient) == 0 {
@@ -64,17 +51,6 @@ func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (strin
 	return gui.xeth.Transact(from, recipient, value, gas, gasPrice, data)
 }
 
-// functions that allow Gui to implement interface guilogger.LogSystem
-func (gui *Gui) SetLogLevel(level logger.LogLevel) {
-	gui.logLevel = level
-	gui.eth.Logger().SetLogLevel(level)
-	gui.config.Save("loglevel", level)
-}
-
-func (gui *Gui) GetLogLevel() logger.LogLevel {
-	return gui.logLevel
-}
-
 func (self *Gui) AddPlugin(pluginPath string) {
 	self.plugins[pluginPath] = plugin{Name: pluginPath, Path: pluginPath}
 
@@ -89,11 +65,6 @@ func (self *Gui) RemovePlugin(pluginPath string) {
 	ethutil.WriteFile(self.eth.DataDir+"/plugins.json", json)
 }
 
-// this extra function needed to give int typecast value to gui widget
-// that sets initial loglevel to default
-func (gui *Gui) GetLogLevelInt() int {
-	return int(gui.logLevel)
-}
 func (self *Gui) DumpState(hash, path string) {
 	var stateDump []byte
 
diff --git a/cmd/mist/debugger.go b/cmd/mist/debugger.go
index c1ab2f3f1..bd8ddde37 100644
--- a/cmd/mist/debugger.go
+++ b/cmd/mist/debugger.go
@@ -137,16 +137,18 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
 		return
 	}
 
+	// TODO: improve this
+	allAccounts, _ := self.lib.eth.AccountManager().Accounts()
+
 	var (
 		gas      = ethutil.Big(gasStr)
 		gasPrice = ethutil.Big(gasPriceStr)
 		value    = ethutil.Big(valueStr)
-		// Contract addr as test address
-		keyPair = self.lib.eth.KeyManager().KeyPair()
+		acc      = allAccounts[0]
 	)
 
 	statedb := self.lib.eth.ChainManager().TransState()
-	account := self.lib.eth.ChainManager().TransState().GetAccount(keyPair.Address())
+	account := self.lib.eth.ChainManager().TransState().GetAccount(acc.Address)
 	contract := statedb.NewStateObject([]byte{0})
 	contract.SetCode(script)
 	contract.SetBalance(value)
diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go
deleted file mode 100644
index 139af5923..000000000
--- a/cmd/mist/flags.go
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-	This file is part of go-ethereum
-
-	go-ethereum is free software: you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation, either version 3 of the License, or
-	(at your option) any later version.
-
-	go-ethereum is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @authors
- * 	Jeffrey Wilcke <i@jev.io>
- */
-package main
-
-import (
-	"crypto/ecdsa"
-	"flag"
-	"fmt"
-	"log"
-	"os"
-	"path"
-	"runtime"
-
-	"github.com/ethereum/go-ethereum/crypto"
-	"github.com/ethereum/go-ethereum/ethutil"
-	"github.com/ethereum/go-ethereum/logger"
-	"github.com/ethereum/go-ethereum/p2p/nat"
-	"github.com/ethereum/go-ethereum/vm"
-)
-
-var (
-	Identifier       string
-	KeyRing          string
-	KeyStore         string
-	StartRpc         bool
-	RpcListenAddress string
-	RpcPort          int
-	OutboundPort     string
-	ShowGenesis      bool
-	AddPeer          string
-	MaxPeer          int
-	GenAddr          bool
-	BootNodes        string
-	NodeKey          *ecdsa.PrivateKey
-	NAT              nat.Interface
-	SecretFile       string
-	ExportDir        string
-	NonInteractive   bool
-	Datadir          string
-	LogFile          string
-	ConfigFile       string
-	DebugFile        string
-	LogLevel         int
-	VmType           int
-	MinerThreads     int
-)
-
-// flags specific to gui client
-var AssetPath string
-var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
-
-func Init() {
-	// TODO: move common flag processing to cmd/utils
-	flag.Usage = func() {
-		fmt.Fprintf(os.Stderr, "%s [options] [filename]:\noptions precedence: default < config file < environment variables < command line\n", os.Args[0])
-		flag.PrintDefaults()
-	}
-
-	flag.IntVar(&VmType, "vm", 0, "Virtual Machine type: 0-1: standard, debug")
-	flag.StringVar(&Identifier, "id", "", "Custom client identifier")
-	flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
-	flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file")
-	flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on")
-	flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
-	flag.BoolVar(&StartRpc, "rpc", true, "start rpc server")
-	flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
-	flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
-	flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
-	flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
-	flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
-	flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
-	flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
-	flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
-	flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5 (= silent,error,warn,info,debug,debug detail)")
-
-	flag.StringVar(&AssetPath, "asset_path", ethutil.DefaultAssetPath(), "absolute path to GUI assets directory")
-
-	// Network stuff
-	var (
-		nodeKeyFile = flag.String("nodekey", "", "network private key file")
-		nodeKeyHex  = flag.String("nodekeyhex", "", "network private key (for testing)")
-		natstr      = flag.String("nat", "any", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
-	)
-	flag.StringVar(&OutboundPort, "port", "30303", "listening port")
-	flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
-	flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
-
-	flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
-
-	flag.Parse()
-
-	var err error
-	if NAT, err = nat.Parse(*natstr); err != nil {
-		log.Fatalf("-nat: %v", err)
-	}
-	switch {
-	case *nodeKeyFile != "" && *nodeKeyHex != "":
-		log.Fatal("Options -nodekey and -nodekeyhex are mutually exclusive")
-	case *nodeKeyFile != "":
-		if NodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil {
-			log.Fatalf("-nodekey: %v", err)
-		}
-	case *nodeKeyHex != "":
-		if NodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil {
-			log.Fatalf("-nodekeyhex: %v", err)
-		}
-	}
-
-	if VmType >= int(vm.MaxVmTy) {
-		log.Fatal("Invalid VM type ", VmType)
-	}
-}
diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go
index bc6e9ed53..e21d6fcea 100644
--- a/cmd/mist/gui.go
+++ b/cmd/mist/gui.go
@@ -23,7 +23,6 @@ package main
 import "C"
 
 import (
-	"bytes"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
@@ -70,20 +69,18 @@ type Gui struct {
 
 	txDb *ethdb.LDBDatabase
 
-	logLevel logger.LogLevel
-	open     bool
+	open bool
 
 	xeth *xeth.XEth
 
 	Session string
-	config  *ethutil.ConfigManager
 
 	plugins map[string]plugin
 }
 
 // Create GUI, but doesn't start it
-func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, session string, logLevel int) *Gui {
-	db, err := ethdb.NewLDBDatabase("tx_database")
+func NewWindow(ethereum *eth.Ethereum) *Gui {
+	db, err := ethdb.NewLDBDatabase(path.Join(ethereum.DataDir, "tx_database"))
 	if err != nil {
 		panic(err)
 	}
@@ -92,10 +89,7 @@ func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, session st
 	gui := &Gui{eth: ethereum,
 		txDb:          db,
 		xeth:          xeth,
-		logLevel:      logger.LogLevel(logLevel),
-		Session:       session,
 		open:          false,
-		config:        config,
 		plugins:       make(map[string]plugin),
 		serviceEvents: make(chan ServEv, 1),
 	}
@@ -142,18 +136,12 @@ func (gui *Gui) Start(assetPath string) {
 	gui.open = true
 	win.Show()
 
-	// only add the gui guilogger after window is shown otherwise slider wont be shown
-	logger.AddLogSystem(gui)
 	win.Wait()
-
-	// need to silence gui guilogger after window closed otherwise logsystem hangs (but do not save loglevel)
-	gui.logLevel = logger.Silence
 	gui.open = false
 }
 
 func (gui *Gui) Stop() {
 	if gui.open {
-		gui.logLevel = logger.Silence
 		gui.open = false
 		gui.win.Hide()
 	}
@@ -172,9 +160,6 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
 	return gui.win, nil
 }
 
-func (gui *Gui) ImportKey(filePath string) {
-}
-
 func (gui *Gui) GenerateKey() {
 	_, err := gui.eth.AccountManager().NewAccount("hurr")
 	if err != nil {
@@ -198,31 +183,11 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
 	return gui.win
 }
 
-func (gui *Gui) ImportAndSetPrivKey(secret string) bool {
-	err := gui.eth.KeyManager().InitFromString(gui.Session, 0, secret)
-	if err != nil {
-		guilogger.Errorln("unable to import: ", err)
-		return false
-	}
-	guilogger.Errorln("successfully imported: ", err)
-	return true
-}
-
-func (gui *Gui) CreateAndSetPrivKey() (string, string, string, string) {
-	err := gui.eth.KeyManager().Init(gui.Session, 0, true)
-	if err != nil {
-		guilogger.Errorln("unable to create key: ", err)
-		return "", "", "", ""
-	}
-	return gui.eth.KeyManager().KeyPair().AsStrings()
-}
-
 func (gui *Gui) setInitialChain(ancientBlocks bool) {
 	sBlk := gui.eth.ChainManager().LastBlockHash()
 	blk := gui.eth.ChainManager().GetBlock(sBlk)
 	for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) {
 		sBlk = blk.ParentHash()
-
 		gui.processBlock(blk, true)
 	}
 }
@@ -266,10 +231,8 @@ func (self *Gui) loadMergedMiningOptions() {
 }
 
 func (gui *Gui) insertTransaction(window string, tx *types.Transaction) {
-	addr := gui.address()
-
 	var inout string
-	if bytes.Compare(tx.From(), addr) == 0 {
+	if gui.eth.AccountManager().HasAccount(tx.From()) {
 		inout = "send"
 	} else {
 		inout = "recv"
@@ -487,14 +450,6 @@ func (gui *Gui) setPeerInfo() {
 	}
 }
 
-func (gui *Gui) privateKey() string {
-	return ethutil.Bytes2Hex(gui.eth.KeyManager().PrivateKey())
-}
-
-func (gui *Gui) address() []byte {
-	return gui.eth.KeyManager().Address()
-}
-
 /*
 func LoadExtension(path string) (uintptr, error) {
 	lib, err := ffi.NewLibrary(path)
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index 1d4403848..425630ece 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -26,10 +26,10 @@ import (
 	"runtime"
 	"time"
 
+	"github.com/codegangsta/cli"
 	"github.com/ethereum/go-ethereum/cmd/utils"
-	"github.com/ethereum/go-ethereum/eth"
+	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
-	"github.com/ethereum/go-ethereum/p2p"
 	"github.com/ethereum/go-ethereum/ui/qt/webengine"
 	"github.com/obscuren/qml"
 )
@@ -39,56 +39,32 @@ const (
 	Version          = "0.8.6"
 )
 
-var ethereum *eth.Ethereum
-var mainlogger = logger.NewLogger("MAIN")
-
-func run() error {
-	webengine.Initialize()
-
-	// precedence: code-internal flag default < config file < environment variables < command line
-	Init() // parsing command line
-
-	tstart := time.Now()
-	config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
-
-	ethereum, err := eth.New(&eth.Config{
-		Name:         p2p.MakeName(ClientIdentifier, Version),
-		KeyStore:     KeyStore,
-		DataDir:      Datadir,
-		LogFile:      LogFile,
-		LogLevel:     LogLevel,
-		MaxPeers:     MaxPeer,
-		Port:         OutboundPort,
-		NAT:          NAT,
-		Shh:          true,
-		BootNodes:    BootNodes,
-		NodeKey:      NodeKey,
-		KeyRing:      KeyRing,
-		Dial:         true,
-		MinerThreads: MinerThreads,
-	})
-	if err != nil {
-		mainlogger.Fatalln(err)
+var (
+	app           = utils.NewApp(Version, "the ether browser")
+	assetPathFlag = cli.StringFlag{
+		Name:  "asset_path",
+		Usage: "absolute path to GUI assets directory",
+		Value: ethutil.DefaultAssetPath(),
 	}
-	utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
+)
 
-	if StartRpc {
-		utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
+func init() {
+	app.Action = run
+	app.Flags = []cli.Flag{
+		assetPathFlag,
+
+		utils.BootnodesFlag,
+		utils.DataDirFlag,
+		utils.ListenPortFlag,
+		utils.LogFileFlag,
+		utils.LogLevelFlag,
+		utils.MaxPeersFlag,
+		utils.MinerThreadsFlag,
+		utils.NATFlag,
+		utils.NodeKeyFileFlag,
+		utils.RPCListenAddrFlag,
+		utils.RPCPortFlag,
 	}
-
-	gui := NewWindow(ethereum, config, KeyRing, LogLevel)
-
-	utils.RegisterInterrupt(func(os.Signal) {
-		gui.Stop()
-	})
-	go utils.StartEthereum(ethereum)
-
-	fmt.Println("ETH stack took", time.Since(tstart))
-
-	// gui blocks the main thread
-	gui.Start(AssetPath)
-
-	return nil
 }
 
 func main() {
@@ -97,15 +73,16 @@ func main() {
 	// This is a bit of a cheat, but ey!
 	os.Setenv("QTWEBKIT_INSPECTOR_SERVER", "127.0.0.1:99999")
 
-	qml.Run(run)
-
 	var interrupted = false
 	utils.RegisterInterrupt(func(os.Signal) {
 		interrupted = true
 	})
-
 	utils.HandleInterrupt()
 
+	if err := app.Run(os.Args); err != nil {
+		fmt.Fprintln(os.Stderr, "Error: ", err)
+	}
+
 	// we need to run the interrupt callbacks in case gui is closed
 	// this skips if we got here by actual interrupt stopping the GUI
 	if !interrupted {
@@ -113,3 +90,23 @@ func main() {
 	}
 	logger.Flush()
 }
+
+func run(ctx *cli.Context) {
+	tstart := time.Now()
+
+	// TODO: show qml popup instead of exiting if initialization fails.
+	ethereum := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	utils.StartRPC(ethereum, ctx)
+	go utils.StartEthereum(ethereum)
+	fmt.Println("initializing eth stack took", time.Since(tstart))
+
+	// Open the window
+	qml.Run(func() error {
+		webengine.Initialize()
+		gui := NewWindow(ethereum)
+		utils.RegisterInterrupt(func(os.Signal) { gui.Stop() })
+		// gui blocks the main thread
+		gui.Start(ctx.GlobalString(assetPathFlag.Name))
+		return nil
+	})
+}
-- 
cgit v1.2.3


From cd51860bf024d949a09b3863c88a278a386227a7 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Mon, 9 Mar 2015 23:06:04 +0100
Subject: cmd/utils: delete InitConfig, KeyTasks

---
 cmd/utils/cmd.go | 40 ----------------------------------------
 1 file changed, 40 deletions(-)

(limited to 'cmd')

diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 79ae7888a..271a879c7 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -29,7 +29,6 @@ import (
 
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/types"
-	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
@@ -96,14 +95,6 @@ func initDataDir(Datadir string) {
 	}
 }
 
-func InitConfig(vmType int, ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager {
-	initDataDir(Datadir)
-	cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
-	cfg.VmType = vmType
-
-	return cfg
-}
-
 func exit(err error) {
 	status := 0
 	if err != nil {
@@ -132,37 +123,6 @@ func StartEthereum(ethereum *eth.Ethereum) {
 	})
 }
 
-func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
-	var err error
-	switch {
-	case GenAddr:
-		if NonInteractive || confirm("This action overwrites your old private key.") {
-			err = keyManager.Init(KeyRing, 0, true)
-		}
-		exit(err)
-	case len(SecretFile) > 0:
-		SecretFile = ethutil.ExpandHomePath(SecretFile)
-
-		if NonInteractive || confirm("This action overwrites your old private key.") {
-			err = keyManager.InitFromSecretsFile(KeyRing, 0, SecretFile)
-		}
-		exit(err)
-	case len(ExportDir) > 0:
-		err = keyManager.Init(KeyRing, 0, false)
-		if err == nil {
-			err = keyManager.Export(ExportDir)
-		}
-		exit(err)
-	default:
-		// Creates a keypair if none exists
-		err = keyManager.Init(KeyRing, 0, false)
-		if err != nil {
-			exit(err)
-		}
-	}
-	clilogger.Infof("Main address %x\n", keyManager.Address())
-}
-
 func FormatTransactionData(data string) []byte {
 	d := ethutil.StringToByteFunc(data, func(s string) (ret []byte) {
 		slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000)
-- 
cgit v1.2.3


From 487f68ec4892794cb994cffd95d5bc2bf3052d3e Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 00:09:39 +0100
Subject: accounts: add {Timed,}Unlock, remove SignLocked

---
 cmd/utils/flags.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'cmd')

diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index ee7ea4c79..cde5fa024 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -8,7 +8,6 @@ import (
 	"os"
 	"path"
 	"runtime"
-	"time"
 
 	"github.com/codegangsta/cli"
 	"github.com/ethereum/go-ethereum/accounts"
@@ -199,7 +198,7 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database, ethutil.D
 func GetAccountManager(ctx *cli.Context) *accounts.Manager {
 	dataDir := ctx.GlobalString(DataDirFlag.Name)
 	ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
-	return accounts.NewManager(ks, 300*time.Second)
+	return accounts.NewManager(ks)
 }
 
 func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
-- 
cgit v1.2.3


From d1e04f7388ec29b009d646e20570393a5851f54d Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 00:24:11 +0100
Subject: cmd/ethereum: allow multiple js files

---
 cmd/ethereum/main.go | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 1ae8e46a2..d0edef81d 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -159,13 +159,13 @@ func runjs(ctx *cli.Context) {
 	startEth(ctx, eth)
 	if len(ctx.Args()) == 0 {
 		runREPL(eth)
-		eth.Stop()
-		eth.WaitForShutdown()
-	} else if len(ctx.Args()) == 1 {
-		execJsFile(eth, ctx.Args()[0])
 	} else {
-		utils.Fatalf("This command can handle at most one argument.")
+		for _, file := range ctx.Args() {
+			execJsFile(eth, file)
+		}
 	}
+	eth.Stop()
+	eth.WaitForShutdown()
 }
 
 func startEth(ctx *cli.Context, eth *eth.Ethereum) {
-- 
cgit v1.2.3


From 9f0e3bd286472f85ab2457fc19cd48cdf12df110 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 02:00:57 +0100
Subject: cmd/ethereum: unlock accounts on JS REPL

---
 cmd/ethereum/js.go   | 210 ++++++++++++++++++++++++++-------------------------
 cmd/ethereum/main.go |   5 +-
 2 files changed, 111 insertions(+), 104 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/js.go b/cmd/ethereum/js.go
index e3165d3f5..96e292733 100644
--- a/cmd/ethereum/js.go
+++ b/cmd/ethereum/js.go
@@ -22,11 +22,9 @@ import (
 	"fmt"
 	"io/ioutil"
 	"os"
-	"os/signal"
 	"path"
 	"strings"
 
-	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/ethutil"
@@ -37,94 +35,96 @@ import (
 	"github.com/peterh/liner"
 )
 
-func execJsFile(ethereum *eth.Ethereum, filename string) {
-	file, err := os.Open(filename)
-	if err != nil {
-		utils.Fatalf("%v", err)
-	}
-	content, err := ioutil.ReadAll(file)
-	if err != nil {
-		utils.Fatalf("%v", err)
-	}
-	re := javascript.NewJSRE(xeth.New(ethereum, nil))
-	if _, err := re.Run(string(content)); err != nil {
-		utils.Fatalf("Javascript Error: %v", err)
-	}
+type prompter interface {
+	AppendHistory(string)
+	Prompt(p string) (string, error)
+	PasswordPrompt(p string) (string, error)
+}
+
+type dumbPrompter struct{ r *bufio.Reader }
+
+func (r dumbPrompter) Prompt(p string) (string, error) {
+	fmt.Print(p)
+	return r.r.ReadString('\n')
 }
 
-type repl struct {
+func (r dumbPrompter) PasswordPrompt(p string) (string, error) {
+	fmt.Println("!! Unsupported terminal, password will echo.")
+	fmt.Print(p)
+	input, err := bufio.NewReader(os.Stdin).ReadString('\n')
+	fmt.Println()
+	return input, err
+}
+
+func (r dumbPrompter) AppendHistory(string) {}
+
+type jsre struct {
 	re       *javascript.JSRE
 	ethereum *eth.Ethereum
 	xeth     *xeth.XEth
-	prompt   string
-	lr       *liner.State
+	ps1      string
+	prompter
 }
 
-func runREPL(ethereum *eth.Ethereum) {
-	xeth := xeth.New(ethereum, nil)
-	repl := &repl{
-		re:       javascript.NewJSRE(xeth),
-		xeth:     xeth,
-		ethereum: ethereum,
-		prompt:   "> ",
-	}
-	repl.initStdFuncs()
+func newJSRE(ethereum *eth.Ethereum) *jsre {
+	js := &jsre{ethereum: ethereum, ps1: "> "}
+	js.xeth = xeth.New(ethereum, js)
+	js.re = javascript.NewJSRE(js.xeth)
+	js.initStdFuncs()
+
 	if !liner.TerminalSupported() {
-		repl.dumbRead()
+		js.prompter = dumbPrompter{bufio.NewReader(os.Stdin)}
 	} else {
 		lr := liner.NewLiner()
-		defer lr.Close()
 		lr.SetCtrlCAborts(true)
-		repl.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
-		repl.read(lr)
-		repl.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
+		defer lr.Close()
+		js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
+		defer js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
+		js.prompter = lr
 	}
+	return js
 }
 
-func (self *repl) withHistory(op func(*os.File)) {
-	hist, err := os.OpenFile(path.Join(self.ethereum.DataDir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
-	if err != nil {
-		fmt.Printf("unable to open history file: %v\n", err)
-		return
-	}
-	op(hist)
-	hist.Close()
+func (self *jsre) ConfirmTransaction(tx *types.Transaction) bool {
+	p := fmt.Sprintf("Confirm Transaction %v\n[y/n] ", tx)
+	answer, _ := self.prompter.Prompt(p)
+	return strings.HasPrefix(strings.Trim(answer, " "), "y")
 }
 
-func (self *repl) parseInput(code string) {
-	defer func() {
-		if r := recover(); r != nil {
-			fmt.Println("[native] error", r)
-		}
-	}()
-	value, err := self.re.Run(code)
+func (self *jsre) UnlockAccount(addr []byte) bool {
+	fmt.Printf("Please unlock account %x.\n", addr)
+	pass, err := self.prompter.PasswordPrompt("Passphrase: ")
 	if err != nil {
-		fmt.Println(err)
-		return
+		return false
+	}
+	// TODO: allow retry
+	if err := self.ethereum.AccountManager().Unlock(addr, pass); err != nil {
+		fmt.Println("Unlocking failed: ", err)
+		return false
+	} else {
+		fmt.Println("Account is now unlocked for this session.")
+		return true
 	}
-	self.printValue(value)
 }
 
-var indentCount = 0
-var str = ""
-
-func (self *repl) setIndent() {
-	open := strings.Count(str, "{")
-	open += strings.Count(str, "(")
-	closed := strings.Count(str, "}")
-	closed += strings.Count(str, ")")
-	indentCount = open - closed
-	if indentCount <= 0 {
-		self.prompt = "> "
-	} else {
-		self.prompt = strings.Join(make([]string, indentCount*2), "..")
-		self.prompt += " "
+func (self *jsre) exec(filename string) error {
+	file, err := os.Open(filename)
+	if err != nil {
+		return err
+	}
+	content, err := ioutil.ReadAll(file)
+	if err != nil {
+		return err
 	}
+	if _, err := self.re.Run(string(content)); err != nil {
+		return fmt.Errorf("Javascript Error: %v", err)
+	}
+	return nil
 }
 
-func (self *repl) read(lr *liner.State) {
+func (self *jsre) interactive() {
 	for {
-		input, err := lr.Prompt(self.prompt)
+		input, err := self.prompter.Prompt(self.ps1)
 		if err != nil {
 			return
 		}
@@ -138,49 +138,55 @@ func (self *repl) read(lr *liner.State) {
 				return
 			}
 			hist := str[:len(str)-1]
-			lr.AppendHistory(hist)
+			self.prompter.AppendHistory(hist)
 			self.parseInput(str)
 			str = ""
 		}
 	}
 }
 
-func (self *repl) dumbRead() {
-	fmt.Println("Unsupported terminal, line editing will not work.")
-
-	// process lines
-	readDone := make(chan struct{})
-	go func() {
-		r := bufio.NewReader(os.Stdin)
-	loop:
-		for {
-			fmt.Print(self.prompt)
-			line, err := r.ReadString('\n')
-			switch {
-			case err != nil || line == "exit":
-				break loop
-			case line == "":
-				continue
-			default:
-				self.parseInput(line + "\n")
-			}
+func (self *jsre) withHistory(op func(*os.File)) {
+	hist, err := os.OpenFile(path.Join(self.ethereum.DataDir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
+	if err != nil {
+		fmt.Printf("unable to open history file: %v\n", err)
+		return
+	}
+	op(hist)
+	hist.Close()
+}
+
+func (self *jsre) parseInput(code string) {
+	defer func() {
+		if r := recover(); r != nil {
+			fmt.Println("[native] error", r)
 		}
-		close(readDone)
 	}()
+	value, err := self.re.Run(code)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	self.printValue(value)
+}
 
-	// wait for Ctrl-C
-	sigc := make(chan os.Signal, 1)
-	signal.Notify(sigc, os.Interrupt, os.Kill)
-	defer signal.Stop(sigc)
+var indentCount = 0
+var str = ""
 
-	select {
-	case <-readDone:
-	case <-sigc:
-		os.Stdin.Close() // terminate read
+func (self *jsre) setIndent() {
+	open := strings.Count(str, "{")
+	open += strings.Count(str, "(")
+	closed := strings.Count(str, "}")
+	closed += strings.Count(str, ")")
+	indentCount = open - closed
+	if indentCount <= 0 {
+		self.ps1 = "> "
+	} else {
+		self.ps1 = strings.Join(make([]string, indentCount*2), "..")
+		self.ps1 += " "
 	}
 }
 
-func (self *repl) printValue(v interface{}) {
+func (self *jsre) printValue(v interface{}) {
 	method, _ := self.re.Vm.Get("prettyPrint")
 	v, err := self.re.Vm.ToValue(v)
 	if err == nil {
@@ -191,7 +197,7 @@ func (self *repl) printValue(v interface{}) {
 	}
 }
 
-func (self *repl) initStdFuncs() {
+func (self *jsre) initStdFuncs() {
 	t, _ := self.re.Vm.Get("eth")
 	eth := t.Object()
 	eth.Set("connect", self.connect)
@@ -205,7 +211,7 @@ func (self *repl) initStdFuncs() {
  * The following methods are natively implemented javascript functions.
  */
 
-func (self *repl) dump(call otto.FunctionCall) otto.Value {
+func (self *jsre) dump(call otto.FunctionCall) otto.Value {
 	var block *types.Block
 
 	if len(call.ArgumentList) > 0 {
@@ -236,17 +242,17 @@ func (self *repl) dump(call otto.FunctionCall) otto.Value {
 	return v
 }
 
-func (self *repl) stopMining(call otto.FunctionCall) otto.Value {
+func (self *jsre) stopMining(call otto.FunctionCall) otto.Value {
 	self.xeth.Miner().Stop()
 	return otto.TrueValue()
 }
 
-func (self *repl) startMining(call otto.FunctionCall) otto.Value {
+func (self *jsre) startMining(call otto.FunctionCall) otto.Value {
 	self.xeth.Miner().Start()
 	return otto.TrueValue()
 }
 
-func (self *repl) connect(call otto.FunctionCall) otto.Value {
+func (self *jsre) connect(call otto.FunctionCall) otto.Value {
 	nodeURL, err := call.Argument(0).ToString()
 	if err != nil {
 		return otto.FalseValue()
@@ -257,7 +263,7 @@ func (self *repl) connect(call otto.FunctionCall) otto.Value {
 	return otto.TrueValue()
 }
 
-func (self *repl) export(call otto.FunctionCall) otto.Value {
+func (self *jsre) export(call otto.FunctionCall) otto.Value {
 	if len(call.ArgumentList) == 0 {
 		fmt.Println("err: require file name")
 		return otto.FalseValue()
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index d0edef81d..1703c02bb 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -157,11 +157,12 @@ func run(ctx *cli.Context) {
 func runjs(ctx *cli.Context) {
 	eth := utils.GetEthereum(ClientIdentifier, Version, ctx)
 	startEth(ctx, eth)
+	repl := newJSRE(eth)
 	if len(ctx.Args()) == 0 {
-		runREPL(eth)
+		repl.interactive()
 	} else {
 		for _, file := range ctx.Args() {
-			execJsFile(eth, file)
+			repl.exec(file)
 		}
 	}
 	eth.Stop()
-- 
cgit v1.2.3


From ae38871a54b1ccb51346ce5d99beb863b7febe66 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 02:33:59 +0100
Subject: cmd/ethereum: remove "prompter" in identifiers

---
 cmd/ethereum/js.go | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/js.go b/cmd/ethereum/js.go
index 96e292733..de73e83a2 100644
--- a/cmd/ethereum/js.go
+++ b/cmd/ethereum/js.go
@@ -41,14 +41,14 @@ type prompter interface {
 	PasswordPrompt(p string) (string, error)
 }
 
-type dumbPrompter struct{ r *bufio.Reader }
+type dumbterm struct{ r *bufio.Reader }
 
-func (r dumbPrompter) Prompt(p string) (string, error) {
+func (r dumbterm) Prompt(p string) (string, error) {
 	fmt.Print(p)
 	return r.r.ReadString('\n')
 }
 
-func (r dumbPrompter) PasswordPrompt(p string) (string, error) {
+func (r dumbterm) PasswordPrompt(p string) (string, error) {
 	fmt.Println("!! Unsupported terminal, password will echo.")
 	fmt.Print(p)
 	input, err := bufio.NewReader(os.Stdin).ReadString('\n')
@@ -56,13 +56,14 @@ func (r dumbPrompter) PasswordPrompt(p string) (string, error) {
 	return input, err
 }
 
-func (r dumbPrompter) AppendHistory(string) {}
+func (r dumbterm) AppendHistory(string) {}
 
 type jsre struct {
 	re       *javascript.JSRE
 	ethereum *eth.Ethereum
 	xeth     *xeth.XEth
 	ps1      string
+
 	prompter
 }
 
@@ -73,7 +74,7 @@ func newJSRE(ethereum *eth.Ethereum) *jsre {
 	js.initStdFuncs()
 
 	if !liner.TerminalSupported() {
-		js.prompter = dumbPrompter{bufio.NewReader(os.Stdin)}
+		js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
 	} else {
 		lr := liner.NewLiner()
 		lr.SetCtrlCAborts(true)
@@ -87,13 +88,13 @@ func newJSRE(ethereum *eth.Ethereum) *jsre {
 
 func (self *jsre) ConfirmTransaction(tx *types.Transaction) bool {
 	p := fmt.Sprintf("Confirm Transaction %v\n[y/n] ", tx)
-	answer, _ := self.prompter.Prompt(p)
+	answer, _ := self.Prompt(p)
 	return strings.HasPrefix(strings.Trim(answer, " "), "y")
 }
 
 func (self *jsre) UnlockAccount(addr []byte) bool {
 	fmt.Printf("Please unlock account %x.\n", addr)
-	pass, err := self.prompter.PasswordPrompt("Passphrase: ")
+	pass, err := self.PasswordPrompt("Passphrase: ")
 	if err != nil {
 		return false
 	}
@@ -124,7 +125,7 @@ func (self *jsre) exec(filename string) error {
 
 func (self *jsre) interactive() {
 	for {
-		input, err := self.prompter.Prompt(self.ps1)
+		input, err := self.Prompt(self.ps1)
 		if err != nil {
 			return
 		}
@@ -138,7 +139,7 @@ func (self *jsre) interactive() {
 				return
 			}
 			hist := str[:len(str)-1]
-			self.prompter.AppendHistory(hist)
+			self.AppendHistory(hist)
 			self.parseInput(str)
 			str = ""
 		}
-- 
cgit v1.2.3


From 80985f97da8174576ee227909035a364af2fd6c9 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 02:35:46 +0100
Subject: cmd/evm, core, ethdb, state, tests/helper: remove ReadConfig calls

---
 cmd/evm/main.go | 2 --
 1 file changed, 2 deletions(-)

(limited to 'cmd')

diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index d6a93460e..960558bb4 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -59,8 +59,6 @@ func main() {
 
 	logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(*loglevel)))
 
-	ethutil.ReadConfig("/tmp/evmtest", "/tmp/evm", "")
-
 	db, _ := ethdb.NewMemDatabase()
 	statedb := state.New(nil, db)
 	sender := statedb.NewStateObject([]byte("sender"))
-- 
cgit v1.2.3


From 0395c174ca5221dd936c19143ced454dac56d54a Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 14:31:54 +0100
Subject: cmd/ethereum: fix line editing setup and history

---
 cmd/ethereum/js.go | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/js.go b/cmd/ethereum/js.go
index de73e83a2..5432fb9b1 100644
--- a/cmd/ethereum/js.go
+++ b/cmd/ethereum/js.go
@@ -63,6 +63,7 @@ type jsre struct {
 	ethereum *eth.Ethereum
 	xeth     *xeth.XEth
 	ps1      string
+	atexit   func()
 
 	prompter
 }
@@ -77,11 +78,13 @@ func newJSRE(ethereum *eth.Ethereum) *jsre {
 		js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
 	} else {
 		lr := liner.NewLiner()
-		lr.SetCtrlCAborts(true)
-		defer lr.Close()
 		js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
-		defer js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
+		lr.SetCtrlCAborts(true)
 		js.prompter = lr
+		js.atexit = func() {
+			js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
+			lr.Close()
+		}
 	}
 	return js
 }
@@ -100,7 +103,6 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
 	}
 	// TODO: allow retry
 	if err := self.ethereum.AccountManager().Unlock(addr, pass); err != nil {
-		fmt.Println("Unlocking failed: ", err)
 		return false
 	} else {
 		fmt.Println("Account is now unlocked for this session.")
@@ -127,7 +129,7 @@ func (self *jsre) interactive() {
 	for {
 		input, err := self.Prompt(self.ps1)
 		if err != nil {
-			return
+			break
 		}
 		if input == "" {
 			continue
@@ -136,7 +138,7 @@ func (self *jsre) interactive() {
 		self.setIndent()
 		if indentCount <= 0 {
 			if input == "exit" {
-				return
+				break
 			}
 			hist := str[:len(str)-1]
 			self.AppendHistory(hist)
@@ -144,6 +146,9 @@ func (self *jsre) interactive() {
 			str = ""
 		}
 	}
+	if self.atexit != nil {
+		self.atexit()
+	}
 }
 
 func (self *jsre) withHistory(op func(*os.File)) {
-- 
cgit v1.2.3


From c3f94a4341056d36ec9f42dd80702ec7ec6986af Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 15:42:25 +0100
Subject: cmd/utils: remove extra space in fatal error message

---
 cmd/utils/cmd.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'cmd')

diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index a802a08da..c5568948d 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -98,7 +98,7 @@ func initDataDir(Datadir string) {
 func exit(err error) {
 	status := 0
 	if err != nil {
-		fmt.Fprintln(os.Stderr, "Fatal: ", err)
+		fmt.Fprintln(os.Stderr, "Fatal:", err)
 		status = 1
 	}
 	logger.Flush()
-- 
cgit v1.2.3


From 0bb7377ebee69c3467c21d355dd24945d0becad5 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 15:44:05 +0100
Subject: cmd/ethereum: show more helpful message if no accounts exist

---
 cmd/ethereum/main.go | 19 +++++++++++++++++--
 cmd/mist/main.go     |  5 ++++-
 cmd/utils/flags.go   |  8 ++------
 3 files changed, 23 insertions(+), 9 deletions(-)

(limited to 'cmd')

diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 1703c02bb..8beba471a 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -29,6 +29,7 @@ import (
 	"time"
 
 	"github.com/codegangsta/cli"
+	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/cmd/utils"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/eth"
@@ -148,14 +149,28 @@ func main() {
 func run(ctx *cli.Context) {
 	fmt.Printf("Welcome to the FRONTIER\n")
 	utils.HandleInterrupt()
-	eth := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	if err == accounts.ErrNoKeys {
+		utils.Fatalf(`No accounts configured.
+Please run 'ethereum account new' to create a new account.`)
+	} else if err != nil {
+		utils.Fatalf("%v", err)
+	}
+
 	startEth(ctx, eth)
 	// this blocks the thread
 	eth.WaitForShutdown()
 }
 
 func runjs(ctx *cli.Context) {
-	eth := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	if err == accounts.ErrNoKeys {
+		utils.Fatalf(`No accounts configured.
+Please run 'ethereum account new' to create a new account.`)
+	} else if err != nil {
+		utils.Fatalf("%v", err)
+	}
+
 	startEth(ctx, eth)
 	repl := newJSRE(eth)
 	if len(ctx.Args()) == 0 {
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index c27f1dba9..9a773e33a 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -95,7 +95,10 @@ func run(ctx *cli.Context) {
 	tstart := time.Now()
 
 	// TODO: show qml popup instead of exiting if initialization fails.
-	ethereum := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	ethereum, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
+	if err != nil {
+		utils.Fatalf("%v", err)
+	}
 	utils.StartRPC(ethereum, ctx)
 	go utils.StartEthereum(ethereum)
 	fmt.Println("initializing eth stack took", time.Since(tstart))
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index cde5fa024..97d312dd4 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -157,8 +157,8 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
 	return key
 }
 
-func GetEthereum(clientID, version string, ctx *cli.Context) *eth.Ethereum {
-	ethereum, err := eth.New(&eth.Config{
+func GetEthereum(clientID, version string, ctx *cli.Context) (*eth.Ethereum, error) {
+	return eth.New(&eth.Config{
 		Name:           p2p.MakeName(clientID, version),
 		DataDir:        ctx.GlobalString(DataDirFlag.Name),
 		LogFile:        ctx.GlobalString(LogFileFlag.Name),
@@ -175,10 +175,6 @@ func GetEthereum(clientID, version string, ctx *cli.Context) *eth.Ethereum {
 		Dial:           true,
 		BootNodes:      ctx.GlobalString(BootnodesFlag.Name),
 	})
-	if err != nil {
-		exit(err)
-	}
-	return ethereum
 }
 
 func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database, ethutil.Database) {
-- 
cgit v1.2.3


From 221fae411278825dcaa0ec4058f065752046869b Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 16:44:22 +0100
Subject: cmd/ethereum: show some help before prompting for encryption
 passphrase

---
 cmd/ethereum/main.go | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'cmd')

diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 8beba471a..ed17fcc1f 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -186,6 +186,7 @@ Please run 'ethereum account new' to create a new account.`)
 
 func startEth(ctx *cli.Context, eth *eth.Ethereum) {
 	utils.StartEthereum(eth)
+	// Start auxiliary services if enabled.
 	if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
 		utils.StartRPC(eth, ctx)
 	}
@@ -207,6 +208,8 @@ func accountList(ctx *cli.Context) {
 
 func accountCreate(ctx *cli.Context) {
 	am := utils.GetAccountManager(ctx)
+	fmt.Println("The new account will be encrypted with a passphrase.")
+	fmt.Println("Please enter a passphrase now.")
 	auth, err := readPassword("Passphrase: ", true)
 	if err != nil {
 		utils.Fatalf("%v", err)
-- 
cgit v1.2.3


From 972e2c1e31067a9bab77228c19348b66964ce643 Mon Sep 17 00:00:00 2001
From: Felix Lange <fjl@twurst.com>
Date: Tue, 10 Mar 2015 16:44:48 +0100
Subject: cmd/utils: improve CLI help templates

Help for a specific command now shows available subcommands.
---
 cmd/utils/flags.go | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

(limited to 'cmd')

diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 97d312dd4..e945a32ee 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -24,11 +24,38 @@ import (
 	"github.com/ethereum/go-ethereum/xeth"
 )
 
+func init() {
+	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
+
+VERSION:
+   {{.Version}}
+
+COMMANDS:
+   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
+   {{end}}{{if .Flags}}
+GLOBAL OPTIONS:
+   {{range .Flags}}{{.}}
+   {{end}}{{end}}
+`
+
+	cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...]
+{{if .Description}}{{.Description}}
+{{end}}{{if .Subcommands}}
+SUBCOMMANDS:
+	{{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
+	{{end}}{{end}}{{if .Flags}}
+OPTIONS:
+	{{range .Flags}}{{.}}
+	{{end}}{{end}}
+`
+}
+
 // NewApp creates an app with sane defaults.
 func NewApp(version, usage string) *cli.App {
 	app := cli.NewApp()
 	app.Name = path.Base(os.Args[0])
 	app.Author = ""
+	app.Authors = nil
 	app.Email = ""
 	app.Version = version
 	app.Usage = usage
-- 
cgit v1.2.3