Merge pull request #96 from ethersphere/feature/keys

Feature/keys
This commit is contained in:
Jeffrey Wilcke 2014-07-01 16:15:59 +02:00
commit 5e02d2b586
15 changed files with 152 additions and 266 deletions

View File

@ -13,6 +13,8 @@ import (
) )
var Identifier string var Identifier string
var KeyRing string
var KeyStore string
var StartRpc bool var StartRpc bool
var RpcPort int var RpcPort int
var UseUPnP bool var UseUPnP bool
@ -22,8 +24,8 @@ var AddPeer string
var MaxPeer int var MaxPeer int
var GenAddr bool var GenAddr bool
var UseSeed bool var UseSeed bool
var ImportKey string var SecretFile string
var ExportKey bool var ExportDir string
var NonInteractive bool var NonInteractive bool
var Datadir string var Datadir string
var LogFile string var LogFile string
@ -73,6 +75,8 @@ func Init() {
} }
flag.StringVar(&Identifier, "id", "", "Custom client identifier") 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.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support") flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers") 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(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
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.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(&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(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")

View File

@ -10,7 +10,7 @@ import (
) )
func main() { func main() {
// Leave QT on top at ALL times. // Leave QT on top at ALL times. Qt Needs to be initialized from the main thread
qml.Init(nil) qml.Init(nil)
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
@ -30,10 +30,14 @@ func main() {
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile) 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 // create, import, export keys
utils.KeyTasks(GenAddr, ImportKey, ExportKey, NonInteractive) utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
ethereum := utils.NewEthereum(db, keyManager, UseUPnP, OutboundPort, MaxPeer)
if ShowGenesis { if ShowGenesis {
utils.ShowGenesis(ethereum) utils.ShowGenesis(ethereum)
@ -43,7 +47,7 @@ func main() {
utils.StartRpc(ethereum, RpcPort) utils.StartRpc(ethereum, RpcPort)
} }
gui := ethui.New(ethereum, LogLevel) gui := ethui.New(ethereum, KeyRing, LogLevel)
utils.RegisterInterrupt(func(os.Signal) { utils.RegisterInterrupt(func(os.Signal) {
gui.Stop() gui.Stop()

View File

@ -49,7 +49,7 @@ func (self *DebuggerWindow) SetData(data string) {
self.win.Set("dataText", data) self.win.Set("dataText", data)
} }
func (self *DebuggerWindow) SetAsm(data string) { func (self *DebuggerWindow) SetAsm(data string) {
dis := ethchain.Disassemble(ethutil.FromHex(data)) dis := ethchain.Disassemble(ethutil.Hex2Bytes(data))
for _, str := range dis { for _, str := range dis {
self.win.Root().Call("setAsm", str) self.win.Root().Call("setAsm", str)
} }
@ -101,7 +101,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
gasPrice = ethutil.Big(gasPriceStr) gasPrice = ethutil.Big(gasPriceStr)
value = ethutil.Big(valueStr) value = ethutil.Big(valueStr)
// Contract addr as test address // Contract addr as test address
keyPair = ethutil.GetKeyRing().Get(0) keyPair = self.lib.eth.KeyManager().KeyPair()
callerTx = ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, script) callerTx = ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, script)
) )
callerTx.Sign(keyPair.PrivateKey) callerTx.Sign(keyPair.PrivateKey)

View File

@ -121,10 +121,10 @@ out:
func (app *ExtApplication) Watch(addr, storageAddr string) { func (app *ExtApplication) Watch(addr, storageAddr string) {
var event string var event string
if len(storageAddr) == 0 { if len(storageAddr) == 0 {
event = "object:" + string(ethutil.FromHex(addr)) event = "object:" + string(ethutil.Hex2Bytes(addr))
app.lib.eth.Reactor().Subscribe(event, app.changeChan) app.lib.eth.Reactor().Subscribe(event, app.changeChan)
} else { } 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) app.lib.eth.Reactor().Subscribe(event, app.changeChan)
} }

View File

@ -28,36 +28,28 @@ type Gui struct {
eth *eth.Ethereum eth *eth.Ethereum
// The public Ethereum library // The public Ethereum library
lib *EthLib
uiLib *UiLib uiLib *UiLib
txDb *ethdb.LDBDatabase txDb *ethdb.LDBDatabase
addr []byte
pub *ethpub.PEthereum pub *ethpub.PEthereum
logLevel ethlog.LogLevel logLevel ethlog.LogLevel
open bool open bool
Session string
} }
// Create GUI, but doesn't start it // Create GUI, but doesn't start it
func New(ethereum *eth.Ethereum, logLevel int) *Gui { func New(ethereum *eth.Ethereum, session string, logLevel int) *Gui {
lib := &EthLib{stateManager: ethereum.StateManager(), blockChain: ethereum.BlockChain(), txPool: ethereum.TxPool()}
db, err := ethdb.NewLDBDatabase("tx_database") db, err := ethdb.NewLDBDatabase("tx_database")
if err != nil { if err != nil {
panic(err) 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) 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}
} }
func (gui *Gui) Start(assetPath string) { func (gui *Gui) Start(assetPath string) {
@ -158,12 +150,11 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
} }
func (gui *Gui) showKeyImport(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")) component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return gui.createWindow(component), nil return gui.createWindow(component), nil
} }
@ -175,15 +166,36 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
return gui.win 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() { func (gui *Gui) setInitialBlockChain() {
sBlk := gui.eth.BlockChain().LastBlockHash sBlk := gui.eth.BlockChain().LastBlockHash
blk := gui.eth.BlockChain().GetBlock(sBlk) blk := gui.eth.BlockChain().GetBlock(sBlk)
for ; blk != nil; blk = gui.eth.BlockChain().GetBlock(sBlk) { for ; blk != nil; blk = gui.eth.BlockChain().GetBlock(sBlk) {
sBlk = blk.PrevHash sBlk = blk.PrevHash
addr := gui.address()
// Loop through all transactions to see if we missed any while being offline // Loop through all transactions to see if we missed any while being offline
for _, tx := range blk.Transactions() { 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 { if ok, _ := gui.txDb.Get(tx.Hash()); ok == nil {
gui.txDb.Put(tx.Hash(), tx.RlpEncode()) gui.txDb.Put(tx.Hash(), tx.RlpEncode())
} }
@ -199,25 +211,26 @@ type address struct {
Name, Address string Name, Address string
} }
var namereg = ethutil.FromHex("bb5f186604d057c1c5240ca2ae0f6430138ac010") var namereg = ethutil.Hex2Bytes("bb5f186604d057c1c5240ca2ae0f6430138ac010")
func (gui *Gui) loadAddressBook() { func (gui *Gui) loadAddressBook() {
gui.win.Root().Call("clearAddress") gui.win.Root().Call("clearAddress")
stateObject := gui.eth.StateManager().CurrentState().GetStateObject(namereg) stateObject := gui.eth.StateManager().CurrentState().GetStateObject(namereg)
if stateObject != nil { if stateObject != nil {
stateObject.State().EachStorage(func(name string, value *ethutil.Value) { stateObject.State().EachStorage(func(name string, value *ethutil.Value) {
gui.win.Root().Call("addAddress", struct{ Name, Address string }{name, ethutil.Hex(value.Bytes())}) gui.win.Root().Call("addAddress", struct{ Name, Address string }{name, ethutil.Bytes2Hex(value.Bytes())})
}) })
} }
} }
func (gui *Gui) readPreviousTransactions() { func (gui *Gui) readPreviousTransactions() {
it := gui.txDb.Db().NewIterator(nil, nil) it := gui.txDb.Db().NewIterator(nil, nil)
addr := gui.address()
for it.Next() { for it.Next() {
tx := ethchain.NewTransactionFromBytes(it.Value()) tx := ethchain.NewTransactionFromBytes(it.Value())
var inout string var inout string
if bytes.Compare(tx.Sender(), gui.addr) == 0 { if bytes.Compare(tx.Sender(), addr) == 0 {
inout = "send" inout = "send"
} else { } else {
inout = "recv" inout = "recv"
@ -269,29 +282,29 @@ func (gui *Gui) update() {
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.GetAccount(gui.addr).Amount))) gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Amount)))
for { for {
select { select {
case b := <-blockChan: case b := <-blockChan:
block := b.Resource.(*ethchain.Block) block := b.Resource.(*ethchain.Block)
gui.processBlock(block, false) gui.processBlock(block, false)
if bytes.Compare(block.Coinbase, gui.addr) == 0 { if bytes.Compare(block.Coinbase, gui.address()) == 0 {
gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.addr).Amount, nil) gui.setWalletValue(gui.eth.StateManager().CurrentState().GetAccount(gui.address()).Amount, nil)
} }
case txMsg := <-txChan: case txMsg := <-txChan:
tx := txMsg.Resource.(*ethchain.Transaction) tx := txMsg.Resource.(*ethchain.Transaction)
if txMsg.Event == "newTx:pre" { 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.win.Root().Call("addTx", ethpub.NewPTx(tx), "send")
gui.txDb.Put(tx.Hash(), tx.RlpEncode()) gui.txDb.Put(tx.Hash(), tx.RlpEncode())
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.address()) == 0 {
gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "recv") gui.win.Root().Call("addTx", ethpub.NewPTx(tx), "recv")
gui.txDb.Put(tx.Hash(), tx.RlpEncode()) gui.txDb.Put(tx.Hash(), tx.RlpEncode())
@ -300,10 +313,10 @@ func (gui *Gui) update() {
gui.setWalletValue(object.Amount, unconfirmedFunds) gui.setWalletValue(object.Amount, unconfirmedFunds)
} else { } else {
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 {
object.SubAmount(tx.Value) 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) object.AddAmount(tx.Value)
} }
@ -330,22 +343,25 @@ 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) { func (gui *Gui) RegisterName(name string) {
keyPair := ethutil.GetKeyRing().Get(0)
name = fmt.Sprintf("\"%s\"\n1", name) name = fmt.Sprintf("\"%s\"\n1", name)
gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), "namereg", "1000", "1000000", "150", name) gui.pub.Transact(gui.privateKey(), "namereg", "1000", "1000000", "150", name)
} }
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.GetKeyRing().Get(0) return gui.pub.Transact(gui.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.GetKeyRing().Get(0) return gui.pub.Transact(gui.privateKey(), recipient, value, gas, gasPrice, data)
return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data)
} }
func (gui *Gui) ChangeClientId(id string) { func (gui *Gui) ChangeClientId(id string) {

View File

@ -116,7 +116,7 @@ func (app *HtmlApplication) Window() *qml.Window {
} }
func (app *HtmlApplication) NewBlock(block *ethchain.Block) { 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) app.webView.Call("onNewBlockCb", b)
} }

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

@ -38,7 +38,7 @@ func (app *QmlApplication) NewWatcher(quitChan chan bool) {
// Events // Events
func (app *QmlApplication) NewBlock(block *ethchain.Block) { 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) app.win.Call("onNewBlockCb", pblock)
} }

View File

@ -77,9 +77,9 @@ func (ui *UiLib) AssetPath(p string) string {
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) { func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
dbWindow := NewDebuggerWindow(self) dbWindow := NewDebuggerWindow(self)
object := self.eth.StateManager().CurrentState().GetStateObject(ethutil.FromHex(contractHash)) object := self.eth.StateManager().CurrentState().GetStateObject(ethutil.Hex2Bytes(contractHash))
if len(object.Script()) > 0 { if len(object.Script()) > 0 {
dbWindow.SetCode("0x" + ethutil.Hex(object.Script())) dbWindow.SetCode("0x" + ethutil.Bytes2Hex(object.Script()))
} }
dbWindow.SetData("0x" + data) dbWindow.SetData("0x" + data)

View File

@ -10,6 +10,8 @@ import (
) )
var Identifier string var Identifier string
var KeyRing string
var KeyStore string
var StartRpc bool var StartRpc bool
var RpcPort int var RpcPort int
var UseUPnP bool var UseUPnP bool
@ -19,8 +21,8 @@ var AddPeer string
var MaxPeer int var MaxPeer int
var GenAddr bool var GenAddr bool
var UseSeed bool var UseSeed bool
var ImportKey string var SecretFile string
var ExportKey bool var ExportDir string
var NonInteractive bool var NonInteractive bool
var Datadir string var Datadir string
var LogFile string var LogFile string
@ -47,6 +49,8 @@ func Init() {
} }
flag.StringVar(&Identifier, "id", "", "Custom client identifier") 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.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support") flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers") flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
@ -55,9 +59,9 @@ func Init() {
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(&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.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(&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(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")

View File

@ -122,12 +122,12 @@ out:
} }
case object := <-self.changeChan: case object := <-self.changeChan:
if stateObject, ok := object.Resource.(*ethchain.StateObject); ok { if stateObject, ok := object.Resource.(*ethchain.StateObject); ok {
for _, cb := range self.objectCb[ethutil.Hex(stateObject.Address())] { for _, cb := range self.objectCb[ethutil.Bytes2Hex(stateObject.Address())] {
val, _ := self.vm.ToValue(ethpub.NewPStateObject(stateObject)) val, _ := self.vm.ToValue(ethpub.NewPStateObject(stateObject))
cb.Call(cb, val) cb.Call(cb, val)
} }
} else if storageObject, ok := object.Resource.(*ethchain.StorageState); ok { } else if storageObject, ok := object.Resource.(*ethchain.StorageState); ok {
for _, cb := range self.objectCb[ethutil.Hex(storageObject.StateAddress)+ethutil.Hex(storageObject.Address)] { for _, cb := range self.objectCb[ethutil.Bytes2Hex(storageObject.StateAddress)+ethutil.Bytes2Hex(storageObject.Address)] {
val, _ := self.vm.ToValue(ethpub.NewPStorageState(storageObject)) val, _ := self.vm.ToValue(ethpub.NewPStorageState(storageObject))
cb.Call(cb, val) cb.Call(cb, val)
} }
@ -178,12 +178,12 @@ func (self *JSRE) watch(call otto.FunctionCall) otto.Value {
if storageCallback { if storageCallback {
self.objectCb[addr+storageAddr] = append(self.objectCb[addr+storageAddr], cb) 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) self.ethereum.Reactor().Subscribe(event, self.changeChan)
} else { } else {
self.objectCb[addr] = append(self.objectCb[addr], cb) self.objectCb[addr] = append(self.objectCb[addr], cb)
event := "object:" + string(ethutil.FromHex(addr)) event := "object:" + string(ethutil.Hex2Bytes(addr))
self.ethereum.Reactor().Subscribe(event, self.changeChan) self.ethereum.Reactor().Subscribe(event, self.changeChan)
} }
@ -221,7 +221,7 @@ func (self *JSRE) execBlock(call otto.FunctionCall) otto.Value {
return otto.UndefinedValue() return otto.UndefinedValue()
} }
err = utils.BlockDo(self.ethereum, ethutil.FromHex(hash)) err = utils.BlockDo(self.ethereum, ethutil.Hex2Bytes(hash))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return otto.FalseValue() return otto.FalseValue()

View File

@ -21,10 +21,14 @@ func main() {
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile) 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 // create, import, export keys
utils.KeyTasks(GenAddr, ImportKey, ExportKey, NonInteractive) utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
ethereum := utils.NewEthereum(db, keyManager, UseUPnP, OutboundPort, MaxPeer)
if ShowGenesis { if ShowGenesis {
utils.ShowGenesis(ethereum) utils.ShowGenesis(ethereum)

View File

@ -27,7 +27,7 @@ if [ $? != 0 ]; then
fi fi
echo "serpent-go" echo "serpent-go"
cd $GOPATH/src/github.com/obscuren/mutan cd $GOPATH/src/github.com/obscuren/serpent-go
echo "init submodule" echo "init submodule"
git submodule init git submodule init
@ -49,5 +49,9 @@ else
fi fi
go install go install
if [ $? == 0 ]; then
echo "go install failed"
exit
fi
echo "done. Please run $exe :-)" echo "done. Please run $exe :-)"

View File

@ -3,6 +3,8 @@ package utils
import ( import (
"fmt" "fmt"
"github.com/ethereum/eth-go" "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/ethlog"
"github.com/ethereum/eth-go/ethminer" "github.com/ethereum/eth-go/ethminer"
"github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethpub"
@ -13,7 +15,6 @@ import (
"os" "os"
"os/signal" "os/signal"
"path" "path"
"strings"
"time" "time"
) )
@ -77,7 +78,7 @@ func InitDataDir(Datadir string) {
_, err := os.Stat(Datadir) _, err := os.Stat(Datadir)
if err != nil { if err != nil {
if os.IsNotExist(err) { 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) os.Mkdir(Datadir, 0777)
} }
} }
@ -100,16 +101,28 @@ 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, Identifier string, EnvPrefix string) {
InitDataDir(Datadir) InitDataDir(Datadir)
ethutil.ReadConfig(ConfigFile, Datadir, Identifier, EnvPrefix) ethutil.ReadConfig(ConfigFile, Datadir, Identifier, EnvPrefix)
ethutil.Config.Set("rpcport", "700")
} }
func exit(status int) { func exit(err error) {
status := 0
if err != nil {
logger.Errorln("Fatal: ", err)
status = 1
}
ethlog.Flush() ethlog.Flush()
os.Exit(status) os.Exit(status)
} }
func NewEthereum(UseUPnP bool, OutboundPort string, MaxPeer int) *eth.Ethereum { func NewDatabase() ethutil.Database {
ethereum, err := eth.New(eth.CapDefault, UseUPnP) db, err := ethdb.NewLDBDatabase("database")
if err != nil {
exit(err)
}
return db
}
func NewEthereum(db ethutil.Database, keyManager *ethcrypto.KeyManager, usePnp bool, OutboundPort string, MaxPeer int) *eth.Ethereum {
ethereum, err := eth.New(db, keyManager, eth.CapDefault, usePnp)
if err != nil { if err != nil {
logger.Fatalln("eth start err:", err) logger.Fatalln("eth start err:", err)
} }
@ -129,50 +142,47 @@ func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
func ShowGenesis(ethereum *eth.Ethereum) { func ShowGenesis(ethereum *eth.Ethereum) {
logger.Infoln(ethereum.BlockChain().Genesis()) 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 KeyTasks(keyManager *ethcrypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
var err error
switch { switch {
case GenAddr: case GenAddr:
if NonInteractive || confirm("This action overwrites your old private key.") { if NonInteractive || confirm("This action overwrites your old private key.") {
CreateKeyPair(true) err = keyManager.Init(KeyRing, 0, true)
} }
exit(0) exit(err)
case len(ImportKey) > 0: case len(SecretFile) > 0:
if NonInteractive || confirm("This action overwrites your old private key.") { if NonInteractive || confirm("This action overwrites your old private key.") {
// import should be from file err = keyManager.InitFromSecretsFile(KeyRing, 0, SecretFile)
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.")
}
} }
exit(0) exit(err)
case ExportKey: // this should be exporting to a filename case len(ExportDir) > 0:
keyPair := ethutil.GetKeyRing().Get(0) err = keyManager.Init(KeyRing, 0, false)
fmt.Printf(` if err == nil {
Generating new address and keypair. err = keyManager.Export(ExportDir)
Please keep your keys somewhere save. }
exit(err)
++++++++++++++++ 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)
default: default:
// Creates a keypair if none exists // Creates a keypair if none exists
CreateKeyPair(false) err = keyManager.Init(KeyRing, 0, false)
if err != nil {
exit(err)
}
} }
} }
@ -192,19 +202,13 @@ func StartMining(ethereum *eth.Ethereum) bool {
if !ethereum.Mining { if !ethereum.Mining {
ethereum.Mining = true ethereum.Mining = true
if ethutil.GetKeyRing().Len() == 0 { addr := ethereum.KeyManager().Address()
logger.Errorln("No address found, can't start mining")
ethereum.Mining = false
return true //????
}
keyPair := ethutil.GetKeyRing().Get(0)
addr := keyPair.Address()
go func() { go func() {
miner = ethminer.NewDefaultMiner(addr, ethereum) miner = ethminer.NewDefaultMiner(addr, ethereum)
// Give it some time to connect with peers // Give it some time to connect with peers
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)
for !ethereum.IsUpToDate() == false { for !ethereum.IsUpToDate() {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
} }

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)
}
*/