mirror of
https://github.com/ACINQ/eclair.git
synced 2024-11-20 02:27:32 +01:00
Allow to disable route randomization via configuration (#851)
* Allow to enable/disable the route randomization feature from the configuration * Move router related configuration keys in router block.
This commit is contained in:
parent
3165f5dc36
commit
968961248e
@ -79,11 +79,6 @@ eclair {
|
||||
|
||||
revocation-timeout = 20 seconds // after sending a commit_sig, we will wait for at most that duration before disconnecting
|
||||
|
||||
channel-exclude-duration = 60 seconds // when a temporary channel failure is returned, we exclude the channel from our payment routes for this duration
|
||||
router-broadcast-interval = 60 seconds // see BOLT #7
|
||||
|
||||
router-init-timeout = 5 minutes
|
||||
|
||||
ping-interval = 30 seconds
|
||||
ping-timeout = 10 seconds // will disconnect if peer takes longer than that to respond
|
||||
ping-disconnect = true // disconnect if no answer to our pings
|
||||
@ -96,4 +91,11 @@ eclair {
|
||||
min-funding-satoshis = 100000
|
||||
|
||||
autoprobe-count = 0 // number of parallel tasks that send test payments to detect invalid channels
|
||||
|
||||
router {
|
||||
randomize-route-selection = true // when computing a route for a payment we randomize the final selection
|
||||
channel-exclude-duration = 60 seconds // when a temporary channel failure is returned, we exclude the channel from our payment routes for this duration
|
||||
broadcast-interval = 60 seconds // see BOLT #7
|
||||
init-timeout = 5 minutes
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,9 @@ case class NodeParams(keyManager: KeyManager,
|
||||
paymentRequestExpiry: FiniteDuration,
|
||||
maxPendingPaymentRequests: Int,
|
||||
maxPaymentFee: Double,
|
||||
minFundingSatoshis: Long) {
|
||||
minFundingSatoshis: Long,
|
||||
randomizeRouteSelection: Boolean
|
||||
) {
|
||||
|
||||
val privateKey = keyManager.nodeKey.privateKey
|
||||
val nodeId = keyManager.nodeId
|
||||
@ -209,7 +211,7 @@ object NodeParams {
|
||||
paymentsDb = paymentsDb,
|
||||
auditDb = auditDb,
|
||||
revocationTimeout = FiniteDuration(config.getDuration("revocation-timeout").getSeconds, TimeUnit.SECONDS),
|
||||
routerBroadcastInterval = FiniteDuration(config.getDuration("router-broadcast-interval").getSeconds, TimeUnit.SECONDS),
|
||||
routerBroadcastInterval = FiniteDuration(config.getDuration("router.broadcast-interval").getSeconds, TimeUnit.SECONDS),
|
||||
pingInterval = FiniteDuration(config.getDuration("ping-interval").getSeconds, TimeUnit.SECONDS),
|
||||
pingTimeout = FiniteDuration(config.getDuration("ping-timeout").getSeconds, TimeUnit.SECONDS),
|
||||
pingDisconnect = config.getBoolean("ping-disconnect"),
|
||||
@ -218,12 +220,13 @@ object NodeParams {
|
||||
autoReconnect = config.getBoolean("auto-reconnect"),
|
||||
chainHash = chainHash,
|
||||
channelFlags = config.getInt("channel-flags").toByte,
|
||||
channelExcludeDuration = FiniteDuration(config.getDuration("channel-exclude-duration").getSeconds, TimeUnit.SECONDS),
|
||||
channelExcludeDuration = FiniteDuration(config.getDuration("router.channel-exclude-duration").getSeconds, TimeUnit.SECONDS),
|
||||
watcherType = watcherType,
|
||||
paymentRequestExpiry = FiniteDuration(config.getDuration("payment-request-expiry").getSeconds, TimeUnit.SECONDS),
|
||||
maxPendingPaymentRequests = config.getInt("max-pending-payment-requests"),
|
||||
maxPaymentFee = config.getDouble("max-payment-fee"),
|
||||
minFundingSatoshis = config.getLong("min-funding-satoshis")
|
||||
minFundingSatoshis = config.getLong("min-funding-satoshis"),
|
||||
randomizeRouteSelection = config.getBoolean("router.randomize-route-selection")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ class Setup(datadir: File,
|
||||
}
|
||||
|
||||
router = system.actorOf(SimpleSupervisor.props(Router.props(nodeParams, watcher, Some(routerInitialized)), "router", SupervisorStrategy.Resume))
|
||||
routerTimeout = after(FiniteDuration(config.getDuration("router-init-timeout").getSeconds, TimeUnit.SECONDS), using = system.scheduler)(Future.failed(new RuntimeException("Router initialization timed out")))
|
||||
routerTimeout = after(FiniteDuration(config.getDuration("router.init-timeout").getSeconds, TimeUnit.SECONDS), using = system.scheduler)(Future.failed(new RuntimeException("Router initialization timed out")))
|
||||
_ <- Future.firstCompletedOf(routerInitialized.future :: routerTimeout :: Nil)
|
||||
|
||||
wallet = bitcoin match {
|
||||
|
@ -193,7 +193,7 @@ object PaymentLifecycle {
|
||||
/**
|
||||
* @param maxFeePct set by default to 3% as a safety measure (even if a route is found, if fee is higher than that payment won't be attempted)
|
||||
*/
|
||||
case class SendPayment(amountMsat: Long, paymentHash: BinaryData, targetNodeId: PublicKey, assistedRoutes: Seq[Seq[ExtraHop]] = Nil, finalCltvExpiry: Long = Channel.MIN_CLTV_EXPIRY, maxAttempts: Int = 5, maxFeePct: Double = 0.03, randomize: Boolean = true) {
|
||||
case class SendPayment(amountMsat: Long, paymentHash: BinaryData, targetNodeId: PublicKey, assistedRoutes: Seq[Seq[ExtraHop]] = Nil, finalCltvExpiry: Long = Channel.MIN_CLTV_EXPIRY, maxAttempts: Int = 5, maxFeePct: Double = 0.03, randomize: Option[Boolean] = None) {
|
||||
require(amountMsat > 0, s"amountMsat must be > 0")
|
||||
}
|
||||
case class CheckPayment(paymentHash: BinaryData)
|
||||
|
@ -46,7 +46,7 @@ import scala.util.{Random, Try}
|
||||
|
||||
case class ChannelDesc(shortChannelId: ShortChannelId, a: PublicKey, b: PublicKey)
|
||||
case class Hop(nodeId: PublicKey, nextNodeId: PublicKey, lastUpdate: ChannelUpdate)
|
||||
case class RouteRequest(source: PublicKey, target: PublicKey, amountMsat: Long, assistedRoutes: Seq[Seq[ExtraHop]] = Nil, ignoreNodes: Set[PublicKey] = Set.empty, ignoreChannels: Set[ChannelDesc] = Set.empty, randomize: Boolean = true)
|
||||
case class RouteRequest(source: PublicKey, target: PublicKey, amountMsat: Long, assistedRoutes: Seq[Seq[ExtraHop]] = Nil, ignoreNodes: Set[PublicKey] = Set.empty, ignoreChannels: Set[ChannelDesc] = Set.empty, randomize: Option[Boolean] = None)
|
||||
case class RouteResponse(hops: Seq[Hop], ignoreNodes: Set[PublicKey], ignoreChannels: Set[ChannelDesc]) {
|
||||
require(hops.size > 0, "route cannot be empty")
|
||||
}
|
||||
@ -384,7 +384,7 @@ class Router(nodeParams: NodeParams, watcher: ActorRef, initialized: Option[Prom
|
||||
log.info(s"finding a route $start->$end with assistedChannels={} ignoreNodes={} ignoreChannels={} excludedChannels={}", assistedUpdates.keys.mkString(","), ignoreNodes.map(_.toBin).mkString(","), ignoreChannels.mkString(","), d.excludedChannels.mkString(","))
|
||||
val extraEdges = assistedUpdates.map { case (c, u) => GraphEdge(c, u) }.toSet
|
||||
// if we want to randomize we ask the router to make a random selection among the three best routes
|
||||
val routesToFind = if(randomize) DEFAULT_ROUTES_COUNT else 1
|
||||
val routesToFind = if(randomize.getOrElse(nodeParams.randomizeRouteSelection)) DEFAULT_ROUTES_COUNT else 1
|
||||
findRoute(d.graph, start, end, amount, numRoutes = routesToFind, extraEdges = extraEdges, ignoredEdges = ignoredUpdates.toSet)
|
||||
.map(r => sender ! RouteResponse(r, ignoreNodes, ignoreChannels))
|
||||
.recover { case t => sender ! Status.Failure(t) }
|
||||
|
@ -86,7 +86,9 @@ object TestConstants {
|
||||
paymentRequestExpiry = 1 hour,
|
||||
maxPendingPaymentRequests = 10000000,
|
||||
maxPaymentFee = 0.03,
|
||||
minFundingSatoshis = 1000L)
|
||||
minFundingSatoshis = 1000L,
|
||||
randomizeRouteSelection = true
|
||||
)
|
||||
|
||||
def channelParams = Peer.makeChannelParams(
|
||||
nodeParams = nodeParams,
|
||||
@ -145,7 +147,8 @@ object TestConstants {
|
||||
paymentRequestExpiry = 1 hour,
|
||||
maxPendingPaymentRequests = 10000000,
|
||||
maxPaymentFee = 0.03,
|
||||
minFundingSatoshis = 1000L)
|
||||
minFundingSatoshis = 1000L,
|
||||
randomizeRouteSelection = true)
|
||||
|
||||
def channelParams = Peer.makeChannelParams(
|
||||
nodeParams = nodeParams,
|
||||
|
@ -251,7 +251,7 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
|
||||
sender.send(nodes("D").paymentHandler, ReceivePayment(Some(amountMsat), "1 coffee"))
|
||||
val pr = sender.expectMsgType[PaymentRequest]
|
||||
// then we make the actual payment, do not randomize the route to make sure we route through node B
|
||||
val sendReq = SendPayment(amountMsat.amount, pr.paymentHash, nodes("D").nodeParams.nodeId, randomize = false)
|
||||
val sendReq = SendPayment(amountMsat.amount, pr.paymentHash, nodes("D").nodeParams.nodeId, randomize = Some(false))
|
||||
sender.send(nodes("A").paymentInitiator, sendReq)
|
||||
// A will receive an error from B that include the updated channel update, then will retry the payment
|
||||
sender.expectMsgType[PaymentSucceeded](5 seconds)
|
||||
|
Loading…
Reference in New Issue
Block a user