mirror of
https://github.com/ACINQ/eclair.git
synced 2025-03-13 19:37:35 +01:00
When the recipient is a direct peer, we can use the accurate knowledge of our local channels instead of hard-coded MPP parameters to choose the number of routes and the minimum route amount. This change makes it possible to easily send all local funds in one payment when we're directly connected to the recipient.
This commit is contained in:
parent
20eb41fb01
commit
4426981d03
2 changed files with 21 additions and 6 deletions
|
@ -302,15 +302,23 @@ object RouteCalculation {
|
|||
routeParams: RouteParams,
|
||||
currentBlockHeight: Long): Either[RouterException, Seq[Route]] = {
|
||||
// We use Yen's k-shortest paths to find many paths for chunks of the total amount.
|
||||
val numRoutes = {
|
||||
val directChannelsCount = g.getEdgesBetween(localNodeId, targetNodeId).length
|
||||
routeParams.mpp.maxParts.max(directChannelsCount) // if we have direct channels to the target, we can use them all
|
||||
// When the recipient is a direct peer, we have complete visibility on our local channels so we can use more accurate MPP parameters.
|
||||
val routeParams1 = {
|
||||
case class DirectChannel(balance: MilliSatoshi, isEmpty: Boolean)
|
||||
val directChannels = g.getEdgesBetween(localNodeId, targetNodeId).collect {
|
||||
// We should always have balance information available for local channels.
|
||||
case GraphEdge(_, update, _, Some(balance)) => DirectChannel(balance, balance < update.htlcMinimumMsat)
|
||||
}
|
||||
// If we have direct channels to the target, we can use them all.
|
||||
val numRoutes = routeParams.mpp.maxParts.max(directChannels.length)
|
||||
// If we have direct channels to the target, we can use them all, even if they have only a small balance left.
|
||||
val minPartAmount = (amount +: routeParams.mpp.minPartAmount +: directChannels.filter(!_.isEmpty).map(_.balance)).min
|
||||
routeParams.copy(mpp = MultiPartParams(minPartAmount, numRoutes))
|
||||
}
|
||||
val routeAmount = routeParams.mpp.minPartAmount.min(amount)
|
||||
findRouteInternal(g, localNodeId, targetNodeId, routeAmount, maxFee, numRoutes, extraEdges, ignoredEdges, ignoredVertices, routeParams, currentBlockHeight) match {
|
||||
findRouteInternal(g, localNodeId, targetNodeId, routeParams1.mpp.minPartAmount, maxFee, routeParams1.mpp.maxParts, extraEdges, ignoredEdges, ignoredVertices, routeParams1, currentBlockHeight) match {
|
||||
case Right(routes) =>
|
||||
// We use these shortest paths to find a set of non-conflicting HTLCs that send the total amount.
|
||||
split(amount, mutable.Queue(routes: _*), initializeUsedCapacity(pendingHtlcs), routeParams) match {
|
||||
split(amount, mutable.Queue(routes: _*), initializeUsedCapacity(pendingHtlcs), routeParams1) match {
|
||||
case Right(routes) if validateMultiPartRoute(amount, maxFee, routes) => Right(routes)
|
||||
case _ => Left(RouteNotFound)
|
||||
}
|
||||
|
|
|
@ -981,6 +981,13 @@ class RouteCalculationSpec extends AnyFunSuite with ParallelTestExecution {
|
|||
assert(routes.forall(_.length == 1), routes)
|
||||
checkRouteAmounts(routes, amount, 0 msat)
|
||||
}
|
||||
{
|
||||
// We set min-part-amount to a value that would exclude channels 1 and 4, but it should be ignored when sending to a direct neighbor.
|
||||
val Success(routes) = findMultiPartRoute(g, a, b, amount, 1 msat, routeParams = routeParams.copy(mpp = MultiPartParams(20000 msat, 3)), currentBlockHeight = 400000)
|
||||
assert(routes.length === 4, routes)
|
||||
assert(routes.forall(_.length == 1), routes)
|
||||
checkRouteAmounts(routes, amount, 0 msat)
|
||||
}
|
||||
}
|
||||
|
||||
test("calculate multipart route to neighbor (single channel, known balance)") {
|
||||
|
|
Loading…
Add table
Reference in a new issue