Skip to content

Commit b0fdb36

Browse files
committed
loopd: static address deposit withdrawal support
1 parent 1e2bc07 commit b0fdb36

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

loopd/daemon.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
loop_looprpc "github.com/lightninglabs/loop/looprpc"
2424
"github.com/lightninglabs/loop/staticaddr/address"
2525
"github.com/lightninglabs/loop/staticaddr/deposit"
26+
"github.com/lightninglabs/loop/staticaddr/withdraw"
2627
loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc"
2728
"github.com/lightninglabs/loop/sweepbatcher"
2829
"github.com/lightningnetwork/lnd/clock"
@@ -437,6 +438,12 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
437438
swapClient.Conn,
438439
)
439440

441+
// Create a static address client that cooperatively closes deposits
442+
// with the server.
443+
withdrawalClient := loop_swaprpc.NewWithdrawalServerClient(
444+
swapClient.Conn,
445+
)
446+
440447
// Both the client RPC server and the swap server client should stop
441448
// on main context cancel. So we create it early and pass it down.
442449
d.mainCtx, d.mainCtxCancel = context.WithCancel(context.Background())
@@ -500,6 +507,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
500507

501508
staticAddressManager *address.Manager
502509
depositManager *deposit.Manager
510+
withdrawalManager *withdraw.Manager
503511
)
504512
// Create the reservation and instantout managers.
505513
if d.cfg.EnableExperimental {
@@ -561,6 +569,17 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
561569
Signer: d.lnd.Signer,
562570
}
563571
depositManager = deposit.NewManager(depoCfg)
572+
573+
// Static address deposit closure manager setup.
574+
closeCfg := &withdraw.ManagerConfig{
575+
WithdrawalServerClient: withdrawalClient,
576+
AddressManager: staticAddressManager,
577+
DepositManager: depositManager,
578+
WalletKit: d.lnd.WalletKit,
579+
ChainNotifier: d.lnd.ChainNotifier,
580+
Signer: d.lnd.Signer,
581+
}
582+
withdrawalManager = withdraw.NewManager(closeCfg)
564583
}
565584

566585
// Now finally fully initialize the swap client RPC server instance.
@@ -578,6 +597,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
578597
instantOutManager: instantOutManager,
579598
staticAddressManager: staticAddressManager,
580599
depositManager: depositManager,
600+
withdrawalManager: withdrawalManager,
581601
}
582602

583603
// Retrieve all currently existing swaps from the database.
@@ -709,6 +729,32 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
709729
depositManager.WaitInitComplete()
710730
}
711731

732+
// Start the static address deposit withdrawal manager.
733+
if withdrawalManager != nil {
734+
d.wg.Add(1)
735+
go func() {
736+
defer d.wg.Done()
737+
738+
// Lnd's GetInfo call supplies us with the current block
739+
// height.
740+
info, err := d.lnd.Client.GetInfo(d.mainCtx)
741+
if err != nil {
742+
d.internalErrChan <- err
743+
return
744+
}
745+
746+
log.Info("Starting static address deposit closure " +
747+
"manager...")
748+
err = withdrawalManager.Run(d.mainCtx, info.BlockHeight)
749+
if err != nil && !errors.Is(context.Canceled, err) {
750+
d.internalErrChan <- err
751+
}
752+
log.Info("Static address deposit closure " +
753+
"manager stopped")
754+
}()
755+
withdrawalManager.WaitInitComplete()
756+
}
757+
712758
// Last, start our internal error handler. This will return exactly one
713759
// error or nil on the main error channel to inform the caller that
714760
// something went wrong or that shutdown is complete. We don't add to

loopd/perms/perms.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ var RequiredPermissions = map[string][]bakery.Op{
8383
Entity: "loop",
8484
Action: "in",
8585
}},
86+
"/looprpc.SwapClient/WithdrawDeposits": {{
87+
Entity: "swap",
88+
Action: "execute",
89+
}, {
90+
Entity: "loop",
91+
Action: "in",
92+
}},
8693
"/looprpc.SwapClient/GetLsatTokens": {{
8794
Entity: "auth",
8895
Action: "read",

loopd/swapclient_server.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/btcsuite/btcd/btcec/v2"
1616
"github.com/btcsuite/btcd/btcutil"
1717
"github.com/btcsuite/btcd/chaincfg"
18+
"github.com/btcsuite/btcd/wire"
1819
"github.com/lightninglabs/aperture/lsat"
1920
"github.com/lightninglabs/lndclient"
2021
"github.com/lightninglabs/loop"
@@ -26,6 +27,7 @@ import (
2627
clientrpc "github.com/lightninglabs/loop/looprpc"
2728
"github.com/lightninglabs/loop/staticaddr/address"
2829
"github.com/lightninglabs/loop/staticaddr/deposit"
30+
"github.com/lightninglabs/loop/staticaddr/withdraw"
2931
"github.com/lightninglabs/loop/swap"
3032
looprpc "github.com/lightninglabs/loop/swapserverrpc"
3133
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
@@ -87,6 +89,7 @@ type swapClientServer struct {
8789
instantOutManager *instantout.Manager
8890
staticAddressManager *address.Manager
8991
depositManager *deposit.Manager
92+
withdrawalManager *withdraw.Manager
9093
swaps map[lntypes.Hash]loop.SwapInfo
9194
subscribers map[int]chan<- interface{}
9295
statusChan chan loop.SwapInfo
@@ -1278,6 +1281,61 @@ func (s *swapClientServer) ListUnspent(ctx context.Context,
12781281
return &clientrpc.ListUnspentResponse{Utxos: respUtxos}, nil
12791282
}
12801283

1284+
// WithdrawDeposits tries to obtain a partial signature from the server to spend
1285+
// the selected deposits to the client's wallet.
1286+
func (s *swapClientServer) WithdrawDeposits(ctx context.Context,
1287+
req *clientrpc.WithdrawDepositsRequest) (
1288+
*clientrpc.WithdrawDepositsResponse, error) {
1289+
1290+
var (
1291+
isAllSelected = req.All
1292+
isUtxoSelected = req.Outpoints != nil
1293+
outpoints []wire.OutPoint
1294+
err error
1295+
)
1296+
1297+
switch {
1298+
case isAllSelected == isUtxoSelected:
1299+
return nil, fmt.Errorf("must select either all or some utxos")
1300+
1301+
case isAllSelected:
1302+
outpoints, err = s.depositManager.GetActiveOutpoints()
1303+
if err != nil {
1304+
return nil, err
1305+
}
1306+
1307+
case isUtxoSelected:
1308+
outpoints, err = toServerOutpoints(req.Outpoints)
1309+
if err != nil {
1310+
return nil, err
1311+
}
1312+
}
1313+
1314+
err = s.withdrawalManager.WithdrawDeposits(ctx, outpoints)
1315+
if err != nil {
1316+
return nil, err
1317+
}
1318+
1319+
return &clientrpc.WithdrawDepositsResponse{}, err
1320+
}
1321+
1322+
func toServerOutpoints(outpoints []*clientrpc.OutPoint) ([]wire.OutPoint,
1323+
error) {
1324+
1325+
var serverOutpoints []wire.OutPoint
1326+
for _, o := range outpoints {
1327+
outpointStr := fmt.Sprintf("%s:%d", o.TxidStr, o.OutputIndex)
1328+
newOutpoint, err := wire.NewOutPointFromString(outpointStr)
1329+
if err != nil {
1330+
return nil, err
1331+
}
1332+
1333+
serverOutpoints = append(serverOutpoints, *newOutpoint)
1334+
}
1335+
1336+
return serverOutpoints, nil
1337+
}
1338+
12811339
func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) {
12821340
switch reason {
12831341
case liquidity.ReasonNone:

0 commit comments

Comments
 (0)