diff --git a/liquidity/liquidity.go b/liquidity/liquidity.go index 9afe872..7556117 100644 --- a/liquidity/liquidity.go +++ b/liquidity/liquidity.go @@ -157,6 +157,15 @@ var ( // set together are specified. ErrExclusiveRules = errors.New("channel and peer rules must be " + "exclusive") + + // ErrAmbiguousDestAddr is returned when a destination address and + // a extended public key account is set. + ErrAmbiguousDestAddr = errors.New("ambiguous destination address") + + // ErrAccountAndAddrType indicates if an account is set but the + // account address type is not or vice versa. + ErrAccountAndAddrType = errors.New("account and address type have " + + "to be both either set or unset") ) // Config contains the external functionality required to run the diff --git a/liquidity/loopout_builder.go b/liquidity/loopout_builder.go index b8726b3..062b1f3 100644 --- a/liquidity/loopout_builder.go +++ b/liquidity/loopout_builder.go @@ -154,9 +154,15 @@ func (b *loopOutBuilder) buildSwap(ctx context.Context, pubkey route.Vertex, request.Label = labels.EasyAutoloopLabel(swap.TypeOut) } + account := "" + addrType := walletrpc.AddressType_WITNESS_PUBKEY_HASH + if len(params.Account) > 0 { + account = params.Account + addrType = params.AccountAddrType + } + addr, err := b.cfg.Lnd.WalletKit.NextAddr( - ctx, "", walletrpc.AddressType_WITNESS_PUBKEY_HASH, - false, + ctx, account, addrType, false, ) if err != nil { return nil, err diff --git a/liquidity/parameters.go b/liquidity/parameters.go index 34f8ae1..7fcdb10 100644 --- a/liquidity/parameters.go +++ b/liquidity/parameters.go @@ -3,6 +3,7 @@ package liquidity import ( "errors" "fmt" + "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "strings" "time" @@ -42,10 +43,18 @@ type Parameters struct { // Autoloop enables automatic dispatch of swaps. Autoloop bool - // DestAddr is the address to be used for sweeping the on-chain HTLC that - // is related with a loop out. + // DestAddr is the address to be used for sweeping the on-chain HTLC + // that is related with a loop out. DestAddr btcutil.Address + // An alternative destination address source for the swap. This field + // represents the name of the account in the backing lnd instance. + // Refer to lnd's wallet import functions for reference. + Account string + + // The address type of the account specified in the account field. + AccountAddrType walletrpc.AddressType + // AutoFeeBudget is the total amount we allow to be spent on // automatically dispatched swaps. Once this budget has been used, we // will stop dispatching swaps until the budget is refreshed. @@ -227,6 +236,21 @@ func (p Parameters) validate(minConfs int32, openChans []lndclient.ChannelInfo, return ErrZeroInFlight } + // Destination address and account cannot be set at the same time. + if p.DestAddr != nil && len(p.DestAddr.String()) > 0 && + len(p.Account) > 0 { + + return ErrAmbiguousDestAddr + } + + // If an account is specified the respective address type must be + // specified as well, or both must be unset. + if len(p.Account) == 0 != + (p.AccountAddrType == walletrpc.AddressType_UNKNOWN) { + + return ErrAccountAndAddrType + } + err := validateRestrictions(server, &p.ClientRestrictions) if err != nil { return err @@ -376,13 +400,20 @@ func RpcToParameters(req *clientrpc.LiquidityParameters) (*Parameters, if req.AutoloopDestAddress == "default" { destaddr = nil } else { - destaddr, err = btcutil.DecodeAddress(req.AutoloopDestAddress, nil) + destaddr, err = btcutil.DecodeAddress( + req.AutoloopDestAddress, nil, + ) if err != nil { return nil, err } } } + addrType := walletrpc.AddressType_UNKNOWN + if req.AccountAddrType == clientrpc.AddressType_TAPROOT_PUBKEY { + addrType = walletrpc.AddressType_TAPROOT_PUBKEY + } + params := &Parameters{ FeeLimit: feeLimit, SweepConfTarget: req.SweepConfTarget, @@ -393,6 +424,8 @@ func RpcToParameters(req *clientrpc.LiquidityParameters) (*Parameters, int64(req.AutoloopBudgetLastRefresh), 0, ), DestAddr: destaddr, + Account: req.Account, + AccountAddrType: addrType, AutoFeeBudget: btcutil.Amount(req.AutoloopBudgetSat), MaxAutoInFlight: int(req.AutoMaxInFlight), ChannelRules: make( @@ -487,6 +520,16 @@ func ParametersToRpc(cfg Parameters) (*clientrpc.LiquidityParameters, destaddr = cfg.DestAddr.String() } + var addrType clientrpc.AddressType + switch cfg.AccountAddrType { + case walletrpc.AddressType_TAPROOT_PUBKEY: + addrType = clientrpc.AddressType_TAPROOT_PUBKEY + + default: + addrType = clientrpc.AddressType_ADDRESS_TYPE_UNKNOWN + + } + rpcCfg := &clientrpc.LiquidityParameters{ SweepConfTarget: cfg.SweepConfTarget, FailureBackoffSec: uint64(cfg.FailureBackOff.Seconds()), @@ -512,6 +555,8 @@ func ParametersToRpc(cfg Parameters) (*clientrpc.LiquidityParameters, HtlcConfTarget: cfg.HtlcConfTarget, EasyAutoloop: cfg.EasyAutoloop, EasyAutoloopLocalTargetSat: uint64(cfg.EasyAutoloopTarget), + Account: cfg.Account, + AccountAddrType: addrType, } switch f := cfg.FeeLimit.(type) {