diff options
author | Jeffrey Wilcke <jeffrey@ethereum.org> | 2015-02-26 06:58:30 +0800 |
---|---|---|
committer | Jeffrey Wilcke <jeffrey@ethereum.org> | 2015-02-26 06:58:30 +0800 |
commit | 46ce66a82905185b2b42803d58f5d8f00431e03c (patch) | |
tree | 08abbf3ae369c78a51ba442e9b561ca68f137f73 /accounts/account_manager.go | |
parent | b155b9d80b1cb921c52c20e296f27039de3b069b (diff) | |
parent | 23f265809170fae044be12851f5591f55495003a (diff) | |
download | go-tangerine-46ce66a82905185b2b42803d58f5d8f00431e03c.tar go-tangerine-46ce66a82905185b2b42803d58f5d8f00431e03c.tar.gz go-tangerine-46ce66a82905185b2b42803d58f5d8f00431e03c.tar.bz2 go-tangerine-46ce66a82905185b2b42803d58f5d8f00431e03c.tar.lz go-tangerine-46ce66a82905185b2b42803d58f5d8f00431e03c.tar.xz go-tangerine-46ce66a82905185b2b42803d58f5d8f00431e03c.tar.zst go-tangerine-46ce66a82905185b2b42803d58f5d8f00431e03c.zip |
Merge pull request #385 from Gustav-Simonsson/account_manager_key_locking
Add automatic locking / unlocking of accounts
Diffstat (limited to 'accounts/account_manager.go')
-rw-r--r-- | accounts/account_manager.go | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/accounts/account_manager.go b/accounts/account_manager.go index f7a7506ba..90fed1343 100644 --- a/accounts/account_manager.go +++ b/accounts/account_manager.go @@ -34,24 +34,32 @@ package accounts import ( crand "crypto/rand" + "errors" "github.com/ethereum/go-ethereum/crypto" + "sync" + "time" ) +var ErrLocked = errors.New("account is locked; please request passphrase") + // TODO: better name for this struct? type Account struct { Address []byte } type AccountManager struct { - keyStore crypto.KeyStore2 + keyStore crypto.KeyStore2 + unlockedKeys map[string]crypto.Key + unlockMilliseconds time.Duration + mutex sync.RWMutex } -// TODO: get key by addr - modify KeyStore2 GetKey to work with addr - -// TODO: pass through passphrase for APIs which require access to private key? -func NewAccountManager(keyStore crypto.KeyStore2) AccountManager { +func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) AccountManager { + keysMap := make(map[string]crypto.Key) am := &AccountManager{ - keyStore: keyStore, + keyStore: keyStore, + unlockedKeys: keysMap, + unlockMilliseconds: unlockMilliseconds, } return *am } @@ -60,11 +68,26 @@ func (am AccountManager) DeleteAccount(address []byte, auth string) error { return am.keyStore.DeleteKey(address, auth) } -func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { +func (am *AccountManager) Sign(fromAccount *Account, toSign []byte) (signature []byte, err error) { + am.mutex.RLock() + unlockedKey := am.unlockedKeys[string(fromAccount.Address)] + am.mutex.RUnlock() + if unlockedKey.Address == nil { + return nil, ErrLocked + } + signature, err = crypto.Sign(toSign, unlockedKey.PrivateKey) + return signature, err +} + +func (am *AccountManager) SignLocked(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth) if err != nil { return nil, err } + am.mutex.RLock() + am.unlockedKeys[string(fromAccount.Address)] = *key + am.mutex.RUnlock() + go unlockLater(am, fromAccount.Address) signature, err = crypto.Sign(toSign, key.PrivateKey) return signature, err } @@ -80,8 +103,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) { return ua, err } -// set of accounts == set of keys in given key store -// TODO: do we need persistence of accounts as well? func (am *AccountManager) Accounts() ([]Account, error) { addresses, err := am.keyStore.GetKeyAddresses() if err != nil { @@ -97,3 +118,13 @@ func (am *AccountManager) Accounts() ([]Account, error) { } return accounts, err } + +func unlockLater(am *AccountManager, addr []byte) { + select { + case <-time.After(time.Millisecond * am.unlockMilliseconds): + } + am.mutex.RLock() + // TODO: how do we know the key is actually gone from memory? + delete(am.unlockedKeys, string(addr)) + am.mutex.RUnlock() +} |