Compare commits

...

56 Commits

Author SHA1 Message Date
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
Maran
d4af5a5763 Merge branch 'hotfix/2' into develop 2014-05-28 11:53:31 +02:00
Maran
198ef97108 Merge branch 'hotfix/2' 2014-05-28 11:53:07 +02:00
Maran
138b7fe2d8 Consolidated external qml files to hopefully prevent crashing bug 2014-05-28 11:52:52 +02:00
obscuren
87a669aeda Merge branch 'develop' 2014-05-27 16:23:59 +02:00
obscuren
969b4a4a36 Added some shortcuts 2014-05-27 16:23:53 +02:00
obscuren
118860abb2 Merge branch 'release/poc5-rc10' into develop 2014-05-27 16:11:08 +02:00
obscuren
0dda955f90 Merge branch 'release/poc5-rc10' 2014-05-27 16:11:01 +02:00
obscuren
34b861c19c bump 2014-05-27 16:10:15 +02:00
obscuren
a0f73c2703 Minor fixes and improvements to the ui 2014-05-27 16:09:04 +02:00
obscuren
2be9823010 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop
Conflicts:
	ethereal/assets/qml/wallet.qml
2014-05-27 13:31:57 +02:00
obscuren
47417506c3 New debugger implemented 2014-05-27 13:28:11 +02:00
obscuren
d0b31e2030 New debugger 2014-05-27 13:09:47 +02:00
Maran
6fe42f007c Uhm what 2014-05-27 12:46:02 +02:00
Maran
1ab865a994 Adding new blocks on broadcast 2014-05-27 11:49:42 +02:00
obscuren
4fd267a778 Sep debugger from main 2014-05-27 10:42:37 +02:00
Maran
07204f129e Increase size for asm 2014-05-27 10:38:51 +02:00
Maran
47a58b40cd Removed recursive function for loop 2014-05-27 10:29:39 +02:00
Maran
474c85bc9d Fix merge conflict 2014-05-27 10:29:12 +02:00
obscuren
d694e00a33 Fixed debugger 2014-05-26 21:11:38 +02:00
Maran
f7eb4e587f Remove extra log statement 2014-05-26 17:18:34 +02:00
Maran
5fc6ee6a4a Implemented simple block/tx explorer 2014-05-26 17:07:20 +02:00
Maran
5374a95c58 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-05-26 10:53:58 +02:00
obscuren
26ecf4b780 Merge branch 'release/poc5-rc9' into develop 2014-05-26 00:42:03 +02:00
obscuren
0d89c1d212 Merge branch 'release/poc5-rc9' 2014-05-26 00:41:55 +02:00
obscuren
818bc84591 Bump 2014-05-26 00:39:05 +02:00
obscuren
b42c70be9c Recv send for txs 2014-05-26 00:10:38 +02:00
obscuren
d35380c19e New main script through init return value 2014-05-23 14:37:03 +02:00
Maran
36683f2e29 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-05-23 10:29:17 +02:00
obscuren
5f8911f7cb Custom identifier 2014-05-22 10:38:37 +02:00
Maran
6b115659ca Hide inspector by default 2014-05-22 10:27:21 +02:00
Maran
8419ba0ec0 Fix merge conflicts 2014-05-22 10:26:39 +02:00
obscuren
01b833146f Added mining stop and start 2014-05-22 00:25:48 +02:00
obscuren
b902de20c7 Fixes #49 2014-05-21 23:46:16 +02:00
obscuren
3f5b348451 Fixes #50 2014-05-21 23:36:55 +02:00
Maran
93d79babc9 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-05-21 14:07:45 +02:00
obscuren
941e0ba60a Merge branch 'release/poc5-rc8' into develop 2014-05-21 14:05:01 +02:00
obscuren
7f1a4c377c Merge branch 'release/poc5-rc8' 2014-05-21 14:04:54 +02:00
obscuren
3ddaf56afd Bumped 2014-05-21 14:04:11 +02:00
obscuren
10e2c40b59 Improved on some ui elements 2014-05-21 14:00:54 +02:00
obscuren
68f4a12a8b Fixed unconfirmed balance string 2014-05-21 13:37:46 +02:00
Maran
34008da807 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-05-21 12:14:55 +02:00
obscuren
16bd88c10a Removed method name 2014-05-21 12:14:39 +02:00
Maran
0bccf1c3cd Wait with mining until up to date 2014-05-21 11:45:19 +02:00
obscuren
d16d56d39f Updated readme to reflect options 2014-05-20 22:13:39 +02:00
obscuren
93e12250c7 Switch variables as intended 2014-05-20 22:12:42 +02:00
obscuren
f4551a7e9f Changed flag parsing 2014-05-20 22:12:22 +02:00
obscuren
563c035eb5 Refactored some of the functions 2014-05-20 19:28:48 +02:00
obscuren
de1dfae717 Forked version of otto so we can support lowerCased methods 2014-05-20 17:49:12 +02:00
obscuren
4198969302 Merge branch 'release/poc5-rc7' into develop 2014-05-20 17:09:36 +02:00
18 changed files with 1622 additions and 841 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 RC7. Current state: Proof of Concept 5.0 RC11.
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).
@@ -26,28 +26,25 @@ General command line options
==================== ====================
``` ```
-c Launch the developer console (node only) Shared between ethereum and ethereal
-m Start mining blocks -m Start mining blocks
-genaddr Generates a new address and private key (destructive action) -genaddr Generates a new address and private key (destructive action)
-p Port on which the server will accept incomming connections (= 30303) -p Port on which the server will accept incomming connections
-upnp Enable UPnP (= false) -upnp Enable UPnP
-x Desired amount of peers (= 5) -x Desired amount of peers
-h This help
-r Start JSON RPC -r Start JSON RPC
-dir Data directory used to store configs and databases (=".ethereum") -dir Data directory used to store configs and databases
-import Import a private key (hex) -import Import a private key
``` -h This
Developer console commands Ethereum only
========================== ethereum [options] [filename]
-js Start the JavaScript REPL
filename Load the given file and interpret as JavaScript
Etheral only
-asset_path absolute path to GUI assets directory
``` ```
addp <host>:<port> Connect to the given host
tx <addr> <amount> Send <amount> Wei to the specified <addr>
contract <value> <gasprice> Creates a new contract and launches the editor
```
See the "help" command for *developer* options.
Contribution Contribution
============ ============

View File

@@ -0,0 +1,240 @@
import QtQuick 2.0
import QtQuick.Controls 1.0;
import QtQuick.Layouts 1.0;
import QtQuick.Dialogs 1.0;
import QtQuick.Window 2.1;
import QtQuick.Controls.Styles 1.1
import Ethereum 1.0
ApplicationWindow {
visible: false
title: "IceCream"
minimumWidth: 1280
minimumHeight: 900
width: 1290
height: 900
property alias codeText: codeEditor.text
property alias dataText: rawDataField.text
MenuBar {
Menu {
title: "Debugger"
MenuItem {
text: "Run"
shortcut: "Ctrl+r"
onTriggered: debugCurrent()
}
MenuItem {
text: "Next"
shortcut: "Ctrl+n"
onTriggered: dbg.next()
}
}
}
SplitView {
anchors.fill: parent
property var asmModel: ListModel {
id: asmModel
}
TableView {
id: asmTableView
width: 200
TableViewColumn{ role: "value" ; title: "" ; width: 100 }
model: asmModel
}
Rectangle {
color: "#00000000"
anchors.left: asmTableView.right
anchors.right: parent.right
SplitView {
orientation: Qt.Vertical
anchors.fill: parent
Rectangle {
color: "#00000000"
height: 500
anchors.left: parent.left
anchors.right: parent.right
TextArea {
id: codeEditor
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: settings.left
}
Column {
id: settings
spacing: 5
width: 300
height: parent.height
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
Label {
text: "Arbitrary data"
}
TextArea {
id: rawDataField
anchors.left: parent.left
anchors.right: parent.right
height: 150
}
Label {
text: "Amount"
}
TextField {
id: txValue
width: 200
placeholderText: "Amount"
validator: RegExpValidator { regExp: /\d*/ }
}
Label {
text: "Amount of gas"
}
TextField {
id: txGas
width: 200
validator: RegExpValidator { regExp: /\d*/ }
text: "10000"
placeholderText: "Gas"
}
Label {
text: "Gas price"
}
TextField {
id: txGasPrice
width: 200
placeholderText: "Gas price"
text: "1000000000000"
validator: RegExpValidator { regExp: /\d*/ }
}
}
}
SplitView {
orientation: Qt.Vertical
id: inspectorPane
height: 500
SplitView {
orientation: Qt.Horizontal
height: 250
TableView {
id: stackTableView
property var stackModel: ListModel {
id: stackModel
}
height: parent.height
width: 300
TableViewColumn{ role: "value" ; title: "Stack" ; width: 200 }
model: stackModel
}
TableView {
id: memoryTableView
property var memModel: ListModel {
id: memModel
}
height: parent.height
width: parent.width - stackTableView.width
TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50}
TableViewColumn{ role: "value" ; title: "Memory" ; width: 750}
model: memModel
}
}
SplitView {
height: 300
TableView {
id: storageTableView
property var memModel: ListModel {
id: storageModel
}
height: parent.height
width: parent.width - stackTableView.width
TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2}
TableViewColumn{ role: "value" ; title: "value" ; width: storageTableView.width / 2}
model: storageModel
}
}
}
}
}
}
toolBar: ToolBar {
RowLayout {
spacing: 5
Button {
property var enabled: true
id: debugStart
onClicked: {
debugCurrent()
}
text: "Debug"
}
Button {
property var enabled: true
id: debugNextButton
onClicked: {
dbg.next()
}
text: "Next"
}
}
}
function debugCurrent() {
dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text, rawDataField.text)
}
function setAsm(asm) {
asmModel.append({asm: asm})
}
function clearAsm() {
asmModel.clear()
}
function setInstruction(num) {
asmTableView.selection.clear()
asmTableView.selection.select(num)
}
function setMem(mem) {
memModel.append({num: mem.num, value: mem.value})
}
function clearMem(){
memModel.clear()
}
function setStack(stack) {
stackModel.append({value: stack})
}
function addDebugMessage(message){
debuggerLog.append({value: message})
}
function clearStack() {
stackModel.clear()
}
function clearStorage() {
storageModel.clear()
}
function setStorage(storage) {
storageModel.append({key: storage.key, value: storage.value})
}
}

BIN
ethereal/assets/heart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,196 +0,0 @@
import QtQuick 2.0
import QtQuick.Controls 1.0;
import QtQuick.Layouts 1.0;
import QtQuick.Dialogs 1.0;
import QtQuick.Window 2.1;
import QtQuick.Controls.Styles 1.1
import Ethereum 1.0
Component {
id: newContract
Column {
id: mainContractColumn
function contractFormReady(){
if(codeView.text.length > 0 && txValue.text.length > 0 && txGas.text.length > 0 && txGasPrice.length > 0) {
txButton.state = "READY"
}else{
txButton.state = "NOTREADY"
}
}
states: [
State{
name: "ERROR"
PropertyChanges { target: txResult; visible:true}
PropertyChanges { target: codeView; visible:true}
},
State {
name: "DONE"
PropertyChanges { target: txValue; visible:false}
PropertyChanges { target: txGas; visible:false}
PropertyChanges { target: txGasPrice; visible:false}
PropertyChanges { target: codeView; visible:false}
PropertyChanges { target: txButton; visible:false}
PropertyChanges { target: txDataLabel; visible:false}
PropertyChanges { target: txResult; visible:true}
PropertyChanges { target: txOutput; visible:true}
PropertyChanges { target: newTxButton; visible:true}
},
State {
name: "SETUP"
PropertyChanges { target: txValue; visible:true; text: ""}
PropertyChanges { target: txGas; visible:true; text: ""}
PropertyChanges { target: txGasPrice; visible:true; text: ""}
PropertyChanges { target: codeView; visible:true; text: ""}
PropertyChanges { target: txButton; visible:true}
PropertyChanges { target: txDataLabel; visible:true}
PropertyChanges { target: txResult; visible:false}
PropertyChanges { target: txOutput; visible:false}
PropertyChanges { target: newTxButton; visible:false}
}
]
width: 400
spacing: 5
anchors.left: parent.left
anchors.top: parent.top
anchors.leftMargin: 5
anchors.topMargin: 5
TextField {
id: txValue
width: 200
placeholderText: "Amount"
validator: RegExpValidator { regExp: /\d*/ }
onTextChanged: {
contractFormReady()
}
}
TextField {
id: txGas
width: 200
validator: RegExpValidator { regExp: /\d*/ }
placeholderText: "Gas"
onTextChanged: {
contractFormReady()
}
}
TextField {
id: txGasPrice
width: 200
placeholderText: "Gas price"
validator: RegExpValidator { regExp: /\d*/ }
onTextChanged: {
contractFormReady()
}
}
Row {
id: rowContract
ExclusiveGroup { id: contractTypeGroup }
RadioButton {
id: createContractRadio
text: "Create contract"
checked: true
exclusiveGroup: contractTypeGroup
onClicked: {
txFuelRecipient.visible = false
txDataLabel.text = "Contract code"
}
}
RadioButton {
id: runContractRadio
text: "Run contract"
exclusiveGroup: contractTypeGroup
onClicked: {
txFuelRecipient.visible = true
txDataLabel.text = "Contract arguments"
}
}
}
Label {
id: txDataLabel
text: "Contract code"
}
TextArea {
id: codeView
height: 300
anchors.topMargin: 5
Layout.fillWidth: true
width: parent.width /2
onTextChanged: {
contractFormReady()
}
}
TextField {
id: txFuelRecipient
placeholderText: "Contract address"
validator: RegExpValidator { regExp: /[a-f0-9]{40}/ }
visible: false
width: 530
}
Button {
id: txButton
/* enabled: false */
states: [
State {
name: "READY"
PropertyChanges { target: txButton; /*enabled: true*/}
},
State {
name: "NOTREADY"
PropertyChanges { target: txButton; /*enabled:false*/}
}
]
text: "Send"
onClicked: {
//this.enabled = false
var res = eth.create(txFuelRecipient.text, txValue.text, txGas.text, txGasPrice.text, codeView.text)
if(res[1]) {
txResult.text = "Your contract <b>could not</b> be send over the network:\n<b>"
txResult.text += res[1].error()
txResult.text += "</b>"
mainContractColumn.state = "ERROR"
} else {
txResult.text = "Your transaction has been submitted:\n"
txOutput.text = res[0].address
mainContractColumn.state = "DONE"
}
}
}
Text {
id: txResult
visible: false
}
TextField {
id: txOutput
visible: false
width: 530
}
Button {
id: newTxButton
visible: false
text: "Create an other contract"
onClicked: {
this.visible = false
txResult.text = ""
txOutput.text = ""
mainContractColumn.state = "SETUP"
}
}
Button {
id: debugButton
text: "Debug"
onClicked: {
var res = ui.debugTx("", txValue.text, txGas.text, txGasPrice.text, codeView.text)
debugWindow.visible = true
}
}
}
}

View File

@@ -1,112 +0,0 @@
import QtQuick 2.0
import QtQuick.Controls 1.0;
import QtQuick.Layouts 1.0;
import QtQuick.Dialogs 1.0;
import QtQuick.Window 2.1;
import QtQuick.Controls.Styles 1.1
import Ethereum 1.0
Component {
id: newTransaction
Column {
id: simpleSendColumn
states: [
State{
name: "ERROR"
},
State {
name: "DONE"
PropertyChanges { target: txSimpleValue; visible:false}
PropertyChanges { target: txSimpleRecipient; visible:false}
PropertyChanges { target:newSimpleTxButton; visible:false}
PropertyChanges { target: txSimpleResult; visible:true}
PropertyChanges { target: txSimpleOutput; visible:true}
PropertyChanges { target:newSimpleTxButton; visible:true}
},
State {
name: "SETUP"
PropertyChanges { target: txSimpleValue; visible:true; text: ""}
PropertyChanges { target: txSimpleRecipient; visible:true; text: ""}
PropertyChanges { target: txSimpleButton; visible:true}
PropertyChanges { target:newSimpleTxButton; visible:false}
}
]
spacing: 5
anchors.leftMargin: 5
anchors.topMargin: 5
anchors.top: parent.top
anchors.left: parent.left
function checkFormState(){
if(txSimpleRecipient.text.length == 40 && txSimpleValue.text.length > 0) {
txSimpleButton.state = "READY"
}else{
txSimpleButton.state = "NOTREADY"
}
}
TextField {
id: txSimpleRecipient
placeholderText: "Recipient address"
Layout.fillWidth: true
validator: RegExpValidator { regExp: /[a-f0-9]{40}/ }
width: 530
onTextChanged: { checkFormState() }
}
TextField {
id: txSimpleValue
width: 200
placeholderText: "Amount"
anchors.rightMargin: 5
validator: RegExpValidator { regExp: /\d*/ }
onTextChanged: { checkFormState() }
}
Button {
id: txSimpleButton
/*enabled: false*/
states: [
State {
name: "READY"
PropertyChanges { target: txSimpleButton; /*enabled: true*/}
},
State {
name: "NOTREADY"
PropertyChanges { target: txSimpleButton; /*enabled: false*/}
}
]
text: "Send"
onClicked: {
//this.enabled = false
var res = eth.transact(txSimpleRecipient.text, txSimpleValue.text,"","","")
if(res[1]) {
txSimpleResult.text = "There has been an error broadcasting your transaction:" + res[1].error()
} else {
txSimpleResult.text = "Your transaction has been broadcasted over the network.\nYour transaction id is:"
txSimpleOutput.text = res[0].hash
this.visible = false
simpleSendColumn.state = "DONE"
}
}
}
Text {
id: txSimpleResult
visible: false
}
TextField {
id: txSimpleOutput
visible: false
width: 530
}
Button {
id: newSimpleTxButton
visible: false
text: "Create an other transaction"
onClicked: {
this.visible = false
simpleSendColumn.state = "SETUP"
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -4,6 +4,7 @@ import (
"flag" "flag"
) )
var Identifier string
var StartConsole bool var StartConsole bool
var StartMining bool var StartMining bool
var StartRpc bool var StartRpc bool
@@ -21,6 +22,7 @@ var DataDir string
var AssetPath string var AssetPath string
func Init() { func Init() {
flag.StringVar(&Identifier, "i", "", "Custom client identifier")
flag.BoolVar(&StartConsole, "c", false, "debug and testing console") flag.BoolVar(&StartConsole, "c", false, "debug and testing console")
flag.BoolVar(&StartMining, "m", false, "start dagger mining") flag.BoolVar(&StartMining, "m", false, "start dagger mining")
flag.BoolVar(&StartRpc, "r", false, "start rpc server") flag.BoolVar(&StartRpc, "r", false, "start rpc server")

View File

@@ -39,7 +39,7 @@ func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
ethchain.InitFees() ethchain.InitFees()
ethutil.ReadConfig(DataDir, ethutil.LogFile|ethutil.LogStd) ethutil.ReadConfig(DataDir, ethutil.LogFile|ethutil.LogStd, Identifier)
// Instantiated a eth stack // Instantiated a eth stack
ethereum, err := eth.New(eth.CapDefault, UseUPnP) ethereum, err := eth.New(eth.CapDefault, UseUPnP)

199
ethereal/ui/debugger.go Normal file
View File

@@ -0,0 +1,199 @@
package ethui
import (
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml"
"math/big"
"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 {
win *qml.Window
engine *qml.Engine
lib *UiLib
Db *Debugger
}
func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
engine := qml.NewEngine()
component, err := engine.LoadFile(lib.AssetPath("debugger/debugger.qml"))
if err != nil {
fmt.Println(err)
return nil
}
win := component.CreateWindow(nil)
db := &Debugger{win, make(chan bool), make(chan bool), true}
return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db}
}
func (self *DebuggerWindow) Show() {
context := self.engine.Context()
context.SetVar("dbg", self)
go func() {
self.win.Show()
self.win.Wait()
}()
}
func (self *DebuggerWindow) SetCode(code string) {
self.win.Set("codeText", code)
}
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) {
if !self.Db.done {
self.Db.Q <- true
}
defer func() {
if r := recover(); r != nil {
fmt.Println(r)
self.Db.done = true
}
}()
data := ethutil.StringToByteFunc(dataStr, func(s string) (ret []byte) {
slice := strings.Split(dataStr, "\n")
for _, dataItem := range slice {
d := formatData(dataItem)
ret = append(ret, d...)
}
return
})
var err error
script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
ret, err = ethutil.Compile(s)
return
})
if err != nil {
ethutil.Config.Log.Debugln(err)
return
}
dis := ethchain.Disassemble(script)
self.win.Root().Call("clearAsm")
for _, str := range dis {
self.win.Root().Call("setAsm", str)
}
// Contract addr as test address
keyPair := ethutil.GetKeyRing().Get(0)
callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script)
callerTx.Sign(keyPair.PrivateKey)
state := self.lib.eth.BlockChain().CurrentBlock.State()
account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address())
contract := ethchain.MakeContract(callerTx, state)
callerClosure := ethchain.NewClosure(account, contract, script, state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr))
block := self.lib.eth.BlockChain().CurrentBlock
vm := ethchain.NewVm(state, self.lib.eth.StateManager(), ethchain.RuntimeVars{
Origin: account.Address(),
BlockNumber: block.BlockInfo().Number,
PrevHash: block.PrevHash,
Coinbase: block.Coinbase,
Time: block.Time,
Diff: block.Difficulty,
})
self.Db.done = false
go func() {
callerClosure.Call(vm, data, self.Db.halting)
state.Reset()
self.Db.done = true
}()
}
func (self *DebuggerWindow) Next() {
self.Db.Next()
}
type Debugger struct {
win *qml.Window
N chan bool
Q chan bool
done bool
}
type storeVal struct {
Key, Value string
}
func (d *Debugger) halting(pc int, op ethchain.OpCode, mem *ethchain.Memory, stack *ethchain.Stack, stateObject *ethchain.StateObject) bool {
d.win.Root().Call("setInstruction", pc)
d.win.Root().Call("clearMem")
d.win.Root().Call("clearStack")
d.win.Root().Call("clearStorage")
addr := 0
for i := 0; i+32 <= mem.Len(); i += 32 {
d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("% x", mem.Data()[i:i+32])})
addr++
}
for _, val := range stack.Data() {
d.win.Root().Call("setStack", val.String())
}
stateObject.State().EachStorage(func(key string, node *ethutil.Value) {
d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
})
out:
for {
select {
case <-d.N:
break out
case <-d.Q:
d.done = true
return false
}
}
return true
}
func (d *Debugger) Next() {
if !d.done {
d.N <- true
}
}

View File

@@ -9,7 +9,6 @@ import (
"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/go-qml/qml" "github.com/go-qml/qml"
"github.com/obscuren/mutan"
"math/big" "math/big"
"strings" "strings"
) )
@@ -55,7 +54,7 @@ func New(ethereum *eth.Ethereum) *Gui {
} }
func (gui *Gui) Start(assetPath string) { func (gui *Gui) Start(assetPath string) {
const version = "0.5.0 RC7" const version = "0.5.0 RC11"
defer gui.txDb.Close() defer gui.txDb.Close()
@@ -74,6 +73,7 @@ func (gui *Gui) Start(assetPath string) {
// Expose the eth library and the ui library to QML // Expose the eth library and the ui library to QML
context.SetVar("eth", gui) context.SetVar("eth", gui)
context.SetVar("pub", gui.pub)
gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath) gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath)
context.SetVar("ui", gui.uiLib) context.SetVar("ui", gui.uiLib)
@@ -130,20 +130,19 @@ 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)} db := &Debugger{gui.win, make(chan bool), make(chan bool), true}
gui.lib.Db = db gui.lib.Db = db
gui.uiLib.Db = db gui.uiLib.Db = db
return gui.win return gui.win
} }
func (gui *Gui) setInitialBlockChain() { func (gui *Gui) setInitialBlockChain() {
// Load previous 10 blocks sBlk := gui.eth.BlockChain().LastBlockHash
chain := gui.eth.BlockChain().GetChain(gui.eth.BlockChain().CurrentBlock.Hash(), 10) blk := gui.eth.BlockChain().GetBlock(sBlk)
for _, block := range chain { for ; blk != nil; blk = gui.eth.BlockChain().GetBlock(sBlk) {
gui.processBlock(block) sBlk = blk.PrevHash
gui.processBlock(blk, true)
} }
} }
func (gui *Gui) readPreviousTransactions() { func (gui *Gui) readPreviousTransactions() {
@@ -151,20 +150,28 @@ func (gui *Gui) readPreviousTransactions() {
for it.Next() { for it.Next() {
tx := ethchain.NewTransactionFromBytes(it.Value()) tx := ethchain.NewTransactionFromBytes(it.Value())
gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) var inout string
if bytes.Compare(tx.Sender(), gui.addr) == 0 {
inout = "send"
} else {
inout = "recv"
}
gui.win.Root().Call("addTx", ethpub.NewPTx(tx), inout)
} }
it.Release() it.Release()
} }
func (gui *Gui) processBlock(block *ethchain.Block) { func (gui *Gui) processBlock(block *ethchain.Block, initial bool) {
gui.win.Root().Call("addBlock", ethpub.NewPBlock(block)) gui.win.Root().Call("addBlock", ethpub.NewPBlock(block), initial)
} }
func (gui *Gui) setWalletValue(amount, unconfirmedFunds *big.Int) { func (gui *Gui) setWalletValue(amount, unconfirmedFunds *big.Int) {
var str string var str string
if unconfirmedFunds != nil { if unconfirmedFunds != nil {
pos := "+" pos := "+"
if unconfirmedFunds.Cmp(big.NewInt(0)) >= 0 { if unconfirmedFunds.Cmp(big.NewInt(0)) < 0 {
pos = "-" pos = "-"
} }
val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds))) val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds)))
@@ -196,6 +203,7 @@ func (gui *Gui) update() {
select { select {
case b := <-blockChan: case b := <-blockChan:
block := b.Resource.(*ethchain.Block) block := b.Resource.(*ethchain.Block)
gui.processBlock(block, false)
if bytes.Compare(block.Coinbase, gui.addr) == 0 { if bytes.Compare(block.Coinbase, gui.addr) == 0 {
gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.addr).Amount, nil) gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.addr).Amount, nil)
} }
@@ -206,18 +214,13 @@ func (gui *Gui) update() {
if txMsg.Event == "newTx:pre" { if txMsg.Event == "newTx:pre" {
object := state.GetAccount(gui.addr) object := state.GetAccount(gui.addr)
if bytes.Compare(tx.Sender(), gui.addr) == 0 && object.Nonce <= tx.Nonce { if bytes.Compare(tx.Sender(), gui.addr) == 0 {
gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "send")
gui.txDb.Put(tx.Hash(), tx.RlpEncode()) gui.txDb.Put(tx.Hash(), tx.RlpEncode())
/*
object.Nonce += 1
state.SetStateObject(object)
*/
unconfirmedFunds.Sub(unconfirmedFunds, tx.Value) unconfirmedFunds.Sub(unconfirmedFunds, tx.Value)
} else if bytes.Compare(tx.Recipient, gui.addr) == 0 { } else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "recv")
gui.txDb.Put(tx.Hash(), tx.RlpEncode()) gui.txDb.Put(tx.Hash(), tx.RlpEncode())
unconfirmedFunds.Add(unconfirmedFunds, tx.Value) unconfirmedFunds.Add(unconfirmedFunds, tx.Value)
@@ -234,7 +237,7 @@ func (gui *Gui) update() {
gui.setWalletValue(object.Amount, nil) gui.setWalletValue(object.Amount, nil)
state.SetStateObject(object) state.UpdateStateObject(object)
} }
} }
} }
@@ -266,7 +269,5 @@ 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)
mainInput, initInput := mutan.PreParse(data) return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, data)
return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, initInput, mainInput)
} }

View File

@@ -2,13 +2,10 @@ package ethui
import ( import (
"bitbucket.org/kardianos/osext" "bitbucket.org/kardianos/osext"
"fmt"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"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/go-qml/qml" "github.com/go-qml/qml"
"github.com/obscuren/mutan"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@@ -27,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 {
@@ -91,6 +89,29 @@ 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(data)
dbWindow.Show()
}
func (self *UiLib) StartDbWithCode(code string) {
dbWindow := NewDebuggerWindow(self)
dbWindow.SetCode("0x" + code)
dbWindow.Show()
}
func (self *UiLib) StartDebugger() {
dbWindow := NewDebuggerWindow(self)
//self.DbWindow = dbWindow
dbWindow.Show()
}
func DefaultAssetPath() string { func DefaultAssetPath() string {
var base string var base string
@@ -121,27 +142,28 @@ func DefaultAssetPath() string {
func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) { func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) {
state := ui.eth.BlockChain().CurrentBlock.State() state := ui.eth.BlockChain().CurrentBlock.State()
mainInput, _ := mutan.PreParse(data) script, err := ethutil.Compile(data)
callerScript, err := utils.Compile(mainInput)
if err != nil { if err != nil {
ethutil.Config.Log.Debugln(err) ethutil.Config.Log.Debugln(err)
return return
} }
dis := ethchain.Disassemble(callerScript) dis := ethchain.Disassemble(script)
ui.win.Root().Call("clearAsm") ui.win.Root().Call("clearAsm")
for _, str := range dis { for _, str := range dis {
ui.win.Root().Call("setAsm", str) ui.win.Root().Call("setAsm", str)
} }
callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), callerScript, nil)
// 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.Sign(keyPair.PrivateKey)
account := ui.eth.StateManager().TransState().GetStateObject(keyPair.Address()) account := ui.eth.StateManager().TransState().GetStateObject(keyPair.Address())
c := ethchain.MakeContract(callerTx, state) contract := ethchain.MakeContract(callerTx, state)
callerClosure := ethchain.NewClosure(account, c, c.Script(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr)) callerClosure := ethchain.NewClosure(account, contract, contract.Init(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr))
block := ui.eth.BlockChain().CurrentBlock block := ui.eth.BlockChain().CurrentBlock
vm := ethchain.NewVm(state, ui.eth.StateManager(), ethchain.RuntimeVars{ vm := ethchain.NewVm(state, ui.eth.StateManager(), ethchain.RuntimeVars{
@@ -151,50 +173,18 @@ func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string)
Coinbase: block.Coinbase, Coinbase: block.Coinbase,
Time: block.Time, Time: block.Time,
Diff: block.Difficulty, Diff: block.Difficulty,
TxData: nil,
}) })
ui.Db.done = false
go func() { go func() {
callerClosure.Call(vm, nil, ui.Db.halting) callerClosure.Call(vm, contract.Init(), ui.Db.halting)
state.Reset() state.Reset()
ui.Db.done = true
}() }()
} }
func (ui *UiLib) Next() { func (ui *UiLib) Next() {
ui.Db.Next() ui.Db.Next()
} }
type Debugger struct {
win *qml.Window
N chan bool
}
func (d *Debugger) halting(pc int, op ethchain.OpCode, mem *ethchain.Memory, stack *ethchain.Stack) {
d.win.Root().Call("setInstruction", pc)
d.win.Root().Call("clearMem")
d.win.Root().Call("clearStack")
addr := 0
for i := 0; i+32 <= mem.Len(); i += 32 {
d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("% x", mem.Data()[i:i+32])})
addr++
}
for _, val := range stack.Data() {
d.win.Root().Call("setStack", val.String())
}
out:
for {
select {
case <-d.N:
break out
default:
}
}
}
func (d *Debugger) Next() {
d.N <- true
}

View File

@@ -2,8 +2,11 @@ package main
import ( import (
"flag" "flag"
"fmt"
"os"
) )
var Identifier string
var StartMining bool var StartMining bool
var StartRpc bool var StartRpc bool
var RpcPort int var RpcPort int
@@ -23,6 +26,12 @@ var StartJsConsole bool
var InputFile string var InputFile string
func Init() { func Init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s [options] [filename]:\n", os.Args[0])
flag.PrintDefaults()
}
flag.StringVar(&Identifier, "i", "", "custom client identifier")
flag.BoolVar(&StartMining, "m", false, "start dagger mining") flag.BoolVar(&StartMining, "m", false, "start dagger mining")
flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits") flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits")
flag.BoolVar(&StartRpc, "r", false, "start rpc server") flag.BoolVar(&StartRpc, "r", false, "start rpc server")
@@ -38,7 +47,8 @@ func Init() {
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.IntVar(&MaxPeer, "x", 10, "maximum desired peers")
flag.BoolVar(&StartJsConsole, "js", false, "exp") flag.BoolVar(&StartJsConsole, "js", false, "exp")
flag.StringVar(&InputFile, "e", "", "Run javascript file")
flag.Parse() flag.Parse()
InputFile = flag.Arg(0)
} }

View File

@@ -52,12 +52,15 @@ func main() {
var logSys *log.Logger var logSys *log.Logger
flags := log.LstdFlags flags := log.LstdFlags
var lt ethutil.LoggerType
if StartJsConsole || len(InputFile) > 0 { if StartJsConsole || len(InputFile) > 0 {
ethutil.ReadConfig(DataDir, ethutil.LogFile) lt = ethutil.LogFile
} else { } else {
ethutil.ReadConfig(DataDir, ethutil.LogFile|ethutil.LogStd) lt = ethutil.LogFile | ethutil.LogStd
} }
ethutil.ReadConfig(DataDir, lt, Identifier)
logger := ethutil.Config.Log logger := ethutil.Config.Log
if LogFile != "" { if LogFile != "" {

View File

@@ -6,7 +6,11 @@ import (
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
"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/robertkrimen/otto" "github.com/ethereum/go-ethereum/utils"
"github.com/obscuren/otto"
"io/ioutil"
"os"
"path/filepath"
) )
type JSRE struct { type JSRE struct {
@@ -53,6 +57,22 @@ func (self *JSRE) Run(code string) (otto.Value, error) {
return self.vm.Run(code) return self.vm.Run(code)
} }
func (self *JSRE) Require(file string) error {
if len(filepath.Ext(file)) == 0 {
file += ".js"
}
fh, err := os.Open(file)
if err != nil {
return err
}
content, _ := ioutil.ReadAll(fh)
self.Run("exports = {};(function() {" + string(content) + "})();")
return nil
}
func (self *JSRE) Stop() { func (self *JSRE) Stop() {
// Kill the main loop // Kill the main loop
self.quitChan <- true self.quitChan <- true
@@ -82,7 +102,10 @@ out:
cb.Call(cb, val) cb.Call(cb, val)
} }
} else if storageObject, ok := object.Resource.(*ethchain.StorageState); ok { } else if storageObject, ok := object.Resource.(*ethchain.StorageState); ok {
fmt.Println(storageObject) for _, cb := range self.objectCb[ethutil.Hex(storageObject.StateAddress)+ethutil.Hex(storageObject.Address)] {
val, _ := self.vm.ToValue(ethpub.NewPStorageState(storageObject))
cb.Call(cb, val)
}
} }
} }
} }
@@ -91,24 +114,77 @@ out:
func (self *JSRE) initStdFuncs() { func (self *JSRE) initStdFuncs() {
t, _ := self.vm.Get("eth") t, _ := self.vm.Get("eth")
eth := t.Object() eth := t.Object()
eth.Set("watch", func(call otto.FunctionCall) otto.Value { eth.Set("watch", self.watch)
addr, _ := call.Argument(0).ToString() eth.Set("addPeer", self.addPeer)
cb := call.Argument(1) eth.Set("require", self.require)
eth.Set("stopMining", self.stopMining)
eth.Set("startMining", self.startMining)
}
/*
* The following methods are natively implemented javascript functions
*/
func (self *JSRE) stopMining(call otto.FunctionCall) otto.Value {
v, _ := self.vm.ToValue(utils.StopMining(self.ethereum))
return v
}
func (self *JSRE) startMining(call otto.FunctionCall) otto.Value {
v, _ := self.vm.ToValue(utils.StartMining(self.ethereum))
return v
}
// eth.watch
func (self *JSRE) watch(call otto.FunctionCall) otto.Value {
addr, _ := call.Argument(0).ToString()
var storageAddr string
var cb otto.Value
var storageCallback bool
if len(call.ArgumentList) > 2 {
storageCallback = true
storageAddr, _ = call.Argument(1).ToString()
cb = call.Argument(2)
} else {
cb = call.Argument(1)
}
if storageCallback {
self.objectCb[addr+storageAddr] = append(self.objectCb[addr+storageAddr], cb)
event := "storage:" + string(ethutil.FromHex(addr)) + ":" + string(ethutil.FromHex(storageAddr))
self.ethereum.Reactor().Subscribe(event, self.changeChan)
} else {
self.objectCb[addr] = append(self.objectCb[addr], cb) self.objectCb[addr] = append(self.objectCb[addr], cb)
event := "object:" + string(ethutil.FromHex(addr)) event := "object:" + string(ethutil.FromHex(addr))
self.ethereum.Reactor().Subscribe(event, self.changeChan) self.ethereum.Reactor().Subscribe(event, self.changeChan)
}
return otto.UndefinedValue() return otto.UndefinedValue()
}) }
eth.Set("addPeer", func(call otto.FunctionCall) otto.Value {
host, err := call.Argument(0).ToString() func (self *JSRE) addPeer(call otto.FunctionCall) otto.Value {
if err != nil { host, err := call.Argument(0).ToString()
return otto.FalseValue() if err != nil {
} return otto.FalseValue()
self.ethereum.ConnectToPeer(host) }
self.ethereum.ConnectToPeer(host)
return otto.TrueValue()
}) return otto.TrueValue()
}
func (self *JSRE) require(call otto.FunctionCall) otto.Value {
file, err := call.Argument(0).ToString()
if err != nil {
return otto.UndefinedValue()
}
if err := self.Require(file); err != nil {
fmt.Println("err:", err)
return otto.UndefinedValue()
}
t, _ := self.vm.Get("exports")
return t
} }

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethpub"
"github.com/robertkrimen/otto" "github.com/obscuren/otto"
) )
type Repl interface { type Repl interface {
@@ -48,11 +48,24 @@ func (self *JSRepl) parseInput(code string) {
// The JSEthereum object attempts to wrap the PEthereum object and returns // The JSEthereum object attempts to wrap the PEthereum object and returns
// meaningful javascript objects // meaningful javascript objects
type JSBlock struct {
*ethpub.PBlock
eth *JSEthereum
}
func (self *JSBlock) GetTransaction(hash string) otto.Value {
return self.eth.toVal(self.PBlock.GetTransaction(hash))
}
type JSEthereum struct { type JSEthereum struct {
*ethpub.PEthereum *ethpub.PEthereum
vm *otto.Otto vm *otto.Otto
} }
func (self *JSEthereum) GetBlock(hash string) otto.Value {
return self.toVal(&JSBlock{self.PEthereum.GetBlock(hash), self})
}
func (self *JSEthereum) GetKey() otto.Value { func (self *JSEthereum) GetKey() otto.Value {
return self.toVal(self.PEthereum.GetKey()) return self.toVal(self.PEthereum.GetKey())
} }
@@ -72,8 +85,8 @@ func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr,
return self.toVal(r) return self.toVal(r)
} }
func (self *JSEthereum) Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyStr string) otto.Value { func (self *JSEthereum) Create(key, valueStr, gasStr, gasPriceStr, scriptStr string) otto.Value {
r, err := self.PEthereum.Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyStr) r, err := self.PEthereum.Create(key, valueStr, gasStr, gasPriceStr, scriptStr)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)

View File

@@ -1,18 +1,42 @@
package main package main
// #cgo darwin CFLAGS: -I/usr/local/opt/readline/include
// #cgo darwin LDFLAGS: -L/usr/local/opt/readline/lib
// #cgo LDFLAGS: -lreadline // #cgo LDFLAGS: -lreadline
// #include <stdio.h> // #include <stdio.h>
// #include <stdlib.h> // #include <stdlib.h>
// #include <readline/readline.h> // #include <readline/readline.h>
// #include <readline/history.h> // #include <readline/history.h>
import "C" import "C"
import ( import (
"github.com/robertkrimen/otto" "os"
"os/signal"
"strings" "strings"
"syscall"
"unsafe" "unsafe"
) )
func initReadLine() {
C.rl_catch_sigwinch = 0
C.rl_catch_signals = 0
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGWINCH)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
switch sig {
case syscall.SIGWINCH:
C.rl_resize_terminal()
case os.Interrupt:
C.rl_cleanup_after_signal()
default:
}
}
}()
}
func readLine(prompt *string) *string { func readLine(prompt *string) *string {
var p *C.char var p *C.char
@@ -60,6 +84,7 @@ func (self *JSRepl) setIndent() {
} }
func (self *JSRepl) read() { func (self *JSRepl) read() {
initReadLine()
L: L:
for { for {
switch result := readLine(&self.prompt); true { switch result := readLine(&self.prompt); true {
@@ -77,7 +102,7 @@ L:
break L break L
} }
addHistory(str) //allow user to recall this line addHistory(str[:len(str)-1]) //allow user to recall this line
self.parseInput(str) self.parseInput(str)
@@ -87,7 +112,10 @@ L:
} }
} }
func (self *JSRepl) PrintValue(value otto.Value) { func (self *JSRepl) PrintValue(v interface{}) {
method, _ := self.re.vm.Get("prettyPrint") method, _ := self.re.vm.Get("prettyPrint")
method.Call(method, value) v, err := self.re.vm.ToValue(v)
if err == nil {
method.Call(method, v)
}
} }

View File

@@ -19,6 +19,8 @@ func DoRpc(ethereum *eth.Ethereum, RpcPort int) {
} }
} }
var miner ethminer.Miner
func DoMining(ethereum *eth.Ethereum) { func DoMining(ethereum *eth.Ethereum) {
// Set Mining status // Set Mining status
ethereum.Mining = true ethereum.Mining = true
@@ -31,17 +33,44 @@ 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)
// Give it some time to connect with peers // Give it some time to connect with peers
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)
/* for ethereum.IsUpToDate() == false {
for ethereum.IsUpToDate() == false { time.Sleep(5 * time.Second)
time.Sleep(5 * time.Second) }
}
*/
ethutil.Config.Log.Infoln("Miner started") ethutil.Config.Log.Infoln("Miner started")
miner := ethminer.NewDefaultMiner(addr, ethereum) miner := ethminer.NewDefaultMiner(addr, ethereum)
miner.Start() miner.Start()
}() }()
} }
func StopMining(ethereum *eth.Ethereum) bool {
if ethereum.Mining {
miner.Stop()
ethutil.Config.Log.Infoln("Miner stopped")
ethereum.Mining = false
return true
}
return false
}
func StartMining(ethereum *eth.Ethereum) bool {
if !ethereum.Mining {
DoMining(ethereum)
return true
}
return false
}