Skip to content

Commit 192f3bf

Browse files
Simplify outgoing payment state machine (#692)
We previously supported having multiple channels with our peer, because we didn't yet support splicing. Now that we support splicing, we always have at most one active channel with our peer. This lets us simplify greatly the outgoing payment state machine: payments are always made with a single outgoing HTLC instead of potentially multiple HTLCs (MPP). We don't need any kind of path-finding: we simply need to check the balance of our active channel, if any. We may introduce support for connecting to multiple peers in the future. When that happens, we will still have a single active channel per peer, but we may allow splitting outgoing payments across our peers. We will need to re-work the outgoing payment state machine when this happens, but it is too early to support this now anyway. This refactoring makes it easier to create payment onion, by creating the trampoline onion *and* the outer onion in the same function call. This will make it simpler to migrate to the version of trampoline that is currently specified in lightning/bolts#836 where some fields will be included in the payment onion instead of the trampoline onion. Co-authored-by: Thomas HUET <[email protected]>
1 parent f86fffe commit 192f3bf

File tree

12 files changed

+939
-1825
lines changed

12 files changed

+939
-1825
lines changed

src/commonMain/kotlin/fr/acinq/lightning/channel/ChannelException.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ data class CannotAffordFirstCommitFees (override val channelId: Byte
8383
data class CannotAffordFees (override val channelId: ByteVector32, val missing: Satoshi, val reserve: Satoshi, val fees: Satoshi) : ChannelException(channelId, "can't pay the fee: missing=$missing reserve=$reserve fees=$fees")
8484
data class CannotSignWithoutChanges (override val channelId: ByteVector32) : ChannelException(channelId, "cannot sign when there are no change")
8585
data class CannotSignBeforeRevocation (override val channelId: ByteVector32) : ChannelException(channelId, "cannot sign until next revocation hash is received")
86+
data class CannotSignDisconnected (override val channelId: ByteVector32) : ChannelException(channelId, "disconnected before signing outgoing payments")
8687
data class UnexpectedRevocation (override val channelId: ByteVector32) : ChannelException(channelId, "received unexpected RevokeAndAck message")
8788
data class InvalidRevocation (override val channelId: ByteVector32) : ChannelException(channelId, "invalid revocation")
8889
data class InvalidFailureCode (override val channelId: ByteVector32) : ChannelException(channelId, "UpdateFailMalformedHtlc message doesn't have BADONION bit set")
90+
data class CannotDecryptFailure (override val channelId: ByteVector32, val details: String) : ChannelException(channelId, "cannot decrypt failure message: $details")
8991
data class PleasePublishYourCommitment (override val channelId: ByteVector32) : ChannelException(channelId, "please publish your local commitment")
9092
data class CommandUnavailableInThisState (override val channelId: ByteVector32, val state: String) : ChannelException(channelId, "cannot execute command in state=$state")
9193
data class ForbiddenDuringSplice (override val channelId: ByteVector32, val command: String?) : ChannelException(channelId, "cannot process $command while splicing")

src/commonMain/kotlin/fr/acinq/lightning/io/Peer.kt

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -812,34 +812,28 @@ class Peer(
812812
is ChannelAction.ProcessIncomingHtlc -> processIncomingPayment(Either.Right(action.add))
813813
is ChannelAction.ProcessCmdRes.NotExecuted -> logger.warning(action.t) { "command not executed" }
814814
is ChannelAction.ProcessCmdRes.AddFailed -> {
815-
when (val result = outgoingPaymentHandler.processAddFailed(actualChannelId, action, _channels)) {
816-
is OutgoingPaymentHandler.Progress -> {
817-
_eventsFlow.emit(PaymentProgress(result.request, result.fees))
818-
result.actions.forEach { input.send(it) }
819-
}
820-
815+
when (val result = outgoingPaymentHandler.processAddFailed(actualChannelId, action)) {
821816
is OutgoingPaymentHandler.Failure -> _eventsFlow.emit(PaymentNotSent(result.request, result.failure))
822817
null -> logger.debug { "non-final error, more partial payments are still pending: ${action.error.message}" }
823818
}
824819
}
825820
is ChannelAction.ProcessCmdRes.AddSettledFail -> {
826821
val currentTip = currentTipFlow.filterNotNull().first()
827-
when (val result = outgoingPaymentHandler.processAddSettled(actualChannelId, action, _channels, currentTip)) {
822+
when (val result = outgoingPaymentHandler.processAddSettledFailed(actualChannelId, action, _channels, currentTip)) {
828823
is OutgoingPaymentHandler.Progress -> {
829824
_eventsFlow.emit(PaymentProgress(result.request, result.fees))
830825
result.actions.forEach { input.send(it) }
831826
}
832827

833828
is OutgoingPaymentHandler.Success -> _eventsFlow.emit(PaymentSent(result.request, result.payment))
834829
is OutgoingPaymentHandler.Failure -> _eventsFlow.emit(PaymentNotSent(result.request, result.failure))
835-
null -> logger.debug { "non-final error, more partial payments are still pending: ${action.result}" }
830+
null -> logger.debug { "non-final error, another payment attempt (retry) is still pending: ${action.result}" }
836831
}
837832
}
838833
is ChannelAction.ProcessCmdRes.AddSettledFulfill -> {
839-
when (val result = outgoingPaymentHandler.processAddSettled(action)) {
834+
when (val result = outgoingPaymentHandler.processAddSettledFulfilled(action)) {
840835
is OutgoingPaymentHandler.Success -> _eventsFlow.emit(PaymentSent(result.request, result.payment))
841-
is OutgoingPaymentHandler.PreimageReceived -> logger.debug(mapOf("paymentId" to result.request.paymentId)) { "payment preimage received: ${result.preimage}" }
842-
null -> logger.debug { "unknown payment" }
836+
null -> logger.error { "unknown payment fulfilled: this should never happen" }
843837
}
844838
}
845839
is ChannelAction.Storage.StoreState -> {

0 commit comments

Comments
 (0)