[#issue-403] Account package cleanup
This commit is contained in:
parent
01769e9ee8
commit
18fbebc942
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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"
|
"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.
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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/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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
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
|
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 {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue