Skip to content

Commit

Permalink
Implement the option_simple_close protocol
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
t-bast committed Mar 27, 2024
1 parent 3fa7de6 commit 48b7348
Show file tree
Hide file tree
Showing 59 changed files with 1,135 additions and 3,477 deletions.
3 changes: 3 additions & 0 deletions src/commonMain/kotlin/fr/acinq/lightning/NodeParams.kt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ data class NodeParams(
require(features.hasFeature(Feature.PaymentSecret, FeatureSupport.Mandatory)) { "${Feature.PaymentSecret.rfcName} should be mandatory" }
require(features.hasFeature(Feature.ChannelType, FeatureSupport.Mandatory)) { "${Feature.ChannelType.rfcName} should be mandatory" }
require(features.hasFeature(Feature.DualFunding, FeatureSupport.Mandatory)) { "${Feature.DualFunding.rfcName} should be mandatory" }
require(features.hasFeature(Feature.ShutdownAnySegwit, FeatureSupport.Mandatory)) { "${Feature.ShutdownAnySegwit.rfcName} should be mandatory" }
require(features.hasFeature(Feature.SimpleClose, FeatureSupport.Mandatory)) { "${Feature.SimpleClose.rfcName} should be mandatory" }
require(!features.hasFeature(Feature.ZeroConfChannels)) { "${Feature.ZeroConfChannels.rfcName} has been deprecated: use the zeroConfPeers whitelist instead" }
require(!features.hasFeature(Feature.TrustedSwapInClient)) { "${Feature.TrustedSwapInClient.rfcName} has been deprecated" }
require(!features.hasFeature(Feature.TrustedSwapInProvider)) { "${Feature.TrustedSwapInProvider.rfcName} has been deprecated" }
Expand All @@ -185,6 +187,7 @@ data class NodeParams(
Feature.ShutdownAnySegwit to FeatureSupport.Mandatory,
Feature.ChannelType to FeatureSupport.Mandatory,
Feature.PaymentMetadata to FeatureSupport.Optional,
Feature.SimpleClose to FeatureSupport.Mandatory,
Feature.ExperimentalTrampolinePayment to FeatureSupport.Optional,
Feature.ZeroReserveChannels to FeatureSupport.Optional,
Feature.WakeUpNotificationClient to FeatureSupport.Optional,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import fr.acinq.lightning.MilliSatoshi
import fr.acinq.lightning.blockchain.WatchEvent
import fr.acinq.lightning.blockchain.electrum.WalletState
import fr.acinq.lightning.blockchain.fee.FeeratePerKw
import fr.acinq.lightning.channel.states.ClosingFeerates
import fr.acinq.lightning.channel.states.PersistedChannelState
import fr.acinq.lightning.crypto.KeyManager
import fr.acinq.lightning.utils.UUID
Expand Down Expand Up @@ -132,7 +131,7 @@ sealed class ChannelCommand {
}

sealed class Close : ChannelCommand() {
data class MutualClose(val scriptPubKey: ByteVector?, val feerates: ClosingFeerates?) : Close(), ForbiddenDuringSplice, ForbiddenDuringQuiescence
data class MutualClose(val scriptPubKey: ByteVector?, val feerate: FeeratePerKw?) : Close(), ForbiddenDuringSplice, ForbiddenDuringQuiescence
data object ForceClose : Close()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ import fr.acinq.lightning.channel.Helpers.publishIfNeeded
import fr.acinq.lightning.channel.Helpers.watchConfirmedIfNeeded
import fr.acinq.lightning.channel.Helpers.watchSpentIfNeeded
import fr.acinq.lightning.crypto.KeyManager
import fr.acinq.lightning.logging.*
import fr.acinq.lightning.logging.LoggingContext
import fr.acinq.lightning.transactions.Scripts
import fr.acinq.lightning.transactions.Transactions.TransactionWithInputInfo.*
import fr.acinq.lightning.wire.ClosingSigned

/**
* Details about a force-close where we published our commitment.
Expand Down Expand Up @@ -354,7 +353,7 @@ data class LocalParams(
val defaultFinalScriptPubKey: ByteVector,
val features: Features
) {
constructor(nodeParams: NodeParams, isInitiator: Boolean): this(
constructor(nodeParams: NodeParams, isInitiator: Boolean) : this(
nodeId = nodeParams.nodeId,
fundingKeyPath = nodeParams.keyManager.newFundingKeyPath(isInitiator), // we make sure that initiator and non-initiator key path end differently
dustLimit = nodeParams.dustLimit,
Expand Down Expand Up @@ -389,8 +388,6 @@ object ChannelFlags {
const val Empty = 0x00.toByte()
}

data class ClosingTxProposed(val unsignedTx: ClosingTx, val localClosingSigned: ClosingSigned)

/** Reason for creating a new channel or a splice. */
// @formatter:off
sealed class Origin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ data class FeerateTooSmall (override val channelId: Byte
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()}")
data class InvalidCommitmentSignature (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid commitment signature: txId=$txId")
data class InvalidHtlcSignature (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid htlc signature: txId=$txId")
data class CannotGenerateClosingTx (override val channelId: ByteVector32) : ChannelException(channelId, "failed to generate closing transaction: all outputs are trimmed")
data class MissingCloseSignature (override val channelId: ByteVector32) : ChannelException(channelId, "closing_complete is missing a signature for a closing transaction including our output")
data class InvalidCloseSignature (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid close signature: txId=$txId")
data class InvalidCloseAmountBelowDust (override val channelId: ByteVector32, val txId: TxId) : ChannelException(channelId, "invalid closing tx: some outputs are below dust: txId=$txId")
data class CommitSigCountMismatch (override val channelId: ByteVector32, val expected: Int, val actual: Int) : ChannelException(channelId, "commit sig count mismatch: expected=$expected actual=$actual")
Expand Down
Loading

0 comments on commit 48b7348

Please sign in to comment.