diff --git a/liquidity/autoloop_test.go b/liquidity/autoloop_test.go index 561a0e187..76a477242 100644 --- a/liquidity/autoloop_test.go +++ b/liquidity/autoloop_test.go @@ -1287,9 +1287,20 @@ func TestEasyAutoloop(t *testing.T) { Capacity: 100000, } + // The custom channel should be ignored. + easyChannelCustom := lndclient.ChannelInfo{ + Active: true, + ChannelID: chanID1.ToUint64(), + PubKeyBytes: peer1, + LocalBalance: 50000, + RemoteBalance: 0, + Capacity: 100000, + CustomChannelData: []byte("foo"), + } + var ( channels = []lndclient.ChannelInfo{ - easyChannel1, easyChannel2, + easyChannel1, easyChannel2, easyChannelCustom, } params = Parameters{ @@ -1361,7 +1372,7 @@ func TestEasyAutoloop(t *testing.T) { // new context and restart the autolooper. easyChannel1.LocalBalance -= chan1Swap.Amount channels = []lndclient.ChannelInfo{ - easyChannel1, easyChannel2, + easyChannel1, easyChannel2, easyChannelCustom, } // Remove the custom dest address. @@ -1419,7 +1430,7 @@ func TestEasyAutoloop(t *testing.T) { // new context and restart the autolooper. easyChannel2.LocalBalance -= btcutil.Amount(amt2) channels = []lndclient.ChannelInfo{ - easyChannel1, easyChannel2, + easyChannel1, easyChannel2, easyChannelCustom, } c = newAutoloopTestCtx(t, params, channels, testRestrictions) @@ -1438,7 +1449,7 @@ func TestEasyAutoloop(t *testing.T) { // Restore the local balance to a higher value that will trigger a swap. easyChannel2.LocalBalance = btcutil.Amount(95000) channels = []lndclient.ChannelInfo{ - easyChannel1, easyChannel2, + easyChannel1, easyChannel2, easyChannelCustom, } // Override the feeppm with a lower one. diff --git a/liquidity/liquidity.go b/liquidity/liquidity.go index fbd842b1f..b8cbf5771 100644 --- a/liquidity/liquidity.go +++ b/liquidity/liquidity.go @@ -556,6 +556,9 @@ func (m *Manager) dispatchBestEasyAutoloopSwap(ctx context.Context) error { localTotal := btcutil.Amount(0) for _, channel := range channels { + if channelIsCustom(channel) { + continue + } localTotal += channel.LocalBalance } @@ -781,6 +784,10 @@ func (m *Manager) SuggestSwaps(ctx context.Context) ( channelPeers := make(map[uint64]route.Vertex) peerChannels := make(map[route.Vertex]*balances) for _, channel := range channels { + if channelIsCustom(channel) { + continue + } + channelPeers[channel.ChannelID] = channel.PubKeyBytes bal, ok := peerChannels[channel.PubKeyBytes] @@ -834,6 +841,14 @@ func (m *Manager) SuggestSwaps(ctx context.Context) ( balance := newBalances(channel) channelID := lnwire.NewShortChanIDFromInt(channel.ChannelID) + + if channelIsCustom(channel) { + resp.DisqualifiedChans[channelID] = + ReasonCustomChannelData + + continue + } + rule, ok := m.params.ChannelRules[channelID] if !ok { continue @@ -1424,6 +1439,10 @@ func (m *Manager) pickEasyAutoloopChannel(channels []lndclient.ChannelInfo, // Check each channel, since channels are already sorted we return the // first channel that passes all checks. for _, channel := range channels { + if channelIsCustom(channel) { + continue + } + shortChanID := lnwire.NewShortChanIDFromInt(channel.ChannelID) if !channel.Active { @@ -1548,3 +1567,12 @@ func satPerKwToSatPerVByte(satPerKw chainfee.SatPerKWeight) int64 { func ppmToSat(amount btcutil.Amount, ppm uint64) btcutil.Amount { return btcutil.Amount(uint64(amount) * ppm / FeeBase) } + +// channelIsCustom returns true if the channel has custom channel data. +// we'll want to ignore these channels for autoloop recommendations. +func channelIsCustom(channel lndclient.ChannelInfo) bool { + // If the channel has custom channel data, the channel is a + // non-standard channel, such as an asset channel and we + // don't want to consider it for swaps. + return channel.CustomChannelData != nil +} diff --git a/liquidity/liquidity_test.go b/liquidity/liquidity_test.go index f3fae1e65..b45c3dc1b 100644 --- a/liquidity/liquidity_test.go +++ b/liquidity/liquidity_test.go @@ -794,6 +794,29 @@ func TestSuggestSwaps(t *testing.T) { }, }, }, + { + + name: "don't consider asset channel", + channels: []lndclient.ChannelInfo{ + { + ChannelID: chanID1.ToUint64(), + PubKeyBytes: peer1, + LocalBalance: 10000, + RemoteBalance: 0, + Capacity: 10000, + CustomChannelData: []byte("foo"), + }, + }, + rules: map[lnwire.ShortChannelID]*SwapRule{ + chanID1: chanRule, + }, + suggestions: &Suggestions{ + DisqualifiedChans: map[lnwire.ShortChannelID]Reason{ // nolint: lll + chanID1: ReasonCustomChannelData, + }, + DisqualifiedPeers: noPeersDisqualified, + }, + }, } for _, testCase := range tests { diff --git a/liquidity/reasons.go b/liquidity/reasons.go index aee4a4c16..a73f9000a 100644 --- a/liquidity/reasons.go +++ b/liquidity/reasons.go @@ -69,6 +69,10 @@ const ( // ReasonLoopInUnreachable indicates that the server does not have a // path to the client, so cannot perform a loop in swap at this time. ReasonLoopInUnreachable + + // ReasonCustomChannelData indicates that the channel is not standard + // and should not be used for swaps. + ReasonCustomChannelData ) // String returns a string representation of a reason.