From e08aad7d731817169d6c7140fabc7e02d277dd19 Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Wed, 5 Jul 2023 16:56:34 +0100 Subject: [PATCH] Send account/settings on login --- api/geth_backend.go | 54 ++++++++++++++++++++++++++++------ appdatabase/database.go | 16 +++++------ node/status_node_services.go | 3 +- signal/events_node.go | 13 +++++++-- signal/events_wakuv2.go | 4 ++- sqlite/sqlite.go | 34 +++++++++++++--------- wakuv2/api_test.go | 2 +- wakuv2/waku.go | 56 ++++++++++++++++++++---------------- wakuv2/waku_test.go | 8 +++--- 9 files changed, 126 insertions(+), 64 deletions(-) diff --git a/api/geth_backend.go b/api/geth_backend.go index 901a5966c..a79a076a5 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -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 } diff --git a/appdatabase/database.go b/appdatabase/database.go index 88f54517f..5d66cddbb 100644 --- a/appdatabase/database.go +++ b/appdatabase/database.go @@ -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 ( diff --git a/node/status_node_services.go b/node/status_node_services.go index 0c77e402c..78a81f903 100644 --- a/node/status_node_services.go +++ b/node/status_node_services.go @@ -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 diff --git a/signal/events_node.go b/signal/events_node.go index 787de40eb..d627888fd 100644 --- a/signal/events_node.go +++ b/signal/events_node.go @@ -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() } diff --git a/signal/events_wakuv2.go b/signal/events_wakuv2.go index dfbdcfd8c..02281607e 100644 --- a/signal/events_wakuv2.go +++ b/signal/events_wakuv2.go @@ -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) } diff --git a/sqlite/sqlite.go b/sqlite/sqlite.go index 9f8e083c9..91252cd8b 100644 --- a/sqlite/sqlite.go +++ b/sqlite/sqlite.go @@ -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) } diff --git a/wakuv2/api_test.go b/wakuv2/api_test.go index 15046de97..437806681 100644 --- a/wakuv2/api_test.go +++ b/wakuv2/api_test.go @@ -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) } diff --git a/wakuv2/waku.go b/wakuv2/waku.go index d300c8409..d184b46b1 100644 --- a/wakuv2/waku.go +++ b/wakuv2/waku.go @@ -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 diff --git a/wakuv2/waku_test.go b/wakuv2/waku_test.go index 0160f0a24..e883231b2 100644 --- a/wakuv2/waku_test.go +++ b/wakuv2/waku_test.go @@ -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())