@@ -969,7 +969,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
969969 makeEdge(4L , a, b, 100 msat, 20 , minHtlc = 1 msat, balance_opt = Some (16000 msat)),
970970 ))
971971 // We set max-parts to 3, but it should be ignored when sending to a direct neighbor.
972- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 3 ))
972+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 3 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
973973
974974 {
975975 val Success (routes) = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
@@ -985,7 +985,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
985985 }
986986 {
987987 // We set min-part-amount to a value that excludes channels 1 and 4.
988- val failure = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams.copy(mpp = MultiPartParams (16500 msat, 3 )), currentBlockHeight = BlockHeight (400000 ))
988+ val failure = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams.copy(mpp = MultiPartParams (16500 msat, 3 , routeParams.mpp.splittingStrategy )), currentBlockHeight = BlockHeight (400000 ))
989989 assert(failure == Failure (RouteNotFound ))
990990 }
991991 }
@@ -1112,7 +1112,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
11121112 ))
11131113
11141114 val amount = 30000 msat
1115- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 5 ))
1115+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (2500 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
11161116 val Success (routes) = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
11171117 assert(routes.forall(_.hops.length == 1 ), routes)
11181118 assert(routes.length == 3 , routes)
@@ -1244,7 +1244,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
12441244 // | |
12451245 // +--- B --- D ---+
12461246 // Our balance and the amount we want to send are below the minimum part amount.
1247- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (5000 msat, 5 ))
1247+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (5000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
12481248 val g = DirectedGraph (List (
12491249 makeEdge(1L , a, b, 50 msat, 100 , minHtlc = 1 msat, balance_opt = Some (1500 msat)),
12501250 makeEdge(2L , b, d, 15 msat, 0 , minHtlc = 1 msat, capacity = 25 sat),
@@ -1364,22 +1364,22 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
13641364 {
13651365 val amount = 15_000_000 msat
13661366 val maxFee = 50_000 msat // this fee is enough to go through the preferred route
1367- val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 ))
1367+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
13681368 val Success (routes) = findMultiPartRoute(g, a, d, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
13691369 checkRouteAmounts(routes, amount, maxFee)
13701370 assert(routes2Ids(routes) == Set (Seq (100L , 101L )))
13711371 }
13721372 {
13731373 val amount = 15_000_000 msat
13741374 val maxFee = 10_000 msat // this fee is too low to go through the preferred route
1375- val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 ))
1375+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
13761376 val failure = findMultiPartRoute(g, a, d, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
13771377 assert(failure == Failure (RouteNotFound ))
13781378 }
13791379 {
13801380 val amount = 5_000_000 msat
13811381 val maxFee = 10_000 msat // this fee is enough to go through the preferred route, but the cheaper ones can handle it
1382- val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 ))
1382+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(randomize = false , mpp = MultiPartParams (50_000 msat, 5 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
13831383 val Success (routes) = findMultiPartRoute(g, a, d, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
13841384 assert(routes.length == 5 )
13851385 routes.foreach(route => {
@@ -1469,7 +1469,7 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
14691469 makeEdge(6L , b, c, 5 msat, 50 , minHtlc = 1000 msat, capacity = 20 sat),
14701470 makeEdge(7L , c, f, 5 msat, 10 , minHtlc = 1500 msat, capacity = 50 sat)
14711471 ))
1472- val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (1500 msat, 10 ))
1472+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = MultiPartParams (1500 msat, 10 , DEFAULT_ROUTE_PARAMS .mpp.splittingStrategy ))
14731473
14741474 {
14751475 val (amount, maxFee) = (15000 msat, 50 msat)
@@ -1599,6 +1599,55 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
15991599 }
16001600 }
16011601
1602+ test(" calculate multipart route to remote node using max expected amount splitting strategy" ) {
1603+ // +----- B -----+
1604+ // | |
1605+ // A----- C ---- E
1606+ // | |
1607+ // +----- D -----+
1608+ val (amount, maxFee) = (50000 msat, 1000 msat)
1609+ val g = DirectedGraph (List (
1610+ // The A -> B -> E route is the most economic one, but we already have a pending HTLC in it.
1611+ makeEdge(1L , a, b, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1612+ makeEdge(2L , b, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 50 sat),
1613+ makeEdge(3L , a, c, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1614+ makeEdge(4L , c, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1615+ makeEdge(5L , a, d, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1616+ makeEdge(6L , d, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1617+ ))
1618+
1619+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = DEFAULT_ROUTE_PARAMS .mpp.copy(splittingStrategy = MultiPartParams .MaxExpectedAmount ))
1620+ val Success (routes) = findMultiPartRoute(g, a, e, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
1621+ assert(routes.forall(_.hops.length == 2 ), routes)
1622+ checkRouteAmounts(routes, amount, maxFee)
1623+ assert(routes.map(route => (route.amount, route.hops.head.shortChannelId.toLong)).toSet == Set ((25000 msat, 1L ), (12500 msat, 3L ), (12500 msat, 5L )))
1624+ }
1625+
1626+ test(" calculate multipart route to remote node using max expected amount splitting strategy, respect minPartAmount" ) {
1627+ // +----- B -----+
1628+ // | |
1629+ // A----- C ---- E
1630+ // | |
1631+ // +----- D -----+
1632+ val (amount, maxFee) = (55000 msat, 1000 msat)
1633+ val g = DirectedGraph (List (
1634+ // The A -> B -> E route is the most economic one, but we already have a pending HTLC in it.
1635+ makeEdge(1L , a, b, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1636+ makeEdge(2L , b, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 50 sat),
1637+ makeEdge(3L , a, c, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1638+ makeEdge(4L , c, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1639+ makeEdge(5L , a, d, 50 msat, 0 , minHtlc = 100 msat, balance_opt = Some (100000 msat)),
1640+ makeEdge(6L , d, e, 50 msat, 0 , minHtlc = 100 msat, capacity = 25 sat),
1641+ ))
1642+
1643+ val routeParams = DEFAULT_ROUTE_PARAMS .copy(mpp = DEFAULT_ROUTE_PARAMS .mpp.copy(minPartAmount = 15000 msat, splittingStrategy = MultiPartParams .MaxExpectedAmount ))
1644+ val Success (routes) = findMultiPartRoute(g, a, e, amount, maxFee, routeParams = routeParams, currentBlockHeight = BlockHeight (400000 ))
1645+ routes.foreach(println)
1646+ assert(routes.forall(_.hops.length == 2 ), routes)
1647+ checkRouteAmounts(routes, amount, maxFee)
1648+ assert(routes.map(route => (route.amount, route.hops.head.shortChannelId.toLong)).toSet == Set ((25000 msat, 1L ), (15000 msat, 3L ), (15000 msat, 5L )))
1649+ }
1650+
16021651 test(" loop trap" ) {
16031652 // +-----------------+
16041653 // | |
@@ -1927,7 +1976,7 @@ object RouteCalculationSpec {
19271976 randomize = false ,
19281977 boundaries = SearchBoundaries (21000 msat, 0.03 , 6 , CltvExpiryDelta (2016 )),
19291978 Left (NO_WEIGHT_RATIOS ),
1930- MultiPartParams (1000 msat, 10 ),
1979+ MultiPartParams (1000 msat, 10 , MultiPartParams . FullCapacity ),
19311980 experimentName = " my-test-experiment" ,
19321981 experimentPercentage = 100 ).getDefaultRouteParams
19331982
0 commit comments