diff --git a/accounts/account_manager.go b/accounts/account_manager.go index 3e9fa77991..3b77852318 100644 --- a/accounts/account_manager.go +++ b/accounts/account_manager.go @@ -42,7 +42,10 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -var ErrLocked = errors.New("account is locked; please request passphrase") +var ( + ErrLocked = errors.New("account is locked") + ErrNoKeys = errors.New("no keys in store") +) // TODO: better name for this struct? type Account struct { @@ -56,17 +59,39 @@ type AccountManager struct { mutex sync.RWMutex } -func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) AccountManager { - keysMap := make(map[string]crypto.Key) - am := &AccountManager{ +func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) *AccountManager { + return &AccountManager{ keyStore: keyStore, - unlockedKeys: keysMap, + unlockedKeys: make(map[string]crypto.Key), unlockMilliseconds: unlockMilliseconds, } - return *am } -func (am AccountManager) DeleteAccount(address []byte, auth string) error { +// Coinbase returns the account address that mining rewards are sent to. +func (am *AccountManager) Coinbase() (addr []byte, err error) { + // TODO: persist coinbase address on disk + return am.firstAddr() +} + +// MainAccount returns the primary account used for transactions. +func (am *AccountManager) Default() (*Account, error) { + // TODO: persist main account address on disk + addr, err := am.firstAddr() + return &Account{Address: addr}, err +} + +func (am *AccountManager) firstAddr() ([]byte, error) { + addrs, err := am.keyStore.GetKeyAddresses() + if err != nil { + return nil, err + } + if len(addrs) == 0 { + return nil, ErrNoKeys + } + return addrs[0], nil +} + +func (am *AccountManager) DeleteAccount(address []byte, auth string) error { return am.keyStore.DeleteKey(address, auth) } diff --git a/core/manager.go b/core/manager.go index bb039d063b..29f786653c 100644 --- a/core/manager.go +++ b/core/manager.go @@ -1,7 +1,6 @@ package core import ( - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/p2p" @@ -14,7 +13,6 @@ type Backend interface { PeerCount() int IsListening() bool Peers() []*p2p.Peer - KeyManager() *crypto.KeyManager Db() ethutil.Database EventMux() *event.TypeMux } diff --git a/eth/backend.go b/eth/backend.go index 02e7e2746d..cc5284dfa3 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -38,11 +38,9 @@ var ( type Config struct { Name string - KeyStore string DataDir string LogFile string LogLevel int - KeyRing string LogFormat string MaxPeers int @@ -60,9 +58,8 @@ type Config struct { Shh bool Dial bool - MinerThreads int - - KeyManager *crypto.KeyManager + MinerThreads int + AccountManager *accounts.AccountManager } func (cfg *Config) parseBootNodes() []*discover.Node { @@ -127,8 +124,7 @@ type Ethereum struct { blockSub event.Subscription miner *miner.Miner - RpcServer rpc.RpcServer - keyManager *crypto.KeyManager + RpcServer rpc.RpcServer logger logger.LogSystem @@ -153,35 +149,22 @@ func New(config *Config) (*Ethereum, error) { return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, path) } - // Create new keymanager - var keyManager *crypto.KeyManager - switch config.KeyStore { - case "db": - keyManager = crypto.NewDBKeyManager(db) - case "file": - keyManager = crypto.NewFileKeyManager(config.DataDir) - default: - return nil, fmt.Errorf("unknown keystore type: %s", config.KeyStore) - } - // Initialise the keyring - keyManager.Init(config.KeyRing, 0, false) - saveProtocolVersion(db) //ethutil.Config.Db = db eth := &Ethereum{ - shutdownChan: make(chan bool), - db: db, - keyManager: keyManager, - eventMux: &event.TypeMux{}, - logger: ethlogger, - DataDir: config.DataDir, + shutdownChan: make(chan bool), + db: db, + eventMux: &event.TypeMux{}, + logger: ethlogger, + accountManager: config.AccountManager, + 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 + cb, err := eth.accountManager.Coinbase() + if err != nil { + return nil, fmt.Errorf("no coinbase: %v", err) + } eth.chainManager = core.NewChainManager(db, eth.EventMux()) pow := ethash.New(eth.chainManager) @@ -189,7 +172,7 @@ func New(config *Config) (*Ethereum, error) { eth.blockProcessor = core.NewBlockProcessor(db, pow, eth.txPool, eth.chainManager, eth.EventMux()) eth.chainManager.SetProcessor(eth.blockProcessor) eth.whisper = whisper.New() - eth.miner = miner.New(keyManager.Address(), eth, pow, config.MinerThreads) + eth.miner = miner.New(cb, eth, pow, config.MinerThreads) hasBlock := eth.chainManager.HasBlock insertChain := eth.chainManager.InsertChain @@ -221,7 +204,6 @@ 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) AccountManager() *accounts.AccountManager { return s.accountManager } @@ -237,7 +219,6 @@ func (s *Ethereum) IsListening() bool { return true } // 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/xeth/xeth.go b/xeth/xeth.go index 91bd35f8e7..1ad62a7bf6 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -32,7 +32,6 @@ type Backend interface { PeerCount() int IsListening() bool Peers() []*p2p.Peer - KeyManager() *crypto.KeyManager Db() ethutil.Database EventMux() *event.TypeMux Whisper() *whisper.Whisper @@ -142,7 +141,8 @@ func (self *XEth) IsListening() bool { } func (self *XEth) Coinbase() string { - return toHex(self.eth.KeyManager().Address()) + cb, _ := self.eth.AccountManager().Coinbase() + return toHex(cb) } func (self *XEth) NumberToHuman(balance string) string { @@ -251,10 +251,13 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st gasPriceStr = "1" } + acct, err := self.accountManager.Default() + if err != nil { + return "", err + } var ( statedb = self.State().State() //self.chainManager.TransState() - key = self.eth.KeyManager().KeyPair() - from = statedb.GetOrNewStateObject(key.Address()) + from = statedb.GetOrNewStateObject(acct.Address) block = self.chainManager.CurrentBlock() to = statedb.GetOrNewStateObject(fromHex(toStr)) data = fromHex(dataStr) @@ -264,9 +267,12 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st ) msg := types.NewTransactionMessage(fromHex(toStr), value, gas, price, data) - msg.Sign(key.PrivateKey) + sig, err := self.accountManager.Sign(acct, msg.Hash()) + if err != nil { + return "", err + } + msg.SetSignatureValues(sig) vmenv := core.NewEnv(statedb, self.chainManager, msg, block) - res, err := vmenv.Call(from, to.Address(), data, gas, price, value) if err != nil { return "", err