Merge branch 'develop'

This commit is contained in:
obscuren 2014-05-30 16:58:17 +02:00
commit 5f28013f79
10 changed files with 1002 additions and 1043 deletions

View File

@ -27,20 +27,22 @@ General command line options
``` ```
Shared between ethereum and ethereal Shared between ethereum and ethereal
-m Start mining blocks -id Set the custom identifier of the client (shows up on other clients)
-genaddr Generates a new address and private key (destructive action) -port Port on which the server will accept incomming connections
-p Port on which the server will accept incomming connections
-upnp Enable UPnP -upnp Enable UPnP
-x Desired amount of peers -maxpeer Desired amount of peers
-r Start JSON RPC -rpc Start JSON RPC
-dir Data directory used to store configs and databases -dir Data directory used to store configs and databases
-import Import a private key -import Import a private key
-genaddr Generates a new address and private key (destructive action)
-h This -h This
Ethereum only Ethereum only
ethereum [options] [filename] ethereum [options] [filename]
-js Start the JavaScript REPL -js Start the JavaScript REPL
filename Load the given file and interpret as JavaScript filename Load the given file and interpret as JavaScript
-m Start mining blocks
Etheral only Etheral only
-asset_path absolute path to GUI assets directory -asset_path absolute path to GUI assets directory

View File

@ -8,7 +8,7 @@ import Ethereum 1.0
ApplicationWindow { ApplicationWindow {
visible: false visible: false
title: "IceCream" title: "IceCREAM"
minimumWidth: 1280 minimumWidth: 1280
minimumHeight: 900 minimumHeight: 900
width: 1290 width: 1290
@ -224,8 +224,8 @@ ApplicationWindow {
} }
function setInstruction(num) { function setInstruction(num) {
asmTableView.selection.clear() //asmTableView.selection.clear()
asmTableView.selection.select(num) //asmTableView.selection.select(num)
} }
function setMem(mem) { function setMem(mem) {
@ -255,6 +255,10 @@ ApplicationWindow {
} }
function setLog(msg) { function setLog(msg) {
logModel.append({message: msg}) logModel.insert(0, {message: msg})
}
function clearLog() {
logModel.clear()
} }
} }

View File

@ -10,6 +10,8 @@ import Ethereum 1.0
ApplicationWindow { ApplicationWindow {
id: root id: root
property alias miningButtonText: miningButton.text
width: 900 width: 900
height: 600 height: 600
minimumHeight: 300 minimumHeight: 300
@ -27,13 +29,6 @@ ApplicationWindow {
} }
Menu { Menu {
title: "Tools"
MenuItem {
text: "Muted"
shortcut: "Ctrl+e"
onTriggered: ui.muted("")
}
MenuItem { MenuItem {
text: "Debugger" text: "Debugger"
shortcut: "Ctrl+d" shortcut: "Ctrl+d"
@ -50,11 +45,6 @@ ApplicationWindow {
addPeerWin.visible = true addPeerWin.visible = true
} }
} }
MenuItem {
text: "Start"
onTriggered: ui.connect()
}
} }
Menu { Menu {
@ -180,6 +170,7 @@ ApplicationWindow {
visible: false visible: false
anchors.fill: parent anchors.fill: parent
color: "#00000000" color: "#00000000"
/*
TabView{ TabView{
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 5 anchors.rightMargin: 5
@ -192,6 +183,10 @@ ApplicationWindow {
addTab("Contracts", newContract) addTab("Contracts", newContract)
} }
} }
*/
Component.onCompleted: {
newContract.createObject(newTxView)
}
} }
Rectangle { Rectangle {
@ -204,7 +199,7 @@ ApplicationWindow {
id: blockTable id: blockTable
width: parent.width width: parent.width
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: logView.top anchors.bottom: parent.bottom
TableViewColumn{ role: "number" ; title: "#" ; width: 100 } TableViewColumn{ role: "number" ; title: "#" ; width: 100 }
TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 } TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 }
TableViewColumn{ role: "txAmount" ; title: "Tx amount" ; width: 100 } TableViewColumn{ role: "txAmount" ; title: "Tx amount" ; width: 100 }
@ -217,19 +212,6 @@ ApplicationWindow {
} }
} }
property var logModel: ListModel {
id: logModel
}
TableView {
id: logView
width: parent.width
height: 150
anchors.bottom: parent.bottom
TableViewColumn{ role: "description" ; title: "log" }
model: logModel
}
} }
Rectangle { Rectangle {
@ -257,6 +239,35 @@ ApplicationWindow {
text: pub.getKey().address text: pub.getKey().address
width: 500 width: 500
} }
property var addressModel: ListModel {
id: addressModel
}
TableView {
id: addressView
width: parent.width
height: 200
anchors.bottom: logView.top
TableViewColumn{ role: "name"; title: "name" }
TableViewColumn{ role: "address"; title: "address"; width: 300}
model: addressModel
}
property var logModel: ListModel {
id: logModel
}
TableView {
id: logView
width: parent.width
height: 200
anchors.bottom: parent.bottom
TableViewColumn{ role: "description" ; title: "log" }
model: logModel
}
} }
/* /*
@ -294,8 +305,15 @@ ApplicationWindow {
} }
statusBar: StatusBar { statusBar: StatusBar {
height: 30
RowLayout { RowLayout {
anchors.fill: parent Button {
id: miningButton
onClicked: {
eth.toggleMining()
}
text: "Start Mining"
}
Button { Button {
property var enabled: true property var enabled: true
@ -319,8 +337,10 @@ ApplicationWindow {
anchors.leftMargin: 5 anchors.leftMargin: 5
id: walletValueLabel id: walletValueLabel
} }
}
Label { Label {
y: 7
anchors.right: peerImage.left anchors.right: peerImage.left
anchors.rightMargin: 5 anchors.rightMargin: 5
id: peerLabel id: peerLabel
@ -328,26 +348,26 @@ ApplicationWindow {
text: "0 / 0" text: "0 / 0"
} }
Image { Image {
y: 7
id: peerImage id: peerImage
anchors.right: parent.right anchors.right: parent.right
width: 10; height: 10 width: 10; height: 10
source: ui.assetPath("network.png") source: ui.assetPath("network.png")
} }
} }
}
Window { Window {
id: popup id: popup
visible: false visible: false
property var block property var block
width: root.width width: root.width
height: 240 height: 300
Component{ Component{
id: blockDetailsDelegate id: blockDetailsDelegate
Rectangle { Rectangle {
color: "#252525" color: "#252525"
width: popup.width width: popup.width
height: 200 height: 150
Column { Column {
anchors.leftMargin: 10 anchors.leftMargin: 10
anchors.topMargin: 5 anchors.topMargin: 5
@ -356,6 +376,7 @@ ApplicationWindow {
Text { text: '<h3>Block details</h3>'; color: "#F2F2F2"} Text { text: '<h3>Block details</h3>'; color: "#F2F2F2"}
Text { text: '<b>Block number:</b> ' + number; color: "#F2F2F2"} Text { text: '<b>Block number:</b> ' + number; color: "#F2F2F2"}
Text { text: '<b>Hash:</b> ' + hash; color: "#F2F2F2"} Text { text: '<b>Hash:</b> ' + hash; color: "#F2F2F2"}
Text { text: '<b>Coinbase:</b> ' + coinbase; color: "#F2F2F2"}
Text { text: '<b>Block found at:</b> ' + prettyTime; color: "#F2F2F2"} Text { text: '<b>Block found at:</b> ' + prettyTime; color: "#F2F2F2"}
} }
} }
@ -364,7 +385,7 @@ ApplicationWindow {
model: singleBlock model: singleBlock
delegate: blockDetailsDelegate delegate: blockDetailsDelegate
anchors.top: parent.top anchors.top: parent.top
height: 70 height: 100
anchors.leftMargin: 20 anchors.leftMargin: 20
id: listViewThing id: listViewThing
Layout.maximumHeight: 40 Layout.maximumHeight: 40
@ -389,7 +410,7 @@ ApplicationWindow {
if(tx.data) { if(tx.data) {
popup.showContractData(tx) popup.showContractData(tx)
}else{ }else{
popup.height = 230 popup.height = 440
} }
} }
} }
@ -403,7 +424,7 @@ ApplicationWindow {
contractLabel.text = "<h4> Transaction ran contract " + tx.address + "</h4>" contractLabel.text = "<h4> Transaction ran contract " + tx.address + "</h4>"
contractData.text = tx.rawData contractData.text = tx.rawData
} }
popup.height = 400 popup.height = 540
} }
Rectangle { Rectangle {
@ -455,7 +476,7 @@ ApplicationWindow {
} }
function setDetails(block){ function setDetails(block){
singleBlock.set(0,block) singleBlock.set(0,block)
popup.height = 230 popup.height = 300
transactionModel.clear() transactionModel.clear()
if(block.txs != undefined){ if(block.txs != undefined){
for(var i = 0; i < block.txs.count; ++i) { for(var i = 0; i < block.txs.count; ++i) {
@ -529,126 +550,17 @@ ApplicationWindow {
font.pointSize: 12 font.pointSize: 12
text: "<h2>Ethereal</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>" text: "<h2>Ethereal</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>"
} }
} }
ApplicationWindow {
id: debugWindow
visible: false
title: "Debugger"
minimumWidth: 600
minimumHeight: 600
width: 800
height: 600
Item {
id: keyHandler
focus: true
Keys.onPressed: {
if (event.key == Qt.Key_Space) {
ui.next()
}
}
}
SplitView {
anchors.fill: parent
property var asmModel: ListModel {
id: asmModel
}
TableView {
id: asmTableView
width: 200
TableViewColumn{ role: "value" ; title: "" ; width: 100 }
model: asmModel
}
Rectangle {
anchors.left: asmTableView.right
anchors.right: parent.right
SplitView {
orientation: Qt.Vertical
anchors.fill: parent
TableView {
property var memModel: ListModel {
id: memModel
}
height: parent.height/2
width: parent.width
TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50}
TableViewColumn{ role: "value" ; title: "Memory" ; width: 750}
model: memModel
}
SplitView {
orientation: Qt.Horizontal
id: debugSplitView
TableView {
property var debuggerLog: ListModel {
id: debuggerLog
}
TableViewColumn{ role: "value"; title: "Debug messages" }
model: debuggerLog
}
TableView {
property var stackModel: ListModel {
id: stackModel
}
height: parent.height/2
width: parent.width
TableViewColumn{ role: "value" ; title: "Stack" ; width: debugSplitView.width }
model: stackModel
}
}
}
}
}
statusBar: StatusBar {
RowLayout {
anchors.fill: parent
Button {
property var enabled: true
id: debugNextButton
onClicked: {
ui.next()
}
text: "Next"
}
}
}
}
function setAsm(asm) {
asmModel.append({asm: asm})
}
function setInstruction(num) {
asmTableView.selection.clear()
asmTableView.selection.select(num-1)
}
function clearAsm() {
asmModel.clear()
}
function setMem(mem) {
memModel.append({num: mem.num, value: mem.value})
}
function clearMem(){
memModel.clear()
}
function setStack(stack) {
stackModel.append({value: stack})
}
function addDebugMessage(message){ function addDebugMessage(message){
console.log("WOOP:")
debuggerLog.append({value: message}) debuggerLog.append({value: message})
} }
function clearStack() { function addAddress(address) {
stackModel.clear() addressModel.append({name: address.name, address: address.address})
}
function clearAddress() {
addressModel.clear()
} }
function loadPlugin(name) { function loadPlugin(name) {
@ -667,7 +579,14 @@ ApplicationWindow {
}else{ }else{
isContract = "No" isContract = "No"
} }
txModel.insert(0, {inout: inout, hash: tx.hash, address: tx.address, value: tx.value, contract: isContract})
var address;
if(inout == "recv") {
address = tx.sender;
} else {
address = tx.address;
}
txModel.insert(0, {inout: inout, hash: tx.hash, address: address, value: tx.value, contract: isContract})
} }
function addBlock(block, initial) { function addBlock(block, initial) {
@ -682,15 +601,15 @@ ApplicationWindow {
} }
if(initial){ if(initial){
blockModel.append({number: block.number, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) blockModel.append({number: block.number, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
}else{ }else{
blockModel.insert(0, {number: block.number, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)}) blockModel.insert(0, {number: block.number, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
} }
} }
function addLog(str) { function addLog(str) {
if(str.len != 0) { if(str.len != 0) {
logModel.append({description: str}) logModel.insert(0, {description: str})
} }
} }
@ -718,6 +637,7 @@ ApplicationWindow {
id: newContract id: newContract
Column { Column {
id: mainContractColumn id: mainContractColumn
anchors.fill: parent
function contractFormReady(){ function contractFormReady(){
if(codeView.text.length > 0 && txValue.text.length > 0 && txGas.text.length > 0 && txGasPrice.length > 0) { if(codeView.text.length > 0 && txValue.text.length > 0 && txGas.text.length > 0 && txGasPrice.length > 0) {
txButton.state = "READY" txButton.state = "READY"
@ -739,6 +659,8 @@ ApplicationWindow {
PropertyChanges { target: codeView; visible:false} PropertyChanges { target: codeView; visible:false}
PropertyChanges { target: txButton; visible:false} PropertyChanges { target: txButton; visible:false}
PropertyChanges { target: txDataLabel; visible:false} PropertyChanges { target: txDataLabel; visible:false}
PropertyChanges { target: atLabel; visible:false}
PropertyChanges { target: txFuelRecipient; visible:false}
PropertyChanges { target: txResult; visible:true} PropertyChanges { target: txResult; visible:true}
PropertyChanges { target: txOutput; visible:true} PropertyChanges { target: txOutput; visible:true}
@ -765,82 +687,70 @@ ApplicationWindow {
anchors.leftMargin: 5 anchors.leftMargin: 5
anchors.topMargin: 5 anchors.topMargin: 5
TextField {
id: txFuelRecipient
placeholderText: "Address / Name or empty for contract"
//validator: RegExpValidator { regExp: /[a-f0-9]{40}/ }
width: 400
}
TextField { TextField {
id: txValue id: txValue
width: 200 width: 222
placeholderText: "Amount" placeholderText: "Amount"
validator: RegExpValidator { regExp: /\d*/ } validator: RegExpValidator { regExp: /\d*/ }
onTextChanged: { onTextChanged: {
contractFormReady() contractFormReady()
} }
} }
RowLayout {
TextField { TextField {
id: txGas id: txGas
width: 200 width: 50
validator: RegExpValidator { regExp: /\d*/ } validator: RegExpValidator { regExp: /\d*/ }
placeholderText: "Gas" placeholderText: "Gas"
text: "500"
/*
onTextChanged: { onTextChanged: {
contractFormReady() contractFormReady()
} }
*/
} }
Label {
id: atLabel
text: "@"
}
TextField { TextField {
id: txGasPrice id: txGasPrice
width: 200 width: 200
placeholderText: "Gas price" placeholderText: "Gas price"
text: "1000000"
validator: RegExpValidator { regExp: /\d*/ } validator: RegExpValidator { regExp: /\d*/ }
/*
onTextChanged: { onTextChanged: {
contractFormReady() contractFormReady()
} }
} */
Row {
id: rowContract
ExclusiveGroup { id: contractTypeGroup }
RadioButton {
id: createContractRadio
text: "Create contract"
checked: true
exclusiveGroup: contractTypeGroup
onClicked: {
txFuelRecipient.visible = false
txDataLabel.text = "Contract code"
} }
} }
RadioButton {
id: runContractRadio
text: "Run contract"
exclusiveGroup: contractTypeGroup
onClicked: {
txFuelRecipient.visible = true
txDataLabel.text = "Contract arguments"
}
}
}
Label { Label {
id: txDataLabel id: txDataLabel
text: "Contract code" text: "Data"
} }
TextArea { TextArea {
id: codeView id: codeView
height: 300 height: 300
anchors.topMargin: 5 anchors.topMargin: 5
Layout.fillWidth: true width: 400
width: parent.width /2
onTextChanged: { onTextChanged: {
contractFormReady() contractFormReady()
} }
} }
TextField {
id: txFuelRecipient
placeholderText: "Contract address"
validator: RegExpValidator { regExp: /[a-f0-9]{40}/ }
visible: false
width: 530
}
Button { Button {
id: txButton id: txButton
@ -883,7 +793,7 @@ ApplicationWindow {
Button { Button {
id: newTxButton id: newTxButton
visible: false visible: false
text: "Create an other contract" text: "Create a new transaction"
onClicked: { onClicked: {
this.visible = false this.visible = false
txResult.text = "" txResult.text = ""
@ -891,15 +801,6 @@ ApplicationWindow {
mainContractColumn.state = "SETUP" mainContractColumn.state = "SETUP"
} }
} }
Button {
id: debugButton
text: "Debug"
onClicked: {
var res = ui.debugTx("", txValue.text, txGas.text, txGasPrice.text, codeView.text)
debugWindow.visible = true
}
}
} }
} }
@ -948,7 +849,7 @@ ApplicationWindow {
id: txSimpleRecipient id: txSimpleRecipient
placeholderText: "Recipient address" placeholderText: "Recipient address"
Layout.fillWidth: true Layout.fillWidth: true
validator: RegExpValidator { regExp: /[a-f0-9]{40}/ } //validator: RegExpValidator { regExp: /[a-f0-9]{40}/ }
width: 530 width: 530
onTextChanged: { checkFormState() } onTextChanged: { checkFormState() }
} }
@ -976,7 +877,7 @@ ApplicationWindow {
text: "Send" text: "Send"
onClicked: { onClicked: {
//this.enabled = false //this.enabled = false
var res = eth.transact(txSimpleRecipient.text, txSimpleValue.text,"","","") var res = eth.transact(txSimpleRecipient.text, txSimpleValue.text, "500", "1000000", "")
if(res[1]) { if(res[1]) {
txSimpleResult.text = "There has been an error broadcasting your transaction:" + res[1].error() txSimpleResult.text = "There has been an error broadcasting your transaction:" + res[1].error()
} else { } else {

View File

@ -5,8 +5,8 @@ import (
) )
var Identifier string var Identifier string
var StartConsole bool
var StartMining bool //var StartMining bool
var StartRpc bool var StartRpc bool
var RpcPort int var RpcPort int
var UseUPnP bool var UseUPnP bool
@ -18,25 +18,22 @@ var GenAddr bool
var UseSeed bool var UseSeed bool
var ImportKey string var ImportKey string
var ExportKey bool var ExportKey bool
var DataDir string
var AssetPath string var AssetPath string
func Init() { func Init() {
flag.StringVar(&Identifier, "i", "", "Custom client identifier") flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.BoolVar(&StartConsole, "c", false, "debug and testing console") flag.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&StartMining, "m", false, "start dagger mining")
flag.BoolVar(&StartRpc, "r", false, "start rpc server")
flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support") flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
flag.StringVar(&AssetPath, "asset_path", "", "absolute path to GUI assets directory")
flag.BoolVar(&ShowGenesis, "genesis", false, "prints genesis header and exits")
flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key") flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.StringVar(&OutboundPort, "p", "30303", "listening port")
flag.StringVar(&DataDir, "dir", ".ethereal", "ethereum data directory")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)") flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.IntVar(&MaxPeer, "x", 10, "maximum desired peers")
flag.StringVar(&AssetPath, "asset_path", "", "absolute path to GUI assets directory")
flag.Parse() flag.Parse()
} }

View File

@ -8,9 +8,11 @@ import (
"github.com/ethereum/go-ethereum/ethereal/ui" "github.com/ethereum/go-ethereum/ethereal/ui"
"github.com/ethereum/go-ethereum/utils" "github.com/ethereum/go-ethereum/utils"
"github.com/go-qml/qml" "github.com/go-qml/qml"
"github.com/rakyll/globalconf"
"log" "log"
"os" "os"
"os/signal" "os/signal"
"path"
"runtime" "runtime"
) )
@ -39,7 +41,16 @@ func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
ethchain.InitFees() ethchain.InitFees()
ethutil.ReadConfig(DataDir, ethutil.LogFile|ethutil.LogStd, Identifier)
g, err := globalconf.NewWithOptions(&globalconf.Options{
Filename: path.Join(ethutil.ApplicationFolder(".ethereal"), "conf.ini"),
})
if err != nil {
fmt.Println(err)
} else {
g.ParseAll()
}
ethutil.ReadConfig(".ethereal", ethutil.LogFile|ethutil.LogStd, Identifier)
// Instantiated a eth stack // Instantiated a eth stack
ethereum, err := eth.New(eth.CapDefault, UseUPnP) ethereum, err := eth.New(eth.CapDefault, UseUPnP)
@ -108,9 +119,11 @@ save these words so you can restore your account later: %s
os.Exit(0) os.Exit(0)
} }
/*
if StartMining { if StartMining {
utils.DoMining(ethereum) utils.DoMining(ethereum)
} }
*/
if StartRpc { if StartRpc {
utils.DoRpc(ethereum, RpcPort) utils.DoRpc(ethereum, RpcPort)

View File

@ -71,6 +71,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
var err error var err error
script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) { script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
ret, err = ethutil.Compile(s) ret, err = ethutil.Compile(s)
fmt.Printf("%x\n", ret)
return return
}) })
@ -82,6 +83,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
dis := ethchain.Disassemble(script) dis := ethchain.Disassemble(script)
self.win.Root().Call("clearAsm") self.win.Root().Call("clearAsm")
self.win.Root().Call("clearLog")
for _, str := range dis { for _, str := range dis {
self.win.Root().Call("setAsm", str) self.win.Root().Call("setAsm", str)

View File

@ -8,6 +8,7 @@ import (
"github.com/ethereum/eth-go/ethdb" "github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils"
"github.com/go-qml/qml" "github.com/go-qml/qml"
"math/big" "math/big"
"strings" "strings"
@ -66,7 +67,6 @@ func (gui *Gui) Start(assetPath string) {
}}) }})
ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", version)) ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", version))
ethutil.Config.Log.Infoln("[GUI] Starting GUI")
// Create a new QML engine // Create a new QML engine
gui.engine = qml.NewEngine() gui.engine = qml.NewEngine()
context := gui.engine.Context() context := gui.engine.Context()
@ -93,12 +93,28 @@ func (gui *Gui) Start(assetPath string) {
panic(err) panic(err)
} }
ethutil.Config.Log.AddLogSystem(gui)
ethutil.Config.Log.Infoln("[GUI] Starting GUI")
win.Show() win.Show()
win.Wait() win.Wait()
gui.eth.Stop() gui.eth.Stop()
} }
func (gui *Gui) ToggleMining() {
var txt string
if gui.eth.Mining {
utils.StopMining(gui.eth)
txt = "Start mining"
} else {
utils.StartMining(gui.eth)
txt = "Stop mining"
}
gui.win.Root().Set("miningButtonText", txt)
}
func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) { func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/wallet.qml")) component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/wallet.qml"))
if err != nil { if err != nil {
@ -107,8 +123,11 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
win := gui.createWindow(component) win := gui.createWindow(component)
go gui.setInitialBlockChain() gui.setInitialBlockChain()
go gui.readPreviousTransactions() gui.loadAddressBook()
gui.readPreviousTransactions()
gui.setPeerInfo()
go gui.update() go gui.update()
return win, nil return win, nil
@ -145,6 +164,19 @@ func (gui *Gui) setInitialBlockChain() {
} }
} }
type address struct {
Name, Address string
}
var namereg = ethutil.FromHex("bb5f186604d057c1c5240ca2ae0f6430138ac010")
func (gui *Gui) loadAddressBook() {
gui.win.Root().Call("clearAddress")
gui.eth.StateManager().CurrentState().GetStateObject(namereg).State().EachStorage(func(name string, value *ethutil.Value) {
gui.win.Root().Call("addAddress", struct{ Name, Address string }{name, ethutil.Hex(value.Bytes())})
})
}
func (gui *Gui) readPreviousTransactions() { func (gui *Gui) readPreviousTransactions() {
it := gui.txDb.Db().NewIterator(nil, nil) it := gui.txDb.Db().NewIterator(nil, nil)
for it.Next() { for it.Next() {
@ -189,10 +221,14 @@ func (gui *Gui) update() {
blockChan := make(chan ethutil.React, 1) blockChan := make(chan ethutil.React, 1)
txChan := make(chan ethutil.React, 1) txChan := make(chan ethutil.React, 1)
objectChan := make(chan ethutil.React, 1)
peerChan := make(chan ethutil.React, 1)
reactor.Subscribe("newBlock", blockChan) reactor.Subscribe("newBlock", blockChan)
reactor.Subscribe("newTx:pre", txChan) reactor.Subscribe("newTx:pre", txChan)
reactor.Subscribe("newTx:post", txChan) reactor.Subscribe("newTx:post", txChan)
reactor.Subscribe("object:"+string(namereg), objectChan)
reactor.Subscribe("peerList", peerChan)
state := gui.eth.StateManager().TransState() state := gui.eth.StateManager().TransState()
@ -239,10 +275,18 @@ func (gui *Gui) update() {
state.UpdateStateObject(object) state.UpdateStateObject(object)
} }
case <-objectChan:
gui.loadAddressBook()
case <-peerChan:
gui.setPeerInfo()
} }
} }
} }
func (gui *Gui) setPeerInfo() {
gui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", gui.eth.PeerCount(), gui.eth.MaxPeers))
}
// Logging functions that log directly to the GUI interface // Logging functions that log directly to the GUI interface
func (gui *Gui) Println(v ...interface{}) { func (gui *Gui) Println(v ...interface{}) {
str := strings.TrimRight(fmt.Sprintln(v...), "\n") str := strings.TrimRight(fmt.Sprintln(v...), "\n")

View File

@ -20,7 +20,6 @@ var UseSeed bool
var ImportKey string var ImportKey string
var ExportKey bool var ExportKey bool
var LogFile string var LogFile string
var DataDir string
var NonInteractive bool var NonInteractive bool
var StartJsConsole bool var StartJsConsole bool
var InputFile string var InputFile string
@ -31,22 +30,21 @@ func Init() {
flag.PrintDefaults() flag.PrintDefaults()
} }
flag.StringVar(&Identifier, "i", "", "custom client identifier") flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.BoolVar(&StartMining, "m", false, "start dagger mining") flag.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits")
flag.BoolVar(&StartRpc, "r", false, "start rpc server")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support") flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
flag.BoolVar(&StartJsConsole, "js", false, "exp")
flag.BoolVar(&StartMining, "mine", false, "start dagger mining")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key") flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.StringVar(&OutboundPort, "p", "30303", "listening port")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&DataDir, "dir", ".ethereum", "ethereum data directory")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)") flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.IntVar(&MaxPeer, "x", 10, "maximum desired peers")
flag.BoolVar(&StartJsConsole, "js", false, "exp")
flag.Parse() flag.Parse()

View File

@ -59,7 +59,7 @@ func main() {
lt = ethutil.LogFile | ethutil.LogStd lt = ethutil.LogFile | ethutil.LogStd
} }
ethutil.ReadConfig(DataDir, lt, Identifier) ethutil.ReadConfig(".ethereum", lt, Identifier)
logger := ethutil.Config.Log logger := ethutil.Config.Log

View File

@ -33,8 +33,6 @@ func DoMining(ethereum *eth.Ethereum) {
addr := keyPair.Address() addr := keyPair.Address()
go func() { go func() {
ethutil.Config.Log.Infoln("Miner started")
miner = ethminer.NewDefaultMiner(addr, ethereum) miner = ethminer.NewDefaultMiner(addr, ethereum)
// Give it some time to connect with peers // Give it some time to connect with peers