cmd/mist: use cli library and package accounts

This commit is contained in:
Felix Lange 2015-03-09 23:03:20 +01:00
parent c2e5dacf55
commit 697f6748b8
6 changed files with 58 additions and 304 deletions

View File

@ -54,7 +54,6 @@ Rectangle {
height: 200 height: 200
anchors { anchors {
left: parent.left left: parent.left
right: logLevelSlider.left
bottom: parent.bottom bottom: parent.bottom
top: parent.top 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 { property var logModel: ListModel {

View File

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "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/ethutil" "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/state"
) )
@ -37,18 +36,6 @@ type plugin struct {
Path string `json:"path"` 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) { func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
var data string var data string
if len(recipient) == 0 { 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) 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) { func (self *Gui) AddPlugin(pluginPath string) {
self.plugins[pluginPath] = plugin{Name: pluginPath, Path: pluginPath} 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) 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) { func (self *Gui) DumpState(hash, path string) {
var stateDump []byte var stateDump []byte

View File

@ -137,16 +137,18 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
return return
} }
// TODO: improve this
allAccounts, _ := self.lib.eth.AccountManager().Accounts()
var ( var (
gas = ethutil.Big(gasStr) gas = ethutil.Big(gasStr)
gasPrice = ethutil.Big(gasPriceStr) gasPrice = ethutil.Big(gasPriceStr)
value = ethutil.Big(valueStr) value = ethutil.Big(valueStr)
// Contract addr as test address acc = allAccounts[0]
keyPair = self.lib.eth.KeyManager().KeyPair()
) )
statedb := self.lib.eth.ChainManager().TransState() 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 := statedb.NewStateObject([]byte{0})
contract.SetCode(script) contract.SetCode(script)
contract.SetBalance(value) contract.SetBalance(value)

View File

@ -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)
}
}

View File

@ -23,7 +23,6 @@ package main
import "C" import "C"
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -70,20 +69,18 @@ type Gui struct {
txDb *ethdb.LDBDatabase txDb *ethdb.LDBDatabase
logLevel logger.LogLevel open bool
open bool
xeth *xeth.XEth xeth *xeth.XEth
Session string Session string
config *ethutil.ConfigManager
plugins map[string]plugin plugins map[string]plugin
} }
// Create GUI, but doesn't start it // Create GUI, but doesn't start it
func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, session string, logLevel int) *Gui { func NewWindow(ethereum *eth.Ethereum) *Gui {
db, err := ethdb.NewLDBDatabase("tx_database") db, err := ethdb.NewLDBDatabase(path.Join(ethereum.DataDir, "tx_database"))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -92,10 +89,7 @@ func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, session st
gui := &Gui{eth: ethereum, gui := &Gui{eth: ethereum,
txDb: db, txDb: db,
xeth: xeth, xeth: xeth,
logLevel: logger.LogLevel(logLevel),
Session: session,
open: false, open: false,
config: config,
plugins: make(map[string]plugin), plugins: make(map[string]plugin),
serviceEvents: make(chan ServEv, 1), serviceEvents: make(chan ServEv, 1),
} }
@ -142,18 +136,12 @@ func (gui *Gui) Start(assetPath string) {
gui.open = true gui.open = true
win.Show() win.Show()
// only add the gui guilogger after window is shown otherwise slider wont be shown
logger.AddLogSystem(gui)
win.Wait() 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 gui.open = false
} }
func (gui *Gui) Stop() { func (gui *Gui) Stop() {
if gui.open { if gui.open {
gui.logLevel = logger.Silence
gui.open = false gui.open = false
gui.win.Hide() gui.win.Hide()
} }
@ -172,9 +160,6 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
return gui.win, nil return gui.win, nil
} }
func (gui *Gui) ImportKey(filePath string) {
}
func (gui *Gui) GenerateKey() { func (gui *Gui) GenerateKey() {
_, err := gui.eth.AccountManager().NewAccount("hurr") _, err := gui.eth.AccountManager().NewAccount("hurr")
if err != nil { if err != nil {
@ -198,31 +183,11 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
return gui.win 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) { func (gui *Gui) setInitialChain(ancientBlocks bool) {
sBlk := gui.eth.ChainManager().LastBlockHash() sBlk := gui.eth.ChainManager().LastBlockHash()
blk := gui.eth.ChainManager().GetBlock(sBlk) blk := gui.eth.ChainManager().GetBlock(sBlk)
for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) { for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) {
sBlk = blk.ParentHash() sBlk = blk.ParentHash()
gui.processBlock(blk, true) gui.processBlock(blk, true)
} }
} }
@ -266,10 +231,8 @@ func (self *Gui) loadMergedMiningOptions() {
} }
func (gui *Gui) insertTransaction(window string, tx *types.Transaction) { func (gui *Gui) insertTransaction(window string, tx *types.Transaction) {
addr := gui.address()
var inout string var inout string
if bytes.Compare(tx.From(), addr) == 0 { if gui.eth.AccountManager().HasAccount(tx.From()) {
inout = "send" inout = "send"
} else { } else {
inout = "recv" 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) { func LoadExtension(path string) (uintptr, error) {
lib, err := ffi.NewLibrary(path) lib, err := ffi.NewLibrary(path)

View File

@ -26,10 +26,10 @@ import (
"runtime" "runtime"
"time" "time"
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils" "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/logger"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/ui/qt/webengine" "github.com/ethereum/go-ethereum/ui/qt/webengine"
"github.com/obscuren/qml" "github.com/obscuren/qml"
) )
@ -39,56 +39,32 @@ const (
Version = "0.8.6" Version = "0.8.6"
) )
var ethereum *eth.Ethereum var (
var mainlogger = logger.NewLogger("MAIN") app = utils.NewApp(Version, "the ether browser")
assetPathFlag = cli.StringFlag{
func run() error { Name: "asset_path",
webengine.Initialize() Usage: "absolute path to GUI assets directory",
Value: ethutil.DefaultAssetPath(),
// 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)
} }
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) )
if StartRpc { func init() {
utils.StartRpc(ethereum, RpcListenAddress, RpcPort) 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() { func main() {
@ -97,15 +73,16 @@ func main() {
// This is a bit of a cheat, but ey! // This is a bit of a cheat, but ey!
os.Setenv("QTWEBKIT_INSPECTOR_SERVER", "127.0.0.1:99999") os.Setenv("QTWEBKIT_INSPECTOR_SERVER", "127.0.0.1:99999")
qml.Run(run)
var interrupted = false var interrupted = false
utils.RegisterInterrupt(func(os.Signal) { utils.RegisterInterrupt(func(os.Signal) {
interrupted = true interrupted = true
}) })
utils.HandleInterrupt() 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 // we need to run the interrupt callbacks in case gui is closed
// this skips if we got here by actual interrupt stopping the GUI // this skips if we got here by actual interrupt stopping the GUI
if !interrupted { if !interrupted {
@ -113,3 +90,23 @@ func main() {
} }
logger.Flush() 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
})
}