2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-16 00:12:52 +00:00
loop/liquidity/loopin_builder.go
George Tsagkarelis a48924a664
liquidity: get autoloop flag directly from params
Previously we would exclusively pass the autoloop boolean to multiple
functions while they had directly access to the manager's parameters.
With this commit we remove this explicit flag from the various function
interfaces and retrieve the value directly from the parameters.
2023-05-29 13:24:16 +03:00

127 lines
3.5 KiB
Go

package liquidity
import (
"context"
"github.com/btcsuite/btcd/btcutil"
"github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/labels"
"github.com/lightninglabs/loop/swap"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// Compile-time assertion that loopInBuilder satisfies the swapBuilder
// interface.
var _ swapBuilder = (*loopInBuilder)(nil)
func newLoopInBuilder(cfg *Config) *loopInBuilder {
return &loopInBuilder{
cfg: cfg,
}
}
type loopInBuilder struct {
// cfg contains all the external functionality we require to create
// swaps.
cfg *Config
}
// swapType returns the swap type that the builder is responsible for creating.
func (b *loopInBuilder) swapType() swap.Type {
return swap.TypeIn
}
// maySwap checks whether we can currently execute a swap, examining the
// current on-chain fee conditions against relevant to our swap type against
// our fee restrictions.
//
// For loop in, we cannot check any upfront costs because we do not know how
// many inputs will be used for our on-chain htlc before it is made, so we can't
// make nay estimations.
func (b *loopInBuilder) maySwap(_ context.Context, _ Parameters) error {
return nil
}
// inUse examines our current swap traffic to determine whether we should
// suggest the builder's type of swap for the peer and channels suggested.
func (b *loopInBuilder) inUse(traffic *swapTraffic, peer route.Vertex,
channels []lnwire.ShortChannelID) error {
for _, chanID := range channels {
if traffic.ongoingLoopOut[chanID] {
log.Debugf("Channel: %v not eligible for suggestions, "+
"ongoing loop out utilizing channel", chanID)
return newReasonError(ReasonLoopOut)
}
}
if traffic.ongoingLoopIn[peer] {
log.Debugf("Peer: %x not eligible for suggestions ongoing "+
"loop in utilizing peer", peer)
return newReasonError(ReasonLoopIn)
}
lastFail, recentFail := traffic.failedLoopIn[peer]
if recentFail {
log.Debugf("Peer: %v not eligible for suggestions, "+
"was part of a failed swap at: %v", peer,
lastFail)
return newReasonError(ReasonFailureBackoff)
}
return nil
}
// buildSwap creates a swap for the target peer/channels provided. The autoloop
// boolean indicates whether this swap will actually be executed.
//
// For loop in, we do not add the autoloop label for dry runs.
func (b *loopInBuilder) buildSwap(ctx context.Context, pubkey route.Vertex,
_ []lnwire.ShortChannelID, amount btcutil.Amount,
params Parameters) (swapSuggestion, error) {
quote, err := b.cfg.LoopInQuote(ctx, &loop.LoopInQuoteRequest{
Amount: amount,
LastHop: &pubkey,
HtlcConfTarget: params.HtlcConfTarget,
})
if err != nil {
// If the server fails our quote, we're not reachable right
// now, so we want to catch this error and fail with a
// structured error so that we know why we can't swap.
status, ok := status.FromError(err)
if ok && status.Code() == codes.FailedPrecondition {
return nil, newReasonError(ReasonLoopInUnreachable)
}
return nil, err
}
if err := params.FeeLimit.loopInLimits(amount, quote); err != nil {
return nil, err
}
request := loop.LoopInRequest{
Amount: amount,
MaxSwapFee: quote.SwapFee,
MaxMinerFee: quote.MinerFee,
HtlcConfTarget: params.HtlcConfTarget,
LastHop: &pubkey,
Initiator: autoloopSwapInitiator,
}
if params.Autoloop {
request.Label = labels.AutoloopLabel(swap.TypeIn)
}
return &loopInSwapSuggestion{
LoopInRequest: request,
}, nil
}