Verify valid sub-accounts using database
This commit is contained in:
parent
b8ea79a3f0
commit
bf95a71f6f
|
@ -557,25 +557,16 @@ func (b *StatusBackend) HashTypedData(typed typeddata.TypedData) (common.Hash, e
|
|||
func (b *StatusBackend) getVerifiedWalletAccount(address, password string) (*account.SelectedExtKey, error) {
|
||||
config := b.StatusNode().Config()
|
||||
|
||||
var validAddress bool
|
||||
|
||||
addresses := b.accountManager.WatchAddresses()
|
||||
mainAccountAddress, err := b.accountManager.MainAccountAddress()
|
||||
db := accounts.NewDB(b.appDB)
|
||||
exists, err := db.AddressExists(common.HexToAddress(address))
|
||||
if err != nil {
|
||||
b.log.Error("failed to query db for a given address", "address", address, "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addresses = append(addresses, mainAccountAddress)
|
||||
for _, a := range addresses {
|
||||
if a.String() == address {
|
||||
validAddress = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !validAddress {
|
||||
if !exists {
|
||||
b.log.Error("failed to get a selected account", "err", transactions.ErrInvalidTxSender)
|
||||
return nil, transactions.ErrInvalidTxSender
|
||||
return nil, transactions.ErrAccountDoesntExist
|
||||
}
|
||||
|
||||
key, err := b.accountManager.VerifyAccountPassword(config.KeyStoreDir, address, password)
|
||||
|
|
|
@ -4,7 +4,10 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
|
@ -12,11 +15,14 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/status-im/status-go/account"
|
||||
"github.com/status-im/status-go/multiaccounts"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
"github.com/status-im/status-go/node"
|
||||
"github.com/status-im/status-go/params"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
"github.com/status-im/status-go/services/typeddata"
|
||||
"github.com/status-im/status-go/t/utils"
|
||||
"github.com/status-im/status-go/transactions"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -478,3 +484,56 @@ func TestHashTypedData(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.NotEqual(t, common.Hash{}, hash)
|
||||
}
|
||||
|
||||
func TestBackendGetVerifiedAccount(t *testing.T) {
|
||||
password := "test"
|
||||
tmpdir, err := ioutil.TempDir("", "verified-account-test-")
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(tmpdir)
|
||||
backend := NewStatusBackend()
|
||||
backend.UpdateRootDataDir(tmpdir)
|
||||
require.NoError(t, backend.accountManager.InitKeystore(filepath.Join(tmpdir, "keystore")))
|
||||
require.NoError(t, backend.ensureAppDBOpened(multiaccounts.Account{Address: common.Address{1, 1, 1}}, password))
|
||||
config, err := params.NewNodeConfig(tmpdir, 178733)
|
||||
require.NoError(t, err)
|
||||
// this is for StatusNode().Config() call inside of the getVerifiedWalletAccount
|
||||
require.NoError(t, backend.StartNode(config))
|
||||
defer func() {
|
||||
require.NoError(t, backend.StopNode())
|
||||
}()
|
||||
|
||||
t.Run("AccountDoesntExist", func(t *testing.T) {
|
||||
pkey, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
address := crypto.PubkeyToAddress(pkey.PublicKey)
|
||||
key, err := backend.getVerifiedWalletAccount(address.String(), password)
|
||||
require.EqualError(t, err, transactions.ErrAccountDoesntExist.Error())
|
||||
require.Nil(t, key)
|
||||
})
|
||||
|
||||
t.Run("PasswordDoesntMatch", func(t *testing.T) {
|
||||
pkey, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
address := crypto.PubkeyToAddress(pkey.PublicKey)
|
||||
db := accounts.NewDB(backend.appDB)
|
||||
_, err = backend.accountManager.ImportAccount(pkey, password)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveAccounts([]accounts.Account{{Address: address}}))
|
||||
key, err := backend.getVerifiedWalletAccount(address.String(), "wrong-password")
|
||||
require.EqualError(t, err, "could not decrypt key with given passphrase")
|
||||
require.Nil(t, key)
|
||||
})
|
||||
|
||||
t.Run("Success", func(t *testing.T) {
|
||||
pkey, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
address := crypto.PubkeyToAddress(pkey.PublicKey)
|
||||
db := accounts.NewDB(backend.appDB)
|
||||
_, err = backend.accountManager.ImportAccount(pkey, password)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveAccounts([]accounts.Account{{Address: address}}))
|
||||
key, err := backend.getVerifiedWalletAccount(address.String(), password)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, address, key.Address)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -38,7 +38,10 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
)
|
||||
import "github.com/status-im/status-go/multiaccounts/accounts"
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
)
|
||||
|
||||
const initJS = `
|
||||
var _status_catalog = {
|
||||
|
@ -594,21 +597,11 @@ func testSendTransactionWithLogin(t *testing.T, feed *event.Feed) bool {
|
|||
}
|
||||
|
||||
func testSendTransactionInvalidPassword(t *testing.T, feed *event.Feed) bool {
|
||||
createAccountAndLogin(t, feed)
|
||||
acc := createAccountAndLogin(t, feed)
|
||||
EnsureNodeSync(statusBackend.StatusNode().EnsureSync)
|
||||
|
||||
// log into account from which transactions will be sent
|
||||
if err := statusBackend.SelectAccount(buildLoginParams(
|
||||
TestConfig.Account1.WalletAddress,
|
||||
TestConfig.Account1.ChatAddress,
|
||||
TestConfig.Account1.Password,
|
||||
)); err != nil {
|
||||
t.Errorf("cannot select account: %v. Error %q", TestConfig.Account1.WalletAddress, err)
|
||||
return false
|
||||
}
|
||||
|
||||
args, err := json.Marshal(transactions.SendTxArgs{
|
||||
From: account.FromAddress(TestConfig.Account1.WalletAddress),
|
||||
From: common.HexToAddress(acc.WalletAddress),
|
||||
To: account.ToAddress(TestConfig.Account2.WalletAddress),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
|
@ -635,14 +628,8 @@ func testFailedTransaction(t *testing.T, feed *event.Feed) bool {
|
|||
createAccountAndLogin(t, feed)
|
||||
EnsureNodeSync(statusBackend.StatusNode().EnsureSync)
|
||||
|
||||
// log into wrong account in order to get selectedAccount error
|
||||
if err := statusBackend.SelectAccount(buildLoginParams(TestConfig.Account2.WalletAddress, TestConfig.Account2.ChatAddress, TestConfig.Account2.Password)); err != nil {
|
||||
t.Errorf("cannot select account: %v. Error %q", TestConfig.Account2.WalletAddress, err)
|
||||
return false
|
||||
}
|
||||
|
||||
args, err := json.Marshal(transactions.SendTxArgs{
|
||||
From: account.FromAddress(TestConfig.Account1.WalletAddress),
|
||||
From: *account.ToAddress(TestConfig.Account1.WalletAddress),
|
||||
To: account.ToAddress(TestConfig.Account2.WalletAddress),
|
||||
Value: (*hexutil.Big)(big.NewInt(1000000000000)),
|
||||
})
|
||||
|
@ -658,8 +645,8 @@ func testFailedTransaction(t *testing.T, feed *event.Feed) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if result.Error.Message != transactions.ErrInvalidTxSender.Error() {
|
||||
t.Errorf("expected error to be ErrInvalidTxSender, got %s", result.Error.Message)
|
||||
if result.Error.Message != transactions.ErrAccountDoesntExist.Error() {
|
||||
t.Errorf("expected error to be ErrAccountDoesntExist, got %s", result.Error.Message)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -186,3 +186,9 @@ func (db *Database) GetAddresses() (rst []common.Address, err error) {
|
|||
}
|
||||
return rst, nil
|
||||
}
|
||||
|
||||
// AddressExists returns true if given address is stored in database.
|
||||
func (db *Database) AddressExists(address common.Address) (exists bool, err error) {
|
||||
err = db.db.QueryRow("SELECT EXISTS (SELECT 1 FROM accounts WHERE address = ?)", address).Scan(&exists)
|
||||
return exists, err
|
||||
}
|
||||
|
|
|
@ -175,3 +175,25 @@ func TestGetAccounts(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, accounts, rst)
|
||||
}
|
||||
|
||||
func TestAddressExists(t *testing.T) {
|
||||
db, stop := setupTestDB(t)
|
||||
defer stop()
|
||||
|
||||
accounts := []Account{
|
||||
{Address: common.Address{0x01}, Chat: true, Wallet: true},
|
||||
}
|
||||
require.NoError(t, db.SaveAccounts(accounts))
|
||||
|
||||
exists, err := db.AddressExists(accounts[0].Address)
|
||||
require.NoError(t, err)
|
||||
require.True(t, exists)
|
||||
}
|
||||
|
||||
func TestAddressDoesntExist(t *testing.T) {
|
||||
db, stop := setupTestDB(t)
|
||||
defer stop()
|
||||
exists, err := db.AddressExists(common.Address{1, 1, 1})
|
||||
require.NoError(t, err)
|
||||
require.False(t, exists)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
whisper "github.com/status-im/whisper/whisperv6"
|
||||
|
||||
"github.com/status-im/status-go/api"
|
||||
"github.com/status-im/status-go/multiaccounts"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
"github.com/status-im/status-go/node"
|
||||
"github.com/status-im/status-go/signal"
|
||||
. "github.com/status-im/status-go/t/utils" //nolint: golint
|
||||
|
@ -100,6 +102,28 @@ func (s *BackendTestSuite) StartTestBackend(opts ...TestNodeOption) {
|
|||
s.True(s.Backend.IsNodeRunning())
|
||||
}
|
||||
|
||||
func (s *BackendTestSuite) StartTestBackendWithAccount(account multiaccounts.Account, password string, subaccs []accounts.Account, opts ...TestNodeOption) {
|
||||
nodeConfig, err := MakeTestNodeConfig(GetNetworkID())
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Apply any options altering node config.
|
||||
for i := range opts {
|
||||
opts[i](nodeConfig)
|
||||
}
|
||||
// accounts must be imported before keystore is initialized
|
||||
s.NoError(importTestAccounts(nodeConfig.KeyStoreDir))
|
||||
s.Backend.UpdateRootDataDir(nodeConfig.DataDir)
|
||||
s.NoError(s.Backend.OpenAccounts())
|
||||
s.NoError(s.Backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir))
|
||||
|
||||
s.Require().NoError(s.Backend.StartNodeWithAccountAndConfig(account, password, nodeConfig, subaccs))
|
||||
}
|
||||
|
||||
func (s *BackendTestSuite) LogoutAndStop() {
|
||||
s.NoError(s.Backend.Logout())
|
||||
s.StopTestBackend()
|
||||
}
|
||||
|
||||
// StopTestBackend stops the node.
|
||||
func (s *BackendTestSuite) StopTestBackend() {
|
||||
s.True(s.Backend.IsNodeRunning())
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package transactions
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
@ -9,6 +11,8 @@ import (
|
|||
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/status-im/status-go/account"
|
||||
"github.com/status-im/status-go/multiaccounts"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
"github.com/status-im/status-go/params"
|
||||
e2e "github.com/status-im/status-go/t/e2e"
|
||||
. "github.com/status-im/status-go/t/utils"
|
||||
|
@ -99,12 +103,18 @@ func (s *TransactionsTestSuite) sendTransactionUsingRPCClient(
|
|||
func (s *TransactionsTestSuite) TestEmptyToFieldPreserved() {
|
||||
CheckTestSkipForNetworks(s.T(), params.MainNetworkID)
|
||||
|
||||
s.StartTestBackend()
|
||||
defer s.StopTestBackend()
|
||||
tmpdir, err := ioutil.TempDir("", "transactions-tests-")
|
||||
s.Require().NoError(err)
|
||||
defer os.Remove(tmpdir)
|
||||
|
||||
wallet := common.HexToAddress(TestConfig.Account1.WalletAddress)
|
||||
s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password,
|
||||
[]accounts.Account{{Address: wallet, Wallet: true, Chat: true}},
|
||||
e2e.WithDataDir(tmpdir),
|
||||
)
|
||||
defer s.LogoutAndStop()
|
||||
|
||||
EnsureNodeSync(s.Backend.StatusNode().EnsureSync)
|
||||
err := s.Backend.SelectAccount(buildLoginParams(TestConfig.Account1.WalletAddress, TestConfig.Account1.ChatAddress, TestConfig.Account1.Password))
|
||||
s.NoError(err)
|
||||
|
||||
args := transactions.SendTxArgs{
|
||||
From: account.FromAddress(TestConfig.Account1.WalletAddress),
|
||||
|
@ -166,14 +176,19 @@ func (s *TransactionsTestSuite) TestSendContractTx() {
|
|||
}
|
||||
|
||||
func (s *TransactionsTestSuite) testSendContractTx(setInputAndDataValue initFunc, expectedError error, expectedErrorDescription string) {
|
||||
s.StartTestBackend()
|
||||
defer s.StopTestBackend()
|
||||
tmpdir, err := ioutil.TempDir("", "transactions-tests-")
|
||||
s.Require().NoError(err)
|
||||
defer os.Remove(tmpdir)
|
||||
|
||||
wallet := common.HexToAddress(TestConfig.Account1.WalletAddress)
|
||||
s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password,
|
||||
[]accounts.Account{{Address: wallet, Wallet: true, Chat: true}},
|
||||
e2e.WithDataDir(tmpdir),
|
||||
)
|
||||
defer s.LogoutAndStop()
|
||||
|
||||
EnsureNodeSync(s.Backend.StatusNode().EnsureSync)
|
||||
|
||||
err := s.Backend.AccountManager().SelectAccount(buildLoginParams(TestConfig.Account1.WalletAddress, TestConfig.Account1.ChatAddress, TestConfig.Account1.Password))
|
||||
s.NoError(err)
|
||||
|
||||
// this call blocks, up until Complete Transaction is called
|
||||
byteCode, err := hexutil.Decode(`0x6060604052341561000c57fe5b5b60a58061001b6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636ffa1caa14603a575bfe5b3415604157fe5b60556004808035906020019091905050606b565b6040518082815260200191505060405180910390f35b60008160020290505b9190505600a165627a7a72305820ccdadd737e4ac7039963b54cee5e5afb25fa859a275252bdcf06f653155228210029`)
|
||||
s.NoError(err)
|
||||
|
@ -194,20 +209,23 @@ func (s *TransactionsTestSuite) testSendContractTx(setInputAndDataValue initFunc
|
|||
}
|
||||
s.NoError(err)
|
||||
s.False(reflect.DeepEqual(hash, gethcommon.Hash{}))
|
||||
s.NoError(s.Backend.Logout())
|
||||
}
|
||||
|
||||
func (s *TransactionsTestSuite) TestSendEther() {
|
||||
CheckTestSkipForNetworks(s.T(), params.MainNetworkID)
|
||||
tmpdir, err := ioutil.TempDir("", "transactions-tests-")
|
||||
s.Require().NoError(err)
|
||||
defer os.Remove(tmpdir)
|
||||
|
||||
s.StartTestBackend()
|
||||
defer s.StopTestBackend()
|
||||
wallet := common.HexToAddress(TestConfig.Account1.WalletAddress)
|
||||
s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password,
|
||||
[]accounts.Account{{Address: wallet, Wallet: true, Chat: true}},
|
||||
e2e.WithDataDir(tmpdir),
|
||||
)
|
||||
defer s.LogoutAndStop()
|
||||
|
||||
EnsureNodeSync(s.Backend.StatusNode().EnsureSync)
|
||||
|
||||
err := s.Backend.AccountManager().SelectAccount(buildLoginParams(TestConfig.Account1.WalletAddress, TestConfig.Account1.ChatAddress, TestConfig.Account1.Password))
|
||||
s.NoError(err)
|
||||
|
||||
hash, err := s.Backend.SendTransaction(transactions.SendTxArgs{
|
||||
From: account.FromAddress(TestConfig.Account1.WalletAddress),
|
||||
To: account.ToAddress(TestConfig.Account2.WalletAddress),
|
||||
|
@ -220,13 +238,19 @@ func (s *TransactionsTestSuite) TestSendEther() {
|
|||
func (s *TransactionsTestSuite) TestSendEtherTxUpstream() {
|
||||
CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "transactions-tests-")
|
||||
s.Require().NoError(err)
|
||||
defer os.Remove(tmpdir)
|
||||
addr, err := GetRemoteURL()
|
||||
s.NoError(err)
|
||||
s.StartTestBackend(e2e.WithUpstream(addr))
|
||||
defer s.StopTestBackend()
|
||||
|
||||
err = s.Backend.SelectAccount(buildLoginParams(TestConfig.Account1.WalletAddress, TestConfig.Account1.ChatAddress, TestConfig.Account1.Password))
|
||||
s.NoError(err)
|
||||
wallet := common.HexToAddress(TestConfig.Account1.WalletAddress)
|
||||
s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password,
|
||||
[]accounts.Account{{Address: wallet, Wallet: true, Chat: true}},
|
||||
e2e.WithUpstream(addr),
|
||||
e2e.WithDataDir(tmpdir),
|
||||
)
|
||||
defer s.LogoutAndStop()
|
||||
|
||||
hash, err := s.Backend.SendTransaction(transactions.SendTxArgs{
|
||||
From: account.FromAddress(TestConfig.Account1.WalletAddress),
|
||||
|
|
|
@ -15,8 +15,10 @@ var (
|
|||
ErrInvalidSendTxArgs = errors.New("transaction arguments are invalid")
|
||||
// ErrUnexpectedArgs is returned when args are of unexpected length.
|
||||
ErrUnexpectedArgs = errors.New("unexpected args")
|
||||
//ErrInvalidTxSender is returned when selected account is different tham From field.
|
||||
//ErrInvalidTxSender is returned when selected account is different than From field.
|
||||
ErrInvalidTxSender = errors.New("transaction can only be send by its creator")
|
||||
//ErrAccountDoesntExist is sent when provided sub-account is not stored in database.
|
||||
ErrAccountDoesntExist = errors.New("account doesn't exist")
|
||||
)
|
||||
|
||||
// PendingNonceProvider provides information about nonces.
|
||||
|
|
Loading…
Reference in New Issue