Skip to content

Commit

Permalink
Start abstracting geth Keystore
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro Pombeiro committed Dec 19, 2019
1 parent ef87c33 commit dd894ec
Show file tree
Hide file tree
Showing 22 changed files with 245 additions and 216 deletions.
36 changes: 18 additions & 18 deletions account/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"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/types"
"github.com/status-im/status-go/extkeys"
)
Expand All @@ -32,7 +32,7 @@ var (
ErrAccountKeyStoreMissing = errors.New("account key store is not set")
)

var zeroAddress = common.Address{}
var zeroAddress = types.Address{}

// Manager represents account manager interface.
type Manager struct {
Expand All @@ -44,8 +44,8 @@ type Manager struct {
onboarding *Onboarding

selectedChatAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
mainAccountAddress common.Address
watchAddresses []common.Address
mainAccountAddress types.Address
watchAddresses []types.Address
}

// NewManager returns new node account manager.
Expand Down Expand Up @@ -157,7 +157,7 @@ func (m *Manager) VerifyAccountPassword(keyStoreDir, address, password string) (
var err error
var foundKeyFile []byte

addressObj := common.BytesToAddress(common.FromHex(address))
addressObj := types.BytesToAddress(types.FromHex(address))
checkAccountKey := func(path string, fileInfo os.FileInfo) error {
if len(foundKeyFile) > 0 || fileInfo.IsDir() {
return nil
Expand All @@ -175,7 +175,7 @@ func (m *Manager) VerifyAccountPassword(keyStoreDir, address, password string) (
return fmt.Errorf("failed to read key file: %s", e)
}

if common.HexToAddress("0x"+accountKey.Address).Hex() == addressObj.Hex() {
if types.HexToAddress("0x"+accountKey.Address).Hex() == addressObj.Hex() {
foundKeyFile = rawKeyFile
}

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

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

Expand All @@ -227,8 +227,8 @@ func (m *Manager) SelectAccount(loginParams LoginParams) error {
return nil
}

func (m *Manager) SetAccountAddresses(main common.Address, secondary ...common.Address) {
m.watchAddresses = []common.Address{main}
func (m *Manager) SetAccountAddresses(main types.Address, secondary ...types.Address) {
m.watchAddresses = []types.Address{main}
m.watchAddresses = append(m.watchAddresses, secondary...)
m.mainAccountAddress = main
}
Expand All @@ -242,7 +242,7 @@ func (m *Manager) SetChatAccount(privKey *ecdsa.PrivateKey) {
id := uuid.NewRandom()
key := &keystore.Key{
Id: id,
Address: address,
Address: common.Address(address),
PrivateKey: privKey,
}

Expand All @@ -253,7 +253,7 @@ func (m *Manager) SetChatAccount(privKey *ecdsa.PrivateKey) {
}

// MainAccountAddress returns currently selected watch addresses.
func (m *Manager) MainAccountAddress() (common.Address, error) {
func (m *Manager) MainAccountAddress() (types.Address, error) {
m.mu.RLock()
defer m.mu.RUnlock()

Expand All @@ -265,7 +265,7 @@ func (m *Manager) MainAccountAddress() (common.Address, error) {
}

// WatchAddresses returns currently selected watch addresses.
func (m *Manager) WatchAddresses() []common.Address {
func (m *Manager) WatchAddresses() []types.Address {
m.mu.RLock()
defer m.mu.RUnlock()

Expand Down Expand Up @@ -295,14 +295,14 @@ func (m *Manager) Logout() {
}

// ImportAccount imports the account specified with privateKey.
func (m *Manager) ImportAccount(privateKey *ecdsa.PrivateKey, password string) (common.Address, error) {
func (m *Manager) ImportAccount(privateKey *ecdsa.PrivateKey, password string) (types.Address, error) {
if m.keystore == nil {
return common.Address{}, ErrAccountKeyStoreMissing
return types.Address{}, ErrAccountKeyStoreMissing
}

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

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

func (m *Manager) ImportSingleExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) {
Expand Down Expand Up @@ -355,10 +355,10 @@ func (m *Manager) importExtendedKey(keyPurpose extkeys.KeyPurpose, extKey *extke

// Accounts returns list of addresses for selected account, including
// subaccounts.
func (m *Manager) Accounts() ([]common.Address, error) {
func (m *Manager) Accounts() ([]types.Address, error) {
m.mu.RLock()
defer m.mu.RUnlock()
addresses := make([]common.Address, 0)
addresses := make([]types.Address, 0)
if m.mainAccountAddress != zeroAddress {
addresses = append(addresses, m.mainAccountAddress)
}
Expand Down Expand Up @@ -444,7 +444,7 @@ func (m *Manager) unlockExtendedKey(address, password string) (*SelectedExtKey,
}

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

Expand Down
32 changes: 16 additions & 16 deletions account/accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"reflect"
"testing"

"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/t/utils"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
Expand All @@ -32,7 +32,7 @@ func TestVerifyAccountPassword(t *testing.T) {
require.NoError(t, utils.ImportTestAccount(keyStoreDir, utils.GetAccount1PKFile()))
require.NoError(t, utils.ImportTestAccount(keyStoreDir, utils.GetAccount2PKFile()))

account1Address := common.BytesToAddress(common.FromHex(utils.TestConfig.Account1.WalletAddress))
account1Address := types.BytesToAddress(types.FromHex(utils.TestConfig.Account1.WalletAddress))

testCases := []struct {
name string
Expand Down Expand Up @@ -86,8 +86,8 @@ func TestVerifyAccountPassword(t *testing.T) {
if accountKey == nil {
require.Fail(t, "no error reported, but account key is missing")
}
accountAddress := common.BytesToAddress(common.FromHex(testCase.address))
if accountKey.Address != accountAddress {
accountAddress := types.BytesToAddress(types.FromHex(testCase.address))
if types.Address(accountKey.Address) != accountAddress {
require.Fail(t, "account mismatch: have %s, want %s", accountKey.Address.Hex(), accountAddress.Hex())
}
}
Expand All @@ -108,7 +108,7 @@ func TestVerifyAccountPasswordWithAccountBeforeEIP55(t *testing.T) {

accManager := NewManager()

address := common.HexToAddress(utils.TestConfig.Account3.WalletAddress)
address := types.HexToAddress(utils.TestConfig.Account3.WalletAddress)
_, err = accManager.VerifyAccountPassword(keyStoreDir, address.Hex(), utils.TestConfig.Account3.Password)
require.NoError(t, err)
}
Expand Down Expand Up @@ -220,18 +220,18 @@ func (s *ManagerTestSuite) TestOnboarding() {
}

func (s *ManagerTestSuite) TestSelectAccountSuccess() {
s.testSelectAccount(common.HexToAddress(s.testAccount.chatAddress), common.HexToAddress(s.testAccount.walletAddress), s.testAccount.password, nil)
s.testSelectAccount(types.HexToAddress(s.testAccount.chatAddress), types.HexToAddress(s.testAccount.walletAddress), s.testAccount.password, nil)
}

func (s *ManagerTestSuite) TestSelectAccountWrongAddress() {
s.testSelectAccount(common.HexToAddress("0x0000000000000000000000000000000000000001"), common.HexToAddress(s.testAccount.walletAddress), s.testAccount.password, errors.New("cannot retrieve a valid key for a given account: no key for given address or file"))
s.testSelectAccount(types.HexToAddress("0x0000000000000000000000000000000000000001"), types.HexToAddress(s.testAccount.walletAddress), s.testAccount.password, errors.New("cannot retrieve a valid key for a given account: no key for given address or file"))
}

func (s *ManagerTestSuite) TestSelectAccountWrongPassword() {
s.testSelectAccount(common.HexToAddress(s.testAccount.chatAddress), common.HexToAddress(s.testAccount.walletAddress), "wrong", errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password"))
s.testSelectAccount(types.HexToAddress(s.testAccount.chatAddress), types.HexToAddress(s.testAccount.walletAddress), "wrong", errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password"))
}

func (s *ManagerTestSuite) testSelectAccount(chat, wallet common.Address, password string, expErr error) {
func (s *ManagerTestSuite) testSelectAccount(chat, wallet types.Address, password string, expErr error) {
loginParams := LoginParams{
ChatAddress: chat,
MainAccount: wallet,
Expand All @@ -249,7 +249,7 @@ func (s *ManagerTestSuite) testSelectAccount(chat, wallet common.Address, passwo
s.Equal(wallet, selectedMainAccountAddress)
s.Equal(chat, crypto.PubkeyToAddress(selectedChatAccount.AccountKey.PrivateKey.PublicKey))
} else {
s.Equal(common.Address{}, selectedMainAccountAddress)
s.Equal(types.Address{}, selectedMainAccountAddress)
s.Nil(selectedChatAccount)
s.Equal(walletErr, ErrNoAccountSelected)
s.Equal(chatErr, ErrNoAccountSelected)
Expand All @@ -275,12 +275,12 @@ func (s *ManagerTestSuite) TestSetChatAccount() {

selectedMainAccountAddress, err := s.accManager.MainAccountAddress()
s.Error(err)
s.Equal(common.Address{}, selectedMainAccountAddress)
s.Equal(types.Address{}, selectedMainAccountAddress)
}

func (s *ManagerTestSuite) TestLogout() {
s.accManager.Logout()
s.Equal(common.Address{}, s.accManager.mainAccountAddress)
s.Equal(types.Address{}, s.accManager.mainAccountAddress)
s.Nil(s.accManager.selectedChatAccount)
s.Len(s.accManager.watchAddresses, 0)
}
Expand All @@ -289,8 +289,8 @@ func (s *ManagerTestSuite) TestLogout() {
func (s *ManagerTestSuite) TestAccounts() {
// Select the test account
loginParams := LoginParams{
MainAccount: common.HexToAddress(s.walletAddress),
ChatAddress: common.HexToAddress(s.chatAddress),
MainAccount: types.HexToAddress(s.walletAddress),
ChatAddress: types.HexToAddress(s.chatAddress),
Password: s.password,
}
err := s.accManager.SelectAccount(loginParams)
Expand All @@ -301,7 +301,7 @@ func (s *ManagerTestSuite) TestAccounts() {
s.NoError(err)
s.NotNil(accs)
// Selected main account address is zero address but doesn't fail
s.accManager.mainAccountAddress = common.Address{}
s.accManager.mainAccountAddress = types.Address{}
accs, err = s.accManager.Accounts()
s.NoError(err)
s.NotNil(accs)
Expand Down
6 changes: 3 additions & 3 deletions account/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/pborman/uuid"
"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 @@ -27,7 +27,7 @@ var (
type AccountManager interface {
AddressToDecryptedAccount(address, password string) (accounts.Account, *keystore.Key, error)
ImportSingleExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error)
ImportAccount(privateKey *ecdsa.PrivateKey, password string) (common.Address, error)
ImportAccount(privateKey *ecdsa.PrivateKey, password string) (types.Address, error)
}

type Generator struct {
Expand Down
35 changes: 24 additions & 11 deletions account/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"

"github.com/status-im/status-go/eth-node/types"
)

// errors
Expand All @@ -17,10 +19,10 @@ var (
)

type LoginParams struct {
ChatAddress common.Address `json:"chatAddress"`
Password string `json:"password"`
MainAccount common.Address `json:"mainAccount"`
WatchAddresses []common.Address `json:"watchAddresses"`
ChatAddress types.Address `json:"chatAddress"`
Password string `json:"password"`
MainAccount types.Address `json:"mainAccount"`
WatchAddresses []types.Address `json:"watchAddresses"`
}

type ErrZeroAddress struct {
Expand All @@ -40,7 +42,7 @@ func newErrZeroAddress(field string) *ErrZeroAddress {
func ParseLoginParams(paramsJSON string) (LoginParams, error) {
var (
params LoginParams
zeroAddress common.Address
zeroAddress types.Address
)
if err := json.Unmarshal([]byte(paramsJSON), &params); err != nil {
return params, err
Expand Down Expand Up @@ -72,7 +74,7 @@ type Info struct {

// SelectedExtKey is a container for the selected (logged in) external account.
type SelectedExtKey struct {
Address common.Address
Address types.Address
AccountKey *keystore.Key
SubAccounts []accounts.Account
}
Expand All @@ -89,16 +91,16 @@ func (k *SelectedExtKey) Hex() string {
// ParseAccountString parses hex encoded string and returns is as accounts.Account.
func ParseAccountString(account string) (accounts.Account, error) {
// valid address, convert to account
if common.IsHexAddress(account) {
if types.IsHexAddress(account) {
return accounts.Account{Address: common.HexToAddress(account)}, nil
}

return accounts.Account{}, ErrInvalidAccountAddressOrKey
}

// FromAddress converts account address from string to common.Address.
// GethFromAddress converts account address from string to common.Address.
// The function is useful to format "From" field of send transaction struct.
func FromAddress(accountAddress string) common.Address {
func GethFromAddress(accountAddress string) common.Address {
from, err := ParseAccountString(accountAddress)
if err != nil {
return common.Address{}
Expand All @@ -107,9 +109,20 @@ func FromAddress(accountAddress string) common.Address {
return from.Address
}

// ToAddress converts account address from string to *common.Address.
// FromAddress converts account address from string to types.Address.
// The function is useful to format "From" field of send transaction struct.
func FromAddress(accountAddress string) types.Address {
from, err := ParseAccountString(accountAddress)
if err != nil {
return types.Address{}
}

return types.Address(from.Address)
}

// GethToAddress converts account address from string to *common.Address.
// The function is useful to format "To" field of send transaction struct.
func ToAddress(accountAddress string) *common.Address {
func GethToAddress(accountAddress string) *common.Address {
to, err := ParseAccountString(accountAddress)
if err != nil {
return nil
Expand Down
23 changes: 19 additions & 4 deletions account/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ func (suite *AccountUtilsTestSuite) SetupTest() {
suite.validKey = "0xF35E0325dad87e2661c4eF951d58727e6d583d5c"
}

func (suite *AccountUtilsTestSuite) TestToAddress() {
addr := ToAddress(suite.validKey)
func (suite *AccountUtilsTestSuite) TestGethToAddress() {
addr := GethToAddress(suite.validKey)
suite.Equal(suite.validKey, addr.String())
}

func (suite *AccountUtilsTestSuite) TestToAddressInvalidAddress() {
addr := ToAddress("foobar")
func (suite *AccountUtilsTestSuite) TestGethToAddressInvalidAddress() {
addr := GethToAddress("foobar")
suite.Nil(addr)
}

Expand All @@ -46,6 +46,21 @@ func (suite *AccountUtilsTestSuite) TestFromAddress() {
}
}

func (suite *AccountUtilsTestSuite) TestGethFromAddress() {
var flagtests = []struct {
in string
out string
}{
{suite.validKey, suite.validKey},
{"foobar", "0x0000000000000000000000000000000000000000"},
}

for _, tt := range flagtests {
addr := GethFromAddress(tt.in)
suite.Equal(tt.out, addr.String())
}
}

func (suite *AccountUtilsTestSuite) TestHex() {
var addr *SelectedExtKey
cr, _ := crypto.GenerateKey()
Expand Down
Loading

0 comments on commit dd894ec

Please # to comment.