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 . -*/ -/** - * @authors - * Jeffrey Wilcke - */ -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:)") - ) - 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(ð.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 + }) +}