aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustav Simonsson <gustav.simonsson@gmail.com>2015-02-26 20:22:09 +0800
committerFelix Lange <fjl@twurst.com>2015-03-06 21:10:42 +0800
commitbc45e5c6de3052a4c853387dea0af5cd9207f1f7 (patch)
tree3230b89b3bf25eaf53e1b3b164cb72e89d8c4398
parente64f727529287b7414af6d1f482ea5f318cbd2eb (diff)
downloadgo-tangerine-bc45e5c6de3052a4c853387dea0af5cd9207f1f7.tar
go-tangerine-bc45e5c6de3052a4c853387dea0af5cd9207f1f7.tar.gz
go-tangerine-bc45e5c6de3052a4c853387dea0af5cd9207f1f7.tar.bz2
go-tangerine-bc45e5c6de3052a4c853387dea0af5cd9207f1f7.tar.lz
go-tangerine-bc45e5c6de3052a4c853387dea0af5cd9207f1f7.tar.xz
go-tangerine-bc45e5c6de3052a4c853387dea0af5cd9207f1f7.tar.zst
go-tangerine-bc45e5c6de3052a4c853387dea0af5cd9207f1f7.zip
Integrate eth_accounts and eth_transact to use new account manager
* Add from to eth_transact / xeth.Transact and add static pass in lieu of integrating with native Mist window for user passphrase entry * Make eth_accounts return AccountManager.Accounts() * Add a Generate Key menu item in Mist
-rw-r--r--cmd/mist/assets/qml/main.qml5
-rw-r--r--cmd/mist/bindings.go4
-rw-r--r--cmd/mist/gui.go7
-rw-r--r--cmd/mist/ui_lib.go1
-rw-r--r--core/types/transaction.go8
-rw-r--r--eth/backend.go41
-rw-r--r--javascript/types.go4
-rw-r--r--rpc/api.go30
-rw-r--r--rpc/args.go1
-rw-r--r--xeth/xeth.go40
10 files changed, 83 insertions, 58 deletions
diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml
index f9ee6939d..7f72d35f4 100644
--- a/cmd/mist/assets/qml/main.qml
+++ b/cmd/mist/assets/qml/main.qml
@@ -190,6 +190,11 @@ ApplicationWindow {
}
}
+ MenuItem {
+ text: "Generate key"
+ shortcut: "Ctrl+k"
+ onTriggered: gui.generateKey()
+ }
}
Menu {
diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go
index f21aa3135..fd89eb7e2 100644
--- a/cmd/mist/bindings.go
+++ b/cmd/mist/bindings.go
@@ -49,7 +49,7 @@ func (gui *Gui) LogPrint(level logger.LogLevel, msg string) {
}
*/
}
-func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, error) {
+func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
var data string
if len(recipient) == 0 {
code, err := ethutil.Compile(d, false)
@@ -61,7 +61,7 @@ func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, err
data = ethutil.Bytes2Hex(utils.FormatTransactionData(d))
}
- return gui.xeth.Transact(recipient, value, gas, gasPrice, data)
+ return gui.xeth.Transact(from, recipient, value, gas, gasPrice, data)
}
// functions that allow Gui to implement interface guilogger.LogSystem
diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go
index 869b689dd..bc6e9ed53 100644
--- a/cmd/mist/gui.go
+++ b/cmd/mist/gui.go
@@ -175,6 +175,13 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
func (gui *Gui) ImportKey(filePath string) {
}
+func (gui *Gui) GenerateKey() {
+ _, err := gui.eth.AccountManager().NewAccount("hurr")
+ if err != nil {
+ // TODO: UI feedback?
+ }
+}
+
func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
context.SetVar("lib", gui)
component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go
index 098e8fca5..af78f0c10 100644
--- a/cmd/mist/ui_lib.go
+++ b/cmd/mist/ui_lib.go
@@ -171,6 +171,7 @@ func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
object := mapToTxParams(params)
return self.XEth.Transact(
+ object["from"],
object["to"],
object["value"],
object["gas"],
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 7a1d6104e..7d34c86f4 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -129,6 +129,7 @@ func (tx *Transaction) sender() []byte {
return crypto.Sha3(pubkey[1:])[12:]
}
+// TODO: deprecate after new accounts & key stores are integrated
func (tx *Transaction) Sign(privk []byte) error {
sig := tx.Signature(privk)
@@ -140,6 +141,13 @@ func (tx *Transaction) Sign(privk []byte) error {
return nil
}
+func (tx *Transaction) SetSignatureValues(sig []byte) error {
+ tx.R = sig[:32]
+ tx.S = sig[32:64]
+ tx.V = uint64(sig[64] + 27)
+ return nil
+}
+
func (tx *Transaction) SignECDSA(key *ecdsa.PrivateKey) error {
return tx.Sign(crypto.FromECDSA(key))
}
diff --git a/eth/backend.go b/eth/backend.go
index 1c711a775..02e7e2746 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -8,6 +8,7 @@ import (
"strings"
"github.com/ethereum/ethash"
+ "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/blockpool"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
@@ -117,6 +118,7 @@ type Ethereum struct {
txPool *core.TxPool
chainManager *core.ChainManager
blockPool *blockpool.BlockPool
+ accountManager *accounts.AccountManager
whisper *whisper.Whisper
net *p2p.Server
@@ -176,9 +178,13 @@ func New(config *Config) (*Ethereum, error) {
DataDir: config.DataDir,
}
+ // TODO: add config flag and case on plain/protected key store
+ ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir())
+ am := accounts.NewAccountManager(ks, 300000) // keys unlocked for 300s
+ eth.accountManager = &am
+
eth.chainManager = core.NewChainManager(db, eth.EventMux())
pow := ethash.New(eth.chainManager)
-
eth.txPool = core.NewTxPool(eth.EventMux())
eth.blockProcessor = core.NewBlockProcessor(db, pow, eth.txPool, eth.chainManager, eth.EventMux())
eth.chainManager.SetProcessor(eth.blockProcessor)
@@ -215,22 +221,23 @@ func New(config *Config) (*Ethereum, error) {
return eth, nil
}
-func (s *Ethereum) KeyManager() *crypto.KeyManager { return s.keyManager }
-func (s *Ethereum) Logger() logger.LogSystem { return s.logger }
-func (s *Ethereum) Name() string { return s.net.Name }
-func (s *Ethereum) ChainManager() *core.ChainManager { return s.chainManager }
-func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcessor }
-func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
-func (s *Ethereum) BlockPool() *blockpool.BlockPool { return s.blockPool }
-func (s *Ethereum) Whisper() *whisper.Whisper { return s.whisper }
-func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
-func (s *Ethereum) Db() ethutil.Database { return s.db }
-func (s *Ethereum) Miner() *miner.Miner { return s.miner }
-func (s *Ethereum) IsListening() bool { return true } // Always listening
-func (s *Ethereum) PeerCount() int { return s.net.PeerCount() }
-func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() }
-func (s *Ethereum) MaxPeers() int { return s.net.MaxPeers }
-func (s *Ethereum) Coinbase() []byte { return nil } // TODO
+func (s *Ethereum) KeyManager() *crypto.KeyManager { return s.keyManager }
+func (s *Ethereum) Logger() logger.LogSystem { return s.logger }
+func (s *Ethereum) Name() string { return s.net.Name }
+func (s *Ethereum) AccountManager() *accounts.AccountManager { return s.accountManager }
+func (s *Ethereum) ChainManager() *core.ChainManager { return s.chainManager }
+func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcessor }
+func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
+func (s *Ethereum) BlockPool() *blockpool.BlockPool { return s.blockPool }
+func (s *Ethereum) Whisper() *whisper.Whisper { return s.whisper }
+func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
+func (s *Ethereum) Db() ethutil.Database { return s.db }
+func (s *Ethereum) Miner() *miner.Miner { return s.miner }
+func (s *Ethereum) IsListening() bool { return true } // Always listening
+func (s *Ethereum) PeerCount() int { return s.net.PeerCount() }
+func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() }
+func (s *Ethereum) MaxPeers() int { return s.net.MaxPeers }
+func (s *Ethereum) Coinbase() []byte { return nil } // TODO
// Start the ethereum
func (s *Ethereum) Start() error {
diff --git a/javascript/types.go b/javascript/types.go
index 77e209d19..e07267c8f 100644
--- a/javascript/types.go
+++ b/javascript/types.go
@@ -70,8 +70,8 @@ func (self *JSEthereum) GetStateObject(addr string) otto.Value {
return self.toVal(&JSStateObject{self.XEth.State().SafeGet(addr), self})
}
-func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
- r, err := self.XEth.Transact(recipient, valueStr, gasStr, gasPriceStr, dataStr)
+func (self *JSEthereum) Transact(fromStr, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
+ r, err := self.XEth.Transact(fromStr, recipient, valueStr, gasStr, gasPriceStr, dataStr)
if err != nil {
fmt.Println(err)
diff --git a/rpc/api.go b/rpc/api.go
index 28024c206..b622945eb 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -252,38 +252,18 @@ func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error {
}
func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
- if len(args.Gas) == 0 {
+ // TODO: align default values to have the same type, e.g. not depend on
+ // ethutil.Value conversions later on
+ if ethutil.Big(args.Gas).Cmp(big.NewInt(0)) == 0 {
args.Gas = defaultGas.String()
}
- if len(args.GasPrice) == 0 {
+ if ethutil.Big(args.GasPrice).Cmp(big.NewInt(0)) == 0 {
args.GasPrice = defaultGasPrice.String()
}
- // TODO if no_private_key then
- //if _, exists := p.register[args.From]; exists {
- // p.register[args.From] = append(p.register[args.From], args)
- //} else {
- /*
- account := accounts.Get(fromHex(args.From))
- if account != nil {
- if account.Unlocked() {
- if !unlockAccount(account) {
- return
- }
- }
-
- result, _ := account.Transact(fromHex(args.To), fromHex(args.Value), fromHex(args.Gas), fromHex(args.GasPrice), fromHex(args.Data))
- if len(result) > 0 {
- *reply = toHex(result)
- }
- } else if _, exists := p.register[args.From]; exists {
- p.register[ags.From] = append(p.register[args.From], args)
- }
- */
- result, _ := p.xeth().Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
+ result, _ := p.xeth().Transact(args.From, args.To, args.Value, args.Gas, args.GasPrice, args.Data)
*reply = result
- //}
return nil
}
diff --git a/rpc/args.go b/rpc/args.go
index ea8489585..ec3359a4a 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -24,6 +24,7 @@ func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) {
type NewTxArgs struct {
From string `json:"from"`
+ Pass string `json:"pass"`
To string `json:"to"`
Value string `json:"value"`
Gas string `json:"gas"`
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 677d40fd5..91bd35f8e 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -7,8 +7,8 @@ package xeth
import (
"bytes"
"encoding/json"
- "fmt"
+ "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@@ -27,6 +27,7 @@ var pipelogger = logger.NewLogger("XETH")
type Backend interface {
BlockProcessor() *core.BlockProcessor
ChainManager() *core.ChainManager
+ AccountManager() *accounts.AccountManager
TxPool() *core.TxPool
PeerCount() int
IsListening() bool
@@ -42,6 +43,7 @@ type XEth struct {
eth Backend
blockProcessor *core.BlockProcessor
chainManager *core.ChainManager
+ accountManager *accounts.AccountManager
state *State
whisper *Whisper
miner *miner.Miner
@@ -52,6 +54,7 @@ func New(eth Backend) *XEth {
eth: eth,
blockProcessor: eth.BlockProcessor(),
chainManager: eth.ChainManager(),
+ accountManager: eth.AccountManager(),
whisper: NewWhisper(eth.Whisper()),
miner: eth.Miner(),
}
@@ -106,7 +109,13 @@ func (self *XEth) Block(v interface{}) *Block {
}
func (self *XEth) Accounts() []string {
- return []string{toHex(self.eth.KeyManager().Address())}
+ // TODO: check err?
+ accounts, _ := self.eth.AccountManager().Accounts()
+ accountAddresses := make([]string, len(accounts))
+ for i, ac := range accounts {
+ accountAddresses[i] = toHex(ac.Address)
+ }
+ return accountAddresses
}
func (self *XEth) PeerCount() int {
@@ -266,17 +275,19 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
return toHex(res), nil
}
-func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
+func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
+
var (
+ from []byte
to []byte
value = ethutil.NewValue(valueStr)
gas = ethutil.NewValue(gasStr)
price = ethutil.NewValue(gasPriceStr)
data []byte
- key = self.eth.KeyManager().KeyPair()
contractCreation bool
)
+ from = fromHex(fromStr)
data = fromHex(codeStr)
to = fromHex(toStr)
if len(to) == 0 {
@@ -290,21 +301,26 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
tx = types.NewTransactionMessage(to, value.BigInt(), gas.BigInt(), price.BigInt(), data)
}
- var err error
- state := self.eth.ChainManager().TxState()
- if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 {
- return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value())
- }
- nonce := state.GetNonce(key.Address())
+ state := self.chainManager.TransState()
+ nonce := state.GetNonce(from)
tx.SetNonce(nonce)
- tx.Sign(key.PrivateKey)
+ sig, err := self.accountManager.Sign(&accounts.Account{Address: from}, tx.Hash())
+ if err != nil {
+ return "", err
+ }
+ tx.SetSignatureValues(sig)
err = self.eth.TxPool().Add(tx)
if err != nil {
return "", err
}
- state.SetNonce(key.Address(), nonce+1)
+ state.SetNonce(from, nonce+1)
+
+ if contractCreation {
+ addr := core.AddressFromMessage(tx)
+ pipelogger.Infof("Contract addr %x\n", addr)
+ }
if types.IsContractAddr(to) {
return toHex(core.AddressFromMessage(tx)), nil