273 lines
11 KiB
Go
273 lines
11 KiB
Go
package whisper
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
"github.com/status-im/status-go/account"
|
|
e2e "github.com/status-im/status-go/t/e2e"
|
|
. "github.com/status-im/status-go/t/utils"
|
|
"github.com/status-im/status-go/whisper/v6"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
func TestWhisperTestSuite(t *testing.T) {
|
|
suite.Run(t, new(WhisperTestSuite))
|
|
}
|
|
|
|
type WhisperTestSuite struct {
|
|
e2e.BackendTestSuite
|
|
}
|
|
|
|
func buildLoginParams(mainAccountAddress, chatAddress, password string) account.LoginParams {
|
|
return account.LoginParams{
|
|
ChatAddress: common.HexToAddress(chatAddress),
|
|
Password: password,
|
|
MainAccount: common.HexToAddress(mainAccountAddress),
|
|
}
|
|
}
|
|
|
|
// TODO(adam): can anyone explain what this test is testing?
|
|
// I don't see any race condition testing here.
|
|
func (s *WhisperTestSuite) TestWhisperFilterRace() {
|
|
s.StartTestBackend()
|
|
defer s.StopTestBackend()
|
|
|
|
whisperService, err := s.Backend.StatusNode().WhisperService()
|
|
s.NoError(err)
|
|
|
|
accountManager := s.Backend.AccountManager()
|
|
s.NotNil(accountManager)
|
|
|
|
whisperAPI := whisper.NewPublicWhisperAPI(whisperService)
|
|
|
|
// account1
|
|
_, accountKey1, err := accountManager.AddressToDecryptedAccount(TestConfig.Account1.ChatAddress, TestConfig.Account1.Password)
|
|
s.NoError(err)
|
|
accountKey1Byte := crypto.FromECDSAPub(&accountKey1.PrivateKey.PublicKey)
|
|
|
|
key1ID, err := whisperService.AddKeyPair(accountKey1.PrivateKey)
|
|
s.NoError(err)
|
|
ok := whisperAPI.HasKeyPair(context.Background(), key1ID)
|
|
s.True(ok, "identity not injected")
|
|
|
|
// account2
|
|
_, accountKey2, err := accountManager.AddressToDecryptedAccount(TestConfig.Account2.ChatAddress, TestConfig.Account2.Password)
|
|
s.NoError(err)
|
|
key2ID, err := whisperService.AddKeyPair(accountKey2.PrivateKey)
|
|
s.NoError(err)
|
|
ok = whisperAPI.HasKeyPair(context.Background(), key2ID)
|
|
s.True(ok, "identity not injected")
|
|
|
|
// race filter addition
|
|
filterAdded := make(chan struct{})
|
|
allFiltersAdded := make(chan struct{})
|
|
|
|
go func() {
|
|
counter := 10
|
|
for range filterAdded {
|
|
counter--
|
|
if counter <= 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
close(allFiltersAdded)
|
|
}()
|
|
|
|
for i := 0; i < 10; i++ {
|
|
go func() {
|
|
// nolint: errcheck
|
|
whisperAPI.NewMessageFilter(whisper.Criteria{
|
|
Sig: accountKey1Byte,
|
|
PrivateKeyID: key2ID,
|
|
Topics: []whisper.TopicType{
|
|
{0x4e, 0x03, 0x65, 0x7a},
|
|
{0x34, 0x60, 0x7c, 0x9b},
|
|
{0x21, 0x41, 0x7d, 0xf9},
|
|
},
|
|
})
|
|
filterAdded <- struct{}{}
|
|
}()
|
|
}
|
|
|
|
<-allFiltersAdded
|
|
}
|
|
|
|
func (s *WhisperTestSuite) TestSelectAccount() {
|
|
s.StartTestBackend()
|
|
defer s.StopTestBackend()
|
|
|
|
whisperService, err := s.Backend.StatusNode().WhisperService()
|
|
s.NoError(err)
|
|
|
|
// create account 1
|
|
accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
|
|
s.NoError(err)
|
|
|
|
// create account 2
|
|
accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account2.Password)
|
|
s.NoError(err)
|
|
|
|
// make sure that identities are not injected yet
|
|
s.False(whisperService.HasKeyPair(accountInfo1.ChatPubKey), "identity already present in whisper")
|
|
s.False(whisperService.HasKeyPair(accountInfo2.ChatPubKey), "identity already present in whisper")
|
|
|
|
// try selecting with wrong password
|
|
err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, "wrongpassword"))
|
|
s.NotNil(err)
|
|
|
|
// select account 1
|
|
err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, TestConfig.Account1.Password))
|
|
s.NoError(err)
|
|
s.True(whisperService.HasKeyPair(accountInfo1.ChatPubKey), "identity not injected in whisper")
|
|
|
|
// select account 2, make sure that previous account is wiped out from Whisper cache
|
|
s.False(whisperService.HasKeyPair(accountInfo2.ChatPubKey), "identity already present in whisper")
|
|
s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, TestConfig.Account2.Password)))
|
|
s.True(whisperService.HasKeyPair(accountInfo2.ChatPubKey), "identity not injected into whisper")
|
|
}
|
|
|
|
func (s *WhisperTestSuite) TestLogout() {
|
|
s.StartTestBackend()
|
|
defer s.StopTestBackend()
|
|
|
|
whisperService, err := s.Backend.StatusNode().WhisperService()
|
|
s.NoError(err)
|
|
|
|
// create an account
|
|
accountInfo, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
|
|
s.NoError(err)
|
|
|
|
// make sure that identity doesn't exist (yet) in Whisper
|
|
s.False(whisperService.HasKeyPair(accountInfo.ChatPubKey), "identity already present in whisper")
|
|
s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo.WalletAddress, accountInfo.ChatAddress, TestConfig.Account1.Password)))
|
|
s.True(whisperService.HasKeyPair(accountInfo.ChatPubKey), "identity not injected into whisper")
|
|
|
|
s.NoError(s.Backend.Logout())
|
|
s.False(whisperService.HasKeyPair(accountInfo.ChatPubKey), "identity not cleared from whisper")
|
|
}
|
|
|
|
func (s *WhisperTestSuite) TestSelectedAccountOnRestart() {
|
|
s.StartTestBackend()
|
|
|
|
// we need to make sure that selected account is injected as identity into Whisper
|
|
whisperService := s.WhisperService()
|
|
|
|
// create test accounts
|
|
accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
|
|
s.NoError(err)
|
|
accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account2.Password)
|
|
s.NoError(err)
|
|
|
|
// make sure that identity is not (yet injected)
|
|
s.False(whisperService.HasKeyPair(accountInfo1.ChatPubKey), "identity already present in whisper")
|
|
|
|
// make sure that no wallet account is selected by default
|
|
selectedWalletAccount, err := s.Backend.AccountManager().MainAccountAddress()
|
|
s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be")
|
|
s.Equal(common.Address{}, selectedWalletAccount)
|
|
|
|
// make sure that no chat account is selected by default
|
|
selectedChatAccount, err := s.Backend.AccountManager().SelectedChatAccount()
|
|
s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be")
|
|
s.Nil(selectedChatAccount)
|
|
|
|
// select account with wrong password
|
|
err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, "wrongPassword"))
|
|
expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password")
|
|
s.EqualError(expectedErr, err.Error())
|
|
|
|
// select account with right password
|
|
s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, TestConfig.Account1.Password)))
|
|
selectedChatAccount1, err := s.Backend.AccountManager().SelectedChatAccount()
|
|
s.NoError(err)
|
|
selectedChatPubKey1 := hexutil.Encode(crypto.FromECDSAPub(&selectedChatAccount1.AccountKey.PrivateKey.PublicKey))
|
|
s.Equal(selectedChatPubKey1, accountInfo1.ChatPubKey)
|
|
s.True(whisperService.HasKeyPair(selectedChatPubKey1), "identity not injected into whisper")
|
|
|
|
// select another account, make sure that previous account is wiped out from Whisper cache
|
|
s.False(whisperService.HasKeyPair(accountInfo2.ChatPubKey), "identity already present in whisper")
|
|
s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, TestConfig.Account2.Password)))
|
|
selectedChatAccount2, err := s.Backend.AccountManager().SelectedChatAccount()
|
|
s.NoError(err)
|
|
selectedChatPubKey2 := hexutil.Encode(crypto.FromECDSAPub(&selectedChatAccount2.AccountKey.PrivateKey.PublicKey))
|
|
s.Equal(selectedChatPubKey2, accountInfo2.ChatPubKey)
|
|
s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
|
|
s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should be removed, but it is still present in whisper")
|
|
|
|
// stop node (and all of its sub-protocols)
|
|
nodeConfig := s.Backend.StatusNode().Config()
|
|
s.NotNil(nodeConfig)
|
|
preservedNodeConfig := *nodeConfig
|
|
s.NoError(s.Backend.StopNode())
|
|
|
|
// resume node
|
|
s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig))
|
|
|
|
// re-check selected account (account2 MUST be selected)
|
|
selectedWalletAccount, err = s.Backend.AccountManager().MainAccountAddress()
|
|
s.NoError(err)
|
|
s.NotNil(selectedWalletAccount)
|
|
s.Equal(selectedWalletAccount.String(), accountInfo2.WalletAddress, "incorrect wallet address selected")
|
|
selectedChatAccount, err = s.Backend.AccountManager().SelectedChatAccount()
|
|
s.NoError(err)
|
|
s.NotNil(selectedChatAccount)
|
|
s.Equal(selectedChatAccount.Address.Hex(), accountInfo2.ChatAddress, "incorrect chat address selected")
|
|
|
|
// make sure that Whisper gets identity re-injected
|
|
whisperService = s.WhisperService()
|
|
s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
|
|
s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should not be present, but it is still present in whisper")
|
|
|
|
// now restart node using RestartNode() method, and make sure that account is still available
|
|
s.RestartTestNode()
|
|
defer s.StopTestBackend()
|
|
|
|
whisperService = s.WhisperService()
|
|
s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
|
|
s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should not be present, but it is still present in whisper")
|
|
|
|
// now logout, and make sure that on restart no account is selected (i.e. logout works properly)
|
|
s.NoError(s.Backend.Logout())
|
|
s.RestartTestNode()
|
|
whisperService = s.WhisperService()
|
|
s.False(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
|
|
s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should not be present, but it is still present in whisper")
|
|
|
|
selectedWalletAccount, err = s.Backend.AccountManager().MainAccountAddress()
|
|
s.EqualError(account.ErrNoAccountSelected, err.Error())
|
|
s.Equal(common.Address{}, selectedWalletAccount)
|
|
|
|
selectedChatAccount, err = s.Backend.AccountManager().SelectedChatAccount()
|
|
s.EqualError(account.ErrNoAccountSelected, err.Error())
|
|
s.Nil(selectedChatAccount)
|
|
}
|
|
|
|
func (s *WhisperTestSuite) TestSelectedChatKeyIsUsedInWhisper() {
|
|
s.StartTestBackend()
|
|
defer s.StopTestBackend()
|
|
|
|
whisperService, err := s.Backend.StatusNode().WhisperService()
|
|
s.NoError(err)
|
|
|
|
// create an account
|
|
accountInfo, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
|
|
s.NoError(err)
|
|
|
|
// select account
|
|
s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo.WalletAddress, accountInfo.ChatAddress, TestConfig.Account1.Password)))
|
|
|
|
// Get the chat account
|
|
selectedChatAccount, err := s.Backend.AccountManager().SelectedChatAccount()
|
|
s.NoError(err)
|
|
|
|
// chat key should be injected in whisper
|
|
selectedChatPubKey := hexutil.Encode(crypto.FromECDSAPub(&selectedChatAccount.AccountKey.PrivateKey.PublicKey))
|
|
s.True(whisperService.HasKeyPair(selectedChatPubKey), "identity not injected in whisper")
|
|
}
|