Skip to content

Commit

Permalink
Allow for user-configurable fee options (#317)
Browse files Browse the repository at this point in the history
The SendPayment command now accepts a `trampolineFees` parameter, which allows the sender to override the defaults. This allows, for example, applications to provide a user-configurable max-fees option.
  • Loading branch information
robbiehanson committed Jan 21, 2022
1 parent 5bfcf09 commit 13c7143
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/fr/acinq/lightning/io/Peer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ sealed class PaymentEvent : PeerEvent()
data class ReceivePayment(val paymentPreimage: ByteVector32, val amount: MilliSatoshi?, val description: String, val expirySeconds: Long? = null, val result: CompletableDeferred<PaymentRequest>) : PaymentEvent()
object CheckPaymentsTimeout : PaymentEvent()
data class PayToOpenResponseEvent(val payToOpenResponse: PayToOpenResponse) : PeerEvent()
data class SendPayment(val paymentId: UUID, val amount: MilliSatoshi, val recipient: PublicKey, val details: OutgoingPayment.Details.Normal) : PaymentEvent() {
data class SendPayment(val paymentId: UUID, val amount: MilliSatoshi, val recipient: PublicKey, val details: OutgoingPayment.Details.Normal, val trampolineFeesOverride: List<TrampolineFees>? = null) : PaymentEvent() {
val paymentHash: ByteVector32 = details.paymentHash
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class OutgoingPaymentHandler(val nodeId: PublicKey, val walletParams: WalletPara
logger.error { "h:${request.paymentHash} p:${request.paymentId} invoice has already been paid" }
return Failure(request, FinalFailure.AlreadyPaid.toPaymentFailure())
}

val (trampolineAmount, trampolineExpiry, trampolinePacket) = createTrampolinePayload(request, walletParams.trampolineFees.first(), currentBlockHeight)
val trampolineFees = request.trampolineFeesOverride ?: walletParams.trampolineFees
val (trampolineAmount, trampolineExpiry, trampolinePacket) = createTrampolinePayload(request, trampolineFees.first(), currentBlockHeight)
return when (val result = RouteCalculation.findRoutes(request.paymentId, trampolineAmount, channels)) {
is Either.Left -> {
logger.warning { "h:${request.paymentHash} p:${request.paymentId} payment failed: ${result.value}" }
Expand Down Expand Up @@ -138,8 +138,9 @@ class OutgoingPaymentHandler(val nodeId: PublicKey, val walletParams: WalletPara

val (updated, result) = when (payment) {
is PaymentAttempt.PaymentInProgress -> {
val trampolineFees = payment.request.trampolineFeesOverride ?: walletParams.trampolineFees
val finalError = when {
walletParams.trampolineFees.size <= payment.attemptNumber + 1 -> FinalFailure.RetryExhausted
trampolineFees.size <= payment.attemptNumber + 1 -> FinalFailure.RetryExhausted
failure == UnknownNextPeer -> FinalFailure.RecipientUnreachable
failure != TrampolineExpiryTooSoon && failure != TrampolineFeeInsufficient -> FinalFailure.UnknownError // non-retriable error
else -> null
Expand All @@ -155,9 +156,9 @@ class OutgoingPaymentHandler(val nodeId: PublicKey, val walletParams: WalletPara
// NB: we don't update failures here to avoid duplicate trampoline errors
Pair(updated, null)
} else {
val trampolineFees = walletParams.trampolineFees[payment.attemptNumber + 1]
logger.info { "h:${payment.request.paymentHash} p:${payment.request.paymentId} retrying payment with higher fees (base=${trampolineFees.feeBase}, proportional=${trampolineFees.feeProportional})..." }
val (trampolineAmount, trampolineExpiry, trampolinePacket) = createTrampolinePayload(payment.request, trampolineFees, currentBlockHeight)
val nextFees = trampolineFees[payment.attemptNumber + 1]
logger.info { "h:${payment.request.paymentHash} p:${payment.request.paymentId} retrying payment with higher fees (base=${nextFees.feeBase}, proportional=${nextFees.feeProportional})..." }
val (trampolineAmount, trampolineExpiry, trampolinePacket) = createTrampolinePayload(payment.request, nextFees, currentBlockHeight)
when (val routes = RouteCalculation.findRoutes(payment.request.paymentId, trampolineAmount, channels)) {
is Either.Left -> {
logger.warning { "h:${payment.request.paymentHash} p:${payment.request.paymentId} payment failed: ${routes.value}" }
Expand Down

0 comments on commit 13c7143

Please sign in to comment.