Skip to content

Commit

Permalink
Abstract accounts.Key and geth keystore
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro Pombeiro committed Dec 20, 2019
1 parent b99af53 commit 7963987
Show file tree
Hide file tree
Showing 34 changed files with 1,146 additions and 244 deletions.
75 changes: 21 additions & 54 deletions account/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import (
"path/filepath"
"sync"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/pborman/uuid"

"github.com/status-im/status-go/account/generator"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/keystore"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/extkeys"
)
Expand All @@ -37,8 +35,7 @@ var zeroAddress = types.Address{}
// Manager represents account manager interface.
type Manager struct {
mu sync.RWMutex
keystore *keystore.KeyStore
manager *accounts.Manager
keystore types.KeyStore

accountsGenerator *generator.Generator
onboarding *Onboarding
Expand All @@ -48,51 +45,18 @@ type Manager struct {
watchAddresses []types.Address
}

// NewManager returns new node account manager.
func NewManager() *Manager {
m := &Manager{}
m.accountsGenerator = generator.New(m)
return m
}

// InitKeystore sets key manager and key store.
func (m *Manager) InitKeystore(keydir string) error {
m.mu.Lock()
defer m.mu.Unlock()
manager, err := makeAccountManager(keydir)
if err != nil {
return err
}
m.manager = manager
backends := manager.Backends(keystore.KeyStoreType)
if len(backends) == 0 {
return ErrAccountKeyStoreMissing
}
keyStore, ok := backends[0].(*keystore.KeyStore)
if !ok {
return ErrAccountKeyStoreMissing
}
m.keystore = keyStore
return nil
// AccountsGenerator returns accountsGenerator.
func (m *Manager) AccountsGenerator() *generator.Generator {
return m.accountsGenerator
}

func (m *Manager) GetKeystore() *keystore.KeyStore {
// GetKeystore is only used in tests
func (m *Manager) GetKeystore() types.KeyStore {
m.mu.RLock()
defer m.mu.RUnlock()
return m.keystore
}

func (m *Manager) GetManager() *accounts.Manager {
m.mu.RLock()
defer m.mu.RUnlock()
return m.manager
}

// AccountsGenerator returns accountsGenerator.
func (m *Manager) AccountsGenerator() *generator.Generator {
return m.accountsGenerator
}

// CreateAccount creates an internal geth account
// BIP44-compatible keys are generated: CKD#1 is stored as account key, CKD#2 stored as sub-account root
// Public key of CKD#1 is returned, with CKD#2 securely encoded into account key file (to be used for
Expand Down Expand Up @@ -153,7 +117,7 @@ func (m *Manager) RecoverAccount(password, mnemonic string) (Info, error) {

// VerifyAccountPassword tries to decrypt a given account key file, with a provided password.
// If no error is returned, then account is considered verified.
func (m *Manager) VerifyAccountPassword(keyStoreDir, address, password string) (*keystore.Key, error) {
func (m *Manager) VerifyAccountPassword(keyStoreDir, address, password string) (*types.Key, error) {
var err error
var foundKeyFile []byte

Expand Down Expand Up @@ -202,7 +166,7 @@ func (m *Manager) VerifyAccountPassword(keyStoreDir, address, password string) (
}

// avoid swap attack
if types.Address(key.Address) != addressObj {
if key.Address != addressObj {
return nil, fmt.Errorf("account mismatch: have %s, want %s", key.Address.Hex(), addressObj.Hex())
}

Expand Down Expand Up @@ -240,9 +204,9 @@ func (m *Manager) SetChatAccount(privKey *ecdsa.PrivateKey) {

address := crypto.PubkeyToAddress(privKey.PublicKey)
id := uuid.NewRandom()
key := &keystore.Key{
key := &types.Key{
Id: id,
Address: common.Address(address),
Address: address,
PrivateKey: privKey,
}

Expand Down Expand Up @@ -302,9 +266,13 @@ func (m *Manager) ImportAccount(privateKey *ecdsa.PrivateKey, password string) (

account, err := m.keystore.ImportECDSA(privateKey, password)

return types.Address(account.Address), err
return account.Address, err
}

// ImportSingleExtendedKey imports an extended key setting it in both the PrivateKey and ExtendedKey fields
// of the Key struct.
// ImportExtendedKey is used in older version of Status where PrivateKey is set to be the BIP44 key at index 0,
// and ExtendedKey is the extended key of the BIP44 key at index 1.
func (m *Manager) ImportSingleExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) {
if m.keystore == nil {
return "", "", ErrAccountKeyStoreMissing
Expand Down Expand Up @@ -418,18 +386,17 @@ func (m *Manager) ImportOnboardingAccount(id string, password string) (Info, str
// AddressToDecryptedAccount tries to load decrypted key for a given account.
// The running node, has a keystore directory which is loaded on start. Key file
// for a given address is expected to be in that directory prior to node start.
func (m *Manager) AddressToDecryptedAccount(address, password string) (accounts.Account, *keystore.Key, error) {
func (m *Manager) AddressToDecryptedAccount(address, password string) (types.Account, *types.Key, error) {
if m.keystore == nil {
return accounts.Account{}, nil, ErrAccountKeyStoreMissing
return types.Account{}, nil, ErrAccountKeyStoreMissing
}

account, err := ParseAccountString(address)
if err != nil {
return accounts.Account{}, nil, ErrAddressToAccountMappingFailure
return types.Account{}, nil, ErrAddressToAccountMappingFailure
}

var key *keystore.Key
account, key, err = m.keystore.AccountDecryptedKey(account, password)
account, key, err := m.keystore.AccountDecryptedKey(account, password)
if err != nil {
err = fmt.Errorf("%s: %s", ErrAccountToKeyMappingFailure, err)
}
Expand All @@ -444,7 +411,7 @@ func (m *Manager) unlockExtendedKey(address, password string) (*SelectedExtKey,
}

selectedExtendedKey := &SelectedExtKey{
Address: types.Address(account.Address),
Address: account.Address,
AccountKey: accountKey,
}

Expand Down
42 changes: 42 additions & 0 deletions account/accounts_geth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// +build !nimbus

package account

import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/status-im/status-go/account/generator"
)

// GethManager represents account manager interface.
type GethManager struct {
Manager

manager *accounts.Manager
}

// NewManager returns new node account manager.
func NewManager() *GethManager {
m := &GethManager{}
m.accountsGenerator = generator.New(m)
return m
}

// InitKeystore sets key manager and key store.
func (m *GethManager) InitKeystore(keydir string) error {
m.mu.Lock()
defer m.mu.Unlock()

var err error
m.manager, err = makeAccountManager(keydir)
if err != nil {
return err
}
m.keystore, err = makeKeyStore(m.manager)
return err
}

func (m *GethManager) GetManager() *accounts.Manager {
m.mu.RLock()
defer m.mu.RUnlock()
return m.manager
}
28 changes: 28 additions & 0 deletions account/accounts_nimbus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// +build nimbus

package account

import (
"github.com/status-im/status-go/account/generator"
)

// NewManager returns new node account manager.
func NewManager() *Manager {
m := &Manager{}
m.accountsGenerator = generator.New(m)
return m
}

// InitKeystore sets key manager and key store.
func (m *Manager) InitKeystore(keydir string) error {
m.mu.Lock()
defer m.mu.Unlock()

// TODO: Wire with the Nimbus keystore
manager, err := makeAccountManager(keydir)
if err != nil {
return err
}
m.keystore, err = makeKeyStore(manager)
return err
}
4 changes: 2 additions & 2 deletions account/accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func TestVerifyAccountPassword(t *testing.T) {
require.Fail(t, "no error reported, but account key is missing")
}
accountAddress := types.BytesToAddress(types.FromHex(testCase.address))
if types.Address(accountKey.Address) != accountAddress {
if accountKey.Address != accountAddress {
require.Fail(t, "account mismatch: have %s, want %s", accountKey.Address.Hex(), accountAddress.Hex())
}
}
Expand Down Expand Up @@ -120,7 +120,7 @@ func TestManagerTestSuite(t *testing.T) {
type ManagerTestSuite struct {
suite.Suite
testAccount
accManager *Manager
accManager *GethManager
keydir string
}

Expand Down
3 changes: 1 addition & 2 deletions account/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"strings"
"sync"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/pborman/uuid"
"github.com/status-im/status-go/eth-node/crypto"
Expand All @@ -25,7 +24,7 @@ var (
)

type AccountManager interface {
AddressToDecryptedAccount(address, password string) (accounts.Account, *keystore.Key, error)
AddressToDecryptedAccount(address, password string) (types.Account, *types.Key, error)
ImportSingleExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error)
ImportAccount(privateKey *ecdsa.PrivateKey, password string) (types.Address, error)
}
Expand Down
4 changes: 2 additions & 2 deletions account/generator/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"bytes"
"errors"

"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/extkeys"
)

Expand All @@ -21,7 +21,7 @@ var (

// ValidateKeystoreExtendedKey validates the keystore keys, checking that
// ExtendedKey is the extended key of PrivateKey.
func ValidateKeystoreExtendedKey(key *keystore.Key) error {
func ValidateKeystoreExtendedKey(key *types.Key) error {
if key.ExtendedKey.IsZeroed() {
return nil
}
Expand Down
8 changes: 4 additions & 4 deletions account/generator/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package generator
import (
"testing"

"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/extkeys"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -25,22 +25,22 @@ func TestValidateKeystoreExtendedKey(t *testing.T) {
extendedKey2 := generateTestKey(t)

// new keystore file format
key := &keystore.Key{
key := &types.Key{
PrivateKey: extendedKey1.ToECDSA(),
ExtendedKey: extendedKey1,
}
assert.NoError(t, ValidateKeystoreExtendedKey(key))

// old keystore file format where the extended key was
// from another derivation path and not the same of the private key
oldKey := &keystore.Key{
oldKey := &types.Key{
PrivateKey: extendedKey1.ToECDSA(),
ExtendedKey: extendedKey2,
}
assert.Error(t, ValidateKeystoreExtendedKey(oldKey))

// normal key where we don't have an extended key
normalKey := &keystore.Key{
normalKey := &types.Key{
PrivateKey: extendedKey1.ToECDSA(),
ExtendedKey: nil,
}
Expand Down
26 changes: 0 additions & 26 deletions account/keystore.go

This file was deleted.

Loading

0 comments on commit 7963987

Please # to comment.