Send account/settings on login

This commit is contained in:
Andrea Maria Piana 2023-07-05 16:56:34 +01:00
parent dffcb708ea
commit e08aad7d73
9 changed files with 126 additions and 64 deletions

View File

@ -312,7 +312,7 @@ func (b *GethStatusBackend) runDBFileMigrations(account multiaccounts.Account, p
}
if _, err = os.Stat(v3Path); err == nil {
if err := appdatabase.MigrateV3ToV4(v3Path, v4Path, password, account.KDFIterations); err != nil {
if err := appdatabase.MigrateV3ToV4(v3Path, v4Path, password, account.KDFIterations, signal.SendReEncryptionStarted, signal.SendReEncryptionFinished); err != nil {
_ = os.Remove(v4Path)
_ = os.Remove(v4Path + "-shm")
_ = os.Remove(v4Path + "-wal")
@ -450,11 +450,13 @@ func (b *GethStatusBackend) StartNodeWithKey(acc multiaccounts.Account, password
if err != nil {
// Stop node for clean up
_ = b.StopNode()
return err
}
// get logged in
if !b.localPairing {
signal.SendLoggedIn(err)
return b.LoggedIn(acc.KeyUID, err)
}
return err
return nil
}
func (b *GethStatusBackend) OverwriteNodeConfigValues(conf *params.NodeConfig, n *params.NodeConfig) (*params.NodeConfig, error) {
@ -504,9 +506,9 @@ func (b *GethStatusBackend) LoginAccount(request *requests.Login) error {
if err != nil {
// Stop node for clean up
_ = b.StopNode()
return err
}
signal.SendLoggedIn(err)
return err
return b.LoggedIn(request.KeyUID, err)
}
func (b *GethStatusBackend) loginAccount(request *requests.Login) error {
@ -665,6 +667,20 @@ func (b *GethStatusBackend) startNodeWithAccount(acc multiaccounts.Account, pass
return nil
}
func (b *GethStatusBackend) GetSettings() (*settings.Settings, error) {
accountDB, err := accounts.NewDB(b.appDB)
if err != nil {
return nil, err
}
settings, err := accountDB.GetSettings()
if err != nil {
return nil, err
}
return &settings, nil
}
func (b *GethStatusBackend) MigrateKeyStoreDir(acc multiaccounts.Account, password, oldDir, newDir string) error {
err := b.ensureAppDBOpened(acc, password)
if err != nil {
@ -704,11 +720,31 @@ func (b *GethStatusBackend) StartNodeWithAccount(acc multiaccounts.Account, pass
if err != nil {
// Stop node for clean up
_ = b.StopNode()
return err
}
// get logged in
if !b.localPairing {
signal.SendLoggedIn(err)
return b.LoggedIn(acc.KeyUID, err)
}
return err
return nil
}
func (b *GethStatusBackend) LoggedIn(keyUID string, err error) error {
if err != nil {
signal.SendLoggedIn(nil, nil, err)
return nil
}
settings, err := b.GetSettings()
if err != nil {
return err
}
account, err := b.getAccountByKeyUID(keyUID)
if err != nil {
return err
}
signal.SendLoggedIn(account, settings, nil)
return nil
}
func (b *GethStatusBackend) ExportUnencryptedDatabase(acc multiaccounts.Account, password, directory string) error {
@ -746,7 +782,7 @@ func (b *GethStatusBackend) ImportUnencryptedDatabase(acc multiaccounts.Account,
path := filepath.Join(b.rootDataDir, fmt.Sprintf("%s-v4.db", acc.KeyUID))
err := appdatabase.EncryptDatabase(databasePath, path, password, acc.KDFIterations)
err := appdatabase.EncryptDatabase(databasePath, path, password, acc.KDFIterations, signal.SendReEncryptionStarted, signal.SendReEncryptionFinished)
if err != nil {
b.log.Error("failed to initialize db", "err", err)
return err
@ -795,7 +831,7 @@ func (b *GethStatusBackend) ChangeDatabasePassword(keyUID string, password strin
}()
// Exporting database to a temporary file with a new password
err = appdatabase.ExportDB(dbPath, password, account.KDFIterations, newDBPath, newPassword)
err = appdatabase.ExportDB(dbPath, password, account.KDFIterations, newDBPath, newPassword, signal.SendReEncryptionStarted, signal.SendReEncryptionFinished)
if err != nil {
return err
}

View File

@ -69,16 +69,16 @@ func DecryptDatabase(oldPath, newPath, password string, kdfIterationsNumber int)
// EncryptDatabase creates an encrypted copy of the database and copies it to the
// user path
func EncryptDatabase(oldPath, newPath, password string, kdfIterationsNumber int) error {
return sqlite.EncryptDB(oldPath, newPath, password, kdfIterationsNumber)
func EncryptDatabase(oldPath, newPath, password string, kdfIterationsNumber int, onStart func(), onEnd func()) error {
return sqlite.EncryptDB(oldPath, newPath, password, kdfIterationsNumber, onStart, onEnd)
}
func ExportDB(path string, password string, kdfIterationsNumber int, newDbPAth string, newPassword string) error {
return sqlite.ExportDB(path, password, kdfIterationsNumber, newDbPAth, newPassword)
func ExportDB(path string, password string, kdfIterationsNumber int, newDbPAth string, newPassword string, onStart func(), onEnd func()) error {
return sqlite.ExportDB(path, password, kdfIterationsNumber, newDbPAth, newPassword, onStart, onEnd)
}
func ChangeDatabasePassword(path string, password string, kdfIterationsNumber int, newPassword string) error {
return sqlite.ChangeEncryptionKey(path, password, kdfIterationsNumber, newPassword)
func ChangeDatabasePassword(path string, password string, kdfIterationsNumber int, newPassword string, onStart func(), onEnd func()) error {
return sqlite.ChangeEncryptionKey(path, password, kdfIterationsNumber, newPassword, onStart, onEnd)
}
// GetDBFilename takes an instance of sql.DB and returns the filename of the "main" database
@ -205,8 +205,8 @@ func migrateEnsUsernames(sqlTx *sql.Tx) error {
return nil
}
func MigrateV3ToV4(v3Path string, v4Path string, password string, kdfIterationsNumber int) error {
return sqlite.MigrateV3ToV4(v3Path, v4Path, password, kdfIterationsNumber)
func MigrateV3ToV4(v3Path string, v4Path string, password string, kdfIterationsNumber int, onStart func(), onEnd func()) error {
return sqlite.MigrateV3ToV4(v3Path, v4Path, password, kdfIterationsNumber, onStart, onEnd)
}
const (

View File

@ -8,6 +8,7 @@ import (
"time"
"github.com/status-im/status-go/server"
"github.com/status-im/status-go/signal"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p/enode"
@ -314,7 +315,7 @@ func (b *StatusNode) wakuV2Service(nodeConfig *params.NodeConfig, telemetryServe
cfg.MaxMessageSize = nodeConfig.WakuV2Config.MaxMessageSize
}
w, err := wakuv2.New(nodeConfig.NodeKey, nodeConfig.ClusterConfig.Fleet, cfg, logutils.ZapLogger(), b.appDB, b.timeSource())
w, err := wakuv2.New(nodeConfig.NodeKey, nodeConfig.ClusterConfig.Fleet, cfg, logutils.ZapLogger(), b.appDB, b.timeSource(), signal.SendHistoricMessagesRequestFailed, signal.SendPeerStats)
if err != nil {
return nil, err

View File

@ -1,5 +1,10 @@
package signal
import (
"github.com/status-im/status-go/multiaccounts"
"github.com/status-im/status-go/multiaccounts/settings"
)
const (
// EventNodeStarted is triggered when underlying node is started
EventNodeStarted = "node.started"
@ -28,7 +33,9 @@ type NodeCrashEvent struct {
// NodeLoginEvent returns the result of the login event
type NodeLoginEvent struct {
Error string `json:"error,omitempty"`
Error string `json:"error,omitempty"`
Settings *settings.Settings `json:"settings,omitempty"`
Account *multiaccounts.Account `json:"account,omitempty"`
}
// SendNodeCrashed emits a signal when status node has crashed, and
@ -62,8 +69,8 @@ func SendChainDataRemoved() {
send(EventChainDataRemoved, nil)
}
func SendLoggedIn(err error) {
event := NodeLoginEvent{}
func SendLoggedIn(account *multiaccounts.Account, settings *settings.Settings, err error) {
event := NodeLoginEvent{Settings: settings, Account: account}
if err != nil {
event.Error = err.Error()
}

View File

@ -1,5 +1,7 @@
package signal
import "github.com/status-im/status-go/eth-node/types"
const (
// EventPeerStats is sent when peer is added or removed.
// it will be a map with capability=peer count k/v's.
@ -7,6 +9,6 @@ const (
)
// SendPeerStats sends discovery.summary signal.
func SendPeerStats(peerStats interface{}) {
func SendPeerStats(peerStats types.ConnStatus) {
send(EventPeerStats, peerStats)
}

View File

@ -13,7 +13,6 @@ import (
sqlcipher "github.com/mutecomm/go-sqlcipher/v4" // We require go sqlcipher that overrides default implementation
"github.com/status-im/status-go/protocol/sqlite"
"github.com/status-im/status-go/signal"
)
const (
@ -51,9 +50,13 @@ func DecryptDB(oldPath string, newPath string, key string, kdfIterationsNumber i
return err
}
func encryptDB(db *sql.DB, encryptedPath string, key string, kdfIterationsNumber int) error {
signal.SendReEncryptionStarted()
defer signal.SendReEncryptionFinished()
func encryptDB(db *sql.DB, encryptedPath string, key string, kdfIterationsNumber int, onStart func(), onEnd func()) error {
if onStart != nil {
onStart()
}
if onEnd != nil {
defer onEnd()
}
_, err := db.Exec(`ATTACH DATABASE '` + encryptedPath + `' AS encrypted KEY '` + key + `'`)
if err != nil {
@ -92,24 +95,24 @@ func encryptDB(db *sql.DB, encryptedPath string, key string, kdfIterationsNumber
}
// EncryptDB takes a plaintext database and adds encryption
func EncryptDB(unencryptedPath string, encryptedPath string, key string, kdfIterationsNumber int) error {
func EncryptDB(unencryptedPath string, encryptedPath string, key string, kdfIterationsNumber int, onStart func(), onEnd func()) error {
_ = os.Remove(encryptedPath)
db, err := OpenUnecryptedDB(unencryptedPath)
if err != nil {
return err
}
return encryptDB(db, encryptedPath, key, kdfIterationsNumber)
return encryptDB(db, encryptedPath, key, kdfIterationsNumber, onStart, onEnd)
}
// Export takes an encrypted database and re-encrypts it in a new file, with a new key
func ExportDB(encryptedPath string, key string, kdfIterationsNumber int, newPath string, newKey string) error {
func ExportDB(encryptedPath string, key string, kdfIterationsNumber int, newPath string, newKey string, onStart func(), onEnd func()) error {
db, err := openDB(encryptedPath, key, kdfIterationsNumber, V4CipherPageSize)
if err != nil {
return err
}
defer db.Close()
return encryptDB(db, newPath, newKey, kdfIterationsNumber)
return encryptDB(db, newPath, newKey, kdfIterationsNumber, onStart, onEnd)
}
func buildSqlcipherDSN(path string) (string, error) {
@ -253,9 +256,14 @@ func OpenUnecryptedDB(path string) (*sql.DB, error) {
return db, nil
}
func ChangeEncryptionKey(path string, key string, kdfIterationsNumber int, newKey string) error {
signal.SendReEncryptionStarted()
defer signal.SendReEncryptionFinished()
func ChangeEncryptionKey(path string, key string, kdfIterationsNumber int, newKey string, onStart func(), onEnd func()) error {
if onStart != nil {
onStart()
}
if onEnd != nil {
defer onEnd()
}
if kdfIterationsNumber <= 0 {
kdfIterationsNumber = sqlite.ReducedKDFIterationsNumber
@ -276,7 +284,7 @@ func ChangeEncryptionKey(path string, key string, kdfIterationsNumber int, newKe
}
// MigrateV3ToV4 migrates database from v3 to v4 format with encryption.
func MigrateV3ToV4(v3Path string, v4Path string, key string, kdfIterationsNumber int) error {
func MigrateV3ToV4(v3Path string, v4Path string, key string, kdfIterationsNumber int, onStart func(), onEnd func()) error {
db, err := openDB(v3Path, key, kdfIterationsNumber, V3CipherPageSize)
@ -286,5 +294,5 @@ func MigrateV3ToV4(v3Path string, v4Path string, key string, kdfIterationsNumber
}
defer db.Close()
return encryptDB(db, v4Path, key, kdfIterationsNumber)
return encryptDB(db, v4Path, key, kdfIterationsNumber, onStart, onEnd)
}

View File

@ -27,7 +27,7 @@ import (
)
func TestMultipleTopicCopyInNewMessageFilter(t *testing.T) {
w, err := New("", "", nil, nil, nil, nil)
w, err := New("", "", nil, nil, nil, nil, nil, nil)
if err != nil {
t.Fatalf("Error creating WakuV2 client: %v", err)
}

View File

@ -63,7 +63,6 @@ import (
"github.com/status-im/status-go/connection"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/signal"
"github.com/status-im/status-go/timesource"
"github.com/status-im/status-go/wakuv2/common"
"github.com/status-im/status-go/wakuv2/persistence"
@ -154,6 +153,9 @@ type Waku struct {
// discV5BootstrapNodes is the ENR to be used to fetch bootstrap nodes for discovery
discV5BootstrapNodes []string
onHistoricMessagesRequestFailed func([]byte, peer.ID, error)
onPeerStats func(types.ConnStatus)
}
func getUsableUDPPort() (int, error) {
@ -169,7 +171,7 @@ func getUsableUDPPort() (int, error) {
}
// New creates a WakuV2 client ready to communicate through the LibP2P network.
func New(nodeKey string, fleet string, cfg *Config, logger *zap.Logger, appDB *sql.DB, ts *timesource.NTPTimeSource) (*Waku, error) {
func New(nodeKey string, fleet string, cfg *Config, logger *zap.Logger, appDB *sql.DB, ts *timesource.NTPTimeSource, onHistoricMessagesRequestFailed func([]byte, peer.ID, error), onPeerStats func(types.ConnStatus)) (*Waku, error) {
var err error
if logger == nil {
logger, err = zap.NewDevelopment()
@ -194,26 +196,28 @@ func New(nodeKey string, fleet string, cfg *Config, logger *zap.Logger, appDB *s
logger.Debug("starting wakuv2 with config", zap.Any("config", cfg))
waku := &Waku{
appDB: appDB,
cfg: cfg,
privateKeys: make(map[string]*ecdsa.PrivateKey),
symKeys: make(map[string][]byte),
envelopes: make(map[gethcommon.Hash]*common.ReceivedMessage),
expirations: make(map[uint32]mapset.Set),
msgQueue: make(chan *common.ReceivedMessage, messageQueueLimit),
sendQueue: make(chan *protocol.Envelope, 1000),
connStatusChan: make(chan node.ConnStatus, 100),
connStatusSubscriptions: make(map[string]*types.ConnStatusSubscription),
wg: sync.WaitGroup{},
dnsAddressCache: make(map[string][]dnsdisc.DiscoveredNode),
dnsAddressCacheLock: &sync.RWMutex{},
storeMsgIDs: make(map[gethcommon.Hash]bool),
filterPeerDisconnectMap: make(map[peer.ID]int64),
filterSubscriptions: make(map[*common.Filter]map[string]*filter.SubscriptionDetails),
timesource: ts,
storeMsgIDsMu: sync.RWMutex{},
logger: logger,
discV5BootstrapNodes: cfg.DiscV5BootstrapNodes,
appDB: appDB,
cfg: cfg,
privateKeys: make(map[string]*ecdsa.PrivateKey),
symKeys: make(map[string][]byte),
envelopes: make(map[gethcommon.Hash]*common.ReceivedMessage),
expirations: make(map[uint32]mapset.Set),
msgQueue: make(chan *common.ReceivedMessage, messageQueueLimit),
sendQueue: make(chan *protocol.Envelope, 1000),
connStatusChan: make(chan node.ConnStatus, 100),
connStatusSubscriptions: make(map[string]*types.ConnStatusSubscription),
wg: sync.WaitGroup{},
dnsAddressCache: make(map[string][]dnsdisc.DiscoveredNode),
dnsAddressCacheLock: &sync.RWMutex{},
storeMsgIDs: make(map[gethcommon.Hash]bool),
filterPeerDisconnectMap: make(map[peer.ID]int64),
filterSubscriptions: make(map[*common.Filter]map[string]*filter.SubscriptionDetails),
timesource: ts,
storeMsgIDsMu: sync.RWMutex{},
logger: logger,
discV5BootstrapNodes: cfg.DiscV5BootstrapNodes,
onHistoricMessagesRequestFailed: onHistoricMessagesRequestFailed,
onPeerStats: onPeerStats,
}
// This fn is being mocked in test
waku.isFilterSubAlive = func(sub *filter.SubscriptionDetails) error {
@ -1135,7 +1139,9 @@ func (w *Waku) Query(ctx context.Context, peerID peer.ID, topics []common.TopicT
result, err := w.query(ctx, peerID, topics, from, to, opts)
if err != nil {
w.logger.Error("error querying storenode", zap.String("requestID", hexutil.Encode(requestID)), zap.String("peerID", peerID.String()), zap.Error(err))
signal.SendHistoricMessagesRequestFailed(requestID, peerID, err)
if w.onHistoricMessagesRequestFailed != nil {
w.onHistoricMessagesRequestFailed(requestID, peerID, err)
}
return nil, err
}
@ -1215,7 +1221,9 @@ func (w *Waku) Start() error {
}
}
w.connStatusMu.Unlock()
signal.SendPeerStats(latestConnStatus)
if w.onPeerStats != nil {
w.onPeerStats(latestConnStatus)
}
if w.cfg.EnableDiscV5 {
// Restarting DiscV5

View File

@ -28,7 +28,7 @@ func TestDiscoveryV5(t *testing.T) {
config.DiscV5BootstrapNodes = []string{testENRBootstrap}
config.DiscoveryLimit = 20
config.UDPPort = 9001
w, err := New("", "", config, nil, nil, nil)
w, err := New("", "", config, nil, nil, nil, nil, nil)
require.NoError(t, err)
require.NoError(t, w.Start())
@ -53,7 +53,7 @@ func TestRestartDiscoveryV5(t *testing.T) {
config.DiscV5BootstrapNodes = []string{"enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@1.1.1.2"}
config.DiscoveryLimit = 20
config.UDPPort = 9002
w, err := New("", "", config, nil, nil, nil)
w, err := New("", "", config, nil, nil, nil, nil, nil)
require.NoError(t, err)
require.NoError(t, w.Start())
@ -107,7 +107,7 @@ func TestBasicWakuV2(t *testing.T) {
config.DiscoveryLimit = 20
config.UDPPort = 9001
config.WakuNodes = []string{enrTreeAddress}
w, err := New("", "", config, nil, nil, nil)
w, err := New("", "", config, nil, nil, nil, nil, nil)
require.NoError(t, err)
require.NoError(t, w.Start())
@ -182,7 +182,7 @@ func TestWakuV2Filter(t *testing.T) {
config.UDPPort = 9001
config.WakuNodes = []string{enrTreeAddress}
fleet := "status.test" // Need a name fleet so that LightClient is not set to false
w, err := New("", fleet, config, nil, nil, nil)
w, err := New("", fleet, config, nil, nil, nil, nil, nil)
require.NoError(t, err)
require.NoError(t, w.Start())