Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
c951702423 | |||
7d64b589b4 | |||
c302afd411 | |||
28948d061c | |||
223432fa1e | |||
c0ae5c58a6 | |||
e53acdc2ac | |||
dce0ccf490 | |||
e6a428f85f | |||
288f1c5387 | |||
d3e31a4a6d | |||
fc8bd7229e | |||
c2bca5939d | |||
05c1899895 | |||
7e88dd4e6b | |||
61d5d107b6 | |||
7f9e614b5d | |||
79259c916d | |||
685aebc72e | |||
0360e60dd5 | |||
0c132e4c9e | |||
f9e2e5276f | |||
8e5117444e | |||
1e4ae24126 | |||
0ae3bbc3f5 | |||
b9fa4dada8 | |||
9754c01f56 | |||
043920d157 | |||
3ebcd36667 | |||
9e38ca555d | |||
de183e80db | |||
ca395306e3 | |||
24ff81d14e | |||
9de30d96f0 | |||
a3c4823511 | |||
0076fa583c | |||
a0dd1ebb6d | |||
50c0938226 | |||
98f21669c7 | |||
7d0004f058 | |||
e5b45d1c86 | |||
677de48f6c | |||
c4f9151c67 | |||
4918531dd5 | |||
2835321377 | |||
74ef489fe2 |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "ethereal/assets/samplecoin"]
|
||||
path = ethereal/assets/samplecoin
|
||||
url = git@github.com:obscuren/SampleCoin.git
|
@ -1,22 +0,0 @@
|
||||
UNAME = $(shell uname)
|
||||
FILES=qml *.png
|
||||
GOPATH=$(PWD)
|
||||
|
||||
|
||||
# Default is building
|
||||
all:
|
||||
go get -d
|
||||
cp *.go $(GOPATH)/src/github.com/ethereum/go-ethereum
|
||||
cp -r ui $(GOPATH)/src/github.com/ethereum/go-ethereum
|
||||
go build
|
||||
|
||||
install:
|
||||
# Linux build
|
||||
ifeq ($(UNAME),Linux)
|
||||
cp -r assets/* /usr/share/ethereal
|
||||
cp go-ethereum /usr/local/bin/ethereal
|
||||
endif
|
||||
# OS X build
|
||||
ifeq ($(UNAME),Darwin)
|
||||
# Execute py script
|
||||
endif
|
@ -7,16 +7,21 @@ import QtQuick.Controls.Styles 1.1
|
||||
import Ethereum 1.0
|
||||
|
||||
ApplicationWindow {
|
||||
id: win
|
||||
visible: false
|
||||
title: "IceCREAM"
|
||||
minimumWidth: 1280
|
||||
minimumHeight: 700
|
||||
width: 1290
|
||||
height: 700
|
||||
height: 750
|
||||
|
||||
property alias codeText: codeEditor.text
|
||||
property alias dataText: rawDataField.text
|
||||
|
||||
onClosing: {
|
||||
//compileTimer.stop()
|
||||
}
|
||||
|
||||
MenuBar {
|
||||
Menu {
|
||||
title: "Debugger"
|
||||
@ -31,18 +36,57 @@ ApplicationWindow {
|
||||
shortcut: "Ctrl+n"
|
||||
onTriggered: dbg.next()
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Continue"
|
||||
shortcut: "Ctrl+g"
|
||||
onTriggered: dbg.continue()
|
||||
}
|
||||
MenuItem {
|
||||
text: "Command"
|
||||
shortcut: "Ctrl+l"
|
||||
onTriggered: {
|
||||
dbgCommand.focus = true
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: "Focus code"
|
||||
shortcut: "Ctrl+1"
|
||||
onTriggered: {
|
||||
codeEditor.focus = true
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: "Focus data"
|
||||
shortcut: "Ctrl+2"
|
||||
onTriggered: {
|
||||
rawDataField.focus = true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
MenuItem {
|
||||
text: "Close window"
|
||||
shortcut: "Ctrl+w"
|
||||
onTriggered: {
|
||||
win.close()
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SplitView {
|
||||
anchors.fill: parent
|
||||
property var asmModel: ListModel {
|
||||
id: asmModel
|
||||
}
|
||||
|
||||
TableView {
|
||||
id: asmTableView
|
||||
width: 200
|
||||
TableViewColumn{ role: "value" ; title: "" ; width: 200 }
|
||||
TableViewColumn{ role: "value" ; title: "" ; width: asmTableView.width - 2 }
|
||||
model: asmModel
|
||||
}
|
||||
|
||||
@ -66,6 +110,17 @@ ApplicationWindow {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: settings.left
|
||||
focus: true
|
||||
|
||||
/*
|
||||
Timer {
|
||||
id: compileTimer
|
||||
interval: 500 ; running: true ; repeat: true
|
||||
onTriggered: {
|
||||
dbg.autoComp(codeEditor.text)
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Column {
|
||||
@ -178,7 +233,7 @@ ApplicationWindow {
|
||||
}
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
TableViewColumn{ id: message ; role: "message" ; title: "log" ; width: logTableView.width }
|
||||
TableViewColumn{ id: message ; role: "message" ; title: "log" ; width: logTableView.width - 2 }
|
||||
model: logModel
|
||||
}
|
||||
}
|
||||
@ -187,7 +242,28 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
function exec() {
|
||||
dbg.execCommand(dbgCommand.text);
|
||||
dbgCommand.text = "";
|
||||
}
|
||||
statusBar: StatusBar {
|
||||
height: 30
|
||||
|
||||
|
||||
TextField {
|
||||
id: dbgCommand
|
||||
y: 1
|
||||
x: asmTableView.width
|
||||
width: 500
|
||||
placeholderText: "Debugger (type 'help')"
|
||||
Keys.onReturnPressed: {
|
||||
exec()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toolBar: ToolBar {
|
||||
height: 30
|
||||
RowLayout {
|
||||
spacing: 5
|
||||
|
||||
@ -208,13 +284,32 @@ ApplicationWindow {
|
||||
}
|
||||
text: "Next"
|
||||
}
|
||||
CheckBox {
|
||||
id: breakEachLine
|
||||
objectName: "breakEachLine"
|
||||
text: "Break each instruction"
|
||||
checked: true
|
||||
|
||||
Button {
|
||||
id: debugContinueButton
|
||||
onClicked: {
|
||||
dbg.continue()
|
||||
}
|
||||
text: "Continue"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ComboBox {
|
||||
id: snippets
|
||||
anchors.right: parent.right
|
||||
model: ListModel {
|
||||
ListElement { text: "Snippets" ; value: "" }
|
||||
ListElement { text: "Call Contract" ; value: "var[2] in;\nvar ret;\n\nin[0] = \"arg1\"\nin[1] = 0xdeadbeef\n\nvar success = call(0x0c542ddea93dae0c2fcb2cf175f03ad80d6be9a0, 0, 7000, in, ret)\n\nreturn ret" }
|
||||
}
|
||||
onCurrentIndexChanged: {
|
||||
if(currentIndex != 0) {
|
||||
var code = snippets.model.get(currentIndex).value;
|
||||
codeEditor.insert(codeEditor.cursorPosition, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function debugCurrent() {
|
||||
@ -261,7 +356,19 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function setLog(msg) {
|
||||
logModel.insert(0, {message: msg})
|
||||
// Remove first item once we've reached max log items
|
||||
if(logModel.count > 250) {
|
||||
logModel.remove(0)
|
||||
}
|
||||
|
||||
if(msg.len != 0) {
|
||||
if(logTableView.flickableItem.atYEnd) {
|
||||
logModel.append({message: msg})
|
||||
logTableView.positionViewAtRow(logTableView.rowCount - 1, ListView.Contain)
|
||||
} else {
|
||||
logModel.append({message: msg})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
|
@ -100,7 +100,7 @@ ApplicationWindow {
|
||||
anchors.right: parent.right
|
||||
height: 200
|
||||
Image {
|
||||
source: ui.assetPath("tx.png")
|
||||
source: "../tx.png"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@ -110,7 +110,7 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
Image {
|
||||
source: ui.assetPath("new.png")
|
||||
source: "../new.png"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@ -120,7 +120,7 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
Image {
|
||||
source: ui.assetPath("net.png")
|
||||
source: "../net.png"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@ -131,7 +131,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
Image {
|
||||
source: ui.assetPath("heart.png")
|
||||
source: "../heart.png"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@ -248,9 +248,9 @@ ApplicationWindow {
|
||||
text: "Client ID"
|
||||
}
|
||||
TextField {
|
||||
text: eth.clientId()
|
||||
text: eth.getCustomIdentifier()
|
||||
onTextChanged: {
|
||||
eth.changeClientId(text)
|
||||
eth.setCustomIdentifier(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -436,7 +436,7 @@ ApplicationWindow {
|
||||
onDoubleClicked: peerWindow.visible = true
|
||||
anchors.fill: parent
|
||||
}
|
||||
source: ui.assetPath("network.png")
|
||||
source: "../network.png"
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,7 +624,7 @@ ApplicationWindow {
|
||||
width: 150
|
||||
fillMode: Image.PreserveAspectFit
|
||||
smooth: true
|
||||
source: ui.assetPath("facet.png")
|
||||
source: "../facet.png"
|
||||
x: 10
|
||||
y: 10
|
||||
}
|
||||
@ -633,7 +633,7 @@ ApplicationWindow {
|
||||
anchors.left: aboutIcon.right
|
||||
anchors.leftMargin: 10
|
||||
font.pointSize: 12
|
||||
text: "<h2>Ethereal</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>"
|
||||
text: "<h2>Ethereal</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>Viktor Trón<br>"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ ApplicationWindow {
|
||||
experimental.preferences.javascriptEnabled: true
|
||||
experimental.preferences.navigatorQtObjectEnabled: true
|
||||
experimental.preferences.developerExtrasEnabled: true
|
||||
experimental.userScripts: [ui.assetPath("ext/pre.js"), ui.assetPath("ext/big.js"), ui.assetPath("ext/string.js"), ui.assetPath("ext/ethereum.js")]
|
||||
experimental.userScripts: ["../ext/pre.js", "../ext/big.js", "../ext/string.js", "../ext/ethereum.js"]
|
||||
experimental.onMessageReceived: {
|
||||
console.log("[onMessageReceived]: ", message.data)
|
||||
// TODO move to messaging.js
|
||||
@ -191,6 +191,7 @@ ApplicationWindow {
|
||||
inspector.visible = false
|
||||
}else{
|
||||
inspector.visible = true
|
||||
inspector.url = webview.experimental.remoteInspectorUrl
|
||||
}
|
||||
}
|
||||
onDoubleClicked: {
|
||||
@ -224,7 +225,6 @@ ApplicationWindow {
|
||||
WebView {
|
||||
id: inspector
|
||||
visible: false
|
||||
url: webview.experimental.remoteInspectorUrl
|
||||
anchors {
|
||||
left: root.left
|
||||
right: root.right
|
||||
@ -238,7 +238,6 @@ ApplicationWindow {
|
||||
name: "inspectorShown"
|
||||
PropertyChanges {
|
||||
target: inspector
|
||||
url: webview.experimental.remoteInspectorUrl
|
||||
}
|
||||
}
|
||||
]
|
||||
|
File diff suppressed because one or more lines are too long
7
ethereal/assets/samplecoin/bootstrap.min.css
vendored
7
ethereal/assets/samplecoin/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 85 KiB |
@ -1,34 +0,0 @@
|
||||
/* Space out content a bit */
|
||||
body {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Everything but the jumbotron gets side spacing for mobile first
|
||||
* views */
|
||||
.header,
|
||||
.marketing,
|
||||
.footer {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
/* Custom page header */
|
||||
.header {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
/* Make the masthead heading the same height as the navigation */
|
||||
.header h3 {
|
||||
padding-bottom: 19px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.jumbotron {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
|
||||
margin: 0 auto;
|
||||
width: 300px;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>jeffcoin</title>
|
||||
|
||||
<link rel="stylesheet" href="bootstrap.min.css">
|
||||
<link rel="stylesheet" href="bootstrap-theme.min.css">
|
||||
<link rel="stylesheet" href="samplecoin.css">
|
||||
<meta name="viewport" content="minimum-scale=1; maximum-scale=1; initial-scale=1;">
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var jefcoinAddr = "22fa3ebce6ef9ca661a960104d3087eec040011e"
|
||||
var mAddr = ""
|
||||
|
||||
function createTransaction() {
|
||||
var addr = ("0x" + document.querySelector("#addr").value).pad(32);
|
||||
var amount = document.querySelector("#amount").value.pad(32);
|
||||
|
||||
var data = (addr + amount).unbin();
|
||||
eth.transact(mAddr, jefcoinAddr, 0, "50000", "1000000", data, function(receipt) {
|
||||
debug("received tx hash:", reciept.address)
|
||||
})
|
||||
}
|
||||
|
||||
function init() {
|
||||
eth.getKey(function(sec) {
|
||||
mAddr = sec;
|
||||
eth.getSecretToAddress(sec, function(addr) {
|
||||
eth.getStorageAt(jefcoinAddr, addr, function(storage) {
|
||||
document.querySelector("#current-amount").innerHTML = storage;
|
||||
});
|
||||
|
||||
eth.watch(jefcoinAddr, addr, function(addr, value) {
|
||||
document.querySelector("#current-amount").innerHTML = value
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="init();">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h3 class="text-muted">JeffCoin</h3>
|
||||
</div>
|
||||
|
||||
<div class="jumbotron ">
|
||||
<img src="icon.png">
|
||||
<div>Amount: <strong id="current-amount"></strong></div>
|
||||
|
||||
<div id="transactions">
|
||||
<div class="form-group">
|
||||
<input id="addr" class="form-control" type="text" placeholder="Receiver address"></input><br>
|
||||
<input id="amount" class="form-control" type="text" placeholder="Amount"></input><br>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-default" onclick="createTransaction();">Send Tx</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="debug" style="border: 1px solid black; min-height: 30px;"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ethui
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/go-qml/qml"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -13,7 +14,9 @@ type DebuggerWindow struct {
|
||||
win *qml.Window
|
||||
engine *qml.Engine
|
||||
lib *UiLib
|
||||
Db *Debugger
|
||||
|
||||
vm *ethchain.Vm
|
||||
Db *Debugger
|
||||
}
|
||||
|
||||
func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
|
||||
@ -26,9 +29,11 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
|
||||
}
|
||||
|
||||
win := component.CreateWindow(nil)
|
||||
db := &Debugger{win, make(chan bool), make(chan bool), true, false, true}
|
||||
|
||||
return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db}
|
||||
w := &DebuggerWindow{engine: engine, win: win, lib: lib, vm: ðchain.Vm{}}
|
||||
w.Db = NewDebugger(w)
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) Show() {
|
||||
@ -48,18 +53,42 @@ func (self *DebuggerWindow) SetCode(code string) {
|
||||
func (self *DebuggerWindow) SetData(data string) {
|
||||
self.win.Set("dataText", data)
|
||||
}
|
||||
func (self *DebuggerWindow) SetAsm(data string) {
|
||||
dis := ethchain.Disassemble(ethutil.Hex2Bytes(data))
|
||||
func (self *DebuggerWindow) SetAsm(data []byte) {
|
||||
self.win.Root().Call("clearAsm")
|
||||
|
||||
dis := ethchain.Disassemble(data)
|
||||
for _, str := range dis {
|
||||
self.win.Root().Call("setAsm", str)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) Compile(code string) {
|
||||
var err error
|
||||
script := ethutil.StringToByteFunc(code, func(s string) (ret []byte) {
|
||||
ret, err = ethutil.Compile(s, true)
|
||||
return
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
self.SetAsm(script)
|
||||
}
|
||||
}
|
||||
|
||||
// Used by QML
|
||||
func (self *DebuggerWindow) AutoComp(code string) {
|
||||
if self.Db.done {
|
||||
self.Compile(code)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) ClearLog() {
|
||||
self.win.Root().Call("clearLog")
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, dataStr string) {
|
||||
if !self.Db.done {
|
||||
self.Db.Q <- true
|
||||
}
|
||||
self.Db.breakOnInstr = self.win.Root().ObjectByName("breakEachLine").Bool("checked")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -78,7 +107,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||
|
||||
var err error
|
||||
script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
|
||||
ret, err = ethutil.Compile(s)
|
||||
ret, err = ethutil.Compile(s, false)
|
||||
return
|
||||
})
|
||||
|
||||
@ -88,28 +117,19 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||
return
|
||||
}
|
||||
|
||||
dis := ethchain.Disassemble(script)
|
||||
self.win.Root().Call("clearAsm")
|
||||
self.win.Root().Call("clearLog")
|
||||
|
||||
for _, str := range dis {
|
||||
self.win.Root().Call("setAsm", str)
|
||||
}
|
||||
|
||||
var (
|
||||
gas = ethutil.Big(gasStr)
|
||||
gasPrice = ethutil.Big(gasPriceStr)
|
||||
value = ethutil.Big(valueStr)
|
||||
// Contract addr as test address
|
||||
keyPair = self.lib.eth.KeyManager().KeyPair()
|
||||
callerTx = ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, script)
|
||||
keyPair = self.lib.eth.KeyManager().KeyPair()
|
||||
)
|
||||
callerTx.Sign(keyPair.PrivateKey)
|
||||
|
||||
state := self.lib.eth.BlockChain().CurrentBlock.State()
|
||||
state := self.lib.eth.StateManager().TransState()
|
||||
account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address())
|
||||
contract := ethchain.MakeContract(callerTx, state)
|
||||
contract := ethchain.NewStateObject([]byte{0})
|
||||
contract.Amount = value
|
||||
|
||||
callerClosure := ethchain.NewClosure(account, contract, script, state, gas, gasPrice)
|
||||
|
||||
block := self.lib.eth.BlockChain().CurrentBlock
|
||||
@ -124,11 +144,13 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||
Value: ethutil.Big(valueStr),
|
||||
})
|
||||
vm.Verbose = true
|
||||
vm.Dbg = self.Db
|
||||
|
||||
self.vm = vm
|
||||
self.Db.done = false
|
||||
self.Logf("callsize %d", len(script))
|
||||
go func() {
|
||||
ret, g, err := callerClosure.Call(vm, data, self.Db.halting)
|
||||
ret, g, err := callerClosure.Call(vm, data)
|
||||
tot := new(big.Int).Mul(g, gasPrice)
|
||||
self.Logf("gas usage %v total price = %v (%v)", g, tot, ethutil.CurrencyToString(tot))
|
||||
if err != nil {
|
||||
@ -164,18 +186,90 @@ func (self *DebuggerWindow) Next() {
|
||||
self.Db.Next()
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) Continue() {
|
||||
self.vm.Stepping = false
|
||||
self.Next()
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) ExecCommand(command string) {
|
||||
if len(command) > 0 {
|
||||
cmd := strings.Split(command, " ")
|
||||
switch cmd[0] {
|
||||
case "help":
|
||||
self.Logln("Debugger commands:")
|
||||
self.Logln("break, bp Set breakpoint on instruction")
|
||||
self.Logln("clear [log, break, bp] Clears previous set sub-command(s)")
|
||||
case "break", "bp":
|
||||
if len(cmd) > 1 {
|
||||
lineNo, err := strconv.Atoi(cmd[1])
|
||||
if err != nil {
|
||||
self.Logln(err)
|
||||
break
|
||||
}
|
||||
self.Db.breakPoints = append(self.Db.breakPoints, int64(lineNo))
|
||||
self.Logf("break point set on instruction %d", lineNo)
|
||||
} else {
|
||||
self.Logf("'%s' requires line number", cmd[0])
|
||||
}
|
||||
case "clear":
|
||||
if len(cmd) > 1 {
|
||||
switch cmd[1] {
|
||||
case "break", "bp":
|
||||
self.Db.breakPoints = nil
|
||||
|
||||
self.Logln("Breakpoints cleared")
|
||||
case "log":
|
||||
self.ClearLog()
|
||||
default:
|
||||
self.Logf("clear '%s' is not valid", cmd[1])
|
||||
}
|
||||
} else {
|
||||
self.Logln("'clear' requires sub command")
|
||||
}
|
||||
|
||||
default:
|
||||
self.Logf("Unknown command %s", cmd[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Debugger struct {
|
||||
win *qml.Window
|
||||
N chan bool
|
||||
Q chan bool
|
||||
done, interrupt bool
|
||||
breakOnInstr bool
|
||||
breakPoints []int64
|
||||
main *DebuggerWindow
|
||||
win *qml.Window
|
||||
}
|
||||
|
||||
func NewDebugger(main *DebuggerWindow) *Debugger {
|
||||
db := &Debugger{make(chan bool), make(chan bool), true, false, nil, main, main.win}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
type storeVal struct {
|
||||
Key, Value string
|
||||
}
|
||||
|
||||
func (self *Debugger) BreakHook(pc int, op ethchain.OpCode, mem *ethchain.Memory, stack *ethchain.Stack, stateObject *ethchain.StateObject) bool {
|
||||
self.main.Logln("break on instr:", pc)
|
||||
|
||||
return self.halting(pc, op, mem, stack, stateObject)
|
||||
}
|
||||
|
||||
func (self *Debugger) StepHook(pc int, op ethchain.OpCode, mem *ethchain.Memory, stack *ethchain.Stack, stateObject *ethchain.StateObject) bool {
|
||||
return self.halting(pc, op, mem, stack, stateObject)
|
||||
}
|
||||
|
||||
func (self *Debugger) SetCode(byteCode []byte) {
|
||||
self.main.SetAsm(byteCode)
|
||||
}
|
||||
|
||||
func (self *Debugger) BreakPoints() []int64 {
|
||||
return self.breakPoints
|
||||
}
|
||||
|
||||
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")
|
||||
@ -196,18 +290,16 @@ func (d *Debugger) halting(pc int, op ethchain.OpCode, mem *ethchain.Memory, sta
|
||||
d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
|
||||
})
|
||||
|
||||
if d.breakOnInstr {
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case <-d.N:
|
||||
break out
|
||||
case <-d.Q:
|
||||
d.interrupt = true
|
||||
d.clearBuffers()
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case <-d.N:
|
||||
break out
|
||||
case <-d.Q:
|
||||
d.interrupt = true
|
||||
d.clearBuffers()
|
||||
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ethui
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -36,6 +36,7 @@ var LogLevel int
|
||||
// flags specific to gui client
|
||||
var AssetPath string
|
||||
|
||||
//TODO: If we re-use the one defined in cmd.go the binary osx image crashes. If somebody finds out why we can dry this up.
|
||||
func defaultAssetPath() string {
|
||||
var assetPath string
|
||||
// If the current working directory is the go-ethereum dir
|
||||
@ -52,15 +53,14 @@ func defaultAssetPath() string {
|
||||
assetPath = filepath.Join(exedir, "../Resources")
|
||||
case "linux":
|
||||
assetPath = "/usr/share/ethereal"
|
||||
case "window":
|
||||
fallthrough
|
||||
case "windows":
|
||||
assetPath = "./assets"
|
||||
default:
|
||||
assetPath = "."
|
||||
}
|
||||
}
|
||||
return assetPath
|
||||
}
|
||||
|
||||
func defaultDataDir() string {
|
||||
usr, _ := user.Current()
|
||||
return path.Join(usr.HomeDir, ".ethereal")
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ethui
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"github.com/ethereum/eth-go/ethlog"
|
||||
"github.com/ethereum/eth-go/ethpub"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/ethereum/eth-go/ethwire"
|
||||
"github.com/ethereum/go-ethereum/utils"
|
||||
"github.com/go-qml/qml"
|
||||
"math/big"
|
||||
@ -36,12 +37,13 @@ type Gui struct {
|
||||
logLevel ethlog.LogLevel
|
||||
open bool
|
||||
|
||||
Session string
|
||||
Session string
|
||||
clientIdentity *ethwire.SimpleClientIdentity
|
||||
config *ethutil.ConfigManager
|
||||
}
|
||||
|
||||
// Create GUI, but doesn't start it
|
||||
func New(ethereum *eth.Ethereum, session string, logLevel int) *Gui {
|
||||
|
||||
func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIdentity *ethwire.SimpleClientIdentity, session string, logLevel int) *Gui {
|
||||
db, err := ethdb.NewLDBDatabase("tx_database")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -49,11 +51,10 @@ func New(ethereum *eth.Ethereum, session string, logLevel int) *Gui {
|
||||
|
||||
pub := ethpub.NewPEthereum(ethereum)
|
||||
|
||||
return &Gui{eth: ethereum, txDb: db, pub: pub, logLevel: ethlog.LogLevel(logLevel), Session: session, open: false}
|
||||
return &Gui{eth: ethereum, txDb: db, pub: pub, logLevel: ethlog.LogLevel(logLevel), Session: session, open: false, clientIdentity: clientIdentity, config: config}
|
||||
}
|
||||
|
||||
func (gui *Gui) Start(assetPath string) {
|
||||
const version = "0.5.16"
|
||||
|
||||
defer gui.txDb.Close()
|
||||
|
||||
@ -66,8 +67,6 @@ func (gui *Gui) Start(assetPath string) {
|
||||
Init: func(p *ethpub.KeyVal, obj qml.Object) { p.Key = ""; p.Value = "" },
|
||||
}})
|
||||
|
||||
ethutil.Config.SetClientString("Ethereal")
|
||||
|
||||
// Create a new QML engine
|
||||
gui.engine = qml.NewEngine()
|
||||
context := gui.engine.Context()
|
||||
@ -104,14 +103,14 @@ func (gui *Gui) Start(assetPath string) {
|
||||
ethlog.AddLogSystem(gui)
|
||||
}
|
||||
win.Wait()
|
||||
// need to silence gui logger after window closed otherwise logsystem hangs
|
||||
gui.SetLogLevel(ethlog.Silence)
|
||||
// need to silence gui logger after window closed otherwise logsystem hangs (but do not save loglevel)
|
||||
gui.logLevel = ethlog.Silence
|
||||
gui.open = false
|
||||
}
|
||||
|
||||
func (gui *Gui) Stop() {
|
||||
if gui.open {
|
||||
gui.SetLogLevel(ethlog.Silence)
|
||||
gui.logLevel = ethlog.Silence
|
||||
gui.open = false
|
||||
gui.win.Hide()
|
||||
}
|
||||
@ -211,14 +210,15 @@ type address struct {
|
||||
Name, Address string
|
||||
}
|
||||
|
||||
var namereg = ethutil.Hex2Bytes("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.Bytes2Hex(value.Bytes())})
|
||||
|
||||
nameReg := ethpub.EthereumConfig(gui.eth.StateManager()).NameReg()
|
||||
if nameReg != nil {
|
||||
nameReg.State().EachStorage(func(name string, value *ethutil.Value) {
|
||||
if name[0] != 0 {
|
||||
gui.win.Root().Call("addAddress", struct{ Name, Address string }{name, ethutil.Bytes2Hex(value.Bytes())})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -274,7 +274,11 @@ func (gui *Gui) update() {
|
||||
reactor.Subscribe("newBlock", blockChan)
|
||||
reactor.Subscribe("newTx:pre", txChan)
|
||||
reactor.Subscribe("newTx:post", txChan)
|
||||
reactor.Subscribe("object:"+string(namereg), objectChan)
|
||||
|
||||
nameReg := ethpub.EthereumConfig(gui.eth.StateManager()).NameReg()
|
||||
if nameReg != nil {
|
||||
reactor.Subscribe("object:"+string(nameReg.Address()), objectChan)
|
||||
}
|
||||
reactor.Subscribe("peerList", peerChan)
|
||||
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
@ -352,8 +356,9 @@ func (gui *Gui) address() []byte {
|
||||
}
|
||||
|
||||
func (gui *Gui) RegisterName(name string) {
|
||||
name = fmt.Sprintf("\"%s\"\n1", name)
|
||||
gui.pub.Transact(gui.privateKey(), "namereg", "1000", "1000000", "150", name)
|
||||
name = fmt.Sprintf("\"%s\"", name)
|
||||
|
||||
gui.pub.Transact(gui.privateKey(), "NameReg", "", "10000", "10000000000000", name)
|
||||
}
|
||||
|
||||
func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
|
||||
@ -364,17 +369,19 @@ func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PR
|
||||
return gui.pub.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data)
|
||||
}
|
||||
|
||||
func (gui *Gui) ChangeClientId(id string) {
|
||||
ethutil.Config.SetIdentifier(id)
|
||||
func (gui *Gui) SetCustomIdentifier(customIdentifier string) {
|
||||
gui.clientIdentity.SetCustomIdentifier(customIdentifier)
|
||||
gui.config.Save("id", customIdentifier)
|
||||
}
|
||||
|
||||
func (gui *Gui) ClientId() string {
|
||||
return ethutil.Config.Identifier
|
||||
func (gui *Gui) GetCustomIdentifier() string {
|
||||
return gui.clientIdentity.GetCustomIdentifier()
|
||||
}
|
||||
|
||||
// functions that allow Gui to implement interface ethlog.LogSystem
|
||||
func (gui *Gui) SetLogLevel(level ethlog.LogLevel) {
|
||||
gui.logLevel = level
|
||||
gui.config.Save("loglevel", level)
|
||||
}
|
||||
|
||||
func (gui *Gui) GetLogLevel() ethlog.LogLevel {
|
@ -1,4 +1,4 @@
|
||||
package ethui
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -8,7 +8,6 @@ import (
|
||||
"github.com/go-qml/qml"
|
||||
"github.com/howeyc/fsnotify"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
@ -59,7 +58,7 @@ func (app *HtmlApplication) RootFolder() string {
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return path.Dir(folder.RequestURI())
|
||||
return path.Dir(ethutil.WindonizePath(folder.RequestURI()))
|
||||
}
|
||||
func (app *HtmlApplication) RecursiveFolders() []os.FileInfo {
|
||||
files, _ := ioutil.ReadDir(app.RootFolder())
|
||||
@ -77,11 +76,13 @@ func (app *HtmlApplication) NewWatcher(quitChan chan bool) {
|
||||
|
||||
app.watcher, err = fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
logger.Infoln("Could not create new auto-reload watcher:", err)
|
||||
return
|
||||
}
|
||||
err = app.watcher.Watch(app.RootFolder())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logger.Infoln("Could not start auto-reload watcher:", err)
|
||||
return
|
||||
}
|
||||
for _, folder := range app.RecursiveFolders() {
|
||||
fullPath := app.RootFolder() + "/" + folder.Name()
|
@ -2,13 +2,17 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/ethereum/eth-go/ethlog"
|
||||
"github.com/ethereum/go-ethereum/ethereal/ui"
|
||||
"github.com/ethereum/go-ethereum/utils"
|
||||
"github.com/go-qml/qml"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
ClientIdentifier = "Ethereal"
|
||||
Version = "0.5.16"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Leave QT on top at ALL times. Qt Needs to be initialized from the main thread
|
||||
qml.Init(nil)
|
||||
@ -24,7 +28,8 @@ func main() {
|
||||
|
||||
// precedence: code-internal flag default < config file < environment variables < command line
|
||||
Init() // parsing command line
|
||||
utils.InitConfig(ConfigFile, Datadir, Identifier, "ETH")
|
||||
|
||||
config := utils.InitConfig(ConfigFile, Datadir, "ETH")
|
||||
|
||||
utils.InitDataDir(Datadir)
|
||||
|
||||
@ -37,7 +42,9 @@ func main() {
|
||||
// create, import, export keys
|
||||
utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||
|
||||
ethereum := utils.NewEthereum(db, keyManager, UseUPnP, OutboundPort, MaxPeer)
|
||||
clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier)
|
||||
|
||||
ethereum := utils.NewEthereum(db, clientIdentity, keyManager, UseUPnP, OutboundPort, MaxPeer)
|
||||
|
||||
if ShowGenesis {
|
||||
utils.ShowGenesis(ethereum)
|
||||
@ -47,7 +54,7 @@ func main() {
|
||||
utils.StartRpc(ethereum, RpcPort)
|
||||
}
|
||||
|
||||
gui := ethui.New(ethereum, KeyRing, LogLevel)
|
||||
gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel)
|
||||
|
||||
utils.RegisterInterrupt(func(os.Signal) {
|
||||
gui.Stop()
|
||||
|
@ -1,10 +1,11 @@
|
||||
package ethui
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/ethereum/eth-go/ethchain"
|
||||
"github.com/ethereum/eth-go/ethpub"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/go-qml/qml"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type QmlApplication struct {
|
||||
@ -20,7 +21,14 @@ func NewQmlApplication(path string, lib *UiLib) *QmlApplication {
|
||||
}
|
||||
|
||||
func (app *QmlApplication) Create() error {
|
||||
component, err := app.engine.LoadFile(app.path)
|
||||
path := string(app.path)
|
||||
|
||||
// For some reason for windows we get /c:/path/to/something, windows doesn't like the first slash but is fine with the others so we are removing it
|
||||
if string(app.path[0]) == "/" && runtime.GOOS == "windows" {
|
||||
path = app.path[1:]
|
||||
}
|
||||
|
||||
component, err := app.engine.LoadFile(path)
|
||||
if err != nil {
|
||||
logger.Warnln(err)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package ethui
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/ethereum/eth-go"
|
@ -2,13 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/ethereum/eth-go"
|
||||
"github.com/ethereum/go-ethereum/ethereum/repl"
|
||||
"github.com/ethereum/go-ethereum/utils"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
func InitJsConsole(ethereum *eth.Ethereum) {
|
||||
repl := NewJSRepl(ethereum)
|
||||
repl := ethrepl.NewJSRepl(ethereum)
|
||||
go repl.Start()
|
||||
utils.RegisterInterrupt(func(os.Signal) {
|
||||
repl.Stop()
|
||||
@ -24,7 +25,7 @@ func ExecJsFile(ethereum *eth.Ethereum, InputFile string) {
|
||||
if err != nil {
|
||||
logger.Fatalln(err)
|
||||
}
|
||||
re := NewJSRE(ethereum)
|
||||
re := ethrepl.NewJSRE(ethereum)
|
||||
utils.RegisterInterrupt(func(os.Signal) {
|
||||
re.Stop()
|
||||
})
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
|
||||
var Identifier string
|
||||
var KeyRing string
|
||||
var DiffTool bool
|
||||
var DiffType string
|
||||
var KeyStore string
|
||||
var StartRpc bool
|
||||
var RpcPort int
|
||||
@ -66,6 +68,8 @@ func Init() {
|
||||
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
|
||||
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
|
||||
flag.IntVar(&LogLevel, "loglevel", int(ethlog.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
|
||||
flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
|
||||
flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
|
||||
|
||||
flag.BoolVar(&StartMining, "mine", false, "start dagger mining")
|
||||
flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console")
|
||||
|
@ -2,10 +2,16 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/ethereum/eth-go/ethlog"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/ethereum/go-ethereum/utils"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
ClientIdentifier = "Ethereum(G)"
|
||||
Version = "0.5.16"
|
||||
)
|
||||
|
||||
var logger = ethlog.NewLogger("CLI")
|
||||
|
||||
func main() {
|
||||
@ -15,7 +21,15 @@ func main() {
|
||||
|
||||
// precedence: code-internal flag default < config file < environment variables < command line
|
||||
Init() // parsing command line
|
||||
utils.InitConfig(ConfigFile, Datadir, Identifier, "ETH")
|
||||
|
||||
// If the difftool option is selected ignore all other log output
|
||||
if DiffTool {
|
||||
LogLevel = 0
|
||||
}
|
||||
|
||||
utils.InitConfig(ConfigFile, Datadir, "ETH")
|
||||
ethutil.Config.Diff = DiffTool
|
||||
ethutil.Config.DiffType = DiffType
|
||||
|
||||
utils.InitDataDir(Datadir)
|
||||
|
||||
@ -28,7 +42,9 @@ func main() {
|
||||
// create, import, export keys
|
||||
utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||
|
||||
ethereum := utils.NewEthereum(db, keyManager, UseUPnP, OutboundPort, MaxPeer)
|
||||
clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier)
|
||||
|
||||
ethereum := utils.NewEthereum(db, clientIdentity, keyManager, UseUPnP, OutboundPort, MaxPeer)
|
||||
|
||||
if ShowGenesis {
|
||||
utils.ShowGenesis(ethereum)
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package ethrepl
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package ethrepl
|
||||
|
||||
const jsLib = `
|
||||
function pp(object) {
|
83
ethereum/repl/repl.go
Normal file
83
ethereum/repl/repl.go
Normal file
@ -0,0 +1,83 @@
|
||||
package ethrepl
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/ethereum/eth-go"
|
||||
"github.com/ethereum/eth-go/ethlog"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
var logger = ethlog.NewLogger("REPL")
|
||||
|
||||
type Repl interface {
|
||||
Start()
|
||||
Stop()
|
||||
}
|
||||
|
||||
type JSRepl struct {
|
||||
re *JSRE
|
||||
|
||||
prompt string
|
||||
|
||||
history *os.File
|
||||
|
||||
running bool
|
||||
}
|
||||
|
||||
func NewJSRepl(ethereum *eth.Ethereum) *JSRepl {
|
||||
hist, err := os.OpenFile(path.Join(ethutil.Config.ExecPath, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &JSRepl{re: NewJSRE(ethereum), prompt: "> ", history: hist}
|
||||
}
|
||||
|
||||
func (self *JSRepl) Start() {
|
||||
if !self.running {
|
||||
self.running = true
|
||||
logger.Infoln("init JS Console")
|
||||
reader := bufio.NewReader(self.history)
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil && err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
fmt.Println("error reading history", err)
|
||||
break
|
||||
}
|
||||
|
||||
addHistory(line[:len(line)-1])
|
||||
}
|
||||
self.read()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *JSRepl) Stop() {
|
||||
if self.running {
|
||||
self.running = false
|
||||
self.re.Stop()
|
||||
logger.Infoln("exit JS Console")
|
||||
self.history.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *JSRepl) parseInput(code string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("[native] error", r)
|
||||
}
|
||||
}()
|
||||
|
||||
value, err := self.re.Run(code)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
self.PrintValue(value)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package ethrepl
|
||||
|
||||
// #cgo darwin CFLAGS: -I/usr/local/opt/readline/include
|
||||
// #cgo darwin LDFLAGS: -L/usr/local/opt/readline/lib
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package ethrepl
|
||||
|
||||
import (
|
||||
"bufio"
|
@ -1,84 +1,26 @@
|
||||
package main
|
||||
package ethrepl
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/ethereum/eth-go"
|
||||
"github.com/ethereum/eth-go/ethpub"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/obscuren/otto"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type Repl interface {
|
||||
Start()
|
||||
Stop()
|
||||
type JSStateObject struct {
|
||||
*ethpub.PStateObject
|
||||
eth *JSEthereum
|
||||
}
|
||||
|
||||
type JSRepl struct {
|
||||
re *JSRE
|
||||
func (self *JSStateObject) EachStorage(call otto.FunctionCall) otto.Value {
|
||||
cb := call.Argument(0)
|
||||
self.PStateObject.EachStorage(func(key string, value *ethutil.Value) {
|
||||
value.Decode()
|
||||
|
||||
prompt string
|
||||
cb.Call(self.eth.toVal(self), self.eth.toVal(key), self.eth.toVal(ethutil.Bytes2Hex(value.Bytes())))
|
||||
})
|
||||
|
||||
history *os.File
|
||||
|
||||
running bool
|
||||
}
|
||||
|
||||
func NewJSRepl(ethereum *eth.Ethereum) *JSRepl {
|
||||
hist, err := os.OpenFile(path.Join(ethutil.Config.ExecPath, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &JSRepl{re: NewJSRE(ethereum), prompt: "> ", history: hist}
|
||||
}
|
||||
|
||||
func (self *JSRepl) Start() {
|
||||
if !self.running {
|
||||
self.running = true
|
||||
logger.Infoln("init JS Console")
|
||||
reader := bufio.NewReader(self.history)
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil && err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
fmt.Println("error reading history", err)
|
||||
break
|
||||
}
|
||||
|
||||
addHistory(line[:len(line)-1])
|
||||
}
|
||||
self.read()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *JSRepl) Stop() {
|
||||
if self.running {
|
||||
self.running = false
|
||||
self.re.Stop()
|
||||
logger.Infoln("exit JS Console")
|
||||
self.history.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *JSRepl) parseInput(code string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("[native] error", r)
|
||||
}
|
||||
}()
|
||||
|
||||
value, err := self.re.Run(code)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
self.PrintValue(value)
|
||||
return otto.UndefinedValue()
|
||||
}
|
||||
|
||||
// The JSEthereum object attempts to wrap the PEthereum object and returns
|
||||
@ -110,7 +52,7 @@ func (self *JSEthereum) GetKey() otto.Value {
|
||||
}
|
||||
|
||||
func (self *JSEthereum) GetStateObject(addr string) otto.Value {
|
||||
return self.toVal(self.PEthereum.GetStateObject(addr))
|
||||
return self.toVal(&JSStateObject{self.PEthereum.GetStateObject(addr), self})
|
||||
}
|
||||
|
||||
func (self *JSEthereum) GetStateKeyVals(addr string) otto.Value {
|
48
utils/cmd.go
48
utils/cmd.go
@ -1,6 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bitbucket.org/kardianos/osext"
|
||||
"fmt"
|
||||
"github.com/ethereum/eth-go"
|
||||
"github.com/ethereum/eth-go/ethcrypto"
|
||||
@ -10,11 +11,14 @@ import (
|
||||
"github.com/ethereum/eth-go/ethpub"
|
||||
"github.com/ethereum/eth-go/ethrpc"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/ethereum/eth-go/ethwire"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -98,14 +102,15 @@ func InitLogging(Datadir string, LogFile string, LogLevel int, DebugFile string)
|
||||
}
|
||||
}
|
||||
|
||||
func InitConfig(ConfigFile string, Datadir string, Identifier string, EnvPrefix string) {
|
||||
func InitConfig(ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager {
|
||||
InitDataDir(Datadir)
|
||||
ethutil.ReadConfig(ConfigFile, Datadir, Identifier, EnvPrefix)
|
||||
return ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
|
||||
}
|
||||
|
||||
func exit(err error) {
|
||||
status := 0
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
logger.Errorln("Fatal: ", err)
|
||||
status = 1
|
||||
}
|
||||
@ -121,8 +126,12 @@ func NewDatabase() ethutil.Database {
|
||||
return db
|
||||
}
|
||||
|
||||
func NewEthereum(db ethutil.Database, keyManager *ethcrypto.KeyManager, usePnp bool, OutboundPort string, MaxPeer int) *eth.Ethereum {
|
||||
ethereum, err := eth.New(db, keyManager, eth.CapDefault, usePnp)
|
||||
func NewClientIdentity(clientIdentifier, version, customIdentifier string) *ethwire.SimpleClientIdentity {
|
||||
return ethwire.NewSimpleClientIdentity(clientIdentifier, version, customIdentifier)
|
||||
}
|
||||
|
||||
func NewEthereum(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager *ethcrypto.KeyManager, usePnp bool, OutboundPort string, MaxPeer int) *eth.Ethereum {
|
||||
ethereum, err := eth.New(db, clientIdentity, keyManager, eth.CapDefault, usePnp)
|
||||
if err != nil {
|
||||
logger.Fatalln("eth start err:", err)
|
||||
}
|
||||
@ -132,7 +141,7 @@ func NewEthereum(db ethutil.Database, keyManager *ethcrypto.KeyManager, usePnp b
|
||||
}
|
||||
|
||||
func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
|
||||
logger.Infof("Starting Ethereum v%s", ethutil.Config.Ver)
|
||||
logger.Infof("Starting %s", ethereum.ClientIdentity())
|
||||
ethereum.Start(UseSeed)
|
||||
RegisterInterrupt(func(sig os.Signal) {
|
||||
ethereum.Stop()
|
||||
@ -158,7 +167,34 @@ func NewKeyManager(KeyStore string, Datadir string, db ethutil.Database) *ethcry
|
||||
return keyManager
|
||||
}
|
||||
|
||||
func DefaultAssetPath() string {
|
||||
var assetPath string
|
||||
// If the current working directory is the go-ethereum dir
|
||||
// assume a debug build and use the source directory as
|
||||
// asset directory.
|
||||
pwd, _ := os.Getwd()
|
||||
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal") {
|
||||
assetPath = path.Join(pwd, "assets")
|
||||
} else {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
// Get Binary Directory
|
||||
exedir, _ := osext.ExecutableFolder()
|
||||
assetPath = filepath.Join(exedir, "../Resources")
|
||||
case "linux":
|
||||
assetPath = "/usr/share/ethereal"
|
||||
case "windows":
|
||||
assetPath = "./assets"
|
||||
default:
|
||||
assetPath = "."
|
||||
}
|
||||
}
|
||||
return assetPath
|
||||
}
|
||||
|
||||
func KeyTasks(keyManager *ethcrypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
|
||||
ethcrypto.InitWords(DefaultAssetPath()) // Init mnemonic word list
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case GenAddr:
|
||||
@ -167,6 +203,8 @@ func KeyTasks(keyManager *ethcrypto.KeyManager, KeyRing string, GenAddr bool, Se
|
||||
}
|
||||
exit(err)
|
||||
case len(SecretFile) > 0:
|
||||
SecretFile = ethutil.ExpandHomePath(SecretFile)
|
||||
|
||||
if NonInteractive || confirm("This action overwrites your old private key.") {
|
||||
err = keyManager.InitFromSecretsFile(KeyRing, 0, SecretFile)
|
||||
}
|
||||
|
Reference in New Issue
Block a user