[#issue-403] Account package cleanup

This commit is contained in:
Adrià Cidre 2018-03-22 13:31:12 +01:00
parent 01769e9ee8
commit 18fbebc942
No known key found for this signature in database
GPG Key ID: D246A27D58A92CAB
20 changed files with 413 additions and 544 deletions

View File

@ -1,7 +1,6 @@
package account package account
import ( import (
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -14,30 +13,32 @@ import (
gethcommon "github.com/ethereum/go-ethereum/common" gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/status-go/extkeys" "github.com/status-im/status-go/extkeys"
"github.com/status-im/status-go/geth/common"
"github.com/status-im/status-go/geth/rpc"
) )
// errors // errors
var ( var (
ErrAddressToAccountMappingFailure = errors.New("cannot retrieve a valid account for a given address") ErrAddressToAccountMappingFailure = errors.New("cannot retrieve a valid account for a given address")
ErrAccountToKeyMappingFailure = errors.New("cannot retrieve a valid key for a given account") ErrAccountToKeyMappingFailure = errors.New("cannot retrieve a valid key for a given account")
ErrWhisperIdentityInjectionFailure = errors.New("failed to inject identity into Whisper") ErrNoAccountSelected = errors.New("no account has been selected, please login")
ErrWhisperClearIdentitiesFailure = errors.New("failed to clear whisper identities") ErrInvalidMasterKeyCreated = errors.New("can not create master extended key")
ErrNoAccountSelected = errors.New("no account has been selected, please login")
ErrInvalidMasterKeyCreated = errors.New("can not create master extended key")
) )
// Manager represents account manager interface // GethServiceProvider provides required geth services.
type Manager struct { type GethServiceProvider interface {
nodeManager common.NodeManager AccountManager() (*accounts.Manager, error)
selectedAccount *common.SelectedExtKey // account that was processed during the last call to SelectAccount() AccountKeyStore() (*keystore.KeyStore, error)
} }
// NewManager returns new node account manager // Manager represents account manager interface.
func NewManager(nodeManager common.NodeManager) *Manager { type Manager struct {
geth GethServiceProvider
selectedAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
}
// NewManager returns new node account manager.
func NewManager(geth GethServiceProvider) *Manager {
return &Manager{ return &Manager{
nodeManager: nodeManager, geth: geth,
} }
} }
@ -72,7 +73,7 @@ func (m *Manager) CreateAccount(password string) (address, pubKey, mnemonic stri
// CKD#2 is used as root for master accounts (when parentAddress is ""). // CKD#2 is used as root for master accounts (when parentAddress is "").
// Otherwise (when parentAddress != ""), child is derived directly from parent. // Otherwise (when parentAddress != ""), child is derived directly from parent.
func (m *Manager) CreateChildAccount(parentAddress, password string) (address, pubKey string, err error) { func (m *Manager) CreateChildAccount(parentAddress, password string) (address, pubKey string, err error) {
keyStore, err := m.nodeManager.AccountKeyStore() keyStore, err := m.geth.AccountKeyStore()
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -85,7 +86,7 @@ func (m *Manager) CreateChildAccount(parentAddress, password string) (address, p
return "", "", ErrNoAccountSelected return "", "", ErrNoAccountSelected
} }
account, err := common.ParseAccountString(parentAddress) account, err := ParseAccountString(parentAddress)
if err != nil { if err != nil {
return "", "", ErrAddressToAccountMappingFailure return "", "", ErrAddressToAccountMappingFailure
} }
@ -203,15 +204,14 @@ func (m *Manager) VerifyAccountPassword(keyStoreDir, address, password string) (
} }
// SelectAccount selects current account, by verifying that address has corresponding account which can be decrypted // SelectAccount selects current account, by verifying that address has corresponding account which can be decrypted
// using provided password. Once verification is done, decrypted key is injected into Whisper (as a single identity, // using provided password. Once verification is done, all previous identities are removed).
// all previous identities are removed).
func (m *Manager) SelectAccount(address, password string) error { func (m *Manager) SelectAccount(address, password string) error {
keyStore, err := m.nodeManager.AccountKeyStore() keyStore, err := m.geth.AccountKeyStore()
if err != nil { if err != nil {
return err return err
} }
account, err := common.ParseAccountString(address) account, err := ParseAccountString(address)
if err != nil { if err != nil {
return ErrAddressToAccountMappingFailure return ErrAddressToAccountMappingFailure
} }
@ -221,22 +221,12 @@ func (m *Manager) SelectAccount(address, password string) error {
return fmt.Errorf("%s: %v", ErrAccountToKeyMappingFailure.Error(), err) return fmt.Errorf("%s: %v", ErrAccountToKeyMappingFailure.Error(), err)
} }
whisperService, err := m.nodeManager.WhisperService()
if err != nil {
return err
}
err = whisperService.SelectKeyPair(accountKey.PrivateKey)
if err != nil {
return ErrWhisperIdentityInjectionFailure
}
// persist account key for easier recovery of currently selected key // persist account key for easier recovery of currently selected key
subAccounts, err := m.findSubAccounts(accountKey.ExtendedKey, accountKey.SubAccountIndex) subAccounts, err := m.findSubAccounts(accountKey.ExtendedKey, accountKey.SubAccountIndex)
if err != nil { if err != nil {
return err return err
} }
m.selectedAccount = &common.SelectedExtKey{ m.selectedAccount = &SelectedExtKey{
Address: account.Address, Address: account.Address,
AccountKey: accountKey, AccountKey: accountKey,
SubAccounts: subAccounts, SubAccounts: subAccounts,
@ -246,44 +236,15 @@ func (m *Manager) SelectAccount(address, password string) error {
} }
// SelectedAccount returns currently selected account // SelectedAccount returns currently selected account
func (m *Manager) SelectedAccount() (*common.SelectedExtKey, error) { func (m *Manager) SelectedAccount() (*SelectedExtKey, error) {
if m.selectedAccount == nil { if m.selectedAccount == nil {
return nil, ErrNoAccountSelected return nil, ErrNoAccountSelected
} }
return m.selectedAccount, nil return m.selectedAccount, nil
} }
// ReSelectAccount selects previously selected account, often, after node restart. // Logout clears selectedAccount.
func (m *Manager) ReSelectAccount() error {
selectedAccount := m.selectedAccount
if selectedAccount == nil {
return nil
}
whisperService, err := m.nodeManager.WhisperService()
if err != nil {
return err
}
if err := whisperService.SelectKeyPair(selectedAccount.AccountKey.PrivateKey); err != nil {
return ErrWhisperIdentityInjectionFailure
}
return nil
}
// Logout clears whisper identities
func (m *Manager) Logout() error { func (m *Manager) Logout() error {
whisperService, err := m.nodeManager.WhisperService()
if err != nil {
return err
}
err = whisperService.DeleteKeyPairs()
if err != nil {
return fmt.Errorf("%s: %v", ErrWhisperClearIdentitiesFailure, err)
}
m.selectedAccount = nil m.selectedAccount = nil
return nil return nil
@ -292,7 +253,7 @@ func (m *Manager) Logout() error {
// importExtendedKey processes incoming extended key, extracts required info and creates corresponding account key. // importExtendedKey processes incoming extended key, extracts required info and creates corresponding account key.
// Once account key is formed, that key is put (if not already) into keystore i.e. key is *encoded* into key file. // Once account key is formed, that key is put (if not already) into keystore i.e. key is *encoded* into key file.
func (m *Manager) importExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) { func (m *Manager) importExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) {
keyStore, err := m.nodeManager.AccountKeyStore() keyStore, err := m.geth.AccountKeyStore()
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -317,7 +278,7 @@ func (m *Manager) importExtendedKey(extKey *extkeys.ExtendedKey, password string
// Accounts returns list of addresses for selected account, including // Accounts returns list of addresses for selected account, including
// subaccounts. // subaccounts.
func (m *Manager) Accounts() ([]gethcommon.Address, error) { func (m *Manager) Accounts() ([]gethcommon.Address, error) {
am, err := m.nodeManager.AccountManager() am, err := m.geth.AccountManager()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -353,13 +314,6 @@ func (m *Manager) Accounts() ([]gethcommon.Address, error) {
return filtered, nil return filtered, nil
} }
// AccountsRPCHandler returns RPC Handler for the Accounts() method.
func (m *Manager) AccountsRPCHandler() rpc.Handler {
return func(context.Context, ...interface{}) (interface{}, error) {
return m.Accounts()
}
}
// refreshSelectedAccount re-populates list of sub-accounts of the currently selected account (if any) // refreshSelectedAccount re-populates list of sub-accounts of the currently selected account (if any)
func (m *Manager) refreshSelectedAccount() { func (m *Manager) refreshSelectedAccount() {
if m.selectedAccount == nil { if m.selectedAccount == nil {
@ -376,7 +330,7 @@ func (m *Manager) refreshSelectedAccount() {
if err != nil { if err != nil {
return return
} }
m.selectedAccount = &common.SelectedExtKey{ m.selectedAccount = &SelectedExtKey{
Address: m.selectedAccount.Address, Address: m.selectedAccount.Address,
AccountKey: m.selectedAccount.AccountKey, AccountKey: m.selectedAccount.AccountKey,
SubAccounts: subAccounts, SubAccounts: subAccounts,
@ -387,7 +341,7 @@ func (m *Manager) refreshSelectedAccount() {
// that belong to the currently selected account. // that belong to the currently selected account.
// The extKey is CKD#2 := root of sub-accounts of the main account // The extKey is CKD#2 := root of sub-accounts of the main account
func (m *Manager) findSubAccounts(extKey *extkeys.ExtendedKey, subAccountIndex uint32) ([]accounts.Account, error) { func (m *Manager) findSubAccounts(extKey *extkeys.ExtendedKey, subAccountIndex uint32) ([]accounts.Account, error) {
keyStore, err := m.nodeManager.AccountKeyStore() keyStore, err := m.geth.AccountKeyStore()
if err != nil { if err != nil {
return []accounts.Account{}, err return []accounts.Account{}, err
} }
@ -421,12 +375,12 @@ func (m *Manager) findSubAccounts(extKey *extkeys.ExtendedKey, subAccountIndex u
// The running node, has a keystore directory which is loaded on start. Key file // 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. // 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) (accounts.Account, *keystore.Key, error) {
keyStore, err := m.nodeManager.AccountKeyStore() keyStore, err := m.geth.AccountKeyStore()
if err != nil { if err != nil {
return accounts.Account{}, nil, err return accounts.Account{}, nil, err
} }
account, err := common.ParseAccountString(address) account, err := ParseAccountString(address)
if err != nil { if err != nil {
return accounts.Account{}, nil, ErrAddressToAccountMappingFailure return accounts.Account{}, nil, ErrAddressToAccountMappingFailure
} }

View File

@ -12,7 +12,6 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
gethcommon "github.com/ethereum/go-ethereum/common" gethcommon "github.com/ethereum/go-ethereum/common"
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/status-im/status-go/geth/common" "github.com/status-im/status-go/geth/common"
. "github.com/status-im/status-go/t/utils" . "github.com/status-im/status-go/t/utils"
@ -115,7 +114,6 @@ func TestVerifyAccountPasswordWithAccountBeforeEIP55(t *testing.T) {
} }
var ( var (
errWhisper = errors.New("Can't return a whisper service")
errKeyStore = errors.New("Can't return a key store") errKeyStore = errors.New("Can't return a key store")
errAccManager = errors.New("Can't return an account manager") errAccManager = errors.New("Can't return an account manager")
) )
@ -149,7 +147,6 @@ func TestManagerTestSuite(t *testing.T) {
nodeManager: nodeManager, nodeManager: nodeManager,
accManager: accManager, accManager: accManager,
keyStore: keyStore, keyStore: keyStore,
shh: whisper.New(nil),
gethAccManager: accounts.NewManager(), gethAccManager: accounts.NewManager(),
} }
@ -167,7 +164,6 @@ type ManagerTestSuite struct {
nodeManager *common.MockNodeManager nodeManager *common.MockNodeManager
accManager *Manager accManager *Manager
keyStore *keystore.KeyStore keyStore *keystore.KeyStore
shh *whisper.Whisper
gethAccManager *accounts.Manager gethAccManager *accounts.Manager
} }
@ -183,7 +179,7 @@ type testAccount struct {
// development so this is a good workaround to use with EXPECT().Func().AnyTimes() // development so this is a good workaround to use with EXPECT().Func().AnyTimes()
func (s *ManagerTestSuite) reinitMock() { func (s *ManagerTestSuite) reinitMock() {
s.nodeManager = newMockNodeManager(s.T()) s.nodeManager = newMockNodeManager(s.T())
s.accManager.nodeManager = s.nodeManager s.accManager.geth = s.nodeManager
} }
// SetupTest is used here for reinitializing the mock before every // SetupTest is used here for reinitializing the mock before every
@ -219,7 +215,6 @@ func (s *ManagerTestSuite) TestSelectAccount() {
testCases := []struct { testCases := []struct {
name string name string
accountKeyStoreReturn []interface{} accountKeyStoreReturn []interface{}
whisperServiceReturn []interface{}
address string address string
password string password string
expectedError error expectedError error
@ -227,7 +222,6 @@ func (s *ManagerTestSuite) TestSelectAccount() {
{ {
"success", "success",
[]interface{}{s.keyStore, nil}, []interface{}{s.keyStore, nil},
[]interface{}{s.shh, nil},
s.address, s.address,
s.password, s.password,
nil, nil,
@ -235,23 +229,13 @@ func (s *ManagerTestSuite) TestSelectAccount() {
{ {
"fail_keyStore", "fail_keyStore",
[]interface{}{nil, errKeyStore}, []interface{}{nil, errKeyStore},
[]interface{}{s.shh, nil},
s.address, s.address,
s.password, s.password,
errKeyStore, errKeyStore,
}, },
{
"fail_whisperService",
[]interface{}{s.keyStore, nil},
[]interface{}{nil, errWhisper},
s.address,
s.password,
errWhisper,
},
{ {
"fail_wrongAddress", "fail_wrongAddress",
[]interface{}{s.keyStore, nil}, []interface{}{s.keyStore, nil},
[]interface{}{s.shh, nil},
"wrong-address", "wrong-address",
s.password, s.password,
ErrAddressToAccountMappingFailure, ErrAddressToAccountMappingFailure,
@ -259,7 +243,6 @@ func (s *ManagerTestSuite) TestSelectAccount() {
{ {
"fail_wrongPassword", "fail_wrongPassword",
[]interface{}{s.keyStore, nil}, []interface{}{s.keyStore, nil},
[]interface{}{s.shh, nil},
s.address, s.address,
"wrong-password", "wrong-password",
errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase"), errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase"),
@ -270,7 +253,6 @@ func (s *ManagerTestSuite) TestSelectAccount() {
s.T().Run(testCase.name, func(t *testing.T) { s.T().Run(testCase.name, func(t *testing.T) {
s.reinitMock() s.reinitMock()
s.nodeManager.EXPECT().AccountKeyStore().Return(testCase.accountKeyStoreReturn...).AnyTimes() s.nodeManager.EXPECT().AccountKeyStore().Return(testCase.accountKeyStoreReturn...).AnyTimes()
s.nodeManager.EXPECT().WhisperService().Return(testCase.whisperServiceReturn...).AnyTimes()
err := s.accManager.SelectAccount(testCase.address, testCase.password) err := s.accManager.SelectAccount(testCase.address, testCase.password)
s.Equal(testCase.expectedError, err) s.Equal(testCase.expectedError, err)
}) })
@ -290,7 +272,6 @@ func (s *ManagerTestSuite) TestCreateChildAccount() {
// Now, select the test account for rest of the test cases. // Now, select the test account for rest of the test cases.
s.reinitMock() s.reinitMock()
s.nodeManager.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes() s.nodeManager.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes()
s.nodeManager.EXPECT().WhisperService().Return(s.shh, nil).AnyTimes()
err := s.accManager.SelectAccount(s.address, s.password) err := s.accManager.SelectAccount(s.address, s.password)
s.NoError(err) s.NoError(err)
@ -347,60 +328,16 @@ func (s *ManagerTestSuite) TestCreateChildAccount() {
} }
} }
func (s *ManagerTestSuite) TestSelectedAndReSelectAccount() {
// Select the test account
s.nodeManager.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes()
s.nodeManager.EXPECT().WhisperService().Return(s.shh, nil).AnyTimes()
err := s.accManager.SelectAccount(s.address, s.password)
s.NoError(err)
s.T().Run("success", func(t *testing.T) {
acc, err := s.accManager.SelectedAccount()
s.NoError(err)
s.NotNil(acc)
err = s.accManager.ReSelectAccount()
s.NoError(err)
})
s.T().Run("ReSelect_fail_whisper", func(t *testing.T) {
s.reinitMock()
s.nodeManager.EXPECT().WhisperService().Return(nil, errWhisper).AnyTimes()
err = s.accManager.ReSelectAccount()
s.Equal(errWhisper, err)
})
s.accManager.selectedAccount = nil
s.reinitMock()
s.nodeManager.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes()
s.nodeManager.EXPECT().WhisperService().Return(s.shh, nil).AnyTimes()
s.T().Run("Selected_fail_noAccount", func(t *testing.T) {
_, err := s.accManager.SelectedAccount()
s.Equal(ErrNoAccountSelected, err)
})
s.T().Run("ReSelect_success_noAccount", func(t *testing.T) {
err = s.accManager.ReSelectAccount()
s.NoError(err)
})
}
func (s *ManagerTestSuite) TestLogout() { func (s *ManagerTestSuite) TestLogout() {
s.nodeManager.EXPECT().WhisperService().Return(s.shh, nil)
err := s.accManager.Logout() err := s.accManager.Logout()
s.NoError(err) s.Nil(err)
s.Nil(s.accManager.selectedAccount)
s.nodeManager.EXPECT().WhisperService().Return(nil, errWhisper)
err = s.accManager.Logout()
s.Equal(errWhisper, err)
} }
// TestAccounts tests cases for (*Manager).Accounts. // TestAccounts tests cases for (*Manager).Accounts.
func (s *ManagerTestSuite) TestAccounts() { func (s *ManagerTestSuite) TestAccounts() {
// Select the test account // Select the test account
s.nodeManager.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes() s.nodeManager.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes()
s.nodeManager.EXPECT().WhisperService().Return(s.shh, nil).AnyTimes()
err := s.accManager.SelectAccount(s.address, s.password) err := s.accManager.SelectAccount(s.address, s.password)
s.NoError(err) s.NoError(err)

62
geth/account/utils.go Normal file
View File

@ -0,0 +1,62 @@
package account
import (
"errors"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
)
// errors
var (
ErrInvalidAccountAddressOrKey = errors.New("cannot parse address or key to valid account address")
)
// SelectedExtKey is a container for the selected (logged in) external account.
type SelectedExtKey struct {
Address common.Address
AccountKey *keystore.Key
SubAccounts []accounts.Account
}
// Hex dumps address of a given extended key as hex string.
func (k *SelectedExtKey) Hex() string {
if k == nil {
return "0x0"
}
return k.Address.Hex()
}
// 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) {
return accounts.Account{Address: common.HexToAddress(account)}, nil
}
return accounts.Account{}, ErrInvalidAccountAddressOrKey
}
// FromAddress 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 {
from, err := ParseAccountString(accountAddress)
if err != nil {
return common.Address{}
}
return from.Address
}
// ToAddress 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 {
to, err := ParseAccountString(accountAddress)
if err != nil {
return nil
}
return &to.Address
}

View File

@ -0,0 +1,67 @@
package account
// Basic imports
import (
"testing"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/suite"
)
type AccountUtilsTestSuite struct {
suite.Suite
validKey string
}
func (suite *AccountUtilsTestSuite) SetupTest() {
suite.validKey = "0xF35E0325dad87e2661c4eF951d58727e6d583d5c"
}
func (suite *AccountUtilsTestSuite) TestToAddress() {
addr := ToAddress(suite.validKey)
suite.Equal(suite.validKey, addr.String())
}
func (suite *AccountUtilsTestSuite) TestToAddressInvalidAddress() {
addr := ToAddress("foobar")
suite.Nil(addr)
}
func (suite *AccountUtilsTestSuite) TestFromAddress() {
var flagtests = []struct {
in string
out string
}{
{suite.validKey, suite.validKey},
{"foobar", "0x0000000000000000000000000000000000000000"},
}
for _, tt := range flagtests {
addr := FromAddress(tt.in)
suite.Equal(tt.out, addr.String())
}
}
func (suite *AccountUtilsTestSuite) TestHex() {
var addr *SelectedExtKey
cr, _ := crypto.GenerateKey()
var flagtests = []struct {
in *SelectedExtKey
out string
}{
{&SelectedExtKey{
Address: FromAddress(suite.validKey),
AccountKey: &keystore.Key{PrivateKey: cr},
}, suite.validKey},
{addr, "0x0"},
}
for _, tt := range flagtests {
suite.Equal(tt.in.Hex(), tt.out)
}
}
func TestAccountUtilsTestSuite(t *testing.T) {
suite.Run(t, new(AccountUtilsTestSuite))
}

View File

@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
gethcommon "github.com/ethereum/go-ethereum/common" gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/status-im/status-go/geth/account"
"github.com/status-im/status-go/geth/common" "github.com/status-im/status-go/geth/common"
"github.com/status-im/status-go/geth/jail" "github.com/status-im/status-go/geth/jail"
"github.com/status-im/status-go/geth/params" "github.com/status-im/status-go/geth/params"
@ -39,7 +40,7 @@ func (api *StatusAPI) NodeManager() common.NodeManager {
} }
// AccountManager returns reference to account manager // AccountManager returns reference to account manager
func (api *StatusAPI) AccountManager() common.AccountManager { func (api *StatusAPI) AccountManager() *account.Manager {
return api.b.AccountManager() return api.b.AccountManager()
} }
@ -135,13 +136,13 @@ func (api *StatusAPI) SelectAccount(address, password string) error {
// FIXME(oleg-raev): This method doesn't make stop, it rather resets its cells to an initial state // FIXME(oleg-raev): This method doesn't make stop, it rather resets its cells to an initial state
// and should be properly renamed, for example: ResetCells // and should be properly renamed, for example: ResetCells
api.b.jailManager.Stop() api.b.jailManager.Stop()
return api.b.AccountManager().SelectAccount(address, password) return api.b.SelectAccount(address, password)
} }
// Logout clears whisper identities // Logout clears whisper identities
func (api *StatusAPI) Logout() error { func (api *StatusAPI) Logout() error {
api.b.jailManager.Stop() api.b.jailManager.Stop()
return api.b.AccountManager().Logout() return api.b.Logout()
} }
// SendTransaction creates a new transaction and waits until it's complete. // SendTransaction creates a new transaction and waits until it's complete.

View File

@ -2,6 +2,7 @@ package api
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"sync" "sync"
@ -23,11 +24,18 @@ const (
fcmServerKey = "AAAAxwa-r08:APA91bFtMIToDVKGAmVCm76iEXtA4dn9MPvLdYKIZqAlNpLJbd12EgdBI9DSDSXKdqvIAgLodepmRhGVaWvhxnXJzVpE6MoIRuKedDV3kfHSVBhWFqsyoLTwXY4xeufL9Sdzb581U-lx" fcmServerKey = "AAAAxwa-r08:APA91bFtMIToDVKGAmVCm76iEXtA4dn9MPvLdYKIZqAlNpLJbd12EgdBI9DSDSXKdqvIAgLodepmRhGVaWvhxnXJzVpE6MoIRuKedDV3kfHSVBhWFqsyoLTwXY4xeufL9Sdzb581U-lx"
) )
var (
// ErrWhisperClearIdentitiesFailure clearing whisper identities has failed.
ErrWhisperClearIdentitiesFailure = errors.New("failed to clear whisper identities")
// ErrWhisperIdentityInjectionFailure injecting whisper identities has failed.
ErrWhisperIdentityInjectionFailure = errors.New("failed to inject identity into Whisper")
)
// StatusBackend implements Status.im service // StatusBackend implements Status.im service
type StatusBackend struct { type StatusBackend struct {
mu sync.Mutex mu sync.Mutex
nodeManager *node.NodeManager nodeManager *node.NodeManager
accountManager common.AccountManager accountManager *account.Manager
txQueueManager *transactions.Manager txQueueManager *transactions.Manager
jailManager jail.Manager jailManager jail.Manager
newNotification common.NotificationConstructor newNotification common.NotificationConstructor
@ -61,7 +69,7 @@ func (b *StatusBackend) NodeManager() *node.NodeManager {
} }
// AccountManager returns reference to account manager // AccountManager returns reference to account manager
func (b *StatusBackend) AccountManager() common.AccountManager { func (b *StatusBackend) AccountManager() *account.Manager {
return b.accountManager return b.accountManager
} }
@ -116,7 +124,7 @@ func (b *StatusBackend) startNode(config *params.NodeConfig) (err error) {
if err := b.registerHandlers(); err != nil { if err := b.registerHandlers(); err != nil {
b.log.Error("Handler registration failed", "err", err) b.log.Error("Handler registration failed", "err", err)
} }
if err := b.accountManager.ReSelectAccount(); err != nil { if err := b.ReSelectAccount(); err != nil {
b.log.Error("Reselect account failed", "err", err) b.log.Error("Reselect account failed", "err", err)
} }
b.log.Info("Account reselected") b.log.Info("Account reselected")
@ -226,7 +234,9 @@ func (b *StatusBackend) registerHandlers() error {
if rpcClient == nil { if rpcClient == nil {
return node.ErrRPCClient return node.ErrRPCClient
} }
rpcClient.RegisterHandler("eth_accounts", b.accountManager.AccountsRPCHandler()) rpcClient.RegisterHandler("eth_accounts", func(context.Context, ...interface{}) (interface{}, error) {
return b.AccountManager().Accounts()
})
rpcClient.RegisterHandler("eth_sendTransaction", b.txQueueManager.SendTransactionRPCHandler) rpcClient.RegisterHandler("eth_sendTransaction", b.txQueueManager.SendTransactionRPCHandler)
return nil return nil
} }
@ -247,3 +257,60 @@ func (b *StatusBackend) AppStateChange(state AppState) {
// TODO: put node in low-power mode if the app is in background (or inactive) // TODO: put node in low-power mode if the app is in background (or inactive)
// and normal mode if the app is in foreground. // and normal mode if the app is in foreground.
} }
// Logout clears whisper identities.
func (b *StatusBackend) Logout() error {
whisperService, err := b.nodeManager.WhisperService()
if err != nil {
return err
}
err = whisperService.DeleteKeyPairs()
if err != nil {
return fmt.Errorf("%s: %v", ErrWhisperClearIdentitiesFailure, err)
}
return b.AccountManager().Logout()
}
// ReSelectAccount selects previously selected account, often, after node restart.
func (b *StatusBackend) ReSelectAccount() error {
selectedAccount, err := b.AccountManager().SelectedAccount()
if selectedAccount == nil || err == account.ErrNoAccountSelected {
return nil
}
whisperService, err := b.nodeManager.WhisperService()
if err != nil {
return err
}
if err := whisperService.SelectKeyPair(selectedAccount.AccountKey.PrivateKey); err != nil {
return ErrWhisperIdentityInjectionFailure
}
return nil
}
// SelectAccount selects current account, by verifying that address has corresponding account which can be decrypted
// using provided password. Once verification is done, decrypted key is injected into Whisper (as a single identity,
// all previous identities are removed).
func (b *StatusBackend) SelectAccount(address, password string) error {
err := b.accountManager.SelectAccount(address, password)
if err != nil {
return err
}
acc, err := b.accountManager.SelectedAccount()
if err != nil {
return err
}
whisperService, err := b.nodeManager.WhisperService()
if err != nil {
return err
}
err = whisperService.SelectKeyPair(acc.AccountKey.PrivateKey)
if err != nil {
return ErrWhisperIdentityInjectionFailure
}
return nil
}

View File

@ -27,22 +27,6 @@ var (
ErrDeprecatedMethod = errors.New("Method is depricated and will be removed in future release") ErrDeprecatedMethod = errors.New("Method is depricated and will be removed in future release")
) )
// SelectedExtKey is a container for currently selected (logged in) account
type SelectedExtKey struct {
Address common.Address
AccountKey *keystore.Key
SubAccounts []accounts.Account
}
// Hex dumps address of a given extended key as hex string
func (k *SelectedExtKey) Hex() string {
if k == nil {
return "0x0"
}
return k.Address.Hex()
}
// NodeManager defines expected methods for managing Status node // NodeManager defines expected methods for managing Status node
type NodeManager interface { type NodeManager interface {
// StartNode start Status node, fails if node is already started // StartNode start Status node, fails if node is already started
@ -89,53 +73,6 @@ type NodeManager interface {
RPCClient() *rpc.Client RPCClient() *rpc.Client
} }
// AccountManager defines expected methods for managing Status accounts
type AccountManager interface {
// 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
// sub-account derivations)
CreateAccount(password string) (address, pubKey, mnemonic string, err error)
// CreateChildAccount creates sub-account for an account identified by parent address.
// CKD#2 is used as root for master accounts (when parentAddress is "").
// Otherwise (when parentAddress != ""), child is derived directly from parent.
CreateChildAccount(parentAddress, password string) (address, pubKey string, err error)
// RecoverAccount re-creates master key using given details.
// Once master key is re-generated, it is inserted into keystore (if not already there).
RecoverAccount(password, mnemonic string) (address, pubKey string, err error)
// VerifyAccountPassword tries to decrypt a given account key file, with a provided password.
// If no error is returned, then account is considered verified.
VerifyAccountPassword(keyStoreDir, address, password string) (*keystore.Key, error)
// SelectAccount selects current account, by verifying that address has corresponding account which can be decrypted
// using provided password. Once verification is done, decrypted key is injected into Whisper (as a single identity,
// all previous identities are removed).
SelectAccount(address, password string) error
// ReSelectAccount selects previously selected account, often, after node restart.
ReSelectAccount() error
// SelectedAccount returns currently selected account
SelectedAccount() (*SelectedExtKey, error)
// Logout clears whisper identities
Logout() error
// Accounts returns handler to process account list request
Accounts() ([]common.Address, error)
// AccountsRPCHandler returns RPC wrapper for Accounts()
AccountsRPCHandler() rpc.Handler
// 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.
AddressToDecryptedAccount(address, password string) (accounts.Account, *keystore.Key, error)
}
// TransactionResult is a JSON returned from transaction complete function (used internally) // TransactionResult is a JSON returned from transaction complete function (used internally)
type TransactionResult struct { type TransactionResult struct {
Hash common.Hash Hash common.Hash

View File

@ -10,7 +10,6 @@ import (
accounts "github.com/ethereum/go-ethereum/accounts" accounts "github.com/ethereum/go-ethereum/accounts"
keystore "github.com/ethereum/go-ethereum/accounts/keystore" keystore "github.com/ethereum/go-ethereum/accounts/keystore"
common "github.com/ethereum/go-ethereum/common"
les "github.com/ethereum/go-ethereum/les" les "github.com/ethereum/go-ethereum/les"
node "github.com/ethereum/go-ethereum/node" node "github.com/ethereum/go-ethereum/node"
whisperv6 "github.com/ethereum/go-ethereum/whisper/whisperv6" whisperv6 "github.com/ethereum/go-ethereum/whisper/whisperv6"
@ -215,170 +214,3 @@ func (m *MockNodeManager) RPCClient() *rpc.Client {
func (mr *MockNodeManagerMockRecorder) RPCClient() *gomock.Call { func (mr *MockNodeManagerMockRecorder) RPCClient() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RPCClient", reflect.TypeOf((*MockNodeManager)(nil).RPCClient)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RPCClient", reflect.TypeOf((*MockNodeManager)(nil).RPCClient))
} }
// MockAccountManager is a mock of AccountManager interface
type MockAccountManager struct {
ctrl *gomock.Controller
recorder *MockAccountManagerMockRecorder
}
// MockAccountManagerMockRecorder is the mock recorder for MockAccountManager
type MockAccountManagerMockRecorder struct {
mock *MockAccountManager
}
// NewMockAccountManager creates a new mock instance
func NewMockAccountManager(ctrl *gomock.Controller) *MockAccountManager {
mock := &MockAccountManager{ctrl: ctrl}
mock.recorder = &MockAccountManagerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockAccountManager) EXPECT() *MockAccountManagerMockRecorder {
return m.recorder
}
// CreateAccount mocks base method
func (m *MockAccountManager) CreateAccount(password string) (string, string, string, error) {
ret := m.ctrl.Call(m, "CreateAccount", password)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(string)
ret2, _ := ret[2].(string)
ret3, _ := ret[3].(error)
return ret0, ret1, ret2, ret3
}
// CreateAccount indicates an expected call of CreateAccount
func (mr *MockAccountManagerMockRecorder) CreateAccount(password interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAccount", reflect.TypeOf((*MockAccountManager)(nil).CreateAccount), password)
}
// CreateChildAccount mocks base method
func (m *MockAccountManager) CreateChildAccount(parentAddress, password string) (string, string, error) {
ret := m.ctrl.Call(m, "CreateChildAccount", parentAddress, password)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(string)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// CreateChildAccount indicates an expected call of CreateChildAccount
func (mr *MockAccountManagerMockRecorder) CreateChildAccount(parentAddress, password interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateChildAccount", reflect.TypeOf((*MockAccountManager)(nil).CreateChildAccount), parentAddress, password)
}
// RecoverAccount mocks base method
func (m *MockAccountManager) RecoverAccount(password, mnemonic string) (string, string, error) {
ret := m.ctrl.Call(m, "RecoverAccount", password, mnemonic)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(string)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// RecoverAccount indicates an expected call of RecoverAccount
func (mr *MockAccountManagerMockRecorder) RecoverAccount(password, mnemonic interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecoverAccount", reflect.TypeOf((*MockAccountManager)(nil).RecoverAccount), password, mnemonic)
}
// VerifyAccountPassword mocks base method
func (m *MockAccountManager) VerifyAccountPassword(keyStoreDir, address, password string) (*keystore.Key, error) {
ret := m.ctrl.Call(m, "VerifyAccountPassword", keyStoreDir, address, password)
ret0, _ := ret[0].(*keystore.Key)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// VerifyAccountPassword indicates an expected call of VerifyAccountPassword
func (mr *MockAccountManagerMockRecorder) VerifyAccountPassword(keyStoreDir, address, password interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VerifyAccountPassword", reflect.TypeOf((*MockAccountManager)(nil).VerifyAccountPassword), keyStoreDir, address, password)
}
// SelectAccount mocks base method
func (m *MockAccountManager) SelectAccount(address, password string) error {
ret := m.ctrl.Call(m, "SelectAccount", address, password)
ret0, _ := ret[0].(error)
return ret0
}
// SelectAccount indicates an expected call of SelectAccount
func (mr *MockAccountManagerMockRecorder) SelectAccount(address, password interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectAccount", reflect.TypeOf((*MockAccountManager)(nil).SelectAccount), address, password)
}
// ReSelectAccount mocks base method
func (m *MockAccountManager) ReSelectAccount() error {
ret := m.ctrl.Call(m, "ReSelectAccount")
ret0, _ := ret[0].(error)
return ret0
}
// ReSelectAccount indicates an expected call of ReSelectAccount
func (mr *MockAccountManagerMockRecorder) ReSelectAccount() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReSelectAccount", reflect.TypeOf((*MockAccountManager)(nil).ReSelectAccount))
}
// SelectedAccount mocks base method
func (m *MockAccountManager) SelectedAccount() (*SelectedExtKey, error) {
ret := m.ctrl.Call(m, "SelectedAccount")
ret0, _ := ret[0].(*SelectedExtKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SelectedAccount indicates an expected call of SelectedAccount
func (mr *MockAccountManagerMockRecorder) SelectedAccount() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectedAccount", reflect.TypeOf((*MockAccountManager)(nil).SelectedAccount))
}
// Logout mocks base method
func (m *MockAccountManager) Logout() error {
ret := m.ctrl.Call(m, "Logout")
ret0, _ := ret[0].(error)
return ret0
}
// Logout indicates an expected call of Logout
func (mr *MockAccountManagerMockRecorder) Logout() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Logout", reflect.TypeOf((*MockAccountManager)(nil).Logout))
}
// Accounts mocks base method
func (m *MockAccountManager) Accounts() ([]common.Address, error) {
ret := m.ctrl.Call(m, "Accounts")
ret0, _ := ret[0].([]common.Address)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Accounts indicates an expected call of Accounts
func (mr *MockAccountManagerMockRecorder) Accounts() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Accounts", reflect.TypeOf((*MockAccountManager)(nil).Accounts))
}
// AccountsRPCHandler mocks base method
func (m *MockAccountManager) AccountsRPCHandler() rpc.Handler {
ret := m.ctrl.Call(m, "AccountsRPCHandler")
ret0, _ := ret[0].(rpc.Handler)
return ret0
}
// AccountsRPCHandler indicates an expected call of AccountsRPCHandler
func (mr *MockAccountManagerMockRecorder) AccountsRPCHandler() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccountsRPCHandler", reflect.TypeOf((*MockAccountManager)(nil).AccountsRPCHandler))
}
// AddressToDecryptedAccount mocks base method
func (m *MockAccountManager) AddressToDecryptedAccount(address, password string) (accounts.Account, *keystore.Key, error) {
ret := m.ctrl.Call(m, "AddressToDecryptedAccount", address, password)
ret0, _ := ret[0].(accounts.Account)
ret1, _ := ret[1].(*keystore.Key)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// AddressToDecryptedAccount indicates an expected call of AddressToDecryptedAccount
func (mr *MockAccountManagerMockRecorder) AddressToDecryptedAccount(address, password interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressToDecryptedAccount", reflect.TypeOf((*MockAccountManager)(nil).AddressToDecryptedAccount), address, password)
}

View File

@ -3,7 +3,6 @@ package common
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -13,8 +12,6 @@ import (
"runtime/debug" "runtime/debug"
"time" "time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/pborman/uuid" "github.com/pborman/uuid"
"github.com/status-im/status-go/static" "github.com/status-im/status-go/static"
@ -28,46 +25,9 @@ const (
type contextKey string // in order to make sure that our context key does not collide with keys from other packages type contextKey string // in order to make sure that our context key does not collide with keys from other packages
// errors
var (
ErrInvalidAccountAddressOrKey = errors.New("cannot parse address or key to valid account address")
)
// All general log messages in this package should be routed through this logger. // All general log messages in this package should be routed through this logger.
var logger = log.New("package", "status-go/geth/common") var logger = log.New("package", "status-go/geth/common")
// 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) {
return accounts.Account{Address: common.HexToAddress(account)}, nil
}
return accounts.Account{}, ErrInvalidAccountAddressOrKey
}
// FromAddress 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 {
from, err := ParseAccountString(accountAddress)
if err != nil {
return common.Address{}
}
return from.Address
}
// ToAddress 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 {
to, err := ParseAccountString(accountAddress)
if err != nil {
return nil
}
return &to.Address
}
// ImportTestAccount imports keystore from static resources, see "static/keys" folder // ImportTestAccount imports keystore from static resources, see "static/keys" folder
func ImportTestAccount(keystoreDir, accountFile string) error { func ImportTestAccount(keystoreDir, accountFile string) error {
// make sure that keystore folder exists // make sure that keystore folder exists

View File

@ -0,0 +1,58 @@
package transactions
import (
"reflect"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/golang/mock/gomock"
"github.com/status-im/status-go/geth/account"
)
// MockAccountManager is a mock of AccountManager interface
type MockAccountManager struct {
ctrl *gomock.Controller
recorder *MockAccountManagerMockRecorder
}
// MockAccountManagerMockRecorder is the mock recorder for MockAccountManager
type MockAccountManagerMockRecorder struct {
mock *MockAccountManager
}
// NewMockAccountManager creates a new mock instance
func NewMockAccountManager(ctrl *gomock.Controller) *MockAccountManager {
mock := &MockAccountManager{ctrl: ctrl}
mock.recorder = &MockAccountManagerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockAccountManager) EXPECT() *MockAccountManagerMockRecorder {
return m.recorder
}
// VerifyAccountPassword mocks base method
func (m *MockAccountManager) VerifyAccountPassword(keyStoreDir, address, password string) (*keystore.Key, error) {
ret := m.ctrl.Call(m, "VerifyAccountPassword", keyStoreDir, address, password)
ret0, _ := ret[0].(*keystore.Key)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// VerifyAccountPassword indicates an expected call of VerifyAccountPassword
func (mr *MockAccountManagerMockRecorder) VerifyAccountPassword(keyStoreDir, address, password interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VerifyAccountPassword", reflect.TypeOf((*MockAccountManager)(nil).VerifyAccountPassword), keyStoreDir, address, password)
}
// SelectedAccount mocks base method
func (m *MockAccountManager) SelectedAccount() (*account.SelectedExtKey, error) {
ret := m.ctrl.Call(m, "SelectedAccount")
ret0, _ := ret[0].(*account.SelectedExtKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SelectedAccount indicates an expected call of SelectedAccount
func (mr *MockAccountManagerMockRecorder) SelectedAccount() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectedAccount", reflect.TypeOf((*MockAccountManager)(nil).SelectedAccount))
}

View File

@ -0,0 +1,16 @@
package transactions
import (
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/status-im/status-go/geth/account"
)
// Accounter defines expected methods for managing Status accounts.
type Accounter interface {
// SelectedAccount returns currently selected account
SelectedAccount() (*account.SelectedExtKey, error)
// VerifyAccountPassword tries to decrypt a given account key file, with a provided password.
// If no error is returned, then account is considered verified.
VerifyAccountPassword(keyStoreDir, address, password string) (*keystore.Key, error)
}

View File

@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/status-im/status-go/geth/account"
"github.com/status-im/status-go/geth/common" "github.com/status-im/status-go/geth/common"
"github.com/status-im/status-go/geth/params" "github.com/status-im/status-go/geth/params"
"github.com/status-im/status-go/geth/transactions/queue" "github.com/status-im/status-go/geth/transactions/queue"
@ -29,7 +30,7 @@ const (
// Manager provides means to manage internal Status Backend (injected into LES) // Manager provides means to manage internal Status Backend (injected into LES)
type Manager struct { type Manager struct {
nodeManager common.NodeManager nodeManager common.NodeManager
accountManager common.AccountManager accountManager Accounter
txQueue *queue.TxQueue txQueue *queue.TxQueue
ethTxClient EthTransactor ethTxClient EthTransactor
notify bool notify bool
@ -42,7 +43,7 @@ type Manager struct {
} }
// NewManager returns a new Manager. // NewManager returns a new Manager.
func NewManager(nodeManager common.NodeManager, accountManager common.AccountManager) *Manager { func NewManager(nodeManager common.NodeManager, accountManager Accounter) *Manager {
return &Manager{ return &Manager{
nodeManager: nodeManager, nodeManager: nodeManager,
accountManager: accountManager, accountManager: accountManager,
@ -151,7 +152,7 @@ func (m *Manager) CompleteTransaction(id common.QueuedTxID, password string) (ha
return hash, err return hash, err
} }
func (m *Manager) validateAccount(config *params.NodeConfig, tx *common.QueuedTx, password string) (*common.SelectedExtKey, error) { func (m *Manager) validateAccount(config *params.NodeConfig, tx *common.QueuedTx, password string) (*account.SelectedExtKey, error) {
selectedAccount, err := m.accountManager.SelectedAccount() selectedAccount, err := m.accountManager.SelectedAccount()
if err != nil { if err != nil {
m.log.Warn("failed to get a selected account", "err", err) m.log.Warn("failed to get a selected account", "err", err)
@ -170,7 +171,7 @@ func (m *Manager) validateAccount(config *params.NodeConfig, tx *common.QueuedTx
return selectedAccount, nil return selectedAccount, nil
} }
func (m *Manager) completeTransaction(config *params.NodeConfig, selectedAccount *common.SelectedExtKey, queuedTx *common.QueuedTx) (hash gethcommon.Hash, err error) { func (m *Manager) completeTransaction(config *params.NodeConfig, selectedAccount *account.SelectedExtKey, queuedTx *common.QueuedTx) (hash gethcommon.Hash, err error) {
m.log.Info("complete transaction", "id", queuedTx.ID) m.log.Info("complete transaction", "id", queuedTx.ID)
m.addrLock.LockAddr(queuedTx.Args.From) m.addrLock.LockAddr(queuedTx.Args.From)
var localNonce uint64 var localNonce uint64

View File

@ -18,6 +18,7 @@ import (
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/status-im/status-go/geth/account"
"github.com/status-im/status-go/geth/common" "github.com/status-im/status-go/geth/common"
"github.com/status-im/status-go/geth/params" "github.com/status-im/status-go/geth/params"
"github.com/status-im/status-go/geth/rpc" "github.com/status-im/status-go/geth/rpc"
@ -35,7 +36,7 @@ type TxQueueTestSuite struct {
nodeManagerMockCtrl *gomock.Controller nodeManagerMockCtrl *gomock.Controller
nodeManagerMock *common.MockNodeManager nodeManagerMock *common.MockNodeManager
accountManagerMockCtrl *gomock.Controller accountManagerMockCtrl *gomock.Controller
accountManagerMock *common.MockAccountManager accountManagerMock *MockAccountManager
server *gethrpc.Server server *gethrpc.Server
client *gethrpc.Client client *gethrpc.Client
txServiceMockCtrl *gomock.Controller txServiceMockCtrl *gomock.Controller
@ -51,7 +52,7 @@ func (s *TxQueueTestSuite) SetupTest() {
s.txServiceMockCtrl = gomock.NewController(s.T()) s.txServiceMockCtrl = gomock.NewController(s.T())
s.nodeManagerMock = common.NewMockNodeManager(s.nodeManagerMockCtrl) s.nodeManagerMock = common.NewMockNodeManager(s.nodeManagerMockCtrl)
s.accountManagerMock = common.NewMockAccountManager(s.accountManagerMockCtrl) s.accountManagerMock = NewMockAccountManager(s.accountManagerMockCtrl)
s.server, s.txServiceMock = fake.NewTestServer(s.txServiceMockCtrl) s.server, s.txServiceMock = fake.NewTestServer(s.txServiceMockCtrl)
s.client = gethrpc.DialInProc(s.server) s.client = gethrpc.DialInProc(s.server)
@ -83,7 +84,7 @@ var (
testNonce = hexutil.Uint64(10) testNonce = hexutil.Uint64(10)
) )
func (s *TxQueueTestSuite) setupTransactionPoolAPI(tx *common.QueuedTx, returnNonce, resultNonce hexutil.Uint64, account *common.SelectedExtKey, txErr error) { func (s *TxQueueTestSuite) setupTransactionPoolAPI(tx *common.QueuedTx, returnNonce, resultNonce hexutil.Uint64, account *account.SelectedExtKey, txErr error) {
// Expect calls to gas functions only if there are no user defined values. // Expect calls to gas functions only if there are no user defined values.
// And also set the expected gas and gas price for RLP encoding the expected tx. // And also set the expected gas and gas price for RLP encoding the expected tx.
var usedGas hexutil.Uint64 var usedGas hexutil.Uint64
@ -107,7 +108,7 @@ func (s *TxQueueTestSuite) setupTransactionPoolAPI(tx *common.QueuedTx, returnNo
s.txServiceMock.EXPECT().SendRawTransaction(gomock.Any(), data).Return(gethcommon.Hash{}, txErr) s.txServiceMock.EXPECT().SendRawTransaction(gomock.Any(), data).Return(gethcommon.Hash{}, txErr)
} }
func (s *TxQueueTestSuite) rlpEncodeTx(tx *common.QueuedTx, config *params.NodeConfig, account *common.SelectedExtKey, nonce *hexutil.Uint64, gas hexutil.Uint64, gasPrice *big.Int) hexutil.Bytes { func (s *TxQueueTestSuite) rlpEncodeTx(tx *common.QueuedTx, config *params.NodeConfig, account *account.SelectedExtKey, nonce *hexutil.Uint64, gas hexutil.Uint64, gasPrice *big.Int) hexutil.Bytes {
newTx := types.NewTransaction( newTx := types.NewTransaction(
uint64(*nonce), uint64(*nonce),
gethcommon.Address(*tx.Args.To), gethcommon.Address(*tx.Args.To),
@ -124,7 +125,7 @@ func (s *TxQueueTestSuite) rlpEncodeTx(tx *common.QueuedTx, config *params.NodeC
return hexutil.Bytes(data) return hexutil.Bytes(data)
} }
func (s *TxQueueTestSuite) setupStatusBackend(account *common.SelectedExtKey, password string, passwordErr error) { func (s *TxQueueTestSuite) setupStatusBackend(account *account.SelectedExtKey, password string, passwordErr error) {
s.nodeManagerMock.EXPECT().NodeConfig().Return(s.nodeConfig, nil) s.nodeManagerMock.EXPECT().NodeConfig().Return(s.nodeConfig, nil)
s.accountManagerMock.EXPECT().SelectedAccount().Return(account, nil) s.accountManagerMock.EXPECT().SelectedAccount().Return(account, nil)
s.accountManagerMock.EXPECT().VerifyAccountPassword(s.nodeConfig.KeyStoreDir, account.Address.String(), password).Return( s.accountManagerMock.EXPECT().VerifyAccountPassword(s.nodeConfig.KeyStoreDir, account.Address.String(), password).Return(
@ -134,8 +135,8 @@ func (s *TxQueueTestSuite) setupStatusBackend(account *common.SelectedExtKey, pa
func (s *TxQueueTestSuite) TestCompleteTransaction() { func (s *TxQueueTestSuite) TestCompleteTransaction() {
password := TestConfig.Account1.Password password := TestConfig.Account1.Password
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
account := &common.SelectedExtKey{ selectedAccount := &account.SelectedExtKey{
Address: common.FromAddress(TestConfig.Account1.Address), Address: account.FromAddress(TestConfig.Account1.Address),
AccountKey: &keystore.Key{PrivateKey: key}, AccountKey: &keystore.Key{PrivateKey: key},
} }
testCases := []struct { testCases := []struct {
@ -168,14 +169,14 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
for _, testCase := range testCases { for _, testCase := range testCases {
s.T().Run(testCase.name, func(t *testing.T) { s.T().Run(testCase.name, func(t *testing.T) {
s.SetupTest() s.SetupTest()
s.setupStatusBackend(account, password, nil) s.setupStatusBackend(selectedAccount, password, nil)
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Gas: testCase.gas, Gas: testCase.gas,
GasPrice: testCase.gasPrice, GasPrice: testCase.gasPrice,
}) })
s.setupTransactionPoolAPI(tx, testNonce, testNonce, account, nil) s.setupTransactionPoolAPI(tx, testNonce, testNonce, selectedAccount, nil)
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
w := make(chan struct{}) w := make(chan struct{})
@ -203,18 +204,18 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
func (s *TxQueueTestSuite) TestCompleteTransactionMultipleTimes() { func (s *TxQueueTestSuite) TestCompleteTransactionMultipleTimes() {
password := TestConfig.Account1.Password password := TestConfig.Account1.Password
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
account := &common.SelectedExtKey{ selectedAccount := &account.SelectedExtKey{
Address: common.FromAddress(TestConfig.Account1.Address), Address: account.FromAddress(TestConfig.Account1.Address),
AccountKey: &keystore.Key{PrivateKey: key}, AccountKey: &keystore.Key{PrivateKey: key},
} }
s.setupStatusBackend(account, password, nil) s.setupStatusBackend(selectedAccount, password, nil)
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.setupTransactionPoolAPI(tx, testNonce, testNonce, account, nil) s.setupTransactionPoolAPI(tx, testNonce, testNonce, selectedAccount, nil)
err := s.manager.QueueTransaction(tx) err := s.manager.QueueTransaction(tx)
s.NoError(err) s.NoError(err)
@ -257,13 +258,13 @@ func (s *TxQueueTestSuite) TestCompleteTransactionMultipleTimes() {
func (s *TxQueueTestSuite) TestAccountMismatch() { func (s *TxQueueTestSuite) TestAccountMismatch() {
s.nodeManagerMock.EXPECT().NodeConfig().Return(s.nodeConfig, nil) s.nodeManagerMock.EXPECT().NodeConfig().Return(s.nodeConfig, nil)
s.accountManagerMock.EXPECT().SelectedAccount().Return(&common.SelectedExtKey{ s.accountManagerMock.EXPECT().SelectedAccount().Return(&account.SelectedExtKey{
Address: common.FromAddress(TestConfig.Account2.Address), Address: account.FromAddress(TestConfig.Account2.Address),
}, nil) }, nil)
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
@ -279,14 +280,14 @@ func (s *TxQueueTestSuite) TestAccountMismatch() {
func (s *TxQueueTestSuite) TestInvalidPassword() { func (s *TxQueueTestSuite) TestInvalidPassword() {
password := "invalid-password" password := "invalid-password"
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
account := &common.SelectedExtKey{ selectedAccount := &account.SelectedExtKey{
Address: common.FromAddress(TestConfig.Account1.Address), Address: account.FromAddress(TestConfig.Account1.Address),
AccountKey: &keystore.Key{PrivateKey: key}, AccountKey: &keystore.Key{PrivateKey: key},
} }
s.setupStatusBackend(account, password, keystore.ErrDecrypt) s.setupStatusBackend(selectedAccount, password, keystore.ErrDecrypt)
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
@ -300,8 +301,8 @@ func (s *TxQueueTestSuite) TestInvalidPassword() {
func (s *TxQueueTestSuite) TestDiscardTransaction() { func (s *TxQueueTestSuite) TestDiscardTransaction() {
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
@ -320,8 +321,8 @@ func (s *TxQueueTestSuite) TestDiscardTransaction() {
func (s *TxQueueTestSuite) TestCompletionTimedOut() { func (s *TxQueueTestSuite) TestCompletionTimedOut() {
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
@ -340,21 +341,21 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
txCount := 3 txCount := 3
password := TestConfig.Account1.Password password := TestConfig.Account1.Password
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
account := &common.SelectedExtKey{ selectedAccount := &account.SelectedExtKey{
Address: common.FromAddress(TestConfig.Account1.Address), Address: account.FromAddress(TestConfig.Account1.Address),
AccountKey: &keystore.Key{PrivateKey: key}, AccountKey: &keystore.Key{PrivateKey: key},
} }
// setup call expectations for 5 transactions in total // setup call expectations for 5 transactions in total
for i := 0; i < txCount+2; i++ { for i := 0; i < txCount+2; i++ {
s.setupStatusBackend(account, password, nil) s.setupStatusBackend(selectedAccount, password, nil)
} }
nonce := hexutil.Uint64(0) nonce := hexutil.Uint64(0)
for i := 0; i < txCount; i++ { for i := 0; i < txCount; i++ {
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.setupTransactionPoolAPI(tx, nonce, hexutil.Uint64(i), account, nil) s.setupTransactionPoolAPI(tx, nonce, hexutil.Uint64(i), selectedAccount, nil)
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
hash, err := s.manager.CompleteTransaction(tx.ID, password) hash, err := s.manager.CompleteTransaction(tx.ID, password)
rst := s.manager.WaitForTransaction(tx) rst := s.manager.WaitForTransaction(tx)
@ -367,10 +368,10 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
} }
nonce = hexutil.Uint64(5) nonce = hexutil.Uint64(5)
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{ tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.setupTransactionPoolAPI(tx, nonce, nonce, account, nil) s.setupTransactionPoolAPI(tx, nonce, nonce, selectedAccount, nil)
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
hash, err := s.manager.CompleteTransaction(tx.ID, password) hash, err := s.manager.CompleteTransaction(tx.ID, password)
rst := s.manager.WaitForTransaction(tx) rst := s.manager.WaitForTransaction(tx)
@ -381,10 +382,10 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
s.Equal(uint64(nonce)+1, resultNonce.(uint64)) s.Equal(uint64(nonce)+1, resultNonce.(uint64))
testErr := errors.New("test") testErr := errors.New("test")
s.txServiceMock.EXPECT().GetTransactionCount(gomock.Any(), account.Address, gethrpc.PendingBlockNumber).Return(nil, testErr) s.txServiceMock.EXPECT().GetTransactionCount(gomock.Any(), selectedAccount.Address, gethrpc.PendingBlockNumber).Return(nil, testErr)
tx = common.CreateTransaction(context.Background(), common.SendTxArgs{ tx = common.CreateTransaction(context.Background(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
}) })
s.NoError(s.manager.QueueTransaction(tx)) s.NoError(s.manager.QueueTransaction(tx))
_, err = s.manager.CompleteTransaction(tx.ID, password) _, err = s.manager.CompleteTransaction(tx.ID, password)

View File

@ -410,7 +410,7 @@ func testCreateChildAccount(t *testing.T) bool { //nolint: gocyclo
address, pubKey, mnemonic := createAccountResponse.Address, createAccountResponse.PubKey, createAccountResponse.Mnemonic address, pubKey, mnemonic := createAccountResponse.Address, createAccountResponse.PubKey, createAccountResponse.Mnemonic
t.Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic) t.Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic)
acct, err := common.ParseAccountString(address) acct, err := account.ParseAccountString(address)
if err != nil { if err != nil {
t.Errorf("can not get account from address: %v", err) t.Errorf("can not get account from address: %v", err)
return false return false
@ -548,7 +548,7 @@ func testRecoverAccount(t *testing.T) bool { //nolint: gocyclo
} }
// now test recovering, but make sure that account/key file is removed i.e. simulate recovering on a new device // now test recovering, but make sure that account/key file is removed i.e. simulate recovering on a new device
account, err := common.ParseAccountString(address) account, err := account.ParseAccountString(address)
if err != nil { if err != nil {
t.Errorf("can not get account from address: %v", err) t.Errorf("can not get account from address: %v", err)
} }
@ -819,8 +819,8 @@ func testCompleteTransaction(t *testing.T) bool {
// this call blocks, up until Complete Transaction is called // this call blocks, up until Complete Transaction is called
txCheckHash, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{ txCheckHash, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
if err != nil { if err != nil {
@ -884,8 +884,8 @@ func testCompleteMultipleQueuedTransactions(t *testing.T) bool { //nolint: gocyc
// this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called // this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called
sendTx := func() { sendTx := func() {
txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
if err != nil { if err != nil {
@ -1067,8 +1067,8 @@ func testDiscardTransaction(t *testing.T) bool { //nolint: gocyclo
// this call blocks, and should return when DiscardQueuedTransaction() is called // this call blocks, and should return when DiscardQueuedTransaction() is called
txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
if err != transactions.ErrQueuedTxDiscarded { if err != transactions.ErrQueuedTxDiscarded {
@ -1158,8 +1158,8 @@ func testDiscardMultipleQueuedTransactions(t *testing.T) bool { //nolint: gocycl
// this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called // this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called
sendTx := func() { sendTx := func() {
txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
if err != transactions.ErrQueuedTxDiscarded { if err != transactions.ErrQueuedTxDiscarded {

View File

@ -23,7 +23,7 @@ func (s *AccountsTestSuite) TestRPCEthAccounts() {
defer s.StopTestBackend() defer s.StopTestBackend()
// log into test account // log into test account
err := s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) err := s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
rpcClient := s.Backend.NodeManager().RPCClient() rpcClient := s.Backend.NodeManager().RPCClient()
@ -50,7 +50,7 @@ func (s *AccountsTestSuite) TestRPCEthAccountsWithUpstream() {
defer s.StopTestBackend() defer s.StopTestBackend()
// log into test account // log into test account
err = s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) err = s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
rpcClient := s.Backend.NodeManager().RPCClient() rpcClient := s.Backend.NodeManager().RPCClient()

View File

@ -6,7 +6,6 @@ import (
"testing" "testing"
"github.com/status-im/status-go/geth/account" "github.com/status-im/status-go/geth/account"
"github.com/status-im/status-go/geth/common"
e2e "github.com/status-im/status-go/t/e2e" e2e "github.com/status-im/status-go/t/e2e"
. "github.com/status-im/status-go/t/utils" . "github.com/status-im/status-go/t/utils"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
@ -40,7 +39,7 @@ func (s *AccountsTestSuite) TestAccountsList() {
s.Zero(len(accounts), "accounts returned, while there should be none (we haven't logged in yet)") s.Zero(len(accounts), "accounts returned, while there should be none (we haven't logged in yet)")
// select account (sub-accounts will be created for this key) // select account (sub-accounts will be created for this key)
err = s.Backend.AccountManager().SelectAccount(address, TestConfig.Account1.Password) err = s.Backend.SelectAccount(address, TestConfig.Account1.Password)
s.NoError(err, "account selection failed") s.NoError(err, "account selection failed")
// at this point main account should show up // at this point main account should show up
@ -94,7 +93,7 @@ func (s *AccountsTestSuite) TestCreateChildAccount() {
s.NoError(err) s.NoError(err)
s.T().Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic) s.T().Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic)
acct, err := common.ParseAccountString(address) acct, err := account.ParseAccountString(address)
s.NoError(err, "can not get account from address") s.NoError(err, "can not get account from address")
// obtain decrypted key, and make sure that extended key (which will be used as root for sub-accounts) is present // obtain decrypted key, and make sure that extended key (which will be used as root for sub-accounts) is present
@ -106,7 +105,7 @@ func (s *AccountsTestSuite) TestCreateChildAccount() {
_, _, err = s.Backend.AccountManager().CreateChildAccount("", TestConfig.Account1.Password) _, _, err = s.Backend.AccountManager().CreateChildAccount("", TestConfig.Account1.Password)
s.EqualError(account.ErrNoAccountSelected, err.Error(), "expected error is not returned (tried to create sub-account w/o login)") s.EqualError(account.ErrNoAccountSelected, err.Error(), "expected error is not returned (tried to create sub-account w/o login)")
err = s.Backend.AccountManager().SelectAccount(address, TestConfig.Account1.Password) err = s.Backend.SelectAccount(address, TestConfig.Account1.Password)
s.NoError(err, "cannot select account") s.NoError(err, "cannot select account")
// try to create sub-account with wrong password // try to create sub-account with wrong password
@ -147,7 +146,7 @@ func (s *AccountsTestSuite) TestRecoverAccount() {
s.False(address != addressCheck || pubKey != pubKeyCheck, "incorrect accound details recovered") s.False(address != addressCheck || pubKey != pubKeyCheck, "incorrect accound details recovered")
// now test recovering, but make sure that acc/key file is removed i.e. simulate recovering on a new device // now test recovering, but make sure that acc/key file is removed i.e. simulate recovering on a new device
acc, err := common.ParseAccountString(address) acc, err := account.ParseAccountString(address)
s.NoError(err, "can not get acc from address") s.NoError(err, "can not get acc from address")
acc, key, err := keyStore.AccountDecryptedKey(acc, TestConfig.Account1.Password) acc, key, err := keyStore.AccountDecryptedKey(acc, TestConfig.Account1.Password)
@ -177,7 +176,7 @@ func (s *AccountsTestSuite) TestRecoverAccount() {
// make sure that identity is not (yet injected) // make sure that identity is not (yet injected)
s.False(whisperService.HasKeyPair(pubKeyCheck), "identity already present in whisper") s.False(whisperService.HasKeyPair(pubKeyCheck), "identity already present in whisper")
s.NoError(s.Backend.AccountManager().SelectAccount(addressCheck, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(addressCheck, TestConfig.Account1.Password))
s.True(whisperService.HasKeyPair(pubKeyCheck), "identity not injected into whisper") s.True(whisperService.HasKeyPair(pubKeyCheck), "identity not injected into whisper")
} }
@ -201,17 +200,17 @@ func (s *AccountsTestSuite) TestSelectAccount() {
s.False(whisperService.HasKeyPair(pubKey1), "identity already present in whisper") s.False(whisperService.HasKeyPair(pubKey1), "identity already present in whisper")
// try selecting with wrong password // try selecting with wrong password
err = s.Backend.AccountManager().SelectAccount(address1, "wrongPassword") err = s.Backend.SelectAccount(address1, "wrongPassword")
expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase") expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase")
s.EqualError(expectedErr, err.Error(), "select account is expected to throw error: wrong password used") s.EqualError(expectedErr, err.Error(), "select account is expected to throw error: wrong password used")
err = s.Backend.AccountManager().SelectAccount(address1, TestConfig.Account1.Password) err = s.Backend.SelectAccount(address1, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
s.True(whisperService.HasKeyPair(pubKey1), "identity not injected into whisper") s.True(whisperService.HasKeyPair(pubKey1), "identity not injected into whisper")
// select another account, make sure that previous account is wiped out from Whisper cache // select another account, make sure that previous account is wiped out from Whisper cache
s.False(whisperService.HasKeyPair(pubKey2), "identity already present in whisper") s.False(whisperService.HasKeyPair(pubKey2), "identity already present in whisper")
s.NoError(s.Backend.AccountManager().SelectAccount(address2, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(address2, TestConfig.Account1.Password))
s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper")
s.False(whisperService.HasKeyPair(pubKey1), "identity should be removed, but it is still present in whisper") s.False(whisperService.HasKeyPair(pubKey1), "identity should be removed, but it is still present in whisper")
} }
@ -237,16 +236,16 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() {
s.Nil(selectedAccount) s.Nil(selectedAccount)
// select account // select account
err = s.Backend.AccountManager().SelectAccount(address1, "wrongPassword") err = s.Backend.SelectAccount(address1, "wrongPassword")
expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase") expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase")
s.EqualError(expectedErr, err.Error()) s.EqualError(expectedErr, err.Error())
s.NoError(s.Backend.AccountManager().SelectAccount(address1, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(address1, TestConfig.Account1.Password))
s.True(whisperService.HasKeyPair(pubKey1), "identity not injected into whisper") s.True(whisperService.HasKeyPair(pubKey1), "identity not injected into whisper")
// select another account, make sure that previous account is wiped out from Whisper cache // select another account, make sure that previous account is wiped out from Whisper cache
s.False(whisperService.HasKeyPair(pubKey2), "identity already present in whisper") s.False(whisperService.HasKeyPair(pubKey2), "identity already present in whisper")
s.NoError(s.Backend.AccountManager().SelectAccount(address2, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(address2, TestConfig.Account1.Password))
s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper")
s.False(whisperService.HasKeyPair(pubKey1), "identity should be removed, but it is still present in whisper") s.False(whisperService.HasKeyPair(pubKey1), "identity should be removed, but it is still present in whisper")

View File

@ -104,7 +104,7 @@ func (s *APIBackendTestSuite) TestRaceConditions() {
// SelectAccount // SelectAccount
log.Info("CreateAccount()") log.Info("CreateAccount()")
err = s.Backend.AccountManager().SelectAccount(address, "password") err = s.Backend.SelectAccount(address, "password")
s.T().Logf("SelectAccount(%v, %v), error: %v", address, "password", err) s.T().Logf("SelectAccount(%v, %v), error: %v", address, "password", err)
// CreateChildAccount // CreateChildAccount

View File

@ -131,7 +131,7 @@ func (s *JailRPCTestSuite) TestContractDeployment() {
event := envelope.Event.(map[string]interface{}) event := envelope.Event.(map[string]interface{})
s.T().Logf("transaction queued and will be completed shortly, id: %v", event["id"]) s.T().Logf("transaction queued and will be completed shortly, id: %v", event["id"])
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
txID := event["id"].(string) txID := event["id"].(string)
var txErr error var txErr error
@ -197,7 +197,7 @@ func (s *JailRPCTestSuite) TestJailVMPersistence() {
EnsureNodeSync(s.Backend.NodeManager()) EnsureNodeSync(s.Backend.NodeManager())
// log into account from which transactions will be sent // log into account from which transactions will be sent
err := s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) err := s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)
s.NoError(err, "cannot select account: %v", TestConfig.Account1.Address) s.NoError(err, "cannot select account: %v", TestConfig.Account1.Address)
type testCase struct { type testCase struct {

View File

@ -39,7 +39,7 @@ func (s *TransactionsTestSuite) TestCallRPCSendTransaction() {
EnsureNodeSync(s.Backend.NodeManager()) EnsureNodeSync(s.Backend.NodeManager())
err := s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) err := s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
transactionCompleted := make(chan struct{}) transactionCompleted := make(chan struct{})
@ -91,7 +91,7 @@ func (s *TransactionsTestSuite) TestCallRPCSendTransactionUpstream() {
s.StartTestBackend(e2e.WithUpstream(addr)) s.StartTestBackend(e2e.WithUpstream(addr))
defer s.StopTestBackend() defer s.StopTestBackend()
err = s.Backend.AccountManager().SelectAccount(TestConfig.Account2.Address, TestConfig.Account2.Password) err = s.Backend.SelectAccount(TestConfig.Account2.Address, TestConfig.Account2.Password)
s.NoError(err) s.NoError(err)
transactionCompleted := make(chan struct{}) transactionCompleted := make(chan struct{})
@ -176,7 +176,7 @@ func (s *TransactionsTestSuite) TestSendContractTx() {
// the second call will also fail (we are logged in as different user) // the second call will also fail (we are logged in as different user)
log.Info("trying to complete with invalid user") log.Info("trying to complete with invalid user")
err = s.Backend.AccountManager().SelectAccount(sampleAddress, TestConfig.Account1.Password) err = s.Backend.SelectAccount(sampleAddress, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
txHash, err = s.Backend.CompleteTransaction( txHash, err = s.Backend.CompleteTransaction(
common.QueuedTxID(event["id"].(string)), common.QueuedTxID(event["id"].(string)),
@ -190,7 +190,7 @@ func (s *TransactionsTestSuite) TestSendContractTx() {
// the third call will work as expected (as we are logged in with correct credentials) // the third call will work as expected (as we are logged in with correct credentials)
log.Info("trying to complete with correct user, this should succeed") log.Info("trying to complete with correct user, this should succeed")
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
txHash, err = s.Backend.CompleteTransaction( txHash, err = s.Backend.CompleteTransaction(
common.QueuedTxID(event["id"].(string)), common.QueuedTxID(event["id"].(string)),
TestConfig.Account1.Password, TestConfig.Account1.Password,
@ -209,7 +209,7 @@ func (s *TransactionsTestSuite) TestSendContractTx() {
gas := uint64(params.DefaultGas) gas := uint64(params.DefaultGas)
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: nil, // marker, contract creation is expected To: nil, // marker, contract creation is expected
//Value: (*hexutil.Big)(new(big.Int).Mul(big.NewInt(1), gethcommon.Ether)), //Value: (*hexutil.Big)(new(big.Int).Mul(big.NewInt(1), gethcommon.Ether)),
Gas: (*hexutil.Uint64)(&gas), Gas: (*hexutil.Uint64)(&gas),
@ -265,7 +265,7 @@ func (s *TransactionsTestSuite) TestSendEther() {
// the second call will also fail (we are logged in as different user) // the second call will also fail (we are logged in as different user)
log.Info("trying to complete with invalid user") log.Info("trying to complete with invalid user")
err = s.Backend.AccountManager().SelectAccount(sampleAddress, TestConfig.Account1.Password) err = s.Backend.SelectAccount(sampleAddress, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
txHash, err = s.Backend.CompleteTransaction( txHash, err = s.Backend.CompleteTransaction(
common.QueuedTxID(event["id"].(string)), TestConfig.Account1.Password) common.QueuedTxID(event["id"].(string)), TestConfig.Account1.Password)
@ -277,7 +277,7 @@ func (s *TransactionsTestSuite) TestSendEther() {
// the third call will work as expected (as we are logged in with correct credentials) // the third call will work as expected (as we are logged in with correct credentials)
log.Info("trying to complete with correct user, this should succeed") log.Info("trying to complete with correct user, this should succeed")
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
txHash, err = s.Backend.CompleteTransaction( txHash, err = s.Backend.CompleteTransaction(
common.QueuedTxID(event["id"].(string)), common.QueuedTxID(event["id"].(string)),
TestConfig.Account1.Password, TestConfig.Account1.Password,
@ -291,8 +291,8 @@ func (s *TransactionsTestSuite) TestSendEther() {
// this call blocks, up until Complete Transaction is called // this call blocks, up until Complete Transaction is called
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
s.NoError(err, "cannot send transaction") s.NoError(err, "cannot send transaction")
@ -318,7 +318,7 @@ func (s *TransactionsTestSuite) TestSendEtherTxUpstream() {
s.StartTestBackend(e2e.WithUpstream(addr)) s.StartTestBackend(e2e.WithUpstream(addr))
defer s.StopTestBackend() defer s.StopTestBackend()
err = s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) err = s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
completeQueuedTransaction := make(chan struct{}) completeQueuedTransaction := make(chan struct{})
@ -348,8 +348,8 @@ func (s *TransactionsTestSuite) TestSendEtherTxUpstream() {
// This call blocks, up until Complete Transaction is called. // This call blocks, up until Complete Transaction is called.
// Explicitly not setting Gas to get it estimated. // Explicitly not setting Gas to get it estimated.
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
GasPrice: (*hexutil.Big)(big.NewInt(28000000000)), GasPrice: (*hexutil.Big)(big.NewInt(28000000000)),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
@ -372,7 +372,7 @@ func (s *TransactionsTestSuite) TestDoubleCompleteQueuedTransactions() {
EnsureNodeSync(s.Backend.NodeManager()) EnsureNodeSync(s.Backend.NodeManager())
// log into account from which transactions will be sent // log into account from which transactions will be sent
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
completeQueuedTransaction := make(chan struct{}) completeQueuedTransaction := make(chan struct{})
@ -421,8 +421,8 @@ func (s *TransactionsTestSuite) TestDoubleCompleteQueuedTransactions() {
// this call blocks, and should return on *second* attempt to CompleteTransaction (w/ the correct password) // this call blocks, and should return on *second* attempt to CompleteTransaction (w/ the correct password)
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
s.NoError(err, "cannot send transaction") s.NoError(err, "cannot send transaction")
@ -449,7 +449,7 @@ func (s *TransactionsTestSuite) TestDiscardQueuedTransaction() {
s.Backend.TxQueueManager().TransactionQueue().Reset() s.Backend.TxQueueManager().TransactionQueue().Reset()
// log into account from which transactions will be sent // log into account from which transactions will be sent
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
completeQueuedTransaction := make(chan struct{}) completeQueuedTransaction := make(chan struct{})
@ -499,8 +499,8 @@ func (s *TransactionsTestSuite) TestDiscardQueuedTransaction() {
// this call blocks, and should return when DiscardQueuedTransaction() is called // this call blocks, and should return when DiscardQueuedTransaction() is called
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
s.EqualError(err, transactions.ErrQueuedTxDiscarded.Error(), "transaction is expected to be discarded") s.EqualError(err, transactions.ErrQueuedTxDiscarded.Error(), "transaction is expected to be discarded")
@ -523,7 +523,7 @@ func (s *TransactionsTestSuite) TestCompleteMultipleQueuedTransactions() {
s.TxQueueManager().TransactionQueue().Reset() s.TxQueueManager().TransactionQueue().Reset()
// log into account from which transactions will be sent // log into account from which transactions will be sent
err := s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) err := s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
s.sendConcurrentTransactions(3) s.sendConcurrentTransactions(3)
@ -539,7 +539,7 @@ func (s *TransactionsTestSuite) TestDiscardMultipleQueuedTransactions() {
s.Backend.TxQueueManager().TransactionQueue().Reset() s.Backend.TxQueueManager().TransactionQueue().Reset()
// log into account from which transactions will be sent // log into account from which transactions will be sent
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
testTxCount := 3 testTxCount := 3
txIDs := make(chan common.QueuedTxID, testTxCount) txIDs := make(chan common.QueuedTxID, testTxCount)
@ -584,8 +584,8 @@ func (s *TransactionsTestSuite) TestDiscardMultipleQueuedTransactions() {
// this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called // this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called
sendTx := func() { sendTx := func() {
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
require.EqualError(err, transactions.ErrQueuedTxDiscarded.Error()) require.EqualError(err, transactions.ErrQueuedTxDiscarded.Error())
@ -650,7 +650,7 @@ func (s *TransactionsTestSuite) TestNonExistentQueuedTransactions() {
defer s.StopTestBackend() defer s.StopTestBackend()
// log into account from which transactions will be sent // log into account from which transactions will be sent
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
// replace transaction notification handler // replace transaction notification handler
signal.SetDefaultNodeNotificationHandler(func(string) {}) signal.SetDefaultNodeNotificationHandler(func(string) {})
@ -688,7 +688,7 @@ func (s *TransactionsTestSuite) TestEvictionOfQueuedTransactions() {
s.Backend.TxQueueManager().TransactionQueue().Reset() s.Backend.TxQueueManager().TransactionQueue().Reset()
// log into account from which transactions will be sent // log into account from which transactions will be sent
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
txQueue := s.Backend.TxQueueManager().TransactionQueue() txQueue := s.Backend.TxQueueManager().TransactionQueue()
s.Zero(txQueue.Count(), "transaction count should be zero") s.Zero(txQueue.Count(), "transaction count should be zero")
@ -721,7 +721,7 @@ func (s *TransactionsTestSuite) TestCompleteMultipleQueuedTransactionsUpstream()
s.TxQueueManager().TransactionQueue().Reset() s.TxQueueManager().TransactionQueue().Reset()
// log into account from which transactions will be sent // log into account from which transactions will be sent
err := s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password) err := s.Backend.SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
s.sendConcurrentTransactions(30) s.sendConcurrentTransactions(30)
@ -767,8 +767,8 @@ func (s *TransactionsTestSuite) sendConcurrentTransactions(testTxCount int) {
// this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called // this call blocks, and should return when DiscardQueuedTransaction() for a given tx id is called
sendTx := func() { sendTx := func() {
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{ txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
From: common.FromAddress(TestConfig.Account1.Address), From: account.FromAddress(TestConfig.Account1.Address),
To: common.ToAddress(TestConfig.Account2.Address), To: account.ToAddress(TestConfig.Account2.Address),
Value: (*hexutil.Big)(big.NewInt(1000000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)),
}) })
require.NoError(err, "cannot send transaction") require.NoError(err, "cannot send transaction")

View File

@ -92,26 +92,3 @@ func (s *WhisperTestSuite) TestWhisperFilterRace() {
<-allFiltersAdded <-allFiltersAdded
} }
func (s *WhisperTestSuite) TestLogout() {
s.StartTestNode()
defer s.StopTestNode()
whisperService, err := s.NodeManager.WhisperService()
s.NoError(err)
accountManager := account.NewManager(s.NodeManager)
s.NotNil(accountManager)
// create an account
address, pubKey, _, err := accountManager.CreateAccount(TestConfig.Account1.Password)
s.NoError(err)
// make sure that identity doesn't exist (yet) in Whisper
s.False(whisperService.HasKeyPair(pubKey), "identity already present in whisper")
s.NoError(accountManager.SelectAccount(address, TestConfig.Account1.Password))
s.True(whisperService.HasKeyPair(pubKey), "identity not injected into whisper")
s.NoError(accountManager.Logout())
s.False(whisperService.HasKeyPair(pubKey), "identity not cleared from whisper")
}