@@ -905,7 +905,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
905905 makeEdge(4L , a, b, 100 msat, 20 , minHtlc = 1 msat, balance_opt = Some (16000 msat)),
906906 )), 1 day)
907907 // We set max-parts to 3, but it should be ignored when sending to a direct neighbor.
908- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 3 ))
908+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 3 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
909909
910910 {
911911 val Success (routes) = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
@@ -921,7 +921,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
921921 }
922922 {
923923 // We set min-part-amount to a value that excludes channels 1 and 4.
924- val failure = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams.copy(mpp = MultiPartParams (16500 msat, 3 )), currentBlockHeight = BlockHeight (400000 ))
924+ val failure = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams.copy(mpp = MultiPartParams (16500 msat, 3 , routeParams.mpp.splittingStrategy )), currentBlockHeight = BlockHeight (400000 ))
925925 assert(failure == Failure (RouteNotFound ))
926926 }
927927 }
@@ -1048,7 +1048,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
10481048 )), 1 day)
10491049
10501050 val amount = 30000 msat
1051- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 5 ))
1051+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
10521052 val Success (routes) = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
10531053 assert(routes.forall(_.hops.length == 1 ), routes)
10541054 assert(routes.length == 3 , routes)
@@ -1180,7 +1180,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
11801180 // | |
11811181 // +--- B --- D ---+
11821182 // Our balance and the amount we want to send are below the minimum part amount.
1183- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (5000 msat, 5 ))
1183+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (5000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
11841184 val g = GraphWithBalanceEstimates (DirectedGraph (List (
11851185 makeEdge(1L , a, b, 50 msat, 100 , minHtlc = 1 msat, balance_opt = Some (1500 msat)),
11861186 makeEdge(2L , b, d, 15 msat, 0 , minHtlc = 1 msat, capacity = 25 sat),
@@ -1300,22 +1300,22 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
13001300 {
13011301 val amount = 15_000_000 msat
13021302 val maxFee = 50_000 msat // this fee is enough to go through the preferred route
1303- val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 ))
1303+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
13041304 val Success (routes) = findMultiPartRoute(g, a, d, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
13051305 checkRouteAmounts(routes, amount, maxFee)
13061306 assert(routes2Ids(routes) == Set (Seq (100L , 101L )))
13071307 }
13081308 {
13091309 val amount = 15_000_000 msat
13101310 val maxFee = 10_000 msat // this fee is too low to go through the preferred route
1311- val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 ))
1311+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
13121312 val failure = findMultiPartRoute(g, a, d, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
13131313 assert(failure == Failure (RouteNotFound ))
13141314 }
13151315 {
13161316 val amount = 5_000_000 msat
13171317 val maxFee = 10_000 msat // this fee is enough to go through the preferred route, but the cheaper ones can handle it
1318- val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 ))
1318+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
13191319 val Success (routes) = findMultiPartRoute(g, a, d, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
13201320 assert(routes.length == 5 )
13211321 routes.foreach(route => {
@@ -1405,7 +1405,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
14051405 makeEdge(6L , b, c, 5 msat, 50 , minHtlc = 1000 msat, capacity = 20 sat),
14061406 makeEdge(7L , c, f, 5 msat, 10 , minHtlc = 1500 msat, capacity = 50 sat)
14071407 )), 1 day)
1408- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (1500 msat, 10 ))
1408+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (1500 msat, 10 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
14091409
14101410 {
14111411 val (amount, maxFee) = (15000 msat, 50 msat)
@@ -1535,6 +1535,56 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
15351535 }
15361536 }
15371537
1538+ test(" calculate multipart route to remote node using max expected amount splitting strategy" ) {
1539+ // A-------------E
1540+ // | |
1541+ // +----- B -----+
1542+ // | |
1543+ // +----- C ---- +
1544+ // | |
1545+ // +----- D -----+
1546+ val (amount, maxFee) = (60000 msat, 1000 msat)
1547+ val g = GraphWithBalanceEstimates (DirectedGraph (List (
1548+ // The A -> B -> E route is the most economic one, but we already have a pending HTLC in it.
1549+ makeEdge(0L , a, e, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (10000 msat)),
1550+ makeEdge(1L , a, b, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1551+ makeEdge(2L , b, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 50 sat),
1552+ makeEdge(3L , a, c, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1553+ makeEdge(4L , c, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1554+ makeEdge(5L , a, d, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1555+ makeEdge(6L , d, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1556+ )), 1 day)
1557+
1558+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = DEFAULT_ROUTE_PARAMS .mpp.copy(splittingStrategy = MultiPartParams .MaxExpectedAmount ))
1559+ val Success (routes) = findMultiPartRoute(g, a, e, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
1560+ checkRouteAmounts(routes, amount, maxFee)
1561+ assert(routes.map(route => (route.amount, route.hops.head.shortChannelId.toLong)).toSet == Set ((10000 msat, 0L ), (25000 msat, 1L ), (12500 msat, 3L ), (12500 msat, 5L )))
1562+ }
1563+
1564+ test(" calculate multipart route to remote node using max expected amount splitting strategy, respect minPartAmount" ) {
1565+ // +----- B -----+
1566+ // | |
1567+ // A----- C ---- E
1568+ // | |
1569+ // +----- D -----+
1570+ val (amount, maxFee) = (55000 msat, 1000 msat)
1571+ val g = GraphWithBalanceEstimates (DirectedGraph (List (
1572+ // The A -> B -> E route is the most economic one, but we already have a pending HTLC in it.
1573+ makeEdge(1L , a, b, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1574+ makeEdge(2L , b, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 50 sat),
1575+ makeEdge(3L , a, c, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1576+ makeEdge(4L , c, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1577+ makeEdge(5L , a, d, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1578+ makeEdge(6L , d, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1579+ )), 1 day)
1580+
1581+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = DEFAULT_ROUTE_PARAMS .mpp.copy(minPartAmount = 15000 msat, splittingStrategy = MultiPartParams .MaxExpectedAmount ))
1582+ val Success (routes) = findMultiPartRoute(g, a, e, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
1583+ assert(routes.forall(_.hops.length == 2 ), routes)
1584+ checkRouteAmounts(routes, amount, maxFee)
1585+ assert(routes.map(route => (route.amount, route.hops.head.shortChannelId.toLong)).toSet == Set ((25000 msat, 1L ), (15000 msat, 3L ), (15000 msat, 5L )))
1586+ }
1587+
15381588 test(" loop trap" ) {
15391589 // +-----------------+
15401590 // | |
@@ -1899,7 +1949,7 @@ object RouteCalculationSpec {
18991949 randomize = false ,
19001950 boundaries = SearchBoundaries (21000 msat, 0.03 , 6 , CltvExpiryDelta (2016 )),
19011951 NO_WEIGHT_RATIOS ,
1902- MultiPartParams (1000 msat, 10 ),
1952+ MultiPartParams (1000 msat, 10 , MultiPartParams . FullCapacity ),
19031953 experimentName = " my-test-experiment" ,
19041954 experimentPercentage = 100 ).getDefaultRouteParams
19051955
0 commit comments