get nodes with high incoming fee rate

This commit is contained in:
Carsten Otto
2022-06-18 19:10:52 +02:00
parent 1dd7aeb7e7
commit 91fd885416
10 changed files with 289 additions and 0 deletions

View File

@@ -1,12 +1,25 @@
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.Pubkey;
import de.cotto.lndmanagej.model.PubkeyAndFeeRate;
import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service
public class GraphService {
private static final Coins MIN_CAPACITY = Coins.ofSatoshis(10_000_000);
private static final long MAX_FEE_RATE = 5_000;
private static final int MIN_EDGES = 10;
private final GrpcGraph grpcGraph;
public GraphService(GrpcGraph grpcGraph) {
@@ -20,4 +33,55 @@ public class GraphService {
public void resetCache() {
grpcGraph.resetCache();
}
public List<PubkeyAndFeeRate> getNodesWithHighFeeRate() {
Set<DirectedChannelEdge> edges = grpcGraph.getChannelEdges().orElse(null);
if (edges == null) {
return List.of();
}
Map<Pubkey, Set<DirectedChannelEdge>> 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()
.filter(e -> e.policy().enabled())
.filter(e -> e.policy().feeRate() <= MAX_FEE_RATE)
.filter(e -> e.policy().feeRate() > 0)
.filter(e -> MIN_CAPACITY.compareTo(e.capacity()) <= 0)
.collect(LinkedHashMap::new, this::add, this::combine);
candidates.values().removeIf(s -> s.size() < MIN_EDGES);
return candidates;
}
private void combine(
Map<Pubkey, Set<DirectedChannelEdge>> first,
Map<Pubkey, Set<DirectedChannelEdge>> second
) {
for (Map.Entry<Pubkey, Set<DirectedChannelEdge>> 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) -> {
if (s == null) {
s = new LinkedHashSet<>();
}
s.add(edge);
return s;
});
}
private PubkeyAndFeeRate withAverageFeeRate(Map.Entry<Pubkey, Set<DirectedChannelEdge>> entry) {
Pubkey pubkey = entry.getKey();
long feeRateSum = entry.getValue().stream().mapToLong(e -> e.policy().feeRate()).sum();
int average = (int) (feeRateSum / entry.getValue().size());
return new PubkeyAndFeeRate(pubkey, average);
}
}