Skip to content

Commit f379f68

Browse files
committed
Implement the option_simple_close protocol
We update the `Negotiating` state to exchange the `closing_complete` and `closing_sig` messages, and allow RBF-ing previous transactions and updating our closing script. We stay in that state until one of the transactions confirms, or a force close is detected. This is important to ensure we're able to correctly reconnect and negotiate RBF candidates.
1 parent 3f57c04 commit f379f68

File tree

52 files changed

+1290
-2332
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1290
-2332
lines changed

modules/core/src/commonMain/kotlin/fr/acinq/lightning/NodeParams.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ data class NodeParams(
174174
require(features.hasFeature(Feature.ChannelType, FeatureSupport.Mandatory)) { "${Feature.ChannelType.rfcName} should be mandatory" }
175175
require(features.hasFeature(Feature.DualFunding, FeatureSupport.Mandatory)) { "${Feature.DualFunding.rfcName} should be mandatory" }
176176
require(features.hasFeature(Feature.RouteBlinding)) { "${Feature.RouteBlinding.rfcName} should be supported" }
177+
require(features.hasFeature(Feature.ShutdownAnySegwit, FeatureSupport.Mandatory)) { "${Feature.ShutdownAnySegwit.rfcName} should be mandatory" }
178+
require(features.hasFeature(Feature.SimpleClose, FeatureSupport.Mandatory)) { "${Feature.SimpleClose.rfcName} should be mandatory" }
177179
require(!features.hasFeature(Feature.ZeroConfChannels)) { "${Feature.ZeroConfChannels.rfcName} has been deprecated: use the zeroConfPeers whitelist instead" }
178180
require(!features.hasFeature(Feature.TrustedSwapInClient)) { "${Feature.TrustedSwapInClient.rfcName} has been deprecated" }
179181
require(!features.hasFeature(Feature.TrustedSwapInProvider)) { "${Feature.TrustedSwapInProvider.rfcName} has been deprecated" }
@@ -205,6 +207,7 @@ data class NodeParams(
205207
Feature.Quiescence to FeatureSupport.Mandatory,
206208
Feature.ChannelType to FeatureSupport.Mandatory,
207209
Feature.PaymentMetadata to FeatureSupport.Optional,
210+
Feature.SimpleClose to FeatureSupport.Mandatory,
208211
Feature.ExperimentalTrampolinePayment to FeatureSupport.Optional,
209212
Feature.ZeroReserveChannels to FeatureSupport.Optional,
210213
Feature.WakeUpNotificationClient to FeatureSupport.Optional,

modules/core/src/commonMain/kotlin/fr/acinq/lightning/channel/ChannelCommand.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import fr.acinq.lightning.MilliSatoshi
66
import fr.acinq.lightning.blockchain.WatchTriggered
77
import fr.acinq.lightning.blockchain.electrum.WalletState
88
import fr.acinq.lightning.blockchain.fee.FeeratePerKw
9-
import fr.acinq.lightning.channel.states.ClosingFeerates
109
import fr.acinq.lightning.channel.states.PersistedChannelState
1110
import fr.acinq.lightning.crypto.KeyManager
1211
import fr.acinq.lightning.utils.UUID
@@ -105,7 +104,7 @@ sealed class ChannelCommand {
105104
}
106105

107106
sealed class Close : ChannelCommand() {
108-
data class MutualClose(val scriptPubKey: ByteVector?, val feerates: ClosingFeerates?) : Close(), ForbiddenDuringSplice, ForbiddenDuringQuiescence
107+
data class MutualClose(val scriptPubKey: ByteVector?, val feerate: FeeratePerKw) : Close(), ForbiddenDuringSplice, ForbiddenDuringQuiescence
109108
data object ForceClose : Close()
110109
}
111110

modules/core/src/commonMain/kotlin/fr/acinq/lightning/channel/ChannelData.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import fr.acinq.lightning.logging.LoggingContext
1313
import fr.acinq.lightning.transactions.Scripts
1414
import fr.acinq.lightning.transactions.Transactions.TransactionWithInputInfo.*
1515
import fr.acinq.lightning.utils.toMilliSatoshi
16-
import fr.acinq.lightning.wire.ClosingSigned
1716

1817
/**
1918
* Details about a force-close where we published our commitment.
@@ -370,10 +369,6 @@ data class LocalParams(
370369
features = nodeParams.features.initFeatures()
371370
)
372371

373-
// The node responsible for the commit tx fees is also the node paying the mutual close fees.
374-
// The other node's balance may be empty, which wouldn't allow them to pay the closing fees.
375-
val paysClosingFees: Boolean = paysCommitTxFees
376-
377372
fun channelKeys(keyManager: KeyManager) = keyManager.channelKeys(fundingKeyPath)
378373
}
379374

@@ -397,8 +392,6 @@ data class RemoteParams(
397392
*/
398393
data class ChannelFlags(val announceChannel: Boolean, val nonInitiatorPaysCommitFees: Boolean)
399394

400-
data class ClosingTxProposed(val unsignedTx: ClosingTx, val localClosingSigned: ClosingSigned)
401-
402395
/**
403396
* @param miningFee fee paid to miners for the underlying on-chain transaction.
404397
* @param serviceFee fee paid to our peer for any service provided with the on-chain transaction.

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package fr.acinq.lightning.channel
22

3-
import fr.acinq.bitcoin.BlockHash
4-
import fr.acinq.bitcoin.ByteVector32
5-
import fr.acinq.bitcoin.Satoshi
6-
import fr.acinq.bitcoin.TxId
3+
import fr.acinq.bitcoin.*
74
import fr.acinq.lightning.CltvExpiry
85
import fr.acinq.lightning.CltvExpiryDelta
96
import fr.acinq.lightning.MilliSatoshi
@@ -62,8 +59,10 @@ data class FeerateTooSmall (override val channelId: Byte
6259
data class FeerateTooDifferent (override val channelId: ByteVector32, val localFeeratePerKw: FeeratePerKw, val remoteFeeratePerKw: FeeratePerKw) : ChannelException(channelId, "local/remote feerates are too different: remoteFeeratePerKw=${remoteFeeratePerKw.toLong()} localFeeratePerKw=${localFeeratePerKw.toLong()}")
6360
data class InvalidCommitmentSignature (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid commitment signature: txId=$txId")
6461
data class InvalidHtlcSignature (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid htlc signature: txId=$txId")
62+
data class CannotGenerateClosingTx (override val channelId: ByteVector32) : ChannelException(channelId, "failed to generate closing transaction: all outputs are trimmed")
63+
data class MissingCloseSignature (override val channelId: ByteVector32) : ChannelException(channelId, "closing_complete is missing a signature for a closing transaction including our output")
6564
data class InvalidCloseSignature (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid close signature: txId=$txId")
66-
data class InvalidCloseAmountBelowDust (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid closing tx: some outputs are below dust: txId=$txId")
65+
data class InvalidCloseeScript (override val channelId: ByteVector32, val received: ByteVector, val expected: ByteVector) : ChannelException(channelId, "invalid closee script used in closing_complete: our latest script is $expected, you're using $received")
6766
data class CommitSigCountMismatch (override val channelId: ByteVector32, val expected: Int, val actual: Int) : ChannelException(channelId, "commit sig count mismatch: expected=$expected actual=$actual")
6867
data class HtlcSigCountMismatch (override val channelId: ByteVector32, val expected: Int, val actual: Int) : ChannelException(channelId, "htlc sig count mismatch: expected=$expected actual: $actual")
6968
data class ForcedLocalCommit (override val channelId: ByteVector32) : ChannelException(channelId, "forced local commit")

0 commit comments

Comments
 (0)