Skip to content

Commit c30aaee

Browse files
session: use sqlcmig6 for kvdb to sql migration
This commit updates the session package to use the new `sqlcmig6` package for kvdb to SQL migration.
1 parent 760a80c commit c30aaee

File tree

2 files changed

+218
-28
lines changed

2 files changed

+218
-28
lines changed

session/sql_migration.go

Lines changed: 213 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@ import (
99
"reflect"
1010
"time"
1111

12+
"github.com/btcsuite/btcd/btcec/v2"
1213
"github.com/davecgh/go-spew/spew"
14+
"github.com/lightninglabs/lightning-node-connect/mailbox"
1315
"github.com/lightninglabs/lightning-terminal/accounts"
14-
"github.com/lightninglabs/lightning-terminal/db/sqlc"
16+
"github.com/lightninglabs/lightning-terminal/db/sqlcmig6"
17+
"github.com/lightningnetwork/lnd/fn"
1518
"github.com/lightningnetwork/lnd/sqldb"
1619
"github.com/pmezard/go-difflib/difflib"
1720
"go.etcd.io/bbolt"
21+
"gopkg.in/macaroon-bakery.v2/bakery"
22+
"gopkg.in/macaroon.v2"
1823
)
1924

2025
var (
@@ -31,7 +36,7 @@ var (
3136
// NOTE: As sessions may contain linked accounts, the accounts sql migration
3237
// MUST be run prior to this migration.
3338
func MigrateSessionStoreToSQL(ctx context.Context, kvStore *bbolt.DB,
34-
tx SQLQueries) error {
39+
tx SQLMig6Queries) error {
3540

3641
log.Infof("Starting migration of the KV sessions store to SQL")
3742

@@ -118,7 +123,7 @@ func getBBoltSessions(db *bbolt.DB) ([]*Session, error) {
118123
// from the KV database to the SQL database, and validates that the migrated
119124
// sessions match the original sessions.
120125
func migrateSessionsToSQLAndValidate(ctx context.Context,
121-
tx SQLQueries, kvSessions []*Session) error {
126+
tx SQLMig6Queries, kvSessions []*Session) error {
122127

123128
for _, kvSession := range kvSessions {
124129
err := migrateSingleSessionToSQL(ctx, tx, kvSession)
@@ -127,18 +132,9 @@ func migrateSessionsToSQLAndValidate(ctx context.Context,
127132
kvSession.ID, err)
128133
}
129134

130-
// Validate that the session was correctly migrated and matches
131-
// the original session in the kv store.
132-
sqlSess, err := tx.GetSessionByAlias(ctx, kvSession.ID[:])
133-
if err != nil {
134-
if errors.Is(err, sql.ErrNoRows) {
135-
err = ErrSessionNotFound
136-
}
137-
return fmt.Errorf("unable to get migrated session "+
138-
"from sql store: %w", err)
139-
}
140-
141-
migratedSession, err := unmarshalSession(ctx, tx, sqlSess)
135+
migratedSession, err := getAndUnmarshalSession(
136+
ctx, tx, kvSession.ID[:],
137+
)
142138
if err != nil {
143139
return fmt.Errorf("unable to unmarshal migrated "+
144140
"session: %w", err)
@@ -172,12 +168,206 @@ func migrateSessionsToSQLAndValidate(ctx context.Context,
172168
return nil
173169
}
174170

171+
func getAndUnmarshalSession(ctx context.Context,
172+
tx SQLMig6Queries, legacyID []byte) (*Session, error) {
173+
174+
// Validate that the session was correctly migrated and matches
175+
// the original session in the kv store.
176+
sqlSess, err := tx.GetSessionByAlias(ctx, legacyID)
177+
if err != nil {
178+
if errors.Is(err, sql.ErrNoRows) {
179+
err = ErrSessionNotFound
180+
}
181+
182+
return nil, fmt.Errorf("unable to get migrated session "+
183+
"from sql store: %w", err)
184+
}
185+
186+
migratedSession, err := unmarshalMig6Session(ctx, tx, sqlSess)
187+
if err != nil {
188+
return nil, fmt.Errorf("unable to unmarshal migrated "+
189+
"session: %w", err)
190+
}
191+
192+
return migratedSession, nil
193+
194+
}
195+
196+
func unmarshalMig6Session(ctx context.Context, db SQLMig6Queries,
197+
dbSess sqlcmig6.Session) (*Session, error) {
198+
199+
var legacyGroupID ID
200+
if dbSess.GroupID.Valid {
201+
groupID, err := db.GetAliasBySessionID(
202+
ctx, dbSess.GroupID.Int64,
203+
)
204+
if err != nil {
205+
return nil, fmt.Errorf("unable to get legacy group "+
206+
"Alias: %v", err)
207+
}
208+
209+
legacyGroupID, err = IDFromBytes(groupID)
210+
if err != nil {
211+
return nil, fmt.Errorf("unable to get legacy Alias: %v",
212+
err)
213+
}
214+
}
215+
216+
var acctAlias fn.Option[accounts.AccountID]
217+
if dbSess.AccountID.Valid {
218+
account, err := db.GetAccount(ctx, dbSess.AccountID.Int64)
219+
if err != nil {
220+
return nil, fmt.Errorf("unable to get account: %v", err)
221+
}
222+
223+
accountAlias, err := accounts.AccountIDFromInt64(account.Alias)
224+
if err != nil {
225+
return nil, fmt.Errorf("unable to get account ID: %v", err)
226+
}
227+
acctAlias = fn.Some(accountAlias)
228+
}
229+
230+
legacyID, err := IDFromBytes(dbSess.Alias)
231+
if err != nil {
232+
return nil, fmt.Errorf("unable to get legacy Alias: %v", err)
233+
}
234+
235+
var revokedAt time.Time
236+
if dbSess.RevokedAt.Valid {
237+
revokedAt = dbSess.RevokedAt.Time
238+
}
239+
240+
localPriv, localPub := btcec.PrivKeyFromBytes(dbSess.LocalPrivateKey)
241+
242+
var remotePub *btcec.PublicKey
243+
if len(dbSess.RemotePublicKey) != 0 {
244+
remotePub, err = btcec.ParsePubKey(dbSess.RemotePublicKey)
245+
if err != nil {
246+
return nil, fmt.Errorf("unable to parse remote "+
247+
"public key: %v", err)
248+
}
249+
}
250+
251+
// Get the macaroon permissions if they exist.
252+
perms, err := db.GetSessionMacaroonPermissions(ctx, dbSess.ID)
253+
if err != nil {
254+
return nil, fmt.Errorf("unable to get macaroon "+
255+
"permissions: %v", err)
256+
}
257+
258+
// Get the macaroon caveats if they exist.
259+
caveats, err := db.GetSessionMacaroonCaveats(ctx, dbSess.ID)
260+
if err != nil {
261+
return nil, fmt.Errorf("unable to get macaroon "+
262+
"caveats: %v", err)
263+
}
264+
265+
var macRecipe *MacaroonRecipe
266+
if perms != nil || caveats != nil {
267+
macRecipe = &MacaroonRecipe{
268+
Permissions: unmarshalMig6MacPerms(perms),
269+
Caveats: unmarshalMig6MacCaveats(caveats),
270+
}
271+
}
272+
273+
// Get the feature configs if they exist.
274+
featureConfigs, err := db.GetSessionFeatureConfigs(ctx, dbSess.ID)
275+
if err != nil {
276+
return nil, fmt.Errorf("unable to get feature configs: %v", err)
277+
}
278+
279+
var featureCfgs *FeaturesConfig
280+
if featureConfigs != nil {
281+
featureCfgs = unmarshalMig6FeatureConfigs(featureConfigs)
282+
}
283+
284+
// Get the privacy flags if they exist.
285+
privacyFlags, err := db.GetSessionPrivacyFlags(ctx, dbSess.ID)
286+
if err != nil {
287+
return nil, fmt.Errorf("unable to get privacy flags: %v", err)
288+
}
289+
290+
var privFlags PrivacyFlags
291+
if privacyFlags != nil {
292+
privFlags = unmarshalMig6PrivacyFlags(privacyFlags)
293+
}
294+
295+
var pairingSecret [mailbox.NumPassphraseEntropyBytes]byte
296+
copy(pairingSecret[:], dbSess.PairingSecret)
297+
298+
return &Session{
299+
ID: legacyID,
300+
Label: dbSess.Label,
301+
State: State(dbSess.State),
302+
Type: Type(dbSess.Type),
303+
Expiry: dbSess.Expiry,
304+
CreatedAt: dbSess.CreatedAt,
305+
RevokedAt: revokedAt,
306+
ServerAddr: dbSess.ServerAddress,
307+
DevServer: dbSess.DevServer,
308+
MacaroonRootKey: uint64(dbSess.MacaroonRootKey),
309+
PairingSecret: pairingSecret,
310+
LocalPrivateKey: localPriv,
311+
LocalPublicKey: localPub,
312+
RemotePublicKey: remotePub,
313+
WithPrivacyMapper: dbSess.Privacy,
314+
GroupID: legacyGroupID,
315+
PrivacyFlags: privFlags,
316+
MacaroonRecipe: macRecipe,
317+
FeatureConfig: featureCfgs,
318+
AccountID: acctAlias,
319+
}, nil
320+
}
321+
322+
func unmarshalMig6MacPerms(dbPerms []sqlcmig6.SessionMacaroonPermission) []bakery.Op {
323+
ops := make([]bakery.Op, len(dbPerms))
324+
for i, dbPerm := range dbPerms {
325+
ops[i] = bakery.Op{
326+
Entity: dbPerm.Entity,
327+
Action: dbPerm.Action,
328+
}
329+
}
330+
331+
return ops
332+
}
333+
334+
func unmarshalMig6MacCaveats(dbCaveats []sqlcmig6.SessionMacaroonCaveat) []macaroon.Caveat {
335+
caveats := make([]macaroon.Caveat, len(dbCaveats))
336+
for i, dbCaveat := range dbCaveats {
337+
caveats[i] = macaroon.Caveat{
338+
Id: dbCaveat.CaveatID,
339+
VerificationId: dbCaveat.VerificationID,
340+
Location: dbCaveat.Location.String,
341+
}
342+
}
343+
344+
return caveats
345+
}
346+
347+
func unmarshalMig6FeatureConfigs(dbConfigs []sqlcmig6.SessionFeatureConfig) *FeaturesConfig {
348+
configs := make(FeaturesConfig, len(dbConfigs))
349+
for _, dbConfig := range dbConfigs {
350+
configs[dbConfig.FeatureName] = dbConfig.Config
351+
}
352+
353+
return &configs
354+
}
355+
356+
func unmarshalMig6PrivacyFlags(dbFlags []sqlcmig6.SessionPrivacyFlag) PrivacyFlags {
357+
flags := make(PrivacyFlags, len(dbFlags))
358+
for i, dbFlag := range dbFlags {
359+
flags[i] = PrivacyFlag(dbFlag.Flag)
360+
}
361+
362+
return flags
363+
}
364+
175365
// migrateSingleSessionToSQL runs the migration for a single session from the
176366
// KV database to the SQL database. Note that if the session links to an
177367
// account, the linked accounts store MUST have been migrated before that
178368
// session is migrated.
179369
func migrateSingleSessionToSQL(ctx context.Context,
180-
tx SQLQueries, session *Session) error {
370+
tx SQLMig6Queries, session *Session) error {
181371

182372
var (
183373
acctID sql.NullInt64
@@ -213,7 +403,7 @@ func migrateSingleSessionToSQL(ctx context.Context,
213403
}
214404

215405
// Proceed to insert the session into the sql db.
216-
sqlId, err := tx.InsertSession(ctx, sqlc.InsertSessionParams{
406+
sqlId, err := tx.InsertSession(ctx, sqlcmig6.InsertSessionParams{
217407
Alias: session.ID[:],
218408
Label: session.Label,
219409
State: int16(session.State),
@@ -239,7 +429,7 @@ func migrateSingleSessionToSQL(ctx context.Context,
239429
// has been created.
240430
if !session.RevokedAt.IsZero() {
241431
err = tx.SetSessionRevokedAt(
242-
ctx, sqlc.SetSessionRevokedAtParams{
432+
ctx, sqlcmig6.SetSessionRevokedAtParams{
243433
ID: sqlId,
244434
RevokedAt: sqldb.SQLTime(
245435
session.RevokedAt.UTC(),
@@ -265,7 +455,7 @@ func migrateSingleSessionToSQL(ctx context.Context,
265455
}
266456

267457
// Now lets set the group ID for the session.
268-
err = tx.SetSessionGroupID(ctx, sqlc.SetSessionGroupIDParams{
458+
err = tx.SetSessionGroupID(ctx, sqlcmig6.SetSessionGroupIDParams{
269459
ID: sqlId,
270460
GroupID: sqldb.SQLInt64(groupID),
271461
})
@@ -279,7 +469,7 @@ func migrateSingleSessionToSQL(ctx context.Context,
279469
// We start by inserting the macaroon permissions.
280470
for _, sessionPerm := range session.MacaroonRecipe.Permissions {
281471
err = tx.InsertSessionMacaroonPermission(
282-
ctx, sqlc.InsertSessionMacaroonPermissionParams{
472+
ctx, sqlcmig6.InsertSessionMacaroonPermissionParams{
283473
SessionID: sqlId,
284474
Entity: sessionPerm.Entity,
285475
Action: sessionPerm.Action,
@@ -293,7 +483,7 @@ func migrateSingleSessionToSQL(ctx context.Context,
293483
// Next we insert the macaroon caveats.
294484
for _, caveat := range session.MacaroonRecipe.Caveats {
295485
err = tx.InsertSessionMacaroonCaveat(
296-
ctx, sqlc.InsertSessionMacaroonCaveatParams{
486+
ctx, sqlcmig6.InsertSessionMacaroonCaveatParams{
297487
SessionID: sqlId,
298488
CaveatID: caveat.Id,
299489
VerificationID: caveat.VerificationId,
@@ -312,7 +502,7 @@ func migrateSingleSessionToSQL(ctx context.Context,
312502
if session.FeatureConfig != nil {
313503
for featureName, config := range *session.FeatureConfig {
314504
err = tx.InsertSessionFeatureConfig(
315-
ctx, sqlc.InsertSessionFeatureConfigParams{
505+
ctx, sqlcmig6.InsertSessionFeatureConfigParams{
316506
SessionID: sqlId,
317507
FeatureName: featureName,
318508
Config: config,
@@ -327,7 +517,7 @@ func migrateSingleSessionToSQL(ctx context.Context,
327517
// Finally we insert the privacy flags.
328518
for _, privacyFlag := range session.PrivacyFlags {
329519
err = tx.InsertSessionPrivacyFlag(
330-
ctx, sqlc.InsertSessionPrivacyFlagParams{
520+
ctx, sqlcmig6.InsertSessionPrivacyFlagParams{
331521
SessionID: sqlId,
332522
Flag: int32(privacyFlag),
333523
},

session/sql_migration_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"time"
88

99
"github.com/lightninglabs/lightning-terminal/accounts"
10-
"github.com/lightninglabs/lightning-terminal/db/sqlc"
10+
"github.com/lightninglabs/lightning-terminal/db/sqlcmig6"
1111
"github.com/lightningnetwork/lnd/clock"
1212
"github.com/lightningnetwork/lnd/lnwire"
1313
"github.com/lightningnetwork/lnd/macaroons"
@@ -37,7 +37,7 @@ func TestSessionsStoreMigration(t *testing.T) {
3737
}
3838

3939
makeSQLDB := func(t *testing.T, acctStore accounts.Store) (*SQLStore,
40-
*SQLQueriesExecutor[SQLQueries]) {
40+
*SQLMig6QueriesExecutor[SQLMig6Queries]) {
4141

4242
// Create a sql store with a linked account store.
4343
testDBStore := NewTestDBWithAccounts(t, clock, acctStore)
@@ -47,9 +47,9 @@ func TestSessionsStoreMigration(t *testing.T) {
4747

4848
baseDB := store.BaseDB
4949

50-
queries := sqlc.NewForType(baseDB, baseDB.BackendType)
50+
queries := sqlcmig6.NewForType(baseDB, baseDB.BackendType)
5151

52-
return store, NewSQLQueriesExecutor(baseDB, queries)
52+
return store, NewSQLMig6QueriesExecutor(baseDB, queries)
5353
}
5454

5555
// assertMigrationResults asserts that the sql store contains the
@@ -369,7 +369,7 @@ func TestSessionsStoreMigration(t *testing.T) {
369369
var opts sqldb.MigrationTxOptions
370370
err = txEx.ExecTx(
371371
ctx, &opts,
372-
func(tx SQLQueries) error {
372+
func(tx SQLMig6Queries) error {
373373
return MigrateSessionStoreToSQL(
374374
ctx, kvStore.DB, tx,
375375
)

0 commit comments

Comments
 (0)