Compare commits

..

44 Commits
2 ... poc5-rc12

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
Maran
2114218ed8 Merge branch 'release/poc5-rc11' 2014-05-28 16:19:58 +02:00
Maran
58032d60e7 Bump to RC11 2014-05-28 16:17:57 +02:00
Maran
d4f9daa631 Refactor hex encode and remove coupling of popup to main window 2014-05-28 16:14:24 +02:00
Maran
1eda1d25b0 Hooked up the Block Explorer to the Debugger so we can instantly debug made transactions 2014-05-28 15:48:17 +02:00
obscuren
aaeb268522 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-05-28 13:01:04 +02:00
obscuren
540d39220d Merge branch 'master' into develop 2014-05-28 13:00:51 +02:00
obscuren
09728bf43c Debugger script&data now accept "0x" values 2014-05-28 13:00:45 +02:00
obscuren
090447c664 Data and script in the debugger accept "0x" values and regular scripting 2014-05-28 12:59:10 +02:00
Maran
d4af5a5763 Merge branch 'hotfix/2' into develop 2014-05-28 11:53:31 +02:00
16 changed files with 1486 additions and 1249 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 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,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: "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 {
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);
@@ -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

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

@@ -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,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