Compare commits

...

79 Commits

Author SHA1 Message Date
obscuren
0d89c1d212 Merge branch 'release/poc5-rc9' 2014-05-26 00:41:55 +02:00
obscuren
818bc84591 Bump 2014-05-26 00:39:05 +02:00
obscuren
b42c70be9c Recv send for txs 2014-05-26 00:10:38 +02:00
obscuren
d35380c19e New main script through init return value 2014-05-23 14:37:03 +02:00
obscuren
5f8911f7cb Custom identifier 2014-05-22 10:38:37 +02:00
obscuren
01b833146f Added mining stop and start 2014-05-22 00:25:48 +02:00
obscuren
b902de20c7 Fixes #49 2014-05-21 23:46:16 +02:00
obscuren
3f5b348451 Fixes #50 2014-05-21 23:36:55 +02:00
obscuren
941e0ba60a Merge branch 'release/poc5-rc8' into develop 2014-05-21 14:05:01 +02:00
obscuren
7f1a4c377c Merge branch 'release/poc5-rc8' 2014-05-21 14:04:54 +02:00
obscuren
3ddaf56afd Bumped 2014-05-21 14:04:11 +02:00
obscuren
10e2c40b59 Improved on some ui elements 2014-05-21 14:00:54 +02:00
obscuren
68f4a12a8b Fixed unconfirmed balance string 2014-05-21 13:37:46 +02:00
obscuren
16bd88c10a Removed method name 2014-05-21 12:14:39 +02:00
obscuren
d16d56d39f Updated readme to reflect options 2014-05-20 22:13:39 +02:00
obscuren
93e12250c7 Switch variables as intended 2014-05-20 22:12:42 +02:00
obscuren
f4551a7e9f Changed flag parsing 2014-05-20 22:12:22 +02:00
obscuren
563c035eb5 Refactored some of the functions 2014-05-20 19:28:48 +02:00
obscuren
de1dfae717 Forked version of otto so we can support lowerCased methods 2014-05-20 17:49:12 +02:00
obscuren
4198969302 Merge branch 'release/poc5-rc7' into develop 2014-05-20 17:09:36 +02:00
obscuren
c07c454935 Merge branch 'release/poc5-rc7' 2014-05-20 17:09:26 +02:00
obscuren
34014c1c51 Bump 2014-05-20 17:08:23 +02:00
Maran
0cf617ef0c Implemented GUI watchers for rapid reload. Implements #46 2014-05-20 16:58:13 +02:00
obscuren
0ef7f63729 Removed old console in favor of the new JS REPL 2014-05-20 12:57:43 +02:00
obscuren
a05adb1128 Refactored file structure 2014-05-20 12:48:34 +02:00
Maran
dfc3cb441b Increase default peer amount to 10 2014-05-20 11:52:36 +02:00
obscuren
92eaa98e83 Added js interpret mode 2014-05-19 17:01:40 +02:00
obscuren
017bbbb582 Improved REPL output 2014-05-19 16:32:45 +02:00
obscuren
16421106d4 Added multi-line support 2014-05-19 13:04:31 +02:00
obscuren
3b7707c3fd Improved console
* Added watch
2014-05-19 12:15:03 +02:00
obscuren
30842eb8d0 Changed logging 2014-05-19 12:14:47 +02:00
obscuren
43f88b2bbb Removed nonce incrementing 2014-05-19 12:14:32 +02:00
obscuren
770808ce0d Readline repl for linux & osx 2014-05-17 15:15:46 +02:00
obscuren
2ac292dc7a Merge branch 'feature/otto' into develop 2014-05-15 22:17:23 +02:00
obscuren
6a78e080e6 Tell config which loggers to use 2014-05-15 22:17:09 +02:00
obscuren
0a03484188 Implemented JavaScript console 2014-05-15 22:15:14 +02:00
obscuren
cbce882f5e Basic javascript console 2014-05-15 20:45:19 +02:00
obscuren
3a2bddc160 Refactored to reactor. Fixes #42 2014-05-15 14:06:06 +02:00
obscuren
9ba3c6d1af Merge branch 'release/poc5-rc6' into develop 2014-05-14 21:34:37 +02:00
obscuren
942f552c62 Merge branch 'release/poc5-rc6' 2014-05-14 21:34:21 +02:00
obscuren
a73ae8727d Bumped version 2014-05-14 21:34:01 +02:00
obscuren
278ee3f16c Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-05-14 14:57:16 +02:00
obscuren
9a057021c3 Update wallet value for coinbase rewards. Implements #44 & #43 2014-05-14 14:57:05 +02:00
Maran
a1dcc5cd17 Prevent crash during import of privkeys.
@obscuren please check if this was commented out for a reason
2014-05-14 14:11:45 +02:00
Maran
c9db87277b Fix merge conflicts 2014-05-14 14:04:43 +02:00
Maran
2c7b625daa Make sure we have a coinbase address to mine with 2014-05-14 13:55:55 +02:00
obscuren
f18ec51cb3 Switched to new keyring methods 2014-05-14 13:55:08 +02:00
Maran
9fce273ce9 Refactored RPC client to utils so it can be reused 2014-05-14 13:32:49 +02:00
Maran
2012e0c67a Rewritten a check to only start mining once we are caught up with all peers 2014-05-14 13:26:15 +02:00
Maran
e8147cf7c6 Refactored mining into utils and exposed it to ethereal. Partly fixes #43 2014-05-14 12:41:30 +02:00
Maran
0d9c948b9b Generate coinbase from privatekey, not pubkey. Partily fixes #43 2014-05-14 12:24:49 +02:00
obscuren
faa3073625 Changed validators to regexp validators
IntValidator limits to 32bit int (JavaScript limitation) and therefor
the input fields are limited in length.
2014-05-13 22:25:05 +02:00
obscuren
809b4ae0f6 Merge branch 'develop' 2014-05-13 16:39:32 +02:00
obscuren
7f94b266c7 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-05-13 16:39:23 +02:00
obscuren
1adfc272a8 Merge branch 'release/poc5-rc4' 2014-05-13 16:37:47 +02:00
obscuren
9caf53f8c6 Bumped 2014-05-13 16:37:15 +02:00
Maran
fca36cc03d Typo 2014-05-13 16:36:29 +02:00
Maran
b71094b01c Removed harcoded addresses from GetBlock JS bindings. Fixes #39 2014-05-13 16:32:35 +02:00
Maran
edc281ac5f Depcrecated set 2014-05-13 14:53:46 +02:00
Maran
ee2cef3b2e Adding new API test case html 2014-05-13 14:49:21 +02:00
Maran
54eff2d778 Change coinbase to be the address not public key 2014-05-13 14:48:45 +02:00
Maran
20ea78945e Implemented new JS/EthPub methods
- getTxCountAt
- getPeerCount
- getIsMining
- getIsListening
- getCoinbase
2014-05-13 14:43:08 +02:00
obscuren
dd60382fc3 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop
Conflicts:
	ethereal/ethereum.go
	ethereum/ethereum.go
2014-05-13 12:46:40 +02:00
obscuren
32c6126593 Fix 2014-05-13 12:45:47 +02:00
obscuren
03371b74d7 Public ethereum interface uses EthManager 2014-05-13 12:42:01 +02:00
Maran
c99aa7bdcf Fix merge conflict 2014-05-13 12:40:45 +02:00
Maran
5208b04821 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-05-13 12:08:54 +02:00
Maran
9a03df7bd8 Implemented a flag for a different RPC port; --rpcport 2014-05-13 12:00:48 +02:00
obscuren
67820506cb Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-05-13 11:59:13 +02:00
obscuren
8c9e6746ce Fixed wallet crash for new account. Fixes #38 2014-05-13 11:59:03 +02:00
Maran
b9876df5dc Added support to NewJsonRpc to return an error as well as an interface 2014-05-13 11:50:39 +02:00
Maran
a5963d1377 Enable seed again 2014-05-13 11:34:47 +02:00
Maran
c3ad210846 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-05-12 17:23:16 +02:00
Maran
618f523124 Actually start the Ethereum server on starting the GUI 2014-05-12 17:23:14 +02:00
obscuren
c7132e5d22 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-05-12 13:56:37 +02:00
obscuren
c43ea30e75 Refactored some code and fixed #37 2014-05-12 13:56:29 +02:00
Maran
cf7ab07264 Disable seed by default
Seed host seems down, only causes timeouts, not helpful
2014-05-12 13:41:52 +02:00
obscuren
5d15563ea7 PreProcess => PreParse 2014-05-12 12:22:16 +02:00
obscuren
a3cc4b0b80 Merge branch 'release/poc5-rc3' into develop 2014-05-10 16:25:08 +02:00
28 changed files with 1219 additions and 566 deletions

View File

@@ -5,7 +5,7 @@ Ethereum
Ethereum Go Client © 2014 Jeffrey Wilcke. Ethereum Go Client © 2014 Jeffrey Wilcke.
Current state: Proof of Concept 5.0 RC3. Current state: Proof of Concept 5.0 RC9.
For the development package please see the [eth-go package](https://github.com/ethereum/eth-go). For the development package please see the [eth-go package](https://github.com/ethereum/eth-go).
@@ -26,28 +26,25 @@ General command line options
==================== ====================
``` ```
-c Launch the developer console (node only) Shared between ethereum and ethereal
-m Start mining blocks -m Start mining blocks
-genaddr Generates a new address and private key (destructive action) -genaddr Generates a new address and private key (destructive action)
-p Port on which the server will accept incomming connections (= 30303) -p Port on which the server will accept incomming connections
-upnp Enable UPnP (= false) -upnp Enable UPnP
-x Desired amount of peers (= 5) -x Desired amount of peers
-h This help
-r Start JSON RPC -r Start JSON RPC
-dir Data directory used to store configs and databases (=".ethereum") -dir Data directory used to store configs and databases
-import Import a private key (hex) -import Import a private key
``` -h This
Developer console commands Ethereum only
========================== ethereum [options] [filename]
-js Start the JavaScript REPL
filename Load the given file and interpret as JavaScript
Etheral only
-asset_path absolute path to GUI assets directory
``` ```
addp <host>:<port> Connect to the given host
tx <addr> <amount> Send <amount> Wei to the specified <addr>
contract <value> <gasprice> Creates a new contract and launches the editor
```
See the "help" command for *developer* options.
Contribution Contribution
============ ============

View File

@@ -36,6 +36,21 @@ window.eth = {
postData({call: "getKey"}, cb); postData({call: "getKey"}, cb);
}, },
getTxCountAt: function(address, cb) {
postData({call: "getTxCountAt", args: [address]}, cb);
},
getIsMining: function(cb){
postData({call: "getIsMining"}, cb)
},
getIsListening: function(cb){
postData({call: "getIsListening"}, cb)
},
getCoinBase: function(cb){
postData({call: "getCoinBase"}, cb);
},
getPeerCount: function(cb){
postData({call: "getPeerCount"}, cb);
},
getBalanceAt: function(address, cb) { getBalanceAt: function(address, cb) {
postData({call: "getBalance", args: [address]}, cb); postData({call: "getBalance", args: [address]}, cb);
}, },
@@ -115,6 +130,8 @@ window.eth = {
} }
} }
}, },
} }
window.eth._callbacks = {} window.eth._callbacks = {}
window.eth._onCallbacks = {} window.eth._onCallbacks = {}

View File

@@ -46,6 +46,7 @@
.CodeMirror { .CodeMirror {
height: 70%; height: 70%;
font-size: 14pt;
} }
</style> </style>
</head> </head>

View File

@@ -61,7 +61,7 @@ ApplicationWindow {
text: "Restore" text: "Restore"
enabled: false enabled: false
onClicked: { onClicked: {
var success = eth.importAndSetPrivKey(txPrivKey.text) var success = lib.importAndSetPrivKey(txPrivKey.text)
if(success){ if(success){
importedDetails.visible = true importedDetails.visible = true
restoreColumn.visible = false restoreColumn.visible = false
@@ -139,7 +139,7 @@ ApplicationWindow {
id: newKey id: newKey
text: "I don't have an account yet" text: "I don't have an account yet"
onClicked: { onClicked: {
var res = eth.createAndSetPrivKey() var res = lib.createAndSetPrivKey()
mnemonicInput.text = res[0] mnemonicInput.text = res[0]
addressInput.text = res[1] addressInput.text = res[1]
privkeyInput.text = res[2] privkeyInput.text = res[2]

View File

@@ -61,7 +61,7 @@ Component {
id: txValue id: txValue
width: 200 width: 200
placeholderText: "Amount" placeholderText: "Amount"
validator: IntValidator { } validator: RegExpValidator { regExp: /\d*/ }
onTextChanged: { onTextChanged: {
contractFormReady() contractFormReady()
} }
@@ -69,7 +69,7 @@ Component {
TextField { TextField {
id: txGas id: txGas
width: 200 width: 200
validator: IntValidator { } validator: RegExpValidator { regExp: /\d*/ }
placeholderText: "Gas" placeholderText: "Gas"
onTextChanged: { onTextChanged: {
contractFormReady() contractFormReady()
@@ -79,7 +79,7 @@ Component {
id: txGasPrice id: txGasPrice
width: 200 width: 200
placeholderText: "Gas price" placeholderText: "Gas price"
validator: IntValidator { } validator: RegExpValidator { regExp: /\d*/ }
onTextChanged: { onTextChanged: {
contractFormReady() contractFormReady()
} }

View File

@@ -56,9 +56,10 @@ Component {
} }
TextField { TextField {
id: txSimpleValue id: txSimpleValue
width: 200
placeholderText: "Amount" placeholderText: "Amount"
anchors.rightMargin: 5 anchors.rightMargin: 5
validator: IntValidator { } validator: RegExpValidator { regExp: /\d*/ }
onTextChanged: { checkFormState() } onTextChanged: { checkFormState() }
} }
Button { Button {

View File

@@ -67,6 +67,7 @@ ApplicationWindow {
networkView.visible = false networkView.visible = false
historyView.visible = false historyView.visible = false
newTxView.visible = false newTxView.visible = false
infoView.visible = false
view.visible = true view.visible = true
//root.title = "Ethereal - " = view.title //root.title = "Ethereal - " = view.title
} }
@@ -84,7 +85,6 @@ ApplicationWindow {
//color: "#D9DDE7" //color: "#D9DDE7"
color: "#252525" color: "#252525"
ColumnLayout { ColumnLayout {
y: 50 y: 50
anchors.left: parent.left anchors.left: parent.left
@@ -120,6 +120,17 @@ ApplicationWindow {
} }
} }
} }
Image {
source: ui.assetPath("net.png")
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
anchors.fill: parent
onClicked: {
setView(infoView)
}
}
}
} }
} }
@@ -143,6 +154,7 @@ ApplicationWindow {
TableView { TableView {
id: txTableView id: txTableView
anchors.fill: parent anchors.fill: parent
TableViewColumn{ role: "inout" ; title: "" ; width: 40 }
TableViewColumn{ role: "value" ; title: "Value" ; width: 100 } TableViewColumn{ role: "value" ; title: "Value" ; width: 100 }
TableViewColumn{ role: "address" ; title: "Address" ; width: 430 } TableViewColumn{ role: "address" ; title: "Address" ; width: 430 }
TableViewColumn{ role: "contract" ; title: "Contract" ; width: 100 } TableViewColumn{ role: "contract" ; title: "Contract" ; width: 100 }
@@ -217,6 +229,33 @@ ApplicationWindow {
} }
} }
Rectangle {
id: infoView
property var title: "Information"
visible: false
color: "#00000000"
anchors.fill: parent
Label {
id: addressLabel
text: "Address"
anchors {
margins: 5
top: parent.top
left: parent.left
}
}
TextField {
anchors {
margins: 5
left: addressLabel.right
top: parent.top
}
text: pub.getKey().address
width: 500
}
}
/* /*
signal addPlugin(string name) signal addPlugin(string name)
Component { Component {
@@ -365,7 +404,7 @@ ApplicationWindow {
anchors.left: aboutIcon.right anchors.left: aboutIcon.right
anchors.leftMargin: 10 anchors.leftMargin: 10
font.pointSize: 12 font.pointSize: 12
text: "<h2>Ethereal</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br><h3>Binary Distribution</h3>Jarrad Hope<br>" text: "<h2>Ethereal</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>"
} }
} }
@@ -390,7 +429,6 @@ ApplicationWindow {
} }
} }
SplitView { SplitView {
anchors.fill: parent anchors.fill: parent
property var asmModel: ListModel { property var asmModel: ListModel {
id: asmModel id: asmModel
@@ -485,14 +523,14 @@ ApplicationWindow {
walletValueLabel.text = value walletValueLabel.text = value
} }
function addTx(tx) { function addTx(tx, inout) {
var isContract var isContract
if (tx.contract == true){ if (tx.contract == true){
isContract = "Yes" isContract = "Yes"
}else{ }else{
isContract = "No" isContract = "No"
} }
txModel.insert(0, {hash: tx.hash, address: tx.address, value: tx.value, contract: isContract}) txModel.insert(0, {inout: inout, hash: tx.hash, address: tx.address, value: tx.value, contract: isContract})
} }
function addBlock(block) { function addBlock(block) {

View File

@@ -47,13 +47,37 @@ ApplicationWindow {
try { try {
switch(data.call) { switch(data.call) {
case "getCoinBase":
postData(data._seed, eth.getCoinBase())
break
case "getIsListening":
postData(data._seed, eth.getIsListening())
break
case "getIsMining":
postData(data._seed, eth.getIsMining())
break
case "getPeerCount":
postData(data._seed, eth.getPeerCount())
break
case "getTxCountAt":
require(1)
postData(data._seed, eth.getTxCountAt(data.args[0]))
break
case "getBlockByNumber": case "getBlockByNumber":
var block = eth.getBlock("b9b56cf6f907fbee21db0cd7cbc0e6fea2fe29503a3943e275c5e467d649cb06") var block = eth.getBlock(data.args[0])
postData(data._seed, block) postData(data._seed, block)
break break
case "getBlockByHash": case "getBlockByHash":
var block = eth.getBlock("b9b56cf6f907fbee21db0cd7cbc0e6fea2fe29503a3943e275c5e467d649cb06") var block = eth.getBlock(data.args[0])
postData(data._seed, block) postData(data._seed, block)
break break
case "transact": case "transact":
require(5) require(5)
@@ -94,11 +118,14 @@ ApplicationWindow {
postData(data._seed, null) postData(data._seed, null)
break; break;
case "set": case "set":
console.log("'Set' has been depcrecated")
/*
for(var key in data.args) { for(var key in data.args) {
if(webview.hasOwnProperty(key)) { if(webview.hasOwnProperty(key)) {
window[key] = data.args[key]; window[key] = data.args[key];
} }
} }
*/
break; break;
case "getSecretToAddress": case "getSecretToAddress":
require(1) require(1)

View File

@@ -9,7 +9,7 @@
<script type="text/javascript"> <script type="text/javascript">
var jefcoinAddr = "b7cb72c47ec4f31751d0d628b5a33fd6671bbba0" var jefcoinAddr = "fc0a9436890478bb9b1c6ed7455c2535366f4a99"
var mAddr = "" var mAddr = ""
function createTransaction() { function createTransaction() {
@@ -23,8 +23,6 @@ function createTransaction() {
} }
function init() { function init() {
eth.set({width: 500});
eth.getKey(function(sec) { eth.getKey(function(sec) {
mAddr = sec; mAddr = sec;
eth.getSecretToAddress(sec, function(addr) { eth.getSecretToAddress(sec, function(addr) {

View File

@@ -0,0 +1,43 @@
<html>
<head>
<title>Utils</title>
</head>
<body onload="init();">
<label>Nonce for 2ef47100e0787b915105fd5e3f4ff6752079d5cb</label>
<p id="nonce"></p>
<label>Connected peers</label>
<p id="peers"></p>
<label>Is mining</label>
<p id="isMining"></p>
<label>Is listening</label>
<p id="isListen"></p>
<label>Coinbase</label>
<p id="coinbase"></p>
<script type="text/javascript">
function init() {
eth.getTxCountAt("2ef47100e0787b915105fd5e3f4ff6752079d5cb", function(nonce){
document.querySelector("#nonce").innerHTML = nonce;
})
eth.getPeerCount(function(peerLength){
document.querySelector("#peers").innerHTML = peerLength;
})
eth.getIsMining(function(mining){
document.querySelector("#isMining").innerHTML = mining;
})
eth.getIsListening(function(listen){
document.querySelector("#isListen").innerHTML = listen;
})
eth.getCoinBase(function(address){
document.querySelector("#coinbase").innerHTML = address;
})
}
</script>
</body>
</html>

View File

@@ -4,9 +4,11 @@ import (
"flag" "flag"
) )
var Identifier string
var StartConsole bool var StartConsole bool
var StartMining bool var StartMining bool
var StartRpc bool var StartRpc bool
var RpcPort int
var UseUPnP bool var UseUPnP bool
var OutboundPort string var OutboundPort string
var ShowGenesis bool var ShowGenesis bool
@@ -20,6 +22,7 @@ var DataDir string
var AssetPath string var AssetPath string
func Init() { func Init() {
flag.StringVar(&Identifier, "i", "", "Custom client identifier")
flag.BoolVar(&StartConsole, "c", false, "debug and testing console") flag.BoolVar(&StartConsole, "c", false, "debug and testing console")
flag.BoolVar(&StartMining, "m", false, "start dagger mining") flag.BoolVar(&StartMining, "m", false, "start dagger mining")
flag.BoolVar(&StartRpc, "r", false, "start rpc server") flag.BoolVar(&StartRpc, "r", false, "start rpc server")
@@ -28,10 +31,11 @@ func Init() {
flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key") flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.StringVar(&OutboundPort, "p", "30303", "listening port") flag.StringVar(&OutboundPort, "p", "30303", "listening port")
flag.StringVar(&DataDir, "dir", ".ethereal", "ethereum data directory") flag.StringVar(&DataDir, "dir", ".ethereal", "ethereum data directory")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)") flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.IntVar(&MaxPeer, "x", 5, "maximum desired peers") flag.IntVar(&MaxPeer, "x", 10, "maximum desired peers")
flag.StringVar(&AssetPath, "asset_path", "", "absolute path to GUI assets directory") flag.StringVar(&AssetPath, "asset_path", "", "absolute path to GUI assets directory")
flag.Parse() flag.Parse()

View File

@@ -4,8 +4,6 @@ import (
"fmt" "fmt"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethrpc"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/ethereal/ui" "github.com/ethereum/go-ethereum/ethereal/ui"
"github.com/ethereum/go-ethereum/utils" "github.com/ethereum/go-ethereum/utils"
@@ -41,7 +39,7 @@ func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
ethchain.InitFees() ethchain.InitFees()
ethutil.ReadConfig(DataDir) ethutil.ReadConfig(DataDir, ethutil.LogFile|ethutil.LogStd, Identifier)
// Instantiated a eth stack // Instantiated a eth stack
ethereum, err := eth.New(eth.CapDefault, UseUPnP) ethereum, err := eth.New(eth.CapDefault, UseUPnP)
@@ -89,8 +87,19 @@ func main() {
} }
if ExportKey { if ExportKey {
key := ethutil.Config.Db.GetKeys()[0] keyPair := ethutil.GetKeyRing().Get(0)
fmt.Printf("%x\n", key.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)
os.Exit(0) os.Exit(0)
} }
@@ -99,9 +108,12 @@ func main() {
os.Exit(0) os.Exit(0)
} }
if StartMining {
utils.DoMining(ethereum)
}
if StartRpc { if StartRpc {
ethereum.RpcServer = ethrpc.NewJsonRpcServer(ethpub.NewPEthereum(ethereum.StateManager(), ethereum.BlockChain(), ethereum.TxPool())) utils.DoRpc(ethereum, RpcPort)
go ethereum.RpcServer.Start()
} }
log.Printf("Starting Ethereum GUI v%s\n", ethutil.Config.Ver) log.Printf("Starting Ethereum GUI v%s\n", ethutil.Config.Ver)
@@ -110,5 +122,11 @@ func main() {
ethereum.MaxPeers = MaxPeer ethereum.MaxPeers = MaxPeer
gui := ethui.New(ethereum) gui := ethui.New(ethereum)
ethereum.Start(UseSeed)
gui.Start(AssetPath) gui.Start(AssetPath)
// Wait for shutdown
ethereum.WaitForShutdown()
} }

View File

@@ -18,6 +18,7 @@ type AppContainer interface {
NewBlock(*ethchain.Block) NewBlock(*ethchain.Block)
ObjectChanged(*ethchain.StateObject) ObjectChanged(*ethchain.StateObject)
StorageChanged(*ethchain.StorageState) StorageChanged(*ethchain.StorageState)
NewWatcher(chan bool)
} }
type ExtApplication struct { type ExtApplication struct {
@@ -26,6 +27,7 @@ type ExtApplication struct {
blockChan chan ethutil.React blockChan chan ethutil.React
changeChan chan ethutil.React changeChan chan ethutil.React
quitChan chan bool quitChan chan bool
watcherQuitChan chan bool
container AppContainer container AppContainer
lib *UiLib lib *UiLib
@@ -34,10 +36,11 @@ type ExtApplication struct {
func NewExtApplication(container AppContainer, lib *UiLib) *ExtApplication { func NewExtApplication(container AppContainer, lib *UiLib) *ExtApplication {
app := &ExtApplication{ app := &ExtApplication{
ethpub.NewPEthereum(lib.eth.StateManager(), lib.eth.BlockChain(), lib.eth.TxPool()), ethpub.NewPEthereum(lib.eth),
make(chan ethutil.React, 1), make(chan ethutil.React, 1),
make(chan ethutil.React, 1), make(chan ethutil.React, 1),
make(chan bool), make(chan bool),
make(chan bool),
container, container,
lib, lib,
nil, nil,
@@ -66,6 +69,8 @@ func (app *ExtApplication) run() {
reactor := app.lib.eth.Reactor() reactor := app.lib.eth.Reactor()
reactor.Subscribe("newBlock", app.blockChan) reactor.Subscribe("newBlock", app.blockChan)
app.container.NewWatcher(app.watcherQuitChan)
win := app.container.Window() win := app.container.Window()
win.Show() win.Show()
win.Wait() win.Wait()
@@ -83,6 +88,7 @@ func (app *ExtApplication) stop() {
// Kill the main loop // Kill the main loop
app.quitChan <- true app.quitChan <- true
app.watcherQuitChan <- true
close(app.blockChan) close(app.blockChan)
close(app.quitChan) close(app.quitChan)

View File

@@ -9,7 +9,6 @@ import (
"github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml" "github.com/go-qml/qml"
"github.com/obscuren/mutan"
"math/big" "math/big"
"strings" "strings"
) )
@@ -25,6 +24,7 @@ type Gui struct {
// The public Ethereum library // The public Ethereum library
lib *EthLib lib *EthLib
uiLib *UiLib
txDb *ethdb.LDBDatabase txDb *ethdb.LDBDatabase
@@ -41,23 +41,21 @@ func New(ethereum *eth.Ethereum) *Gui {
panic(err) panic(err)
} }
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
// On first run we won't have any keys yet, so this would crash. // 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 // Therefor we check if we are ready to actually start this process
var addr []byte var addr []byte
if len(data) > 0 { if ethutil.GetKeyRing().Len() != 0 {
key := ethutil.Config.Db.GetKeys()[0] addr = ethutil.GetKeyRing().Get(0).Address()
addr = key.Address()
//ethereum.StateManager().WatchAddr(addr)
} }
pub := ethpub.NewPEthereum(ethereum.StateManager(), ethereum.BlockChain(), ethereum.TxPool()) pub := ethpub.NewPEthereum(ethereum)
return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub} return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub}
} }
func (gui *Gui) Start(assetPath string) { func (gui *Gui) Start(assetPath string) {
const version = "0.5.0 RC9"
defer gui.txDb.Close() defer gui.txDb.Close()
// Register ethereum functions // Register ethereum functions
@@ -67,7 +65,7 @@ func (gui *Gui) Start(assetPath string) {
Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" },
}}) }})
ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.5.0 RC3")) ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", version))
ethutil.Config.Log.Infoln("[GUI] Starting GUI") ethutil.Config.Log.Infoln("[GUI] Starting GUI")
// Create a new QML engine // Create a new QML engine
gui.engine = qml.NewEngine() gui.engine = qml.NewEngine()
@@ -75,19 +73,19 @@ func (gui *Gui) Start(assetPath string) {
// Expose the eth library and the ui library to QML // Expose the eth library and the ui library to QML
context.SetVar("eth", gui) context.SetVar("eth", gui)
uiLib := NewUiLib(gui.engine, gui.eth, assetPath) context.SetVar("pub", gui.pub)
context.SetVar("ui", uiLib) gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath)
context.SetVar("ui", gui.uiLib)
// Load the main QML interface // Load the main QML interface
data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
var err error
var component qml.Object
firstRun := len(data) == 0
if firstRun { var win *qml.Window
component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml")) var err error
if len(data) == 0 {
win, err = gui.showKeyImport(context)
} else { } else {
component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml")) win, err = gui.showWallet(context)
} }
if err != nil { if err != nil {
ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'") ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'")
@@ -95,26 +93,48 @@ func (gui *Gui) Start(assetPath string) {
panic(err) panic(err)
} }
gui.win = component.CreateWindow(nil) win.Show()
uiLib.win = gui.win win.Wait()
db := &Debugger{gui.win, make(chan bool)}
gui.lib.Db = db
uiLib.Db = db
// Add the ui as a log system so we can log directly to the UGI gui.eth.Stop()
ethutil.Config.Log.AddLogSystem(gui) }
func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/wallet.qml"))
if err != nil {
return nil, err
}
win := gui.createWindow(component)
// Loads previous blocks
if firstRun == false {
go gui.setInitialBlockChain() go gui.setInitialBlockChain()
go gui.readPreviousTransactions() go gui.readPreviousTransactions()
go gui.update() go gui.update()
return win, nil
} }
gui.win.Show() func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
gui.win.Wait() context.SetVar("lib", gui.lib)
component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
if err != nil {
return nil, err
}
gui.eth.Stop() return gui.createWindow(component), nil
}
func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
win := comp.CreateWindow(nil)
gui.win = win
gui.uiLib.win = win
db := &Debugger{gui.win, make(chan bool)}
gui.lib.Db = db
gui.uiLib.Db = db
return gui.win
} }
func (gui *Gui) setInitialBlockChain() { func (gui *Gui) setInitialBlockChain() {
@@ -131,7 +151,15 @@ func (gui *Gui) readPreviousTransactions() {
for it.Next() { for it.Next() {
tx := ethchain.NewTransactionFromBytes(it.Value()) tx := ethchain.NewTransactionFromBytes(it.Value())
gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) var inout string
if bytes.Compare(tx.Sender(), gui.addr) == 0 {
inout = "send"
} else {
inout = "recv"
}
gui.win.Root().Call("addTx", ethpub.NewPTx(tx), inout)
} }
it.Release() it.Release()
} }
@@ -140,58 +168,76 @@ func (gui *Gui) processBlock(block *ethchain.Block) {
gui.win.Root().Call("addBlock", ethpub.NewPBlock(block)) gui.win.Root().Call("addBlock", ethpub.NewPBlock(block))
} }
func (gui *Gui) setWalletValue(amount, unconfirmedFunds *big.Int) {
var str string
if unconfirmedFunds != nil {
pos := "+"
if unconfirmedFunds.Cmp(big.NewInt(0)) < 0 {
pos = "-"
}
val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds)))
str = fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(amount), pos, val)
} else {
str = fmt.Sprintf("%v", ethutil.CurrencyToString(amount))
}
gui.win.Root().Call("setWalletValue", str)
}
// Simple go routine function that updates the list of peers in the GUI // Simple go routine function that updates the list of peers in the GUI
func (gui *Gui) update() { func (gui *Gui) update() {
txChan := make(chan ethchain.TxMsg, 1) reactor := gui.eth.Reactor()
gui.eth.TxPool().Subscribe(txChan)
blockChan := make(chan ethutil.React, 1)
txChan := make(chan ethutil.React, 1)
reactor.Subscribe("newBlock", blockChan)
reactor.Subscribe("newTx:pre", txChan)
reactor.Subscribe("newTx:post", txChan)
state := gui.eth.StateManager().TransState() state := gui.eth.StateManager().TransState()
unconfirmedFunds := new(big.Int) unconfirmedFunds := new(big.Int)
gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetStateObject(gui.addr).Amount))) gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.addr).Amount)))
for { for {
select { select {
case b := <-blockChan:
block := b.Resource.(*ethchain.Block)
if bytes.Compare(block.Coinbase, gui.addr) == 0 {
gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.addr).Amount, nil)
}
case txMsg := <-txChan: case txMsg := <-txChan:
tx := txMsg.Tx tx := txMsg.Resource.(*ethchain.Transaction)
if txMsg.Type == ethchain.TxPre { if txMsg.Event == "newTx:pre" {
object := state.GetStateObject(gui.addr) object := state.GetAccount(gui.addr)
if bytes.Compare(tx.Sender(), gui.addr) == 0 && object.Nonce <= tx.Nonce { if bytes.Compare(tx.Sender(), gui.addr) == 0 {
gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "send")
gui.txDb.Put(tx.Hash(), tx.RlpEncode()) gui.txDb.Put(tx.Hash(), tx.RlpEncode())
object.Nonce += 1
state.SetStateObject(object)
unconfirmedFunds.Sub(unconfirmedFunds, tx.Value) unconfirmedFunds.Sub(unconfirmedFunds, tx.Value)
} else if bytes.Compare(tx.Recipient, gui.addr) == 0 { } else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "recv")
gui.txDb.Put(tx.Hash(), tx.RlpEncode()) gui.txDb.Put(tx.Hash(), tx.RlpEncode())
unconfirmedFunds.Add(unconfirmedFunds, tx.Value) unconfirmedFunds.Add(unconfirmedFunds, tx.Value)
} }
pos := "+" gui.setWalletValue(object.Amount, unconfirmedFunds)
if unconfirmedFunds.Cmp(big.NewInt(0)) >= 0 {
pos = "-"
}
val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds)))
str := fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(object.Amount), pos, val)
gui.win.Root().Call("setWalletValue", str)
} else { } else {
object := state.GetStateObject(gui.addr) object := state.GetAccount(gui.addr)
if bytes.Compare(tx.Sender(), gui.addr) == 0 { if bytes.Compare(tx.Sender(), gui.addr) == 0 {
object.SubAmount(tx.Value) object.SubAmount(tx.Value)
} else if bytes.Compare(tx.Recipient, gui.addr) == 0 { } else if bytes.Compare(tx.Recipient, gui.addr) == 0 {
object.AddAmount(tx.Value) object.AddAmount(tx.Value)
} }
gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(object.Amount))) gui.setWalletValue(object.Amount, nil)
state.SetStateObject(object) state.UpdateStateObject(object)
} }
} }
} }
@@ -215,15 +261,13 @@ func (gui *Gui) Printf(format string, v ...interface{}) {
} }
func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) { func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
keyPair := ethutil.Config.Db.GetKeys()[0] keyPair := ethutil.GetKeyRing().Get(0)
return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data) return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data)
} }
func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) { func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) {
keyPair := ethutil.Config.Db.GetKeys()[0] keyPair := ethutil.GetKeyRing().Get(0)
mainInput, initInput := mutan.PreParse(data) return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, data)
return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, initInput, mainInput)
} }

View File

@@ -6,6 +6,12 @@ import (
"github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml" "github.com/go-qml/qml"
"github.com/howeyc/fsnotify"
"io/ioutil"
"log"
"net/url"
"os"
"path"
"path/filepath" "path/filepath"
) )
@@ -15,6 +21,7 @@ type HtmlApplication struct {
engine *qml.Engine engine *qml.Engine
lib *UiLib lib *UiLib
path string path string
watcher *fsnotify.Watcher
} }
func NewHtmlApplication(path string, lib *UiLib) *HtmlApplication { func NewHtmlApplication(path string, lib *UiLib) *HtmlApplication {
@@ -47,6 +54,59 @@ func (app *HtmlApplication) Create() error {
return nil return nil
} }
func (app *HtmlApplication) RootFolder() string {
folder, err := url.Parse(app.path)
if err != nil {
return ""
}
return path.Dir(folder.RequestURI())
}
func (app *HtmlApplication) RecursiveFolders() []os.FileInfo {
files, _ := ioutil.ReadDir(app.RootFolder())
var folders []os.FileInfo
for _, file := range files {
if file.IsDir() {
folders = append(folders, file)
}
}
return folders
}
func (app *HtmlApplication) NewWatcher(quitChan chan bool) {
var err error
app.watcher, err = fsnotify.NewWatcher()
if err != nil {
return
}
err = app.watcher.Watch(app.RootFolder())
if err != nil {
log.Fatal(err)
}
for _, folder := range app.RecursiveFolders() {
fullPath := app.RootFolder() + "/" + folder.Name()
app.watcher.Watch(fullPath)
}
go func() {
out:
for {
select {
case <-quitChan:
app.watcher.Close()
break out
case <-app.watcher.Event:
//ethutil.Config.Log.Debugln("Got event:", ev)
app.webView.Call("reload")
case err := <-app.watcher.Error:
// TODO: Do something here
ethutil.Config.Log.Infoln("Watcher error:", err)
}
}
}()
}
func (app *HtmlApplication) Engine() *qml.Engine { func (app *HtmlApplication) Engine() *qml.Engine {
return app.engine return app.engine
} }

View File

@@ -34,10 +34,13 @@ func (lib *EthLib) ImportAndSetPrivKey(privKey string) bool {
} }
func (lib *EthLib) CreateAndSetPrivKey() (string, string, string, string) { func (lib *EthLib) CreateAndSetPrivKey() (string, string, string, string) {
pub, prv := secp256k1.GenerateKeyPair() _, prv := secp256k1.GenerateKeyPair()
pair := &ethutil.Key{PrivateKey: prv, PublicKey: pub} keyPair, err := ethutil.GetKeyRing().NewKeyPair(prv)
ethutil.Config.Db.Put([]byte("KeyRing"), pair.RlpEncode()) if err != nil {
mne := ethutil.MnemonicEncode(ethutil.Hex(prv)) panic(err)
mnemonicString := strings.Join(mne, " ") }
return mnemonicString, fmt.Sprintf("%x", pair.Address()), fmt.Sprintf("%x", prv), fmt.Sprintf("%x", pub)
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

@@ -135,10 +135,10 @@ func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string)
for _, str := range dis { for _, str := range dis {
ui.win.Root().Call("setAsm", str) ui.win.Root().Call("setAsm", str)
} }
callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), callerScript, nil) callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), nil)
// Contract addr as test address // Contract addr as test address
keyPair := ethutil.Config.Db.GetKeys()[0] keyPair := ethutil.GetKeyRing().Get(0)
account := ui.eth.StateManager().TransState().GetStateObject(keyPair.Address()) account := ui.eth.StateManager().TransState().GetStateObject(keyPair.Address())
c := ethchain.MakeContract(callerTx, state) c := ethchain.MakeContract(callerTx, state)
callerClosure := ethchain.NewClosure(account, c, c.Script(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr)) callerClosure := ethchain.NewClosure(account, c, c.Script(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr))

View File

@@ -2,11 +2,14 @@ package main
import ( import (
"flag" "flag"
"fmt"
"os"
) )
var StartConsole bool var Identifier string
var StartMining bool var StartMining bool
var StartRpc bool var StartRpc bool
var RpcPort int
var UseUPnP bool var UseUPnP bool
var OutboundPort string var OutboundPort string
var ShowGenesis bool var ShowGenesis bool
@@ -19,13 +22,20 @@ var ExportKey bool
var LogFile string var LogFile string
var DataDir string var DataDir string
var NonInteractive bool var NonInteractive bool
var StartJsConsole bool
var InputFile string
func Init() { func Init() {
flag.BoolVar(&StartConsole, "c", false, "debug and testing console") flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s [options] [filename]:\n", os.Args[0])
flag.PrintDefaults()
}
flag.StringVar(&Identifier, "i", "", "custom client identifier")
flag.BoolVar(&StartMining, "m", false, "start dagger mining") flag.BoolVar(&StartMining, "m", false, "start dagger mining")
flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits") flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits")
//flag.BoolVar(&UseGui, "gui", true, "use the gui")
flag.BoolVar(&StartRpc, "r", false, "start rpc server") flag.BoolVar(&StartRpc, "r", false, "start rpc server")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support") flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&UseSeed, "seed", true, "seed peers")
@@ -35,7 +45,10 @@ func Init() {
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&DataDir, "dir", ".ethereum", "ethereum data directory") flag.StringVar(&DataDir, "dir", ".ethereum", "ethereum data directory")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)") flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.IntVar(&MaxPeer, "x", 5, "maximum desired peers") flag.IntVar(&MaxPeer, "x", 10, "maximum desired peers")
flag.BoolVar(&StartJsConsole, "js", false, "exp")
flag.Parse() flag.Parse()
InputFile = flag.Arg(0)
} }

View File

@@ -1,259 +0,0 @@
package main
import (
"bufio"
"bytes"
"encoding/hex"
"errors"
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"github.com/ethereum/go-ethereum/utils"
"github.com/obscuren/mutan"
"os"
"strings"
)
type Console struct {
db *ethdb.MemDatabase
trie *ethutil.Trie
ethereum *eth.Ethereum
}
func NewConsole(s *eth.Ethereum) *Console {
db, _ := ethdb.NewMemDatabase()
trie := ethutil.NewTrie(db, "")
return &Console{db: db, trie: trie, ethereum: s}
}
func (i *Console) ValidateInput(action string, argumentLength int) error {
err := false
var expArgCount int
switch {
case action == "update" && argumentLength != 2:
err = true
expArgCount = 2
case action == "get" && argumentLength != 1:
err = true
expArgCount = 1
case action == "dag" && argumentLength != 2:
err = true
expArgCount = 2
case action == "decode" && argumentLength != 1:
err = true
expArgCount = 1
case action == "encode" && argumentLength != 1:
err = true
expArgCount = 1
case action == "gettx" && argumentLength != 1:
err = true
expArgCount = 1
case action == "tx" && argumentLength != 4:
err = true
expArgCount = 4
case action == "getaddr" && argumentLength != 1:
err = true
expArgCount = 1
case action == "contract" && argumentLength != 2:
err = true
expArgCount = 2
case action == "say" && argumentLength != 1:
err = true
expArgCount = 1
case action == "addp" && argumentLength != 1:
err = true
expArgCount = 1
case action == "block" && argumentLength != 1:
err = true
expArgCount = 1
}
if err {
return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
} else {
return nil
}
}
func (i *Console) Editor() string {
var buff bytes.Buffer
for {
reader := bufio.NewReader(os.Stdin)
str, _, err := reader.ReadLine()
if len(str) > 0 {
buff.Write(str)
buff.WriteString("\n")
}
if err != nil && err.Error() == "EOF" {
break
}
}
return buff.String()
}
func (i *Console) PrintRoot() {
root := ethutil.NewValue(i.trie.Root)
if len(root.Bytes()) != 0 {
fmt.Println(hex.EncodeToString(root.Bytes()))
} else {
fmt.Println(i.trie.Root)
}
}
func (i *Console) ParseInput(input string) bool {
scanner := bufio.NewScanner(strings.NewReader(input))
scanner.Split(bufio.ScanWords)
count := 0
var tokens []string
for scanner.Scan() {
count++
tokens = append(tokens, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading input:", err)
}
if len(tokens) == 0 {
return true
}
err := i.ValidateInput(tokens[0], count-1)
if err != nil {
fmt.Println(err)
} else {
switch tokens[0] {
case "update":
i.trie.Update(tokens[1], tokens[2])
i.PrintRoot()
case "get":
fmt.Println(i.trie.Get(tokens[1]))
case "root":
i.PrintRoot()
case "rawroot":
fmt.Println(i.trie.Root)
case "print":
i.db.Print()
case "dag":
fmt.Println(ethchain.DaggerVerify(ethutil.Big(tokens[1]), // hash
ethutil.BigPow(2, 36), // diff
ethutil.Big(tokens[2]))) // nonce
case "decode":
value := ethutil.NewValueFromBytes([]byte(tokens[1]))
fmt.Println(value)
case "getaddr":
encoded, _ := hex.DecodeString(tokens[1])
addr := i.ethereum.BlockChain().CurrentBlock.State().GetAccount(encoded)
fmt.Println("addr:", addr)
case "block":
encoded, _ := hex.DecodeString(tokens[1])
block := i.ethereum.BlockChain().GetBlock(encoded)
info := block.BlockInfo()
fmt.Printf("++++++++++ #%d ++++++++++\n%v\n", info.Number, block)
case "say":
i.ethereum.Broadcast(ethwire.MsgTalkTy, []interface{}{tokens[1]})
case "addp":
i.ethereum.ConnectToPeer(tokens[1])
case "pcount":
fmt.Println("peers:", i.ethereum.Peers().Len())
case "encode":
fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
case "tx":
recipient, err := hex.DecodeString(tokens[1])
if err != nil {
fmt.Println("recipient err:", err)
} else {
tx := ethchain.NewTransactionMessage(recipient, ethutil.Big(tokens[2]), ethutil.Big(tokens[3]), ethutil.Big(tokens[4]), nil)
key := ethutil.Config.Db.GetKeys()[0]
tx.Sign(key.PrivateKey)
i.ethereum.TxPool().QueueTransaction(tx)
fmt.Printf("%x\n", tx.Hash())
}
case "gettx":
addr, _ := hex.DecodeString(tokens[1])
data, _ := ethutil.Config.Db.Get(addr)
if len(data) != 0 {
decoder := ethutil.NewValueFromBytes(data)
fmt.Println(decoder)
} else {
fmt.Println("gettx: tx not found")
}
case "contract":
fmt.Println("Contract editor (Ctrl-D = done)")
mainInput, initInput := mutan.PreProcess(i.Editor())
mainScript, err := utils.Compile(mainInput)
if err != nil {
fmt.Println(err)
break
}
initScript, err := utils.Compile(initInput)
if err != nil {
fmt.Println(err)
break
}
contract := ethchain.NewContractCreationTx(ethutil.Big(tokens[0]), ethutil.Big(tokens[1]), ethutil.Big(tokens[1]), mainScript, initScript)
key := ethutil.Config.Db.GetKeys()[0]
contract.Sign(key.PrivateKey)
i.ethereum.TxPool().QueueTransaction(contract)
fmt.Printf("%x\n", contract.Hash()[12:])
case "exit", "quit", "q":
return false
case "help":
fmt.Printf("COMMANDS:\n" +
"\033[1m= DB =\033[0m\n" +
"update KEY VALUE - Updates/Creates a new value for the given key\n" +
"get KEY - Retrieves the given key\n" +
"root - Prints the hex encoded merkle root\n" +
"rawroot - Prints the raw merkle root\n" +
"block HASH - Prints the block\n" +
"getaddr ADDR - Prints the account associated with the address\n" +
"\033[1m= Dagger =\033[0m\n" +
"dag HASH NONCE - Verifies a nonce with the given hash with dagger\n" +
"\033[1m= Encoding =\033[0m\n" +
"decode STR\n" +
"encode STR\n" +
"\033[1m= Other =\033[0m\n" +
"addp HOST:PORT\n" +
"tx TO AMOUNT\n" +
"contract AMOUNT\n")
default:
fmt.Println("Unknown command:", tokens[0])
}
}
return true
}
func (i *Console) Start() {
fmt.Printf("Eth Console. Type (help) for help\n")
reader := bufio.NewReader(os.Stdin)
for {
fmt.Printf("eth >>> ")
str, _, err := reader.ReadLine()
if err != nil {
fmt.Println("Error reading input", err)
} else {
if !i.ParseInput(string(str)) {
return
}
}
}
}

View File

@@ -4,11 +4,9 @@ import (
"fmt" "fmt"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethminer"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethrpc"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils" "github.com/ethereum/go-ethereum/utils"
"io/ioutil"
"log" "log"
"os" "os"
"os/signal" "os/signal"
@@ -18,16 +16,15 @@ import (
const Debug = true const Debug = true
// Register interrupt handlers so we can stop the ethereum func RegisterInterrupt(cb func(os.Signal)) {
func RegisterInterrupts(s *eth.Ethereum) { go func() {
// Buffered chan of one is enough // Buffered chan of one is enough
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
// Notify about interrupts for now // Notify about interrupts for now
signal.Notify(c, os.Interrupt) signal.Notify(c, os.Interrupt)
go func() {
for sig := range c { for sig := range c {
fmt.Printf("Shutting down (%v) ... \n", sig) cb(sig)
s.Stop()
} }
}() }()
} }
@@ -55,7 +52,15 @@ func main() {
var logSys *log.Logger var logSys *log.Logger
flags := log.LstdFlags flags := log.LstdFlags
ethutil.ReadConfig(DataDir) var lt ethutil.LoggerType
if StartJsConsole || len(InputFile) > 0 {
lt = ethutil.LogFile
} else {
lt = ethutil.LogFile | ethutil.LogStd
}
ethutil.ReadConfig(DataDir, lt, Identifier)
logger := ethutil.Config.Log logger := ethutil.Config.Log
if LogFile != "" { if LogFile != "" {
@@ -67,10 +72,9 @@ func main() {
log.SetOutput(logfile) log.SetOutput(logfile)
logSys = log.New(logfile, "", flags) logSys = log.New(logfile, "", flags)
logger.AddLogSystem(logSys) logger.AddLogSystem(logSys)
} } else {
/*else {
logSys = log.New(os.Stdout, "", flags) logSys = log.New(os.Stdout, "", flags)
}*/ }
ethchain.InitFees() ethchain.InitFees()
@@ -105,8 +109,19 @@ func main() {
} }
os.Exit(0) os.Exit(0)
case ExportKey: case ExportKey:
key := ethutil.Config.Db.GetKeys()[0] keyPair := ethutil.GetKeyRing().Get(0)
logSys.Println(fmt.Sprintf("prvk: %x\n", key.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)
os.Exit(0) os.Exit(0)
case ShowGenesis: case ShowGenesis:
logSys.Println(ethereum.BlockChain().Genesis()) logSys.Println(ethereum.BlockChain().Genesis())
@@ -122,48 +137,50 @@ func main() {
// Set the max peers // Set the max peers
ethereum.MaxPeers = MaxPeer ethereum.MaxPeers = MaxPeer
if StartConsole { // Set Mining status
err := os.Mkdir(ethutil.Config.ExecPath, os.ModePerm) ethereum.Mining = StartMining
// Error is OK if the error is ErrExist
if err != nil && !os.IsExist(err) { if StartMining {
log.Panic("Unable to create EXECPATH:", err) utils.DoMining(ethereum)
} }
console := NewConsole(ethereum) if StartJsConsole {
go console.Start() repl := NewJSRepl(ethereum)
go repl.Start()
RegisterInterrupt(func(os.Signal) {
repl.Stop()
})
} else if len(InputFile) > 0 {
file, err := os.Open(InputFile)
if err != nil {
ethutil.Config.Log.Fatal(err)
} }
content, err := ioutil.ReadAll(file)
if err != nil {
ethutil.Config.Log.Fatal(err)
}
re := NewJSRE(ethereum)
RegisterInterrupt(func(os.Signal) {
re.Stop()
})
re.Run(string(content))
}
if StartRpc { if StartRpc {
ethereum.RpcServer = ethrpc.NewJsonRpcServer(ethpub.NewPEthereum(ethereum.StateManager(), ethereum.BlockChain(), ethereum.TxPool())) utils.DoRpc(ethereum, RpcPort)
go ethereum.RpcServer.Start()
} }
RegisterInterrupts(ethereum) RegisterInterrupt(func(sig os.Signal) {
fmt.Printf("Shutting down (%v) ... \n", sig)
ethereum.Stop()
})
ethereum.Start(UseSeed) ethereum.Start(UseSeed)
if StartMining {
logger.Infoln("Miner started")
// Fake block mining. It broadcasts a new block every 5 seconds
go func() {
if StartMining {
logger.Infoln("Miner started")
go func() {
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
keyRing := ethutil.NewValueFromBytes(data)
addr := keyRing.Get(1).Bytes()
miner := ethminer.NewDefaultMiner(addr, ethereum)
miner.Start()
}()
}
}()
}
// Wait for shutdown // Wait for shutdown
ethereum.WaitForShutdown() ethereum.WaitForShutdown()
} }

View File

@@ -0,0 +1,190 @@
package main
import (
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils"
"github.com/obscuren/otto"
"io/ioutil"
"os"
"path/filepath"
)
type JSRE struct {
ethereum *eth.Ethereum
vm *otto.Otto
lib *ethpub.PEthereum
blockChan chan ethutil.React
changeChan chan ethutil.React
quitChan chan bool
objectCb map[string][]otto.Value
}
func NewJSRE(ethereum *eth.Ethereum) *JSRE {
re := &JSRE{
ethereum,
otto.New(),
ethpub.NewPEthereum(ethereum),
make(chan ethutil.React, 1),
make(chan ethutil.React, 1),
make(chan bool),
make(map[string][]otto.Value),
}
// Init the JS lib
re.vm.Run(jsLib)
// We have to make sure that, whoever calls this, calls "Stop"
go re.mainLoop()
re.Bind("eth", &JSEthereum{re.lib, re.vm})
re.initStdFuncs()
return re
}
func (self *JSRE) Bind(name string, v interface{}) {
self.vm.Set(name, v)
}
func (self *JSRE) Run(code string) (otto.Value, error) {
return self.vm.Run(code)
}
func (self *JSRE) Require(file string) error {
if len(filepath.Ext(file)) == 0 {
file += ".js"
}
fh, err := os.Open(file)
if err != nil {
return err
}
content, _ := ioutil.ReadAll(fh)
self.Run("exports = {};(function() {" + string(content) + "})();")
return nil
}
func (self *JSRE) Stop() {
// Kill the main loop
self.quitChan <- true
close(self.blockChan)
close(self.quitChan)
close(self.changeChan)
}
func (self *JSRE) mainLoop() {
// Subscribe to events
reactor := self.ethereum.Reactor()
reactor.Subscribe("newBlock", self.blockChan)
out:
for {
select {
case <-self.quitChan:
break out
case block := <-self.blockChan:
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())] {
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)] {
val, _ := self.vm.ToValue(ethpub.NewPStorageState(storageObject))
cb.Call(cb, val)
}
}
}
}
}
func (self *JSRE) initStdFuncs() {
t, _ := self.vm.Get("eth")
eth := t.Object()
eth.Set("watch", self.watch)
eth.Set("addPeer", self.addPeer)
eth.Set("require", self.require)
eth.Set("stopMining", self.stopMining)
eth.Set("startMining", self.startMining)
}
/*
* The following methods are natively implemented javascript functions
*/
func (self *JSRE) stopMining(call otto.FunctionCall) otto.Value {
v, _ := self.vm.ToValue(utils.StopMining(self.ethereum))
return v
}
func (self *JSRE) startMining(call otto.FunctionCall) otto.Value {
v, _ := self.vm.ToValue(utils.StartMining(self.ethereum))
return v
}
// eth.watch
func (self *JSRE) watch(call otto.FunctionCall) otto.Value {
addr, _ := call.Argument(0).ToString()
var storageAddr string
var cb otto.Value
var storageCallback bool
if len(call.ArgumentList) > 2 {
storageCallback = true
storageAddr, _ = call.Argument(1).ToString()
cb = call.Argument(2)
} else {
cb = call.Argument(1)
}
if storageCallback {
self.objectCb[addr+storageAddr] = append(self.objectCb[addr+storageAddr], cb)
event := "storage:" + string(ethutil.FromHex(addr)) + ":" + string(ethutil.FromHex(storageAddr))
self.ethereum.Reactor().Subscribe(event, self.changeChan)
} else {
self.objectCb[addr] = append(self.objectCb[addr], cb)
event := "object:" + string(ethutil.FromHex(addr))
self.ethereum.Reactor().Subscribe(event, self.changeChan)
}
return otto.UndefinedValue()
}
func (self *JSRE) addPeer(call otto.FunctionCall) otto.Value {
host, err := call.Argument(0).ToString()
if err != nil {
return otto.FalseValue()
}
self.ethereum.ConnectToPeer(host)
return otto.TrueValue()
}
func (self *JSRE) require(call otto.FunctionCall) otto.Value {
file, err := call.Argument(0).ToString()
if err != nil {
return otto.UndefinedValue()
}
if err := self.Require(file); err != nil {
fmt.Println("err:", err)
return otto.UndefinedValue()
}
t, _ := self.vm.Get("exports")
return t
}

53
ethereum/js_lib.go Normal file
View File

@@ -0,0 +1,53 @@
package main
const jsLib = `
function pp(object) {
var str = "";
if(object instanceof Array) {
str += "[ ";
for(var i = 0, l = object.length; i < l; i++) {
str += pp(object[i]);
if(i < l-1) {
str += ", ";
}
}
str += " ]";
} else if(typeof(object) === "object") {
str += "{ ";
var last = Object.keys(object).sort().pop()
for(var k in object) {
str += k + ": " + pp(object[k]);
if(k !== last) {
str += ", ";
}
}
str += " }";
} else if(typeof(object) === "string") {
str += "\033[32m'" + object + "'";
} else if(typeof(object) === "undefined") {
str += "\033[1m\033[30m" + object;
} else if(typeof(object) === "number") {
str += "\033[31m" + object;
} else if(typeof(object) === "function") {
str += "\033[35m[Function]";
} else {
str += object;
}
str += "\033[0m";
return str;
}
function prettyPrint(/* */) {
var args = arguments;
for(var i = 0, l = args.length; i < l; i++) {
console.log(pp(args[i]))
}
}
var print = prettyPrint;
`

110
ethereum/repl.go Normal file
View File

@@ -0,0 +1,110 @@
package main
import (
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethpub"
"github.com/obscuren/otto"
)
type Repl interface {
Start()
Stop()
}
type JSRepl struct {
re *JSRE
prompt string
}
func NewJSRepl(ethereum *eth.Ethereum) *JSRepl {
return &JSRepl{re: NewJSRE(ethereum), prompt: "> "}
}
func (self *JSRepl) Start() {
self.read()
}
func (self *JSRepl) Stop() {
self.re.Stop()
}
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)
}
// The JSEthereum object attempts to wrap the PEthereum object and returns
// meaningful javascript objects
type JSBlock struct {
*ethpub.PBlock
eth *JSEthereum
}
func (self *JSBlock) GetTransaction(hash string) otto.Value {
return self.eth.toVal(self.PBlock.GetTransaction(hash))
}
type JSEthereum struct {
*ethpub.PEthereum
vm *otto.Otto
}
func (self *JSEthereum) GetBlock(hash string) otto.Value {
return self.toVal(&JSBlock{self.PEthereum.GetBlock(hash), self})
}
func (self *JSEthereum) GetKey() otto.Value {
return self.toVal(self.PEthereum.GetKey())
}
func (self *JSEthereum) GetStateObject(addr string) otto.Value {
return self.toVal(self.PEthereum.GetStateObject(addr))
}
func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
r, err := self.PEthereum.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr)
if err != nil {
fmt.Println(err)
return otto.UndefinedValue()
}
return self.toVal(r)
}
func (self *JSEthereum) Create(key, valueStr, gasStr, gasPriceStr, scriptStr string) otto.Value {
r, err := self.PEthereum.Create(key, valueStr, gasStr, gasPriceStr, scriptStr)
if err != nil {
fmt.Println(err)
return otto.UndefinedValue()
}
return self.toVal(r)
}
func (self *JSEthereum) toVal(v interface{}) otto.Value {
result, err := self.vm.ToValue(v)
if err != nil {
fmt.Println(err)
return otto.UndefinedValue()
}
return result
}

121
ethereum/repl_darwin.go Normal file
View File

@@ -0,0 +1,121 @@
package main
// #cgo darwin CFLAGS: -I/usr/local/opt/readline/include
// #cgo darwin LDFLAGS: -L/usr/local/opt/readline/lib
// #cgo LDFLAGS: -lreadline
// #include <stdio.h>
// #include <stdlib.h>
// #include <readline/readline.h>
// #include <readline/history.h>
import "C"
import (
"os"
"os/signal"
"strings"
"syscall"
"unsafe"
)
func initReadLine() {
C.rl_catch_sigwinch = 0
C.rl_catch_signals = 0
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGWINCH)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
switch sig {
case syscall.SIGWINCH:
C.rl_resize_terminal()
case os.Interrupt:
C.rl_cleanup_after_signal()
default:
}
}
}()
}
func readLine(prompt *string) *string {
var p *C.char
//readline allows an empty prompt(NULL)
if prompt != nil {
p = C.CString(*prompt)
}
ret := C.readline(p)
if p != nil {
C.free(unsafe.Pointer(p))
}
if ret == nil {
return nil
} //EOF
s := C.GoString(ret)
C.free(unsafe.Pointer(ret))
return &s
}
func addHistory(s string) {
p := C.CString(s)
C.add_history(p)
C.free(unsafe.Pointer(p))
}
var indentCount = 0
var str = ""
func (self *JSRepl) setIndent() {
open := strings.Count(str, "{")
open += strings.Count(str, "(")
closed := strings.Count(str, "}")
closed += strings.Count(str, ")")
indentCount = open - closed
if indentCount <= 0 {
self.prompt = "> "
} else {
self.prompt = strings.Join(make([]string, indentCount*2), "..")
self.prompt += " "
}
}
func (self *JSRepl) read() {
initReadLine()
L:
for {
switch result := readLine(&self.prompt); true {
case result == nil:
break L
case *result != "":
str += *result + "\n"
self.setIndent()
if indentCount <= 0 {
if *result == "exit" {
self.Stop()
break L
}
addHistory(str[:len(str)-1]) //allow user to recall this line
self.parseInput(str)
str = ""
}
}
}
}
func (self *JSRepl) PrintValue(v interface{}) {
method, _ := self.re.vm.Get("prettyPrint")
v, err := self.re.vm.ToValue(v)
if err == nil {
method.Call(method, v)
}
}

1
ethereum/repl_linux.go Symbolic link
View File

@@ -0,0 +1 @@
repl_darwin.go

24
ethereum/repl_windows.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"bufio"
"fmt"
"os"
)
func (self *JSRepl) read() {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Printf(self.prompt)
str, _, err := reader.ReadLine()
if err != nil {
fmt.Println("Error reading input", err)
} else {
self.parseInput(string(str))
}
}
}
func (self *JSRepl) PrintValue(value otto.Value) {
fmt.Println(value)
}

69
utils/cmd.go Normal file
View File

@@ -0,0 +1,69 @@
package utils
import (
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethminer"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethrpc"
"github.com/ethereum/eth-go/ethutil"
"time"
)
func DoRpc(ethereum *eth.Ethereum, RpcPort int) {
var err error
ethereum.RpcServer, err = ethrpc.NewJsonRpcServer(ethpub.NewPEthereum(ethereum), RpcPort)
if err != nil {
ethutil.Config.Log.Infoln("Could not start RPC interface:", err)
} else {
go ethereum.RpcServer.Start()
}
}
var miner ethminer.Miner
func DoMining(ethereum *eth.Ethereum) {
// Set Mining status
ethereum.Mining = true
if ethutil.GetKeyRing().Len() == 0 {
ethutil.Config.Log.Infoln("No address found, can't start mining")
return
}
keyPair := ethutil.GetKeyRing().Get(0)
addr := keyPair.Address()
go func() {
ethutil.Config.Log.Infoln("Miner started")
miner = ethminer.NewDefaultMiner(addr, ethereum)
// Give it some time to connect with peers
time.Sleep(3 * time.Second)
miner.Start()
}()
}
func StopMining(ethereum *eth.Ethereum) bool {
if ethereum.Mining {
miner.Stop()
ethutil.Config.Log.Infoln("Miner stopped")
ethereum.Mining = false
return true
}
return false
}
func StartMining(ethereum *eth.Ethereum) bool {
if !ethereum.Mining {
DoMining(ethereum)
return true
}
return false
}

View File

@@ -6,6 +6,60 @@ import (
"github.com/obscuren/secp256k1-go" "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) { func CreateKeyPair(force bool) {
data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
if len(data) == 0 || force { if len(data) == 0 || force {
@@ -28,7 +82,9 @@ save these words so you can restore your account later: %s
} }
} }
*/
/*
func ImportPrivateKey(prvKey string) { func ImportPrivateKey(prvKey string) {
key := ethutil.FromHex(prvKey) key := ethutil.FromHex(prvKey)
msg := []byte("tmp") msg := []byte("tmp")
@@ -49,3 +105,4 @@ pubk: %x
`, pair.Address(), key, pub) `, pair.Address(), key, pub)
} }
*/