replace DirectedChannelEdge by Edge

This commit is contained in:
Carsten Otto
2024-10-31 17:01:46 +01:00
parent c20121bccf
commit 4833d5bac3
11 changed files with 112 additions and 199 deletions

View File

@@ -2,7 +2,7 @@ package de.cotto.lndmanagej.service;
import de.cotto.lndmanagej.grpc.GrpcGraph;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Edge;
import de.cotto.lndmanagej.model.Pubkey;
import de.cotto.lndmanagej.model.PubkeyAndFeeRate;
import org.springframework.stereotype.Service;
@@ -35,19 +35,19 @@ public class GraphService {
}
public List<PubkeyAndFeeRate> getNodesWithHighFeeRate() {
Set<DirectedChannelEdge> edges = grpcGraph.getChannelEdges().orElse(null);
Set<Edge> edges = grpcGraph.getChannelEdges().orElse(null);
if (edges == null) {
return List.of();
}
Map<Pubkey, Set<DirectedChannelEdge>> candidates = getCandidateEdges(edges);
Map<Pubkey, Set<Edge>> candidates = getCandidateEdges(edges);
return candidates.entrySet().parallelStream()
.map(this::withAverageFeeRate)
.sorted(Comparator.comparing(PubkeyAndFeeRate::feeRate).reversed())
.toList();
}
private Map<Pubkey, Set<DirectedChannelEdge>> getCandidateEdges(Set<DirectedChannelEdge> edges) {
Map<Pubkey, Set<DirectedChannelEdge>> candidates = edges.parallelStream()
private Map<Pubkey, Set<Edge>> getCandidateEdges(Set<Edge> edges) {
Map<Pubkey, Set<Edge>> candidates = edges.parallelStream()
.filter(e -> e.policy().enabled())
.filter(e -> e.policy().feeRate() <= MAX_FEE_RATE)
.filter(e -> e.policy().feeRate() > 0)
@@ -58,17 +58,17 @@ public class GraphService {
}
private void combine(
Map<Pubkey, Set<DirectedChannelEdge>> first,
Map<Pubkey, Set<DirectedChannelEdge>> second
Map<Pubkey, Set<Edge>> first,
Map<Pubkey, Set<Edge>> second
) {
for (Map.Entry<Pubkey, Set<DirectedChannelEdge>> entry : second.entrySet()) {
for (Map.Entry<Pubkey, Set<Edge>> entry : second.entrySet()) {
Pubkey pubkey = entry.getKey();
first.computeIfAbsent(pubkey, k -> new LinkedHashSet<>()).addAll(entry.getValue());
}
}
private void add(Map<Pubkey, Set<DirectedChannelEdge>> map, DirectedChannelEdge edge) {
map.compute(edge.target(), (p, s) -> {
private void add(Map<Pubkey, Set<Edge>> map, Edge edge) {
map.compute(edge.endNode(), (p, s) -> {
if (s == null) {
s = new LinkedHashSet<>();
}
@@ -77,7 +77,7 @@ public class GraphService {
});
}
private PubkeyAndFeeRate withAverageFeeRate(Map.Entry<Pubkey, Set<DirectedChannelEdge>> entry) {
private PubkeyAndFeeRate withAverageFeeRate(Map.Entry<Pubkey, Set<Edge>> entry) {
Pubkey pubkey = entry.getKey();
long feeRateSum = entry.getValue().stream().mapToLong(e -> e.policy().feeRate()).sum();
int average = (int) (feeRateSum / entry.getValue().size());

View File

@@ -3,7 +3,7 @@ package de.cotto.lndmanagej.service;
import de.cotto.lndmanagej.model.ChannelId;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DecodedPaymentRequest;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Edge;
import de.cotto.lndmanagej.model.Policy;
import de.cotto.lndmanagej.model.RouteHint;
import org.springframework.scheduling.annotation.Scheduled;
@@ -31,11 +31,11 @@ public class RouteHintService {
public void addDecodedPaymentRequest(DecodedPaymentRequest decodedPaymentRequest) {
decodedPaymentRequest.routeHints().stream()
.map(this::toDirectedChannelEdge)
.map(this::toEdge)
.forEach(edge -> edges.put(edge.channelId(), new EdgeWithInstant(edge)));
}
public Set<DirectedChannelEdge> getEdgesFromPaymentHints() {
public Set<Edge> getEdgesFromPaymentHints() {
return edges.values().stream().map(EdgeWithInstant::edge).collect(Collectors.toSet());
}
@@ -45,12 +45,12 @@ public class RouteHintService {
edges.values().removeIf(edgeWithInstant -> edgeWithInstant.instant().isBefore(cutoff));
}
private DirectedChannelEdge toDirectedChannelEdge(RouteHint routeHint) {
return new DirectedChannelEdge(
private Edge toEdge(RouteHint routeHint) {
return new Edge(
routeHint.channelId(),
FIFTY_COINS,
routeHint.sourceNode(),
routeHint.endNode(),
FIFTY_COINS,
toPolicy(routeHint),
Policy.UNKNOWN
);
@@ -68,8 +68,8 @@ public class RouteHintService {
}
@SuppressWarnings("UnusedVariable")
private record EdgeWithInstant(DirectedChannelEdge edge, Instant instant) {
private EdgeWithInstant(DirectedChannelEdge edge) {
private record EdgeWithInstant(Edge edge, Instant instant) {
private EdgeWithInstant(Edge edge) {
this(edge, Instant.now());
}
}

View File

@@ -2,7 +2,7 @@ package de.cotto.lndmanagej.service;
import de.cotto.lndmanagej.grpc.GrpcGraph;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Edge;
import de.cotto.lndmanagej.model.Policy;
import de.cotto.lndmanagej.model.Pubkey;
import de.cotto.lndmanagej.model.PubkeyAndFeeRate;
@@ -17,7 +17,7 @@ import java.util.Optional;
import java.util.Set;
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
import static de.cotto.lndmanagej.model.DirectedChannelEdgeFixtures.CHANNEL_EDGE_WITH_POLICY;
import static de.cotto.lndmanagej.model.EdgeFixtures.EDGE;
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2;
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3;
@@ -41,7 +41,7 @@ class GraphServiceTest {
@Test
void getNumberOfEdges() {
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(CHANNEL_EDGE_WITH_POLICY)));
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(EDGE)));
assertThat(graphService.getNumberOfChannels()).isEqualTo(1);
}
@@ -63,7 +63,7 @@ class GraphServiceTest {
@Test
void getNodesWithHighFeeRate_no_edge() {
Set<DirectedChannelEdge> edges = Set.of();
Set<Edge> edges = Set.of();
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(edges));
assertThat(graphService.getNodesWithHighFeeRate()).isEmpty();
}
@@ -76,7 +76,7 @@ class GraphServiceTest {
@Test
void getNodesWithHighFeeRate_ignores_disabled_channels() {
Set<DirectedChannelEdge> edges = edges(9, 200, PUBKEY_2);
Set<Edge> edges = edges(9, 200, PUBKEY_2);
Policy policy = new Policy(2_000, Coins.NONE, false, 40, Coins.ofMilliSatoshis(1), Coins.ofSatoshis(10_000));
edges.add(edge(policy, Coins.ofSatoshis(10_000_000), PUBKEY_2));
assertThat(graphService.getNodesWithHighFeeRate()).isEmpty();
@@ -84,21 +84,21 @@ class GraphServiceTest {
@Test
void getNodesWithHighFeeRate_ignores_absurd_fee_rates() {
Set<DirectedChannelEdge> edges = edges(9, 200, PUBKEY_2);
Set<Edge> edges = edges(9, 200, PUBKEY_2);
edges.add(edge(20_000, 20, PUBKEY_2));
assertThat(graphService.getNodesWithHighFeeRate()).isEmpty();
}
@Test
void getNodesWithHighFeeRate_ignores_zero_fee_rate() {
Set<DirectedChannelEdge> edges = edges(9, 200, PUBKEY_2);
Set<Edge> edges = edges(9, 200, PUBKEY_2);
edges.add(edge(0, 20, PUBKEY_2));
assertThat(graphService.getNodesWithHighFeeRate()).isEmpty();
}
@Test
void getNodesWithHighFeeRate_ignores_low_capacity_channels() {
Set<DirectedChannelEdge> edges = edges(9, 200, PUBKEY_2);
Set<Edge> edges = edges(9, 200, PUBKEY_2);
edges.add(edge(200, 9, PUBKEY_2));
assertThat(graphService.getNodesWithHighFeeRate()).isEmpty();
}
@@ -113,7 +113,7 @@ class GraphServiceTest {
@Test
void getNodesWithHighFeeRate_average() {
Set<DirectedChannelEdge> edges = new LinkedHashSet<>();
Set<Edge> edges = new LinkedHashSet<>();
for (int i = 0; i < 10; i++) {
edges.add(edge(300 + i * 10, 20, PUBKEY_4));
edges.add(edge(200, 20 + i, PUBKEY_3));
@@ -125,8 +125,8 @@ class GraphServiceTest {
);
}
private Set<DirectedChannelEdge> edges(int count, int feeRate, Pubkey target) {
Set<DirectedChannelEdge> edges = new LinkedHashSet<>();
private Set<Edge> edges(int count, int feeRate, Pubkey target) {
Set<Edge> edges = new LinkedHashSet<>();
for (int i = 0; i < count; i++) {
edges.add(edge(feeRate, 20 + i, target));
}
@@ -134,18 +134,18 @@ class GraphServiceTest {
return edges;
}
private DirectedChannelEdge edge(long feeRate, long capacityMillionSat, Pubkey target) {
private Edge edge(long feeRate, long capacityMillionSat, Pubkey target) {
Policy policy = new Policy(feeRate, Coins.NONE, true, 40, Coins.ofMilliSatoshis(1), Coins.ofSatoshis(10_000));
Coins capacity = Coins.ofSatoshis(capacityMillionSat * 1_000_000);
return edge(policy, capacity, target);
}
private DirectedChannelEdge edge(Policy policy, Coins capacity, Pubkey target) {
return new DirectedChannelEdge(
private Edge edge(Policy policy, Coins capacity, Pubkey target) {
return new Edge(
CHANNEL_ID,
capacity,
PUBKEY,
target,
capacity,
policy,
Policy.UNKNOWN
);

View File

@@ -2,7 +2,7 @@ package de.cotto.lndmanagej.service;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DecodedPaymentRequest;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Edge;
import de.cotto.lndmanagej.model.Policy;
import de.cotto.lndmanagej.model.RouteHint;
import org.junit.jupiter.api.Test;
@@ -39,10 +39,10 @@ class RouteHintServiceTest {
routeHintService.addDecodedPaymentRequest(DECODED_PAYMENT_REQUEST);
Policy policy1 = new Policy(123, Coins.NONE, true, 9, ONE_MILLI_SATOSHI, FIFTY_COINS);
Policy policy2 = new Policy(1234, ONE_MILLI_SATOSHI, true, 40, ONE_MILLI_SATOSHI, FIFTY_COINS);
DirectedChannelEdge edge1 =
new DirectedChannelEdge(CHANNEL_ID, FIFTY_COINS, PUBKEY, PUBKEY_4, policy1, Policy.UNKNOWN);
DirectedChannelEdge edge2 =
new DirectedChannelEdge(CHANNEL_ID_2, FIFTY_COINS, PUBKEY_3, PUBKEY_4, policy2, Policy.UNKNOWN);
Edge edge1 =
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_4, FIFTY_COINS, policy1, Policy.UNKNOWN);
Edge edge2 =
new Edge(CHANNEL_ID_2, PUBKEY_3, PUBKEY_4, FIFTY_COINS, policy2, Policy.UNKNOWN);
assertThat(routeHintService.getEdgesFromPaymentHints()).contains(edge1, edge2);
}

View File

@@ -4,7 +4,7 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
import de.cotto.lndmanagej.caching.CacheBuilder;
import de.cotto.lndmanagej.model.ChannelId;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Edge;
import de.cotto.lndmanagej.model.Policy;
import de.cotto.lndmanagej.model.Pubkey;
import lnrpc.ChannelEdge;
@@ -20,7 +20,7 @@ import java.util.Set;
public class GrpcGraph {
private static final Policy DEFAULT_DISABLED_POLICY = new Policy(0, Coins.NONE, false, 0, Coins.NONE, Coins.NONE);
private final GrpcService grpcService;
private final LoadingCache<Object, Optional<Set<DirectedChannelEdge>>> channelEdgeCache;
private final LoadingCache<Object, Optional<Set<Edge>>> channelEdgeCache;
private final GrpcPolicy grpcPolicy;
public GrpcGraph(GrpcService grpcService, GrpcPolicy grpcPolicy) {
@@ -33,7 +33,7 @@ public class GrpcGraph {
.build(this::getChannelEdgesWithoutCache);
}
public Optional<Set<DirectedChannelEdge>> getChannelEdges() {
public Optional<Set<Edge>> getChannelEdges() {
return channelEdgeCache.get("");
}
@@ -41,12 +41,12 @@ public class GrpcGraph {
channelEdgeCache.invalidateAll();
}
private Optional<Set<DirectedChannelEdge>> getChannelEdgesWithoutCache() {
private Optional<Set<Edge>> getChannelEdgesWithoutCache() {
ChannelGraph channelGraph = grpcService.describeGraph().orElse(null);
if (channelGraph == null) {
return Optional.empty();
}
Set<DirectedChannelEdge> channelEdges = new LinkedHashSet<>();
Set<Edge> channelEdges = new LinkedHashSet<>();
for (ChannelEdge channelEdge : channelGraph.getEdgesList()) {
ChannelId channelId = ChannelId.fromShortChannelId(channelEdge.getChannelId());
Coins capacity = Coins.ofSatoshis(channelEdge.getCapacity());
@@ -54,24 +54,24 @@ public class GrpcGraph {
Pubkey node2Pubkey = Pubkey.create(channelEdge.getNode2Pub());
Policy node1Policy = getNode1Policy(channelEdge);
Policy node2Policy = getNode2Policy(channelEdge);
DirectedChannelEdge directedChannelEdge1 = new DirectedChannelEdge(
Edge edge1 = new Edge(
channelId,
capacity,
node1Pubkey,
node2Pubkey,
capacity,
node1Policy,
node2Policy
);
DirectedChannelEdge directedChannelEdge2 = new DirectedChannelEdge(
Edge edge2 = new Edge(
channelId,
capacity,
node2Pubkey,
node1Pubkey,
capacity,
node2Policy,
node1Policy
);
channelEdges.add(directedChannelEdge1);
channelEdges.add(directedChannelEdge2);
channelEdges.add(edge1);
channelEdges.add(edge2);
}
return Optional.of(channelEdges);
}

View File

@@ -1,7 +1,7 @@
package de.cotto.lndmanagej.grpc;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Edge;
import de.cotto.lndmanagej.model.Policy;
import lnrpc.ChannelEdge;
import lnrpc.ChannelGraph;
@@ -74,19 +74,19 @@ class GrpcGraphTest {
.build();
Policy policy1 = new Policy(0, Coins.NONE, false, 40, MIN_HTLC, MAX_HTLC);
Policy policy2 = new Policy(1, Coins.NONE, true, 144, MIN_HTLC, MAX_HTLC);
DirectedChannelEdge expectedEdge1 = new DirectedChannelEdge(
Edge expectedEdge1 = new Edge(
CHANNEL_ID,
CAPACITY,
PUBKEY,
PUBKEY_2,
CAPACITY,
policy1,
policy2
);
DirectedChannelEdge expectedEdge2 = new DirectedChannelEdge(
Edge expectedEdge2 = new Edge(
CHANNEL_ID,
CAPACITY,
PUBKEY_2,
PUBKEY,
CAPACITY,
policy2,
policy1
);
@@ -100,19 +100,19 @@ class GrpcGraphTest {
.build();
Policy policy3 = new Policy(456, Coins.NONE, true, 123, MIN_HTLC, MAX_HTLC);
Policy policy4 = new Policy(123, Coins.ofMilliSatoshis(1), true, 456, MIN_HTLC, MAX_HTLC);
DirectedChannelEdge expectedEdge3 = new DirectedChannelEdge(
Edge expectedEdge3 = new Edge(
CHANNEL_ID_2,
CAPACITY_2,
PUBKEY_3,
PUBKEY_4,
CAPACITY_2,
policy3,
policy4
);
DirectedChannelEdge expectedEdge4 = new DirectedChannelEdge(
Edge expectedEdge4 = new Edge(
CHANNEL_ID_2,
CAPACITY_2,
PUBKEY_4,
PUBKEY_3,
CAPACITY_2,
policy4,
policy3
);
@@ -134,19 +134,19 @@ class GrpcGraphTest {
.setNode1Pub(PUBKEY.toString())
.setNode2Pub(PUBKEY_2.toString())
.build();
DirectedChannelEdge expectedPolicyForNode1 = new DirectedChannelEdge(
Edge expectedPolicyForNode1 = new Edge(
CHANNEL_ID,
CAPACITY,
PUBKEY,
PUBKEY_2,
CAPACITY,
Policy.UNKNOWN,
Policy.UNKNOWN
);
DirectedChannelEdge expectedPolicyForNode2 = new DirectedChannelEdge(
Edge expectedPolicyForNode2 = new Edge(
CHANNEL_ID,
CAPACITY,
PUBKEY_2,
PUBKEY,
CAPACITY,
Policy.UNKNOWN,
Policy.UNKNOWN
);

View File

@@ -1,11 +0,0 @@
package de.cotto.lndmanagej.model;
public record DirectedChannelEdge(
ChannelId channelId,
Coins capacity,
Pubkey source,
Pubkey target,
Policy policy,
Policy reversePolicy
) {
}

View File

@@ -1,44 +0,0 @@
package de.cotto.lndmanagej.model;
import org.junit.jupiter.api.Test;
import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY;
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
import static de.cotto.lndmanagej.model.DirectedChannelEdgeFixtures.CHANNEL_EDGE_WITH_POLICY;
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_1;
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_2;
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2;
import static org.assertj.core.api.Assertions.assertThat;
class DirectedChannelEdgeTest {
@Test
void channelId() {
assertThat(CHANNEL_EDGE_WITH_POLICY.channelId()).isEqualTo(CHANNEL_ID);
}
@Test
void capacity() {
assertThat(CHANNEL_EDGE_WITH_POLICY.capacity()).isEqualTo(CAPACITY);
}
@Test
void source() {
assertThat(CHANNEL_EDGE_WITH_POLICY.source()).isEqualTo(PUBKEY);
}
@Test
void target() {
assertThat(CHANNEL_EDGE_WITH_POLICY.target()).isEqualTo(PUBKEY_2);
}
@Test
void policy() {
assertThat(CHANNEL_EDGE_WITH_POLICY.policy()).isEqualTo(POLICY_1);
}
@Test
void reversePolicy() {
assertThat(CHANNEL_EDGE_WITH_POLICY.reversePolicy()).isEqualTo(POLICY_2);
}
}

View File

@@ -1,19 +0,0 @@
package de.cotto.lndmanagej.model;
import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY;
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_1;
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_2;
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2;
public class DirectedChannelEdgeFixtures {
public static final DirectedChannelEdge CHANNEL_EDGE_WITH_POLICY = new DirectedChannelEdge(
CHANNEL_ID,
CAPACITY,
PUBKEY,
PUBKEY_2,
POLICY_1,
POLICY_2
);
}

View File

@@ -6,7 +6,6 @@ import de.cotto.lndmanagej.grpc.GrpcGraph;
import de.cotto.lndmanagej.grpc.middleware.GrpcMiddlewareService;
import de.cotto.lndmanagej.model.ChannelId;
import de.cotto.lndmanagej.model.Coins;
import de.cotto.lndmanagej.model.DirectedChannelEdge;
import de.cotto.lndmanagej.model.Edge;
import de.cotto.lndmanagej.model.EdgeWithLiquidityInformation;
import de.cotto.lndmanagej.model.LocalOpenChannel;
@@ -63,30 +62,19 @@ public class EdgeComputation {
logger.error("Middleware needs to be connected, see requirements section in PickhardtPayments.md");
return EdgesWithLiquidityInformation.EMPTY;
}
Set<DirectedChannelEdge> channelEdges = grpcGraph.getChannelEdges().orElse(null);
Set<Edge> channelEdges = grpcGraph.getChannelEdges().orElse(null);
if (channelEdges == null) {
logger.error("Unable to get graph");
return EdgesWithLiquidityInformation.EMPTY;
}
Set<EdgeWithLiquidityInformation> edgesWithLiquidityInformation = new LinkedHashSet<>();
Pubkey ownPubkey = grpcGetInfo.getPubkey();
Set<DirectedChannelEdge> edgesFromPaymentHints = routeHintService.getEdgesFromPaymentHints();
for (DirectedChannelEdge channelEdge : Sets.union(channelEdges, edgesFromPaymentHints)) {
if (shouldIgnore(channelEdge, paymentOptions, ownPubkey, maximumTimeLockDeltaPerEdge)) {
Set<Edge> edgesFromPaymentHints = routeHintService.getEdgesFromPaymentHints();
for (Edge edge : Sets.union(channelEdges, edgesFromPaymentHints)) {
if (shouldIgnore(edge, paymentOptions, ownPubkey, maximumTimeLockDeltaPerEdge)) {
continue;
}
ChannelId channelId = channelEdge.channelId();
Pubkey pubkey1 = channelEdge.source();
Pubkey pubkey2 = channelEdge.target();
Edge edge = new Edge(
channelId,
pubkey1,
pubkey2,
channelEdge.capacity(),
channelEdge.policy(),
channelEdge.reversePolicy()
);
if (edgesFromPaymentHints.contains(channelEdge)) {
if (edgesFromPaymentHints.contains(edge)) {
edgesWithLiquidityInformation.add(
EdgeWithLiquidityInformation.forLowerAndUpperBound(edge, edge.capacity(), edge.capacity())
);
@@ -115,7 +103,7 @@ public class EdgeComputation {
@SuppressWarnings("PMD.SimplifyBooleanReturns")
private boolean shouldIgnore(
DirectedChannelEdge channelEdge,
Edge channelEdge,
PaymentOptions paymentOptions,
Pubkey pubkey,
int maximumTimeLockDeltaPerEdge
@@ -133,7 +121,7 @@ public class EdgeComputation {
}
long feeRate = policy.feeRate();
boolean hopIsRelevantForFeeCheck =
!pubkey.equals(channelEdge.source()) || !paymentOptions.ignoreFeesForOwnChannels();
!pubkey.equals(channelEdge.startNode()) || !paymentOptions.ignoreFeesForOwnChannels();
if (feeRate >= feeRateLimit && hopIsRelevantForFeeCheck) {
return true;
}
@@ -152,16 +140,16 @@ public class EdgeComputation {
@SuppressWarnings("PMD.SimplifyBooleanReturns")
private boolean isEdgeToUnwantedFirstHop(
DirectedChannelEdge channelEdge,
Edge channelEdge,
PaymentOptions paymentOptions,
Pubkey pubkey
) {
boolean isOutgoingEdge = pubkey.equals(channelEdge.source());
boolean isOutgoingEdge = pubkey.equals(channelEdge.startNode());
if (!isOutgoingEdge) {
return false;
}
Pubkey peerForFirstHop = paymentOptions.peerForFirstHop().orElse(null);
boolean firstHopIsUnexpected = peerForFirstHop != null && !peerForFirstHop.equals(channelEdge.target());
boolean firstHopIsUnexpected = peerForFirstHop != null && !peerForFirstHop.equals(channelEdge.endNode());
if (firstHopIsUnexpected) {
return true;
}
@@ -169,11 +157,11 @@ public class EdgeComputation {
if (peerForLastHop == null) {
return false;
}
return peerForLastHop.equals(channelEdge.target());
return peerForLastHop.equals(channelEdge.endNode());
}
private boolean isIncomingEdge(DirectedChannelEdge channelEdge, Pubkey ownPubkey) {
return ownPubkey.equals(channelEdge.target());
private boolean isIncomingEdge(Edge channelEdge, Pubkey ownPubkey) {
return ownPubkey.equals(channelEdge.endNode());
}
private Optional<Coins> getKnownLiquidity(Edge edge, Pubkey ownPubKey) {

View File

@@ -6,7 +6,6 @@ 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;
import de.cotto.lndmanagej.model.EdgeWithLiquidityInformation;
import de.cotto.lndmanagej.model.LocalOpenChannel;
@@ -112,8 +111,8 @@ class EdgeComputationTest {
@Test
void does_not_add_edge_for_disabled_channel() {
DirectedChannelEdge edge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY, PUBKEY_2, POLICY_DISABLED, Policy.UNKNOWN);
Edge edge =
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, POLICY_DISABLED, Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edge)));
assertThat(edgeComputation.getEdges(DEFAULT_PAYMENT_OPTIONS, MAX_TIME_LOCK_DELTA).edges()).isEmpty();
}
@@ -124,8 +123,8 @@ class EdgeComputationTest {
int maximumTimeLockDelta = edgeDelta - 1;
Policy policy =
new Policy(0, Coins.NONE, true, edgeDelta, Coins.ofMilliSatoshis(1), Coins.ofSatoshis(10_000));
DirectedChannelEdge edge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY, PUBKEY_2, policy, Policy.UNKNOWN);
Edge edge =
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, policy, Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edge)));
assertThat(edgeComputation.getEdges(DEFAULT_PAYMENT_OPTIONS, maximumTimeLockDelta).edges()).isEmpty();
}
@@ -138,12 +137,12 @@ class EdgeComputationTest {
// needs to be excluded to avoid sending top-up payments in a tiny loop: S-X-S
Policy policyAtLimit = policy(199);
Policy policyOk = policy(198);
DirectedChannelEdge edgeExpensive =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY, PUBKEY_2, policyExpensive, Policy.UNKNOWN);
DirectedChannelEdge edgeAtLimit =
new DirectedChannelEdge(CHANNEL_ID_2, CAPACITY, PUBKEY, PUBKEY_2, policyAtLimit, Policy.UNKNOWN);
DirectedChannelEdge edgeOk =
new DirectedChannelEdge(CHANNEL_ID_3, CAPACITY, PUBKEY, PUBKEY_2, policyOk, Policy.UNKNOWN);
Edge edgeExpensive =
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, policyExpensive, Policy.UNKNOWN);
Edge edgeAtLimit =
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, policyAtLimit, Policy.UNKNOWN);
Edge edgeOk =
new Edge(CHANNEL_ID_3, PUBKEY, PUBKEY_2, CAPACITY, policyOk, Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edgeExpensive, edgeAtLimit, edgeOk)));
assertThat(
edgeComputation.getEdges(paymentOptions, MAX_TIME_LOCK_DELTA).edges().stream()
@@ -155,8 +154,8 @@ class EdgeComputationTest {
void adds_edge_with_fee_rate_at_limit_if_first_hop_and_fee_is_ignored() {
int feeRateLimit = 1000;
PaymentOptions paymentOptions = PaymentOptions.forFeeRateLimit(feeRateLimit);
DirectedChannelEdge edge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY_4, PUBKEY_2, policy(feeRateLimit), Policy.UNKNOWN);
Edge edge =
new Edge(CHANNEL_ID, PUBKEY_4, PUBKEY_2, CAPACITY, policy(feeRateLimit), Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edge)));
assertThat(edgeComputation.getEdges(paymentOptions, MAX_TIME_LOCK_DELTA).edges()).isNotEmpty();
}
@@ -172,8 +171,8 @@ class EdgeComputationTest {
Optional.empty(),
Optional.empty()
);
DirectedChannelEdge edge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY_4, PUBKEY, policy(feeRateLimit), Policy.UNKNOWN);
Edge edge =
new Edge(CHANNEL_ID, PUBKEY_4, PUBKEY, CAPACITY, policy(feeRateLimit), Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edge)));
assertThat(edgeComputation.getEdges(paymentOptions, MAX_TIME_LOCK_DELTA).edges()).isEmpty();
}
@@ -191,27 +190,27 @@ class EdgeComputationTest {
Policy lastHopPolicy = policy(199);
Policy firstHopPolicyExpensive = policy(100);
Policy firstHopPolicyOk = policy(99);
DirectedChannelEdge lastHop = new DirectedChannelEdge(
Edge lastHop = new Edge(
CHANNEL_ID,
CAPACITY,
topUpPeer,
ownPubkey,
CAPACITY,
lastHopPolicy,
Policy.UNKNOWN
);
DirectedChannelEdge firstHopExpensive = new DirectedChannelEdge(
Edge firstHopExpensive = new Edge(
CHANNEL_ID_2,
CAPACITY,
ownPubkey,
PUBKEY_2,
CAPACITY,
firstHopPolicyExpensive,
Policy.UNKNOWN
);
DirectedChannelEdge firstHopOk = new DirectedChannelEdge(
Edge firstHopOk = new Edge(
CHANNEL_ID_3,
CAPACITY,
ownPubkey,
PUBKEY_2,
CAPACITY,
firstHopPolicyOk,
Policy.UNKNOWN
);
@@ -230,11 +229,11 @@ class EdgeComputationTest {
when(grpcGetInfo.getPubkey()).thenReturn(ownPubkey);
PaymentOptions paymentOptions = PaymentOptions.forFeeRateLimit(feeRateLimit);
Policy firstHopPolicyExpensive = policy(100);
DirectedChannelEdge firstHopExpensiveButOk = new DirectedChannelEdge(
Edge firstHopExpensiveButOk = new Edge(
CHANNEL_ID_2,
CAPACITY,
ownPubkey,
PUBKEY_2,
CAPACITY,
firstHopPolicyExpensive,
Policy.UNKNOWN
);
@@ -247,8 +246,8 @@ class EdgeComputationTest {
@Test
void adds_edge_for_channel_with_base_fee() {
DirectedChannelEdge edge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY, PUBKEY_2, POLICY_WITH_BASE_FEE, Policy.UNKNOWN);
Edge edge =
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, POLICY_WITH_BASE_FEE, Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edge)));
assertThat(edgeComputation.getEdges(DEFAULT_PAYMENT_OPTIONS, MAX_TIME_LOCK_DELTA).edges()).isNotEmpty();
}
@@ -291,11 +290,11 @@ class EdgeComputationTest {
Policy policy = new Policy(200, Coins.NONE, true, 40, oneMilliSatoshi, fiftyCoins);
Edge edge = new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, fiftyCoins, policy, Policy.UNKNOWN);
when(routeHintService.getEdgesFromPaymentHints()).thenReturn(Set.of(
new DirectedChannelEdge(
new Edge(
edge.channelId(),
edge.capacity(),
edge.startNode(),
edge.endNode(),
edge.capacity(),
edge.policy(),
edge.reversePolicy()
)
@@ -379,10 +378,10 @@ class EdgeComputationTest {
Pubkey ownNode = PUBKEY_4;
Pubkey peerForFirstHop = PUBKEY_3;
DirectedChannelEdge edgeToFirstHop =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, ownNode, peerForFirstHop, POLICY_1, Policy.UNKNOWN);
DirectedChannelEdge otherEdge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, ownNode, PUBKEY, POLICY_1, Policy.UNKNOWN);
Edge edgeToFirstHop =
new Edge(CHANNEL_ID, ownNode, peerForFirstHop, CAPACITY, POLICY_1, Policy.UNKNOWN);
Edge otherEdge =
new Edge(CHANNEL_ID, ownNode, PUBKEY, CAPACITY, POLICY_1, Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edgeToFirstHop, otherEdge)));
PaymentOptions paymentOptions =
@@ -397,10 +396,10 @@ class EdgeComputationTest {
Pubkey ownNode = PUBKEY_4;
Pubkey lastHopNode = PUBKEY_2;
DirectedChannelEdge edgeToLastHop =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, ownNode, lastHopNode, POLICY_1, Policy.UNKNOWN);
DirectedChannelEdge otherEdge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, ownNode, PUBKEY, POLICY_1, Policy.UNKNOWN);
Edge edgeToLastHop =
new Edge(CHANNEL_ID, ownNode, lastHopNode, CAPACITY, POLICY_1, Policy.UNKNOWN);
Edge otherEdge =
new Edge(CHANNEL_ID, ownNode, PUBKEY, CAPACITY, POLICY_1, Policy.UNKNOWN);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edgeToLastHop, otherEdge)));
PaymentOptions paymentOptions =
@@ -504,8 +503,8 @@ class EdgeComputationTest {
}
private void mockEdge() {
DirectedChannelEdge edge =
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY, PUBKEY_2, POLICY_1, POLICY_2);
Edge edge =
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, POLICY_1, POLICY_2);
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edge)));
}