Skip to content

Commit 78e02d4

Browse files
committed
assets+loopdb: publish cooperative deposit withdrawal transaction
This commit implements the full cooperative deposit withdrawal flow. The client first fetches keys for any pending withdrawals, then publishes sweep transactions using the revealed key to sign the deposit sweep. Once the sweep confirms, the deposit’s state is updated in the deposit store.
1 parent bf9d75f commit 78e02d4

File tree

8 files changed

+218
-68
lines changed

8 files changed

+218
-68
lines changed

assets/deposit/manager.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ func (m *Manager) Run(ctx context.Context, bestBlock uint32) error {
169169
return err
170170
}
171171

172+
// Wake the manager up very 10 seconds to check if there're any pending
173+
// chores to do.
174+
const wakeupInterval = time.Duration(10) * time.Second
175+
withdrawTicker := time.NewTicker(wakeupInterval)
176+
172177
for {
173178
select {
174179
case <-m.callEnter:
@@ -188,6 +193,15 @@ func (m *Manager) Run(ctx context.Context, bestBlock uint32) error {
188193
return err
189194
}
190195

196+
case <-withdrawTicker.C:
197+
err := m.publishPendingWithdrawals(ctx)
198+
if err != nil {
199+
log.Errorf("Unable to publish pending "+
200+
"withdrawals: %v", err)
201+
202+
return err
203+
}
204+
191205
case err := <-blockErrChan:
192206
log.Errorf("received error from block epoch "+
193207
"notification: %v", err)
@@ -944,6 +958,8 @@ func (m *Manager) handleDepositSpend(ctx context.Context, d *Deposit,
944958

945959
switch d.State {
946960
case StateTimeoutSweepPublished:
961+
fallthrough
962+
case StateCooperativeSweepPublished:
947963
d.State = StateSwept
948964

949965
err := m.releaseDepositSweepInputs(ctx, d)
@@ -1085,3 +1101,73 @@ func (m *Manager) WithdrawDeposits(ctx context.Context,
10851101

10861102
return nil
10871103
}
1104+
1105+
// publishPendingWithdrawals publishes any pending deposit withdrawals.
1106+
func (m *Manager) publishPendingWithdrawals(ctx context.Context) error {
1107+
for _, d := range m.deposits {
1108+
// TODO(bhandras): republish on StateCooperativeSweepPublished.
1109+
if d.State != StateWithdrawn {
1110+
continue
1111+
}
1112+
1113+
serverKey, err := m.store.GetAssetDepositServerKey(
1114+
ctx, d.ID,
1115+
)
1116+
if err != nil {
1117+
return err
1118+
}
1119+
1120+
lockID, err := d.lockID()
1121+
if err != nil {
1122+
return err
1123+
}
1124+
1125+
// TODO(bhandras): conf target should be dynamic/configrable.
1126+
const confTarget = 2
1127+
feeRateSatPerKw, err := m.walletKit.EstimateFeeRate(
1128+
ctx, confTarget,
1129+
)
1130+
if err != nil {
1131+
return err
1132+
}
1133+
1134+
funder := true
1135+
sendResp, err := m.sweeper.PublishDepositSweepMuSig2(
1136+
ctx, d.Kit, funder, d.Proof, serverKey,
1137+
asset.NewScriptKey(d.SweepScriptKey),
1138+
d.SweepInternalKey, d.withdrawLabel(),
1139+
feeRateSatPerKw.FeePerVByte(), lockID, lockExpiration,
1140+
)
1141+
if err != nil {
1142+
log.Errorf("Unable to publish deposit sweep for %v: %v",
1143+
d.ID, err)
1144+
} else {
1145+
log.Infof("Published sweep for deposit %v: %v", d.ID,
1146+
sendResp.Transfer.AnchorTxHash)
1147+
1148+
d.State = StateCooperativeSweepPublished
1149+
err = m.handleDepositStateUpdate(ctx, d)
1150+
if err != nil {
1151+
log.Errorf("Unable to update deposit %v "+
1152+
"state: %v", d.ID, err)
1153+
1154+
return err
1155+
}
1156+
}
1157+
1158+
// Start monitoring the sweep unless we're already doing so.
1159+
if _, ok := m.pendingSweeps[d.ID]; !ok {
1160+
err := m.waitForDepositSweep(ctx, d, d.withdrawLabel())
1161+
if err != nil {
1162+
log.Errorf("Unable to wait for deposit %v "+
1163+
"spend: %v", d.ID, err)
1164+
1165+
return err
1166+
}
1167+
1168+
m.pendingSweeps[d.ID] = struct{}{}
1169+
}
1170+
}
1171+
1172+
return nil
1173+
}

assets/deposit/sql_store.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ type Querier interface {
3838

3939
SetAssetDepositServerInternalKey(ctx context.Context,
4040
arg sqlc.SetAssetDepositServerInternalKeyParams) error
41+
42+
GetAssetDepositServerInternalKey(ctx context.Context,
43+
depositID string) ([]byte, error)
4144
}
4245

4346
// DepositBaseDB is the interface that contains all the queries generated
@@ -328,3 +331,19 @@ func (s *SQLStore) SetAssetDepositServerKey(ctx context.Context,
328331
},
329332
)
330333
}
334+
335+
func (s *SQLStore) GetAssetDepositServerKey(ctx context.Context,
336+
depositID string) (*btcec.PrivateKey, error) {
337+
338+
keyBytes, err := s.db.GetAssetDepositServerInternalKey(ctx, depositID)
339+
if err != nil {
340+
return nil, err
341+
}
342+
343+
key, _ := btcec.PrivKeyFromBytes(keyBytes)
344+
if err != nil {
345+
return nil, err
346+
}
347+
348+
return key, nil
349+
}

go.mod

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require (
1616
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
1717
github.com/jackc/pgconn v1.14.3
1818
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438
19-
github.com/jackc/pgx/v5 v5.6.0
19+
github.com/jackc/pgx/v5 v5.7.4
2020
github.com/jessevdk/go-flags v1.4.0
2121
github.com/lib/pq v1.10.9
2222
github.com/lightninglabs/aperture v0.3.13-beta
@@ -36,7 +36,7 @@ require (
3636
github.com/stretchr/testify v1.10.0
3737
github.com/urfave/cli v1.22.14
3838
go.etcd.io/bbolt v1.3.11
39-
golang.org/x/sync v0.12.0
39+
golang.org/x/sync v0.13.0
4040
google.golang.org/grpc v1.64.1
4141
google.golang.org/protobuf v1.34.2
4242
gopkg.in/macaroon-bakery.v2 v2.3.0
@@ -73,8 +73,8 @@ require (
7373
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
7474
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
7575
github.com/decred/dcrd/lru v1.1.2 // indirect
76-
github.com/docker/cli v28.0.1+incompatible // indirect
77-
github.com/docker/docker v28.0.1+incompatible // indirect
76+
github.com/docker/cli v28.1.1+incompatible // indirect
77+
github.com/docker/docker v28.1.1+incompatible // indirect
7878
github.com/docker/go-connections v0.5.0 // indirect
7979
github.com/docker/go-units v0.5.0 // indirect
8080
github.com/dustin/go-humanize v1.0.1 // indirect
@@ -102,11 +102,11 @@ require (
102102
github.com/jackc/pgio v1.0.0 // indirect
103103
github.com/jackc/pgpassfile v1.0.0 // indirect
104104
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
105-
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
106-
github.com/jackc/pgtype v1.14.0 // indirect
107-
github.com/jackc/pgx/v4 v4.18.2 // indirect
105+
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
106+
github.com/jackc/pgtype v1.14.4 // indirect
107+
github.com/jackc/pgx/v4 v4.18.3 // indirect
108108
github.com/jackc/puddle v1.3.0 // indirect
109-
github.com/jackc/puddle/v2 v2.2.1 // indirect
109+
github.com/jackc/puddle/v2 v2.2.2 // indirect
110110
github.com/jackpal/gateway v1.0.5 // indirect
111111
github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad // indirect
112112
github.com/jonboulle/clockwork v0.2.2 // indirect
@@ -120,7 +120,7 @@ require (
120120
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.3 // indirect
121121
github.com/lightninglabs/neutrino v0.16.1 // indirect
122122
github.com/lightninglabs/neutrino/cache v1.1.2 // indirect
123-
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb // indirect
123+
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240815225420-8b40adf04ab9 // indirect
124124
github.com/lightningnetwork/lnd/fn/v2 v2.0.8 // indirect
125125
github.com/lightningnetwork/lnd/healthcheck v1.2.6 // indirect
126126
github.com/lightningnetwork/lnd/kvdb v1.4.16 // indirect
@@ -180,13 +180,13 @@ require (
180180
go.uber.org/atomic v1.10.0 // indirect
181181
go.uber.org/multierr v1.6.0 // indirect
182182
go.uber.org/zap v1.23.0 // indirect
183-
golang.org/x/crypto v0.36.0 // indirect
183+
golang.org/x/crypto v0.37.0 // indirect
184184
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
185185
golang.org/x/mod v0.21.0 // indirect
186-
golang.org/x/net v0.38.0 // indirect
187-
golang.org/x/sys v0.31.0 // indirect
188-
golang.org/x/term v0.30.0 // indirect
189-
golang.org/x/text v0.23.0 // indirect
186+
golang.org/x/net v0.39.0 // indirect
187+
golang.org/x/sys v0.32.0 // indirect
188+
golang.org/x/term v0.31.0 // indirect
189+
golang.org/x/text v0.24.0 // indirect
190190
golang.org/x/time v0.5.0 // indirect
191191
golang.org/x/tools v0.24.0 // indirect
192192
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
@@ -215,4 +215,27 @@ replace github.com/lightninglabs/loop/swapserverrpc => ./swapserverrpc
215215

216216
replace github.com/lightninglabs/loop/looprpc => ./looprpc
217217

218-
go 1.23.12
218+
// Temporary replace to add SubmitPackage support (https://github.com/btcsuite/btcwallet/pull/1009).
219+
replace github.com/btcsuite/btcwallet => github.com/bhandras/btcwallet v0.11.1-0.20250507171803-0de1c46b1cfc
220+
221+
// Temporary replace to add SubmitPackage support to btcd (https://github.com/btcsuite/btcd/pull/2366).
222+
replace github.com/btcsuite/btcd => github.com/bhandras/btcd v0.22.0-beta.0.20250507171227-f18160c86e92
223+
224+
// Temporary replace to add SubmitPackage support to lnd (https://github.com/lightningnetwork/lnd/pull/9784).
225+
replace github.com/lightningnetwork/lnd => github.com/bhandras/lnd v0.8.0-beta-rc3.0.20250717123715-6cda96a60994
226+
227+
// Temporary replace to make lnd compile with the SubmitPackage changes.
228+
replace github.com/lightningnetwork/lnd/sqldb => github.com/bhandras/lnd/sqldb v0.0.0-20250716041958-643fbb8af65b
229+
230+
// Temporary replace to include client API for SubmitPackage in lndclient (https://github.com/lightninglabs/lndclient/pull/223)
231+
replace github.com/lightninglabs/lndclient => github.com/lightninglabs/lndclient v1.0.1-0.20250717123354-cf534c9968b9
232+
233+
// Temporary replace to experimentally change all bitcoin transactions to use v3 (https://github.com/bhandras/taproot-assets/tree/v3-experimental)
234+
replace github.com/lightninglabs/taproot-assets => github.com/bhandras/taproot-assets v0.0.0-20250717122952-ca46f25f6c3b
235+
236+
// Temporary replace to make taproot-assets compile with the v3 changes.
237+
replace github.com/lightninglabs/taproot-assets/taprpc => github.com/bhandras/taproot-assets/taprpc v0.0.0-20250605133854-360a25355248
238+
239+
go 1.23.10
240+
241+
toolchain go1.24.5

0 commit comments

Comments
 (0)