2025-10-12 12:53:52 +02:00
|
|
|
package messaging
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"database/sql"
|
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
bindata "github.com/status-im/migrate/v4/source/go_bindata"
|
|
|
|
|
mvdsnode "github.com/status-im/mvds/node"
|
|
|
|
|
mvdsmigrations "github.com/status-im/mvds/persistenceutil"
|
|
|
|
|
|
2025-12-15 12:01:03 +00:00
|
|
|
"github.com/status-im/status-go/internal/db/sqlite"
|
2026-08-17 15:04:09 +02:00
|
|
|
"github.com/status-im/status-go/pkg/messaging/common"
|
2025-12-17 19:40:40 +00:00
|
|
|
messagesendermigrations "github.com/status-im/status-go/pkg/messaging/common/migrations"
|
2026-08-17 15:04:09 +02:00
|
|
|
"github.com/status-im/status-go/pkg/messaging/layers/encryption"
|
2025-12-17 19:40:40 +00:00
|
|
|
encryptionmigrations "github.com/status-im/status-go/pkg/messaging/layers/encryption/migrations"
|
2026-08-17 15:04:09 +02:00
|
|
|
"github.com/status-im/status-go/pkg/messaging/layers/segmentation"
|
2025-12-17 19:40:40 +00:00
|
|
|
segmentationmigrations "github.com/status-im/status-go/pkg/messaging/layers/segmentation/migrations"
|
2026-04-16 13:22:54 +01:00
|
|
|
transport "github.com/status-im/status-go/pkg/messaging/layers/transport"
|
2025-12-17 19:40:40 +00:00
|
|
|
transportmigrations "github.com/status-im/status-go/pkg/messaging/layers/transport/migrations"
|
|
|
|
|
wakumigrations "github.com/status-im/status-go/pkg/messaging/waku/migrations"
|
2025-10-12 12:53:52 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type migrationsMetadata struct {
|
|
|
|
|
*bindata.AssetSource
|
|
|
|
|
MigrationTableName string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var migrations = []migrationsMetadata{
|
|
|
|
|
{
|
|
|
|
|
AssetSource: &bindata.AssetSource{
|
|
|
|
|
Names: wakumigrations.AssetNames(),
|
|
|
|
|
AssetFunc: wakumigrations.Asset,
|
|
|
|
|
},
|
|
|
|
|
MigrationTableName: "status_schema_migrations_waku",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
AssetSource: &bindata.AssetSource{
|
|
|
|
|
Names: transportmigrations.AssetNames(),
|
|
|
|
|
AssetFunc: transportmigrations.Asset,
|
|
|
|
|
},
|
|
|
|
|
MigrationTableName: "status_schema_migrations_transport",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
AssetSource: &bindata.AssetSource{
|
|
|
|
|
Names: segmentationmigrations.AssetNames(),
|
|
|
|
|
AssetFunc: segmentationmigrations.Asset,
|
|
|
|
|
},
|
|
|
|
|
MigrationTableName: "status_schema_migrations_segmentation",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
AssetSource: &bindata.AssetSource{
|
|
|
|
|
Names: encryptionmigrations.AssetNames(),
|
|
|
|
|
AssetFunc: encryptionmigrations.Asset,
|
|
|
|
|
},
|
|
|
|
|
MigrationTableName: "status_schema_migrations_encryption",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
AssetSource: &bindata.AssetSource{
|
|
|
|
|
Names: messagesendermigrations.AssetNames(),
|
|
|
|
|
AssetFunc: messagesendermigrations.Asset,
|
|
|
|
|
},
|
|
|
|
|
MigrationTableName: "status_schema_migrations_message_sender",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SQLiteMigrate applies necessary migrations to the SQLite database schema.
|
|
|
|
|
func SQLiteMigrate(database *sql.DB, maxVersion uint) error {
|
|
|
|
|
if maxVersion > 0 {
|
|
|
|
|
err := createMigrationTables(database, maxVersion)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrap(err, "failed to update migration tables")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err := mvdsmigrations.Migrate(database)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrap(err, "failed to apply mvds migrations")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, m := range migrations {
|
|
|
|
|
err := sqlite.Migrate(database, m.AssetSource, sqlite.MigrateOptions{MigrationTableName: m.MigrationTableName})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrap(err, fmt.Sprintf("failed to apply %s migrations", m.MigrationTableName))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Migration tables were transitioned from a single shared table in the client (status_protocol_go)
|
|
|
|
|
// to dedicated pre-component tables. To maintain migration consistency and prevent reapplication
|
|
|
|
|
// of migrations already executed in the client, it is essential to initialize any newly created
|
|
|
|
|
// migration tables with the latest version. This ensures that components introduced into the client
|
|
|
|
|
// do not re-run migrations that have previously been applied.
|
|
|
|
|
func createMigrationTables(database *sql.DB, maxVersion uint) error {
|
|
|
|
|
for _, m := range migrations {
|
|
|
|
|
err := sqlite.UpdateMigrationTableVersion(database, m.MigrationTableName, m.Names, maxVersion)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrap(err, fmt.Sprintf("failed to update migration table %s", m.MigrationTableName))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type sqlitePersistence struct {
|
|
|
|
|
db *sql.DB
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _ Persistence = (*sqlitePersistence)(nil)
|
|
|
|
|
|
|
|
|
|
func newSQLitePersistence(db *sql.DB) Persistence {
|
|
|
|
|
return &sqlitePersistence{db: db}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type sqliteTransportPersistence struct {
|
|
|
|
|
db *sql.DB
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 13:22:54 +01:00
|
|
|
var _ transport.Persistence = (*sqliteTransportPersistence)(nil)
|
2025-10-12 12:53:52 +02:00
|
|
|
|
2026-04-16 13:22:54 +01:00
|
|
|
func (p *sqliteTransportPersistence) KeysStorage() transport.KeysPersistence {
|
|
|
|
|
return transport.NewSQLiteKeysPersistence(p.db)
|
2025-10-12 12:53:52 +02:00
|
|
|
}
|
|
|
|
|
|
2026-04-16 13:22:54 +01:00
|
|
|
func (p *sqliteTransportPersistence) ProcessedMessageIDsCacheStorage() transport.ProcessedMessageIDsCachePersistence {
|
|
|
|
|
return transport.NewSQLiteProcessedMessageIDsCachePersistence(p.db)
|
2025-10-12 12:53:52 +02:00
|
|
|
}
|
|
|
|
|
|
2026-04-16 13:22:54 +01:00
|
|
|
func (p *sqlitePersistence) TransportStorage() transport.Persistence {
|
2025-10-12 12:53:52 +02:00
|
|
|
return &sqliteTransportPersistence{db: p.db}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-17 15:04:09 +02:00
|
|
|
func (p *sqlitePersistence) SegmentationStorage() segmentation.Persistence {
|
|
|
|
|
return segmentation.NewSQLitePersistence(p.db)
|
2025-10-12 12:53:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *sqlitePersistence) MVDSStorage() mvdsnode.Persistence {
|
|
|
|
|
return mvdsnode.NewSQLitePersistence(p.db)
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-17 15:04:09 +02:00
|
|
|
func (p *sqlitePersistence) EncryptionStorage() encryption.Persistence {
|
|
|
|
|
return encryption.NewSQLitePersistence(p.db)
|
2025-10-12 12:53:52 +02:00
|
|
|
}
|
|
|
|
|
|
2026-08-17 15:04:09 +02:00
|
|
|
func (p *sqlitePersistence) MessageConfirmationStorage() common.MessageConfirmationPersistence {
|
|
|
|
|
return common.NewSQLiteMessageConfirmationPersistence(p.db)
|
2025-11-18 19:59:37 +01:00
|
|
|
}
|
|
|
|
|
|
2026-08-17 15:04:09 +02:00
|
|
|
func (p *sqlitePersistence) HashRatchetStorage() common.HashRatchetPersistence {
|
|
|
|
|
return common.NewSQLiteHashRatchetPersistence(p.db)
|
2025-10-12 12:53:52 +02:00
|
|
|
}
|