Compare commits

...

94 Commits

Author SHA1 Message Date
b3f25a6ade Merge branch 'release/0.6.0' 2014-07-25 10:42:14 +02:00
44da1801d8 Fixed strange issue where qml will crash first run after go install 2014-07-24 14:34:22 +02:00
82a84dca80 Move to goroutine for faster startup time 2014-07-24 14:16:43 +02:00
0ca776a6b8 Merge branch 'feature/new_vm' into develop 2014-07-24 14:16:25 +02:00
2e39efbe7c New State object 2014-07-24 12:34:48 +02:00
a06a84d19b Refactored to reflect the new VM and State 2014-07-24 12:30:41 +02:00
e7a80ec681 set asm 2014-07-22 19:54:33 +02:00
15960a5c04 changed iterator 2014-07-21 11:55:50 +02:00
f702e27485 Fixed miner stopping / starting:wq 2014-07-18 13:49:52 +02:00
0c5a747ef1 Add mining hash to GUI 2014-07-18 12:29:14 +02:00
75df148ba2 Fixed miner channel 2014-07-18 12:21:34 +02:00
4572d4940c Windows don't like dem flags 2014-07-18 12:02:45 +02:00
2b9f16802d WIP to expose hashrate to gui 2014-07-18 12:01:26 +02:00
34e2ab9f9f Added block update 2014-07-18 11:57:58 +02:00
44296c0b33 html tags not allowed 2014-07-17 23:17:10 +02:00
01d9107bce Add namecoin name if available to block 2014-07-17 22:30:17 +02:00
ba3fabda77 Added a catch up indicator 2014-07-17 22:01:39 +02:00
edf10ef8c5 Fixed name reg 2014-07-17 17:10:35 +02:00
6c565eae74 bump 2014-07-17 15:36:16 +02:00
c951702423 Merge branch 'develop' 2014-07-17 15:32:44 +02:00
7d64b589b4 h scroll 2014-07-17 15:02:25 +02:00
c302afd411 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-07-15 20:36:45 +02:00
28948d061c Moved the repl to a new package 2014-07-15 20:34:25 +02:00
223432fa1e Work around crash issues when building OSX binary 2014-07-15 16:21:16 +02:00
c0ae5c58a6 Rewrote mnemonic word loading to facilitate deployable builds. 2014-07-15 12:52:30 +02:00
e53acdc2ac Work around race condition with qt webinspector for windows builds 2014-07-14 16:46:00 +02:00
dce0ccf490 Don't silently fail on watcher creation 2014-07-14 15:29:02 +02:00
e6a428f85f Make the reload watcher use windows-safe paths 2014-07-14 15:25:01 +02:00
288f1c5387 Removed timer 2014-07-12 11:02:50 +02:00
d3e31a4a6d Special diff output + debugger changes 2014-07-11 16:04:27 +02:00
fc8bd7229e Merge branch 'develop' 2014-07-10 21:54:46 +02:00
c2bca5939d Added path check for Windows when loading external QML windows/components 2014-07-09 14:01:53 +02:00
05c1899895 Windos case for assetPath had a typo 2014-07-08 14:58:33 +02:00
7e88dd4e6b Setup default asset path for windows 2014-07-08 14:58:23 +02:00
61d5d107b6 Make script inclusion via QML also relative to asset path 2014-07-08 14:27:22 +02:00
7f9e614b5d Forgot two images 2014-07-08 14:25:30 +02:00
79259c916d Use relative image paths to help with windows builds 2014-07-08 14:05:42 +02:00
685aebc72e Merge branch 'develop' 2014-07-07 22:15:35 +02:00
0360e60dd5 Merge pull request #101 from ethereum/revert-100-feature/ethutil-refactor
Revert "ethreact - Feature/ethutil refactor"
2014-07-07 10:59:30 +02:00
0c132e4c9e Revert "ethreact - Feature/ethutil refactor" 2014-07-07 10:58:42 +02:00
f9e2e5276f Merge pull request #100 from ethersphere/feature/ethutil-refactor
ethreact - Feature/ethutil refactor
2014-07-07 10:55:39 +02:00
8e5117444e New type of debugger 2014-07-05 13:25:16 +02:00
1e4ae24126 use ethreact.Event, unbuffered event channels, subscribe after loop reading from channel starts 2014-07-04 19:48:37 +01:00
0ae3bbc3f5 deleted 2014-07-04 15:53:16 +02:00
b9fa4dada8 Merge branch 'develop' 2014-07-04 15:53:03 +02:00
9754c01f56 Added sample coin as a submodule 2014-07-04 15:49:51 +02:00
043920d157 Removed sample coin 2014-07-04 15:49:32 +02:00
3ebcd36667 Merge branch 'develop' 2014-07-04 15:32:25 +02:00
9e38ca555d Visual updates 2014-07-04 15:31:13 +02:00
de183e80db Silent compiler errors when continues compiling 2014-07-04 13:42:43 +02:00
ca395306e3 Updated debugger
* Compile on the go. Continues compilation in order to update the ASM
  view
* Short cuts commands
2014-07-04 13:04:25 +02:00
24ff81d14e Merge branch 'ethersphere-feature/clientid' into develop 2014-07-04 00:14:17 +02:00
9de30d96f0 Modify main wrappers
- clientIdentifier now set in main wrappers
- version handled within wrapper
- modify InitConfig now returning *ethutil.ConfigManager (passed to gui)
- added NewClientIdentity returning *ethwire.SimpleClientIdentiy (passed to ethereum)
2014-07-03 17:36:24 +01:00
a3c4823511 Gui saves custom client id and loglevel
- gui NewWindow takes SimpleClientIdentity as argument
- gui NewWindow takes ethutil.ConfigManager as argument to manage flag persistence
- gui now saves loglevel and custom client id via config.Save
- rename custom client id methods consistently also in wallet.qml
- clientIdentifier now set in main wrappers
- version handled within wrapper
- modify InitConfig now returning *ethutil.ConfigManager (passed to gui)
2014-07-03 17:35:48 +01:00
0076fa583c Merge branch 'develop' 2014-07-02 17:48:35 +02:00
a0dd1ebb6d . 2014-07-02 13:44:59 +02:00
50c0938226 Break points and debugger commands 2014-07-02 13:08:18 +02:00
98f21669c7 Merge branch 'develop' 2014-07-02 11:30:37 +02:00
7d0004f058 For namreg only show items starting without leading zeros. 2014-07-02 11:29:59 +02:00
e5b45d1c86 VM Update 2014-07-02 01:04:32 +02:00
677de48f6c Listen for namereg changes 2014-07-02 00:28:45 +02:00
c4f9151c67 Moved files 2014-07-02 00:13:50 +02:00
4918531dd5 Merge branch 'develop' 2014-07-01 20:10:49 +02:00
2835321377 Fixed namereg 2014-07-01 20:10:38 +02:00
74ef489fe2 Merge branch 'release/0.5.16' into develop 2014-07-01 16:24:54 +02:00
cb595fb63c Merge branch 'release/0.5.16' 2014-07-01 16:24:35 +02:00
5d3259587f bump 2014-07-01 16:24:34 +02:00
5e02d2b586 Merge pull request #96 from ethersphere/feature/keys
Feature/keys
2014-07-01 16:15:59 +02:00
ce88a73aa6 Merge branch 'develop' of github.com:ethereum/go-ethereum into feature/keys 2014-07-01 15:01:28 +01:00
41a03b29ab Merge branch 'ebuchman-miner_up_to_date' into develop 2014-07-01 11:28:11 +02:00
0ed9528d76 fix: miner wait untill UpToDate 2014-07-01 04:25:42 -04:00
098f7f23ce changed name for ethutil hex functions; and access to keyring via keyManager 2014-06-29 20:39:45 +01:00
8aea468744 gui changes
- remove lib   *EthLib, expose gui itself to initial import window
- remove addr []byte instead use dynamic adress()
- use ethereum.KeyManager to retrieve address and privateKey
- add Session string (keyRing identifier)
- add and reimplement ImportAndSetPrivKey and CreateAndSetPrivKey
2014-06-29 20:38:26 +01:00
29cc1af2bc remove ui/library; instead expose gui itself for initial window 2014-06-29 20:34:07 +01:00
e43e4ff2c1 main loop uses new flags and common methods in util: db, keymanager set up; passes KeyRing/Session string to gui 2014-06-29 20:32:31 +01:00
12fbb7ae5c new command line options
- keyring: keyring/session identifier used by key manager
- keystore: choice of db/file key storage
- import message updated
- export: name of directory to export keys to (was bool)
2014-06-29 20:31:00 +01:00
ce4080faa7 Merge branch 'develop' of github.com:ethereum/go-ethereum into feature/keys 2014-06-29 18:39:31 +01:00
cf7fcadeca added utility functions to set up db, keymanager, ethereum init and simplify key tasks 2014-06-29 18:39:13 +01:00
9bd67de671 remove keys file, now subsumed under ethcrypto/key_manager 2014-06-29 18:38:17 +01:00
27e1352c85 main loop uses new flags and common methods in util: db, keymanager set up 2014-06-29 18:37:22 +01:00
0ea9595d41 new command line options
- keyring: keyring/session identifier used by key manager
- keystore: choice of db/file key storage
- import message updated
- export: name of directory to export keys to (was bool)
2014-06-29 18:33:22 +01:00
e38b016547 changed name for ethutil hex functions 2014-06-29 18:32:48 +01:00
2d48fc1113 fix logmessage if data directory doesn't exist 2014-06-29 13:43:27 +01:00
328ee9a3ec Merge branch 'master' into develop 2014-06-29 10:44:03 +02:00
4fc60f340f Wait for catchup when starting the miner 2014-06-29 10:43:56 +02:00
1b74b98f90 Check if go install succeed 2014-06-26 23:31:07 +02:00
d57b7e8d5f Fix for installer 2014-06-26 23:25:17 +02:00
2d274003b8 Merge branch 'develop'
Conflicts:
	install.sh
2014-06-26 23:14:50 +02:00
52ddf044ae Initialization of Qt should happen before anything else 2014-06-26 23:14:17 +02:00
214721ca01 update 2014-06-26 23:07:20 +02:00
cad98dc4d5 update 2014-06-26 23:06:04 +02:00
e46e7e7a9c Added install script 2014-06-26 23:04:46 +02:00
bf2ac5acc5 Added install script 2014-06-26 23:01:35 +02:00
42414cadaa Merge branch 'release/0.5.15' into develop 2014-06-26 19:54:23 +02:00
35 changed files with 1060 additions and 812 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "ethereal/assets/samplecoin"]
path = ethereal/assets/samplecoin
url = git@github.com:obscuren/SampleCoin.git

View File

@ -5,7 +5,7 @@ Ethereum
Ethereum Go Client © 2014 Jeffrey Wilcke.
Current state: Proof of Concept 0.5.15.
Current state: Proof of Concept 0.6.0.
For the development package please see the [eth-go package](https://github.com/ethereum/eth-go).

View File

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

View File

@ -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() {

View File

@ -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,11 @@ ApplicationWindow {
text: "Client ID"
}
TextField {
text: eth.clientId()
text: eth.getCustomIdentifier()
width: 500
placeholderText: "Anonymous"
onTextChanged: {
eth.changeClientId(text)
eth.setCustomIdentifier(text)
}
}
}
@ -419,30 +421,54 @@ ApplicationWindow {
}
}
Label {
y: 7
anchors.right: peerImage.left
anchors.rightMargin: 5
id: peerLabel
font.pixelSize: 8
text: "0 / 0"
}
Image {
y: 7
id: peerImage
anchors.right: parent.right
width: 10; height: 10
MouseArea {
onDoubleClicked: peerWindow.visible = true
anchors.fill: parent
}
source: ui.assetPath("network.png")
}
Label {
y: 6
id: lastBlockLabel
objectName: "lastBlockLabel"
visible: true
text: ""
font.pixelSize: 10
anchors.right: peerGroup.left
anchors.rightMargin: 5
}
ProgressBar {
id: syncProgressIndicator
visible: false
objectName: "syncProgressIndicator"
y: 3
width: 140
indeterminate: true
anchors.right: peerGroup.left
anchors.rightMargin: 5
}
RowLayout {
id: peerGroup
y: 7
anchors.right: parent.right
MouseArea {
onDoubleClicked: peerWindow.visible = true
anchors.fill: parent
}
Label {
id: peerLabel
font.pixelSize: 8
text: "0 / 0"
}
Image {
id: peerImage
width: 10; height: 10
source: "../network.png"
}
}
}
Window {
id: popup
visible: false
//flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint
property var block
width: root.width
height: 300
@ -460,7 +486,7 @@ ApplicationWindow {
Text { text: '<h3>Block details</h3>'; color: "#F2F2F2"}
Text { text: '<b>Block number:</b> ' + number; color: "#F2F2F2"}
Text { text: '<b>Hash:</b> ' + hash; color: "#F2F2F2"}
Text { text: '<b>Coinbase:</b> ' + coinbase; color: "#F2F2F2"}
Text { text: '<b>Coinbase:</b> &lt;' + name + '&gt; ' + coinbase; color: "#F2F2F2"}
Text { text: '<b>Block found at:</b> ' + prettyTime; color: "#F2F2F2"}
Text { text: '<b>Gas used:</b> ' + gasUsed + " / " + gasLimit; color: "#F2F2F2"}
}
@ -577,6 +603,7 @@ ApplicationWindow {
Window {
id: addPeerWin
//flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint
visible: false
minimumWidth: 230
maximumWidth: 230
@ -624,7 +651,7 @@ ApplicationWindow {
width: 150
fillMode: Image.PreserveAspectFit
smooth: true
source: ui.assetPath("facet.png")
source: "../facet.png"
x: 10
y: 10
}
@ -633,7 +660,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>"
}
}
@ -686,9 +713,9 @@ ApplicationWindow {
}
if(initial){
blockModel.append({number: block.number, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
blockModel.append({number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
}else{
blockModel.insert(0, {number: block.number, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
blockModel.insert(0, {number: block.number, name: block.name, gasLimit: block.gasLimit, gasUsed: block.gasUsed, coinbase: block.coinbase, hash: block.hash, txs: txs, txAmount: amount, time: block.time, prettyTime: convertToPretty(block.time)})
}
}
@ -743,6 +770,7 @@ ApplicationWindow {
// ******************************************
Window {
id: peerWindow
//flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint
height: 200
width: 700
Rectangle {

View File

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

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

View File

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

View File

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

339
ethereal/debugger.go Normal file
View File

@ -0,0 +1,339 @@
package main
import (
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethvm"
"github.com/ethereum/go-ethereum/utils"
"github.com/go-qml/qml"
"math/big"
"strconv"
"strings"
)
type DebuggerWindow struct {
win *qml.Window
engine *qml.Engine
lib *UiLib
vm *ethvm.Vm
Db *Debugger
state *ethstate.State
}
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)
w := &DebuggerWindow{engine: engine, win: win, lib: lib, vm: &ethvm.Vm{}}
w.Db = NewDebugger(w)
return w
}
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 []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
}
defer func() {
if r := recover(); r != nil {
self.Logf("compile FAULT: %v", r)
}
}()
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, false)
return
})
if err != nil {
self.Logln(err)
return
}
var (
gas = ethutil.Big(gasStr)
gasPrice = ethutil.Big(gasPriceStr)
value = ethutil.Big(valueStr)
// Contract addr as test address
keyPair = self.lib.eth.KeyManager().KeyPair()
)
state := self.lib.eth.StateManager().TransState()
account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address())
contract := ethstate.NewStateObject([]byte{0})
contract.Amount = value
self.SetAsm(script)
callerClosure := ethvm.NewClosure(account, contract, script, gas, gasPrice)
block := self.lib.eth.BlockChain().CurrentBlock
/*
vm := ethchain.NewVm(state, self.lib.eth.StateManager(), ethchain.RuntimeVars{
Block: block,
Origin: account.Address(),
BlockNumber: block.Number,
PrevHash: block.PrevHash,
Coinbase: block.Coinbase,
Time: block.Time,
Diff: block.Difficulty,
Value: ethutil.Big(valueStr),
})
*/
env := utils.NewEnv(state, block, account.Address(), value)
vm := ethvm.New(env)
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)
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()
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() {
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 {
N chan bool
Q chan bool
done, interrupt 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 ethvm.OpCode, mem *ethvm.Memory, stack *ethvm.Stack, stateObject *ethstate.StateObject) bool {
self.main.Logln("break on instr:", pc)
return self.halting(pc, op, mem, stack, stateObject)
}
func (self *Debugger) StepHook(pc int, op ethvm.OpCode, mem *ethvm.Memory, stack *ethvm.Stack, stateObject *ethstate.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 ethvm.OpCode, mem *ethvm.Memory, stack *ethvm.Stack, stateObject *ethstate.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.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.interrupt = true
d.clearBuffers()
return false
}
}
return true
}
func (d *Debugger) clearBuffers() {
out:
// drain
for {
select {
case <-d.N:
case <-d.Q:
default:
break out
}
}
}
func (d *Debugger) Next() {
if !d.done {
d.N <- true
}
}

View File

@ -1,9 +1,10 @@
package ethui
package main
import (
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml"
)
@ -16,8 +17,8 @@ type AppContainer interface {
Engine() *qml.Engine
NewBlock(*ethchain.Block)
ObjectChanged(*ethchain.StateObject)
StorageChanged(*ethchain.StorageState)
ObjectChanged(*ethstate.StateObject)
StorageChanged(*ethstate.StorageState)
NewWatcher(chan bool)
}
@ -108,9 +109,9 @@ out:
app.container.NewBlock(block)
}
case object := <-app.changeChan:
if stateObject, ok := object.Resource.(*ethchain.StateObject); ok {
if stateObject, ok := object.Resource.(*ethstate.StateObject); ok {
app.container.ObjectChanged(stateObject)
} else if storageObject, ok := object.Resource.(*ethchain.StorageState); ok {
} else if storageObject, ok := object.Resource.(*ethstate.StorageState); ok {
app.container.StorageChanged(storageObject)
}
}
@ -121,10 +122,10 @@ out:
func (app *ExtApplication) Watch(addr, storageAddr string) {
var event string
if len(storageAddr) == 0 {
event = "object:" + string(ethutil.FromHex(addr))
event = "object:" + string(ethutil.Hex2Bytes(addr))
app.lib.eth.Reactor().Subscribe(event, app.changeChan)
} else {
event = "storage:" + string(ethutil.FromHex(addr)) + ":" + string(ethutil.FromHex(storageAddr))
event = "storage:" + string(ethutil.Hex2Bytes(addr)) + ":" + string(ethutil.Hex2Bytes(storageAddr))
app.lib.eth.Reactor().Subscribe(event, app.changeChan)
}

View File

@ -13,6 +13,8 @@ import (
)
var Identifier string
var KeyRing string
var KeyStore string
var StartRpc bool
var RpcPort int
var UseUPnP bool
@ -22,8 +24,8 @@ var AddPeer string
var MaxPeer int
var GenAddr bool
var UseSeed bool
var ImportKey string
var ExportKey bool
var SecretFile string
var ExportDir string
var NonInteractive bool
var Datadir string
var LogFile string
@ -34,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
@ -50,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")
@ -73,6 +75,8 @@ func Init() {
}
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
@ -81,9 +85,9 @@ func Init() {
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")

View File

@ -1,4 +1,4 @@
package ethui
package main
import (
"bytes"
@ -7,11 +7,14 @@ import (
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethminer"
"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"
"strconv"
"strings"
"time"
)
@ -28,40 +31,34 @@ type Gui struct {
eth *eth.Ethereum
// The public Ethereum library
lib *EthLib
uiLib *UiLib
txDb *ethdb.LDBDatabase
addr []byte
pub *ethpub.PEthereum
logLevel ethlog.LogLevel
open bool
Session string
clientIdentity *ethwire.SimpleClientIdentity
config *ethutil.ConfigManager
miner *ethminer.Miner
}
// Create GUI, but doesn't start it
func New(ethereum *eth.Ethereum, logLevel int) *Gui {
lib := &EthLib{stateManager: ethereum.StateManager(), blockChain: ethereum.BlockChain(), txPool: ethereum.TxPool()}
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)
}
// On first run we won't have any keys yet, so this would crash.
// Therefor we check if we are ready to actually start this process
var addr []byte
if ethutil.GetKeyRing().Len() != 0 {
addr = ethutil.GetKeyRing().Get(0).Address()
}
pub := ethpub.NewPEthereum(ethereum)
return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub, logLevel: ethlog.LogLevel(logLevel), 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.0 RC15"
defer gui.txDb.Close()
@ -74,8 +71,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()
@ -112,14 +107,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()
}
@ -133,6 +128,7 @@ func (gui *Gui) ToggleMining() {
txt = "Start mining"
} else {
utils.StartMining(gui.eth)
gui.miner = utils.GetMiner()
txt = "Stop mining"
}
@ -147,10 +143,12 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
win := gui.createWindow(component)
gui.setInitialBlockChain()
gui.loadAddressBook()
gui.readPreviousTransactions()
gui.setPeerInfo()
go func() {
gui.setInitialBlockChain()
gui.loadAddressBook()
gui.readPreviousTransactions()
gui.setPeerInfo()
}()
go gui.update()
@ -158,12 +156,11 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
}
func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
context.SetVar("lib", gui.lib)
context.SetVar("lib", gui)
component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
if err != nil {
return nil, err
}
return gui.createWindow(component), nil
}
@ -175,15 +172,36 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
return gui.win
}
func (gui *Gui) ImportAndSetPrivKey(secret string) bool {
err := gui.eth.KeyManager().InitFromString(gui.Session, 0, secret)
if err != nil {
logger.Errorln("unable to import: ", err)
return false
}
logger.Errorln("successfully imported: ", err)
return true
}
func (gui *Gui) CreateAndSetPrivKey() (string, string, string, string) {
err := gui.eth.KeyManager().Init(gui.Session, 0, true)
if err != nil {
logger.Errorln("unable to create key: ", err)
return "", "", "", ""
}
return gui.eth.KeyManager().KeyPair().AsStrings()
}
func (gui *Gui) setInitialBlockChain() {
sBlk := gui.eth.BlockChain().LastBlockHash
blk := gui.eth.BlockChain().GetBlock(sBlk)
for ; blk != nil; blk = gui.eth.BlockChain().GetBlock(sBlk) {
sBlk = blk.PrevHash
addr := gui.address()
// 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 bytes.Compare(tx.Sender(), addr) == 0 || bytes.Compare(tx.Recipient, addr) == 0 {
if ok, _ := gui.txDb.Get(tx.Hash()); ok == nil {
gui.txDb.Put(tx.Hash(), tx.RlpEncode())
}
@ -199,25 +217,28 @@ 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())})
nameReg := ethpub.EthereumConfig(gui.eth.StateManager()).NameReg()
if nameReg != nil {
nameReg.EachStorage(func(name string, value *ethutil.Value) {
if name[0] != 0 {
value.Decode()
gui.win.Root().Call("addAddress", struct{ Name, Address string }{name, ethutil.Bytes2Hex(value.Bytes())})
}
})
}
}
func (gui *Gui) readPreviousTransactions() {
it := gui.txDb.Db().NewIterator(nil, nil)
addr := gui.address()
for it.Next() {
tx := ethchain.NewTransactionFromBytes(it.Value())
var inout string
if bytes.Compare(tx.Sender(), gui.addr) == 0 {
if bytes.Compare(tx.Sender(), addr) == 0 {
inout = "send"
} else {
inout = "recv"
@ -230,7 +251,11 @@ func (gui *Gui) readPreviousTransactions() {
}
func (gui *Gui) processBlock(block *ethchain.Block, initial bool) {
gui.win.Root().Call("addBlock", ethpub.NewPBlock(block), initial)
name := ethpub.FindNameInNameReg(gui.eth.StateManager(), block.Coinbase)
b := ethpub.NewPBlock(block)
b.Name = name
gui.win.Root().Call("addBlock", b, initial)
}
func (gui *Gui) setWalletValue(amount, unconfirmedFunds *big.Int) {
@ -249,49 +274,68 @@ func (gui *Gui) setWalletValue(amount, unconfirmedFunds *big.Int) {
gui.win.Root().Call("setWalletValue", str)
}
func (self *Gui) getObjectByName(objectName string) qml.Object {
return self.win.Root().ObjectByName(objectName)
}
// Simple go routine function that updates the list of peers in the GUI
func (gui *Gui) update() {
reactor := gui.eth.Reactor()
blockChan := make(chan ethutil.React, 1)
txChan := make(chan ethutil.React, 1)
objectChan := make(chan ethutil.React, 1)
peerChan := make(chan ethutil.React, 1)
var (
blockChan = make(chan ethutil.React, 1)
txChan = make(chan ethutil.React, 1)
objectChan = make(chan ethutil.React, 1)
peerChan = make(chan ethutil.React, 1)
chainSyncChan = make(chan ethutil.React, 1)
miningChan = make(chan ethutil.React, 1)
)
reactor.Subscribe("newBlock", blockChan)
reactor.Subscribe("newTx:pre", txChan)
reactor.Subscribe("newTx:post", txChan)
reactor.Subscribe("object:"+string(namereg), objectChan)
reactor.Subscribe("chainSync", chainSyncChan)
reactor.Subscribe("miner:start", miningChan)
reactor.Subscribe("miner:stop", miningChan)
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)
peerUpdateTicker := time.NewTicker(5 * time.Second)
generalUpdateTicker := time.NewTicker(1 * time.Second)
state := gui.eth.StateManager().TransState()
unconfirmedFunds := new(big.Int)
gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.addr).Amount)))
gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Amount)))
gui.getObjectByName("syncProgressIndicator").Set("visible", !gui.eth.IsUpToDate())
lastBlockLabel := gui.getObjectByName("lastBlockLabel")
for {
select {
case b := <-blockChan:
block := b.Resource.(*ethchain.Block)
gui.processBlock(block, false)
if bytes.Compare(block.Coinbase, gui.addr) == 0 {
gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.addr).Amount, nil)
if bytes.Compare(block.Coinbase, gui.address()) == 0 {
gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.address()).Amount, nil)
}
case txMsg := <-txChan:
tx := txMsg.Resource.(*ethchain.Transaction)
if txMsg.Event == "newTx:pre" {
object := state.GetAccount(gui.addr)
object := state.GetAccount(gui.address())
if bytes.Compare(tx.Sender(), gui.addr) == 0 {
if bytes.Compare(tx.Sender(), gui.address()) == 0 {
gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "send")
gui.txDb.Put(tx.Hash(), tx.RlpEncode())
unconfirmedFunds.Sub(unconfirmedFunds, tx.Value)
} else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
} else if bytes.Compare(tx.Recipient, gui.address()) == 0 {
gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "recv")
gui.txDb.Put(tx.Hash(), tx.RlpEncode())
@ -300,10 +344,10 @@ func (gui *Gui) update() {
gui.setWalletValue(object.Amount, unconfirmedFunds)
} else {
object := state.GetAccount(gui.addr)
if bytes.Compare(tx.Sender(), gui.addr) == 0 {
object := state.GetAccount(gui.address())
if bytes.Compare(tx.Sender(), gui.address()) == 0 {
object.SubAmount(tx.Value)
} else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
} else if bytes.Compare(tx.Recipient, gui.address()) == 0 {
object.AddAmount(tx.Value)
}
@ -311,12 +355,32 @@ func (gui *Gui) update() {
state.UpdateStateObject(object)
}
case msg := <-chainSyncChan:
sync := msg.Resource.(bool)
gui.win.Root().ObjectByName("syncProgressIndicator").Set("visible", sync)
case <-objectChan:
gui.loadAddressBook()
case <-peerChan:
gui.setPeerInfo()
case <-ticker.C:
case <-peerUpdateTicker.C:
gui.setPeerInfo()
case msg := <-miningChan:
if msg.Event == "miner:start" {
gui.miner = msg.Resource.(*ethminer.Miner)
} else {
gui.miner = nil
}
case <-generalUpdateTicker.C:
statusText := "#" + gui.eth.BlockChain().CurrentBlock.Number.String()
if gui.miner != nil {
pow := gui.miner.GetPow()
if pow.GetHashrate() != 0 {
statusText = "Mining @ " + strconv.FormatInt(pow.GetHashrate(), 10) + "Khash - " + statusText
}
}
lastBlockLabel.Set("text", statusText)
}
}
}
@ -330,35 +394,41 @@ func (gui *Gui) setPeerInfo() {
}
}
func (gui *Gui) privateKey() string {
return ethutil.Bytes2Hex(gui.eth.KeyManager().PrivateKey())
}
func (gui *Gui) address() []byte {
return gui.eth.KeyManager().Address()
}
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)
name = fmt.Sprintf("\"register\"\n\"%s\"", name)
gui.pub.Transact(gui.privateKey(), "NameReg", "", "10000", "10000000000000", name)
}
func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
keyPair := ethutil.GetKeyRing().Get(0)
return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data)
return gui.pub.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data)
}
func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
keyPair := ethutil.GetKeyRing().Get(0)
return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data)
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 {

View File

@ -1,14 +1,14 @@
package ethui
package main
import (
"errors"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml"
"github.com/howeyc/fsnotify"
"io/ioutil"
"log"
"net/url"
"os"
"path"
@ -59,7 +59,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 +77,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()
@ -116,15 +118,15 @@ func (app *HtmlApplication) Window() *qml.Window {
}
func (app *HtmlApplication) NewBlock(block *ethchain.Block) {
b := &ethpub.PBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())}
b := &ethpub.PBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())}
app.webView.Call("onNewBlockCb", b)
}
func (app *HtmlApplication) ObjectChanged(stateObject *ethchain.StateObject) {
func (app *HtmlApplication) ObjectChanged(stateObject *ethstate.StateObject) {
app.webView.Call("onObjectChangeCb", ethpub.NewPStateObject(stateObject))
}
func (app *HtmlApplication) StorageChanged(storageObject *ethchain.StorageState) {
func (app *HtmlApplication) StorageChanged(storageObject *ethstate.StorageState) {
app.webView.Call("onStorageChangeCb", ethpub.NewPStorageState(storageObject))
}

View File

@ -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.6.0"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
@ -23,16 +27,23 @@ 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)
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
ethereum := utils.NewEthereum(UseUPnP, OutboundPort, MaxPeer)
db := utils.NewDatabase()
keyManager := utils.NewKeyManager(KeyStore, Datadir, db)
// create, import, export keys
utils.KeyTasks(GenAddr, ImportKey, ExportKey, NonInteractive)
utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier)
ethereum := utils.NewEthereum(db, clientIdentity, keyManager, UseUPnP, OutboundPort, MaxPeer)
if ShowGenesis {
utils.ShowGenesis(ethereum)
@ -42,7 +53,7 @@ func main() {
utils.StartRpc(ethereum, RpcPort)
}
gui := ethui.New(ethereum, LogLevel)
gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel)
utils.RegisterInterrupt(func(os.Signal) {
gui.Stop()

View File

@ -1,10 +1,12 @@
package ethui
package main
import (
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml"
"runtime"
)
type QmlApplication struct {
@ -20,7 +22,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)
}
@ -38,15 +47,15 @@ func (app *QmlApplication) NewWatcher(quitChan chan bool) {
// Events
func (app *QmlApplication) NewBlock(block *ethchain.Block) {
pblock := &ethpub.PBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())}
pblock := &ethpub.PBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())}
app.win.Call("onNewBlockCb", pblock)
}
func (app *QmlApplication) ObjectChanged(stateObject *ethchain.StateObject) {
func (app *QmlApplication) ObjectChanged(stateObject *ethstate.StateObject) {
app.win.Call("onObjectChangeCb", ethpub.NewPStateObject(stateObject))
}
func (app *QmlApplication) StorageChanged(storageObject *ethchain.StorageState) {
func (app *QmlApplication) StorageChanged(storageObject *ethstate.StorageState) {
app.win.Call("onStorageChangeCb", ethpub.NewPStorageState(storageObject))
}

View File

@ -1,234 +0,0 @@
package ethui
import (
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml"
"math/big"
"strings"
)
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, false, 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
}
self.Db.breakOnInstr = self.win.Root().ObjectByName("breakEachLine").Bool("checked")
defer func() {
if r := recover(); r != nil {
self.Logf("compile FAULT: %v", r)
}
}()
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)
return
})
if err != nil {
self.Logln(err)
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 = ethutil.GetKeyRing().Get(0)
callerTx = ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, 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)
contract.Amount = value
callerClosure := ethchain.NewClosure(account, contract, script, state, gas, gasPrice)
block := self.lib.eth.BlockChain().CurrentBlock
vm := ethchain.NewVm(state, self.lib.eth.StateManager(), ethchain.RuntimeVars{
Block: block,
Origin: account.Address(),
BlockNumber: block.Number,
PrevHash: block.PrevHash,
Coinbase: block.Coinbase,
Time: block.Time,
Diff: block.Difficulty,
Value: ethutil.Big(valueStr),
})
vm.Verbose = true
self.Db.done = false
self.Logf("callsize %d", len(script))
go func() {
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()
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() {
self.Db.Next()
}
type Debugger struct {
win *qml.Window
N chan bool
Q chan bool
done, interrupt bool
breakOnInstr 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())})
})
if d.breakOnInstr {
out:
for {
select {
case <-d.N:
break out
case <-d.Q:
d.interrupt = true
d.clearBuffers()
return false
}
}
}
return true
}
func (d *Debugger) clearBuffers() {
out:
// drain
for {
select {
case <-d.N:
case <-d.Q:
default:
break out
}
}
}
func (d *Debugger) Next() {
if !d.done {
d.N <- true
}
}

View File

@ -1,46 +0,0 @@
package ethui
import (
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils"
"github.com/obscuren/secp256k1-go"
"strings"
)
type EthLib struct {
stateManager *ethchain.StateManager
blockChain *ethchain.BlockChain
txPool *ethchain.TxPool
Db *Debugger
}
func (lib *EthLib) ImportAndSetPrivKey(privKey string) bool {
fmt.Println(privKey)
mnemonic := strings.Split(privKey, " ")
if len(mnemonic) == 24 {
fmt.Println("Got mnemonic key, importing.")
key := ethutil.MnemonicDecode(mnemonic)
utils.ImportPrivateKey(key)
} else if len(mnemonic) == 1 {
fmt.Println("Got hex key, importing.")
utils.ImportPrivateKey(privKey)
} else {
fmt.Println("Did not recognise format, exiting.")
return false
}
return true
}
func (lib *EthLib) CreateAndSetPrivKey() (string, string, string, string) {
_, prv := secp256k1.GenerateKeyPair()
keyPair, err := ethutil.GetKeyRing().NewKeyPair(prv)
if err != nil {
panic(err)
}
mne := ethutil.MnemonicEncode(ethutil.Hex(keyPair.PrivateKey))
mnemonicString := strings.Join(mne, " ")
return mnemonicString, fmt.Sprintf("%x", keyPair.Address()), ethutil.Hex(keyPair.PrivateKey), ethutil.Hex(keyPair.PublicKey)
}

View File

@ -1,4 +1,4 @@
package ethui
package main
import (
"github.com/ethereum/eth-go"
@ -77,9 +77,9 @@ func (ui *UiLib) AssetPath(p string) string {
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()))
object := self.eth.StateManager().CurrentState().GetStateObject(ethutil.Hex2Bytes(contractHash))
if len(object.Code) > 0 {
dbWindow.SetCode("0x" + ethutil.Bytes2Hex(object.Code))
}
dbWindow.SetData("0x" + data)

View File

@ -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()
})

View File

@ -10,6 +10,10 @@ import (
)
var Identifier string
var KeyRing string
var DiffTool bool
var DiffType string
var KeyStore string
var StartRpc bool
var RpcPort int
var UseUPnP bool
@ -19,8 +23,8 @@ var AddPeer string
var MaxPeer int
var GenAddr bool
var UseSeed bool
var ImportKey string
var ExportKey bool
var SecretFile string
var ExportDir string
var NonInteractive bool
var Datadir string
var LogFile string
@ -47,6 +51,8 @@ func Init() {
}
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
@ -55,13 +61,15 @@ func Init() {
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use")
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")

View File

@ -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.6.0"
)
var logger = ethlog.NewLogger("CLI")
func main() {
@ -15,16 +21,30 @@ 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)
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
ethereum := utils.NewEthereum(UseUPnP, OutboundPort, MaxPeer)
db := utils.NewDatabase()
keyManager := utils.NewKeyManager(KeyStore, Datadir, db)
// create, import, export keys
utils.KeyTasks(GenAddr, ImportKey, ExportKey, NonInteractive)
utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier)
ethereum := utils.NewEthereum(db, clientIdentity, keyManager, UseUPnP, OutboundPort, MaxPeer)
if ShowGenesis {
utils.ShowGenesis(ethereum)

View File

@ -1,4 +1,4 @@
package main
package ethrepl
import (
"fmt"
@ -6,6 +6,7 @@ import (
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethstate"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils"
"github.com/obscuren/otto"
@ -121,13 +122,13 @@ out:
if _, ok := block.Resource.(*ethchain.Block); ok {
}
case object := <-self.changeChan:
if stateObject, ok := object.Resource.(*ethchain.StateObject); ok {
for _, cb := range self.objectCb[ethutil.Hex(stateObject.Address())] {
if stateObject, ok := object.Resource.(*ethstate.StateObject); ok {
for _, cb := range self.objectCb[ethutil.Bytes2Hex(stateObject.Address())] {
val, _ := self.vm.ToValue(ethpub.NewPStateObject(stateObject))
cb.Call(cb, val)
}
} else if storageObject, ok := object.Resource.(*ethchain.StorageState); ok {
for _, cb := range self.objectCb[ethutil.Hex(storageObject.StateAddress)+ethutil.Hex(storageObject.Address)] {
} else if storageObject, ok := object.Resource.(*ethstate.StorageState); ok {
for _, cb := range self.objectCb[ethutil.Bytes2Hex(storageObject.StateAddress)+ethutil.Bytes2Hex(storageObject.Address)] {
val, _ := self.vm.ToValue(ethpub.NewPStorageState(storageObject))
cb.Call(cb, val)
}
@ -178,12 +179,12 @@ func (self *JSRE) watch(call otto.FunctionCall) otto.Value {
if storageCallback {
self.objectCb[addr+storageAddr] = append(self.objectCb[addr+storageAddr], cb)
event := "storage:" + string(ethutil.FromHex(addr)) + ":" + string(ethutil.FromHex(storageAddr))
event := "storage:" + string(ethutil.Hex2Bytes(addr)) + ":" + string(ethutil.Hex2Bytes(storageAddr))
self.ethereum.Reactor().Subscribe(event, self.changeChan)
} else {
self.objectCb[addr] = append(self.objectCb[addr], cb)
event := "object:" + string(ethutil.FromHex(addr))
event := "object:" + string(ethutil.Hex2Bytes(addr))
self.ethereum.Reactor().Subscribe(event, self.changeChan)
}
@ -221,7 +222,7 @@ func (self *JSRE) execBlock(call otto.FunctionCall) otto.Value {
return otto.UndefinedValue()
}
err = utils.BlockDo(self.ethereum, ethutil.FromHex(hash))
err = utils.BlockDo(self.ethereum, ethutil.Hex2Bytes(hash))
if err != nil {
fmt.Println(err)
return otto.FalseValue()

View File

@ -1,4 +1,4 @@
package main
package ethrepl
const jsLib = `
function pp(object) {

83
ethereum/repl/repl.go Normal file
View 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)
}

View File

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

View File

@ -1,4 +1,4 @@
package main
package ethrepl
import (
"bufio"

View File

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

57
install.sh Executable file
View File

@ -0,0 +1,57 @@
#!/bin/sh
if [ "$1" == "" ]; then
echo "Usage $0 executable branch ethereum develop"
echo "executable ethereum or ethereal"
echo "branch develop or master"
exit
fi
exe=$1
branch=$2
# Test if go is installed
command -v go >/dev/null 2>&1 || { echo >&2 "Unable to find 'go'. This script requires go."; exit 1; }
# Test if $GOPATH is set
if [ "$GOPATH" == "" ]; then
echo "\$GOPATH not set"
exit
fi
echo "go get -u -d github.com/ethereum/go-ethereum/$exe"
go get -v -u -d github.com/ethereum/go-ethereum/$exe
if [ $? != 0 ]; then
echo "go get failed"
exit
fi
echo "serpent-go"
cd $GOPATH/src/github.com/obscuren/serpent-go
echo "init submodule"
git submodule init
git submodule update
echo "eth-go"
cd $GOPATH/src/github.com/ethereum/eth-go
git checkout $branch
echo "go-ethereum"
cd $GOPATH/src/github.com/ethereum/go-ethereum/$exe
git checkout $branch
if [ "$exe" == "ethereal" ]; then
echo "Building ethereal GUI. Assuming Qt is installed. If this step"
echo "fails; please refer to: https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)"
else
echo "Building ethereum CLI."
fi
go install
if [ $? == 0 ]; then
echo "go install failed"
exit
fi
echo "done. Please run $exe :-)"

View File

@ -1,19 +1,24 @@
package utils
import (
"bitbucket.org/kardianos/osext"
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethminer"
"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"
"strings"
"path/filepath"
"runtime"
"time"
)
@ -77,7 +82,7 @@ func InitDataDir(Datadir string) {
_, err := os.Stat(Datadir)
if err != nil {
if os.IsNotExist(err) {
fmt.Printf("Debug logging directory '%s' doesn't exist, creating it\n", Datadir)
fmt.Printf("Data directory '%s' doesn't exist, creating it\n", Datadir)
os.Mkdir(Datadir, 0777)
}
}
@ -97,19 +102,36 @@ 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)
ethutil.Config.Set("rpcport", "700")
return ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
}
func exit(status int) {
func exit(err error) {
status := 0
if err != nil {
fmt.Println(err)
logger.Errorln("Fatal: ", err)
status = 1
}
ethlog.Flush()
os.Exit(status)
}
func NewEthereum(UseUPnP bool, OutboundPort string, MaxPeer int) *eth.Ethereum {
ethereum, err := eth.New(eth.CapDefault, UseUPnP)
func NewDatabase() ethutil.Database {
db, err := ethdb.NewLDBDatabase("database")
if err != nil {
exit(err)
}
return db
}
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)
}
@ -119,7 +141,7 @@ func NewEthereum(UseUPnP bool, OutboundPort string, MaxPeer int) *eth.Ethereum {
}
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()
@ -129,50 +151,76 @@ func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
func ShowGenesis(ethereum *eth.Ethereum) {
logger.Infoln(ethereum.BlockChain().Genesis())
exit(0)
exit(nil)
}
func KeyTasks(GenAddr bool, ImportKey string, ExportKey bool, NonInteractive bool) {
func NewKeyManager(KeyStore string, Datadir string, db ethutil.Database) *ethcrypto.KeyManager {
var keyManager *ethcrypto.KeyManager
switch {
case KeyStore == "db":
keyManager = ethcrypto.NewDBKeyManager(db)
case KeyStore == "file":
keyManager = ethcrypto.NewFileKeyManager(Datadir)
default:
exit(fmt.Errorf("unknown keystore type: %s", KeyStore))
}
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:
if NonInteractive || confirm("This action overwrites your old private key.") {
CreateKeyPair(true)
err = keyManager.Init(KeyRing, 0, true)
}
exit(0)
case len(ImportKey) > 0:
exit(err)
case len(SecretFile) > 0:
SecretFile = ethutil.ExpandHomePath(SecretFile)
if NonInteractive || confirm("This action overwrites your old private key.") {
// import should be from file
mnemonic := strings.Split(ImportKey, " ")
if len(mnemonic) == 24 {
logger.Infoln("Got mnemonic key, importing.")
key := ethutil.MnemonicDecode(mnemonic)
ImportPrivateKey(key)
} else if len(mnemonic) == 1 {
logger.Infoln("Got hex key, importing.")
ImportPrivateKey(ImportKey)
} else {
logger.Errorln("Did not recognise format, exiting.")
}
err = keyManager.InitFromSecretsFile(KeyRing, 0, SecretFile)
}
exit(0)
case ExportKey: // this should be exporting to a filename
keyPair := ethutil.GetKeyRing().Get(0)
fmt.Printf(`
Generating new address and keypair.
Please keep your keys somewhere save.
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
save these words so you can restore your account later: %s
`, keyPair.Address(), keyPair.PrivateKey, keyPair.PublicKey)
exit(0)
exit(err)
case len(ExportDir) > 0:
err = keyManager.Init(KeyRing, 0, false)
if err == nil {
err = keyManager.Export(ExportDir)
}
exit(err)
default:
// Creates a keypair if none exists
CreateKeyPair(false)
err = keyManager.Init(KeyRing, 0, false)
if err != nil {
exit(err)
}
}
}
@ -186,26 +234,30 @@ func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
}
}
var miner ethminer.Miner
var miner *ethminer.Miner
func GetMiner() *ethminer.Miner {
return miner
}
func StartMining(ethereum *eth.Ethereum) bool {
if !ethereum.Mining {
ethereum.Mining = true
if ethutil.GetKeyRing().Len() == 0 {
logger.Errorln("No address found, can't start mining")
ethereum.Mining = false
return true //????
}
keyPair := ethutil.GetKeyRing().Get(0)
addr := keyPair.Address()
addr := ethereum.KeyManager().Address()
go func() {
miner = ethminer.NewDefaultMiner(addr, ethereum)
if miner == nil {
miner = ethminer.NewDefaultMiner(addr, ethereum)
}
// Give it some time to connect with peers
time.Sleep(3 * time.Second)
for !ethereum.IsUpToDate() {
time.Sleep(5 * time.Second)
}
logger.Infoln("Miner started")
miner := ethminer.NewDefaultMiner(addr, ethereum)
miner.Start()
}()
RegisterInterrupt(func(os.Signal) {
@ -217,12 +269,16 @@ func StartMining(ethereum *eth.Ethereum) bool {
}
func StopMining(ethereum *eth.Ethereum) bool {
if ethereum.Mining {
if ethereum.Mining && miner != nil {
miner.Stop()
logger.Infoln("Miner stopped")
ethereum.Mining = false
return true
}
return false
}

View File

@ -1,108 +0,0 @@
package utils
import (
"fmt"
"github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/secp256k1-go"
)
func CreateKeyPair(force bool) {
if force {
ethutil.GetKeyRing().Reset()
fmt.Println("resetting")
}
if ethutil.GetKeyRing().Get(0) == nil {
_, prv := secp256k1.GenerateKeyPair()
keyPair, err := ethutil.GetKeyRing().NewKeyPair(prv)
if err != nil {
panic(err)
}
mne := ethutil.MnemonicEncode(ethutil.Hex(keyPair.PrivateKey))
fmt.Printf(`
Generating new address and keypair.
Please keep your keys somewhere save.
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
save these words so you can restore your account later: %s
`, keyPair.Address(), keyPair.PrivateKey, keyPair.PublicKey, mne)
}
}
func ImportPrivateKey(sec string) {
ethutil.GetKeyRing().Reset()
keyPair, err := ethutil.GetKeyRing().NewKeyPair(ethutil.FromHex(sec))
if err != nil {
panic(err)
}
mne := ethutil.MnemonicEncode(ethutil.Hex(keyPair.PrivateKey))
fmt.Printf(`
Generating new address and keypair.
Please keep your keys somewhere save.
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
save these words so you can restore your account later: %s
`, keyPair.Address(), keyPair.PrivateKey, keyPair.PublicKey, mne)
}
/*
func CreateKeyPair(force bool) {
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
if len(data) == 0 || force {
pub, prv := secp256k1.GenerateKeyPair()
pair := &ethutil.Key{PrivateKey: prv, PublicKey: pub}
ethutil.Config.Db.Put([]byte("KeyRing"), pair.RlpEncode())
mne := ethutil.MnemonicEncode(ethutil.Hex(prv))
fmt.Printf(`
Generating new address and keypair.
Please keep your keys somewhere save.
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
save these words so you can restore your account later: %s
`, pair.Address(), prv, pub, mne)
}
}
*/
/*
func ImportPrivateKey(prvKey string) {
key := ethutil.FromHex(prvKey)
msg := []byte("tmp")
// Couldn't think of a better way to get the pub key
sig, _ := secp256k1.Sign(msg, key)
pub, _ := secp256k1.RecoverPubkey(msg, sig)
pair := &ethutil.Key{PrivateKey: key, PublicKey: pub}
ethutil.Config.Db.Put([]byte("KeyRing"), pair.RlpEncode())
fmt.Printf(`
Importing private key
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
`, pair.Address(), key, pub)
}
*/

33
utils/vm_env.go Normal file
View File

@ -0,0 +1,33 @@
package utils
import (
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethstate"
"math/big"
)
type VMEnv struct {
state *ethstate.State
block *ethchain.Block
transactor []byte
value *big.Int
}
func NewEnv(state *ethstate.State, block *ethchain.Block, transactor []byte, value *big.Int) *VMEnv {
return &VMEnv{
state: state,
block: block,
transactor: transactor,
value: value,
}
}
func (self *VMEnv) Origin() []byte { return self.transactor }
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number }
func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase }
func (self *VMEnv) Time() int64 { return self.block.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) State() *ethstate.State { return self.state }