Skip to content

Commit 0ae934b

Browse files
committed
sweepbatcher: allow swap_hash to be non-unique
SwapHash used to be a key in the sweeps table. Now the key is outpoint which replaces columns outpoint_txid and outpoint_index. In-memory structures and unit tests were also updated to use outpoint as key. Outpoint is truly unique.
1 parent 3845bde commit 0ae934b

14 files changed

+301
-210
lines changed

loopdb/postgres.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ type PostgresStore struct {
6464
*BaseDB
6565
}
6666

67+
// In migration of sweeps table from outpoint_txid and outpoint_index to
68+
// outpoint we need to reverse the order of bytes in outpoint_txid and to
69+
// convert it to hex. This is done differently in sqlite and postgres.
70+
const (
71+
txidSqlite = "group_concat(hex(substr(outpoint_txid,32+1-i,1)),'')"
72+
txidPostgres = "string_agg(lpad(to_hex(get_byte(outpoint_txid, " +
73+
"32 - i)), 2, '0'), '')"
74+
)
75+
6776
// NewPostgresStore creates a new store that is backed by a Postgres database
6877
// backend.
6978
func NewPostgresStore(cfg *PostgresConfig,
@@ -93,6 +102,7 @@ func NewPostgresStore(cfg *PostgresConfig,
93102
postgresFS := newReplacerFS(sqlSchemas, map[string]string{
94103
"BLOB": "BYTEA",
95104
"INTEGER PRIMARY KEY": "SERIAL PRIMARY KEY",
105+
txidSqlite: txidPostgres,
96106
})
97107

98108
err = applyMigrations(

loopdb/sqlc/batch.sql.go

Lines changed: 18 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- We kept old table as sweeps_old. Use it.
2+
ALTER TABLE sweeps RENAME TO sweeps_new;
3+
ALTER TABLE sweeps_old RENAME TO sweeps;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
-- We want to make column swap_hash non-unique and to use the outpoint as a key.
2+
-- We can't make a column non-unique or remove it in sqlite, so work around.
3+
-- See https://stackoverflow.com/a/42013422
4+
5+
-- We also made outpoint a single point replacing columns outpoint_txid and
6+
-- outpoint_index.
7+
8+
-- sweeps stores the individual sweeps that are part of a batch.
9+
CREATE TABLE sweeps2 (
10+
-- id is the autoincrementing primary key.
11+
id INTEGER PRIMARY KEY,
12+
13+
-- swap_hash is the hash of the swap that is being swept.
14+
swap_hash BLOB NOT NULL,
15+
16+
-- batch_id is the id of the batch this swap is part of.
17+
batch_id INTEGER NOT NULL,
18+
19+
-- outpoint is the UTXO id of the output being swept ("txid:index").
20+
outpoint TEXT NOT NULL UNIQUE,
21+
22+
-- amt is the amount of the output being swept.
23+
amt BIGINT NOT NULL,
24+
25+
-- completed indicates whether the sweep has been completed.
26+
completed BOOLEAN NOT NULL DEFAULT FALSE,
27+
28+
-- Foreign key constraint to ensure that we reference an existing batch
29+
-- id.
30+
FOREIGN KEY (batch_id) REFERENCES sweep_batches(id),
31+
32+
-- Foreign key constraint to ensure that swap_hash references an
33+
-- existing swap.
34+
FOREIGN KEY (swap_hash) REFERENCES swaps(swap_hash)
35+
);
36+
37+
-- Copy all the data from sweeps to sweeps2.
38+
WITH RECURSIVE seq(i) AS (
39+
SELECT 1
40+
UNION ALL
41+
SELECT i + 1 FROM seq WHERE i < 32
42+
)
43+
INSERT INTO sweeps2 (
44+
id, swap_hash, batch_id, outpoint, amt, completed
45+
)
46+
SELECT
47+
id,
48+
swap_hash,
49+
batch_id,
50+
(
51+
SELECT lower(group_concat(hex(substr(outpoint_txid,32+1-i,1)),''))
52+
FROM seq
53+
) || ':' || CAST(outpoint_index AS TEXT),
54+
amt,
55+
completed
56+
FROM sweeps;
57+
58+
-- Rename tables.
59+
ALTER TABLE sweeps RENAME TO sweeps_old;
60+
ALTER TABLE sweeps2 RENAME TO sweeps;

loopdb/sqlc/models.go

Lines changed: 16 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/querier.go

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

loopdb/sqlc/queries/batch.sql

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,18 @@ WHERE
4747
INSERT INTO sweeps (
4848
swap_hash,
4949
batch_id,
50-
outpoint_txid,
51-
outpoint_index,
50+
outpoint,
5251
amt,
5352
completed
5453
) VALUES (
5554
$1,
5655
$2,
5756
$3,
5857
$4,
59-
$5,
60-
$6
61-
) ON CONFLICT (swap_hash) DO UPDATE SET
58+
$5
59+
) ON CONFLICT (outpoint) DO UPDATE SET
6260
batch_id = $2,
63-
outpoint_txid = $3,
64-
outpoint_index = $4,
65-
amt = $5,
66-
completed = $6;
61+
completed = $5;
6762

6863
-- name: GetParentBatch :one
6964
SELECT
@@ -73,7 +68,7 @@ FROM
7368
JOIN
7469
sweeps ON sweep_batches.id = sweeps.batch_id
7570
WHERE
76-
sweeps.swap_hash = $1;
71+
sweeps.outpoint = $1;
7772

7873
-- name: GetBatchSweptAmount :one
7974
SELECT
@@ -101,4 +96,4 @@ SELECT
10196
FROM
10297
(SELECT false AS false_value) AS f
10398
LEFT JOIN
104-
sweeps s ON s.swap_hash = $1;
99+
sweeps s ON s.outpoint = $1;

sweepbatcher/greedy_batch_selection.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/btcsuite/btcd/btcutil"
1010
"github.com/btcsuite/btcd/txscript"
11+
"github.com/btcsuite/btcd/wire"
1112
sweeppkg "github.com/lightninglabs/loop/sweep"
1213
"github.com/lightningnetwork/lnd/input"
1314
"github.com/lightningnetwork/lnd/lntypes"
@@ -108,8 +109,8 @@ func estimateSweepFeeIncrement(s *sweep) (feeDetails, feeDetails, error) {
108109
rbfCache: rbfCache{
109110
FeeRate: s.minFeeRate,
110111
},
111-
sweeps: map[lntypes.Hash]sweep{
112-
s.swapHash: *s,
112+
sweeps: map[wire.OutPoint]sweep{
113+
s.outpoint: *s,
113114
},
114115
}
115116

@@ -120,9 +121,13 @@ func estimateSweepFeeIncrement(s *sweep) (feeDetails, feeDetails, error) {
120121
}
121122

122123
// Add the same sweep again to measure weight increments.
123-
swapHash2 := s.swapHash
124-
swapHash2[0]++
125-
batch.sweeps[swapHash2] = *s
124+
outpoint2 := s.outpoint
125+
outpoint2.Hash[0]++
126+
if _, has := batch.sweeps[outpoint2]; has {
127+
return feeDetails{}, feeDetails{}, fmt.Errorf("dummy outpoint "+
128+
"%s is present in the batch", outpoint2)
129+
}
130+
batch.sweeps[outpoint2] = *s
126131

127132
// Estimate weight of a batch with two sweeps.
128133
fd2, err := estimateBatchWeight(batch)

0 commit comments

Comments
 (0)