Skip to content

Commit 3af4cef

Browse files
committed
staticaddr: selected swap amount migration
1 parent db934a8 commit 3af4cef

File tree

7 files changed

+269
-4
lines changed

7 files changed

+269
-4
lines changed

loopd/daemon.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,16 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
626626
clock.NewDefaultClock(), d.lnd.ChainParams,
627627
)
628628

629+
// Run the selected amount migration.
630+
err = loopin.MigrateSelectedSwapAmount(
631+
d.mainCtx, swapDb, depositStore, staticAddressLoopInStore,
632+
)
633+
if err != nil {
634+
errorf("Selected amount migration failed: %v", err)
635+
636+
return err
637+
}
638+
629639
staticLoopInManager = loopin.NewManager(&loopin.Config{
630640
Server: staticAddressClient,
631641
QuoteGetter: swapClient.Server,

loopdb/sqlc/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/queries/static_address_loopin.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,9 @@ SELECT EXISTS (
9595
FROM static_address_swaps
9696
WHERE swap_hash = $1
9797
);
98+
99+
-- name: OverrideSelectedSwapAmount :exec
100+
UPDATE static_address_swaps
101+
SET
102+
selected_amount = $2
103+
WHERE swap_hash = $1;

loopdb/sqlc/static_address_loopin.sql.go

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package loopin
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strconv"
7+
"strings"
8+
"time"
9+
10+
"github.com/btcsuite/btcd/btcutil"
11+
"github.com/btcsuite/btcd/chaincfg/chainhash"
12+
"github.com/lightninglabs/loop/loopdb"
13+
"github.com/lightninglabs/loop/staticaddr/deposit"
14+
"github.com/lightningnetwork/lnd/lntypes"
15+
)
16+
17+
const (
18+
// selectedAmountMigrationID is the identifier for the selected swap
19+
// amount migration.
20+
selectedAmountMigrationID = "selected_amount"
21+
)
22+
23+
// MigrateSelectedSwapAmount will update the selected swap amount of past swaps
24+
// with the sum of the values of the deposits they swapped.
25+
func MigrateSelectedSwapAmount(ctx context.Context, db loopdb.SwapStore,
26+
depositStore *deposit.SqlStore, swapStore *SqlStore) error {
27+
28+
migrationDone, err := db.HasMigration(ctx, selectedAmountMigrationID)
29+
if err != nil {
30+
return fmt.Errorf("unable to check migration status: %w", err)
31+
}
32+
if migrationDone {
33+
log.Infof("Selected swap amount migration already done, " +
34+
"skipping")
35+
36+
return nil
37+
}
38+
39+
log.Infof("Starting swap amount migration")
40+
startTs := time.Now()
41+
defer func() {
42+
log.Infof("Finished swap amount migration in %v",
43+
time.Since(startTs))
44+
}()
45+
46+
// First we'll fetch all loop out swaps from the database.
47+
swaps, err := swapStore.GetStaticAddressLoopInSwapsByStates(
48+
ctx, FinalStates,
49+
)
50+
if err != nil {
51+
return err
52+
}
53+
54+
// Now we'll calculate the cost for each swap and finally update the
55+
// costs in the database.
56+
// TODO(hieblmi): normalize swap hash and deposit ids.
57+
updateAmounts := make(map[lntypes.Hash]btcutil.Amount)
58+
for _, swap := range swaps {
59+
for _, outpoint := range swap.DepositOutpoints {
60+
op := strings.Split(outpoint, ":")
61+
hash, err := chainhash.NewHashFromStr(op[0])
62+
if err != nil {
63+
return fmt.Errorf("unable to parse outpoint "+
64+
"hash: %w", err)
65+
}
66+
67+
idx, err := strconv.ParseUint(op[1], 10, 32)
68+
if err != nil {
69+
return err
70+
}
71+
72+
deposit, err := depositStore.DepositForOutpoint(
73+
ctx, *hash, uint32(idx),
74+
)
75+
if err != nil {
76+
return fmt.Errorf("unable to fetch deposit "+
77+
"for outpoint %s: %w", outpoint, err)
78+
}
79+
if deposit == nil {
80+
return fmt.Errorf("deposit for outpoint %s "+
81+
"not found", outpoint)
82+
}
83+
84+
// Set the selected amount to the value of the deposit.
85+
updateAmounts[swap.SwapHash] += deposit.Value
86+
}
87+
}
88+
89+
log.Infof("Updating selected swap amounts for %d loop out swaps",
90+
len(updateAmounts))
91+
92+
err = swapStore.BatchUpdateSelectedSwapAmounts(ctx, updateAmounts)
93+
if err != nil {
94+
return err
95+
}
96+
97+
// Finally mark the migration as done.
98+
return db.SetMigration(ctx, selectedAmountMigrationID)
99+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package loopin
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/btcsuite/btcd/btcutil"
9+
"github.com/btcsuite/btcd/chaincfg"
10+
"github.com/btcsuite/btcd/chaincfg/chainhash"
11+
"github.com/btcsuite/btcd/wire"
12+
"github.com/lightninglabs/loop/loopdb"
13+
"github.com/lightninglabs/loop/staticaddr/deposit"
14+
"github.com/lightninglabs/loop/test"
15+
"github.com/lightningnetwork/lnd/clock"
16+
"github.com/lightningnetwork/lnd/lntypes"
17+
"github.com/stretchr/testify/require"
18+
)
19+
20+
// TestMigrateSelectedSwapAmount tests the selected amount migration.
21+
func TestMigrateSelectedSwapAmount(t *testing.T) {
22+
// Set up test context objects.
23+
ctxb := context.Background()
24+
testDb := loopdb.NewTestDB(t)
25+
testClock := clock.NewTestClock(time.Now())
26+
defer testDb.Close()
27+
28+
db := loopdb.NewStoreMock(t)
29+
depositStore := deposit.NewSqlStore(testDb.BaseDB)
30+
swapStore := NewSqlStore(
31+
loopdb.NewTypedStore[Querier](testDb), testClock,
32+
&chaincfg.MainNetParams,
33+
)
34+
35+
newID := func() deposit.ID {
36+
did, err := deposit.GetRandomDepositID()
37+
require.NoError(t, err)
38+
39+
return did
40+
}
41+
42+
d1, d2 := &deposit.Deposit{
43+
ID: newID(),
44+
OutPoint: wire.OutPoint{
45+
Hash: chainhash.Hash{0x1a, 0x2b, 0x3c, 0x4d},
46+
Index: 0,
47+
},
48+
Value: btcutil.Amount(100_000),
49+
TimeOutSweepPkScript: []byte{
50+
0x00, 0x14, 0x1a, 0x2b, 0x3c, 0x41,
51+
},
52+
},
53+
&deposit.Deposit{
54+
ID: newID(),
55+
OutPoint: wire.OutPoint{
56+
Hash: chainhash.Hash{0x2a, 0x2b, 0x3c, 0x4e},
57+
Index: 1,
58+
},
59+
Value: btcutil.Amount(200_000),
60+
TimeOutSweepPkScript: []byte{
61+
0x00, 0x14, 0x1a, 0x2b, 0x3c, 0x4d,
62+
},
63+
}
64+
65+
err := depositStore.CreateDeposit(ctxb, d1)
66+
require.NoError(t, err)
67+
err = depositStore.CreateDeposit(ctxb, d2)
68+
require.NoError(t, err)
69+
70+
outpoints := []string{
71+
d1.OutPoint.String(),
72+
d2.OutPoint.String(),
73+
}
74+
_, clientPubKey := test.CreateKey(1)
75+
_, serverPubKey := test.CreateKey(2)
76+
p2wkhAddr := "bcrt1qq68r6ff4k4pjx39efs44gcyccf7unqnu5qtjjz"
77+
addr, err := btcutil.DecodeAddress(p2wkhAddr, nil)
78+
require.NoError(t, err)
79+
80+
swap := StaticAddressLoopIn{
81+
SwapHash: lntypes.Hash{0x1, 0x2, 0x3, 0x4},
82+
DepositOutpoints: outpoints,
83+
ClientPubkey: clientPubKey,
84+
ServerPubkey: serverPubKey,
85+
HtlcTimeoutSweepAddress: addr,
86+
}
87+
swap.SetState(Succeeded)
88+
89+
err = swapStore.CreateLoopIn(ctxb, &swap)
90+
require.NoError(t, err)
91+
92+
storedSwaps, err := swapStore.GetStaticAddressLoopInSwapsByStates(
93+
ctxb, FinalStates,
94+
)
95+
require.NoError(t, err)
96+
require.EqualValues(t, 0, storedSwaps[0].SelectedAmount)
97+
98+
err = MigrateSelectedSwapAmount(ctxb, db, depositStore, swapStore)
99+
require.NoError(t, err)
100+
101+
storedSwaps, err = swapStore.GetStaticAddressLoopInSwapsByStates(
102+
ctxb, FinalStates,
103+
)
104+
require.NoError(t, err)
105+
require.EqualValues(t, d1.Value+d2.Value, storedSwaps[0].SelectedAmount)
106+
}

staticaddr/loopin/sql_store.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
2121
)
2222

23-
const outpointSeparator = ";"
23+
const OutpointSeparator = ";"
2424

2525
var (
2626
// ErrInvalidOutpoint is returned when an outpoint contains the outpoint
@@ -68,6 +68,11 @@ type Querier interface {
6868
// IsStored returns true if a swap with the given hash is stored in the
6969
// database, false otherwise.
7070
IsStored(ctx context.Context, swapHash []byte) (bool, error)
71+
72+
// OverrideSelectedSwapAmount updates the selected swap amount for
73+
// a given swap hash.
74+
OverrideSelectedSwapAmount(ctx context.Context,
75+
params sqlc.OverrideSelectedSwapAmountParams) error
7176
}
7277

7378
// BaseDB is the interface that contains all the queries generated by sqlc for
@@ -218,13 +223,13 @@ func (s *SqlStore) CreateLoopIn(ctx context.Context,
218223
// If so, we reject the loop-in to prevent potential issues with
219224
// parsing.
220225
for _, outpoint := range loopIn.DepositOutpoints {
221-
if strings.Contains(outpoint, outpointSeparator) {
226+
if strings.Contains(outpoint, OutpointSeparator) {
222227
return ErrInvalidOutpoint
223228
}
224229
}
225230

226231
joinedOutpoints := strings.Join(
227-
loopIn.DepositOutpoints, outpointSeparator,
232+
loopIn.DepositOutpoints, OutpointSeparator,
228233
)
229234
staticAddressLoopInParams := sqlc.InsertStaticAddressLoopInParams{
230235
SwapHash: loopIn.SwapHash[:],
@@ -303,6 +308,27 @@ func (s *SqlStore) UpdateLoopIn(ctx context.Context,
303308
)
304309
}
305310

311+
func (s *SqlStore) BatchUpdateSelectedSwapAmounts(ctx context.Context,
312+
updateAmounts map[lntypes.Hash]btcutil.Amount) error {
313+
314+
return s.baseDB.ExecTx(ctx, loopdb.NewSqlWriteOpts(),
315+
func(q Querier) error {
316+
for swapHash, amount := range updateAmounts {
317+
err := q.OverrideSelectedSwapAmount(
318+
ctx, sqlc.OverrideSelectedSwapAmountParams{
319+
SwapHash: swapHash[:],
320+
SelectedAmount: int64(amount),
321+
},
322+
)
323+
if err != nil {
324+
return err
325+
}
326+
}
327+
328+
return nil
329+
})
330+
}
331+
306332
// IsStored returns true if a swap with the given hash is stored in the
307333
// database, false otherwise.
308334
func (s *SqlStore) IsStored(ctx context.Context, swapHash lntypes.Hash) (bool,
@@ -347,7 +373,7 @@ func toStaticAddressLoopIn(_ context.Context, network *chaincfg.Params,
347373
}
348374

349375
depositOutpoints := strings.Split(
350-
row.DepositOutpoints, outpointSeparator,
376+
row.DepositOutpoints, OutpointSeparator,
351377
)
352378

353379
timeoutAddressString := row.HtlcTimeoutSweepAddress

0 commit comments

Comments
 (0)