From 48f76395f51ac60bb71aadb5766b52f1d0440983 Mon Sep 17 00:00:00 2001 From: pm47 Date: Wed, 27 Sep 2023 19:28:12 +0200 Subject: [PATCH] treat local/remote commit index separately when splicing The assumption that local/remote index are equal when channel is idle is wrong: they can diverge in some cases. This bug led to "invalid sig" errors during splices. --- .../kotlin/fr/acinq/lightning/channel/Helpers.kt | 9 +++++---- .../kotlin/fr/acinq/lightning/channel/InteractiveTx.kt | 10 ++++++---- .../kotlin/fr/acinq/lightning/channel/states/Normal.kt | 3 ++- .../channel/states/WaitForFundingConfirmed.kt | 3 ++- .../lightning/channel/states/WaitForFundingCreated.kt | 3 ++- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/Helpers.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/Helpers.kt index 5f688c3f0..eba01af52 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/Helpers.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/Helpers.kt @@ -288,7 +288,8 @@ object Helpers { fundingAmount: Satoshi, toLocal: MilliSatoshi, toRemote: MilliSatoshi, - commitmentIndex: Long, + localCommitmentIndex: Long, + remoteCommitmentIndex: Long, commitTxFeerate: FeeratePerKw, fundingTxIndex: Long, fundingTxHash: ByteVector32, @@ -313,10 +314,10 @@ object Helpers { val fundingPubKey = channelKeys.fundingPubKey(fundingTxIndex) val commitmentInput = makeFundingInputInfo(fundingTxHash, fundingTxOutputIndex, fundingAmount, fundingPubKey, remoteFundingPubkey) - val localPerCommitmentPoint = channelKeys.commitmentPoint(commitmentIndex) + val localPerCommitmentPoint = channelKeys.commitmentPoint(localCommitmentIndex) val localCommitTx = Commitments.makeLocalTxs( channelKeys, - commitTxNumber = commitmentIndex, + commitTxNumber = localCommitmentIndex, localParams, remoteParams, fundingTxIndex = fundingTxIndex, @@ -327,7 +328,7 @@ object Helpers { ).first val remoteCommitTx = Commitments.makeRemoteTxs( channelKeys, - commitTxNumber = commitmentIndex, + commitTxNumber = remoteCommitmentIndex, localParams, remoteParams, fundingTxIndex = fundingTxIndex, diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt index 70299febf..3b0086c74 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt @@ -825,7 +825,8 @@ data class InteractiveTxSigningSession( sharedTx: SharedTransaction, localPushAmount: MilliSatoshi, remotePushAmount: MilliSatoshi, - commitmentIndex: Long, + localCommitmentIndex: Long, + remoteCommitmentIndex: Long, commitTxFeerate: FeeratePerKw, remotePerCommitmentPoint: PublicKey ): Either> { @@ -839,7 +840,8 @@ data class InteractiveTxSigningSession( fundingAmount = sharedTx.sharedOutput.amount, toLocal = sharedTx.sharedOutput.localAmount - localPushAmount + remotePushAmount, toRemote = sharedTx.sharedOutput.remoteAmount - remotePushAmount + localPushAmount, - commitmentIndex = commitmentIndex, + localCommitmentIndex = localCommitmentIndex, + remoteCommitmentIndex = remoteCommitmentIndex, commitTxFeerate, fundingTxIndex = fundingTxIndex, fundingTxHash = unsignedTx.hash, fundingTxOutputIndex = sharedOutputIndex, remoteFundingPubkey = fundingParams.remoteFundingPubkey, @@ -847,8 +849,8 @@ data class InteractiveTxSigningSession( ).map { firstCommitTx -> val localSigOfRemoteTx = Transactions.sign(firstCommitTx.remoteCommitTx, channelKeys.fundingKey(fundingTxIndex)) val commitSig = CommitSig(channelParams.channelId, localSigOfRemoteTx, listOf()) - val unsignedLocalCommit = UnsignedLocalCommit(commitmentIndex, firstCommitTx.localSpec, firstCommitTx.localCommitTx, listOf()) - val remoteCommit = RemoteCommit(commitmentIndex, firstCommitTx.remoteSpec, firstCommitTx.remoteCommitTx.tx.txid, remotePerCommitmentPoint) + val unsignedLocalCommit = UnsignedLocalCommit(localCommitmentIndex, firstCommitTx.localSpec, firstCommitTx.localCommitTx, listOf()) + val remoteCommit = RemoteCommit(remoteCommitmentIndex, firstCommitTx.remoteSpec, firstCommitTx.remoteCommitTx.tx.txid, remotePerCommitmentPoint) val signedFundingTx = sharedTx.sign(keyManager, fundingParams, channelParams.localParams, channelParams.remoteParams.nodeId) Pair(InteractiveTxSigningSession(fundingParams, fundingTxIndex, signedFundingTx, Either.Left(unsignedLocalCommit), remoteCommit), commitSig) } 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 d5433b2da..739fe3c0d 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt @@ -475,7 +475,8 @@ data class Normal( interactiveTxAction.sharedTx, localPushAmount = spliceStatus.localPushAmount, remotePushAmount = spliceStatus.remotePushAmount, - commitmentIndex = parentCommitment.localCommit.index, // localCommit.index == remoteCommit.index because the channel is idle + localCommitmentIndex = parentCommitment.localCommit.index, + remoteCommitmentIndex = parentCommitment.remoteCommit.index, parentCommitment.localCommit.spec.feerate, parentCommitment.remoteCommit.remotePerCommitmentPoint ) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt index 034736501..f53af97c7 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingConfirmed.kt @@ -173,7 +173,8 @@ data class WaitForFundingConfirmed( interactiveTxAction.sharedTx, localPushAmount, remotePushAmount, - commitmentIndex = replacedCommitment.localCommit.index, + localCommitmentIndex = replacedCommitment.localCommit.index, + remoteCommitmentIndex = replacedCommitment.remoteCommit.index, replacedCommitment.localCommit.spec.feerate, replacedCommitment.remoteCommit.remotePerCommitmentPoint ) diff --git a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt index 97e9f84a3..209848c21 100644 --- a/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt +++ b/src/commonMain/kotlin/fr/acinq/lightning/channel/states/WaitForFundingCreated.kt @@ -62,7 +62,8 @@ data class WaitForFundingCreated( interactiveTxAction.sharedTx, localPushAmount, remotePushAmount, - commitmentIndex = 0, + localCommitmentIndex = 0, + remoteCommitmentIndex = 0, commitTxFeerate, remoteFirstPerCommitmentPoint )