Merge branch 'release/0.3.0' into develop

This commit is contained in:
obscuren 2014-02-28 12:20:59 +01:00
commit b72d3528bf
11 changed files with 154 additions and 138 deletions

View File

@ -3,44 +3,18 @@ Ethereum
[![Build Status](https://travis-ci.org/ethereum/go-ethereum.png?branch=master)](https://travis-ci.org/ethereum/go-ethereum) [![Build Status](https://travis-ci.org/ethereum/go-ethereum.png?branch=master)](https://travis-ci.org/ethereum/go-ethereum)
Ethereum Go developer client (c) Jeffrey Wilcke Ethereum Go Client (c) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof The current state is "Proof of Concept 3". For build instructions see
of Concept 2". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Edge). the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Edge).
Ethereum Go is split up in several sub packages Please refer to each For the development Go Package please see [eth-go package](https://github.com/ethereum/eth-go).
individual package for more information.
1. [eth](https://github.com/ethereum/eth-go)
2. [ethchain](https://github.com/ethereum/eth-go/ethchain)
3. [ethwire](https://github.com/ethereum/eth-go/ethwire)
4. [ethdb](https://github.com/ethereum/eth-go/ethdb)
5. [ethutil](https://github.com/ethereum/eth-go/ethutil)
The [eth](https://github.com/ethereum/eth-go) is the top-level package
of the Ethereum protocol. It functions as the Ethereum bootstrapping and
peer communication layer. The [ethchain](https://github.com/ethereum/ethchain-go)
contains the Ethereum blockchain, block manager, transaction and
transaction handlers. The [ethwire](https://github.com/ethereum/ethwire-go) contains
the Ethereum [wire protocol](http://wiki.ethereum.org/index.php/Wire_Protocol) which can be used
to hook in to the Ethereum network. [ethutil](https://github.com/ethereum/ethutil-go) contains
utility functions which are not Ethereum specific. The utility package
contains the [patricia trie](http://wiki.ethereum.org/index.php/Patricia_Tree),
[RLP Encoding](http://wiki.ethereum.org/index.php/RLP) and hex encoding
helpers. The [ethdb](https://github.com/ethereum/ethdb-go) package
contains the LevelDB interface and memory DB interface.
This executable is the front-end (currently nothing but a dev console) for
the Ethereum Go implementation.
If you'd like to start developing your own tools please check out the
[development](https://github.com/ethereum/eth-go) package.
Build Build
======= =======
For build instruction please see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Edge) For build instruction please see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Edge)
Command line options Command line options
==================== ====================
@ -52,6 +26,9 @@ Command line options
-upnp Enable UPnP (= false) -upnp Enable UPnP (= false)
-x Desired amount of peers (= 5) -x Desired amount of peers (= 5)
-h This help -h This help
-gui Launch with GUI (= true)
-dir Data directory used to store configs and databases (=".ethereum")
-import Import a private key (hex)
``` ```
Developer console commands Developer console commands

View File

@ -179,13 +179,13 @@ func (i *Console) ParseInput(input string) bool {
fmt.Println("recipient err:", err) fmt.Println("recipient err:", err)
} else { } else {
tx := ethchain.NewTransaction(recipient, ethutil.Big(tokens[2]), []string{""}) tx := ethchain.NewTransaction(recipient, ethutil.Big(tokens[2]), []string{""})
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
keyRing := ethutil.NewValueFromBytes(data)
tx.Sign(keyRing.Get(0).Bytes())
fmt.Printf("%x\n", tx.Hash())
i.ethereum.TxPool.QueueTransaction(tx)
}
key := ethutil.Config.Db.GetKeys()[0]
tx.Sign(key.PrivateKey)
i.ethereum.TxPool.QueueTransaction(tx)
fmt.Printf("%x\n", tx.Hash())
}
case "gettx": case "gettx":
addr, _ := hex.DecodeString(tokens[1]) addr, _ := hex.DecodeString(tokens[1])
data, _ := ethutil.Config.Db.Get(addr) data, _ := ethutil.Config.Db.Get(addr)
@ -200,9 +200,9 @@ func (i *Console) ParseInput(input string) bool {
code := ethchain.Compile(i.Editor()) code := ethchain.Compile(i.Editor())
contract := ethchain.NewTransaction(ethchain.ContractAddr, ethutil.Big(tokens[1]), code) contract := ethchain.NewTransaction(ethchain.ContractAddr, ethutil.Big(tokens[1]), code)
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
keyRing := ethutil.NewValueFromBytes(data) key := ethutil.Config.Db.GetKeys()[0]
contract.Sign(keyRing.Get(0).Bytes()) contract.Sign(key.PrivateKey)
i.ethereum.TxPool.QueueTransaction(contract) i.ethereum.TxPool.QueueTransaction(contract)

View File

@ -36,7 +36,8 @@ 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 {
pub, prv := secp256k1.GenerateKeyPair() pub, prv := secp256k1.GenerateKeyPair()
addr := ethutil.Sha3Bin(pub[1:])[12:] pair := &ethutil.Key{PrivateKey: prv, PublicKey: pub}
ethutil.Config.Db.Put([]byte("KeyRing"), pair.RlpEncode())
fmt.Printf(` fmt.Printf(`
Generating new address and keypair. Generating new address and keypair.
@ -48,10 +49,8 @@ prvk: %x
pubk: %x pubk: %x
++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++
`, addr, prv, pub) `, pair.Address(), prv, pub)
keyRing := ethutil.NewValue([]interface{}{prv, addr, pub[1:]})
ethutil.Config.Db.Put([]byte("KeyRing"), keyRing.Encode())
} }
} }
@ -61,7 +60,8 @@ func ImportPrivateKey(prvKey string) {
// Couldn't think of a better way to get the pub key // Couldn't think of a better way to get the pub key
sig, _ := secp256k1.Sign(msg, key) sig, _ := secp256k1.Sign(msg, key)
pub, _ := secp256k1.RecoverPubkey(msg, sig) pub, _ := secp256k1.RecoverPubkey(msg, sig)
addr := ethutil.Sha3Bin(pub[1:])[12:] pair := &ethutil.Key{PrivateKey: key, PublicKey: pub}
ethutil.Config.Db.Put([]byte("KeyRing"), pair.RlpEncode())
fmt.Printf(` fmt.Printf(`
Importing private key Importing private key
@ -72,10 +72,7 @@ prvk: %x
pubk: %x pubk: %x
++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++
`, addr, key, pub) `, pair.Address(), key, pub)
keyRing := ethutil.NewValue([]interface{}{key, addr, pub[1:]})
ethutil.Config.Db.Put([]byte("KeyRing"), keyRing.Encode())
} }
func main() { func main() {
@ -95,11 +92,11 @@ func main() {
// Instantiated a eth stack // Instantiated a eth stack
ethereum, err := eth.New(eth.CapDefault, UseUPnP) ethereum, err := eth.New(eth.CapDefault, UseUPnP)
ethereum.Port = OutboundPort
if err != nil { if err != nil {
log.Println("eth start err:", err) log.Println("eth start err:", err)
return return
} }
ethereum.Port = OutboundPort
if GenAddr { if GenAddr {
fmt.Println("This action overwrites your old private key. Are you sure? (y/n)") fmt.Println("This action overwrites your old private key. Are you sure? (y/n)")
@ -133,6 +130,7 @@ func main() {
if r == "y" { if r == "y" {
ImportPrivateKey(ImportKey) ImportPrivateKey(ImportKey)
os.Exit(0)
} }
} else { } else {
CreateKeyPair(false) CreateKeyPair(false)
@ -140,9 +138,8 @@ func main() {
} }
if ExportKey { if ExportKey {
data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) key := ethutil.Config.Db.GetKeys()[0]
keyRing := ethutil.NewValueFromBytes(data) fmt.Printf("%x\n", key.PrivateKey)
fmt.Printf("%x\n", keyRing.Get(0).Bytes())
os.Exit(0) os.Exit(0)
} }

BIN
net.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
net.pxm Normal file

Binary file not shown.

BIN
new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
tx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
tx.pxm Normal file

Binary file not shown.

View File

@ -9,6 +9,7 @@ import (
"github.com/ethereum/eth-go/ethdb" "github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/niemeyer/qml" "github.com/niemeyer/qml"
"math/big"
"strings" "strings"
) )
@ -62,9 +63,8 @@ func New(ethereum *eth.Ethereum) *Gui {
panic(err) panic(err)
} }
data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) key := ethutil.Config.Db.GetKeys()[0]
keyRing := ethutil.NewValueFromBytes(data) addr := key.Address()
addr := keyRing.Get(1).Bytes()
ethereum.BlockManager.WatchAddr(addr) ethereum.BlockManager.WatchAddr(addr)
@ -127,7 +127,7 @@ func (ui *Gui) setInitialBlockChain() {
} }
func (ui *Gui) readPreviousTransactions() { func (ui *Gui) readPreviousTransactions() {
it := ui.txDb.Db().NewIterator(nil) it := ui.txDb.Db().NewIterator(nil, nil)
for it.Next() { for it.Next() {
tx := ethchain.NewTransactionFromBytes(it.Value()) tx := ethchain.NewTransactionFromBytes(it.Value())
@ -140,45 +140,50 @@ func (ui *Gui) ProcessBlock(block *ethchain.Block) {
ui.win.Root().Call("addBlock", NewBlockFromBlock(block)) ui.win.Root().Call("addBlock", NewBlockFromBlock(block))
} }
func (ui *Gui) ProcessTransaction(tx *ethchain.Transaction) {
ui.txDb.Put(tx.Hash(), tx.RlpEncode())
ui.win.Root().Call("addTx", NewTxFromTransaction(tx))
// TODO replace with general subscribe model
}
// 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 (ui *Gui) update() { func (ui *Gui) update() {
txChan := make(chan ethchain.TxMsg) txChan := make(chan ethchain.TxMsg, 1)
ui.eth.TxPool.Subscribe(txChan) ui.eth.TxPool.Subscribe(txChan)
account := ui.eth.BlockManager.GetAddrState(ui.addr).Account account := ui.eth.BlockManager.GetAddrState(ui.addr).Account
unconfirmedFunds := new(big.Int)
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(account.Amount))) ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(account.Amount)))
for { for {
select { select {
case txMsg := <-txChan: case txMsg := <-txChan:
tx := txMsg.Tx tx := txMsg.Tx
ui.txDb.Put(tx.Hash(), tx.RlpEncode())
ui.win.Root().Call("addTx", NewTxFromTransaction(tx))
// TODO FOR THE LOVE OF EVERYTHING GOOD IN THIS WORLD REFACTOR ME
if txMsg.Type == ethchain.TxPre { if txMsg.Type == ethchain.TxPre {
if bytes.Compare(tx.Sender(), ui.addr) == 0 { if bytes.Compare(tx.Sender(), ui.addr) == 0 {
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v (- %v)", ethutil.CurrencyToString(account.Amount), ethutil.CurrencyToString(tx.Value))) ui.win.Root().Call("addTx", NewTxFromTransaction(tx))
ui.txDb.Put(tx.Hash(), tx.RlpEncode())
ui.eth.BlockManager.GetAddrState(ui.addr).Nonce += 1 ui.eth.BlockManager.GetAddrState(ui.addr).Nonce += 1
fmt.Println("Nonce", ui.eth.BlockManager.GetAddrState(ui.addr).Nonce) unconfirmedFunds.Sub(unconfirmedFunds, tx.Value)
} else if bytes.Compare(tx.Recipient, ui.addr) == 0 { } else if bytes.Compare(tx.Recipient, ui.addr) == 0 {
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v (+ %v)", ethutil.CurrencyToString(account.Amount), ethutil.CurrencyToString(tx.Value))) ui.win.Root().Call("addTx", NewTxFromTransaction(tx))
ui.txDb.Put(tx.Hash(), tx.RlpEncode())
unconfirmedFunds.Add(unconfirmedFunds, tx.Value)
} }
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(account.Amount), pos, val)
ui.win.Root().Call("setWalletValue", str)
} else { } else {
amount := account.Amount
if bytes.Compare(tx.Sender(), ui.addr) == 0 { if bytes.Compare(tx.Sender(), ui.addr) == 0 {
amount := account.Amount.Sub(account.Amount, tx.Value) amount.Sub(account.Amount, tx.Value)
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(amount)))
} else if bytes.Compare(tx.Recipient, ui.addr) == 0 { } else if bytes.Compare(tx.Recipient, ui.addr) == 0 {
amount := account.Amount.Sub(account.Amount, tx.Value) amount.Add(account.Amount, tx.Value)
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(amount)))
} }
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(amount)))
} }
} }

View File

@ -27,9 +27,11 @@ func (ui *UiLib) Open(path string) {
}() }()
} }
func (ui *UiLib) Connect() { func (ui *UiLib) Connect(button qml.Object) {
if !ui.connected { if !ui.connected {
ui.eth.Start() ui.eth.Start()
ui.connected = true
button.Set("enabled", false)
} }
} }

View File

@ -15,35 +15,6 @@ ApplicationWindow {
title: "Ethereal" title: "Ethereal"
toolBar: ToolBar {
id: mainToolbar
RowLayout {
width: parent.width
Button {
text: "Send"
onClicked: {
console.log(eth.createTx(txReceiver.text, txAmount.text, codeView.text))
}
}
TextField {
id: txAmount
width: 200
placeholderText: "Amount"
}
TextField {
id: txReceiver
width: 300
placeholderText: "Receiver Address (or empty for contract)"
Layout.fillWidth: true
}
}
}
MenuBar { MenuBar {
Menu { Menu {
title: "File" title: "File"
@ -86,35 +57,61 @@ ApplicationWindow {
property var blockModel: ListModel { property var blockModel: ListModel {
id: blockModel id: blockModel
} }
function setView(view) {
mainView.visible = false function setView(view) {
transactionView.visible = false networkView.visible = false
view.visible = true historyView.visible = false
} newTxView.visible = false
view.visible = true
//root.title = "Ethereal - " = view.title
}
SplitView { SplitView {
anchors.fill: parent anchors.fill: parent
resizing: false
Rectangle { Rectangle {
id: menu id: menu
width: 200 Layout.minimumWidth: 80
Layout.maximumWidth: 80
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: parent.top anchors.top: parent.top
color: "#D9DDE7" //color: "#D9DDE7"
color: "#252525"
GridLayout { ColumnLayout {
columns: 1 y: 50
Button { anchors.left: parent.left
text: "Main" anchors.right: parent.right
onClicked: { height: 200
setView(mainView) Image {
source: "tx.png"
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
anchors.fill: parent
onClicked: {
setView(historyView)
}
} }
} }
Button { Image {
text: "Transactions" source: "new.png"
onClicked: { anchors.horizontalCenter: parent.horizontalCenter
setView(transactionView) MouseArea {
anchors.fill: parent
onClicked: {
setView(newTxView)
}
}
}
Image {
source: "net.png"
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
anchors.fill: parent
onClicked: {
setView(networkView)
}
} }
} }
} }
@ -126,8 +123,8 @@ ApplicationWindow {
} }
Rectangle { Rectangle {
id: transactionView id: historyView
visible: false property var title: "Transactions"
anchors.right: parent.right anchors.right: parent.right
anchors.left: menu.right anchors.left: menu.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -135,40 +132,73 @@ ApplicationWindow {
TableView { TableView {
id: txTableView id: txTableView
anchors.fill: parent anchors.fill: parent
TableViewColumn{ role: "hash" ; title: "#" ; width: 150 }
TableViewColumn{ role: "value" ; title: "Value" ; width: 100 } TableViewColumn{ role: "value" ; title: "Value" ; width: 100 }
TableViewColumn{ role: "address" ; title: "Address" ; } TableViewColumn{ role: "address" ; title: "Address" ; width: 430 }
model: txModel model: txModel
} }
} }
Rectangle { Rectangle {
id: mainView id: newTxView
property var title: "New transaction"
visible: false
anchors.right: parent.right anchors.right: parent.right
anchors.left: menu.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: parent.top anchors.top: parent.top
SplitView { color: "#00000000"
id: splitView
height: 200
anchors.top: parent.top
anchors.right: parent.right
anchors.left: parent.left
ColumnLayout {
width: 400
anchors.left: parent.left
anchors.top: parent.top
anchors.leftMargin: 5
anchors.topMargin: 5
TextField {
id: txAmount
width: 200
placeholderText: "Amount"
}
TextField {
id: txReceiver
placeholderText: "Receiver Address (or empty for contract)"
Layout.fillWidth: true
}
Label {
text: "Transaction data"
}
TextArea { TextArea {
id: codeView id: codeView
anchors.topMargin: 5
Layout.fillWidth: true
width: parent.width /2 width: parent.width /2
} }
TextArea { Button {
readOnly: true text: "Send"
onClicked: {
console.log(eth.createTx(txReceiver.text, txAmount.text, codeView.text))
}
} }
} }
}
Rectangle {
id: networkView
property var title: "Network"
visible: false
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
TableView { TableView {
id: blockTable id: blockTable
width: parent.width width: parent.width
anchors.top: splitView.bottom anchors.top: parent.top
anchors.bottom: logView.top anchors.bottom: logView.top
TableViewColumn{ role: "number" ; title: "#" ; width: 100 } TableViewColumn{ role: "number" ; title: "#" ; width: 100 }
TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 } TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 }
@ -210,8 +240,13 @@ ApplicationWindow {
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
Button { Button {
property var enabled: true
id: connectButton id: connectButton
onClicked: ui.connect() onClicked: {
if(this.enabled) {
ui.connect(this)
}
}
text: "Connect" text: "Connect"
} }
Button { Button {