Passing Master info to Messenger

This commit is contained in:
Samuel Hawksby-Robinson 2020-12-09 14:03:43 +00:00 committed by Andrea Maria Piana
parent 0b6061b444
commit 16fecf5520
11 changed files with 72 additions and 33 deletions

View File

@ -61,13 +61,15 @@ func (m *Manager) AccountsGenerator() *generator.Generator {
// BIP44-compatible keys are generated: CKD#1 is stored as account key, CKD#2 stored as sub-account root // 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 // Public key of CKD#1 is returned, with CKD#2 securely encoded into account key file (to be used for
// sub-account derivations) // sub-account derivations)
func (m *Manager) CreateAccount(password string) (Info, string, error) { func (m *Manager) CreateAccount(password string) (generator.IdentifiedAccountInfo, Info, string, error) {
var mkInfo generator.IdentifiedAccountInfo
info := Info{} info := Info{}
// generate mnemonic phrase // generate mnemonic phrase
mn := extkeys.NewMnemonic() mn := extkeys.NewMnemonic()
mnemonic, err := mn.MnemonicPhrase(extkeys.EntropyStrength128, extkeys.EnglishLanguage) mnemonic, err := mn.MnemonicPhrase(extkeys.EntropyStrength128, extkeys.EnglishLanguage)
if err != nil { if err != nil {
return info, "", fmt.Errorf("can not create mnemonic seed: %v", err) return mkInfo, info, "", fmt.Errorf("can not create mnemonic seed: %v", err)
} }
// Generate extended master key (see BIP32) // Generate extended master key (see BIP32)
@ -77,19 +79,21 @@ func (m *Manager) CreateAccount(password string) (Info, string, error) {
// for expert users, to be able to add a passphrase to the generation of the seed. // for expert users, to be able to add a passphrase to the generation of the seed.
extKey, err := extkeys.NewMaster(mn.MnemonicSeed(mnemonic, "")) extKey, err := extkeys.NewMaster(mn.MnemonicSeed(mnemonic, ""))
if err != nil { if err != nil {
return info, "", fmt.Errorf("can not create master extended key: %v", err) return mkInfo, info, "", fmt.Errorf("can not create master extended key: %v", err)
} }
mkInfo = generator.IdentifiedAccountInfoFromExtKey(extKey)
// import created key into account keystore // import created key into account keystore
info.WalletAddress, info.WalletPubKey, err = m.importExtendedKey(extkeys.KeyPurposeWallet, extKey, password) info.WalletAddress, info.WalletPubKey, err = m.importExtendedKey(extkeys.KeyPurposeWallet, extKey, password)
if err != nil { if err != nil {
return info, "", err return mkInfo, info, "", err
} }
info.ChatAddress = info.WalletAddress info.ChatAddress = info.WalletAddress
info.ChatPubKey = info.WalletPubKey info.ChatPubKey = info.WalletPubKey
return info, mnemonic, nil return mkInfo, info, mnemonic, nil
} }
// RecoverAccount re-creates master key using given details. // RecoverAccount re-creates master key using given details.

View File

@ -146,7 +146,7 @@ func (s *ManagerTestSuite) SetupTest() {
testPassword := "test-password" testPassword := "test-password"
// Initial test - create test account // Initial test - create test account
accountInfo, mnemonic, err := s.accManager.CreateAccount(testPassword) _, accountInfo, mnemonic, err := s.accManager.CreateAccount(testPassword)
s.Require().NoError(err) s.Require().NoError(err)
s.Require().NotEmpty(accountInfo.WalletAddress) s.Require().NotEmpty(accountInfo.WalletAddress)
s.Require().NotEmpty(accountInfo.WalletPubKey) s.Require().NotEmpty(accountInfo.WalletPubKey)

View File

@ -79,3 +79,12 @@ type GeneratedAndDerivedAccountInfo struct {
GeneratedAccountInfo GeneratedAccountInfo
Derived map[string]AccountInfo `json:"derived"` Derived map[string]AccountInfo `json:"derived"`
} }
func IdentifiedAccountInfoFromExtKey(extKey *extkeys.ExtendedKey) IdentifiedAccountInfo {
acc := account{
privateKey: extKey.ToECDSA(),
extendedKey: extKey,
}
return acc.toIdentifiedAccountInfo("")
}

View File

@ -242,7 +242,7 @@ func initNodeAndLogin(t *testing.T, backend *GethStatusBackend) (string, string)
require.NoError(t, backend.AccountManager().InitKeystore(config.KeyStoreDir)) require.NoError(t, backend.AccountManager().InitKeystore(config.KeyStoreDir))
err = backend.StartNode(config) err = backend.StartNode(config)
require.NoError(t, err) require.NoError(t, err)
info, _, err := backend.AccountManager().CreateAccount(password) _, info, _, err := backend.AccountManager().CreateAccount(password)
require.NoError(t, err) require.NoError(t, err)
loginParams := account.LoginParams{ loginParams := account.LoginParams{

View File

@ -187,7 +187,7 @@ func TestBackendAccountsConcurrently(t *testing.T) {
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
wgCreateAccounts.Add(1) wgCreateAccounts.Add(1)
go func(pass string) { go func(pass string) {
accountInfo, _, err := backend.AccountManager().CreateAccount(pass) _, accountInfo, _, err := backend.AccountManager().CreateAccount(pass)
assert.NoError(t, err) assert.NoError(t, err)
addressCh <- [...]string{accountInfo.WalletAddress, accountInfo.ChatAddress, pass} addressCh <- [...]string{accountInfo.WalletAddress, accountInfo.ChatAddress, pass}
wgCreateAccounts.Done() wgCreateAccounts.Done()

View File

@ -78,6 +78,7 @@ type GethStatusBackend struct {
personalAPI *personal.PublicAPI personalAPI *personal.PublicAPI
rpcFilters *rpcfilters.Service rpcFilters *rpcfilters.Service
multiaccountsDB *multiaccounts.Database multiaccountsDB *multiaccounts.Database
account *multiaccounts.Account
accountManager *account.GethManager accountManager *account.GethManager
transactor *transactions.Transactor transactor *transactions.Transactor
connectionState connectionState connectionState connectionState
@ -266,6 +267,8 @@ func (b *GethStatusBackend) startNodeWithKey(acc multiaccounts.Account, password
if err := logutils.OverrideRootLogWithConfig(conf, false); err != nil { if err := logutils.OverrideRootLogWithConfig(conf, false); err != nil {
return err return err
} }
b.account = &acc
accountsDB := accounts.NewDB(b.appDB) accountsDB := accounts.NewDB(b.appDB)
walletAddr, err := accountsDB.GetWalletAddress() walletAddr, err := accountsDB.GetWalletAddress()
if err != nil { if err != nil {
@ -322,6 +325,7 @@ func (b *GethStatusBackend) startNodeWithAccount(acc multiaccounts.Account, pass
if err := logutils.OverrideRootLogWithConfig(conf, false); err != nil { if err := logutils.OverrideRootLogWithConfig(conf, false); err != nil {
return err return err
} }
b.account = &acc
accountsDB := accounts.NewDB(b.appDB) accountsDB := accounts.NewDB(b.appDB)
chatAddr, err := accountsDB.GetChatAddress() chatAddr, err := accountsDB.GetChatAddress()
if err != nil { if err != nil {
@ -1104,6 +1108,14 @@ func (b *GethStatusBackend) SelectAccount(loginParams account.LoginParams) error
return nil return nil
} }
func (b *GethStatusBackend) GetActiveAccount() (*multiaccounts.Account, error) {
if b.account == nil {
return nil, errors.New("master key account is nil in the GetStatusBackend")
}
return b.account, nil
}
func (b *GethStatusBackend) injectAccountsIntoServices() error { func (b *GethStatusBackend) injectAccountsIntoServices() error {
chatAccount, err := b.accountManager.SelectedChatAccount() chatAccount, err := b.accountManager.SelectedChatAccount()
if err != nil { if err != nil {
@ -1127,13 +1139,18 @@ func (b *GethStatusBackend) injectAccountsIntoServices() error {
return err return err
} }
acc, err := b.GetActiveAccount()
if err != nil {
return err
}
if whisperService != nil { if whisperService != nil {
st, err := b.statusNode.ShhExtService() st, err := b.statusNode.ShhExtService()
if err != nil { if err != nil {
return err return err
} }
if err := st.InitProtocol(identity, b.appDB, b.multiaccountsDB, logutils.ZapLogger()); err != nil { if err := st.InitProtocol(identity, b.appDB, b.multiaccountsDB, acc, logutils.ZapLogger()); err != nil {
return err return err
} }
return nil return nil
@ -1161,7 +1178,7 @@ func (b *GethStatusBackend) injectAccountsIntoServices() error {
return err return err
} }
if err := st.InitProtocol(identity, b.appDB, b.multiaccountsDB, logutils.ZapLogger()); err != nil { if err := st.InitProtocol(identity, b.appDB, b.multiaccountsDB, acc, logutils.ZapLogger()); err != nil {
return err return err
} }
} }

View File

@ -3,7 +3,6 @@ package protocol
import ( import (
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/sha256"
"database/sql" "database/sql"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -22,7 +21,6 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
gethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
enstypes "github.com/status-im/status-go/eth-node/types/ens" enstypes "github.com/status-im/status-go/eth-node/types/ens"
@ -85,6 +83,7 @@ type Messenger struct {
mailserver []byte mailserver []byte
database *sql.DB database *sql.DB
multiAccounts *multiaccounts.Database multiAccounts *multiaccounts.Database
account *multiaccounts.Account
quit chan struct{} quit chan struct{}
mutex sync.Mutex mutex sync.Mutex
@ -285,6 +284,7 @@ func NewMessenger(
verifyTransactionClient: c.verifyTransactionClient, verifyTransactionClient: c.verifyTransactionClient,
database: database, database: database,
multiAccounts: c.multiAccount, multiAccounts: c.multiAccount,
account: c.account,
quit: make(chan struct{}), quit: make(chan struct{}),
shutdownTasks: []func() error{ shutdownTasks: []func() error{
database.Close, database.Close,
@ -573,10 +573,7 @@ func (m *Messenger) shouldPublishChatIdentity(chatID string) (bool, error) {
// context 'public-chat' will attach only the 'thumbnail' IdentityImage // context 'public-chat' will attach only the 'thumbnail' IdentityImage
// context 'private-chat' will attach all IdentityImage // context 'private-chat' will attach all IdentityImage
func (m *Messenger) createChatIdentity(context string) (*protobuf.ChatIdentity, error) { func (m *Messenger) createChatIdentity(context string) (*protobuf.ChatIdentity, error) {
keyUIDBytes := sha256.Sum256(gethcrypto.FromECDSAPub(&m.identity.PublicKey)) m.logger.Info(fmt.Sprintf("account keyUID '%s'", m.account.KeyUID))
keyUID := types.EncodeHex(keyUIDBytes[:])
m.logger.Info(fmt.Sprintf("generated keyUID '%s' from PublicKey", keyUID))
m.logger.Info(fmt.Sprintf("context '%s'", context)) m.logger.Info(fmt.Sprintf("context '%s'", context))
ci := &protobuf.ChatIdentity{ ci := &protobuf.ChatIdentity{
@ -590,7 +587,7 @@ func (m *Messenger) createChatIdentity(context string) (*protobuf.ChatIdentity,
case "public-chat": case "public-chat":
m.logger.Info(fmt.Sprintf("handling public-chat ChatIdentity")) m.logger.Info(fmt.Sprintf("handling public-chat ChatIdentity"))
img, err := m.multiAccounts.GetIdentityImage(keyUID, userimage.SmallDimName) img, err := m.multiAccounts.GetIdentityImage(m.account.KeyUID, userimage.SmallDimName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -599,12 +596,12 @@ func (m *Messenger) createChatIdentity(context string) (*protobuf.ChatIdentity,
m.logger.Info(fmt.Sprintf("public-chat images.IdentityImage '%s' '%s'", string(imgJson), spew.Sdump(img))) m.logger.Info(fmt.Sprintf("public-chat images.IdentityImage '%s' '%s'", string(imgJson), spew.Sdump(img)))
ciis[userimage.SmallDimName] = m.adaptIdentityImageToProtobuf(img) ciis[userimage.SmallDimName] = m.adaptIdentityImageToProtobuf(img)
m.logger.Info(fmt.Sprintf("public-chat protobuf.IdentityImage '%s'", spew.Sdump(ciis))) //m.logger.Info(fmt.Sprintf("public-chat protobuf.IdentityImage '%s'", spew.Sdump(ciis)))
ci.Images = ciis ci.Images = ciis
case "private-chat": case "private-chat":
m.logger.Info(fmt.Sprintf("handling private-chat ChatIdentity")) m.logger.Info(fmt.Sprintf("handling private-chat ChatIdentity"))
imgs, err := m.multiAccounts.GetIdentityImages(keyUID) imgs, err := m.multiAccounts.GetIdentityImages(m.account.KeyUID)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -32,6 +32,7 @@ type config struct {
dbConfig dbConfig dbConfig dbConfig
db *sql.DB db *sql.DB
multiAccount *multiaccounts.Database multiAccount *multiaccounts.Database
account *multiaccounts.Account
verifyTransactionClient EthClient verifyTransactionClient EthClient
@ -101,6 +102,13 @@ func WithMultiAccounts(ma *multiaccounts.Database) Option {
} }
} }
func WithAccount(acc *multiaccounts.Account) Option {
return func(c *config) error {
c.account = acc
return nil
}
}
func WithPushNotificationServerConfig(pushNotificationServerConfig *pushnotificationserver.Config) Option { func WithPushNotificationServerConfig(pushNotificationServerConfig *pushnotificationserver.Config) Option {
return func(c *config) error { return func(c *config) error {
c.pushNotificationServerConfig = pushNotificationServerConfig c.pushNotificationServerConfig = pushNotificationServerConfig

View File

@ -70,6 +70,7 @@ type Service struct {
lastUsedMonitor *mailservers.LastUsedConnectionMonitor lastUsedMonitor *mailservers.LastUsedConnectionMonitor
accountsDB *accounts.Database accountsDB *accounts.Database
multiAccountsDB *multiaccounts.Database multiAccountsDB *multiaccounts.Database
account *multiaccounts.Account
} }
// Make sure that Service implements node.Service interface. // Make sure that Service implements node.Service interface.
@ -115,7 +116,7 @@ func (s *Service) GetPeer(rawURL string) (*enode.Node, error) {
return enode.ParseV4(rawURL) return enode.ParseV4(rawURL)
} }
func (s *Service) InitProtocol(identity *ecdsa.PrivateKey, db *sql.DB, multiAccountDb *multiaccounts.Database, logger *zap.Logger) error { func (s *Service) InitProtocol(identity *ecdsa.PrivateKey, db *sql.DB, multiAccountDb *multiaccounts.Database, acc *multiaccounts.Account, logger *zap.Logger) error {
if !s.config.PFSEnabled { if !s.config.PFSEnabled {
return nil return nil
} }
@ -148,8 +149,9 @@ func (s *Service) InitProtocol(identity *ecdsa.PrivateKey, db *sql.DB, multiAcco
} }
s.accountsDB = accounts.NewDB(db) s.accountsDB = accounts.NewDB(db)
s.multiAccountsDB = multiAccountDb s.multiAccountsDB = multiAccountDb
s.account = acc
options, err := buildMessengerOptions(s.config, identity, db, s.multiAccountsDB, envelopesMonitorConfig, s.accountsDB, logger) options, err := buildMessengerOptions(s.config, identity, db, s.multiAccountsDB, acc, envelopesMonitorConfig, s.accountsDB, logger)
if err != nil { if err != nil {
return err return err
} }
@ -456,6 +458,7 @@ func buildMessengerOptions(
identity *ecdsa.PrivateKey, identity *ecdsa.PrivateKey,
db *sql.DB, db *sql.DB,
multiAccounts *multiaccounts.Database, multiAccounts *multiaccounts.Database,
account *multiaccounts.Account,
envelopesMonitorConfig *transport.EnvelopesMonitorConfig, envelopesMonitorConfig *transport.EnvelopesMonitorConfig,
accountsDB *accounts.Database, accountsDB *accounts.Database,
logger *zap.Logger, logger *zap.Logger,
@ -465,6 +468,7 @@ func buildMessengerOptions(
protocol.WithPushNotifications(), protocol.WithPushNotifications(),
protocol.WithDatabase(db), protocol.WithDatabase(db),
protocol.WithMultiAccounts(multiAccounts), protocol.WithMultiAccounts(multiAccounts),
protocol.WithAccount(account),
protocol.WithEnvelopesMonitorConfig(envelopesMonitorConfig), protocol.WithEnvelopesMonitorConfig(envelopesMonitorConfig),
protocol.WithOnNegotiatedFilters(onNegotiatedFilters), protocol.WithOnNegotiatedFilters(onNegotiatedFilters),
} }

View File

@ -46,7 +46,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)")
// create an account // create an account
accountInfo, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) _, accountInfo, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
// ensure that there is still no accounts returned // ensure that there is still no accounts returned
@ -131,7 +131,7 @@ func (s *AccountsTestSuite) TestRecoverAccount() {
s.NotNil(keyStore) s.NotNil(keyStore)
// create an acc // create an acc
accountInfo, mnemonic, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) _, accountInfo, mnemonic, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s, mnemonic:%s}", s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s, mnemonic:%s}",
accountInfo.WalletAddress, accountInfo.WalletPubKey, accountInfo.ChatAddress, accountInfo.ChatPubKey, mnemonic) accountInfo.WalletAddress, accountInfo.WalletPubKey, accountInfo.ChatAddress, accountInfo.ChatPubKey, mnemonic)
@ -172,12 +172,12 @@ func (s *AccountsTestSuite) TestSelectAccount() {
defer s.StopTestBackend() defer s.StopTestBackend()
// create an account // create an account
accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) _, accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}", s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}",
accountInfo1.WalletAddress, accountInfo1.WalletPubKey, accountInfo1.ChatAddress, accountInfo1.ChatPubKey) accountInfo1.WalletAddress, accountInfo1.WalletPubKey, accountInfo1.ChatAddress, accountInfo1.ChatPubKey)
accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) _, accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}", s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}",
accountInfo2.WalletAddress, accountInfo2.WalletPubKey, accountInfo2.ChatAddress, accountInfo2.ChatPubKey) accountInfo2.WalletAddress, accountInfo2.WalletPubKey, accountInfo2.ChatAddress, accountInfo2.ChatPubKey)
@ -218,9 +218,9 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() {
s.StartTestBackend() s.StartTestBackend()
// create test accounts // create test accounts
accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) _, accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) _, accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
// make sure that no account is selected by default // make sure that no account is selected by default

View File

@ -108,11 +108,11 @@ func (s *WhisperTestSuite) TestSelectAccount() {
s.NoError(err) s.NoError(err)
// create account 1 // create account 1
accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) _, accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
// create account 2 // create account 2
accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account2.Password) _, accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account2.Password)
s.NoError(err) s.NoError(err)
// make sure that identities are not injected yet // make sure that identities are not injected yet
@ -142,7 +142,7 @@ func (s *WhisperTestSuite) TestLogout() {
s.NoError(err) s.NoError(err)
// create an account // create an account
accountInfo, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) _, accountInfo, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
// make sure that identity doesn't exist (yet) in Whisper // make sure that identity doesn't exist (yet) in Whisper
@ -162,9 +162,9 @@ func (s *WhisperTestSuite) TestSelectedAccountOnRestart() {
whisperService := s.WhisperService() whisperService := s.WhisperService()
// create test accounts // create test accounts
accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) _, accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account2.Password) _, accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account2.Password)
s.NoError(err) s.NoError(err)
// make sure that identity is not (yet injected) // make sure that identity is not (yet injected)
@ -259,7 +259,7 @@ func (s *WhisperTestSuite) TestSelectedChatKeyIsUsedInWhisper() {
s.NoError(err) s.NoError(err)
// create an account // create an account
accountInfo, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) _, accountInfo, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
// select account // select account