loopd: static address withdrawals support

This commit is contained in:
Slyghtning 2024-05-06 14:19:43 +02:00
parent 3dca1537c3
commit a7f2f2d8c8
No known key found for this signature in database
GPG key ID: F82D456EA023C9BF
3 changed files with 117 additions and 0 deletions

View file

@ -24,6 +24,7 @@ import (
"github.com/lightninglabs/loop/notifications"
"github.com/lightninglabs/loop/staticaddr/address"
"github.com/lightninglabs/loop/staticaddr/deposit"
"github.com/lightninglabs/loop/staticaddr/withdraw"
loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc"
"github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightningnetwork/lnd/clock"
@ -539,6 +540,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
staticAddressManager *address.Manager
depositManager *deposit.Manager
withdrawalManager *withdraw.Manager
)
// Create the reservation and instantout managers.
@ -604,6 +606,18 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
Signer: d.lnd.Signer,
}
depositManager = deposit.NewManager(depoCfg)
// Static address deposit withdrawal manager setup.
withdrawalCfg := &withdraw.ManagerConfig{
StaticAddressServerClient: staticAddressClient,
AddressManager: staticAddressManager,
DepositManager: depositManager,
WalletKit: d.lnd.WalletKit,
ChainParams: d.lnd.ChainParams,
ChainNotifier: d.lnd.ChainNotifier,
Signer: d.lnd.Signer,
}
withdrawalManager = withdraw.NewManager(withdrawalCfg)
}
// Now finally fully initialize the swap client RPC server instance.
@ -621,6 +635,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
instantOutManager: instantOutManager,
staticAddressManager: staticAddressManager,
depositManager: depositManager,
withdrawalManager: withdrawalManager,
}
// Retrieve all currently existing swaps from the database.
@ -804,6 +819,32 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
depositManager.WaitInitComplete()
}
// Start the static address deposit withdrawal manager.
if withdrawalManager != nil {
d.wg.Add(1)
go func() {
defer d.wg.Done()
// Lnd's GetInfo call supplies us with the current block
// height.
info, err := d.lnd.Client.GetInfo(d.mainCtx)
if err != nil {
d.internalErrChan <- err
return
}
log.Info("Starting static address deposit withdrawal " +
"manager...")
err = withdrawalManager.Run(d.mainCtx, info.BlockHeight)
if err != nil && !errors.Is(context.Canceled, err) {
d.internalErrChan <- err
}
log.Info("Static address deposit withdrawal manager " +
"stopped")
}()
withdrawalManager.WaitInitComplete()
}
// Last, start our internal error handler. This will return exactly one
// error or nil on the main error channel to inform the caller that
// something went wrong or that shutdown is complete. We don't add to

View file

@ -87,6 +87,13 @@ var RequiredPermissions = map[string][]bakery.Op{
Entity: "loop",
Action: "in",
}},
"/looprpc.SwapClient/WithdrawDeposits": {{
Entity: "swap",
Action: "execute",
}, {
Entity: "loop",
Action: "in",
}},
"/looprpc.SwapClient/GetLsatTokens": {{
Entity: "auth",
Action: "read",

View file

@ -15,6 +15,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop"
@ -26,6 +27,7 @@ import (
"github.com/lightninglabs/loop/looprpc"
"github.com/lightninglabs/loop/staticaddr/address"
"github.com/lightninglabs/loop/staticaddr/deposit"
"github.com/lightninglabs/loop/staticaddr/withdraw"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/swapserverrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
@ -87,6 +89,7 @@ type swapClientServer struct {
instantOutManager *instantout.Manager
staticAddressManager *address.Manager
depositManager *deposit.Manager
withdrawalManager *withdraw.Manager
swaps map[lntypes.Hash]loop.SwapInfo
subscribers map[int]chan<- interface{}
statusChan chan loop.SwapInfo
@ -1363,6 +1366,72 @@ func (s *swapClientServer) ListUnspentDeposits(ctx context.Context,
return &looprpc.ListUnspentDepositsResponse{Utxos: respUtxos}, nil
}
// WithdrawDeposits tries to obtain a partial signature from the server to spend
// the selected deposits to the client's wallet.
func (s *swapClientServer) WithdrawDeposits(ctx context.Context,
req *looprpc.WithdrawDepositsRequest) (
*looprpc.WithdrawDepositsResponse, error) {
var (
isAllSelected = req.All
isUtxoSelected = len(req.Outpoints) > 0
outpoints []wire.OutPoint
err error
)
switch {
case isAllSelected == isUtxoSelected:
return nil, fmt.Errorf("must select either all or some utxos")
case isAllSelected:
deposits, err := s.depositManager.GetActiveDepositsInState(
deposit.Deposited,
)
if err != nil {
return nil, err
}
for _, d := range deposits {
outpoints = append(outpoints, d.OutPoint)
}
case isUtxoSelected:
outpoints, err = toServerOutpoints(req.Outpoints)
if err != nil {
return nil, err
}
}
txhash, pkScript, err := s.withdrawalManager.DeliverWithdrawalRequest(
ctx, outpoints,
)
if err != nil {
return nil, err
}
return &looprpc.WithdrawDepositsResponse{
WithdrawalTxHash: txhash,
PkScript: pkScript,
}, err
}
func toServerOutpoints(outpoints []*looprpc.OutPoint) ([]wire.OutPoint,
error) {
var serverOutpoints []wire.OutPoint
for _, o := range outpoints {
outpointStr := fmt.Sprintf("%s:%d", o.TxidStr, o.OutputIndex)
newOutpoint, err := wire.NewOutPointFromString(outpointStr)
if err != nil {
return nil, err
}
serverOutpoints = append(serverOutpoints, *newOutpoint)
}
return serverOutpoints, nil
}
func rpcAutoloopReason(reason liquidity.Reason) (looprpc.AutoReason, error) {
switch reason {
case liquidity.ReasonNone: