diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt index de7fb4503..80af4e7cc 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt @@ -659,11 +659,17 @@ data class InteractiveTxSession( val sharedOutput = sharedOutputs.first() val sharedInput = fundingParams.sharedInput?.let { - // To compute the remote reserve, we discard the local contribution. It's okay if they go below reserve because - // we added capacity to the channel with a splice-in. - val remoteReserve = ((fundingParams.fundingAmount - fundingParams.localContribution) / 100).max(fundingParams.dustLimit) - if (sharedOutput.remoteAmount < remoteReserve && remoteOnlyOutputs.isNotEmpty()) { - return InteractiveTxSessionAction.InvalidTxBelowReserve(fundingParams.channelId, sharedOutput.remoteAmount.truncateToSatoshi(), remoteReserve) + if (fundingParams.remoteContribution >= 0.sat) { + // If remote has a positive contribution, we do not check their post-splice reserve level, because they are improving + // their situation, even if they stay below the requirement. Note that if local splices-in some funds in the same + // operation, remote post-splice reserve may actually be worse than before, but that's not their fault. + } else { + // To compute the remote reserve, we discard the local contribution. It's okay if they go below reserve because + // we added capacity to the channel with a splice-in. + val remoteReserve = ((fundingParams.fundingAmount - fundingParams.localContribution) / 100).max(fundingParams.dustLimit) + if (sharedOutput.remoteAmount < remoteReserve && remoteOnlyOutputs.isNotEmpty()) { + return InteractiveTxSessionAction.InvalidTxBelowReserve(fundingParams.channelId, sharedOutput.remoteAmount.truncateToSatoshi(), remoteReserve) + } } if (sharedInputs.size != 1) { return InteractiveTxSessionAction.InvalidTxSharedInput(fundingParams.channelId) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt index 0868131fd..7ec51e6fe 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt @@ -105,7 +105,7 @@ data class Normal( localOutputs = cmd.spliceOutputs, targetFeerate = cmd.feerate ) - if (parentCommitment.localCommit.spec.toLocal + fundingContribution.toMilliSatoshi() < 0.msat) { + if (fundingContribution < 0.sat && parentCommitment.localCommit.spec.toLocal + fundingContribution.toMilliSatoshi() < parentCommitment.localChannelReserve(commitments.params)) { logger.warning { "cannot do splice: insufficient funds" } cmd.replyTo.complete(ChannelCommand.Commitment.Splice.Response.Failure.InsufficientFunds) Pair(this@Normal, emptyList())