fix(wallet)_: fix crash on nil db for statusd if wallet is enabled

Fixed some other issues with prevented startup of statusd:
- ensure paths for DBs are created
- ensure DBs are opened before calling `StartNode`
- ignore error if multiacc database is not available

Updates #14693
This commit is contained in:
Ivan Belyakov 2024-05-13 15:02:22 +02:00 committed by IvanBelyakoff
parent 838311e902
commit c0e922f0af
7 changed files with 89 additions and 34 deletions

View File

@ -2,6 +2,7 @@ package main
import ( import (
"context" "context"
"database/sql"
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
@ -157,6 +158,40 @@ func main() {
logger.Error("Failed to init keystore", "error", err) logger.Error("Failed to init keystore", "error", err)
return return
} }
if config.NodeKey == "" {
logger.Error("node key needs to be set if running a push notification server")
return
}
identity, err := crypto.HexToECDSA(config.NodeKey)
if err != nil {
logger.Error("node key is invalid", "error", err)
return
}
// Generate installationID from public key, so it's always the same
installationID, err := uuid.FromBytes(crypto.CompressPubkey(&identity.PublicKey)[:16])
if err != nil {
logger.Error("cannot create installation id", "error", err)
return
}
err = createDirsFromConfig(config)
if err != nil {
logger.Error("failed to create directories", "error", err)
return
}
appDB, walletDB, err := openDatabases(config.DataDir + "/" + installationID.String())
if err != nil {
log.Error("failed to open databases")
return
}
backend.StatusNode().SetAppDB(appDB)
backend.StatusNode().SetWalletDB(walletDB)
err = backend.StartNode(config) err = backend.StartNode(config)
if err != nil { if err != nil {
logger.Error("Node start failed", "error", err) logger.Error("Node start failed", "error", err)
@ -191,35 +226,6 @@ func main() {
} }
if config.PushNotificationServerConfig.Enabled { if config.PushNotificationServerConfig.Enabled {
if config.NodeKey == "" {
logger.Error("node key needs to be set if running a push notification server")
return
}
identity, err := crypto.HexToECDSA(config.NodeKey)
if err != nil {
logger.Error("node key is invalid", "error", err)
return
}
// Generate installationID from public key, so it's always the same
installationID, err := uuid.FromBytes(crypto.CompressPubkey(&identity.PublicKey)[:16])
if err != nil {
logger.Error("cannot create installation id", "error", err)
return
}
walletDB, err := walletdatabase.InitializeDB(config.DataDir+"/"+installationID.String()+"-wallet.db", "", dbsetup.ReducedKDFIterationsNumber)
if err != nil {
logger.Error("failed to initialize app db", "error", err)
return
}
appDB, err := appdatabase.InitializeDB(config.DataDir+"/"+installationID.String()+".db", "", dbsetup.ReducedKDFIterationsNumber)
if err != nil {
logger.Error("failed to initialize app db", "error", err)
return
}
options := []protocol.Option{ options := []protocol.Option{
protocol.WithPushNotifications(), protocol.WithPushNotifications(),
protocol.WithPushNotificationServerConfig(&pushnotificationserver.Config{ protocol.WithPushNotificationServerConfig(&pushnotificationserver.Config{
@ -432,3 +438,39 @@ func retrieveMessagesLoop(messenger *protocol.Messenger, tick time.Duration, can
} }
} }
} }
func openDatabases(path string) (*sql.DB, *sql.DB, error) {
walletDB, err := walletdatabase.InitializeDB(path+"-wallet.db", "", dbsetup.ReducedKDFIterationsNumber)
if err != nil {
logger.Error("failed to initialize wallet db", "error", err)
return nil, nil, err
}
appDB, err := appdatabase.InitializeDB(path+".db", "", dbsetup.ReducedKDFIterationsNumber)
if err != nil {
logger.Error("failed to initialize app db", "error", err)
return nil, nil, err
}
return appDB, walletDB, nil
}
func createDirsFromConfig(config *params.NodeConfig) error {
// If DataDir is empty, it means we want to create an ephemeral node
// keeping data only in memory.
if config.DataDir != "" {
// make sure data directory exists
if err := os.MkdirAll(filepath.Clean(config.DataDir), os.ModePerm); err != nil {
return fmt.Errorf("make node: make data directory: %v", err)
}
}
if config.KeyStoreDir != "" {
// make sure keys directory exists
if err := os.MkdirAll(filepath.Clean(config.KeyStoreDir), os.ModePerm); err != nil {
return fmt.Errorf("make node: make keys directory: %v", err)
}
}
return nil
}

View File

@ -296,6 +296,10 @@ type Database struct {
// NewDB returns a new instance of *Database // NewDB returns a new instance of *Database
func NewDB(db *sql.DB) (*Database, error) { func NewDB(db *sql.DB) (*Database, error) {
if db == nil {
return nil, errDbPassedParameterIsNil
}
sDB, err := settings.MakeNewDB(db) sDB, err := settings.MakeNewDB(db)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -79,6 +79,10 @@ func NewClient(client *gethrpc.Client, upstreamChainID uint64, upstream params.U
log := log.New("package", "status-go/rpc.Client") log := log.New("package", "status-go/rpc.Client")
networkManager := network.NewManager(db) networkManager := network.NewManager(db)
if networkManager == nil {
return nil, errors.New("failed to create network manager")
}
err = networkManager.Init(networks) err = networkManager.Init(networks)
if err != nil { if err != nil {
log.Error("Network manager failed to initialize", "error", err) log.Error("Network manager failed to initialize", "error", err)

View File

@ -371,7 +371,7 @@ func Test_removeBalanceHistoryOnEventAccountRemoved(t *testing.T) {
txServiceMockCtrl := gomock.NewController(t) txServiceMockCtrl := gomock.NewController(t)
server, _ := fake.NewTestServer(txServiceMockCtrl) server, _ := fake.NewTestServer(txServiceMockCtrl)
client := gethrpc.DialInProc(server) client := gethrpc.DialInProc(server)
rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, nil) rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, appDB)
rpcClient.UpstreamChainID = chainID rpcClient.UpstreamChainID = chainID
service := NewService(walletDB, accountsDB, &accountFeed, &walletFeed, rpcClient, nil, nil, nil) service := NewService(walletDB, accountsDB, &accountFeed, &walletFeed, rpcClient, nil, nil, nil)

View File

@ -328,7 +328,7 @@ func Test_removeTokenBalanceOnEventAccountRemoved(t *testing.T) {
txServiceMockCtrl := gomock.NewController(t) txServiceMockCtrl := gomock.NewController(t)
server, _ := fake.NewTestServer(txServiceMockCtrl) server, _ := fake.NewTestServer(txServiceMockCtrl)
client := gethrpc.DialInProc(server) client := gethrpc.DialInProc(server)
rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, nil) rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, appDB)
rpcClient.UpstreamChainID = chainID rpcClient.UpstreamChainID = chainID
nm := network.NewManager(appDB) nm := network.NewManager(appDB)
mediaServer, err := mediaserver.NewMediaServer(appDB, nil, nil, walletDB) mediaServer, err := mediaserver.NewMediaServer(appDB, nil, nil, walletDB)

View File

@ -119,12 +119,14 @@ func (c *Controller) CheckRecentHistory(chainIDs []uint64, accounts []common.Add
return nil return nil
} }
omitHistory := false
multiaccSettings, err := c.accountsDB.GetSettings() multiaccSettings, err := c.accountsDB.GetSettings()
if err != nil { if err != nil {
return err log.Error("Failed to get multiacc settings") // not critical
} else {
omitHistory = multiaccSettings.OmitTransfersHistoryScan
} }
omitHistory := multiaccSettings.OmitTransfersHistoryScan
if omitHistory { if omitHistory {
err := c.accountsDB.SaveSettingField(settings.OmitTransfersHistoryScan, false) err := c.accountsDB.SaveSettingField(settings.OmitTransfersHistoryScan, false)
if err != nil { if err != nil {

View File

@ -23,6 +23,7 @@ import (
"github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/params" "github.com/status-im/status-go/params"
"github.com/status-im/status-go/rpc" "github.com/status-im/status-go/rpc"
"github.com/status-im/status-go/sqlite"
"github.com/status-im/status-go/t/utils" "github.com/status-im/status-go/t/utils"
"github.com/status-im/status-go/transactions/fake" "github.com/status-im/status-go/transactions/fake"
) )
@ -51,7 +52,9 @@ func (s *TransactorSuite) SetupTest() {
// expected by simulated backend // expected by simulated backend
chainID := gethparams.AllEthashProtocolChanges.ChainID.Uint64() chainID := gethparams.AllEthashProtocolChanges.ChainID.Uint64()
rpcClient, _ := rpc.NewClient(s.client, chainID, params.UpstreamRPCConfig{}, nil, nil) db, err := sqlite.OpenUnecryptedDB(sqlite.InMemoryPath) // dummy to make rpc.Client happy
s.Require().NoError(err)
rpcClient, _ := rpc.NewClient(s.client, chainID, params.UpstreamRPCConfig{}, nil, db)
rpcClient.UpstreamChainID = chainID rpcClient.UpstreamChainID = chainID
nodeConfig, err := utils.MakeTestNodeConfigWithDataDir("", "/tmp", chainID) nodeConfig, err := utils.MakeTestNodeConfigWithDataDir("", "/tmp", chainID)
s.Require().NoError(err) s.Require().NoError(err)