mirror of
https://github.com/aljazceru/lnd-manageJ.git
synced 2026-01-21 06:54:29 +01:00
allow channels with non-zero base fee
Note that this is an over-approximation. In the routing cost computation it is assumed that the base fee is paid not just once per payment, but possibly several times. As an example, with a base fee of 2sat and a quantization of 10,000sat (which is the current default), the assumed fee rate is the original fee rate plus 200ppm (2sat * 1,000,000 / 10,000). fixes #31
This commit is contained in:
@@ -91,7 +91,8 @@ class ArcInitializer {
|
||||
if (ownPubkey.equals(edge.startNode())) {
|
||||
return 0;
|
||||
}
|
||||
return edge.policy().feeRate();
|
||||
long fromBaseFee = (long) Math.ceil(1.0 * 1_000 / quantization * edge.policy().baseFee().milliSatoshis());
|
||||
return edge.policy().feeRate() + fromBaseFee;
|
||||
}
|
||||
|
||||
private long quantize(Coins coins) {
|
||||
|
||||
@@ -9,7 +9,6 @@ import de.cotto.lndmanagej.model.DirectedChannelEdge;
|
||||
import de.cotto.lndmanagej.model.Edge;
|
||||
import de.cotto.lndmanagej.model.EdgeWithLiquidityInformation;
|
||||
import de.cotto.lndmanagej.model.LocalChannel;
|
||||
import de.cotto.lndmanagej.model.Policy;
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.EdgesWithLiquidityInformation;
|
||||
import de.cotto.lndmanagej.service.BalanceService;
|
||||
@@ -106,8 +105,7 @@ public class EdgeComputation {
|
||||
}
|
||||
|
||||
private boolean shouldIgnore(DirectedChannelEdge channelEdge) {
|
||||
Policy policy = channelEdge.policy();
|
||||
return policy.disabled() || policy.baseFee().isPositive();
|
||||
return channelEdge.policy().disabled();
|
||||
}
|
||||
|
||||
private Optional<Coins> getKnownLiquidity(Edge edge, Pubkey ownPubKey) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.google.ortools.graph.MinCostFlow;
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import de.cotto.lndmanagej.model.Edge;
|
||||
import de.cotto.lndmanagej.model.EdgeWithLiquidityInformation;
|
||||
import de.cotto.lndmanagej.model.Policy;
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.EdgesWithLiquidityInformation;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.IntegerMapping;
|
||||
@@ -13,6 +14,8 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
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.EdgeFixtures.EDGE;
|
||||
import static de.cotto.lndmanagej.model.EdgeFixtures.EDGE_1_3;
|
||||
import static de.cotto.lndmanagej.model.EdgeFixtures.EDGE_2_3;
|
||||
@@ -206,17 +209,56 @@ class ArcInitializerTest {
|
||||
@Test
|
||||
void adds_fee_rate_as_cost() {
|
||||
int feeRateWeight = 1;
|
||||
ArcInitializer arcInitializer = new ArcInitializer(
|
||||
ArcInitializer arcInitializer = getArcInitializer(QUANTIZATION, feeRateWeight);
|
||||
arcInitializer.addArcs(new EdgesWithLiquidityInformation(edgeWithLiquidityInformation));
|
||||
assertThat(minCostFlow.getUnitCost(0)).isEqualTo(200);
|
||||
}
|
||||
|
||||
@Test
|
||||
void includes_base_fee_in_assumed_fee_rate() {
|
||||
Coins baseFee = Coins.ofMilliSatoshis(100);
|
||||
|
||||
int feeRateWeight = 1;
|
||||
int quantization = 10_000;
|
||||
ArcInitializer arcInitializer = getArcInitializer(quantization, feeRateWeight);
|
||||
addEdgeWithBaseFee(baseFee, quantization, arcInitializer);
|
||||
|
||||
long expectedFeeRate = (long) Math.ceil(200 + 10);
|
||||
assertThat(minCostFlow.getUnitCost(0)).isEqualTo(expectedFeeRate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void includes_base_fee_in_assumed_fee_rate_rounds_up() {
|
||||
Coins baseFee = Coins.ofMilliSatoshis(111);
|
||||
|
||||
int feeRateWeight = 1;
|
||||
int quantization = 10_000;
|
||||
ArcInitializer arcInitializer = getArcInitializer(quantization, feeRateWeight);
|
||||
addEdgeWithBaseFee(baseFee, quantization, arcInitializer);
|
||||
|
||||
long expectedFeeRate = (long) Math.ceil(200 + 12);
|
||||
assertThat(minCostFlow.getUnitCost(0)).isEqualTo(expectedFeeRate);
|
||||
}
|
||||
|
||||
private void addEdgeWithBaseFee(Coins baseFee, int quantization, ArcInitializer arcInitializer) {
|
||||
Policy policy = new Policy(200, baseFee, true, 40, Coins.ofSatoshis(10_000));
|
||||
EdgeWithLiquidityInformation edge = EdgeWithLiquidityInformation.forKnownLiquidity(
|
||||
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, policy),
|
||||
Coins.ofSatoshis(30L * quantization)
|
||||
);
|
||||
arcInitializer.addArcs(new EdgesWithLiquidityInformation(edge));
|
||||
}
|
||||
|
||||
private ArcInitializer getArcInitializer(int quantization, int feeRateWeight) {
|
||||
return new ArcInitializer(
|
||||
minCostFlow,
|
||||
integerMapping,
|
||||
edgeMapping,
|
||||
QUANTIZATION,
|
||||
quantization,
|
||||
PIECEWISE_LINEAR_APPROXIMATIONS,
|
||||
feeRateWeight,
|
||||
PUBKEY_2
|
||||
);
|
||||
arcInitializer.addArcs(new EdgesWithLiquidityInformation(edgeWithLiquidityInformation));
|
||||
assertThat(minCostFlow.getUnitCost(0)).isEqualTo(200);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,11 +88,11 @@ class EdgeComputationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void does_not_add_edge_for_channel_with_base_fee() {
|
||||
void adds_edge_for_channel_with_base_fee() {
|
||||
DirectedChannelEdge edge =
|
||||
new DirectedChannelEdge(CHANNEL_ID, CAPACITY, PUBKEY, PUBKEY_2, POLICY_WITH_BASE_FEE);
|
||||
when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(edge)));
|
||||
assertThat(edgeComputation.getEdges().edges()).isEmpty();
|
||||
assertThat(edgeComputation.getEdges().edges()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user