diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/Commitments.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/Commitments.kt index eb1fe0f35..7868688d5 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/Commitments.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/Commitments.kt @@ -422,18 +422,18 @@ data class Commitment( "built remote commit number=${remoteCommit.index + 1} toLocalMsat=${spec.toLocal.toLong()} toRemoteMsat=${spec.toRemote.toLong()} htlc_in=$htlcsIn htlc_out=$htlcsOut feeratePerKw=${spec.feerate} txId=${remoteCommitTx.tx.txid} fundingTxId=$fundingTxId" } - val commitSig = when (spec.htlcs.size) { - 0 -> { + val tlvs = buildSet { + if (spec.htlcs.isEmpty()) { val alternativeSigs = Commitments.alternativeFeerates.map { feerate -> val alternativeSpec = spec.copy(feerate = feerate) val (alternativeRemoteCommitTx, _) = Commitments.makeRemoteTxs(channelKeys, commitTxNumber = remoteCommit.index + 1, params.localParams, params.remoteParams, fundingTxIndex = fundingTxIndex, remoteFundingPubKey = remoteFundingPubkey, commitInput, remotePerCommitmentPoint = remoteNextPerCommitmentPoint, alternativeSpec) val alternativeSig = Transactions.sign(alternativeRemoteCommitTx, channelKeys.fundingKey(fundingTxIndex)) CommitSigTlv.AlternativeFeerateSig(feerate, alternativeSig) } - CommitSig(params.channelId, sig, listOf(), TlvStream(CommitSigTlv.AlternativeFeerateSigs(alternativeSigs))) + add(CommitSigTlv.AlternativeFeerateSigs(alternativeSigs)) } - else -> CommitSig(params.channelId, sig, htlcSigs.toList()) } + val commitSig = CommitSig(params.channelId, sig, htlcSigs.toList(), TlvStream(tlvs)) val commitment1 = copy(nextRemoteCommit = NextRemoteCommit(commitSig, RemoteCommit(remoteCommit.index + 1, spec, remoteCommitTx.tx.txid, remoteNextPerCommitmentPoint))) return Pair(commitment1, commitSig) } @@ -951,6 +951,25 @@ data class Commitments( */ val alternativeFeerates = listOf(1.sat, 2.sat, 5.sat, 10.sat).map { FeeratePerKw(FeeratePerByte(it)) } + /** + * Our peer may publish an alternative version of their commitment using a different feerate. + * This function lists all the alternative commitments they have signatures for. + */ + fun alternativeFeerateCommits(commitments: Commitments, channelKeys: KeyManager.ChannelKeys): List { + return buildList { + add(commitments.latest.remoteCommit) + commitments.latest.nextRemoteCommit?.let { add(it.commit) } + }.filter { remoteCommit -> + remoteCommit.spec.htlcs.isEmpty() + }.flatMap { remoteCommit -> + alternativeFeerates.map { feerate -> + val alternativeSpec = remoteCommit.spec.copy(feerate = feerate) + val (alternativeRemoteCommitTx, _) = makeRemoteTxs(channelKeys, remoteCommit.index, commitments.params.localParams, commitments.params.remoteParams, commitments.latest.fundingTxIndex, commitments.latest.remoteFundingPubkey, commitments.latest.commitInput, remoteCommit.remotePerCommitmentPoint, alternativeSpec) + RemoteCommit(remoteCommit.index, alternativeSpec, alternativeRemoteCommitTx.tx.txid, remoteCommit.remotePerCommitmentPoint) + } + } + } + fun makeLocalTxs( channelKeys: KeyManager.ChannelKeys, commitTxNumber: Long, diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt index 483e79111..da978924e 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Channel.kt @@ -507,19 +507,7 @@ sealed class ChannelStateWithCommitments : PersistedChannelState() { } else -> { // Our peer may publish an alternative version of their commitment using a different feerate. - val alternativeFeerateCommits = buildList { - add(commitments.latest.remoteCommit) - commitments.latest.nextRemoteCommit?.let { add(it.commit) } - }.filter { remoteCommit -> - remoteCommit.spec.htlcs.isEmpty() - }.flatMap { remoteCommit -> - Commitments.alternativeFeerates.map { feerate -> - val alternativeSpec = remoteCommit.spec.copy(feerate = feerate) - val (alternativeRemoteCommitTx, _) = Commitments.makeRemoteTxs(channelKeys(), remoteCommit.index, commitments.params.localParams, commitments.params.remoteParams, commitments.latest.fundingTxIndex, commitments.latest.remoteFundingPubkey, commitments.latest.commitInput, remoteCommit.remotePerCommitmentPoint, alternativeSpec) - RemoteCommit(remoteCommit.index, alternativeSpec, alternativeRemoteCommitTx.tx.txid, remoteCommit.remotePerCommitmentPoint) - } - } - when (val remoteCommit = alternativeFeerateCommits.find { it.txid == tx.txid }) { + when (val remoteCommit = Commitments.alternativeFeerateCommits(commitments, channelKeys()).find { it.txid == tx.txid }) { null -> { logger.warning { "unrecognized tx=${tx.txid}" } // This can happen if the user has two devices.