Compare commits

...

36 Commits

Author SHA1 Message Date
obscuren
aa8a86f0a6 Merge branch 'release/poc5-rc12' 2014-06-09 22:24:24 +02:00
obscuren
d929c63474 bump 2014-06-09 22:23:33 +02:00
obscuren
ba3623d0cc Fixed debugger hang 2014-06-09 22:04:16 +02:00
obscuren
cc20b0e3a0 debugger output 2014-06-06 12:13:13 +02:00
obscuren
a107a5db05 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-06-05 09:01:10 +02:00
obscuren
964587b14a Added more debugger output 2014-06-05 09:00:57 +02:00
Maran
7843390ecd Implement getStateKeyVal for JS bindings.
Gives JS the option to 'loop' over contract key/val storage
2014-06-04 15:54:33 +02:00
Maran
307fe4a3cd Add loading of extra build in js files to JS-Repl. Implements #67 2014-06-04 12:19:50 +02:00
Maran
3755616a29 Added namereg register option to qml wallet 2014-06-03 14:30:26 +02:00
Maran
cc1d043423 Implemented transaction catching up. Implements #73 2014-06-03 11:48:44 +02:00
Maran
9e411d785b Tweaks and latency added to peeroverview 2014-06-03 10:42:36 +02:00
Maran
a6f4eef1da Added Peer Window 2014-06-02 15:16:37 +02:00
obscuren
98811f11e5 ethereum instead of ethereal. Fixes #69 2014-05-31 11:43:08 +02:00
obscuren
d6acb74ac9 fixed logging issue that would otherwise crash the client. Fixes #68 2014-05-31 11:34:37 +02:00
obscuren
397e99fcc6 Merge branch 'develop' 2014-05-30 20:35:44 +02:00
obscuren
be27309dbb show first? 2014-05-30 20:35:37 +02:00
obscuren
4dfce5d347 Merge branch 'develop' 2014-05-30 19:36:21 +02:00
obscuren
0bdb0a9d58 Added ini file for ethereum. fixes #66 2014-05-30 19:36:05 +02:00
obscuren
5f28013f79 Merge branch 'develop' 2014-05-30 16:58:17 +02:00
obscuren
65c5a20e1c Added config file setup. Fixes #59
* Also fixes asset path problems
2014-05-30 16:56:56 +02:00
obscuren
1020d7ff67 Unified the contract interface and tx interface. Fixes #62 2014-05-30 16:14:46 +02:00
obscuren
e7c9b86a5a Improved UI
* Added mining button
2014-05-30 13:28:31 +02:00
obscuren
0938b56829 Update peer info 2014-05-30 13:04:23 +02:00
obscuren
fcbf99a30a Minor GUI updates
* IceCream => IceCREAM
* Added coin base to block info
2014-05-30 11:50:30 +02:00
obscuren
40d72ff40b . 2014-05-29 12:24:56 +02:00
obscuren
efadfbfb17 Minor UI changes
* Moved log from block view
* Prepend instead of append for logs
2014-05-29 12:24:14 +02:00
obscuren
8ee6574d12 Minimal fee for sending transactions 2014-05-29 12:14:25 +02:00
obscuren
efb3ee044b Removed regexp for namereg 2014-05-29 11:49:59 +02:00
obscuren
0b4c42d756 Disabled instruction selection 2014-05-29 02:05:06 +02:00
obscuren
f0f205004c Merge branch 'develop' 2014-05-28 23:23:52 +02:00
obscuren
f802e17626 merge 2014-05-28 23:16:15 +02:00
obscuren
8fab7ce37d Fixes and improved debugger 2014-05-28 23:14:23 +02:00
Maran
44db1a1eb2 Add 0x when feeding data to debugger 2014-05-28 18:11:27 +02:00
Maran
0aee830bde Fix merge conflict 2014-05-28 16:20:36 +02:00
Maran
06d41794f9 Merge branch 'release/poc5-rc11' into develop 2014-05-28 16:20:05 +02:00
obscuren
090447c664 Data and script in the debugger accept "0x" values and regular scripting 2014-05-28 12:59:10 +02:00
16 changed files with 1436 additions and 1268 deletions

View File

@@ -5,7 +5,7 @@ Ethereum
Ethereum Go Client © 2014 Jeffrey Wilcke. Ethereum Go Client © 2014 Jeffrey Wilcke.
Current state: Proof of Concept 5.0 RC11. Current state: Proof of Concept 5.0 RC12.
For the development package please see the [eth-go package](https://github.com/ethereum/eth-go). For the development package please see the [eth-go package](https://github.com/ethereum/eth-go).
@@ -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

@@ -7,12 +7,12 @@ import QtQuick.Controls.Styles 1.1
import Ethereum 1.0 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
height: 900 height: 900
property alias codeText: codeEditor.text property alias codeText: codeEditor.text
property alias dataText: rawDataField.text property alias dataText: rawDataField.text
@@ -32,209 +32,233 @@ ApplicationWindow {
onTriggered: dbg.next() onTriggered: dbg.next()
} }
} }
} }
SplitView { SplitView {
anchors.fill: parent anchors.fill: parent
property var asmModel: ListModel { property var asmModel: ListModel {
id: asmModel id: asmModel
} }
TableView { TableView {
id: asmTableView id: asmTableView
width: 200 width: 200
TableViewColumn{ role: "value" ; title: "" ; width: 100 } TableViewColumn{ role: "value" ; title: "" ; width: 100 }
model: asmModel model: asmModel
} }
Rectangle { Rectangle {
color: "#00000000" color: "#00000000"
anchors.left: asmTableView.right anchors.left: asmTableView.right
anchors.right: parent.right anchors.right: parent.right
SplitView { SplitView {
orientation: Qt.Vertical orientation: Qt.Vertical
anchors.fill: parent anchors.fill: parent
Rectangle { Rectangle {
color: "#00000000" color: "#00000000"
height: 500 height: 500
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
TextArea { TextArea {
id: codeEditor id: codeEditor
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: settings.left anchors.right: settings.left
} }
Column { Column {
id: settings id: settings
spacing: 5 spacing: 5
width: 300 width: 300
height: parent.height height: parent.height
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
Label { Label {
text: "Arbitrary data" text: "Arbitrary data"
} }
TextArea { TextArea {
id: rawDataField id: rawDataField
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: 150 height: 150
} }
Label { Label {
text: "Amount" text: "Amount"
} }
TextField { TextField {
id: txValue id: txValue
width: 200 width: 200
placeholderText: "Amount" placeholderText: "Amount"
validator: RegExpValidator { regExp: /\d*/ } validator: RegExpValidator { regExp: /\d*/ }
} }
Label { Label {
text: "Amount of gas" text: "Amount of gas"
} }
TextField { TextField {
id: txGas id: txGas
width: 200 width: 200
validator: RegExpValidator { regExp: /\d*/ } validator: RegExpValidator { regExp: /\d*/ }
text: "10000" text: "10000"
placeholderText: "Gas" placeholderText: "Gas"
} }
Label { Label {
text: "Gas price" text: "Gas price"
} }
TextField { TextField {
id: txGasPrice id: txGasPrice
width: 200 width: 200
placeholderText: "Gas price" placeholderText: "Gas price"
text: "1000000000000" text: "1000000000000"
validator: RegExpValidator { regExp: /\d*/ } validator: RegExpValidator { regExp: /\d*/ }
} }
} }
} }
SplitView { SplitView {
orientation: Qt.Vertical orientation: Qt.Vertical
id: inspectorPane id: inspectorPane
height: 500 height: 500
SplitView { SplitView {
orientation: Qt.Horizontal orientation: Qt.Horizontal
height: 250 height: 150
TableView { TableView {
id: stackTableView id: stackTableView
property var stackModel: ListModel { property var stackModel: ListModel {
id: stackModel id: stackModel
} }
height: parent.height height: parent.height
width: 300 width: 300
TableViewColumn{ role: "value" ; title: "Stack" ; width: 200 } TableViewColumn{ role: "value" ; title: "Stack" ; width: 200 }
model: stackModel model: stackModel
} }
TableView { TableView {
id: memoryTableView id: memoryTableView
property var memModel: ListModel { property var memModel: ListModel {
id: memModel id: memModel
} }
height: parent.height height: parent.height
width: parent.width - stackTableView.width width: parent.width - stackTableView.width
TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50} TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50}
TableViewColumn{ role: "value" ; title: "Memory" ; width: 750} TableViewColumn{ role: "value" ; title: "Memory" ; width: 750}
model: memModel model: memModel
} }
} }
SplitView { Rectangle {
height: 300 height: 100
TableView { width: parent.width
id: storageTableView TableView {
property var memModel: ListModel { id: storageTableView
id: storageModel property var memModel: ListModel {
} id: storageModel
height: parent.height }
width: parent.width - stackTableView.width height: parent.height
TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2} width: parent.width
TableViewColumn{ role: "value" ; title: "value" ; width: storageTableView.width / 2} TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2}
model: storageModel TableViewColumn{ role: "value" ; title: "Storage" ; width: storageTableView.width / 2}
} model: storageModel
} }
} }
}
}
}
toolBar: ToolBar { Rectangle {
RowLayout { height: 200
spacing: 5 width: parent.width
TableView {
id: logTableView
property var logModel: ListModel {
id: logModel
}
height: parent.height
width: parent.width
TableViewColumn{ id: message ; role: "message" ; title: "log" ; width: logTableView.width }
model: logModel
}
}
}
}
}
}
Button { toolBar: ToolBar {
property var enabled: true RowLayout {
id: debugStart spacing: 5
onClicked: {
debugCurrent()
}
text: "Debug"
}
Button { Button {
property var enabled: true property var enabled: true
id: debugNextButton id: debugStart
onClicked: { onClicked: {
dbg.next() debugCurrent()
} }
text: "Next" text: "Debug"
} }
}
}
function debugCurrent() { Button {
dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text) property var enabled: true
} id: debugNextButton
onClicked: {
dbg.next()
}
text: "Next"
}
}
}
function setAsm(asm) { function debugCurrent() {
asmModel.append({asm: asm}) dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text)
} }
function clearAsm() { function setAsm(asm) {
asmModel.clear() asmModel.append({asm: asm})
} }
function setInstruction(num) { function clearAsm() {
asmTableView.selection.clear() asmModel.clear()
asmTableView.selection.select(num) }
}
function setMem(mem) { function setInstruction(num) {
memModel.append({num: mem.num, value: mem.value}) //asmTableView.selection.clear()
} //asmTableView.selection.select(num)
function clearMem(){ }
memModel.clear()
}
function setStack(stack) { function setMem(mem) {
stackModel.append({value: stack}) memModel.append({num: mem.num, value: mem.value})
} }
function addDebugMessage(message){ function clearMem(){
debuggerLog.append({value: message}) memModel.clear()
} }
function clearStack() { function setStack(stack) {
stackModel.clear() stackModel.append({value: stack})
} }
function addDebugMessage(message){
debuggerLog.append({value: message})
}
function clearStorage() { function clearStack() {
storageModel.clear() stackModel.clear()
} }
function setStorage(storage) { function clearStorage() {
storageModel.append({key: storage.key, value: storage.value}) storageModel.clear()
} }
function setStorage(storage) {
storageModel.append({key: storage.key, value: storage.value})
}
function setLog(msg) {
logModel.insert(0, {message: msg})
}
function clearLog() {
logModel.clear()
}
} }

View File

@@ -32,6 +32,10 @@ window.eth = {
postData({call: "getStorage", args: [address, storageAddress]}, cb); postData({call: "getStorage", args: [address, storageAddress]}, cb);
}, },
getStateKeyVals: function(address, cb){
postData({call: "getStateKeyVals", args: [address]}, cb);
},
getKey: function(cb) { getKey: function(cb) {
postData({call: "getKey"}, cb); postData({call: "getKey"}, cb);
}, },

File diff suppressed because it is too large Load Diff

View File

@@ -34,7 +34,6 @@ ApplicationWindow {
top: parent.top top: parent.top
} }
*/ */
onTitleChanged: { window.title = title } onTitleChanged: { window.title = title }
experimental.preferences.javascriptEnabled: true experimental.preferences.javascriptEnabled: true
experimental.preferences.navigatorQtObjectEnabled: true experimental.preferences.navigatorQtObjectEnabled: true
@@ -97,6 +96,12 @@ ApplicationWindow {
var storage = stateObject.getStorage(data.args[1]) var storage = stateObject.getStorage(data.args[1])
postData(data._seed, storage) postData(data._seed, storage)
break
case "getStateKeyVals":
require(1);
var stateObject = eth.getStateObject(data.args[0]).stateKeyVal(true)
postData(data._seed,stateObject)
break break
case "getBalance": case "getBalance":
require(1); require(1);
@@ -188,7 +193,7 @@ ApplicationWindow {
WebView { WebView {
id: inspector id: inspector
visible: false visible: true
url: webview.experimental.remoteInspectorUrl url: webview.experimental.remoteInspectorUrl
anchors { anchors {
left: root.left left: root.left

View File

@@ -9,7 +9,7 @@
<script type="text/javascript"> <script type="text/javascript">
var jefcoinAddr = "518546ffa883dcc838a64bc2dabada0fd64af459" var jefcoinAddr = "de0bd4ea1947deabf1749d7ed633f289358c9f6c"
var mAddr = "" var mAddr = ""
function createTransaction() { function createTransaction() {

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, g, 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 { /*
utils.DoMining(ethereum) if StartMining {
} utils.DoMining(ethereum)
}
*/
if StartRpc { if StartRpc {
utils.DoRpc(ethereum, RpcPort) utils.DoRpc(ethereum, RpcPort)

View File

@@ -9,23 +9,6 @@ import (
"strings" "strings"
) )
func formatData(data string) []byte {
if len(data) == 0 {
return nil
}
// Simple stupid
d := new(big.Int)
if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
d.SetBytes([]byte(data[1 : len(data)-1]))
} else if data[:2] == "0x" {
d.SetBytes(ethutil.FromHex(data[2:]))
} else {
d.SetString(data, 0)
}
return ethutil.BigToBytes(d, 256)
}
type DebuggerWindow struct { type DebuggerWindow struct {
win *qml.Window win *qml.Window
engine *qml.Engine engine *qml.Engine
@@ -43,7 +26,7 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
} }
win := component.CreateWindow(nil) win := component.CreateWindow(nil)
db := &Debugger{win, make(chan bool), make(chan bool), true} db := &Debugger{win, make(chan bool), make(chan bool), true, false}
return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db} return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db}
} }
@@ -79,15 +62,14 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
fmt.Println(r) self.Logf("compile FAULT: %v", r)
self.Db.done = true
} }
}() }()
data := ethutil.StringToByteFunc(dataStr, func(s string) (ret []byte) { data := ethutil.StringToByteFunc(dataStr, func(s string) (ret []byte) {
slice := strings.Split(dataStr, "\n") slice := strings.Split(dataStr, "\n")
for _, dataItem := range slice { for _, dataItem := range slice {
d := formatData(dataItem) d := ethutil.FormatData(dataItem)
ret = append(ret, d...) ret = append(ret, d...)
} }
return return
@@ -96,31 +78,35 @@ 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
}) })
if err != nil { if err != nil {
ethutil.Config.Log.Debugln(err) self.Logln(err)
return return
} }
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)
} }
gas := ethutil.Big(gasStr)
gasPrice := ethutil.Big(gasPriceStr)
// Contract addr as test address // Contract addr as test address
keyPair := ethutil.GetKeyRing().Get(0) keyPair := ethutil.GetKeyRing().Get(0)
callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script) callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, script)
callerTx.Sign(keyPair.PrivateKey) callerTx.Sign(keyPair.PrivateKey)
state := self.lib.eth.BlockChain().CurrentBlock.State() state := self.lib.eth.BlockChain().CurrentBlock.State()
account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address()) account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address())
contract := ethchain.MakeContract(callerTx, state) contract := ethchain.MakeContract(callerTx, state)
callerClosure := ethchain.NewClosure(account, contract, script, state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr)) callerClosure := ethchain.NewClosure(account, contract, script, state, gas, gasPrice)
block := self.lib.eth.BlockChain().CurrentBlock block := self.lib.eth.BlockChain().CurrentBlock
vm := ethchain.NewVm(state, self.lib.eth.StateManager(), ethchain.RuntimeVars{ vm := ethchain.NewVm(state, self.lib.eth.StateManager(), ethchain.RuntimeVars{
@@ -130,27 +116,53 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
Coinbase: block.Coinbase, Coinbase: block.Coinbase,
Time: block.Time, Time: block.Time,
Diff: block.Difficulty, Diff: block.Difficulty,
Value: ethutil.Big(valueStr),
}) })
self.Db.done = false self.Db.done = false
self.Logf("callsize %d", len(script))
go func() { go func() {
callerClosure.Call(vm, data, self.Db.halting) ret, g, err := callerClosure.Call(vm, data, self.Db.halting)
tot := new(big.Int).Mul(g, gasPrice)
self.Logf("gas usage %v total price = %v (%v)", g, tot, ethutil.CurrencyToString(tot))
if err != nil {
self.Logln("exited with errors:", err)
} else {
if len(ret) > 0 {
self.Logf("exited: % x", ret)
} else {
self.Logf("exited: nil")
}
}
state.Reset() state.Reset()
self.Db.done = true if !self.Db.interrupt {
self.Db.done = true
} else {
self.Db.interrupt = false
}
}() }()
} }
func (self *DebuggerWindow) Logf(format string, v ...interface{}) {
self.win.Root().Call("setLog", fmt.Sprintf(format, v...))
}
func (self *DebuggerWindow) Logln(v ...interface{}) {
str := fmt.Sprintln(v...)
self.Logf("%s", str[:len(str)-1])
}
func (self *DebuggerWindow) Next() { func (self *DebuggerWindow) Next() {
self.Db.Next() self.Db.Next()
} }
type Debugger struct { type Debugger struct {
win *qml.Window win *qml.Window
N chan bool N chan bool
Q chan bool Q chan bool
done bool done, interrupt bool
} }
type storeVal struct { type storeVal struct {
@@ -183,7 +195,8 @@ out:
case <-d.N: case <-d.N:
break out break out
case <-d.Q: case <-d.Q:
d.done = true d.interrupt = true
d.clearBuffers()
return false return false
} }
@@ -192,6 +205,19 @@ out:
return true return true
} }
func (d *Debugger) clearBuffers() {
out:
// drain
for {
select {
case <-d.N:
case <-d.Q:
default:
break out
}
}
}
func (d *Debugger) Next() { func (d *Debugger) Next() {
if !d.done { if !d.done {
d.N <- true d.N <- true

View File

@@ -8,9 +8,11 @@ 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"
"time"
) )
type Gui struct { type Gui struct {
@@ -54,7 +56,7 @@ func New(ethereum *eth.Ethereum) *Gui {
} }
func (gui *Gui) Start(assetPath string) { func (gui *Gui) Start(assetPath string) {
const version = "0.5.0 RC11" const version = "0.5.0 RC12"
defer gui.txDb.Close() defer gui.txDb.Close()
@@ -63,10 +65,12 @@ func (gui *Gui) Start(assetPath string) {
Init: func(p *ethpub.PBlock, obj qml.Object) { p.Number = 0; p.Hash = "" }, Init: func(p *ethpub.PBlock, obj qml.Object) { p.Number = 0; p.Hash = "" },
}, { }, {
Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" },
}, {
Init: func(p *ethpub.KeyVal, obj qml.Object) { p.Key = ""; p.Value = "" },
}}) }})
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()
@@ -86,19 +90,36 @@ func (gui *Gui) Start(assetPath string) {
win, err = gui.showKeyImport(context) win, err = gui.showKeyImport(context)
} else { } else {
win, err = gui.showWallet(context) win, err = gui.showWallet(context)
ethutil.Config.Log.AddLogSystem(gui)
} }
if err != nil { if err != nil {
ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'") ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'", err)
panic(err) panic(err)
} }
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 +128,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
@@ -130,7 +154,7 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
gui.win = win gui.win = win
gui.uiLib.win = win gui.uiLib.win = win
db := &Debugger{gui.win, make(chan bool), make(chan bool), true} db := &Debugger{gui.win, make(chan bool), make(chan bool), true, false}
gui.lib.Db = db gui.lib.Db = db
gui.uiLib.Db = db gui.uiLib.Db = db
@@ -141,10 +165,37 @@ func (gui *Gui) setInitialBlockChain() {
blk := gui.eth.BlockChain().GetBlock(sBlk) blk := gui.eth.BlockChain().GetBlock(sBlk)
for ; blk != nil; blk = gui.eth.BlockChain().GetBlock(sBlk) { for ; blk != nil; blk = gui.eth.BlockChain().GetBlock(sBlk) {
sBlk = blk.PrevHash sBlk = blk.PrevHash
// Loop through all transactions to see if we missed any while being offline
for _, tx := range blk.Transactions() {
if bytes.Compare(tx.Sender(), gui.addr) == 0 || bytes.Compare(tx.Recipient, gui.addr) == 0 {
if ok, _ := gui.txDb.Get(tx.Hash()); ok == nil {
gui.txDb.Put(tx.Hash(), tx.RlpEncode())
}
}
}
gui.processBlock(blk, true) gui.processBlock(blk, true)
} }
} }
type address struct {
Name, Address string
}
var namereg = ethutil.FromHex("bb5f186604d057c1c5240ca2ae0f6430138ac010")
func (gui *Gui) loadAddressBook() {
gui.win.Root().Call("clearAddress")
stateObject := gui.eth.StateManager().CurrentState().GetStateObject(namereg)
if stateObject != nil {
stateObject.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 +240,16 @@ 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)
ticker := time.NewTicker(5 * time.Second)
state := gui.eth.StateManager().TransState() state := gui.eth.StateManager().TransState()
@@ -239,10 +296,25 @@ func (gui *Gui) update() {
state.UpdateStateObject(object) state.UpdateStateObject(object)
} }
case <-objectChan:
gui.loadAddressBook()
case <-peerChan:
gui.setPeerInfo()
case <-ticker.C:
gui.setPeerInfo()
} }
} }
} }
func (gui *Gui) setPeerInfo() {
gui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", gui.eth.PeerCount(), gui.eth.MaxPeers))
gui.win.Root().Call("resetPeers")
for _, peer := range gui.pub.GetPeers() {
gui.win.Root().Call("addPeer", peer)
}
}
// 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")
@@ -259,6 +331,11 @@ func (gui *Gui) Printf(format string, v ...interface{}) {
gui.win.Root().Call("addLog", line) gui.win.Root().Call("addLog", line)
} }
} }
func (gui *Gui) RegisterName(name string) {
keyPair := ethutil.GetKeyRing().Get(0)
name = fmt.Sprintf("\"%s\"\n1", name)
gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), "namereg", "1000", "1000000", "150", name)
}
func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) { func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
keyPair := ethutil.GetKeyRing().Get(0) keyPair := ethutil.GetKeyRing().Get(0)
@@ -269,5 +346,13 @@ func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.
func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) { func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
keyPair := ethutil.GetKeyRing().Get(0) keyPair := ethutil.GetKeyRing().Get(0)
return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, data) return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data)
}
func (gui *Gui) ChangeClientId(id string) {
ethutil.Config.SetIdentifier(id)
}
func (gui *Gui) ClientId() string {
return ethutil.Config.Identifier
} }

View File

@@ -95,7 +95,7 @@ func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
if len(object.Script()) > 0 { if len(object.Script()) > 0 {
dbWindow.SetCode("0x" + ethutil.Hex(object.Script())) dbWindow.SetCode("0x" + ethutil.Hex(object.Script()))
} }
dbWindow.SetData(data) dbWindow.SetData("0x" + data)
dbWindow.Show() dbWindow.Show()
} }

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

@@ -6,10 +6,12 @@ import (
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils" "github.com/ethereum/go-ethereum/utils"
"github.com/rakyll/globalconf"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"os/signal" "os/signal"
"path"
"runtime" "runtime"
"strings" "strings"
) )
@@ -59,7 +61,15 @@ func main() {
lt = ethutil.LogFile | ethutil.LogStd lt = ethutil.LogFile | ethutil.LogStd
} }
ethutil.ReadConfig(DataDir, lt, Identifier) g, err := globalconf.NewWithOptions(&globalconf.Options{
Filename: path.Join(ethutil.ApplicationFolder(".ethereum"), "conf.ini"),
})
if err != nil {
fmt.Println(err)
} else {
g.ParseAll()
}
ethutil.ReadConfig(".ethereum", lt, g, Identifier)
logger := ethutil.Config.Log logger := ethutil.Config.Log

View File

@@ -10,6 +10,7 @@ import (
"github.com/obscuren/otto" "github.com/obscuren/otto"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
) )
@@ -25,6 +26,20 @@ type JSRE struct {
objectCb map[string][]otto.Value objectCb map[string][]otto.Value
} }
func (jsre *JSRE) LoadExtFile(path string) {
result, err := ioutil.ReadFile(path)
if err == nil {
jsre.vm.Run(result)
} else {
ethutil.Config.Log.Debugln("Could not load file:", path)
}
}
func (jsre *JSRE) LoadIntFile(file string) {
assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal", "assets", "ext")
jsre.LoadExtFile(path.Join(assetPath, file))
}
func NewJSRE(ethereum *eth.Ethereum) *JSRE { func NewJSRE(ethereum *eth.Ethereum) *JSRE {
re := &JSRE{ re := &JSRE{
ethereum, ethereum,
@@ -39,6 +54,10 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE {
// Init the JS lib // Init the JS lib
re.vm.Run(jsLib) re.vm.Run(jsLib)
// Load extra javascript files
re.LoadIntFile("string.js")
re.LoadIntFile("big.js")
// We have to make sure that, whoever calls this, calls "Stop" // We have to make sure that, whoever calls this, calls "Stop"
go re.mainLoop() go re.mainLoop()

View File

@@ -66,6 +66,10 @@ func (self *JSEthereum) GetBlock(hash string) otto.Value {
return self.toVal(&JSBlock{self.PEthereum.GetBlock(hash), self}) return self.toVal(&JSBlock{self.PEthereum.GetBlock(hash), self})
} }
func (self *JSEthereum) GetPeers() otto.Value {
return self.toVal(self.PEthereum.GetPeers())
}
func (self *JSEthereum) GetKey() otto.Value { func (self *JSEthereum) GetKey() otto.Value {
return self.toVal(self.PEthereum.GetKey()) return self.toVal(self.PEthereum.GetKey())
} }
@@ -74,6 +78,10 @@ func (self *JSEthereum) GetStateObject(addr string) otto.Value {
return self.toVal(self.PEthereum.GetStateObject(addr)) return self.toVal(self.PEthereum.GetStateObject(addr))
} }
func (self *JSEthereum) GetStateKeyVals(addr string) otto.Value {
return self.toVal(self.PEthereum.GetStateObject(addr).StateKeyVal(false))
}
func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value { func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
r, err := self.PEthereum.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr) r, err := self.PEthereum.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr)
if err != nil { if err != nil {
@@ -101,7 +109,7 @@ func (self *JSEthereum) toVal(v interface{}) otto.Value {
result, err := self.vm.ToValue(v) result, err := self.vm.ToValue(v)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println("Value unknown:", err)
return otto.UndefinedValue() return otto.UndefinedValue()
} }

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