Compare commits

...

55 Commits
2 ... 0.5.13

Author SHA1 Message Date
98335d2040 Merge branch 'release/0.5.13' 2014-06-16 18:24:57 +02:00
c1220e8729 bump 2014-06-16 18:24:24 +02:00
3744151359 Removed init fees 2014-06-16 11:15:08 +02:00
7ab735eb02 Max 250 log 2014-06-15 00:02:41 +02:00
ef1b923b31 Added a log level slider which can change the log level 2014-06-14 15:44:32 +02:00
e7a22af0e6 Minor UI adjustments 2014-06-12 10:06:02 +02:00
1d300bbc10 Toggle inspector / reload using magic rectangle 2014-06-11 15:55:47 +02:00
e36badd744 Reimplement -datadir flag. Implements #79
The config file is actually loaded from the folder that datadir points at
2014-06-11 12:33:11 +02:00
57e3b1b093 Implemented usedGas to the explorer 2014-06-11 11:40:13 +02:00
0ee258bb75 Add GasLimit to the block explorer 2014-06-11 10:27:58 +02:00
66199497a0 Merge branch 'release/poc5-rc12' into develop 2014-06-09 22:24:30 +02:00
aa8a86f0a6 Merge branch 'release/poc5-rc12' 2014-06-09 22:24:24 +02:00
d929c63474 bump 2014-06-09 22:23:33 +02:00
ba3623d0cc Fixed debugger hang 2014-06-09 22:04:16 +02:00
cc20b0e3a0 debugger output 2014-06-06 12:13:13 +02:00
a107a5db05 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-06-05 09:01:10 +02:00
964587b14a Added more debugger output 2014-06-05 09:00:57 +02:00
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
307fe4a3cd Add loading of extra build in js files to JS-Repl. Implements #67 2014-06-04 12:19:50 +02:00
3755616a29 Added namereg register option to qml wallet 2014-06-03 14:30:26 +02:00
cc1d043423 Implemented transaction catching up. Implements #73 2014-06-03 11:48:44 +02:00
9e411d785b Tweaks and latency added to peeroverview 2014-06-03 10:42:36 +02:00
a6f4eef1da Added Peer Window 2014-06-02 15:16:37 +02:00
98811f11e5 ethereum instead of ethereal. Fixes #69 2014-05-31 11:43:08 +02:00
d6acb74ac9 fixed logging issue that would otherwise crash the client. Fixes #68 2014-05-31 11:34:37 +02:00
397e99fcc6 Merge branch 'develop' 2014-05-30 20:35:44 +02:00
be27309dbb show first? 2014-05-30 20:35:37 +02:00
4dfce5d347 Merge branch 'develop' 2014-05-30 19:36:21 +02:00
0bdb0a9d58 Added ini file for ethereum. fixes #66 2014-05-30 19:36:05 +02:00
5f28013f79 Merge branch 'develop' 2014-05-30 16:58:17 +02:00
65c5a20e1c Added config file setup. Fixes #59
* Also fixes asset path problems
2014-05-30 16:56:56 +02:00
1020d7ff67 Unified the contract interface and tx interface. Fixes #62 2014-05-30 16:14:46 +02:00
e7c9b86a5a Improved UI
* Added mining button
2014-05-30 13:28:31 +02:00
0938b56829 Update peer info 2014-05-30 13:04:23 +02:00
fcbf99a30a Minor GUI updates
* IceCream => IceCREAM
* Added coin base to block info
2014-05-30 11:50:30 +02:00
40d72ff40b . 2014-05-29 12:24:56 +02:00
efadfbfb17 Minor UI changes
* Moved log from block view
* Prepend instead of append for logs
2014-05-29 12:24:14 +02:00
8ee6574d12 Minimal fee for sending transactions 2014-05-29 12:14:25 +02:00
efb3ee044b Removed regexp for namereg 2014-05-29 11:49:59 +02:00
0b4c42d756 Disabled instruction selection 2014-05-29 02:05:06 +02:00
f0f205004c Merge branch 'develop' 2014-05-28 23:23:52 +02:00
f802e17626 merge 2014-05-28 23:16:15 +02:00
8fab7ce37d Fixes and improved debugger 2014-05-28 23:14:23 +02:00
44db1a1eb2 Add 0x when feeding data to debugger 2014-05-28 18:11:27 +02:00
0aee830bde Fix merge conflict 2014-05-28 16:20:36 +02:00
06d41794f9 Merge branch 'release/poc5-rc11' into develop 2014-05-28 16:20:05 +02:00
2114218ed8 Merge branch 'release/poc5-rc11' 2014-05-28 16:19:58 +02:00
58032d60e7 Bump to RC11 2014-05-28 16:17:57 +02:00
d4f9daa631 Refactor hex encode and remove coupling of popup to main window 2014-05-28 16:14:24 +02:00
1eda1d25b0 Hooked up the Block Explorer to the Debugger so we can instantly debug made transactions 2014-05-28 15:48:17 +02:00
aaeb268522 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-05-28 13:01:04 +02:00
540d39220d Merge branch 'master' into develop 2014-05-28 13:00:51 +02:00
09728bf43c Debugger script&data now accept "0x" values 2014-05-28 13:00:45 +02:00
090447c664 Data and script in the debugger accept "0x" values and regular scripting 2014-05-28 12:59:10 +02:00
d4af5a5763 Merge branch 'hotfix/2' into develop 2014-05-28 11:53:31 +02:00
16 changed files with 1597 additions and 1254 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 RC10. Current state: Proof of Concept 5.0 RC13.
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,15 @@ 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 dataText: rawDataField.text
MenuBar { MenuBar {
Menu { Menu {
@ -29,208 +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: "Temp" ; 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 {
RowLayout {
spacing: 5
Button { Rectangle {
property var enabled: true height: 200
id: debugStart width: parent.width
onClicked: { TableView {
debugCurrent() id: logTableView
} property var logModel: ListModel {
text: "Debug" 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: debugNextButton spacing: 5
onClicked: {
dbg.next()
}
text: "Next"
}
}
}
function debugCurrent() { Button {
dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text) property var enabled: true
} id: debugStart
onClicked: {
debugCurrent()
}
text: "Debug"
}
function setAsm(asm) { Button {
asmModel.append({asm: asm}) property var enabled: true
} id: debugNextButton
onClicked: {
dbg.next()
}
text: "Next"
}
}
}
function clearAsm() { function debugCurrent() {
asmModel.clear() dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text)
} }
function setInstruction(num) { function setAsm(asm) {
asmTableView.selection.clear() asmModel.append({asm: asm})
asmTableView.selection.select(num-1) }
}
function setMem(mem) { function clearAsm() {
memModel.append({num: mem.num, value: mem.value}) asmModel.clear()
} }
function clearMem(){
memModel.clear()
}
function setStack(stack) { function setInstruction(num) {
stackModel.append({value: stack}) asmTableView.selection.clear()
} asmTableView.selection.select(num)
function addDebugMessage(message){ }
debuggerLog.append({value: message})
}
function clearStack() { function setMem(mem) {
stackModel.clear() memModel.append({num: mem.num, value: mem.value})
} }
function clearMem(){
memModel.clear()
}
function clearStorage() { function setStack(stack) {
storageModel.clear() stackModel.append({value: stack})
} }
function addDebugMessage(message){
debuggerLog.append({value: message})
}
function setStorage(storage) { function clearStack() {
storageModel.append({key: storage.key, value: storage.value}) stackModel.clear()
} }
function clearStorage() {
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);
@ -165,6 +170,30 @@ ApplicationWindow {
postEvent(ev, [storageObject.address, storageObject.value]) postEvent(ev, [storageObject.address, storageObject.value])
} }
} }
Rectangle {
id: toggleInspector
color: "#bcbcbc"
visible: true
height: 12
width: 12
anchors {
right: root.right
}
MouseArea {
onClicked: {
if(inspector.visible == true){
inspector.visible = false
}else{
inspector.visible = true
}
}
onDoubleClicked: {
console.log('refreshing')
webView.reload()
}
anchors.fill: parent
}
}
Rectangle { Rectangle {
id: sizeGrip id: sizeGrip

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,26 @@ 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
var Datadir 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.StringVar(&Datadir, "datadir", ".ethereal", "specifies the datadir to use. Takes precedence over config file.")
flag.Parse() flag.Parse()
} }

View File

@ -3,14 +3,15 @@ package main
import ( import (
"fmt" "fmt"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"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"
) )
@ -38,8 +39,15 @@ func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
ethchain.InitFees() g, err := globalconf.NewWithOptions(&globalconf.Options{
ethutil.ReadConfig(DataDir, ethutil.LogFile|ethutil.LogStd, Identifier) Filename: path.Join(ethutil.ApplicationFolder(Datadir), "conf.ini"),
})
if err != nil {
fmt.Println(err)
} else {
g.ParseAll()
}
ethutil.ReadConfig(Datadir, 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 +116,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

@ -26,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}
} }
@ -41,21 +41,18 @@ func (self *DebuggerWindow) Show() {
}() }()
} }
func formatData(data string) []byte { func (self *DebuggerWindow) SetCode(code string) {
if len(data) == 0 { self.win.Set("codeText", code)
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) func (self *DebuggerWindow) SetData(data string) {
self.win.Set("dataText", data)
}
func (self *DebuggerWindow) SetAsm(data string) {
dis := ethchain.Disassemble(ethutil.FromHex(data))
for _, str := range dis {
self.win.Root().Call("setAsm", str)
}
} }
func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, dataStr string) { func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, dataStr string) {
@ -63,42 +60,53 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
self.Db.Q <- true self.Db.Q <- true
} }
dataSlice := strings.Split(dataStr, "\n")
var data []byte
for _, dataItem := range dataSlice {
d := formatData(dataItem)
data = append(data, d...)
}
state := self.lib.eth.BlockChain().CurrentBlock.State()
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
fmt.Println(r) self.Logf("compile FAULT: %v", r)
} }
}() }()
script, err := ethutil.Compile(scriptStr) data := ethutil.StringToByteFunc(dataStr, func(s string) (ret []byte) {
slice := strings.Split(dataStr, "\n")
for _, dataItem := range slice {
d := ethutil.FormatData(dataItem)
ret = append(ret, d...)
}
return
})
var err error
script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
ret, err = ethutil.Compile(s)
fmt.Printf("%x\n", ret)
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()
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{
@ -108,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 {
@ -161,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
} }
@ -170,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 RC10" const version = "0.5.0 RC13"
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("Ethereal")
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,17 @@ 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
}
func (gui *Gui) SetLogLevel(level int) {
ethutil.Config.Log.SetLevel(level)
} }

View File

@ -24,8 +24,9 @@ type UiLib struct {
connected bool connected bool
assetPath string assetPath string
// The main application window // The main application window
win *qml.Window win *qml.Window
Db *Debugger Db *Debugger
DbWindow *DebuggerWindow
} }
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib { func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
@ -88,9 +89,26 @@ func (ui *UiLib) ConnectToPeer(addr string) {
func (ui *UiLib) AssetPath(p string) string { func (ui *UiLib) AssetPath(p string) string {
return path.Join(ui.assetPath, p) return path.Join(ui.assetPath, p)
} }
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
dbWindow := NewDebuggerWindow(self)
object := self.eth.StateManager().CurrentState().GetStateObject(ethutil.FromHex(contractHash))
if len(object.Script()) > 0 {
dbWindow.SetCode("0x" + ethutil.Hex(object.Script()))
}
dbWindow.SetData("0x" + data)
dbWindow.Show()
}
func (self *UiLib) StartDbWithCode(code string) {
dbWindow := NewDebuggerWindow(self)
dbWindow.SetCode("0x" + code)
dbWindow.Show()
}
func (self *UiLib) StartDebugger() { func (self *UiLib) StartDebugger() {
dbWindow := NewDebuggerWindow(self) dbWindow := NewDebuggerWindow(self)
//self.DbWindow = dbWindow
dbWindow.Show() dbWindow.Show()
} }

View File

@ -20,33 +20,35 @@ 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
var Datadir string
func Init() { func Init() {
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s [options] [filename]:\n", os.Args[0]) fmt.Fprintf(os.Stderr, "%s [options] [filename]:\n", os.Args[0])
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.StringVar(&Datadir, "datadir", ".ethereum", "specifies the datadir to use. Takes precedence over config file.")
flag.Parse() flag.Parse()

View File

@ -3,13 +3,14 @@ package main
import ( import (
"fmt" "fmt"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"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 +60,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(Datadir), "conf.ini"),
})
if err != nil {
fmt.Println(err)
} else {
g.ParseAll()
}
ethutil.ReadConfig(Datadir, lt, g, Identifier)
logger := ethutil.Config.Log logger := ethutil.Config.Log
@ -76,8 +85,6 @@ func main() {
logSys = log.New(os.Stdout, "", flags) logSys = log.New(os.Stdout, "", flags)
} }
ethchain.InitFees()
// Instantiated a eth stack // Instantiated a eth stack
ethereum, err := eth.New(eth.CapDefault, UseUPnP) ethereum, err := eth.New(eth.CapDefault, UseUPnP)
if err != nil { if err != nil {

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