diff --git a/pickhardt-payments/src/main/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputation.java b/pickhardt-payments/src/main/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputation.java index eb754b03..cc03341d 100644 --- a/pickhardt-payments/src/main/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputation.java +++ b/pickhardt-payments/src/main/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputation.java @@ -29,6 +29,7 @@ import java.util.function.Function; @Component public class EdgeComputation { + private static final Coins REMOTE_BALANCE_REQUIRED_TO_SEND = Coins.ofSatoshis(400); private final Logger logger = LoggerFactory.getLogger(getClass()); private final GrpcGraph grpcGraph; @@ -150,6 +151,10 @@ public class EdgeComputation { Pubkey source = edge.startNode(); ChannelId channelId = edge.channelId(); if (ownPubKey.equals(source)) { + Coins availableRemote = getLocalChannelAvailableRemote(channelId).orElse(Coins.NONE); + if (availableRemote.subtract(REMOTE_BALANCE_REQUIRED_TO_SEND).isNonPositive()) { + return Optional.of(Coins.NONE); + } return getLocalChannelAvailableLocal(channelId); } Pubkey target = edge.endNode(); diff --git a/pickhardt-payments/src/test/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputationTest.java b/pickhardt-payments/src/test/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputationTest.java index c6f24e4e..6f9f886a 100644 --- a/pickhardt-payments/src/test/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputationTest.java +++ b/pickhardt-payments/src/test/java/de/cotto/lndmanagej/pickhardtpayments/EdgeComputationTest.java @@ -4,6 +4,7 @@ import de.cotto.lndmanagej.grpc.GrpcGetInfo; import de.cotto.lndmanagej.grpc.GrpcGraph; import de.cotto.lndmanagej.grpc.middleware.GrpcMiddlewareService; import de.cotto.lndmanagej.model.ChannelCoreInformation; +import de.cotto.lndmanagej.model.ChannelId; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.DirectedChannelEdge; import de.cotto.lndmanagej.model.Edge; @@ -198,11 +199,26 @@ class EdgeComputationTest { Coins knownLiquidity = Coins.ofSatoshis(4_567); Coins availableKnownLiquidity = getAvailableKnownLiquidity(knownLiquidity); when(balanceService.getAvailableLocalBalance(EDGE.channelId())).thenReturn(knownLiquidity); + when(balanceService.getAvailableRemoteBalance(EDGE.channelId())).thenReturn(Coins.ofSatoshis(401)); assertThat(edgeComputation.getEdges(DEFAULT_PAYMENT_OPTIONS, MAX_TIME_LOCK_DELTA).edges()) .contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, availableKnownLiquidity)); } + @Test + void ignores_local_channels_with_lots_of_local_liquidity_but_almost_nothing_on_remote_side() { + // https://github.com/lightningnetwork/lnd/issues/7108 + mockEdge(); + ChannelId channelId = EDGE.channelId(); + when(grpcGetInfo.getPubkey()).thenReturn(EDGE.startNode()); + when(channelService.getOpenChannel(channelId)).thenReturn(Optional.of(LOCAL_OPEN_CHANNEL)); + when(balanceService.getAvailableRemoteBalance(channelId)).thenReturn(Coins.ofSatoshis(400)); + lenient().when(balanceService.getAvailableLocalBalance(channelId)).thenReturn(Coins.ofSatoshis(1_000_000)); + + assertThat(edgeComputation.getEdges(DEFAULT_PAYMENT_OPTIONS, MAX_TIME_LOCK_DELTA).edges()) + .contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, Coins.NONE)); + } + @Test void adds_edge_from_route_hint_service() { when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of())); @@ -307,6 +323,7 @@ class EdgeComputationTest { Coins availableKnownLiquidity = getAvailableKnownLiquidity(knownLiquidity); when(channelService.getOpenChannel(EDGE.channelId())).thenReturn(Optional.of(LOCAL_OPEN_CHANNEL)); when(balanceService.getAvailableLocalBalance(EDGE.channelId())).thenReturn(knownLiquidity); + when(balanceService.getAvailableRemoteBalance(EDGE.channelId())).thenReturn(Coins.ofSatoshis(401)); assertThat(edgeComputation.getEdgeWithLiquidityInformation(EDGE)) .isEqualTo(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, availableKnownLiquidity)); }