Skip to content

Commit 409c72b

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 4e07450 commit 409c72b

File tree

7 files changed

+215
-71
lines changed

7 files changed

+215
-71
lines changed

assets/deposit/manager.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ func (m *Manager) Run(ctx context.Context, bestBlock uint32) error {
163163
return err
164164
}
165165

166+
// Wake the manager up very 10 seconds to check if there're any pending
167+
// chores to do.
168+
const wakeupInterval = time.Duration(10) * time.Second
169+
166170
for {
167171
select {
168172
case <-m.callEnter:
@@ -182,6 +186,15 @@ func (m *Manager) Run(ctx context.Context, bestBlock uint32) error {
182186
return err
183187
}
184188

189+
case <-time.After(wakeupInterval):
190+
err := m.publishPendingWithdrawals(ctx)
191+
if err != nil {
192+
log.Errorf("Unable to publish pending "+
193+
"withdrawals: %v", err)
194+
195+
return err
196+
}
197+
185198
case err := <-blockErrChan:
186199
log.Errorf("received error from block epoch "+
187200
"notification: %v", err)
@@ -871,6 +884,8 @@ func (m *Manager) handleDepositSpend(ctx context.Context, d *Deposit,
871884

872885
switch d.State {
873886
case StateTimeoutSweepPublished:
887+
fallthrough
888+
case StateCooperativeSweepPublished:
874889
log.Infof("Deposit %s withdrawn in: %s", d.ID, outpoint)
875890
d.State = StateSwept
876891

@@ -1016,3 +1031,68 @@ func (m *Manager) WithdrawDeposits(ctx context.Context,
10161031

10171032
return nil
10181033
}
1034+
1035+
// publishPendingWithdrawals publishes any pending deposit withdrawals.
1036+
func (m *Manager) publishPendingWithdrawals(ctx context.Context) error {
1037+
for _, d := range m.deposits {
1038+
// TODO(bhandras): republish on StateCooperativeSweepPublished.
1039+
if d.State != StateWithdrawn {
1040+
continue
1041+
}
1042+
1043+
// Start monitoring the sweep unless we're already doing so.
1044+
if _, ok := m.pendingSweeps[d.ID]; !ok {
1045+
err := m.waitForDepositSpend(ctx, d)
1046+
if err != nil {
1047+
log.Errorf("Unable to wait for deposit %v "+
1048+
"spend: %v", d.ID, err)
1049+
1050+
return err
1051+
}
1052+
1053+
m.pendingSweeps[d.ID] = struct{}{}
1054+
}
1055+
1056+
serverKey, err := m.store.GetAssetDepositServerKey(
1057+
ctx, d.ID,
1058+
)
1059+
if err != nil {
1060+
return err
1061+
}
1062+
1063+
lockID, err := d.lockID()
1064+
if err != nil {
1065+
return err
1066+
}
1067+
1068+
sweepAddr, err := address.DecodeAddress(
1069+
d.SweepAddr, &m.addressParams,
1070+
)
1071+
if err != nil {
1072+
return err
1073+
}
1074+
1075+
// TODO(bhandras): conf target should be dynamic/configrable.
1076+
const confTarget = 2
1077+
feeRateSatPerKw, err := m.walletKit.EstimateFeeRate(
1078+
ctx, confTarget,
1079+
)
1080+
1081+
funder := true
1082+
sendAssetResp, err := m.sweeper.PublishDepositSweepMuSig2(
1083+
ctx, d.Kit, funder, d.Proof, serverKey, sweepAddr,
1084+
feeRateSatPerKw.FeePerVByte(), lockID, lockExpiration,
1085+
)
1086+
if err != nil {
1087+
log.Errorf("Unable to publish deposit sweep for %v: %v",
1088+
d.ID, err)
1089+
} else {
1090+
log.Infof("Published sweep for deposit %v: %v", d.ID,
1091+
sendAssetResp.Transfer.AnchorTxHash)
1092+
1093+
d.State = StateCooperativeSweepPublished
1094+
}
1095+
}
1096+
1097+
return nil
1098+
}

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
@@ -314,3 +317,19 @@ func (s *SQLStore) SetAssetDepositServerKey(ctx context.Context,
314317
},
315318
)
316319
}
320+
321+
func (s *SQLStore) GetAssetDepositServerKey(ctx context.Context,
322+
depositID string) (*btcec.PrivateKey, error) {
323+
324+
keyBytes, err := s.db.GetAssetDepositServerInternalKey(ctx, depositID)
325+
if err != nil {
326+
return nil, err
327+
}
328+
329+
key, _ := btcec.PrivKeyFromBytes(keyBytes)
330+
if err != nil {
331+
return nil, err
332+
}
333+
334+
return key, nil
335+
}

go.mod

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ require (
2929
github.com/lightningnetwork/lnd/clock v1.1.1
3030
github.com/lightningnetwork/lnd/queue v1.1.1
3131
github.com/lightningnetwork/lnd/ticker v1.1.1
32-
github.com/lightningnetwork/lnd/tlv v1.3.1
32+
github.com/lightningnetwork/lnd/tlv v1.3.2
3333
github.com/lightningnetwork/lnd/tor v1.1.6
3434
github.com/ory/dockertest/v3 v3.10.0
3535
github.com/stretchr/testify v1.10.0
3636
github.com/urfave/cli v1.22.14
3737
go.etcd.io/bbolt v1.3.11
38-
golang.org/x/net v0.38.0
39-
golang.org/x/sync v0.12.0
38+
golang.org/x/net v0.39.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,12 +102,12 @@ 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
108-
github.com/jackc/pgx/v5 v5.6.0 // 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
108+
github.com/jackc/pgx/v5 v5.7.4 // indirect
109109
github.com/jackc/puddle v1.3.0 // indirect
110-
github.com/jackc/puddle/v2 v2.2.1 // indirect
110+
github.com/jackc/puddle/v2 v2.2.2 // indirect
111111
github.com/jackpal/gateway v1.0.5 // indirect
112112
github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad // indirect
113113
github.com/jonboulle/clockwork v0.2.2 // indirect
@@ -121,11 +121,11 @@ require (
121121
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.3 // indirect
122122
github.com/lightninglabs/neutrino v0.16.1 // indirect
123123
github.com/lightninglabs/neutrino/cache v1.1.2 // indirect
124-
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb // indirect
124+
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240815225420-8b40adf04ab9 // indirect
125125
github.com/lightningnetwork/lnd/fn/v2 v2.0.8 // indirect
126126
github.com/lightningnetwork/lnd/healthcheck v1.2.6 // indirect
127127
github.com/lightningnetwork/lnd/kvdb v1.4.16 // indirect
128-
github.com/lightningnetwork/lnd/sqldb v1.0.9 // indirect
128+
github.com/lightningnetwork/lnd/sqldb v1.0.10 // indirect
129129
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect
130130
github.com/mattn/go-isatty v0.0.20 // indirect
131131
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
@@ -181,12 +181,12 @@ require (
181181
go.uber.org/atomic v1.10.0 // indirect
182182
go.uber.org/multierr v1.6.0 // indirect
183183
go.uber.org/zap v1.23.0 // indirect
184-
golang.org/x/crypto v0.36.0 // indirect
184+
golang.org/x/crypto v0.37.0 // indirect
185185
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
186186
golang.org/x/mod v0.21.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
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.9
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)