liquidity: refactor eligible channels logic to ineligible channels

This commit switches up our eligible channels logic to rather return
a struct containing information about our current swap traffic. This
change is made in preparation for returning reasons indicating why we
did not perform a swap for a specific channel - when we only return
eligible swaps, we lose the information about why all the excluded
channels weren't used.
pull/332/head
carla 3 years ago
parent d5096cdc21
commit b9b75c3c32
No known key found for this signature in database
GPG Key ID: 4CA7FE54A6213C91

@ -652,25 +652,32 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoloop bool) (
return nil, nil return nil, nil
} }
eligible, err := m.getEligibleChannels(ctx, loopOut, loopIn) channels, err := m.cfg.Lnd.Client.ListChannels(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Get a summary of the channels and peers that are not eligible due
// to ongoing swaps.
traffic := m.currentSwapTraffic(loopOut, loopIn)
var suggestions []loop.OutRequest var suggestions []loop.OutRequest
for _, channel := range eligible {
channelID := lnwire.NewShortChanIDFromInt(channel.ChannelID) for _, channel := range channels {
rule, ok := m.params.ChannelRules[channelID] balance := newBalances(channel)
rule, ok := m.params.ChannelRules[balance.channelID]
if !ok { if !ok {
continue continue
} }
balance := newBalances(channel) if !traffic.maySwap(channel.PubKeyBytes, balance.channelID) {
continue
suggestion := rule.suggestSwap(balance, restrictions) }
// We can have nil suggestions in the case where no action is // We can have nil suggestions in the case where no action is
// required, so we skip over them. // required, so we skip over them.
suggestion := rule.suggestSwap(balance, restrictions)
if suggestion == nil { if suggestion == nil {
continue continue
} }
@ -928,17 +935,13 @@ func (m *Manager) checkExistingAutoLoops(ctx context.Context,
return &summary, nil return &summary, nil
} }
// getEligibleChannels takes lists of our existing loop out and in swaps, and // currentSwapTraffic examines our existing swaps and returns a summary of the
// gets a list of channels that are not currently being utilized for a swap. // current activity which can be used to determine whether we should perform
func (m *Manager) getEligibleChannels(ctx context.Context, // any swaps.
loopOut []*loopdb.LoopOut, loopIn []*loopdb.LoopIn) ( func (m *Manager) currentSwapTraffic(loopOut []*loopdb.LoopOut,
[]lndclient.ChannelInfo, error) { loopIn []*loopdb.LoopIn) *swapTraffic {
var ( traffic := newSwapTraffic()
existingOut = make(map[lnwire.ShortChannelID]bool)
existingIn = make(map[route.Vertex]bool)
failedOut = make(map[lnwire.ShortChannelID]time.Time)
)
// Failure cutoff is the most recent failure timestamp we will still // Failure cutoff is the most recent failure timestamp we will still
// consider a channel eligible. Any channels involved in swaps that have // consider a channel eligible. Any channels involved in swaps that have
@ -971,7 +974,7 @@ func (m *Manager) getEligibleChannels(ctx context.Context,
id, id,
) )
failedOut[chanID] = failedAt traffic.failedLoopOut[chanID] = failedAt
} }
} }
} }
@ -988,7 +991,7 @@ func (m *Manager) getEligibleChannels(ctx context.Context,
for _, id := range chanSet { for _, id := range chanSet {
chanID := lnwire.NewShortChanIDFromInt(id) chanID := lnwire.NewShortChanIDFromInt(id)
existingOut[chanID] = true traffic.ongoingLoopOut[chanID] = true
} }
} }
@ -1003,51 +1006,55 @@ func (m *Manager) getEligibleChannels(ctx context.Context,
continue continue
} }
existingIn[*in.Contract.LastHop] = true traffic.ongoingLoopIn[*in.Contract.LastHop] = true
} }
channels, err := m.cfg.Lnd.Client.ListChannels(ctx) return traffic
if err != nil { }
return nil, err
}
// Run through our set of channels and skip over any channels that // swapTraffic contains a summary of our current and previously failed swaps.
// are currently being utilized by a restricted swap (where restricted type swapTraffic struct {
// means that a loop out limited channels, or a loop in limited last ongoingLoopOut map[lnwire.ShortChannelID]bool
// hop). ongoingLoopIn map[route.Vertex]bool
var eligible []lndclient.ChannelInfo failedLoopOut map[lnwire.ShortChannelID]time.Time
for _, channel := range channels { }
shortID := lnwire.NewShortChanIDFromInt(channel.ChannelID)
lastFail, recentFail := failedOut[shortID] func newSwapTraffic() *swapTraffic {
if recentFail { return &swapTraffic{
log.Debugf("Channel: %v not eligible for "+ ongoingLoopOut: make(map[lnwire.ShortChannelID]bool),
"suggestions, was part of a failed swap at: %v", ongoingLoopIn: make(map[route.Vertex]bool),
channel.ChannelID, lastFail) failedLoopOut: make(map[lnwire.ShortChannelID]time.Time),
}
}
continue // maySwap returns a boolean that indicates whether we may perform a swap for a
} // peer and its set of channels.
func (s *swapTraffic) maySwap(peer route.Vertex,
chanID lnwire.ShortChannelID) bool {
if existingOut[shortID] { lastFail, recentFail := s.failedLoopOut[chanID]
log.Debugf("Channel: %v not eligible for "+ if recentFail {
"suggestions, ongoing loop out utilizing "+ log.Debugf("Channel: %v not eligible for suggestions, was "+
"channel", channel.ChannelID) "part of a failed swap at: %v", chanID, lastFail)
continue return false
} }
if existingIn[channel.PubKeyBytes] { if s.ongoingLoopOut[chanID] {
log.Debugf("Channel: %v not eligible for "+ log.Debugf("Channel: %v not eligible for suggestions, "+
"suggestions, ongoing loop in utilizing "+ "ongoing loop out utilizing channel", chanID)
"peer", channel.ChannelID)
continue return false
} }
if s.ongoingLoopIn[peer] {
log.Debugf("Peer: %x not eligible for suggestions ongoing "+
"loop in utilizing peer", peer)
eligible = append(eligible, channel) return false
} }
return eligible, nil return true
} }
// checkFeeLimits takes a set of fees for a swap and checks whether they exceed // checkFeeLimits takes a set of fees for a swap and checks whether they exceed

Loading…
Cancel
Save