do not use local channels that cannot be found or where peer is offline

This commit is contained in:
Carsten Otto
2022-04-02 19:00:02 +02:00
parent dd4d2074ea
commit b871cdde82
2 changed files with 75 additions and 4 deletions

View File

@@ -7,6 +7,7 @@ import de.cotto.lndmanagej.grpc.GrpcGraph;
import de.cotto.lndmanagej.model.ChannelId;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.LocalChannel;
import de.cotto.lndmanagej.model.Policy;
import de.cotto.lndmanagej.model.Pubkey;
import de.cotto.lndmanagej.pickhardtpayments.model.Edge;
@@ -15,6 +16,7 @@ import de.cotto.lndmanagej.pickhardtpayments.model.EdgesWithLiquidityInformation
import de.cotto.lndmanagej.service.BalanceService;
import de.cotto.lndmanagej.service.ChannelService;
import de.cotto.lndmanagej.service.MissionControlService;
import de.cotto.lndmanagej.service.NodeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@@ -23,6 +25,7 @@ import java.time.Duration;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
@Component
public class EdgeComputation {
@@ -31,6 +34,7 @@ public class EdgeComputation {
private final GrpcGraph grpcGraph;
private final GrpcGetInfo grpcGetInfo;
private final ChannelService channelService;
private final NodeService nodeService;
private final BalanceService balanceService;
private final MissionControlService missionControlService;
private final LoadingCache<Object, EdgesWithLiquidityInformation> cache = new CacheBuilder()
@@ -42,12 +46,14 @@ public class EdgeComputation {
GrpcGraph grpcGraph,
GrpcGetInfo grpcGetInfo,
ChannelService channelService,
NodeService nodeService,
BalanceService balanceService,
MissionControlService missionControlService
) {
this.grpcGraph = grpcGraph;
this.grpcGetInfo = grpcGetInfo;
this.channelService = channelService;
this.nodeService = nodeService;
this.balanceService = balanceService;
this.missionControlService = missionControlService;
}
@@ -110,13 +116,22 @@ public class EdgeComputation {
}
private Optional<Coins> getLocalChannelAvailableLocal(ChannelId channelId) {
return channelService.getLocalChannel(channelId)
.map(c -> balanceService.getAvailableLocalBalance(channelId));
return getLocalChannelAvailable(channelId, balanceService::getAvailableLocalBalance);
}
private Optional<Coins> getLocalChannelAvailableRemote(ChannelId channelId) {
return channelService.getLocalChannel(channelId)
.map(c -> balanceService.getAvailableRemoteBalance(channelId));
return getLocalChannelAvailable(channelId, balanceService::getAvailableRemoteBalance);
}
private Optional<Coins> getLocalChannelAvailable(ChannelId channelId, Function<ChannelId, Coins> balanceProvider) {
LocalChannel localChannel = channelService.getLocalChannel(channelId).orElse(null);
if (localChannel == null) {
return Optional.of(Coins.NONE);
}
if (nodeService.getNode(localChannel.getRemotePubkey()).online()) {
return Optional.of(balanceProvider.apply(channelId));
}
return Optional.of(Coins.NONE);
}
private Coins getAvailableLiquidityUpperBound(Edge edge) {

View File

@@ -4,10 +4,13 @@ import de.cotto.lndmanagej.grpc.GrpcGetInfo;
import de.cotto.lndmanagej.grpc.GrpcGraph;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Node;
import de.cotto.lndmanagej.model.Pubkey;
import de.cotto.lndmanagej.pickhardtpayments.model.EdgeWithLiquidityInformation;
import de.cotto.lndmanagej.service.BalanceService;
import de.cotto.lndmanagej.service.ChannelService;
import de.cotto.lndmanagej.service.MissionControlService;
import de.cotto.lndmanagej.service.NodeService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -21,6 +24,7 @@ import java.util.Set;
import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY;
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL;
import static de.cotto.lndmanagej.model.NodeFixtures.NODE_PEER;
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_1;
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_DISABLED;
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_WITH_BASE_FEE;
@@ -31,6 +35,8 @@ import static de.cotto.lndmanagej.pickhardtpayments.model.EdgeFixtures.EDGE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
@@ -53,10 +59,14 @@ class EdgeComputationTest {
@Mock
private MissionControlService missionControlService;
@Mock
private NodeService nodeService;
@BeforeEach
void setUp() {
lenient().when(grpcGetInfo.getPubkey()).thenReturn(PUBKEY_4);
lenient().when(missionControlService.getMinimumOfRecentFailures(any(), any())).thenReturn(Optional.empty());
lenient().when(nodeService.getNode(any())).thenReturn(NODE_PEER);
}
@Test
@@ -91,6 +101,26 @@ class EdgeComputationTest {
.contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, knownLiquidity));
}
@Test
void local_channel_not_found_as_end_node() {
mockEdge();
when(grpcGetInfo.getPubkey()).thenReturn(EDGE.startNode());
assertThat(edgeComputation.getEdges().edges())
.contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, Coins.NONE));
}
@Test
void reduces_liquidity_to_zero_for_offline_peer_as_end_node() {
mockEdge();
mockOfflinePeer();
when(grpcGetInfo.getPubkey()).thenReturn(EDGE.startNode());
assertThat(edgeComputation.getEdges().edges())
.contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, Coins.NONE));
verify(balanceService, never()).getAvailableLocalBalance(EDGE.channelId());
}
@Test
void adds_liquidity_information_for_local_channel_as_target() {
mockEdge();
@@ -103,6 +133,32 @@ class EdgeComputationTest {
.contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, knownLiquidity));
}
@Test
void local_channel_not_found_as_start_node() {
mockEdge();
when(grpcGetInfo.getPubkey()).thenReturn(EDGE.endNode());
assertThat(edgeComputation.getEdges().edges())
.contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, Coins.NONE));
}
@Test
void reduces_liquidity_to_zero_for_offline_peer_as_start_node() {
mockEdge();
mockOfflinePeer();
when(grpcGetInfo.getPubkey()).thenReturn(EDGE.endNode());
assertThat(edgeComputation.getEdges().edges())
.contains(EdgeWithLiquidityInformation.forKnownLiquidity(EDGE, Coins.NONE));
verify(balanceService, never()).getAvailableLocalBalance(EDGE.channelId());
}
private void mockOfflinePeer() {
Pubkey remotePubkey = LOCAL_OPEN_CHANNEL.getRemotePubkey();
when(nodeService.getNode(remotePubkey)).thenReturn(new Node(remotePubkey, "", 0, false));
when(channelService.getLocalChannel(EDGE.channelId())).thenReturn(Optional.of(LOCAL_OPEN_CHANNEL));
}
@Test
void adds_upper_bound_from_mission_control() {
mockEdge();