mirror of
https://github.com/aljazceru/lnd-manageJ.git
synced 2026-01-28 18:34:30 +01:00
compute fes for MPP/routes
This commit is contained in:
@@ -2,6 +2,7 @@ package de.cotto.lndmanagej.pickhardtpayments;
|
||||
|
||||
import de.cotto.lndmanagej.grpc.GrpcGetInfo;
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.Edge;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.Flow;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.Flows;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.MultiPathPayment;
|
||||
@@ -16,11 +17,15 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY;
|
||||
import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY_2;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2;
|
||||
import static de.cotto.lndmanagej.model.PolicyFixtures.POLICY_1;
|
||||
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_4;
|
||||
import static de.cotto.lndmanagej.pickhardtpayments.model.EdgeFixtures.EDGE;
|
||||
import static de.cotto.lndmanagej.pickhardtpayments.model.EdgeFixtures.EDGE_3_2;
|
||||
import static de.cotto.lndmanagej.pickhardtpayments.model.FlowFixtures.FLOW;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
@@ -63,8 +68,7 @@ class MultiPathPaymentSplitterTest {
|
||||
when(flowComputation.getOptimalFlows(PUBKEY, PUBKEY_2, AMOUNT)).thenReturn(new Flows(FLOW));
|
||||
when(grpcGetInfo.getPubkey()).thenReturn(PUBKEY);
|
||||
MultiPathPayment multiPathPayment = multiPathPaymentSplitter.getMultiPathPaymentTo(PUBKEY_2, AMOUNT);
|
||||
MultiPathPayment expected =
|
||||
new MultiPathPayment(AMOUNT, FLOW.getProbability(), Set.of(new Route(List.of(EDGE), AMOUNT)));
|
||||
MultiPathPayment expected = new MultiPathPayment(Set.of(new Route(List.of(EDGE), AMOUNT)));
|
||||
assertThat(multiPathPayment).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@@ -73,9 +77,10 @@ class MultiPathPaymentSplitterTest {
|
||||
long capacitySat = EDGE.capacity().satoshis();
|
||||
Coins halfOfCapacity = Coins.ofSatoshis(capacitySat / 2);
|
||||
Flow flow = new Flow(EDGE, halfOfCapacity);
|
||||
when(flowComputation.getOptimalFlows(PUBKEY, PUBKEY_2, AMOUNT)).thenReturn(new Flows(flow));
|
||||
when(flowComputation.getOptimalFlows(PUBKEY, PUBKEY_2, halfOfCapacity)).thenReturn(new Flows(flow));
|
||||
|
||||
MultiPathPayment multiPathPayment = multiPathPaymentSplitter.getMultiPathPayment(PUBKEY, PUBKEY_2, AMOUNT);
|
||||
MultiPathPayment multiPathPayment =
|
||||
multiPathPaymentSplitter.getMultiPathPayment(PUBKEY, PUBKEY_2, halfOfCapacity);
|
||||
|
||||
assertThat(multiPathPayment.probability())
|
||||
.isEqualTo((1.0 * halfOfCapacity.satoshis() + 1) / (capacitySat + 1));
|
||||
@@ -83,16 +88,18 @@ class MultiPathPaymentSplitterTest {
|
||||
|
||||
@Test
|
||||
void getMultiPathPayment_two_flows_probability() {
|
||||
long capacitySat = EDGE.capacity().satoshis();
|
||||
long capacitySat = CAPACITY.satoshis();
|
||||
Coins halfOfCapacity = Coins.ofSatoshis(capacitySat / 2);
|
||||
Flow flow1 = new Flow(EDGE, halfOfCapacity);
|
||||
Flow flow2 = new Flow(EDGE_3_2, EDGE_3_2.capacity());
|
||||
when(flowComputation.getOptimalFlows(PUBKEY, PUBKEY_2, AMOUNT)).thenReturn(new Flows(flow1, flow2));
|
||||
Flow flow1 = new Flow(new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, POLICY_1), halfOfCapacity);
|
||||
Flow flow2 = new Flow(new Edge(CHANNEL_ID_2, PUBKEY, PUBKEY_2, CAPACITY_2, POLICY_1), CAPACITY_2);
|
||||
Coins totalAmount = halfOfCapacity.add(CAPACITY_2);
|
||||
when(flowComputation.getOptimalFlows(PUBKEY, PUBKEY_2, totalAmount)).thenReturn(new Flows(flow1, flow2));
|
||||
|
||||
MultiPathPayment multiPathPayment = multiPathPaymentSplitter.getMultiPathPayment(PUBKEY, PUBKEY_2, AMOUNT);
|
||||
MultiPathPayment multiPathPayment =
|
||||
multiPathPaymentSplitter.getMultiPathPayment(PUBKEY, PUBKEY_2, totalAmount);
|
||||
|
||||
double probabilityFlow1 = (1.0 * halfOfCapacity.satoshis() + 1) / (capacitySat + 1);
|
||||
double probabilityFlow2 = 1.0 / (EDGE_3_2.capacity().satoshis() + 1);
|
||||
double probabilityFlow2 = 1.0 / (CAPACITY_2.satoshis() + 1);
|
||||
assertThat(multiPathPayment.probability()).isEqualTo(probabilityFlow1 * probabilityFlow2);
|
||||
}
|
||||
|
||||
@@ -102,9 +109,10 @@ class MultiPathPaymentSplitterTest {
|
||||
Coins halfOfCapacity = Coins.ofSatoshis(capacitySat / 2);
|
||||
Flow flow1 = new Flow(EDGE, halfOfCapacity);
|
||||
Flow flow2 = new Flow(EDGE, halfOfCapacity);
|
||||
when(flowComputation.getOptimalFlows(PUBKEY, PUBKEY_2, AMOUNT)).thenReturn(new Flows(flow1, flow2));
|
||||
when(flowComputation.getOptimalFlows(PUBKEY, PUBKEY_2, EDGE.capacity())).thenReturn(new Flows(flow1, flow2));
|
||||
|
||||
MultiPathPayment multiPathPayment = multiPathPaymentSplitter.getMultiPathPayment(PUBKEY, PUBKEY_2, AMOUNT);
|
||||
MultiPathPayment multiPathPayment =
|
||||
multiPathPaymentSplitter.getMultiPathPayment(PUBKEY, PUBKEY_2, EDGE.capacity());
|
||||
|
||||
assertThat(multiPathPayment.probability()).isEqualTo(1.0 / (capacitySat + 1));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.cotto.lndmanagej.pickhardtpayments.model;
|
||||
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.pickhardtpayments.model.MultiPathPaymentFixtures.MULTI_PATH_PAYMENT;
|
||||
@@ -21,4 +22,9 @@ class MultiPathPaymentTest {
|
||||
void routes() {
|
||||
assertThat(MULTI_PATH_PAYMENT.routes()).containsExactly(ROUTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void fees() {
|
||||
assertThat(MULTI_PATH_PAYMENT.fees()).isEqualTo(Coins.ofMilliSatoshis(20));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,26 @@
|
||||
package de.cotto.lndmanagej.pickhardtpayments.model;
|
||||
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import de.cotto.lndmanagej.model.Policy;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2;
|
||||
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;
|
||||
import static de.cotto.lndmanagej.pickhardtpayments.model.EdgeFixtures.EDGE;
|
||||
import static de.cotto.lndmanagej.pickhardtpayments.model.RouteFixtures.ROUTE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
class RouteTest {
|
||||
|
||||
private static final int ONE_MILLION = 1_000_000;
|
||||
|
||||
@Test
|
||||
void getProbability() {
|
||||
long capacitySat = EDGE.capacity().satoshis();
|
||||
@@ -18,6 +28,39 @@ class RouteTest {
|
||||
.isEqualTo(1.0 * (capacitySat + 1 - ROUTE.amount().satoshis()) / (capacitySat + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fees_amount_with_milli_sat() {
|
||||
Coins amount = Coins.ofMilliSatoshis(1_500_000_111);
|
||||
int ppm = 100;
|
||||
Coins baseFee = Coins.ofMilliSatoshis(10);
|
||||
Coins expectedFees =
|
||||
Coins.ofMilliSatoshis((long) (amount.milliSatoshis() * 1.0 * ppm / ONE_MILLION))
|
||||
.add(baseFee);
|
||||
Policy policy = new Policy(ppm, baseFee, true);
|
||||
assertThat(new Route(List.of(new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, policy)), amount).fees())
|
||||
.isEqualTo(expectedFees);
|
||||
}
|
||||
|
||||
@Test
|
||||
void fees_two_hops() {
|
||||
Coins amount = Coins.ofSatoshis(1_500_000);
|
||||
Coins baseFee1 = Coins.ofMilliSatoshis(10);
|
||||
Coins baseFee2 = Coins.ofMilliSatoshis(1);
|
||||
int ppm1 = 100;
|
||||
int ppm2 = 200;
|
||||
Coins expectedFees2 =
|
||||
Coins.ofMilliSatoshis((long) (amount.milliSatoshis() * 1.0 * ppm2 / ONE_MILLION))
|
||||
.add(baseFee2);
|
||||
Coins expectedFees1 =
|
||||
Coins.ofMilliSatoshis((long) (amount.add(expectedFees2).milliSatoshis() * 1.0 * ppm1 / ONE_MILLION))
|
||||
.add(baseFee1);
|
||||
Coins expectedFees = expectedFees1.add(expectedFees2);
|
||||
assertThat(new Route(List.of(
|
||||
new Edge(CHANNEL_ID, PUBKEY, PUBKEY_2, CAPACITY, new Policy(ppm1, baseFee1, true)),
|
||||
new Edge(CHANNEL_ID_2, PUBKEY_2, PUBKEY_3, CAPACITY, new Policy(ppm2, baseFee2, true))
|
||||
), amount).fees()).isEqualTo(expectedFees);
|
||||
}
|
||||
|
||||
@Test
|
||||
void zero_amount() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new Route(List.of(), Coins.NONE));
|
||||
|
||||
Reference in New Issue
Block a user