Files
Igor Sirotin fa25c4fc01 refactor: rename walletdatabase to walletdb and split it
Part of the Go project layout migration, item 4.

internal/db/walletdatabase -> internal/db/walletdb, and its one 45-line
file splits along the two jobs it was doing:

  open.go     DbInitializer, InitializeDB, OpenDB
  migrate.go  walletCustomSteps, doMigration, MigrateDB

scripts/migration_check.sh listed this migration directory as
"walletdatabase/migrations/sql" and appdatabase's as
"appdatabase/migrations/sql". Neither path has existed since those
packages moved under internal/db/, so the check has been silently
skipping both. Both are corrected here.

refs #7067
2026-08-21 16:46:09 +01:00

288 lines
8.0 KiB
Go

package main
import (
"crypto/ecdsa"
"database/sql"
"flag"
"fmt"
"os"
"os/signal"
"path"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
"go.uber.org/zap"
"github.com/status-im/status-go/internal/crypto"
"github.com/status-im/status-go/internal/db/appdatabase"
"github.com/status-im/status-go/internal/db/dbsetup"
"github.com/status-im/status-go/internal/db/walletdb"
logutils "github.com/status-im/status-go/internal/logutils"
"github.com/status-im/status-go/internal/panics"
"github.com/status-im/status-go/internal/protocol"
"github.com/status-im/status-go/internal/protocol/pushnotificationserver"
"github.com/status-im/status-go/internal/protocol/sqlite"
"github.com/status-im/status-go/internal/timesource"
"github.com/status-im/status-go/params"
messaging "github.com/status-im/status-go/pkg/messaging"
"github.com/status-im/status-go/pkg/sentry"
mailserversDB "github.com/status-im/status-go/pkg/services/mailservers"
"github.com/status-im/status-go/pkg/services/personal"
"github.com/status-im/status-go/pkg/version"
)
var (
gorushURL = flag.String("gorush-url", pushnotificationserver.DefaultGorushURL, "gorush server URL")
dataDir = flag.String("data-dir", "", "data directory")
identity = flag.String("identity", "", "Hex-encoded private key to use. When empty, an ephemeral key will be used")
sentryEnabled = flag.Bool("sentry", false, "Enable sentry panic reporting")
logLevel = flag.String("log-level", "INFO", `Log level, one of: "ERROR", "WARN", "INFO", "DEBUG"`)
logNoColors = flag.Bool("log-no-color", false, "Disables log colors")
wakuFleet = flag.String("waku-fleet", "status.prod", "Waku fleet to use")
wakuFleetConfig = flag.String("waku-fleet-config", "", "path to Waku fleet config file")
Port = flag.Int("tcp-port", 30303, "Libp2p TCP port")
UDPPort = flag.Int("udp-port", 30303, "Libp2p UDP port")
// TODO: add pprof and metrics
logger *zap.Logger
)
const (
exitCodeOK = iota
exitCodeInvalidWakuFleetConfig
exitCodeInvalidKey
exitCodeCreateWakuFailed
exitCodeStartMessagingFailed
exitCodeDBMigrationFailed
exitCodeCreateMessengerFailed
exitCodeCreateDatabaseFailed
exitCodeStartServerFailed
exitCodeStartMessengerFailed
)
func init() {
flag.Parse()
logSettings := logutils.LogSettings{
Enabled: true,
Level: *logLevel,
}
if err := logutils.OverrideRootLoggerWithConfig(logSettings); err != nil {
panic(err)
}
logger = logutils.ZapLogger()
}
func main() {
defer func() {
_ = logger.Sync()
}()
if *sentryEnabled {
sentry.MustInit(
sentry.WithDefaultEnvironmentDSN(),
sentry.WithContext("push-notification-server", version.Version()),
)
defer sentry.Recover()
}
if *wakuFleetConfig != "" {
err := params.LoadWakuFleetsFromFile(*wakuFleetConfig)
if err != nil {
logger.Error("failed to load waku fleet config", zap.Error(err))
os.Exit(exitCodeInvalidWakuFleetConfig)
}
}
privateKey, installationID, err := parseNodeKey(*identity)
if err != nil {
logger.Error("failed to parse node key", zap.Error(err))
os.Exit(exitCodeInvalidKey)
}
dbPath := path.Join(*dataDir, installationID+"-app")
db, err := createAppDatabase(dbPath)
if err != nil {
logger.Error("failed to create database", zap.Error(err))
os.Exit(exitCodeCreateDatabaseFailed)
}
walletDBPath := path.Join(*dataDir, installationID)
walletDB, err := createWalletDatabase(walletDBPath)
if err != nil {
logger.Error("failed to create database", zap.Error(err))
os.Exit(exitCodeCreateDatabaseFailed)
}
err = sqlite.Migrate(db)
if err != nil {
logger.Error("failed to migrate database", zap.Error(err))
os.Exit(exitCodeDBMigrationFailed)
}
messaging, err := messaging.NewCore(
messaging.CoreParams{
Identity: privateKey,
NodeKey: nil,
WakuConfig: params.WakuV2Config{
Enabled: true,
Host: "0.0.0.0",
Port: *Port,
UDPPort: *UDPPort,
LightClient: false,
DiscoveryLimit: 20,
AutoUpdate: true,
},
// The waku node resolves its peers from the fleet name; Core = full node.
Fleet: *wakuFleet,
Mode: messaging.ModeCore,
InstallationID: installationID,
TimeSource: timesource.DefaultService(),
},
messaging.WithLogger(logger.Named("messaging")),
messaging.WithSQLitePersistence(db),
)
if err != nil {
os.Exit(exitCodeCreateMessengerFailed)
}
err = messaging.API().Start()
if err != nil {
logger.Error("failed to start messaging", zap.Error(err))
os.Exit(exitCodeStartMessagingFailed)
}
defer func() {
err := messaging.API().Stop()
if err != nil {
logger.Error("failed to stop messaging", zap.Error(err))
}
}()
// Set up the push notifications server
config := &pushnotificationserver.Config{
Enabled: true,
Identity: privateKey,
GorushURL: *gorushURL,
Logger: logger,
}
server := pushnotificationserver.New(config)
// Set up the messenger
options := []protocol.Option{
protocol.WithDatabase(db),
protocol.WithWalletDatabase(walletDB),
protocol.WithMailserversDatabase(mailserversDB.NewDB(db)),
protocol.WithDatasync(),
protocol.WithMessageSigner(personal.New()),
protocol.WithPushNotificationServer(server),
}
messenger, err := protocol.NewMessenger(privateKey, messaging.API(), installationID, options...)
if err != nil {
logger.Error("failed to create messenger", zap.Error(err))
os.Exit(exitCodeCreateMessengerFailed)
}
// Start
serverPersistence := pushnotificationserver.NewSQLitePersistence(db)
err = server.Start(serverPersistence, messenger.Messaging())
if err != nil {
logger.Error("failed to start push notifications server", zap.Error(err))
os.Exit(exitCodeStartServerFailed)
}
defer func() {
server.Stop()
}()
_, err = messenger.Start()
if err != nil {
fmt.Println("failed to start messenger", err)
logger.Error("failed to start messenger", zap.Error(err))
os.Exit(exitCodeStartMessengerFailed)
}
defer func() {
err := messenger.Shutdown()
if err != nil {
logger.Error("failed to shutdown messenger", zap.Error(err))
}
}()
cancelMessenger := make(chan struct{})
messenger.StartRetrieveMessagesLoop(300*time.Millisecond, cancelMessenger)
go func() {
defer panics.LogOnPanic()
select {
case <-cancelMessenger:
return
case <-time.After(10 * time.Second):
}
logger.Info("requesting history")
response, err := messenger.RequestAllHistoricMessages()
if err != nil {
logger.Error("failed to request history", zap.Error(err))
return
}
logger.Info("history fetched",
zap.Any("response", response),
)
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
close(cancelMessenger)
logger.Info("push-notification-server finished")
os.Exit(exitCodeOK)
}
func parseNodeKey(nodeKey string) (*ecdsa.PrivateKey, string, error) {
// Check for environment variable if CLI flag is empty
if nodeKey == "" {
nodeKey = os.Getenv("STATUS_GO_NODE_KEY")
}
// If still empty, return error
if nodeKey == "" {
return nil, "", errors.New("Nodekey must be provided via -identity flag or STATUS_GO_NODE_KEY environment variable")
}
// Parse private key
privateKey, err := crypto.HexToECDSA(nodeKey)
if err != nil {
return nil, "", errors.Wrap(err, "invalid node key")
}
// Generate installationID from public key, so it's always the same
installationID, err := uuid.FromBytes(crypto.CompressPubkey(&privateKey.PublicKey)[:16])
if err != nil {
return nil, "", errors.Wrap(err, "failed to generate installation id")
}
return privateKey, installationID.String(), nil
}
func createAppDatabase(path string) (*sql.DB, error) {
filename := path + ".db"
appDB, err := appdatabase.InitializeDB(filename, "", dbsetup.ReducedKDFIterationsNumber)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize app database")
}
return appDB, nil
}
func createWalletDatabase(path string) (*sql.DB, error) {
filename := path + "-wallet.db"
walletDB, err := walletdb.InitializeDB(filename, "", dbsetup.ReducedKDFIterationsNumber)
if err != nil {
logger.Error("failed to initialize wallet db", zap.Error(err))
return nil, err
}
return walletDB, nil
}