[#issue-403] Account package cleanup
This commit is contained in:
parent
01769e9ee8
commit
18fbebc942
|
@ -1,7 +1,6 @@
|
|||
package account
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -14,30 +13,32 @@ import (
|
|||
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/status-im/status-go/extkeys"
|
||||
"github.com/status-im/status-go/geth/common"
|
||||
"github.com/status-im/status-go/geth/rpc"
|
||||
)
|
||||
|
||||
// errors
|
||||
var (
|
||||
ErrAddressToAccountMappingFailure = errors.New("cannot retrieve a valid account for a given address")
|
||||
ErrAccountToKeyMappingFailure = errors.New("cannot retrieve a valid key for a given account")
|
||||
ErrWhisperIdentityInjectionFailure = errors.New("failed to inject identity into Whisper")
|
||||
ErrWhisperClearIdentitiesFailure = errors.New("failed to clear whisper identities")
|
||||
ErrNoAccountSelected = errors.New("no account has been selected, please login")
|
||||
ErrInvalidMasterKeyCreated = errors.New("can not create master extended key")
|
||||
)
|
||||
|
||||
// Manager represents account manager interface
|
||||
type Manager struct {
|
||||
nodeManager common.NodeManager
|
||||
selectedAccount *common.SelectedExtKey // account that was processed during the last call to SelectAccount()
|
||||
// GethServiceProvider provides required geth services.
|
||||
type GethServiceProvider interface {
|
||||
AccountManager() (*accounts.Manager, error)
|
||||
AccountKeyStore() (*keystore.KeyStore, error)
|
||||
}
|
||||
|
||||
// NewManager returns new node account manager
|
||||
func NewManager(nodeManager common.NodeManager) *Manager {
|
||||
// Manager represents account manager interface.
|
||||
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{
|
||||
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 "").
|
||||
// Otherwise (when parentAddress != ""), child is derived directly from parent.
|
||||
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 {
|
||||
return "", "", err
|
||||
}
|
||||
|
@ -85,7 +86,7 @@ func (m *Manager) CreateChildAccount(parentAddress, password string) (address, p
|
|||
return "", "", ErrNoAccountSelected
|
||||
}
|
||||
|
||||
account, err := common.ParseAccountString(parentAddress)
|
||||
account, err := ParseAccountString(parentAddress)
|
||||
if err != nil {
|
||||
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
|
||||
// using provided password. Once verification is done, decrypted key is injected into Whisper (as a single identity,
|
||||
// all previous identities are removed).
|
||||
// using provided password. Once verification is done, all previous identities are removed).
|
||||
func (m *Manager) SelectAccount(address, password string) error {
|
||||
keyStore, err := m.nodeManager.AccountKeyStore()
|
||||
keyStore, err := m.geth.AccountKeyStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
account, err := common.ParseAccountString(address)
|
||||
account, err := ParseAccountString(address)
|
||||
if err != nil {
|
||||
return ErrAddressToAccountMappingFailure
|
||||
}
|
||||
|
@ -221,22 +221,12 @@ func (m *Manager) SelectAccount(address, password string) error {
|
|||
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
|
||||
subAccounts, err := m.findSubAccounts(accountKey.ExtendedKey, accountKey.SubAccountIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.selectedAccount = &common.SelectedExtKey{
|
||||
m.selectedAccount = &SelectedExtKey{
|
||||
Address: account.Address,
|
||||
AccountKey: accountKey,
|
||||
SubAccounts: subAccounts,
|
||||
|
@ -246,44 +236,15 @@ func (m *Manager) SelectAccount(address, password string) error {
|
|||
}
|
||||
|
||||
// SelectedAccount returns currently selected account
|
||||
func (m *Manager) SelectedAccount() (*common.SelectedExtKey, error) {
|
||||
func (m *Manager) SelectedAccount() (*SelectedExtKey, error) {
|
||||
if m.selectedAccount == nil {
|
||||
return nil, ErrNoAccountSelected
|
||||
}
|
||||
return m.selectedAccount, nil
|
||||
}
|
||||
|
||||
// ReSelectAccount selects previously selected account, often, after node restart.
|
||||
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
|
||||
// Logout clears selectedAccount.
|
||||
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
|
||||
|
||||
return nil
|
||||
|
@ -292,7 +253,7 @@ func (m *Manager) Logout() error {
|
|||
// 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.
|
||||
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 {
|
||||
return "", "", err
|
||||
}
|
||||
|
@ -317,7 +278,7 @@ func (m *Manager) importExtendedKey(extKey *extkeys.ExtendedKey, password string
|
|||
// Accounts returns list of addresses for selected account, including
|
||||
// subaccounts.
|
||||
func (m *Manager) Accounts() ([]gethcommon.Address, error) {
|
||||
am, err := m.nodeManager.AccountManager()
|
||||
am, err := m.geth.AccountManager()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -353,13 +314,6 @@ func (m *Manager) Accounts() ([]gethcommon.Address, error) {
|
|||
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)
|
||||
func (m *Manager) refreshSelectedAccount() {
|
||||
if m.selectedAccount == nil {
|
||||
|
@ -376,7 +330,7 @@ func (m *Manager) refreshSelectedAccount() {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
m.selectedAccount = &common.SelectedExtKey{
|
||||
m.selectedAccount = &SelectedExtKey{
|
||||
Address: m.selectedAccount.Address,
|
||||
AccountKey: m.selectedAccount.AccountKey,
|
||||
SubAccounts: subAccounts,
|
||||
|
@ -387,7 +341,7 @@ func (m *Manager) refreshSelectedAccount() {
|
|||
// that belong to the currently selected 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) {
|
||||
keyStore, err := m.nodeManager.AccountKeyStore()
|
||||
keyStore, err := m.geth.AccountKeyStore()
|
||||
if err != nil {
|
||||
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
|
||||
// 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) {
|
||||
keyStore, err := m.nodeManager.AccountKeyStore()
|
||||
keyStore, err := m.geth.AccountKeyStore()
|
||||
if err != nil {
|
||||
return accounts.Account{}, nil, err
|
||||
}
|
||||
|
||||
account, err := common.ParseAccountString(address)
|
||||
account, err := ParseAccountString(address)
|
||||
if err != nil {
|
||||
return accounts.Account{}, nil, ErrAddressToAccountMappingFailure
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/status-im/status-go/geth/common"
|
||||
. "github.com/status-im/status-go/t/utils"
|
||||
|
@ -115,7 +114,6 @@ func TestVerifyAccountPasswordWithAccountBeforeEIP55(t *testing.T) {
|
|||
}
|
||||
|
||||
var (
|
||||
errWhisper = errors.New("Can't return a whisper service")
|
||||
errKeyStore = errors.New("Can't return a key store")
|
||||
errAccManager = errors.New("Can't return an account manager")
|
||||
)
|
||||
|
@ -149,7 +147,6 @@ func TestManagerTestSuite(t *testing.T) {
|
|||
nodeManager: nodeManager,
|
||||
accManager: accManager,
|
||||
keyStore: keyStore,
|
||||
shh: whisper.New(nil),
|
||||
gethAccManager: accounts.NewManager(),
|
||||
}
|
||||
|
||||
|
@ -167,7 +164,6 @@ type ManagerTestSuite struct {
|
|||
nodeManager *common.MockNodeManager
|
||||
accManager *Manager
|
||||
keyStore *keystore.KeyStore
|
||||
shh *whisper.Whisper
|
||||
gethAccManager *accounts.Manager
|
||||
}
|
||||
|
||||
|
@ -183,7 +179,7 @@ type testAccount struct {
|
|||
// development so this is a good workaround to use with EXPECT().Func().AnyTimes()
|
||||
func (s *ManagerTestSuite) reinitMock() {
|
||||
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
|
||||
|
@ -219,7 +215,6 @@ func (s *ManagerTestSuite) TestSelectAccount() {
|
|||
testCases := []struct {
|
||||
name string
|
||||
accountKeyStoreReturn []interface{}
|
||||
whisperServiceReturn []interface{}
|
||||
address string
|
||||
password string
|
||||
expectedError error
|
||||
|
@ -227,7 +222,6 @@ func (s *ManagerTestSuite) TestSelectAccount() {
|
|||
{
|
||||
"success",
|
||||
[]interface{}{s.keyStore, nil},
|
||||
[]interface{}{s.shh, nil},
|
||||
s.address,
|
||||
s.password,
|
||||
nil,
|
||||
|
@ -235,23 +229,13 @@ func (s *ManagerTestSuite) TestSelectAccount() {
|
|||
{
|
||||
"fail_keyStore",
|
||||
[]interface{}{nil, errKeyStore},
|
||||
[]interface{}{s.shh, nil},
|
||||
s.address,
|
||||
s.password,
|
||||
errKeyStore,
|
||||
},
|
||||
{
|
||||
"fail_whisperService",
|
||||
[]interface{}{s.keyStore, nil},
|
||||
[]interface{}{nil, errWhisper},
|
||||
s.address,
|
||||
s.password,
|
||||
errWhisper,
|
||||
},
|
||||
{
|
||||
"fail_wrongAddress",
|
||||
[]interface{}{s.keyStore, nil},
|
||||
[]interface{}{s.shh, nil},
|
||||
"wrong-address",
|
||||
s.password,
|
||||
ErrAddressToAccountMappingFailure,
|
||||
|
@ -259,7 +243,6 @@ func (s *ManagerTestSuite) TestSelectAccount() {
|
|||
{
|
||||
"fail_wrongPassword",
|
||||
[]interface{}{s.keyStore, nil},
|
||||
[]interface{}{s.shh, nil},
|
||||
s.address,
|
||||
"wrong-password",
|
||||
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.reinitMock()
|
||||
s.nodeManager.EXPECT().AccountKeyStore().Return(testCase.accountKeyStoreReturn...).AnyTimes()
|
||||
s.nodeManager.EXPECT().WhisperService().Return(testCase.whisperServiceReturn...).AnyTimes()
|
||||
err := s.accManager.SelectAccount(testCase.address, testCase.password)
|
||||
s.Equal(testCase.expectedError, err)
|
||||
})
|
||||
|
@ -290,7 +272,6 @@ func (s *ManagerTestSuite) TestCreateChildAccount() {
|
|||
// Now, select the test account for rest of the test cases.
|
||||
s.reinitMock()
|
||||
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)
|
||||
|
||||
|
@ -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() {
|
||||
s.nodeManager.EXPECT().WhisperService().Return(s.shh, nil)
|
||||
err := s.accManager.Logout()
|
||||
s.NoError(err)
|
||||
|
||||
s.nodeManager.EXPECT().WhisperService().Return(nil, errWhisper)
|
||||
err = s.accManager.Logout()
|
||||
s.Equal(errWhisper, err)
|
||||
s.Nil(err)
|
||||
s.Nil(s.accManager.selectedAccount)
|
||||
}
|
||||
|
||||
// TestAccounts tests cases for (*Manager).Accounts.
|
||||
func (s *ManagerTestSuite) TestAccounts() {
|
||||
// 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)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"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/jail"
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
|
@ -39,7 +40,7 @@ func (api *StatusAPI) NodeManager() common.NodeManager {
|
|||
}
|
||||
|
||||
// AccountManager returns reference to account manager
|
||||
func (api *StatusAPI) AccountManager() common.AccountManager {
|
||||
func (api *StatusAPI) AccountManager() *account.Manager {
|
||||
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
|
||||
// and should be properly renamed, for example: ResetCells
|
||||
api.b.jailManager.Stop()
|
||||
return api.b.AccountManager().SelectAccount(address, password)
|
||||
return api.b.SelectAccount(address, password)
|
||||
}
|
||||
|
||||
// Logout clears whisper identities
|
||||
func (api *StatusAPI) Logout() error {
|
||||
api.b.jailManager.Stop()
|
||||
return api.b.AccountManager().Logout()
|
||||
return api.b.Logout()
|
||||
}
|
||||
|
||||
// SendTransaction creates a new transaction and waits until it's complete.
|
||||
|
|
|
@ -2,6 +2,7 @@ package api
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
|
@ -23,11 +24,18 @@ const (
|
|||
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
|
||||
type StatusBackend struct {
|
||||
mu sync.Mutex
|
||||
nodeManager *node.NodeManager
|
||||
accountManager common.AccountManager
|
||||
accountManager *account.Manager
|
||||
txQueueManager *transactions.Manager
|
||||
jailManager jail.Manager
|
||||
newNotification common.NotificationConstructor
|
||||
|
@ -61,7 +69,7 @@ func (b *StatusBackend) NodeManager() *node.NodeManager {
|
|||
}
|
||||
|
||||
// AccountManager returns reference to account manager
|
||||
func (b *StatusBackend) AccountManager() common.AccountManager {
|
||||
func (b *StatusBackend) AccountManager() *account.Manager {
|
||||
return b.accountManager
|
||||
}
|
||||
|
||||
|
@ -116,7 +124,7 @@ func (b *StatusBackend) startNode(config *params.NodeConfig) (err error) {
|
|||
if err := b.registerHandlers(); err != nil {
|
||||
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.Info("Account reselected")
|
||||
|
@ -226,7 +234,9 @@ func (b *StatusBackend) registerHandlers() error {
|
|||
if rpcClient == nil {
|
||||
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)
|
||||
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)
|
||||
// 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
|
||||
}
|
||||
|
|
|
@ -27,22 +27,6 @@ var (
|
|||
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
|
||||
type NodeManager interface {
|
||||
// StartNode start Status node, fails if node is already started
|
||||
|
@ -89,53 +73,6 @@ type NodeManager interface {
|
|||
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)
|
||||
type TransactionResult struct {
|
||||
Hash common.Hash
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
accounts "github.com/ethereum/go-ethereum/accounts"
|
||||
keystore "github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
common "github.com/ethereum/go-ethereum/common"
|
||||
les "github.com/ethereum/go-ethereum/les"
|
||||
node "github.com/ethereum/go-ethereum/node"
|
||||
whisperv6 "github.com/ethereum/go-ethereum/whisper/whisperv6"
|
||||
|
@ -215,170 +214,3 @@ func (m *MockNodeManager) RPCClient() *rpc.Client {
|
|||
func (mr *MockNodeManagerMockRecorder) RPCClient() *gomock.Call {
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package common
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -13,8 +12,6 @@ import (
|
|||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/pborman/uuid"
|
||||
"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
|
||||
|
||||
// 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.
|
||||
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
|
||||
func ImportTestAccount(keystoreDir, accountFile string) error {
|
||||
// make sure that keystore folder exists
|
||||
|
|
|
@ -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))
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"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/params"
|
||||
"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)
|
||||
type Manager struct {
|
||||
nodeManager common.NodeManager
|
||||
accountManager common.AccountManager
|
||||
accountManager Accounter
|
||||
txQueue *queue.TxQueue
|
||||
ethTxClient EthTransactor
|
||||
notify bool
|
||||
|
@ -42,7 +43,7 @@ type Manager struct {
|
|||
}
|
||||
|
||||
// NewManager returns a new Manager.
|
||||
func NewManager(nodeManager common.NodeManager, accountManager common.AccountManager) *Manager {
|
||||
func NewManager(nodeManager common.NodeManager, accountManager Accounter) *Manager {
|
||||
return &Manager{
|
||||
nodeManager: nodeManager,
|
||||
accountManager: accountManager,
|
||||
|
@ -151,7 +152,7 @@ func (m *Manager) CompleteTransaction(id common.QueuedTxID, password string) (ha
|
|||
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()
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
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.addrLock.LockAddr(queuedTx.Args.From)
|
||||
var localNonce uint64
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/golang/mock/gomock"
|
||||
"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/params"
|
||||
"github.com/status-im/status-go/geth/rpc"
|
||||
|
@ -35,7 +36,7 @@ type TxQueueTestSuite struct {
|
|||
nodeManagerMockCtrl *gomock.Controller
|
||||
nodeManagerMock *common.MockNodeManager
|
||||
accountManagerMockCtrl *gomock.Controller
|
||||
accountManagerMock *common.MockAccountManager
|
||||
accountManagerMock *MockAccountManager
|
||||
server *gethrpc.Server
|
||||
client *gethrpc.Client
|
||||
txServiceMockCtrl *gomock.Controller
|
||||
|
@ -51,7 +52,7 @@ func (s *TxQueueTestSuite) SetupTest() {
|
|||
s.txServiceMockCtrl = gomock.NewController(s.T())
|
||||
|
||||
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.client = gethrpc.DialInProc(s.server)
|
||||
|
@ -83,7 +84,7 @@ var (
|
|||
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.
|
||||
// And also set the expected gas and gas price for RLP encoding the expected tx.
|
||||
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)
|
||||
}
|
||||
|
||||
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(
|
||||
uint64(*nonce),
|
||||
gethcommon.Address(*tx.Args.To),
|
||||
|
@ -124,7 +125,7 @@ func (s *TxQueueTestSuite) rlpEncodeTx(tx *common.QueuedTx, config *params.NodeC
|
|||
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.accountManagerMock.EXPECT().SelectedAccount().Return(account, nil)
|
||||
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() {
|
||||
password := TestConfig.Account1.Password
|
||||
key, _ := crypto.GenerateKey()
|
||||
account := &common.SelectedExtKey{
|
||||
Address: common.FromAddress(TestConfig.Account1.Address),
|
||||
selectedAccount := &account.SelectedExtKey{
|
||||
Address: account.FromAddress(TestConfig.Account1.Address),
|
||||
AccountKey: &keystore.Key{PrivateKey: key},
|
||||
}
|
||||
testCases := []struct {
|
||||
|
@ -168,14 +169,14 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
|
|||
for _, testCase := range testCases {
|
||||
s.T().Run(testCase.name, func(t *testing.T) {
|
||||
s.SetupTest()
|
||||
s.setupStatusBackend(account, password, nil)
|
||||
s.setupStatusBackend(selectedAccount, password, nil)
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Gas: testCase.gas,
|
||||
GasPrice: testCase.gasPrice,
|
||||
})
|
||||
s.setupTransactionPoolAPI(tx, testNonce, testNonce, account, nil)
|
||||
s.setupTransactionPoolAPI(tx, testNonce, testNonce, selectedAccount, nil)
|
||||
|
||||
s.NoError(s.manager.QueueTransaction(tx))
|
||||
w := make(chan struct{})
|
||||
|
@ -203,18 +204,18 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
|
|||
func (s *TxQueueTestSuite) TestCompleteTransactionMultipleTimes() {
|
||||
password := TestConfig.Account1.Password
|
||||
key, _ := crypto.GenerateKey()
|
||||
account := &common.SelectedExtKey{
|
||||
Address: common.FromAddress(TestConfig.Account1.Address),
|
||||
selectedAccount := &account.SelectedExtKey{
|
||||
Address: account.FromAddress(TestConfig.Account1.Address),
|
||||
AccountKey: &keystore.Key{PrivateKey: key},
|
||||
}
|
||||
s.setupStatusBackend(account, password, nil)
|
||||
s.setupStatusBackend(selectedAccount, password, nil)
|
||||
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.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)
|
||||
s.NoError(err)
|
||||
|
@ -257,13 +258,13 @@ func (s *TxQueueTestSuite) TestCompleteTransactionMultipleTimes() {
|
|||
|
||||
func (s *TxQueueTestSuite) TestAccountMismatch() {
|
||||
s.nodeManagerMock.EXPECT().NodeConfig().Return(s.nodeConfig, nil)
|
||||
s.accountManagerMock.EXPECT().SelectedAccount().Return(&common.SelectedExtKey{
|
||||
Address: common.FromAddress(TestConfig.Account2.Address),
|
||||
s.accountManagerMock.EXPECT().SelectedAccount().Return(&account.SelectedExtKey{
|
||||
Address: account.FromAddress(TestConfig.Account2.Address),
|
||||
}, nil)
|
||||
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
})
|
||||
|
||||
s.NoError(s.manager.QueueTransaction(tx))
|
||||
|
@ -279,14 +280,14 @@ func (s *TxQueueTestSuite) TestAccountMismatch() {
|
|||
func (s *TxQueueTestSuite) TestInvalidPassword() {
|
||||
password := "invalid-password"
|
||||
key, _ := crypto.GenerateKey()
|
||||
account := &common.SelectedExtKey{
|
||||
Address: common.FromAddress(TestConfig.Account1.Address),
|
||||
selectedAccount := &account.SelectedExtKey{
|
||||
Address: account.FromAddress(TestConfig.Account1.Address),
|
||||
AccountKey: &keystore.Key{PrivateKey: key},
|
||||
}
|
||||
s.setupStatusBackend(account, password, keystore.ErrDecrypt)
|
||||
s.setupStatusBackend(selectedAccount, password, keystore.ErrDecrypt)
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
})
|
||||
|
||||
s.NoError(s.manager.QueueTransaction(tx))
|
||||
|
@ -300,8 +301,8 @@ func (s *TxQueueTestSuite) TestInvalidPassword() {
|
|||
|
||||
func (s *TxQueueTestSuite) TestDiscardTransaction() {
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
})
|
||||
|
||||
s.NoError(s.manager.QueueTransaction(tx))
|
||||
|
@ -320,8 +321,8 @@ func (s *TxQueueTestSuite) TestDiscardTransaction() {
|
|||
|
||||
func (s *TxQueueTestSuite) TestCompletionTimedOut() {
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
})
|
||||
|
||||
s.NoError(s.manager.QueueTransaction(tx))
|
||||
|
@ -340,21 +341,21 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
|
|||
txCount := 3
|
||||
password := TestConfig.Account1.Password
|
||||
key, _ := crypto.GenerateKey()
|
||||
account := &common.SelectedExtKey{
|
||||
Address: common.FromAddress(TestConfig.Account1.Address),
|
||||
selectedAccount := &account.SelectedExtKey{
|
||||
Address: account.FromAddress(TestConfig.Account1.Address),
|
||||
AccountKey: &keystore.Key{PrivateKey: key},
|
||||
}
|
||||
// setup call expectations for 5 transactions in total
|
||||
for i := 0; i < txCount+2; i++ {
|
||||
s.setupStatusBackend(account, password, nil)
|
||||
s.setupStatusBackend(selectedAccount, password, nil)
|
||||
}
|
||||
nonce := hexutil.Uint64(0)
|
||||
for i := 0; i < txCount; i++ {
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.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))
|
||||
hash, err := s.manager.CompleteTransaction(tx.ID, password)
|
||||
rst := s.manager.WaitForTransaction(tx)
|
||||
|
@ -367,10 +368,10 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
|
|||
}
|
||||
nonce = hexutil.Uint64(5)
|
||||
tx := common.CreateTransaction(context.Background(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.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))
|
||||
hash, err := s.manager.CompleteTransaction(tx.ID, password)
|
||||
rst := s.manager.WaitForTransaction(tx)
|
||||
|
@ -381,10 +382,10 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
|
|||
s.Equal(uint64(nonce)+1, resultNonce.(uint64))
|
||||
|
||||
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{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
})
|
||||
s.NoError(s.manager.QueueTransaction(tx))
|
||||
_, err = s.manager.CompleteTransaction(tx.ID, password)
|
||||
|
|
20
lib/utils.go
20
lib/utils.go
|
@ -410,7 +410,7 @@ func testCreateChildAccount(t *testing.T) bool { //nolint: gocyclo
|
|||
address, pubKey, mnemonic := createAccountResponse.Address, createAccountResponse.PubKey, createAccountResponse.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 {
|
||||
t.Errorf("can not get account from address: %v", err)
|
||||
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
|
||||
account, err := common.ParseAccountString(address)
|
||||
account, err := account.ParseAccountString(address)
|
||||
if err != nil {
|
||||
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
|
||||
txCheckHash, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
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
|
||||
sendTx := func() {
|
||||
txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
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
|
||||
txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
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
|
||||
sendTx := func() {
|
||||
txHashCheck, err := statusAPI.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
if err != transactions.ErrQueuedTxDiscarded {
|
||||
|
|
|
@ -23,7 +23,7 @@ func (s *AccountsTestSuite) TestRPCEthAccounts() {
|
|||
defer s.StopTestBackend()
|
||||
|
||||
// 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)
|
||||
|
||||
rpcClient := s.Backend.NodeManager().RPCClient()
|
||||
|
@ -50,7 +50,7 @@ func (s *AccountsTestSuite) TestRPCEthAccountsWithUpstream() {
|
|||
defer s.StopTestBackend()
|
||||
|
||||
// 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)
|
||||
|
||||
rpcClient := s.Backend.NodeManager().RPCClient()
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"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"
|
||||
. "github.com/status-im/status-go/t/utils"
|
||||
"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)")
|
||||
|
||||
// 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")
|
||||
|
||||
// at this point main account should show up
|
||||
|
@ -94,7 +93,7 @@ func (s *AccountsTestSuite) TestCreateChildAccount() {
|
|||
s.NoError(err)
|
||||
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")
|
||||
|
||||
// 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)
|
||||
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")
|
||||
|
||||
// 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")
|
||||
|
||||
// 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")
|
||||
|
||||
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)
|
||||
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")
|
||||
}
|
||||
|
||||
|
@ -201,17 +200,17 @@ func (s *AccountsTestSuite) TestSelectAccount() {
|
|||
s.False(whisperService.HasKeyPair(pubKey1), "identity already present in whisper")
|
||||
|
||||
// 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")
|
||||
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.True(whisperService.HasKeyPair(pubKey1), "identity not injected into whisper")
|
||||
|
||||
// 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.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.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)
|
||||
|
||||
// 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")
|
||||
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")
|
||||
|
||||
// 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.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.False(whisperService.HasKeyPair(pubKey1), "identity should be removed, but it is still present in whisper")
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ func (s *APIBackendTestSuite) TestRaceConditions() {
|
|||
|
||||
// SelectAccount
|
||||
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)
|
||||
|
||||
// CreateChildAccount
|
||||
|
|
|
@ -131,7 +131,7 @@ func (s *JailRPCTestSuite) TestContractDeployment() {
|
|||
event := envelope.Event.(map[string]interface{})
|
||||
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)
|
||||
var txErr error
|
||||
|
@ -197,7 +197,7 @@ func (s *JailRPCTestSuite) TestJailVMPersistence() {
|
|||
EnsureNodeSync(s.Backend.NodeManager())
|
||||
|
||||
// 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)
|
||||
|
||||
type testCase struct {
|
||||
|
|
|
@ -39,7 +39,7 @@ func (s *TransactionsTestSuite) TestCallRPCSendTransaction() {
|
|||
|
||||
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)
|
||||
|
||||
transactionCompleted := make(chan struct{})
|
||||
|
@ -91,7 +91,7 @@ func (s *TransactionsTestSuite) TestCallRPCSendTransactionUpstream() {
|
|||
s.StartTestBackend(e2e.WithUpstream(addr))
|
||||
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)
|
||||
|
||||
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)
|
||||
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)
|
||||
txHash, err = s.Backend.CompleteTransaction(
|
||||
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)
|
||||
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(
|
||||
common.QueuedTxID(event["id"].(string)),
|
||||
TestConfig.Account1.Password,
|
||||
|
@ -209,7 +209,7 @@ func (s *TransactionsTestSuite) TestSendContractTx() {
|
|||
|
||||
gas := uint64(params.DefaultGas)
|
||||
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
|
||||
//Value: (*hexutil.Big)(new(big.Int).Mul(big.NewInt(1), gethcommon.Ether)),
|
||||
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)
|
||||
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)
|
||||
txHash, err = s.Backend.CompleteTransaction(
|
||||
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)
|
||||
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(
|
||||
common.QueuedTxID(event["id"].(string)),
|
||||
TestConfig.Account1.Password,
|
||||
|
@ -291,8 +291,8 @@ func (s *TransactionsTestSuite) TestSendEther() {
|
|||
|
||||
// this call blocks, up until Complete Transaction is called
|
||||
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
s.NoError(err, "cannot send transaction")
|
||||
|
@ -318,7 +318,7 @@ func (s *TransactionsTestSuite) TestSendEtherTxUpstream() {
|
|||
s.StartTestBackend(e2e.WithUpstream(addr))
|
||||
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)
|
||||
|
||||
completeQueuedTransaction := make(chan struct{})
|
||||
|
@ -348,8 +348,8 @@ func (s *TransactionsTestSuite) TestSendEtherTxUpstream() {
|
|||
// This call blocks, up until Complete Transaction is called.
|
||||
// Explicitly not setting Gas to get it estimated.
|
||||
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
GasPrice: (*hexutil.Big)(big.NewInt(28000000000)),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
|
@ -372,7 +372,7 @@ func (s *TransactionsTestSuite) TestDoubleCompleteQueuedTransactions() {
|
|||
EnsureNodeSync(s.Backend.NodeManager())
|
||||
|
||||
// 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{})
|
||||
|
||||
|
@ -421,8 +421,8 @@ func (s *TransactionsTestSuite) TestDoubleCompleteQueuedTransactions() {
|
|||
|
||||
// this call blocks, and should return on *second* attempt to CompleteTransaction (w/ the correct password)
|
||||
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
s.NoError(err, "cannot send transaction")
|
||||
|
@ -449,7 +449,7 @@ func (s *TransactionsTestSuite) TestDiscardQueuedTransaction() {
|
|||
s.Backend.TxQueueManager().TransactionQueue().Reset()
|
||||
|
||||
// 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{})
|
||||
|
||||
|
@ -499,8 +499,8 @@ func (s *TransactionsTestSuite) TestDiscardQueuedTransaction() {
|
|||
|
||||
// this call blocks, and should return when DiscardQueuedTransaction() is called
|
||||
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
s.EqualError(err, transactions.ErrQueuedTxDiscarded.Error(), "transaction is expected to be discarded")
|
||||
|
@ -523,7 +523,7 @@ func (s *TransactionsTestSuite) TestCompleteMultipleQueuedTransactions() {
|
|||
s.TxQueueManager().TransactionQueue().Reset()
|
||||
|
||||
// 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.sendConcurrentTransactions(3)
|
||||
|
@ -539,7 +539,7 @@ func (s *TransactionsTestSuite) TestDiscardMultipleQueuedTransactions() {
|
|||
s.Backend.TxQueueManager().TransactionQueue().Reset()
|
||||
|
||||
// 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
|
||||
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
|
||||
sendTx := func() {
|
||||
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
require.EqualError(err, transactions.ErrQueuedTxDiscarded.Error())
|
||||
|
@ -650,7 +650,7 @@ func (s *TransactionsTestSuite) TestNonExistentQueuedTransactions() {
|
|||
defer s.StopTestBackend()
|
||||
|
||||
// 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
|
||||
signal.SetDefaultNodeNotificationHandler(func(string) {})
|
||||
|
@ -688,7 +688,7 @@ func (s *TransactionsTestSuite) TestEvictionOfQueuedTransactions() {
|
|||
s.Backend.TxQueueManager().TransactionQueue().Reset()
|
||||
|
||||
// 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()
|
||||
s.Zero(txQueue.Count(), "transaction count should be zero")
|
||||
|
@ -721,7 +721,7 @@ func (s *TransactionsTestSuite) TestCompleteMultipleQueuedTransactionsUpstream()
|
|||
s.TxQueueManager().TransactionQueue().Reset()
|
||||
|
||||
// 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.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
|
||||
sendTx := func() {
|
||||
txHashCheck, err := s.Backend.SendTransaction(context.TODO(), common.SendTxArgs{
|
||||
From: common.FromAddress(TestConfig.Account1.Address),
|
||||
To: common.ToAddress(TestConfig.Account2.Address),
|
||||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
require.NoError(err, "cannot send transaction")
|
||||
|
|
|
@ -92,26 +92,3 @@ func (s *WhisperTestSuite) TestWhisperFilterRace() {
|
|||
|
||||
<-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")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue